@hostwebhook/template-engine 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -55,6 +55,35 @@ interface CodeResult {
55
55
  */
56
56
  declare function renderTemplate(template: string, ctx: TemplateContext, opts?: TemplateOptions): TemplateResult | CodeResult;
57
57
 
58
+ /**
59
+ * Resolve a single input value — literal string or {{expression}}.
60
+ *
61
+ * If the value is wrapped in `{{...}}`, it's evaluated as a template expression
62
+ * (supports paths, pipes, $() cross-node references, JS when allowJs).
63
+ * Otherwise, the value is returned as-is (literal).
64
+ *
65
+ * Preserves types: `{{payload.count}}` returns the original number, not a string.
66
+ *
67
+ * @example
68
+ * resolveInput("active", payload) // → "active"
69
+ * resolveInput("{{payload.status}}", payload) // → "delivered"
70
+ * resolveInput("{{payload.amount}}", payload) // → 1500 (number)
71
+ * resolveInput("{{payload.date | formatDate}}", payload) // → "2024-06-15"
72
+ * resolveInput('{{$("Filter").count}}', payload, { allowJs: true, workspacePayloads }) // → 42
73
+ * resolveInput(undefined, payload) // → undefined
74
+ */
75
+ declare function resolveInput(value: string | undefined | null, payload: unknown, opts?: Pick<TemplateOptions, 'allowJs' | 'workspacePayloads'>): unknown;
76
+ /**
77
+ * Normalize a field path — strips `{{`, `}}`, and `payload.` prefix.
78
+ *
79
+ * Accepts any of these formats and returns the plain dot-notation path:
80
+ * - `"{{payload.customer.name}}"` → `"customer.name"`
81
+ * - `"payload.customer.name"` → `"customer.name"`
82
+ * - `"customer.name"` → `"customer.name"`
83
+ * - `"{{customer.name}}"` → `"customer.name"`
84
+ */
85
+ declare function resolveFieldPath(field: string): string;
86
+
58
87
  /**
59
88
  * Resolve a dot-notation path against a TemplateContext.
60
89
  * Supports bracket notation for array indexing: `payload.items[0].name`
@@ -87,4 +116,4 @@ declare function applyPipe(pipe: string, val: unknown, arg?: string, ctx?: Templ
87
116
  */
88
117
  declare function evaluate(expr: string, ctx: TemplateContext, opts?: TemplateOptions): string;
89
118
 
90
- export { type CodeResult, type TemplateContext, type TemplateMode, type TemplateOptions, type TemplateResult, applyPipe, evaluate, renderTemplate, resolvePath, tryNullCoalesce, tryTernary, valueToString };
119
+ export { type CodeResult, type TemplateContext, type TemplateMode, type TemplateOptions, type TemplateResult, applyPipe, evaluate, renderTemplate, resolveFieldPath, resolveInput, resolvePath, tryNullCoalesce, tryTernary, valueToString };
package/dist/index.d.ts CHANGED
@@ -55,6 +55,35 @@ interface CodeResult {
55
55
  */
56
56
  declare function renderTemplate(template: string, ctx: TemplateContext, opts?: TemplateOptions): TemplateResult | CodeResult;
57
57
 
58
+ /**
59
+ * Resolve a single input value — literal string or {{expression}}.
60
+ *
61
+ * If the value is wrapped in `{{...}}`, it's evaluated as a template expression
62
+ * (supports paths, pipes, $() cross-node references, JS when allowJs).
63
+ * Otherwise, the value is returned as-is (literal).
64
+ *
65
+ * Preserves types: `{{payload.count}}` returns the original number, not a string.
66
+ *
67
+ * @example
68
+ * resolveInput("active", payload) // → "active"
69
+ * resolveInput("{{payload.status}}", payload) // → "delivered"
70
+ * resolveInput("{{payload.amount}}", payload) // → 1500 (number)
71
+ * resolveInput("{{payload.date | formatDate}}", payload) // → "2024-06-15"
72
+ * resolveInput('{{$("Filter").count}}', payload, { allowJs: true, workspacePayloads }) // → 42
73
+ * resolveInput(undefined, payload) // → undefined
74
+ */
75
+ declare function resolveInput(value: string | undefined | null, payload: unknown, opts?: Pick<TemplateOptions, 'allowJs' | 'workspacePayloads'>): unknown;
76
+ /**
77
+ * Normalize a field path — strips `{{`, `}}`, and `payload.` prefix.
78
+ *
79
+ * Accepts any of these formats and returns the plain dot-notation path:
80
+ * - `"{{payload.customer.name}}"` → `"customer.name"`
81
+ * - `"payload.customer.name"` → `"customer.name"`
82
+ * - `"customer.name"` → `"customer.name"`
83
+ * - `"{{customer.name}}"` → `"customer.name"`
84
+ */
85
+ declare function resolveFieldPath(field: string): string;
86
+
58
87
  /**
59
88
  * Resolve a dot-notation path against a TemplateContext.
60
89
  * Supports bracket notation for array indexing: `payload.items[0].name`
@@ -87,4 +116,4 @@ declare function applyPipe(pipe: string, val: unknown, arg?: string, ctx?: Templ
87
116
  */
88
117
  declare function evaluate(expr: string, ctx: TemplateContext, opts?: TemplateOptions): string;
89
118
 
90
- export { type CodeResult, type TemplateContext, type TemplateMode, type TemplateOptions, type TemplateResult, applyPipe, evaluate, renderTemplate, resolvePath, tryNullCoalesce, tryTernary, valueToString };
119
+ export { type CodeResult, type TemplateContext, type TemplateMode, type TemplateOptions, type TemplateResult, applyPipe, evaluate, renderTemplate, resolveFieldPath, resolveInput, resolvePath, tryNullCoalesce, tryTernary, valueToString };
package/dist/index.js CHANGED
@@ -33,6 +33,8 @@ __export(index_exports, {
33
33
  applyPipe: () => applyPipe,
34
34
  evaluate: () => evaluate,
35
35
  renderTemplate: () => renderTemplate,
36
+ resolveFieldPath: () => resolveFieldPath,
37
+ resolveInput: () => resolveInput,
36
38
  resolvePath: () => resolvePath,
37
39
  tryNullCoalesce: () => tryNullCoalesce,
38
40
  tryTernary: () => tryTernary,
@@ -377,7 +379,9 @@ function resolveJsonValue(value, ctx, opts) {
377
379
  return !val;
378
380
  }
379
381
  if (/\|\s*\w+/.test(expr)) {
380
- return evaluate(expr, ctx, opts);
382
+ const result = evaluate(expr, ctx, opts);
383
+ if (result !== "" && isFinite(Number(result))) return Number(result);
384
+ return result;
381
385
  }
382
386
  const resolved = resolvePath(expr, ctx);
383
387
  if (resolved !== void 0) return resolved;
@@ -531,11 +535,33 @@ function renderTemplate(template, ctx, opts) {
531
535
  return resolveTextTemplate(template, ctx, opts);
532
536
  }
533
537
  }
538
+
539
+ // src/resolve-input.ts
540
+ function resolveInput(value, payload, opts) {
541
+ if (value == null || value === "") return value;
542
+ const str = String(value);
543
+ const match = str.match(/^\{\{([\s\S]+)\}\}$/);
544
+ if (!match) return value;
545
+ const expr = match[1].trim();
546
+ const ctx = { payload, headers: {}, meta: {} };
547
+ const resolved = resolvePath(expr, ctx);
548
+ if (resolved !== void 0) return resolved;
549
+ const evalOpts = opts ? { allowJs: opts.allowJs, workspacePayloads: opts.workspacePayloads } : void 0;
550
+ const result = evaluate(expr, ctx, evalOpts);
551
+ if (result !== "") return result;
552
+ return value;
553
+ }
554
+ function resolveFieldPath(field) {
555
+ if (!field) return "";
556
+ return field.replace(/^\{\{\s*/, "").replace(/\s*\}\}$/, "").replace(/^payload\./, "").trim();
557
+ }
534
558
  // Annotate the CommonJS export names for ESM import in node:
535
559
  0 && (module.exports = {
536
560
  applyPipe,
537
561
  evaluate,
538
562
  renderTemplate,
563
+ resolveFieldPath,
564
+ resolveInput,
539
565
  resolvePath,
540
566
  tryNullCoalesce,
541
567
  tryTernary,
package/dist/index.mjs CHANGED
@@ -335,7 +335,9 @@ function resolveJsonValue(value, ctx, opts) {
335
335
  return !val;
336
336
  }
337
337
  if (/\|\s*\w+/.test(expr)) {
338
- return evaluate(expr, ctx, opts);
338
+ const result = evaluate(expr, ctx, opts);
339
+ if (result !== "" && isFinite(Number(result))) return Number(result);
340
+ return result;
339
341
  }
340
342
  const resolved = resolvePath(expr, ctx);
341
343
  if (resolved !== void 0) return resolved;
@@ -489,10 +491,32 @@ function renderTemplate(template, ctx, opts) {
489
491
  return resolveTextTemplate(template, ctx, opts);
490
492
  }
491
493
  }
494
+
495
+ // src/resolve-input.ts
496
+ function resolveInput(value, payload, opts) {
497
+ if (value == null || value === "") return value;
498
+ const str = String(value);
499
+ const match = str.match(/^\{\{([\s\S]+)\}\}$/);
500
+ if (!match) return value;
501
+ const expr = match[1].trim();
502
+ const ctx = { payload, headers: {}, meta: {} };
503
+ const resolved = resolvePath(expr, ctx);
504
+ if (resolved !== void 0) return resolved;
505
+ const evalOpts = opts ? { allowJs: opts.allowJs, workspacePayloads: opts.workspacePayloads } : void 0;
506
+ const result = evaluate(expr, ctx, evalOpts);
507
+ if (result !== "") return result;
508
+ return value;
509
+ }
510
+ function resolveFieldPath(field) {
511
+ if (!field) return "";
512
+ return field.replace(/^\{\{\s*/, "").replace(/\s*\}\}$/, "").replace(/^payload\./, "").trim();
513
+ }
492
514
  export {
493
515
  applyPipe,
494
516
  evaluate,
495
517
  renderTemplate,
518
+ resolveFieldPath,
519
+ resolveInput,
496
520
  resolvePath,
497
521
  tryNullCoalesce,
498
522
  tryTernary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostwebhook/template-engine",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Template interpolation and sandboxed JS execution engine for HostWebhook",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",