@qcobro/common 1.11.4 → 1.12.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/utils/outreach.d.ts
CHANGED
|
@@ -5,6 +5,16 @@ import type { NumberSelector } from "../types/dispatch.js";
|
|
|
5
5
|
* script / SMS), never HTML, so escaping is disabled. A missing `{{field}}`
|
|
6
6
|
* renders as empty rather than throwing, so a sparse account never aborts a
|
|
7
7
|
* dispatch mid-flight.
|
|
8
|
+
*
|
|
9
|
+
* A malformed template — most commonly a reference to an unregistered helper,
|
|
10
|
+
* e.g. `{{multiply amount rate}}` before that helper existed — throws a
|
|
11
|
+
* synchronous Handlebars compile/render error. That used to propagate
|
|
12
|
+
* uncaught, crashing the webapp's live template preview
|
|
13
|
+
* (`ReachOutModal.tsx`) and, in the dispatch pipeline, aborting the send
|
|
14
|
+
* attempt. Both are now caught here: the error surfaces as a visible
|
|
15
|
+
* `[Error de plantilla: ...]` marker in the rendered output instead of
|
|
16
|
+
* throwing, so a template bug is obvious without taking down a preview or a
|
|
17
|
+
* send.
|
|
8
18
|
*/
|
|
9
19
|
export declare function renderTemplate(template: string, context: Record<string, unknown>): string;
|
|
10
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outreach.d.ts","sourceRoot":"","sources":["../../src/utils/outreach.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"outreach.d.ts","sourceRoot":"","sources":["../../src/utils/outreach.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAyD3D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQzF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,EAAE,cACsB,CAAC"}
|
package/dist/utils/outreach.js
CHANGED
|
@@ -1,13 +1,80 @@
|
|
|
1
1
|
import Handlebars from "handlebars";
|
|
2
|
+
/**
|
|
3
|
+
* `{{multiply a b}}` — coerces both operands to numbers; either operand being
|
|
4
|
+
* non-numeric (missing field, bad data) yields 0 rather than NaN, so a
|
|
5
|
+
* malformed context never produces `NaN` in a customer-facing message.
|
|
6
|
+
*/
|
|
7
|
+
Handlebars.registerHelper("multiply", (a, b) => {
|
|
8
|
+
const x = Number(a);
|
|
9
|
+
const y = Number(b);
|
|
10
|
+
return Number.isFinite(x) && Number.isFinite(y) ? x * y : 0;
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* `{{eq a b}}` — strict equality, for branching on exact values (e.g.
|
|
14
|
+
* `{{#if (eq customerSegment "variant_A")}}`).
|
|
15
|
+
*/
|
|
16
|
+
Handlebars.registerHelper("eq", (a, b) => a === b);
|
|
17
|
+
/**
|
|
18
|
+
* `{{gt a b}}` / `{{gte a b}}` / `{{lt a b}}` / `{{lte a b}}` — numeric
|
|
19
|
+
* comparisons for use inside `{{#if}}`, e.g. `{{#if (gte daysPastDue 30)}}`.
|
|
20
|
+
* Operands are coerced with `Number()`; a non-numeric operand becomes `NaN`,
|
|
21
|
+
* and every JS comparison against `NaN` is `false` — so a malformed context
|
|
22
|
+
* makes the condition not match rather than throwing. `ge` is registered as
|
|
23
|
+
* an alias of `gte` (both names are in common use).
|
|
24
|
+
*/
|
|
25
|
+
Handlebars.registerHelper("gt", (a, b) => Number(a) > Number(b));
|
|
26
|
+
Handlebars.registerHelper("gte", (a, b) => Number(a) >= Number(b));
|
|
27
|
+
Handlebars.registerHelper("ge", (a, b) => Number(a) >= Number(b));
|
|
28
|
+
Handlebars.registerHelper("lt", (a, b) => Number(a) < Number(b));
|
|
29
|
+
Handlebars.registerHelper("lte", (a, b) => Number(a) <= Number(b));
|
|
30
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
31
|
+
function toDate(value) {
|
|
32
|
+
if (value instanceof Date)
|
|
33
|
+
return Number.isNaN(value.getTime()) ? null : value;
|
|
34
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
35
|
+
return null;
|
|
36
|
+
const parsed = new Date(value);
|
|
37
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `{{daysSince date}}` / `{{daysUntil date}}` — whole days between `date` and
|
|
41
|
+
* now (rounded down), for copy like "han pasado {{daysSince lastPaymentDate}}
|
|
42
|
+
* días desde su último pago". An unparseable or missing date yields `0`
|
|
43
|
+
* rather than `NaN`, matching `multiply`'s malformed-context handling.
|
|
44
|
+
*/
|
|
45
|
+
Handlebars.registerHelper("daysSince", (value) => {
|
|
46
|
+
const date = toDate(value);
|
|
47
|
+
return date ? Math.floor((Date.now() - date.getTime()) / DAY_MS) : 0;
|
|
48
|
+
});
|
|
49
|
+
Handlebars.registerHelper("daysUntil", (value) => {
|
|
50
|
+
const date = toDate(value);
|
|
51
|
+
return date ? Math.floor((date.getTime() - Date.now()) / DAY_MS) : 0;
|
|
52
|
+
});
|
|
2
53
|
/**
|
|
3
54
|
* Renders a Handlebars template against a context. Bodies are plain text (voice
|
|
4
55
|
* script / SMS), never HTML, so escaping is disabled. A missing `{{field}}`
|
|
5
56
|
* renders as empty rather than throwing, so a sparse account never aborts a
|
|
6
57
|
* dispatch mid-flight.
|
|
58
|
+
*
|
|
59
|
+
* A malformed template — most commonly a reference to an unregistered helper,
|
|
60
|
+
* e.g. `{{multiply amount rate}}` before that helper existed — throws a
|
|
61
|
+
* synchronous Handlebars compile/render error. That used to propagate
|
|
62
|
+
* uncaught, crashing the webapp's live template preview
|
|
63
|
+
* (`ReachOutModal.tsx`) and, in the dispatch pipeline, aborting the send
|
|
64
|
+
* attempt. Both are now caught here: the error surfaces as a visible
|
|
65
|
+
* `[Error de plantilla: ...]` marker in the rendered output instead of
|
|
66
|
+
* throwing, so a template bug is obvious without taking down a preview or a
|
|
67
|
+
* send.
|
|
7
68
|
*/
|
|
8
69
|
export function renderTemplate(template, context) {
|
|
9
|
-
|
|
10
|
-
|
|
70
|
+
try {
|
|
71
|
+
const compiled = Handlebars.compile(template, { noEscape: true });
|
|
72
|
+
return compiled(context);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
76
|
+
return `[Error de plantilla: ${message}]`;
|
|
77
|
+
}
|
|
11
78
|
}
|
|
12
79
|
/**
|
|
13
80
|
* Extracts the distinct simple placeholder names from a template, in first-seen order
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outreach.js","sourceRoot":"","sources":["../../src/utils/outreach.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AAIpC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAgC;IAC/E,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"outreach.js","sourceRoot":"","sources":["../../src/utils/outreach.ts"],"names":[],"mappings":"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"}
|