mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-18 23:05:21 +00:00
Support flattened data fields
This commit is contained in:
@@ -236,15 +236,43 @@ interface TemplateContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a body template with {{event}}, {{timestamp}}, {{status}}, and
|
* Render a body template with {{event}}, {{timestamp}}, {{status}}, {{data}},
|
||||||
* {{data}} placeholders, mirroring the logic in HttpLogDestination.
|
* and individual data-field placeholders (e.g. {{orgId}}, {{siteId}}, …).
|
||||||
*
|
*
|
||||||
* {{data}} is replaced first (as raw JSON) so that any literal "{{…}}"
|
* Replacement order:
|
||||||
* strings inside data values are not re-expanded.
|
* 1. {{data}} → raw JSON of the full data object (prevents re-expansion of
|
||||||
|
* nested values that might look like placeholders).
|
||||||
|
* 2. Top-level scalar fields from data (string values are JSON-escaped;
|
||||||
|
* numbers and booleans are rendered as-is). Unknown placeholders are
|
||||||
|
* left untouched.
|
||||||
|
* 3. The fixed top-level keys: event, timestamp, status.
|
||||||
*/
|
*/
|
||||||
function renderTemplate(template: string, ctx: TemplateContext): string {
|
function renderTemplate(template: string, ctx: TemplateContext): string {
|
||||||
const rendered = template
|
// Step 1 – expand {{data}} first so its contents are already serialised
|
||||||
.replace(/\{\{data\}\}/g, JSON.stringify(ctx.data))
|
// and won't be touched by later passes.
|
||||||
|
let rendered = template.replace(/\{\{data\}\}/g, JSON.stringify(ctx.data));
|
||||||
|
|
||||||
|
// Step 2 – expand individual data fields. Only replace placeholders whose
|
||||||
|
// key actually exists in ctx.data; leave everything else as-is.
|
||||||
|
for (const [key, value] of Object.entries(ctx.data)) {
|
||||||
|
if (value === null || value === undefined) continue;
|
||||||
|
const placeholder = new RegExp(
|
||||||
|
`\\{\\{${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\}\\}`,
|
||||||
|
"g"
|
||||||
|
);
|
||||||
|
let serialised: string;
|
||||||
|
if (typeof value === "string") {
|
||||||
|
serialised = escapeJsonString(value);
|
||||||
|
} else if (typeof value === "number" || typeof value === "boolean") {
|
||||||
|
serialised = String(value);
|
||||||
|
} else {
|
||||||
|
serialised = escapeJsonString(JSON.stringify(value));
|
||||||
|
}
|
||||||
|
rendered = rendered.replace(placeholder, serialised);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3 – expand the fixed top-level keys.
|
||||||
|
rendered = rendered
|
||||||
.replace(/\{\{event\}\}/g, escapeJsonString(ctx.event))
|
.replace(/\{\{event\}\}/g, escapeJsonString(ctx.event))
|
||||||
.replace(/\{\{timestamp\}\}/g, escapeJsonString(ctx.timestamp))
|
.replace(/\{\{timestamp\}\}/g, escapeJsonString(ctx.timestamp))
|
||||||
.replace(/\{\{status\}\}/g, escapeJsonString(ctx.status));
|
.replace(/\{\{status\}\}/g, escapeJsonString(ctx.status));
|
||||||
|
|||||||
Reference in New Issue
Block a user