@vertebr/admin 0.14.0 → 0.16.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.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/api/catalog.d.ts +17 -9
- package/dist/runtime/api/catalog.d.ts.map +1 -1
- package/dist/runtime/api/catalog.js +10 -0
- package/dist/runtime/api/catalog.js.map +1 -1
- package/dist/runtime/connectors/payments/connector.d.ts.map +1 -1
- package/dist/runtime/connectors/payments/connector.js +3 -0
- package/dist/runtime/connectors/payments/connector.js.map +1 -1
- package/dist/runtime/createAdmin.d.ts.map +1 -1
- package/dist/runtime/createAdmin.js +3 -0
- package/dist/runtime/createAdmin.js.map +1 -1
- package/dist/runtime/types/addon.d.ts +3 -0
- package/dist/runtime/types/addon.d.ts.map +1 -1
- package/dist/runtime/types/addon.js.map +1 -1
- package/dist/runtime/types/audit.d.ts +3 -0
- package/dist/runtime/types/audit.d.ts.map +1 -1
- package/dist/runtime/types/config.d.ts +5 -0
- package/dist/runtime/types/config.d.ts.map +1 -1
- package/dist/runtime/types/index.d.ts +2 -0
- package/dist/runtime/types/index.d.ts.map +1 -1
- package/dist/runtime/types/index.js +4 -0
- package/dist/runtime/types/index.js.map +1 -1
- package/dist/runtime/types/layout.d.ts +3 -0
- package/dist/runtime/types/layout.d.ts.map +1 -1
- package/dist/runtime/types/mail/definition.d.ts +3 -0
- package/dist/runtime/types/mail/definition.d.ts.map +1 -1
- package/dist/runtime/types/metrics.d.ts +3 -0
- package/dist/runtime/types/metrics.d.ts.map +1 -1
- package/dist/runtime/types/navIcon.d.ts +8 -0
- package/dist/runtime/types/navIcon.d.ts.map +1 -0
- package/dist/runtime/types/navIcon.js +37 -0
- package/dist/runtime/types/navIcon.js.map +1 -0
- package/dist/runtime/types/resource.d.ts +3 -0
- package/dist/runtime/types/resource.d.ts.map +1 -1
- package/dist/schema.d.ts +9 -0
- package/dist/schema.d.ts.map +1 -1
- package/package.json +1 -1
- package/static/assets/index-6EkB-KyS.js +340 -0
- package/static/assets/index-BOeFzdnv.css +1 -0
- package/static/brand/apple-touch-icon.png +0 -0
- package/static/brand/favicon-192.png +0 -0
- package/static/brand/favicon-32.png +0 -0
- package/static/brand/vertebr-mark-light.svg +10 -0
- package/static/brand/vertebr-mark.svg +10 -0
- package/static/index.html +21 -2
- package/dist/api/catalog.d.ts +0 -59
- package/dist/api/catalog.d.ts.map +0 -1
- package/dist/api/catalog.js +0 -85
- package/dist/api/catalog.js.map +0 -1
- package/dist/api/configs.d.ts +0 -15
- package/dist/api/configs.d.ts.map +0 -1
- package/dist/api/configs.js +0 -43
- package/dist/api/configs.js.map +0 -1
- package/dist/api/emails.d.ts +0 -85
- package/dist/api/emails.d.ts.map +0 -1
- package/dist/api/emails.js +0 -520
- package/dist/api/emails.js.map +0 -1
- package/dist/api/gallery.d.ts +0 -28
- package/dist/api/gallery.d.ts.map +0 -1
- package/dist/api/gallery.js +0 -91
- package/dist/api/gallery.js.map +0 -1
- package/dist/api/metrics.d.ts +0 -22
- package/dist/api/metrics.d.ts.map +0 -1
- package/dist/api/metrics.js +0 -38
- package/dist/api/metrics.js.map +0 -1
- package/dist/api/public.d.ts +0 -22
- package/dist/api/public.d.ts.map +0 -1
- package/dist/api/public.js +0 -69
- package/dist/api/public.js.map +0 -1
- package/dist/api/request.d.ts +0 -26
- package/dist/api/request.d.ts.map +0 -1
- package/dist/api/request.js +0 -38
- package/dist/api/request.js.map +0 -1
- package/dist/api/resources.d.ts +0 -85
- package/dist/api/resources.d.ts.map +0 -1
- package/dist/api/resources.js +0 -263
- package/dist/api/resources.js.map +0 -1
- package/dist/api/routes.d.ts +0 -8
- package/dist/api/routes.d.ts.map +0 -1
- package/dist/api/routes.js +0 -202
- package/dist/api/routes.js.map +0 -1
- package/dist/api/spa.d.ts +0 -2
- package/dist/api/spa.d.ts.map +0 -1
- package/dist/api/spa.js +0 -34
- package/dist/api/spa.js.map +0 -1
- package/dist/connectors/payments/connector.d.ts +0 -30
- package/dist/connectors/payments/connector.d.ts.map +0 -1
- package/dist/connectors/payments/connector.js +0 -226
- package/dist/connectors/payments/connector.js.map +0 -1
- package/dist/connectors/payments/index.d.ts +0 -4
- package/dist/connectors/payments/index.d.ts.map +0 -1
- package/dist/connectors/payments/index.js +0 -10
- package/dist/connectors/payments/index.js.map +0 -1
- package/dist/connectors/payments/stripe.d.ts +0 -99
- package/dist/connectors/payments/stripe.d.ts.map +0 -1
- package/dist/connectors/payments/stripe.js +0 -189
- package/dist/connectors/payments/stripe.js.map +0 -1
- package/dist/connectors/payments/types.d.ts +0 -67
- package/dist/connectors/payments/types.d.ts.map +0 -1
- package/dist/connectors/payments/types.js +0 -16
- package/dist/connectors/payments/types.js.map +0 -1
- package/dist/connectors/stripe.d.ts +0 -19
- package/dist/connectors/stripe.d.ts.map +0 -1
- package/dist/connectors/stripe.js +0 -26
- package/dist/connectors/stripe.js.map +0 -1
- package/dist/constants.d.ts +0 -5
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -8
- package/dist/constants.js.map +0 -1
- package/dist/createAdmin.d.ts +0 -3
- package/dist/createAdmin.d.ts.map +0 -1
- package/dist/createAdmin.js +0 -152
- package/dist/createAdmin.js.map +0 -1
- package/dist/database/firestore.d.ts +0 -71
- package/dist/database/firestore.d.ts.map +0 -1
- package/dist/database/firestore.js +0 -115
- package/dist/database/firestore.js.map +0 -1
- package/dist/database/memory.d.ts +0 -12
- package/dist/database/memory.d.ts.map +0 -1
- package/dist/database/memory.js +0 -116
- package/dist/database/memory.js.map +0 -1
- package/dist/database/mongo.d.ts +0 -41
- package/dist/database/mongo.d.ts.map +0 -1
- package/dist/database/mongo.js +0 -151
- package/dist/database/mongo.js.map +0 -1
- package/dist/database/postgres.d.ts +0 -46
- package/dist/database/postgres.d.ts.map +0 -1
- package/dist/database/postgres.js +0 -262
- package/dist/database/postgres.js.map +0 -1
- package/dist/errors.d.ts +0 -17
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -36
- package/dist/errors.js.map +0 -1
- package/dist/index/api/catalog.d.ts +0 -53
- package/dist/index/api/catalog.d.ts.map +0 -1
- package/dist/index/api/catalog.js +0 -70
- package/dist/index/api/catalog.js.map +0 -1
- package/dist/index/api/configs.d.ts +0 -15
- package/dist/index/api/configs.d.ts.map +0 -1
- package/dist/index/api/configs.js +0 -43
- package/dist/index/api/configs.js.map +0 -1
- package/dist/index/api/gallery.d.ts +0 -28
- package/dist/index/api/gallery.d.ts.map +0 -1
- package/dist/index/api/gallery.js +0 -89
- package/dist/index/api/gallery.js.map +0 -1
- package/dist/index/api/metrics.d.ts +0 -9
- package/dist/index/api/metrics.d.ts.map +0 -1
- package/dist/index/api/metrics.js +0 -26
- package/dist/index/api/metrics.js.map +0 -1
- package/dist/index/api/public.d.ts +0 -22
- package/dist/index/api/public.d.ts.map +0 -1
- package/dist/index/api/public.js +0 -69
- package/dist/index/api/public.js.map +0 -1
- package/dist/index/api/request.d.ts +0 -25
- package/dist/index/api/request.d.ts.map +0 -1
- package/dist/index/api/request.js +0 -38
- package/dist/index/api/request.js.map +0 -1
- package/dist/index/api/resources.d.ts +0 -64
- package/dist/index/api/resources.d.ts.map +0 -1
- package/dist/index/api/resources.js +0 -173
- package/dist/index/api/resources.js.map +0 -1
- package/dist/index/api/routes.d.ts +0 -8
- package/dist/index/api/routes.d.ts.map +0 -1
- package/dist/index/api/routes.js +0 -156
- package/dist/index/api/routes.js.map +0 -1
- package/dist/index/api/spa.d.ts +0 -2
- package/dist/index/api/spa.d.ts.map +0 -1
- package/dist/index/api/spa.js +0 -33
- package/dist/index/api/spa.js.map +0 -1
- package/dist/index/connectors/stripe.d.ts +0 -9
- package/dist/index/connectors/stripe.d.ts.map +0 -1
- package/dist/index/connectors/stripe.js +0 -23
- package/dist/index/connectors/stripe.js.map +0 -1
- package/dist/index/constants.d.ts +0 -5
- package/dist/index/constants.d.ts.map +0 -1
- package/dist/index/constants.js +0 -8
- package/dist/index/constants.js.map +0 -1
- package/dist/index/createAdmin.d.ts +0 -3
- package/dist/index/createAdmin.d.ts.map +0 -1
- package/dist/index/createAdmin.js +0 -145
- package/dist/index/createAdmin.js.map +0 -1
- package/dist/index/errors.d.ts +0 -17
- package/dist/index/errors.d.ts.map +0 -1
- package/dist/index/errors.js +0 -36
- package/dist/index/errors.js.map +0 -1
- package/dist/index/services/environment.d.ts +0 -8
- package/dist/index/services/environment.d.ts.map +0 -1
- package/dist/index/services/environment.js +0 -78
- package/dist/index/services/environment.js.map +0 -1
- package/dist/index/services/registry.d.ts +0 -6
- package/dist/index/services/registry.d.ts.map +0 -1
- package/dist/index/services/registry.js +0 -32
- package/dist/index/services/registry.js.map +0 -1
- package/dist/index/services/state.d.ts +0 -24
- package/dist/index/services/state.d.ts.map +0 -1
- package/dist/index/services/state.js +0 -3
- package/dist/index/services/state.js.map +0 -1
- package/dist/index/types/admin.d.ts +0 -77
- package/dist/index/types/admin.d.ts.map +0 -1
- package/dist/index/types/admin.js +0 -3
- package/dist/index/types/admin.js.map +0 -1
- package/dist/index/types/auth.d.ts +0 -67
- package/dist/index/types/auth.d.ts.map +0 -1
- package/dist/index/types/auth.js +0 -3
- package/dist/index/types/auth.js.map +0 -1
- package/dist/index/types/config.d.ts +0 -35
- package/dist/index/types/config.d.ts.map +0 -1
- package/dist/index/types/config.js +0 -3
- package/dist/index/types/config.js.map +0 -1
- package/dist/index/types/index.d.ts +0 -7
- package/dist/index/types/index.d.ts.map +0 -1
- package/dist/index/types/index.js +0 -3
- package/dist/index/types/index.js.map +0 -1
- package/dist/index/types/layout.d.ts +0 -27
- package/dist/index/types/layout.d.ts.map +0 -1
- package/dist/index/types/layout.js +0 -3
- package/dist/index/types/layout.js.map +0 -1
- package/dist/index/types/metrics.d.ts +0 -15
- package/dist/index/types/metrics.d.ts.map +0 -1
- package/dist/index/types/metrics.js +0 -3
- package/dist/index/types/metrics.js.map +0 -1
- package/dist/index/types/resource.d.ts +0 -34
- package/dist/index/types/resource.d.ts.map +0 -1
- package/dist/index/types/resource.js +0 -3
- package/dist/index/types/resource.js.map +0 -1
- package/dist/index/utils/auth.d.ts +0 -4
- package/dist/index/utils/auth.d.ts.map +0 -1
- package/dist/index/utils/auth.js +0 -29
- package/dist/index/utils/auth.js.map +0 -1
- package/dist/index/utils/config.d.ts +0 -4
- package/dist/index/utils/config.d.ts.map +0 -1
- package/dist/index/utils/config.js +0 -14
- package/dist/index/utils/config.js.map +0 -1
- package/dist/index/utils/http.d.ts +0 -5
- package/dist/index/utils/http.d.ts.map +0 -1
- package/dist/index/utils/http.js +0 -38
- package/dist/index/utils/http.js.map +0 -1
- package/dist/index/utils/staticDir.d.ts +0 -2
- package/dist/index/utils/staticDir.d.ts.map +0 -1
- package/dist/index/utils/staticDir.js +0 -16
- package/dist/index/utils/staticDir.js.map +0 -1
- package/dist/index/utils/uploads.d.ts +0 -6
- package/dist/index/utils/uploads.d.ts.map +0 -1
- package/dist/index/utils/uploads.js +0 -66
- package/dist/index/utils/uploads.js.map +0 -1
- package/dist/mail.d.ts +0 -22
- package/dist/mail.d.ts.map +0 -1
- package/dist/mail.js +0 -248
- package/dist/mail.js.map +0 -1
- package/dist/services/environment.d.ts +0 -8
- package/dist/services/environment.d.ts.map +0 -1
- package/dist/services/environment.js +0 -78
- package/dist/services/environment.js.map +0 -1
- package/dist/services/registry.d.ts +0 -6
- package/dist/services/registry.d.ts.map +0 -1
- package/dist/services/registry.js +0 -32
- package/dist/services/registry.js.map +0 -1
- package/dist/services/state.d.ts +0 -25
- package/dist/services/state.d.ts.map +0 -1
- package/dist/services/state.js +0 -3
- package/dist/services/state.js.map +0 -1
- package/dist/types/actions.d.ts +0 -15
- package/dist/types/actions.d.ts.map +0 -1
- package/dist/types/actions.js +0 -3
- package/dist/types/actions.js.map +0 -1
- package/dist/types/admin.d.ts +0 -83
- package/dist/types/admin.d.ts.map +0 -1
- package/dist/types/admin.js +0 -3
- package/dist/types/admin.js.map +0 -1
- package/dist/types/auth.d.ts +0 -67
- package/dist/types/auth.d.ts.map +0 -1
- package/dist/types/auth.js +0 -3
- package/dist/types/auth.js.map +0 -1
- package/dist/types/config.d.ts +0 -39
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js +0 -3
- package/dist/types/config.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -7
- package/dist/types/index.js.map +0 -1
- package/dist/types/layout.d.ts +0 -29
- package/dist/types/layout.d.ts.map +0 -1
- package/dist/types/layout.js +0 -3
- package/dist/types/layout.js.map +0 -1
- package/dist/types/mail/catalog.d.ts +0 -104
- package/dist/types/mail/catalog.d.ts.map +0 -1
- package/dist/types/mail/catalog.js +0 -3
- package/dist/types/mail/catalog.js.map +0 -1
- package/dist/types/mail/definition.d.ts +0 -68
- package/dist/types/mail/definition.d.ts.map +0 -1
- package/dist/types/mail/definition.js +0 -3
- package/dist/types/mail/definition.js.map +0 -1
- package/dist/types/mail/index.d.ts +0 -4
- package/dist/types/mail/index.d.ts.map +0 -1
- package/dist/types/mail/index.js +0 -3
- package/dist/types/mail/index.js.map +0 -1
- package/dist/types/mail/message.d.ts +0 -45
- package/dist/types/mail/message.d.ts.map +0 -1
- package/dist/types/mail/message.js +0 -3
- package/dist/types/mail/message.js.map +0 -1
- package/dist/types/metrics.d.ts +0 -46
- package/dist/types/metrics.d.ts.map +0 -1
- package/dist/types/metrics.js +0 -3
- package/dist/types/metrics.js.map +0 -1
- package/dist/types/resource.d.ts +0 -41
- package/dist/types/resource.d.ts.map +0 -1
- package/dist/types/resource.js +0 -3
- package/dist/types/resource.js.map +0 -1
- package/dist/utils/auth.d.ts +0 -4
- package/dist/utils/auth.d.ts.map +0 -1
- package/dist/utils/auth.js +0 -29
- package/dist/utils/auth.js.map +0 -1
- package/dist/utils/config.d.ts +0 -4
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -14
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/http.d.ts +0 -7
- package/dist/utils/http.d.ts.map +0 -1
- package/dist/utils/http.js +0 -61
- package/dist/utils/http.js.map +0 -1
- package/dist/utils/metricsRange.d.ts +0 -34
- package/dist/utils/metricsRange.d.ts.map +0 -1
- package/dist/utils/metricsRange.js +0 -121
- package/dist/utils/metricsRange.js.map +0 -1
- package/dist/utils/sidebar.d.ts +0 -2
- package/dist/utils/sidebar.d.ts.map +0 -1
- package/dist/utils/sidebar.js +0 -8
- package/dist/utils/sidebar.js.map +0 -1
- package/dist/utils/staticDir.d.ts +0 -2
- package/dist/utils/staticDir.d.ts.map +0 -1
- package/dist/utils/staticDir.js +0 -16
- package/dist/utils/staticDir.js.map +0 -1
- package/dist/utils/uploads.d.ts +0 -6
- package/dist/utils/uploads.d.ts.map +0 -1
- package/dist/utils/uploads.js +0 -66
- package/dist/utils/uploads.js.map +0 -1
- package/static/assets/index-DqDnCvHx.js +0 -340
- package/static/assets/index-bykX16vc.css +0 -1
package/dist/api/configs.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getConfigHandler = getConfigHandler;
|
|
4
|
-
exports.setConfigHandler = setConfigHandler;
|
|
5
|
-
const errors_1 = require("../errors");
|
|
6
|
-
const environment_1 = require("../services/environment");
|
|
7
|
-
const registry_1 = require("../services/registry");
|
|
8
|
-
const request_1 = require("./request");
|
|
9
|
-
async function getConfigHandler(state, request) {
|
|
10
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
11
|
-
const id = (0, request_1.requestParam)(request, "id");
|
|
12
|
-
if (!id) {
|
|
13
|
-
throw new errors_1.VertebrNotFoundError("Missing config id");
|
|
14
|
-
}
|
|
15
|
-
const config = (0, registry_1.findConfig)(state, id);
|
|
16
|
-
const value = await config.get(ctx);
|
|
17
|
-
return {
|
|
18
|
-
id: config.id,
|
|
19
|
-
label: config.label,
|
|
20
|
-
schema: config.schema,
|
|
21
|
-
environment: ctx.env,
|
|
22
|
-
value,
|
|
23
|
-
};
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
async function setConfigHandler(state, request) {
|
|
27
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
28
|
-
const id = (0, request_1.requestParam)(request, "id");
|
|
29
|
-
if (!id) {
|
|
30
|
-
throw new errors_1.VertebrNotFoundError("Missing config id");
|
|
31
|
-
}
|
|
32
|
-
const config = (0, registry_1.findConfig)(state, id);
|
|
33
|
-
const value = (0, request_1.requestObjectPayload)(request);
|
|
34
|
-
await config.set(value, ctx);
|
|
35
|
-
return {
|
|
36
|
-
ok: true,
|
|
37
|
-
id: config.id,
|
|
38
|
-
environment: ctx.env,
|
|
39
|
-
value: await config.get(ctx),
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=configs.js.map
|
package/dist/api/configs.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configs.js","sourceRoot":"","sources":["../../src/api/configs.ts"],"names":[],"mappings":";;AAMA,4CAgBC;AAED,4CAgBC;AAxCD,sCAAiD;AACjD,yDAAyD;AACzD,mDAAkD;AAElD,uCAA+D;AAExD,KAAK,UAAU,gBAAgB,CAAC,KAAiB,EAAE,OAAgB;IACxE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,MAAM,EAAE,GAAG,IAAA,sBAAY,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,6BAAoB,CAAC,mBAAmB,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,MAAM,GAAG,IAAA,qBAAU,EAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW,EAAE,GAAG,CAAC,GAAG;YACpB,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,gBAAgB,CAAC,KAAiB,EAAE,OAAgB;IACxE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,MAAM,EAAE,GAAG,IAAA,sBAAY,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,6BAAoB,CAAC,mBAAmB,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,MAAM,GAAG,IAAA,qBAAU,EAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,IAAA,8BAAoB,EAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO;YACL,EAAE,EAAE,IAAI;YACR,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,WAAW,EAAE,GAAG,CAAC,GAAG;YACpB,KAAK,EAAE,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;SAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/api/emails.d.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { AdminState } from "../services/state";
|
|
2
|
-
import type { MailCampaignAudience, MailLibraryTemplate } from "../types";
|
|
3
|
-
export declare function emailsBoardHandler(state: AdminState, request: unknown): Promise<{
|
|
4
|
-
ok: boolean;
|
|
5
|
-
id: string;
|
|
6
|
-
label: string;
|
|
7
|
-
group: string;
|
|
8
|
-
canSchedule: boolean;
|
|
9
|
-
canHistory: boolean;
|
|
10
|
-
canLibrary: boolean;
|
|
11
|
-
templates: {
|
|
12
|
-
id: string;
|
|
13
|
-
label: string;
|
|
14
|
-
input: Record<string, import("../schema").FieldSchema>;
|
|
15
|
-
}[];
|
|
16
|
-
audiences: {
|
|
17
|
-
id: string;
|
|
18
|
-
label: string;
|
|
19
|
-
templates: string[];
|
|
20
|
-
}[];
|
|
21
|
-
campaigns: import("../types").MailCampaign[];
|
|
22
|
-
history: import("../types").MailHistoryEntry[];
|
|
23
|
-
library: MailLibraryTemplate[];
|
|
24
|
-
products: import("../types").MailProductOption[];
|
|
25
|
-
discounts: import("../types").MailDiscountOption[];
|
|
26
|
-
environment: string;
|
|
27
|
-
}>;
|
|
28
|
-
export declare function emailsPreviewHandler(state: AdminState, request: unknown): Promise<{
|
|
29
|
-
sampleRowId: string | undefined;
|
|
30
|
-
to: string | string[];
|
|
31
|
-
subject: string;
|
|
32
|
-
html: string | undefined;
|
|
33
|
-
text: string | undefined;
|
|
34
|
-
ok: boolean;
|
|
35
|
-
}>;
|
|
36
|
-
export declare function emailsSendHandler(state: AdminState, request: unknown): Promise<{
|
|
37
|
-
ok: boolean;
|
|
38
|
-
resourceId: string;
|
|
39
|
-
templateId: string;
|
|
40
|
-
sent: number;
|
|
41
|
-
failed: number;
|
|
42
|
-
results: {
|
|
43
|
-
rowId: string;
|
|
44
|
-
ok: boolean;
|
|
45
|
-
id?: string;
|
|
46
|
-
error?: string;
|
|
47
|
-
subject?: string;
|
|
48
|
-
reference?: string;
|
|
49
|
-
}[];
|
|
50
|
-
environment: string;
|
|
51
|
-
}>;
|
|
52
|
-
export declare function emailsScheduleHandler(state: AdminState, request: unknown): Promise<{
|
|
53
|
-
ok: boolean;
|
|
54
|
-
campaign: {
|
|
55
|
-
resourceLabel: string;
|
|
56
|
-
templateLabel: string | undefined;
|
|
57
|
-
recipientCount: number;
|
|
58
|
-
id: string;
|
|
59
|
-
resourceId: string;
|
|
60
|
-
templateId: string;
|
|
61
|
-
audience: MailCampaignAudience;
|
|
62
|
-
sendAt: string;
|
|
63
|
-
status: import("../types").MailCampaignStatus;
|
|
64
|
-
createdAt?: string;
|
|
65
|
-
subject?: string;
|
|
66
|
-
error?: string;
|
|
67
|
-
};
|
|
68
|
-
environment: string;
|
|
69
|
-
}>;
|
|
70
|
-
export declare function emailsCancelHandler(state: AdminState, request: unknown): Promise<{
|
|
71
|
-
ok: boolean;
|
|
72
|
-
id: string;
|
|
73
|
-
environment: string;
|
|
74
|
-
}>;
|
|
75
|
-
export declare function emailsLibrarySaveHandler(state: AdminState, request: unknown): Promise<{
|
|
76
|
-
ok: boolean;
|
|
77
|
-
template: MailLibraryTemplate;
|
|
78
|
-
environment: string;
|
|
79
|
-
}>;
|
|
80
|
-
export declare function emailsLibraryDeleteHandler(state: AdminState, request: unknown): Promise<{
|
|
81
|
-
ok: boolean;
|
|
82
|
-
id: string;
|
|
83
|
-
environment: string;
|
|
84
|
-
}>;
|
|
85
|
-
//# sourceMappingURL=emails.d.ts.map
|
package/dist/api/emails.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"emails.d.ts","sourceRoot":"","sources":["../../src/api/emails.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EACV,oBAAoB,EAIpB,mBAAmB,EAGpB,MAAM,UAAU,CAAC;AAmJlB,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;;;;;;;;;;;YANpE,MAAM;eACH,MAAM;mBACF,MAAM,EAAE;;;;;;;;GAwCtB;AAkED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;GA6CjB;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;;;;eAgC9D,MAAM;YACT,OAAO;aACN,MAAM;gBACH,MAAM;kBACJ,MAAM;oBACJ,MAAM;;;GAyFvB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;GAwGjB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;GAYjB;AA2DD,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;GAYjB;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;GAYjB"}
|
package/dist/api/emails.js
DELETED
|
@@ -1,520 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.emailsBoardHandler = emailsBoardHandler;
|
|
4
|
-
exports.emailsPreviewHandler = emailsPreviewHandler;
|
|
5
|
-
exports.emailsSendHandler = emailsSendHandler;
|
|
6
|
-
exports.emailsScheduleHandler = emailsScheduleHandler;
|
|
7
|
-
exports.emailsCancelHandler = emailsCancelHandler;
|
|
8
|
-
exports.emailsLibrarySaveHandler = emailsLibrarySaveHandler;
|
|
9
|
-
exports.emailsLibraryDeleteHandler = emailsLibraryDeleteHandler;
|
|
10
|
-
const errors_1 = require("../errors");
|
|
11
|
-
const mail_1 = require("../mail");
|
|
12
|
-
const environment_1 = require("../services/environment");
|
|
13
|
-
const registry_1 = require("../services/registry");
|
|
14
|
-
const request_1 = require("./request");
|
|
15
|
-
function requireMail(state) {
|
|
16
|
-
if (!state.mailDef) {
|
|
17
|
-
throw new errors_1.VertebrNotFoundError("Mail is not configured");
|
|
18
|
-
}
|
|
19
|
-
return state.mailDef;
|
|
20
|
-
}
|
|
21
|
-
function rowKey(row) {
|
|
22
|
-
return String(row.id ?? row.uid ?? row.slug ?? row.email ?? "").trim();
|
|
23
|
-
}
|
|
24
|
-
async function listRows(resource, ctx) {
|
|
25
|
-
const items = (await (resource.list?.(ctx) ?? []));
|
|
26
|
-
return items;
|
|
27
|
-
}
|
|
28
|
-
async function loadRow(resource, rowId, ctx) {
|
|
29
|
-
if (resource.get) {
|
|
30
|
-
return (await resource.get(rowId, ctx));
|
|
31
|
-
}
|
|
32
|
-
const needle = rowId.trim().toLowerCase();
|
|
33
|
-
return (await listRows(resource, ctx)).find((item) => {
|
|
34
|
-
const keys = [item.id, item.uid, item.slug, item.email]
|
|
35
|
-
.map((value) => String(value ?? "").trim().toLowerCase())
|
|
36
|
-
.filter(Boolean);
|
|
37
|
-
return keys.includes(needle);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
function parseAudience(raw) {
|
|
41
|
-
if (!raw || typeof raw !== "object") {
|
|
42
|
-
throw new errors_1.VertebrBadRequestError("Missing audience.");
|
|
43
|
-
}
|
|
44
|
-
const audience = raw;
|
|
45
|
-
const mode = String(audience.mode ?? "").trim();
|
|
46
|
-
if (mode === "all")
|
|
47
|
-
return { mode: "all" };
|
|
48
|
-
if (mode === "ids") {
|
|
49
|
-
const rowIds = Array.isArray(audience.rowIds)
|
|
50
|
-
? audience.rowIds.map((id) => String(id ?? "").trim()).filter(Boolean)
|
|
51
|
-
: [];
|
|
52
|
-
if (rowIds.length === 0) {
|
|
53
|
-
throw new errors_1.VertebrBadRequestError("Select at least one recipient.");
|
|
54
|
-
}
|
|
55
|
-
return { mode: "ids", rowIds };
|
|
56
|
-
}
|
|
57
|
-
if (mode === "emails") {
|
|
58
|
-
const emails = Array.isArray(audience.emails)
|
|
59
|
-
? audience.emails
|
|
60
|
-
.map((email) => String(email ?? "").trim().toLowerCase())
|
|
61
|
-
.filter(Boolean)
|
|
62
|
-
: String(audience.emailsText ?? "")
|
|
63
|
-
.split(/[\s,;]+/)
|
|
64
|
-
.map((email) => email.trim().toLowerCase())
|
|
65
|
-
.filter(Boolean);
|
|
66
|
-
if (emails.length === 0) {
|
|
67
|
-
throw new errors_1.VertebrBadRequestError("Enter at least one email.");
|
|
68
|
-
}
|
|
69
|
-
return { mode: "emails", emails };
|
|
70
|
-
}
|
|
71
|
-
throw new errors_1.VertebrBadRequestError("Invalid audience mode.");
|
|
72
|
-
}
|
|
73
|
-
async function resolveAudienceRows(resource, binding, mail, audience, ctx) {
|
|
74
|
-
const toField = binding.toField ?? mail.toField ?? "email";
|
|
75
|
-
const all = await listRows(resource, ctx);
|
|
76
|
-
let selected = [];
|
|
77
|
-
if (audience.mode === "all") {
|
|
78
|
-
selected = all;
|
|
79
|
-
}
|
|
80
|
-
else if (audience.mode === "ids") {
|
|
81
|
-
const want = new Set(audience.rowIds.map((id) => id.toLowerCase()));
|
|
82
|
-
selected = all.filter((row) => {
|
|
83
|
-
const keys = [row.id, row.uid, row.slug, row.email]
|
|
84
|
-
.map((value) => String(value ?? "").trim().toLowerCase())
|
|
85
|
-
.filter(Boolean);
|
|
86
|
-
return keys.some((key) => want.has(key));
|
|
87
|
-
});
|
|
88
|
-
if (selected.length === 0) {
|
|
89
|
-
for (const id of audience.rowIds) {
|
|
90
|
-
const row = await loadRow(resource, id, ctx);
|
|
91
|
-
if (row)
|
|
92
|
-
selected.push(row);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
const want = new Set(audience.emails.map((email) => email.toLowerCase()));
|
|
98
|
-
selected = all.filter((row) => want.has(String(row[toField] ?? "").trim().toLowerCase()));
|
|
99
|
-
}
|
|
100
|
-
return selected.filter((row) => {
|
|
101
|
-
const value = row[toField];
|
|
102
|
-
if (Array.isArray(value)) {
|
|
103
|
-
return value.some((item) => String(item ?? "").includes("@"));
|
|
104
|
-
}
|
|
105
|
-
return String(value ?? "").includes("@");
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
function mailAudiences(state) {
|
|
109
|
-
const mail = requireMail(state);
|
|
110
|
-
return state.resources
|
|
111
|
-
.map((resource) => {
|
|
112
|
-
const binding = (0, mail_1.normalizeMailConfig)(resource.mail);
|
|
113
|
-
if (!binding)
|
|
114
|
-
return null;
|
|
115
|
-
const templates = binding.templates.filter((id) => {
|
|
116
|
-
const template = mail.templates[id];
|
|
117
|
-
return template != null && template.bulk !== false;
|
|
118
|
-
});
|
|
119
|
-
if (templates.length === 0)
|
|
120
|
-
return null;
|
|
121
|
-
return {
|
|
122
|
-
id: resource.id,
|
|
123
|
-
label: resource.label,
|
|
124
|
-
templates,
|
|
125
|
-
};
|
|
126
|
-
})
|
|
127
|
-
.filter(Boolean);
|
|
128
|
-
}
|
|
129
|
-
async function emailsBoardHandler(state, request) {
|
|
130
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
131
|
-
const mail = requireMail(state);
|
|
132
|
-
const audiences = mailAudiences(state);
|
|
133
|
-
const templates = Object.entries(mail.templates)
|
|
134
|
-
.filter(([, template]) => template.bulk !== false)
|
|
135
|
-
.map(([id, template]) => ({
|
|
136
|
-
id,
|
|
137
|
-
label: template.label,
|
|
138
|
-
input: (0, mail_1.normalizeActionInput)(template.input),
|
|
139
|
-
}));
|
|
140
|
-
const [campaigns, history, library, products, discounts] = await Promise.all([
|
|
141
|
-
mail.campaigns ? mail.campaigns.list(ctx) : Promise.resolve([]),
|
|
142
|
-
mail.history ? mail.history.list(ctx) : Promise.resolve([]),
|
|
143
|
-
mail.library ? mail.library.list(ctx) : Promise.resolve([]),
|
|
144
|
-
mail.products ? Promise.resolve(mail.products(ctx)) : Promise.resolve([]),
|
|
145
|
-
mail.discounts ? Promise.resolve(mail.discounts(ctx)) : Promise.resolve([]),
|
|
146
|
-
]);
|
|
147
|
-
return {
|
|
148
|
-
ok: true,
|
|
149
|
-
id: "emails",
|
|
150
|
-
label: mail.label ?? "Emails",
|
|
151
|
-
group: mail.group ?? "Growth",
|
|
152
|
-
canSchedule: Boolean(mail.campaigns?.schedule),
|
|
153
|
-
canHistory: Boolean(mail.history),
|
|
154
|
-
canLibrary: Boolean(mail.library),
|
|
155
|
-
templates,
|
|
156
|
-
audiences,
|
|
157
|
-
campaigns,
|
|
158
|
-
history,
|
|
159
|
-
library,
|
|
160
|
-
products,
|
|
161
|
-
discounts,
|
|
162
|
-
environment: ctx.env,
|
|
163
|
-
};
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
function historyComposeMeta(input) {
|
|
167
|
-
const productIds = Array.isArray(input?.productIds)
|
|
168
|
-
? input.productIds.map((id) => String(id)).filter(Boolean)
|
|
169
|
-
: undefined;
|
|
170
|
-
const preset = String(input?.preset ?? "").trim() || undefined;
|
|
171
|
-
const discountCode = String(input?.discountCode ?? "").trim() || undefined;
|
|
172
|
-
const discountOffer = String(input?.discountOffer ?? "").trim() || undefined;
|
|
173
|
-
const reference = String(input?.confirmationNumber ??
|
|
174
|
-
input?.reference ??
|
|
175
|
-
input?.orderId ??
|
|
176
|
-
"").trim() || undefined;
|
|
177
|
-
return { productIds, preset, discountCode, discountOffer, reference };
|
|
178
|
-
}
|
|
179
|
-
function referenceFromSubject(subject) {
|
|
180
|
-
if (!subject)
|
|
181
|
-
return undefined;
|
|
182
|
-
const match = subject.match(/(?:—|-|–)\s*((?:MM|ORD|ORDER)[-_][A-Z0-9-]+|[A-Z]{2,}[-_][A-Z0-9-]{3,})\s*$/i);
|
|
183
|
-
return match?.[1]?.trim() || undefined;
|
|
184
|
-
}
|
|
185
|
-
function sampleRecipientEmails(rows, toField, limit = 8) {
|
|
186
|
-
const out = [];
|
|
187
|
-
const seen = new Set();
|
|
188
|
-
for (const row of rows) {
|
|
189
|
-
const raw = row[toField];
|
|
190
|
-
const values = Array.isArray(raw) ? raw : [raw];
|
|
191
|
-
for (const value of values) {
|
|
192
|
-
const email = String(value ?? "")
|
|
193
|
-
.trim()
|
|
194
|
-
.toLowerCase();
|
|
195
|
-
if (!email.includes("@") || seen.has(email))
|
|
196
|
-
continue;
|
|
197
|
-
seen.add(email);
|
|
198
|
-
out.push(email);
|
|
199
|
-
if (out.length >= limit)
|
|
200
|
-
return out;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return out;
|
|
204
|
-
}
|
|
205
|
-
async function recordHistory(mail, entry, ctx) {
|
|
206
|
-
if (!mail.history?.record)
|
|
207
|
-
return;
|
|
208
|
-
const compact = Object.fromEntries(Object.entries(entry).filter(([, value]) => value !== undefined));
|
|
209
|
-
try {
|
|
210
|
-
await mail.history.record(compact, ctx);
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
/* history must not block send */
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
async function emailsPreviewHandler(state, request) {
|
|
217
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
218
|
-
const mail = requireMail(state);
|
|
219
|
-
const body = (0, request_1.requestObjectPayload)(request);
|
|
220
|
-
const resourceId = String(body.resourceId ?? "").trim();
|
|
221
|
-
const templateId = String(body.templateId ?? "").trim();
|
|
222
|
-
const rowId = String(body.rowId ?? "").trim();
|
|
223
|
-
const input = body.input && typeof body.input === "object"
|
|
224
|
-
? body.input
|
|
225
|
-
: undefined;
|
|
226
|
-
if (!resourceId || !templateId) {
|
|
227
|
-
throw new errors_1.VertebrBadRequestError("resourceId and templateId are required.");
|
|
228
|
-
}
|
|
229
|
-
const resource = (0, registry_1.findResource)(state, resourceId);
|
|
230
|
-
const binding = (0, mail_1.normalizeMailConfig)(resource.mail);
|
|
231
|
-
if (!binding || !binding.templates.includes(templateId)) {
|
|
232
|
-
throw new errors_1.VertebrBadRequestError(`Resource "${resourceId}" does not allow template "${templateId}".`);
|
|
233
|
-
}
|
|
234
|
-
const rows = await listRows(resource, ctx);
|
|
235
|
-
const row = rowId
|
|
236
|
-
? await loadRow(resource, rowId, ctx)
|
|
237
|
-
: rows[0];
|
|
238
|
-
if (!row) {
|
|
239
|
-
throw new errors_1.VertebrBadRequestError("No sample recipient in this audience yet.");
|
|
240
|
-
}
|
|
241
|
-
const message = await (0, mail_1.composeMailMessage)(mail, binding, templateId, row, input, ctx);
|
|
242
|
-
return {
|
|
243
|
-
ok: true,
|
|
244
|
-
...(0, mail_1.publicMailPreview)(message),
|
|
245
|
-
sampleRowId: rowKey(row) || undefined,
|
|
246
|
-
};
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
async function emailsSendHandler(state, request) {
|
|
250
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
251
|
-
const mail = requireMail(state);
|
|
252
|
-
const body = (0, request_1.requestObjectPayload)(request);
|
|
253
|
-
const resourceId = String(body.resourceId ?? "").trim();
|
|
254
|
-
const templateId = String(body.templateId ?? "").trim();
|
|
255
|
-
const input = body.input && typeof body.input === "object"
|
|
256
|
-
? body.input
|
|
257
|
-
: undefined;
|
|
258
|
-
if (!resourceId || !templateId) {
|
|
259
|
-
throw new errors_1.VertebrBadRequestError("resourceId and templateId are required.");
|
|
260
|
-
}
|
|
261
|
-
const resource = (0, registry_1.findResource)(state, resourceId);
|
|
262
|
-
const binding = (0, mail_1.normalizeMailConfig)(resource.mail);
|
|
263
|
-
if (!binding || !binding.templates.includes(templateId)) {
|
|
264
|
-
throw new errors_1.VertebrBadRequestError(`Resource "${resourceId}" does not allow template "${templateId}".`);
|
|
265
|
-
}
|
|
266
|
-
const audience = parseAudience(body.audience);
|
|
267
|
-
const rows = await resolveAudienceRows(resource, binding, mail, audience, ctx);
|
|
268
|
-
if (rows.length === 0) {
|
|
269
|
-
throw new errors_1.VertebrBadRequestError("No recipients matched.");
|
|
270
|
-
}
|
|
271
|
-
const results = [];
|
|
272
|
-
for (const row of rows) {
|
|
273
|
-
const id = rowKey(row) || String(results.length);
|
|
274
|
-
try {
|
|
275
|
-
const sent = await (0, mail_1.runMailTemplate)(mail, binding, templateId, row, input, ctx);
|
|
276
|
-
results.push({
|
|
277
|
-
rowId: id,
|
|
278
|
-
ok: true,
|
|
279
|
-
id: sent.id,
|
|
280
|
-
subject: sent.message.subject,
|
|
281
|
-
reference: sent.reference,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
catch (error) {
|
|
285
|
-
results.push({
|
|
286
|
-
rowId: id,
|
|
287
|
-
ok: false,
|
|
288
|
-
error: error instanceof Error ? error.message : "Send failed",
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
const sent = results.filter((item) => item.ok).length;
|
|
293
|
-
const failed = results.length - sent;
|
|
294
|
-
const firstOk = results.find((item) => item.ok);
|
|
295
|
-
let subject = firstOk?.subject;
|
|
296
|
-
if (!subject) {
|
|
297
|
-
try {
|
|
298
|
-
if (rows[0]) {
|
|
299
|
-
const preview = await (0, mail_1.composeMailMessage)(mail, binding, templateId, rows[0], input, ctx);
|
|
300
|
-
subject = preview.subject;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
catch {
|
|
304
|
-
/* optional */
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
const composeMeta = historyComposeMeta(input);
|
|
308
|
-
const toField = binding.toField ?? mail.toField ?? "email";
|
|
309
|
-
const recipients = sampleRecipientEmails(rows, toField);
|
|
310
|
-
await recordHistory(mail, {
|
|
311
|
-
at: new Date().toISOString(),
|
|
312
|
-
resourceId,
|
|
313
|
-
resourceLabel: resource.label,
|
|
314
|
-
templateId,
|
|
315
|
-
templateLabel: mail.templates[templateId]?.label,
|
|
316
|
-
subject,
|
|
317
|
-
recipientCount: rows.length,
|
|
318
|
-
sent,
|
|
319
|
-
failed,
|
|
320
|
-
status: failed === 0 ? "sent" : sent === 0 ? "failed" : "partial",
|
|
321
|
-
source: "board",
|
|
322
|
-
recipients: recipients.length ? recipients : undefined,
|
|
323
|
-
...composeMeta,
|
|
324
|
-
reference: firstOk?.reference &&
|
|
325
|
-
firstOk.reference !== "MM-PENDING"
|
|
326
|
-
? firstOk.reference
|
|
327
|
-
: composeMeta.reference &&
|
|
328
|
-
composeMeta.reference !== "MM-PENDING"
|
|
329
|
-
? composeMeta.reference
|
|
330
|
-
: referenceFromSubject(subject),
|
|
331
|
-
}, ctx);
|
|
332
|
-
return {
|
|
333
|
-
ok: true,
|
|
334
|
-
resourceId,
|
|
335
|
-
templateId,
|
|
336
|
-
sent,
|
|
337
|
-
failed,
|
|
338
|
-
results,
|
|
339
|
-
environment: ctx.env,
|
|
340
|
-
};
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
async function emailsScheduleHandler(state, request) {
|
|
344
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
345
|
-
const mail = requireMail(state);
|
|
346
|
-
if (!mail.campaigns?.schedule) {
|
|
347
|
-
throw new errors_1.VertebrBadRequestError("Scheduling is not configured.");
|
|
348
|
-
}
|
|
349
|
-
const body = (0, request_1.requestObjectPayload)(request);
|
|
350
|
-
const resourceId = String(body.resourceId ?? "").trim();
|
|
351
|
-
const templateId = String(body.templateId ?? "").trim();
|
|
352
|
-
const sendAt = String(body.sendAt ?? "").trim();
|
|
353
|
-
const input = body.input && typeof body.input === "object"
|
|
354
|
-
? body.input
|
|
355
|
-
: undefined;
|
|
356
|
-
if (!resourceId || !templateId || !sendAt) {
|
|
357
|
-
throw new errors_1.VertebrBadRequestError("resourceId, templateId, and sendAt are required.");
|
|
358
|
-
}
|
|
359
|
-
const when = Date.parse(sendAt);
|
|
360
|
-
if (!Number.isFinite(when)) {
|
|
361
|
-
throw new errors_1.VertebrBadRequestError("sendAt must be a valid date.");
|
|
362
|
-
}
|
|
363
|
-
if (when < Date.now() - 30_000) {
|
|
364
|
-
throw new errors_1.VertebrBadRequestError("sendAt must be in the future.");
|
|
365
|
-
}
|
|
366
|
-
const resource = (0, registry_1.findResource)(state, resourceId);
|
|
367
|
-
const binding = (0, mail_1.normalizeMailConfig)(resource.mail);
|
|
368
|
-
if (!binding || !binding.templates.includes(templateId)) {
|
|
369
|
-
throw new errors_1.VertebrBadRequestError(`Resource "${resourceId}" does not allow template "${templateId}".`);
|
|
370
|
-
}
|
|
371
|
-
const audience = parseAudience(body.audience);
|
|
372
|
-
const rows = await resolveAudienceRows(resource, binding, mail, audience, ctx);
|
|
373
|
-
if (rows.length === 0) {
|
|
374
|
-
throw new errors_1.VertebrBadRequestError("No recipients matched.");
|
|
375
|
-
}
|
|
376
|
-
let subject;
|
|
377
|
-
try {
|
|
378
|
-
const preview = await (0, mail_1.composeMailMessage)(mail, binding, templateId, rows[0], input, ctx);
|
|
379
|
-
subject = preview.subject;
|
|
380
|
-
}
|
|
381
|
-
catch {
|
|
382
|
-
/* optional snapshot */
|
|
383
|
-
}
|
|
384
|
-
const payload = {
|
|
385
|
-
resourceId,
|
|
386
|
-
templateId,
|
|
387
|
-
input,
|
|
388
|
-
audience,
|
|
389
|
-
sendAt: new Date(when).toISOString(),
|
|
390
|
-
subject,
|
|
391
|
-
};
|
|
392
|
-
const campaign = await mail.campaigns.schedule(payload, ctx);
|
|
393
|
-
const composeMeta = historyComposeMeta(input);
|
|
394
|
-
const toField = binding.toField ?? mail.toField ?? "email";
|
|
395
|
-
const recipients = sampleRecipientEmails(rows, toField);
|
|
396
|
-
await recordHistory(mail, {
|
|
397
|
-
at: new Date().toISOString(),
|
|
398
|
-
resourceId,
|
|
399
|
-
resourceLabel: resource.label,
|
|
400
|
-
templateId,
|
|
401
|
-
templateLabel: mail.templates[templateId]?.label,
|
|
402
|
-
subject,
|
|
403
|
-
recipientCount: campaign.recipientCount ?? rows.length,
|
|
404
|
-
sent: 0,
|
|
405
|
-
status: "scheduled",
|
|
406
|
-
source: "campaign",
|
|
407
|
-
campaignId: campaign.id,
|
|
408
|
-
recipients: recipients.length ? recipients : undefined,
|
|
409
|
-
...composeMeta,
|
|
410
|
-
reference: composeMeta.reference ?? referenceFromSubject(subject),
|
|
411
|
-
}, ctx);
|
|
412
|
-
return {
|
|
413
|
-
ok: true,
|
|
414
|
-
campaign: {
|
|
415
|
-
...campaign,
|
|
416
|
-
resourceLabel: campaign.resourceLabel ?? resource.label,
|
|
417
|
-
templateLabel: campaign.templateLabel ?? mail.templates[templateId]?.label,
|
|
418
|
-
recipientCount: campaign.recipientCount ?? rows.length,
|
|
419
|
-
},
|
|
420
|
-
environment: ctx.env,
|
|
421
|
-
};
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
async function emailsCancelHandler(state, request) {
|
|
425
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
426
|
-
const mail = requireMail(state);
|
|
427
|
-
if (!mail.campaigns?.cancel) {
|
|
428
|
-
throw new errors_1.VertebrBadRequestError("Cancel is not configured.");
|
|
429
|
-
}
|
|
430
|
-
const id = (0, request_1.requestParam)(request, "id");
|
|
431
|
-
if (!id)
|
|
432
|
-
throw new errors_1.VertebrNotFoundError("Missing campaign id");
|
|
433
|
-
await mail.campaigns.cancel(id, ctx);
|
|
434
|
-
return { ok: true, id, environment: ctx.env };
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
function parseLibraryTemplate(raw) {
|
|
438
|
-
const id = String(raw.id ?? "").trim();
|
|
439
|
-
const label = String(raw.label ?? "").trim();
|
|
440
|
-
const subject = String(raw.subject ?? "").trim();
|
|
441
|
-
const body = String(raw.body ?? "").trim();
|
|
442
|
-
if (!label)
|
|
443
|
-
throw new errors_1.VertebrBadRequestError("Template label is required.");
|
|
444
|
-
if (!subject)
|
|
445
|
-
throw new errors_1.VertebrBadRequestError("Template subject is required.");
|
|
446
|
-
if (!body)
|
|
447
|
-
throw new errors_1.VertebrBadRequestError("Template body is required.");
|
|
448
|
-
const productIds = Array.isArray(raw.productIds)
|
|
449
|
-
? raw.productIds.map((item) => String(item ?? "").trim()).filter(Boolean)
|
|
450
|
-
: undefined;
|
|
451
|
-
const kind = raw.kind === "promo" ||
|
|
452
|
-
raw.kind === "account" ||
|
|
453
|
-
raw.kind === "discount" ||
|
|
454
|
-
raw.kind === "order" ?
|
|
455
|
-
raw.kind :
|
|
456
|
-
undefined;
|
|
457
|
-
const discountCode = raw.discountCode
|
|
458
|
-
? String(raw.discountCode).trim()
|
|
459
|
-
: undefined;
|
|
460
|
-
const discountOffer = raw.discountOffer
|
|
461
|
-
? String(raw.discountOffer).trim()
|
|
462
|
-
: undefined;
|
|
463
|
-
const discountExpires = raw.discountExpires
|
|
464
|
-
? String(raw.discountExpires).trim()
|
|
465
|
-
: undefined;
|
|
466
|
-
const discountId = raw.discountId
|
|
467
|
-
? String(raw.discountId).trim()
|
|
468
|
-
: undefined;
|
|
469
|
-
const optionalString = (value) => {
|
|
470
|
-
const text = typeof value === "string" ? value.trim() : "";
|
|
471
|
-
return text || undefined;
|
|
472
|
-
};
|
|
473
|
-
return {
|
|
474
|
-
id: id || `tpl_${Date.now().toString(36)}`,
|
|
475
|
-
label,
|
|
476
|
-
fromPreset: raw.fromPreset ? String(raw.fromPreset) : undefined,
|
|
477
|
-
subject,
|
|
478
|
-
body,
|
|
479
|
-
productIds,
|
|
480
|
-
discountId: discountId || undefined,
|
|
481
|
-
discountCode: discountCode || undefined,
|
|
482
|
-
discountOffer: discountOffer || undefined,
|
|
483
|
-
discountExpires: discountExpires || undefined,
|
|
484
|
-
kind,
|
|
485
|
-
eyebrow: optionalString(raw.eyebrow),
|
|
486
|
-
headline: optionalString(raw.headline),
|
|
487
|
-
confirmationLabel: optionalString(raw.confirmationLabel),
|
|
488
|
-
shippingNote: optionalString(raw.shippingNote),
|
|
489
|
-
footer: optionalString(raw.footer),
|
|
490
|
-
signOff: optionalString(raw.signOff),
|
|
491
|
-
createdAt: raw.createdAt ? String(raw.createdAt) : undefined,
|
|
492
|
-
updatedAt: raw.updatedAt ? String(raw.updatedAt) : undefined,
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
async function emailsLibrarySaveHandler(state, request) {
|
|
496
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
497
|
-
const mail = requireMail(state);
|
|
498
|
-
if (!mail.library?.save) {
|
|
499
|
-
throw new errors_1.VertebrBadRequestError("Template library is not configured.");
|
|
500
|
-
}
|
|
501
|
-
const body = (0, request_1.requestObjectPayload)(request);
|
|
502
|
-
const template = parseLibraryTemplate(body);
|
|
503
|
-
const saved = await mail.library.save(template, ctx);
|
|
504
|
-
return { ok: true, template: saved, environment: ctx.env };
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
async function emailsLibraryDeleteHandler(state, request) {
|
|
508
|
-
return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
|
|
509
|
-
const mail = requireMail(state);
|
|
510
|
-
if (!mail.library?.remove) {
|
|
511
|
-
throw new errors_1.VertebrBadRequestError("Template delete is not configured.");
|
|
512
|
-
}
|
|
513
|
-
const id = (0, request_1.requestParam)(request, "id");
|
|
514
|
-
if (!id)
|
|
515
|
-
throw new errors_1.VertebrNotFoundError("Missing template id");
|
|
516
|
-
await mail.library.remove(id, ctx);
|
|
517
|
-
return { ok: true, id, environment: ctx.env };
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
//# sourceMappingURL=emails.js.map
|