@teleporthq/teleport-plugin-next-workflows 0.43.64 → 0.43.66
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/__tests__/cart-clear-db-mirror.test.ts +12 -0
- package/__tests__/cart-get-total-regional-pricing.test.ts +166 -0
- package/__tests__/continue-on-error.test.ts +119 -0
- package/__tests__/custom-node-page-route-rewrite.test.ts +109 -0
- package/__tests__/invoice-delivery-fee.test.ts +104 -0
- package/__tests__/invoice-regional-tax.test.ts +126 -0
- package/__tests__/payment-redirect-and-order-notification.test.ts +6 -0
- package/__tests__/paypal-webhook-order-notification.test.ts +41 -0
- package/__tests__/resolve-handler-entry-name.test.ts +25 -0
- package/__tests__/sent-email-log-module.test.ts +381 -0
- package/__tests__/sent-email-log-wiring.test.ts +267 -0
- package/dist/cjs/account-delete-route-generator.d.ts.map +1 -1
- package/dist/cjs/account-delete-route-generator.js +14 -5
- package/dist/cjs/account-delete-route-generator.js.map +1 -1
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +44 -9
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/auth-generator.d.ts.map +1 -1
- package/dist/cjs/auth-generator.js +15 -6
- package/dist/cjs/auth-generator.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +17 -4
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/cjs/invoice/api-routes-code.js +42 -4
- package/dist/cjs/invoice/api-routes-code.js.map +1 -1
- package/dist/cjs/invoice/email-sender-code.d.ts.map +1 -1
- package/dist/cjs/invoice/email-sender-code.js +58 -29
- package/dist/cjs/invoice/email-sender-code.js.map +1 -1
- package/dist/cjs/invoice/index.d.ts +1 -4
- package/dist/cjs/invoice/index.d.ts.map +1 -1
- package/dist/cjs/invoice/index.js +5 -19
- package/dist/cjs/invoice/index.js.map +1 -1
- package/dist/cjs/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/cjs/invoice/invoice-html-code.js +31 -8
- package/dist/cjs/invoice/invoice-html-code.js.map +1 -1
- package/dist/cjs/invoice/regional-invoice-tax-code.d.ts +25 -0
- package/dist/cjs/invoice/regional-invoice-tax-code.d.ts.map +1 -0
- package/dist/cjs/invoice/regional-invoice-tax-code.js +116 -0
- package/dist/cjs/invoice/regional-invoice-tax-code.js.map +1 -0
- package/dist/cjs/invoice/resolve-data-source.d.ts +6 -0
- package/dist/cjs/invoice/resolve-data-source.d.ts.map +1 -0
- package/dist/cjs/invoice/resolve-data-source.js +23 -0
- package/dist/cjs/invoice/resolve-data-source.js.map +1 -0
- package/dist/cjs/nodes/analytics/commerce-tracking.d.ts +38 -2
- package/dist/cjs/nodes/analytics/commerce-tracking.d.ts.map +1 -1
- package/dist/cjs/nodes/analytics/commerce-tracking.js +41 -26
- package/dist/cjs/nodes/analytics/commerce-tracking.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-add-item.js +3 -1
- package/dist/cjs/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.js +6 -0
- package/dist/cjs/nodes/cart/cart-clear.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.js +81 -5
- package/dist/cjs/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.js +8 -0
- package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
- package/dist/cjs/nodes/types.d.ts.map +1 -1
- package/dist/cjs/nodes/types.js +19 -0
- package/dist/cjs/nodes/types.js.map +1 -1
- package/dist/cjs/sent-email-log/index.d.ts +16 -0
- package/dist/cjs/sent-email-log/index.d.ts.map +1 -0
- package/dist/cjs/sent-email-log/index.js +53 -0
- package/dist/cjs/sent-email-log/index.js.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts +4 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.js +415 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.js.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-scope.d.ts +21 -0
- package/dist/cjs/sent-email-log/sent-email-log-scope.d.ts.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-scope.js +36 -0
- package/dist/cjs/sent-email-log/sent-email-log-scope.js.map +1 -0
- package/dist/cjs/transactional-email-code.d.ts +12 -1
- package/dist/cjs/transactional-email-code.d.ts.map +1 -1
- package/dist/cjs/transactional-email-code.js +43 -5
- package/dist/cjs/transactional-email-code.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/webhook-generator.d.ts.map +1 -1
- package/dist/cjs/webhook-generator.js +9 -2
- package/dist/cjs/webhook-generator.js.map +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +53 -30
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/esm/account-delete-route-generator.d.ts.map +1 -1
- package/dist/esm/account-delete-route-generator.js +15 -6
- package/dist/esm/account-delete-route-generator.js.map +1 -1
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +44 -9
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/auth-generator.d.ts.map +1 -1
- package/dist/esm/auth-generator.js +15 -6
- package/dist/esm/auth-generator.js.map +1 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +17 -4
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/esm/invoice/api-routes-code.js +42 -4
- package/dist/esm/invoice/api-routes-code.js.map +1 -1
- package/dist/esm/invoice/email-sender-code.d.ts.map +1 -1
- package/dist/esm/invoice/email-sender-code.js +58 -29
- package/dist/esm/invoice/email-sender-code.js.map +1 -1
- package/dist/esm/invoice/index.d.ts +1 -4
- package/dist/esm/invoice/index.d.ts.map +1 -1
- package/dist/esm/invoice/index.js +4 -18
- package/dist/esm/invoice/index.js.map +1 -1
- package/dist/esm/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/esm/invoice/invoice-html-code.js +31 -8
- package/dist/esm/invoice/invoice-html-code.js.map +1 -1
- package/dist/esm/invoice/regional-invoice-tax-code.d.ts +25 -0
- package/dist/esm/invoice/regional-invoice-tax-code.d.ts.map +1 -0
- package/dist/esm/invoice/regional-invoice-tax-code.js +113 -0
- package/dist/esm/invoice/regional-invoice-tax-code.js.map +1 -0
- package/dist/esm/invoice/resolve-data-source.d.ts +6 -0
- package/dist/esm/invoice/resolve-data-source.d.ts.map +1 -0
- package/dist/esm/invoice/resolve-data-source.js +19 -0
- package/dist/esm/invoice/resolve-data-source.js.map +1 -0
- package/dist/esm/nodes/analytics/commerce-tracking.d.ts +38 -2
- package/dist/esm/nodes/analytics/commerce-tracking.d.ts.map +1 -1
- package/dist/esm/nodes/analytics/commerce-tracking.js +41 -26
- package/dist/esm/nodes/analytics/commerce-tracking.js.map +1 -1
- package/dist/esm/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-add-item.js +3 -1
- package/dist/esm/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.js +6 -0
- package/dist/esm/nodes/cart/cart-clear.js.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.js +81 -5
- package/dist/esm/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-create-item.js +8 -0
- package/dist/esm/nodes/data/data-create-item.js.map +1 -1
- package/dist/esm/nodes/types.d.ts.map +1 -1
- package/dist/esm/nodes/types.js +19 -0
- package/dist/esm/nodes/types.js.map +1 -1
- package/dist/esm/sent-email-log/index.d.ts +16 -0
- package/dist/esm/sent-email-log/index.d.ts.map +1 -0
- package/dist/esm/sent-email-log/index.js +45 -0
- package/dist/esm/sent-email-log/index.js.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts +4 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-code.js +411 -0
- package/dist/esm/sent-email-log/sent-email-log-code.js.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-scope.d.ts +21 -0
- package/dist/esm/sent-email-log/sent-email-log-scope.d.ts.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-scope.js +31 -0
- package/dist/esm/sent-email-log/sent-email-log-scope.js.map +1 -0
- package/dist/esm/transactional-email-code.d.ts +12 -1
- package/dist/esm/transactional-email-code.d.ts.map +1 -1
- package/dist/esm/transactional-email-code.js +42 -4
- package/dist/esm/transactional-email-code.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/webhook-generator.d.ts.map +1 -1
- package/dist/esm/webhook-generator.js +9 -2
- package/dist/esm/webhook-generator.js.map +1 -1
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +53 -30
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/package.json +4 -4
- package/src/account-delete-route-generator.ts +16 -5
- package/src/api-route-generator.ts +51 -9
- package/src/auth-generator.ts +17 -6
- package/src/executor-generator.ts +17 -4
- package/src/index.ts +1 -0
- package/src/invoice/api-routes-code.ts +48 -4
- package/src/invoice/email-sender-code.ts +58 -29
- package/src/invoice/index.ts +4 -23
- package/src/invoice/invoice-html-code.ts +31 -8
- package/src/invoice/regional-invoice-tax-code.ts +112 -0
- package/src/invoice/resolve-data-source.ts +25 -0
- package/src/nodes/analytics/commerce-tracking.ts +37 -21
- package/src/nodes/cart/cart-add-item.ts +3 -1
- package/src/nodes/cart/cart-clear.ts +6 -0
- package/src/nodes/cart/cart-get-total.ts +94 -5
- package/src/nodes/data/data-create-item.ts +8 -0
- package/src/nodes/types.ts +23 -0
- package/src/sent-email-log/index.ts +57 -0
- package/src/sent-email-log/sent-email-log-code.ts +419 -0
- package/src/sent-email-log/sent-email-log-scope.ts +36 -0
- package/src/transactional-email-code.ts +61 -4
- package/src/webhook-generator.ts +11 -2
- package/src/workflow-project-plugin.ts +52 -29
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSentEmailLogCode = void 0;
|
|
4
|
+
const pg_client_code_1 = require("../pg-client-code");
|
|
5
|
+
/**
|
|
6
|
+
* Emits `utils/email/sent-email-log.js` — the ONE place every email the
|
|
7
|
+
* generated app sends is recorded into `teleport_sent_emails`.
|
|
8
|
+
*
|
|
9
|
+
* Callers (in this order of coverage):
|
|
10
|
+
* - workflow `email-*` / Gmail / Outlook nodes: wrapped per server route by
|
|
11
|
+
* `wrapEmailNodeHandler` (see `generateNodeHandlersForSegment`);
|
|
12
|
+
* - the invoice sender (`utils/invoices/email-sender.js`);
|
|
13
|
+
* - the welcome / farewell routes (`transactional-email-code.ts`);
|
|
14
|
+
* - the order-notification / low-stock routes (`utils/ecommerce/email-sender.js`).
|
|
15
|
+
*
|
|
16
|
+
* Contract: `recordSentEmail` never throws and never rejects, the send is
|
|
17
|
+
* never delayed by it, and a route drains it before replying (a serverless
|
|
18
|
+
* function may be frozen the instant it responds). Only an explicit allow-list
|
|
19
|
+
* of fields is stored — a node config carries credentials.
|
|
20
|
+
*
|
|
21
|
+
* `pgSupported=false` (a MySQL / Mongo / Firestore project) emits a module with
|
|
22
|
+
* the same exports that records nothing, so consumers need no branching.
|
|
23
|
+
*/
|
|
24
|
+
const PG_REQUIRE_LINE = "const { Client } = require('pg');";
|
|
25
|
+
/**
|
|
26
|
+
* The shared `getClient()` boilerplate with its eager `require('pg')` swapped
|
|
27
|
+
* for the lazy loader above: a project can carry an email node and no
|
|
28
|
+
* Postgres driver, and a top-level require would fail the build of every
|
|
29
|
+
* workflow route ("Collecting page data"). `new Client(opts)` keeps working —
|
|
30
|
+
* a constructor that returns an object yields that object.
|
|
31
|
+
*/
|
|
32
|
+
const lazyPgClientCode = () => {
|
|
33
|
+
const code = (0, pg_client_code_1.generatePgClientCode)();
|
|
34
|
+
if (!code.startsWith(PG_REQUIRE_LINE)) {
|
|
35
|
+
throw new Error('sent-email-log: generatePgClientCode() no longer starts with the pg require line');
|
|
36
|
+
}
|
|
37
|
+
return code.replace(PG_REQUIRE_LINE, 'function Client(opts) { var pg = __loadPg(); return new pg.Client(opts); }');
|
|
38
|
+
};
|
|
39
|
+
const generateSentEmailLogCode = (options) => {
|
|
40
|
+
if (!options.pgSupported) {
|
|
41
|
+
return `/**
|
|
42
|
+
* Sent-email ledger — disabled: the project's data source is not Postgres.
|
|
43
|
+
*/
|
|
44
|
+
function recordSentEmail() { return Promise.resolve(false); }
|
|
45
|
+
function settleSentEmailLog() { return Promise.resolve(); }
|
|
46
|
+
function wrapEmailNodeHandler(_nodeType, handler) { return handler; }
|
|
47
|
+
|
|
48
|
+
module.exports = { recordSentEmail, settleSentEmailLog, wrapEmailNodeHandler };
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
return `/**
|
|
52
|
+
* Sent-email ledger.
|
|
53
|
+
*
|
|
54
|
+
* Every email the app sends — workflow email nodes, the invoice sender, the
|
|
55
|
+
* welcome/farewell routes, order and stock alerts — lands here as one row of
|
|
56
|
+
* \`teleport_sent_emails\`: who it went to, what it said, the values the
|
|
57
|
+
* template was filled with, and whether the provider accepted it.
|
|
58
|
+
*
|
|
59
|
+
* Never awaited by the send itself; never throws; drained before a route
|
|
60
|
+
* replies (see settleSentEmailLog).
|
|
61
|
+
*/
|
|
62
|
+
var __pg = null;
|
|
63
|
+
var __pgLoadFailed = false;
|
|
64
|
+
function __loadPg() {
|
|
65
|
+
if (__pg || __pgLoadFailed) return __pg;
|
|
66
|
+
try { __pg = require('pg'); } catch (_e) { __pgLoadFailed = true; __pg = null; }
|
|
67
|
+
return __pg;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
${lazyPgClientCode()}
|
|
71
|
+
|
|
72
|
+
var TABLE_NAME = 'teleport_sent_emails';
|
|
73
|
+
var BODY_MAX_CHARS = 1000000;
|
|
74
|
+
var PAYLOAD_MAX_CHARS = 200000;
|
|
75
|
+
var SUBJECT_MAX_CHARS = 2000;
|
|
76
|
+
var ADDRESS_MAX_CHARS = 320;
|
|
77
|
+
var TRUNCATION_MARKER = '\\n<!-- truncated by sent-email-log -->';
|
|
78
|
+
var INSERT_TIMEOUT_MS = 15000;
|
|
79
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
80
|
+
// Template parameters whose VALUE must not be persisted: a reset link carries
|
|
81
|
+
// a live token, and the ledger is readable from the admin panel.
|
|
82
|
+
var SENSITIVE_PARAM_KEY_RE = /token|password|secret|otp|reset|verif|magic|passcode/i;
|
|
83
|
+
var REDACTED = '[redacted]';
|
|
84
|
+
|
|
85
|
+
var __pending = [];
|
|
86
|
+
var __disabledReason = '';
|
|
87
|
+
var __consecutiveFailures = 0;
|
|
88
|
+
var MAX_CONSECUTIVE_FAILURES = 3;
|
|
89
|
+
|
|
90
|
+
function __disable(reason) {
|
|
91
|
+
if (__disabledReason) return;
|
|
92
|
+
__disabledReason = reason;
|
|
93
|
+
console.warn('[sent-email-log] disabled for this process: ' + reason);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function __hasDatabaseEnv() {
|
|
97
|
+
return !!(process.env.TELEPORT_DB_CONNECTION_STRING || process.env.TELEPORT_DB_HOST);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function __toArray(value) {
|
|
101
|
+
if (value == null || value === '') return [];
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
var out = [];
|
|
104
|
+
for (var i = 0; i < value.length; i++) { out = out.concat(__toArray(value[i])); }
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === 'object') {
|
|
108
|
+
// Provider SDK shapes: { email, name } / { address }.
|
|
109
|
+
var addr = value.email || value.address || value.emailAddress;
|
|
110
|
+
return addr ? [String(addr)] : [];
|
|
111
|
+
}
|
|
112
|
+
return String(value).split(',').map(function (s) { return s.trim(); }).filter(Boolean);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function __truncate(text, max) {
|
|
116
|
+
if (text == null) return null;
|
|
117
|
+
var str = String(text);
|
|
118
|
+
if (str.length <= max) return str;
|
|
119
|
+
return str.slice(0, max) + TRUNCATION_MARKER;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function __safeStringify(value, max) {
|
|
123
|
+
if (value == null) return null;
|
|
124
|
+
var json;
|
|
125
|
+
try {
|
|
126
|
+
json = JSON.stringify(value, function (_k, v) {
|
|
127
|
+
if (typeof v === 'bigint') return String(v);
|
|
128
|
+
if (v && typeof v === 'object' && v.type === 'Buffer' && Array.isArray(v.data)) return '[buffer ' + v.data.length + ' bytes]';
|
|
129
|
+
return v;
|
|
130
|
+
});
|
|
131
|
+
} catch (_e) {
|
|
132
|
+
return '"[unserializable]"';
|
|
133
|
+
}
|
|
134
|
+
if (json == null) return null;
|
|
135
|
+
return __truncate(json, max);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// "Acme Billing <billing@acme.com>" → { name, email }; "billing@acme.com" → { name: '', email }.
|
|
139
|
+
function __parseAddress(from) {
|
|
140
|
+
var str = String(from || '').trim();
|
|
141
|
+
if (!str) return { name: '', email: '' };
|
|
142
|
+
var m = /^(.*)<([^<>]+)>\\s*$/.exec(str);
|
|
143
|
+
if (m) return { name: m[1].trim().replace(/^"|"$/g, ''), email: m[2].trim() };
|
|
144
|
+
return { name: '', email: str };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function __uuidOrNull(value) {
|
|
148
|
+
if (typeof value !== 'string' || !UUID_RE.test(value)) return null;
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// templateParams arrive as [{ key, value }] (workflow nodes) or as a plain
|
|
153
|
+
// object (routes). Returns { payload, redactedValues } where redactedValues
|
|
154
|
+
// are the string values of sensitive keys, to be scrubbed from the body too.
|
|
155
|
+
function __normalizePayload(params) {
|
|
156
|
+
var payload = {};
|
|
157
|
+
var redactedValues = [];
|
|
158
|
+
var entries = [];
|
|
159
|
+
if (Array.isArray(params)) {
|
|
160
|
+
for (var i = 0; i < params.length; i++) {
|
|
161
|
+
var p = params[i];
|
|
162
|
+
if (p && typeof p === 'object' && typeof p.key === 'string') entries.push([p.key, p.value]);
|
|
163
|
+
}
|
|
164
|
+
} else if (params && typeof params === 'object') {
|
|
165
|
+
var keys = Object.keys(params);
|
|
166
|
+
for (var k = 0; k < keys.length; k++) entries.push([keys[k], params[keys[k]]]);
|
|
167
|
+
}
|
|
168
|
+
for (var e = 0; e < entries.length; e++) {
|
|
169
|
+
var key = entries[e][0];
|
|
170
|
+
var value = entries[e][1];
|
|
171
|
+
if (SENSITIVE_PARAM_KEY_RE.test(key)) {
|
|
172
|
+
if (typeof value === 'string' && value.length >= 8) redactedValues.push(value);
|
|
173
|
+
payload[key] = REDACTED;
|
|
174
|
+
} else {
|
|
175
|
+
payload[key] = value;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { payload: entries.length ? payload : null, redactedValues: redactedValues };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function __scrub(text, redactedValues) {
|
|
182
|
+
if (!text) return text;
|
|
183
|
+
var out = String(text);
|
|
184
|
+
for (var i = 0; i < redactedValues.length; i++) {
|
|
185
|
+
out = out.split(redactedValues[i]).join(REDACTED);
|
|
186
|
+
}
|
|
187
|
+
return out;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function __normalizeAttachments(attachments) {
|
|
191
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return null;
|
|
192
|
+
var out = [];
|
|
193
|
+
for (var i = 0; i < attachments.length; i++) {
|
|
194
|
+
var a = attachments[i] || {};
|
|
195
|
+
out.push({
|
|
196
|
+
filename: a.filename || a.name || a.Name || 'attachment',
|
|
197
|
+
contentType: a.contentType || a.type || a.ContentType || null,
|
|
198
|
+
sizeBytes: typeof a.sizeBytes === 'number' ? a.sizeBytes : null,
|
|
199
|
+
url: a.url || null,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return __safeStringify(out, PAYLOAD_MAX_CHARS);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Maps a loose entry onto the table's columns. Returns null when there is
|
|
207
|
+
* nothing to record (no recipient at all).
|
|
208
|
+
*
|
|
209
|
+
* entry: { emailType, audience, to, cc, bcc, from, fromName, replyTo, subject,
|
|
210
|
+
* html, payload, attachments, provider, providerMessageId, status,
|
|
211
|
+
* error, source, sourceRef, orderId, userId, referenceType, referenceId }
|
|
212
|
+
*/
|
|
213
|
+
function buildSentEmailRow(entry) {
|
|
214
|
+
var e = entry || {};
|
|
215
|
+
var recipients = __toArray(e.to);
|
|
216
|
+
if (recipients.length === 0) return null;
|
|
217
|
+
var from = __parseAddress(e.from);
|
|
218
|
+
var fromName = e.fromName ? String(e.fromName) : from.name;
|
|
219
|
+
var normalized = __normalizePayload(e.payload);
|
|
220
|
+
var cc = __toArray(e.cc);
|
|
221
|
+
var bcc = __toArray(e.bcc);
|
|
222
|
+
var status = e.status === 'failed' ? 'failed' : 'sent';
|
|
223
|
+
return {
|
|
224
|
+
email_type: __truncate(e.emailType || 'custom', 100),
|
|
225
|
+
audience: __truncate(e.audience || 'other', 20),
|
|
226
|
+
recipient_email: __truncate(recipients[0], ADDRESS_MAX_CHARS),
|
|
227
|
+
recipients: JSON.stringify(recipients),
|
|
228
|
+
cc: cc.length ? JSON.stringify(cc) : null,
|
|
229
|
+
bcc: bcc.length ? JSON.stringify(bcc) : null,
|
|
230
|
+
reply_to: e.replyTo ? __truncate(__toArray(e.replyTo)[0] || '', ADDRESS_MAX_CHARS) : null,
|
|
231
|
+
from_email: from.email ? __truncate(from.email, ADDRESS_MAX_CHARS) : null,
|
|
232
|
+
from_name: fromName ? __truncate(fromName, 255) : null,
|
|
233
|
+
subject: __truncate(__scrub(e.subject, normalized.redactedValues), SUBJECT_MAX_CHARS),
|
|
234
|
+
body_html: __truncate(__scrub(e.html, normalized.redactedValues), BODY_MAX_CHARS) || '',
|
|
235
|
+
payload: __safeStringify(normalized.payload, PAYLOAD_MAX_CHARS),
|
|
236
|
+
attachments: __normalizeAttachments(e.attachments),
|
|
237
|
+
provider: e.provider ? __truncate(e.provider, 50) : null,
|
|
238
|
+
provider_message_id: e.providerMessageId ? __truncate(String(e.providerMessageId), 255) : null,
|
|
239
|
+
status: status,
|
|
240
|
+
error_message: e.error ? __truncate(String(e.error), 4000) : null,
|
|
241
|
+
source: __truncate(e.source || 'app', 50),
|
|
242
|
+
source_ref: e.sourceRef ? __truncate(String(e.sourceRef), 255) : null,
|
|
243
|
+
order_id: __uuidOrNull(e.orderId),
|
|
244
|
+
user_id: __uuidOrNull(e.userId),
|
|
245
|
+
reference_type: e.referenceType ? __truncate(String(e.referenceType), 50) : null,
|
|
246
|
+
reference_id: e.referenceId ? __truncate(String(e.referenceId), 255) : null,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function __newId() {
|
|
251
|
+
try {
|
|
252
|
+
var crypto = require('crypto');
|
|
253
|
+
if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();
|
|
254
|
+
var b = crypto.randomBytes(16);
|
|
255
|
+
b[6] = (b[6] & 0x0f) | 0x40;
|
|
256
|
+
b[8] = (b[8] & 0x3f) | 0x80;
|
|
257
|
+
var h = b.toString('hex');
|
|
258
|
+
return h.slice(0, 8) + '-' + h.slice(8, 12) + '-' + h.slice(12, 16) + '-' + h.slice(16, 20) + '-' + h.slice(20);
|
|
259
|
+
} catch (_e) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function __withTimeout(promise, ms) {
|
|
265
|
+
var timer;
|
|
266
|
+
var timeout = new Promise(function (_resolve, reject) {
|
|
267
|
+
timer = setTimeout(function () { reject(new Error('sent-email-log insert timed out after ' + ms + 'ms')); }, ms);
|
|
268
|
+
});
|
|
269
|
+
return Promise.race([promise, timeout]).then(function (v) { clearTimeout(timer); return v; }, function (err) { clearTimeout(timer); throw err; });
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function __insert(row) {
|
|
273
|
+
var columns = Object.keys(row);
|
|
274
|
+
var values = columns.map(function (c) { return row[c]; });
|
|
275
|
+
var id = __newId();
|
|
276
|
+
if (id) { columns.unshift('id'); values.unshift(id); }
|
|
277
|
+
var placeholders = values.map(function (_v, i) { return '$' + (i + 1); });
|
|
278
|
+
var sql = 'INSERT INTO "' + TABLE_NAME + '" (' + columns.map(function (c) { return '"' + c + '"'; }).join(', ') + ') VALUES (' + placeholders.join(', ') + ')';
|
|
279
|
+
var client = getClient();
|
|
280
|
+
await client.connect();
|
|
281
|
+
try {
|
|
282
|
+
await __withTimeout(client.query(sql, values), INSERT_TIMEOUT_MS);
|
|
283
|
+
} finally {
|
|
284
|
+
try { await client.end(); } catch (_e) {}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Records one send attempt. Resolves to true when the row landed, false
|
|
290
|
+
* otherwise. NEVER rejects.
|
|
291
|
+
*/
|
|
292
|
+
function recordSentEmail(entry) {
|
|
293
|
+
var task = (async function () {
|
|
294
|
+
if (__disabledReason) return false;
|
|
295
|
+
if (!__hasDatabaseEnv()) { __disable('no database connection configured'); return false; }
|
|
296
|
+
if (!__loadPg()) { __disable('the pg driver is not installed'); return false; }
|
|
297
|
+
var row;
|
|
298
|
+
try { row = buildSentEmailRow(entry); } catch (buildErr) {
|
|
299
|
+
console.error('[sent-email-log] could not build the row:', buildErr && buildErr.message ? buildErr.message : buildErr);
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
if (!row) return false;
|
|
303
|
+
try {
|
|
304
|
+
await __insert(row);
|
|
305
|
+
__consecutiveFailures = 0;
|
|
306
|
+
return true;
|
|
307
|
+
} catch (err) {
|
|
308
|
+
var code = err && err.code;
|
|
309
|
+
if (code === '42P01') { __disable('table ' + TABLE_NAME + ' does not exist — re-run the feature activation in the editor'); return false; }
|
|
310
|
+
if (code === '42703') { __disable('table ' + TABLE_NAME + ' is missing a column — re-run the feature activation in the editor'); return false; }
|
|
311
|
+
__consecutiveFailures += 1;
|
|
312
|
+
console.error('[sent-email-log] insert failed: ' + (err && err.message ? err.message : String(err)));
|
|
313
|
+
if (__consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) __disable('repeated insert failures');
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
})();
|
|
317
|
+
__pending.push(task);
|
|
318
|
+
task.then(function () { __forget(task); }, function () { __forget(task); });
|
|
319
|
+
return task;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function __forget(task) {
|
|
323
|
+
var idx = __pending.indexOf(task);
|
|
324
|
+
if (idx >= 0) __pending.splice(idx, 1);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Awaits every in-flight record. Never rejects. */
|
|
328
|
+
async function settleSentEmailLog() {
|
|
329
|
+
for (var pass = 0; pass < 5 && __pending.length > 0; pass++) {
|
|
330
|
+
await Promise.all(__pending.slice());
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Provider name from a node type: 'email-resend' → 'resend', 'integration-gmail' → 'gmail'.
|
|
335
|
+
function __providerOf(nodeType) {
|
|
336
|
+
var t = String(nodeType || '');
|
|
337
|
+
if (t.indexOf('email-') === 0) return t.slice(6);
|
|
338
|
+
if (t.indexOf('integration-') === 0) return t.slice(12);
|
|
339
|
+
return t || null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function __shouldRecordNode(nodeType, config) {
|
|
343
|
+
if (String(nodeType).indexOf('email-') === 0) return true;
|
|
344
|
+
return !!config && config.action === 'send-email';
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function __entryFromNode(nodeType, config, result, error) {
|
|
348
|
+
var c = config || {};
|
|
349
|
+
var r = result || {};
|
|
350
|
+
var failed = !!error || r.success === false || (typeof r.error === 'string' && r.error) || r.error === true;
|
|
351
|
+
var message = r.message && typeof r.message === 'object' ? r.message : null;
|
|
352
|
+
var providerMessageId = r.messageId || r.id || (message && message.id) || null;
|
|
353
|
+
var errorText = error ? (error.message || String(error)) : (typeof r.error === 'string' ? r.error : (r.error === true && typeof r.message === 'string' ? r.message : null));
|
|
354
|
+
return {
|
|
355
|
+
emailType: c.emailPurpose || 'custom',
|
|
356
|
+
audience: c.emailAudience || 'other',
|
|
357
|
+
to: c.to,
|
|
358
|
+
cc: c.cc,
|
|
359
|
+
bcc: c.bcc,
|
|
360
|
+
from: c.from,
|
|
361
|
+
fromName: c.fromName,
|
|
362
|
+
replyTo: c.replyTo,
|
|
363
|
+
subject: c.subject,
|
|
364
|
+
html: c.body != null ? c.body : (c.html != null ? c.html : c.text),
|
|
365
|
+
payload: c.templateParams,
|
|
366
|
+
provider: __providerOf(nodeType),
|
|
367
|
+
providerMessageId: providerMessageId,
|
|
368
|
+
status: failed ? 'failed' : 'sent',
|
|
369
|
+
error: errorText,
|
|
370
|
+
source: 'workflow',
|
|
371
|
+
sourceRef: nodeType,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Wraps a server node handler so every send is recorded. The record is
|
|
377
|
+
* registered on the workflow context's fire-and-forget queue — the same one
|
|
378
|
+
* \`settlePendingNodePromises\` drains before the route replies — and pushed
|
|
379
|
+
* BEFORE the handler's result is returned, so the drain always sees it.
|
|
380
|
+
* Extra arguments (a streaming callback) are forwarded untouched.
|
|
381
|
+
*/
|
|
382
|
+
function wrapEmailNodeHandler(nodeType, handler) {
|
|
383
|
+
if (typeof handler !== 'function') return handler;
|
|
384
|
+
return async function (config, context) {
|
|
385
|
+
if (!__shouldRecordNode(nodeType, config)) {
|
|
386
|
+
return handler.apply(this, arguments);
|
|
387
|
+
}
|
|
388
|
+
var result;
|
|
389
|
+
try {
|
|
390
|
+
result = await handler.apply(this, arguments);
|
|
391
|
+
} catch (err) {
|
|
392
|
+
__register(context, recordSentEmail(__entryFromNode(nodeType, config, null, err)));
|
|
393
|
+
throw err;
|
|
394
|
+
}
|
|
395
|
+
__register(context, recordSentEmail(__entryFromNode(nodeType, config, result, null)));
|
|
396
|
+
return result;
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function __register(context, promise) {
|
|
401
|
+
if (!context || typeof context !== 'object') return;
|
|
402
|
+
if (!Array.isArray(context.__pendingNodePromises)) context.__pendingNodePromises = [];
|
|
403
|
+
context.__pendingNodePromises.push(promise);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
module.exports = {
|
|
407
|
+
recordSentEmail: recordSentEmail,
|
|
408
|
+
settleSentEmailLog: settleSentEmailLog,
|
|
409
|
+
wrapEmailNodeHandler: wrapEmailNodeHandler,
|
|
410
|
+
buildSentEmailRow: buildSentEmailRow,
|
|
411
|
+
};
|
|
412
|
+
`;
|
|
413
|
+
};
|
|
414
|
+
exports.generateSentEmailLogCode = generateSentEmailLogCode;
|
|
415
|
+
//# sourceMappingURL=sent-email-log-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sent-email-log-code.js","sourceRoot":"","sources":["../../../src/sent-email-log/sent-email-log-code.ts"],"names":[],"mappings":";;;AAAA,sDAAwD;AAExD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,eAAe,GAAG,mCAAmC,CAAA;AAE3D;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,GAAW,EAAE;IACpC,MAAM,IAAI,GAAG,IAAA,qCAAoB,GAAE,CAAA;IACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;QACrC,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAA;KACF;IACD,OAAO,IAAI,CAAC,OAAO,CACjB,eAAe,EACf,4EAA4E,CAC7E,CAAA;AACH,CAAC,CAAA;AAEM,MAAM,wBAAwB,GAAG,CAAC,OAAiC,EAAU,EAAE;IACpF,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;QACxB,OAAO;;;;;;;;CAQV,CAAA;KACE;IAED,OAAO;;;;;;;;;;;;;;;;;;;EAmBP,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsVnB,CAAA;AACD,CAAC,CAAA;AAvXY,QAAA,wBAAwB,4BAuXpC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which generated code sends email, and therefore which projects get the
|
|
3
|
+
* sent-email ledger module (`utils/email/sent-email-log.js`).
|
|
4
|
+
*
|
|
5
|
+
* Every emitter of a send path calls `ensureSentEmailLogModule` itself, so the
|
|
6
|
+
* module exists exactly when something `require`s it. This file only holds the
|
|
7
|
+
* node-type vocabulary the route generators share.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SENT_EMAIL_LOG_FILE_KEY = "sent-email-log";
|
|
10
|
+
export declare const SENT_EMAIL_LOG_PATH: string[];
|
|
11
|
+
export declare const SENT_EMAIL_LOG_FILE_NAME = "sent-email-log";
|
|
12
|
+
/** Provider send-email nodes: `email-resend`, `email-sendgrid`, … */
|
|
13
|
+
export declare const EMAIL_NODE_TYPE_PREFIX = "email-";
|
|
14
|
+
/**
|
|
15
|
+
* Integration nodes that can send mail among other actions. Only their
|
|
16
|
+
* `send-email` action is recorded; the wrapper checks the resolved config.
|
|
17
|
+
*/
|
|
18
|
+
export declare const EMAIL_CAPABLE_INTEGRATION_NODE_TYPES: Set<string>;
|
|
19
|
+
export declare const isEmailSendingNodeType: (nodeType: string) => boolean;
|
|
20
|
+
export declare const hasEmailSendingNodeType: (nodeTypes: Iterable<string>) => boolean;
|
|
21
|
+
//# sourceMappingURL=sent-email-log-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sent-email-log-scope.d.ts","sourceRoot":"","sources":["../../../src/sent-email-log/sent-email-log-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,uBAAuB,mBAAmB,CAAA;AACvD,eAAO,MAAM,mBAAmB,UAAqB,CAAA;AACrD,eAAO,MAAM,wBAAwB,mBAAmB,CAAA;AAExD,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,WAAW,CAAA;AAE9C;;;GAGG;AACH,eAAO,MAAM,oCAAoC,aAG/C,CAAA;AAEF,eAAO,MAAM,sBAAsB,aAAc,MAAM,KAAG,OACyC,CAAA;AAEnG,eAAO,MAAM,uBAAuB,cAAe,SAAS,MAAM,CAAC,KAAG,OAOrE,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Which generated code sends email, and therefore which projects get the
|
|
4
|
+
* sent-email ledger module (`utils/email/sent-email-log.js`).
|
|
5
|
+
*
|
|
6
|
+
* Every emitter of a send path calls `ensureSentEmailLogModule` itself, so the
|
|
7
|
+
* module exists exactly when something `require`s it. This file only holds the
|
|
8
|
+
* node-type vocabulary the route generators share.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.hasEmailSendingNodeType = exports.isEmailSendingNodeType = exports.EMAIL_CAPABLE_INTEGRATION_NODE_TYPES = exports.EMAIL_NODE_TYPE_PREFIX = exports.SENT_EMAIL_LOG_FILE_NAME = exports.SENT_EMAIL_LOG_PATH = exports.SENT_EMAIL_LOG_FILE_KEY = void 0;
|
|
12
|
+
exports.SENT_EMAIL_LOG_FILE_KEY = 'sent-email-log';
|
|
13
|
+
exports.SENT_EMAIL_LOG_PATH = ['utils', 'email'];
|
|
14
|
+
exports.SENT_EMAIL_LOG_FILE_NAME = 'sent-email-log';
|
|
15
|
+
/** Provider send-email nodes: `email-resend`, `email-sendgrid`, … */
|
|
16
|
+
exports.EMAIL_NODE_TYPE_PREFIX = 'email-';
|
|
17
|
+
/**
|
|
18
|
+
* Integration nodes that can send mail among other actions. Only their
|
|
19
|
+
* `send-email` action is recorded; the wrapper checks the resolved config.
|
|
20
|
+
*/
|
|
21
|
+
exports.EMAIL_CAPABLE_INTEGRATION_NODE_TYPES = new Set([
|
|
22
|
+
'integration-gmail',
|
|
23
|
+
'integration-outlook',
|
|
24
|
+
]);
|
|
25
|
+
const isEmailSendingNodeType = (nodeType) => nodeType.startsWith(exports.EMAIL_NODE_TYPE_PREFIX) || exports.EMAIL_CAPABLE_INTEGRATION_NODE_TYPES.has(nodeType);
|
|
26
|
+
exports.isEmailSendingNodeType = isEmailSendingNodeType;
|
|
27
|
+
const hasEmailSendingNodeType = (nodeTypes) => {
|
|
28
|
+
for (const nodeType of nodeTypes) {
|
|
29
|
+
if ((0, exports.isEmailSendingNodeType)(nodeType)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
};
|
|
35
|
+
exports.hasEmailSendingNodeType = hasEmailSendingNodeType;
|
|
36
|
+
//# sourceMappingURL=sent-email-log-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sent-email-log-scope.js","sourceRoot":"","sources":["../../../src/sent-email-log/sent-email-log-scope.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEU,QAAA,uBAAuB,GAAG,gBAAgB,CAAA;AAC1C,QAAA,mBAAmB,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACxC,QAAA,wBAAwB,GAAG,gBAAgB,CAAA;AAExD,qEAAqE;AACxD,QAAA,sBAAsB,GAAG,QAAQ,CAAA;AAE9C;;;GAGG;AACU,QAAA,oCAAoC,GAAG,IAAI,GAAG,CAAC;IAC1D,mBAAmB;IACnB,qBAAqB;CACtB,CAAC,CAAA;AAEK,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAW,EAAE,CAClE,QAAQ,CAAC,UAAU,CAAC,8BAAsB,CAAC,IAAI,4CAAoC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AADtF,QAAA,sBAAsB,0BACgE;AAE5F,MAAM,uBAAuB,GAAG,CAAC,SAA2B,EAAW,EAAE;IAC9E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,IAAI,IAAA,8BAAsB,EAAC,QAAQ,CAAC,EAAE;YACpC,OAAO,IAAI,CAAA;SACZ;KACF;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAPY,QAAA,uBAAuB,2BAOnC"}
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
export declare const SUPPORTED_EMAIL_PROVIDERS: Set<string>;
|
|
2
2
|
export declare const transactionalEmailDependencies: (provider?: string | null) => Record<string, string>;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Where a transactional route's sends are recorded in the sent-email ledger:
|
|
5
|
+
* the purpose slug, the `source` column and the route file, plus the require
|
|
6
|
+
* prefix from the route's directory back to the project root.
|
|
7
|
+
*/
|
|
8
|
+
export interface TransactionalEmailLedger {
|
|
9
|
+
emailType: string;
|
|
10
|
+
source: string;
|
|
11
|
+
sourceRef: string;
|
|
12
|
+
relativePrefix: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const generateProviderSendFunction: (provider?: string | null, ledger?: TransactionalEmailLedger) => string;
|
|
4
15
|
export declare const generateFillTemplateFn: () => string;
|
|
5
16
|
export declare const WELCOME_EMAIL_CONFIG_KEYS: string[];
|
|
6
17
|
//# sourceMappingURL=transactional-email-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactional-email-code.d.ts","sourceRoot":"","sources":["../../src/transactional-email-code.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,yBAAyB,aAMpC,CAAA;AAIF,eAAO,MAAM,8BAA8B,cAC9B,MAAM,GAAG,IAAI,KACvB,OAAO,MAAM,EAAE,MAAM,CAKvB,CAAA;
|
|
1
|
+
{"version":3,"file":"transactional-email-code.d.ts","sourceRoot":"","sources":["../../src/transactional-email-code.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,yBAAyB,aAMpC,CAAA;AAIF,eAAO,MAAM,8BAA8B,cAC9B,MAAM,GAAG,IAAI,KACvB,OAAO,MAAM,EAAE,MAAM,CAKvB,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;CACvB;AAQD,eAAO,MAAM,4BAA4B,cAC5B,MAAM,GAAG,IAAI,WACf,wBAAwB,KAChC,MAqCF,CAAA;AAyDD,eAAO,MAAM,sBAAsB,QAAO,MASxC,CAAA;AAKF,eAAO,MAAM,yBAAyB,UAYrC,CAAA"}
|
|
@@ -24,10 +24,49 @@ const transactionalEmailDependencies = (provider) => {
|
|
|
24
24
|
return (0, email_sender_code_1.getEmailProviderDependencies)(provider);
|
|
25
25
|
};
|
|
26
26
|
exports.transactionalEmailDependencies = transactionalEmailDependencies;
|
|
27
|
-
// Provider-specific `__sendProviderEmail({ from, to, subject, html, apiKey
|
|
28
|
-
// No attachment (unlike the invoice sender). When
|
|
29
|
-
// function is a no-op so the route stays
|
|
30
|
-
|
|
27
|
+
// Provider-specific `__sendProviderEmail({ from, to, subject, html, apiKey,
|
|
28
|
+
// tokenValues?, userId? })`. No attachment (unlike the invoice sender). When
|
|
29
|
+
// no provider is configured the function is a no-op so the route stays
|
|
30
|
+
// self-contained and never throws. With `ledger`, the provider function is
|
|
31
|
+
// emitted as `__sendProviderEmailRaw` and `__sendProviderEmail` records every
|
|
32
|
+
// attempt (success or throw) before returning / rethrowing.
|
|
33
|
+
const generateProviderSendFunction = (provider, ledger) => {
|
|
34
|
+
const raw = generateRawProviderSendFunction(provider);
|
|
35
|
+
if (!ledger || !provider || !exports.SUPPORTED_EMAIL_PROVIDERS.has(provider)) {
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
return `${raw.replace('async function __sendProviderEmail(', 'async function __sendProviderEmailRaw(')}
|
|
39
|
+
|
|
40
|
+
var __sentEmailLog = require('${ledger.relativePrefix}/utils/email/sent-email-log');
|
|
41
|
+
|
|
42
|
+
async function __sendProviderEmail(msg) {
|
|
43
|
+
var failure = null;
|
|
44
|
+
try {
|
|
45
|
+
await __sendProviderEmailRaw(msg);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
failure = err;
|
|
48
|
+
}
|
|
49
|
+
// Recorded in the background; the route settles the ledger before it replies.
|
|
50
|
+
__sentEmailLog.recordSentEmail({
|
|
51
|
+
emailType: ${JSON.stringify(ledger.emailType)},
|
|
52
|
+
audience: 'customer',
|
|
53
|
+
to: msg.to,
|
|
54
|
+
from: msg.from,
|
|
55
|
+
subject: msg.subject,
|
|
56
|
+
html: msg.html,
|
|
57
|
+
payload: msg.tokenValues,
|
|
58
|
+
provider: ${JSON.stringify(provider)},
|
|
59
|
+
status: failure ? 'failed' : 'sent',
|
|
60
|
+
error: failure ? (failure.message || String(failure)) : null,
|
|
61
|
+
source: ${JSON.stringify(ledger.source)},
|
|
62
|
+
sourceRef: ${JSON.stringify(ledger.sourceRef)},
|
|
63
|
+
userId: msg.userId,
|
|
64
|
+
});
|
|
65
|
+
if (failure) { throw failure; }
|
|
66
|
+
}`;
|
|
67
|
+
};
|
|
68
|
+
exports.generateProviderSendFunction = generateProviderSendFunction;
|
|
69
|
+
const generateRawProviderSendFunction = (provider) => {
|
|
31
70
|
switch (provider) {
|
|
32
71
|
case 'resend':
|
|
33
72
|
return `async function __sendProviderEmail(msg) {
|
|
@@ -79,7 +118,6 @@ const generateProviderSendFunction = (provider) => {
|
|
|
79
118
|
}`;
|
|
80
119
|
}
|
|
81
120
|
};
|
|
82
|
-
exports.generateProviderSendFunction = generateProviderSendFunction;
|
|
83
121
|
// Emits the `fillTemplate(str, values)` flat `{{key}}` replacer used to fill the
|
|
84
122
|
// email subject/body tokens at send time.
|
|
85
123
|
const generateFillTemplateFn = () => `function fillTemplate(str, values) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactional-email-code.js","sourceRoot":"","sources":["../../src/transactional-email-code.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,mEAA0E;AAE7D,QAAA,yBAAyB,GAAG,IAAI,GAAG,CAAC;IAC/C,QAAQ;IACR,UAAU;IACV,UAAU;IACV,SAAS;IACT,YAAY;CACb,CAAC,CAAA;AAEF,+EAA+E;AAC/E,8BAA8B;AACvB,MAAM,8BAA8B,GAAG,CAC5C,QAAwB,EACA,EAAE;IAC1B,IAAI,CAAC,QAAQ,IAAI,CAAC,iCAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACzD,OAAO,EAAE,CAAA;KACV;IACD,OAAO,IAAA,gDAA4B,EAAC,QAAQ,CAAC,CAAA;AAC/C,CAAC,CAAA;AAPY,QAAA,8BAA8B,kCAO1C;
|
|
1
|
+
{"version":3,"file":"transactional-email-code.js","sourceRoot":"","sources":["../../src/transactional-email-code.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,mEAA0E;AAE7D,QAAA,yBAAyB,GAAG,IAAI,GAAG,CAAC;IAC/C,QAAQ;IACR,UAAU;IACV,UAAU;IACV,SAAS;IACT,YAAY;CACb,CAAC,CAAA;AAEF,+EAA+E;AAC/E,8BAA8B;AACvB,MAAM,8BAA8B,GAAG,CAC5C,QAAwB,EACA,EAAE;IAC1B,IAAI,CAAC,QAAQ,IAAI,CAAC,iCAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACzD,OAAO,EAAE,CAAA;KACV;IACD,OAAO,IAAA,gDAA4B,EAAC,QAAQ,CAAC,CAAA;AAC/C,CAAC,CAAA;AAPY,QAAA,8BAA8B,kCAO1C;AAcD,4EAA4E;AAC5E,6EAA6E;AAC7E,uEAAuE;AACvE,2EAA2E;AAC3E,8EAA8E;AAC9E,4DAA4D;AACrD,MAAM,4BAA4B,GAAG,CAC1C,QAAwB,EACxB,MAAiC,EACzB,EAAE;IACV,MAAM,GAAG,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAA;IACrD,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,IAAI,CAAC,iCAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACpE,OAAO,GAAG,CAAA;KACX;IACD,OAAO,GAAG,GAAG,CAAC,OAAO,CACnB,qCAAqC,EACrC,wCAAwC,CACzC;;gCAE6B,MAAM,CAAC,cAAc;;;;;;;;;;;iBAWpC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;;;;;;;gBAOjC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;cAG1B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;iBAC1B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;;;;EAI/C,CAAA;AACF,CAAC,CAAA;AAxCY,QAAA,4BAA4B,gCAwCxC;AAED,MAAM,+BAA+B,GAAG,CAAC,QAAwB,EAAU,EAAE;IAC3E,QAAQ,QAAQ,EAAE;QAChB,KAAK,QAAQ;YACX,OAAO;;;;;EAKX,CAAA;QACE,KAAK,UAAU;YACb,OAAO;;;;EAIX,CAAA;QACE,KAAK,UAAU;YACb,OAAO;;;;EAIX,CAAA;QACE,KAAK,SAAS;YACZ,OAAO;;;;;;;;EAQX,CAAA;QACE,KAAK,YAAY;YACf,OAAO;;;;;;;;;;;;;EAaX,CAAA;QACE;YACE,OAAO;;EAEX,CAAA;KACC;AACH,CAAC,CAAA;AAED,iFAAiF;AACjF,0CAA0C;AACnC,MAAM,sBAAsB,GAAG,GAAW,EAAE,CAAC;;;;;;;;;EASlD,CAAA;AATW,QAAA,sBAAsB,0BASjC;AAEF,0EAA0E;AAC1E,+EAA+E;AAC/E,4EAA4E;AAC/D,QAAA,yBAAyB,GAAG;IACvC,eAAe;IACf,MAAM;IACN,UAAU;IACV,QAAQ;IACR,aAAa;IACb,SAAS;IACT,MAAM;IACN,YAAY;IACZ,iBAAiB;IACjB,qBAAqB;IACrB,gBAAgB;CACjB,CAAA"}
|