@dyrected/core 2.5.51 → 2.5.53
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/__tests__/admin-auth.test.d.ts +2 -0
- package/dist/__tests__/admin-auth.test.d.ts.map +1 -0
- package/dist/__tests__/admin-auth.test.js +440 -0
- package/dist/__tests__/admin-auth.test.js.map +1 -0
- package/dist/__tests__/config.test.js +57 -0
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/email.service.test.d.ts +2 -0
- package/dist/__tests__/email.service.test.d.ts.map +1 -0
- package/dist/__tests__/email.service.test.js +46 -0
- package/dist/__tests__/email.service.test.js.map +1 -0
- package/dist/__tests__/fixtures/editorial-workflow.d.ts +9 -0
- package/dist/__tests__/fixtures/editorial-workflow.d.ts.map +1 -0
- package/dist/__tests__/fixtures/editorial-workflow.js +12 -0
- package/dist/__tests__/fixtures/editorial-workflow.js.map +1 -0
- package/dist/__tests__/mocks.d.ts +6 -0
- package/dist/__tests__/mocks.d.ts.map +1 -1
- package/dist/__tests__/mocks.js +8 -0
- package/dist/__tests__/mocks.js.map +1 -1
- package/dist/__tests__/openapi.test.d.ts +2 -0
- package/dist/__tests__/openapi.test.d.ts.map +1 -0
- package/dist/__tests__/openapi.test.js +95 -0
- package/dist/__tests__/openapi.test.js.map +1 -0
- package/dist/__tests__/parse-sort.test.d.ts +2 -0
- package/dist/__tests__/parse-sort.test.d.ts.map +1 -0
- package/dist/__tests__/parse-sort.test.js +24 -0
- package/dist/__tests__/parse-sort.test.js.map +1 -0
- package/dist/__tests__/preferences.test.d.ts +2 -0
- package/dist/__tests__/preferences.test.d.ts.map +1 -0
- package/dist/__tests__/preferences.test.js +168 -0
- package/dist/__tests__/preferences.test.js.map +1 -0
- package/dist/__tests__/router.test.js +4 -0
- package/dist/__tests__/router.test.js.map +1 -1
- package/dist/__tests__/where.test.js +9 -1
- package/dist/__tests__/where.test.js.map +1 -1
- package/dist/__tests__/workflow.test.d.ts +2 -0
- package/dist/__tests__/workflow.test.d.ts.map +1 -0
- package/dist/__tests__/workflow.test.js +497 -0
- package/dist/__tests__/workflow.test.js.map +1 -0
- package/dist/app-config-DLK6bCaP.d.cts +1390 -0
- package/dist/app-config-DLK6bCaP.d.ts +1390 -0
- package/dist/app-config-DqCipvSI.d.cts +1411 -0
- package/dist/app-config-DqCipvSI.d.ts +1411 -0
- package/dist/app-config-oOarB6Fw.d.cts +1411 -0
- package/dist/app-config-oOarB6Fw.d.ts +1411 -0
- package/dist/auth/token.d.ts +2 -0
- package/dist/auth/token.d.ts.map +1 -1
- package/dist/auth/token.js.map +1 -1
- package/dist/controllers/admin-auth.controller.d.ts +68 -0
- package/dist/controllers/admin-auth.controller.d.ts.map +1 -0
- package/dist/controllers/admin-auth.controller.js +414 -0
- package/dist/controllers/admin-auth.controller.js.map +1 -0
- package/dist/controllers/collection.controller.d.ts +69 -0
- package/dist/controllers/collection.controller.d.ts.map +1 -1
- package/dist/controllers/collection.controller.js +232 -7
- package/dist/controllers/collection.controller.js.map +1 -1
- package/dist/controllers/global.controller.js +19 -3
- package/dist/controllers/global.controller.js.map +1 -1
- package/dist/controllers/media.controller.d.ts +2 -0
- package/dist/controllers/media.controller.d.ts.map +1 -1
- package/dist/controllers/media.controller.js +13 -6
- package/dist/controllers/media.controller.js.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +168 -6
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +54 -8
- package/dist/server.d.cts +7 -1
- package/dist/server.d.ts +7 -1
- package/dist/server.js +54 -8
- package/dist/services/email-template.d.ts +46 -0
- package/dist/services/email-template.d.ts.map +1 -0
- package/dist/services/email-template.js +88 -0
- package/dist/services/email-template.js.map +1 -0
- package/dist/services/email.service.d.ts.map +1 -1
- package/dist/services/email.service.js +25 -148
- package/dist/services/email.service.js.map +1 -1
- package/dist/services/population.service.d.ts.map +1 -1
- package/dist/services/population.service.js +27 -1
- package/dist/services/population.service.js.map +1 -1
- package/dist/types/access.d.ts +38 -0
- package/dist/types/access.d.ts.map +1 -0
- package/dist/types/access.js +2 -0
- package/dist/types/access.js.map +1 -0
- package/dist/types/adapters.d.ts +146 -0
- package/dist/types/adapters.d.ts.map +1 -0
- package/dist/types/adapters.js +2 -0
- package/dist/types/adapters.js.map +1 -0
- package/dist/types/admin-auth.d.ts +132 -0
- package/dist/types/admin-auth.d.ts.map +1 -0
- package/dist/types/admin-auth.js +2 -0
- package/dist/types/admin-auth.js.map +1 -0
- package/dist/types/admin.d.ts +65 -0
- package/dist/types/admin.d.ts.map +1 -0
- package/dist/types/admin.js +2 -0
- package/dist/types/admin.js.map +1 -0
- package/dist/types/app-config.d.ts +143 -0
- package/dist/types/app-config.d.ts.map +1 -0
- package/dist/types/app-config.js +2 -0
- package/dist/types/app-config.js.map +1 -0
- package/dist/types/documents.d.ts +65 -0
- package/dist/types/documents.d.ts.map +1 -0
- package/dist/types/documents.js +2 -0
- package/dist/types/documents.js.map +1 -0
- package/dist/types/hooks.d.ts +122 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +12 -1748
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +12 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/request.d.ts +42 -0
- package/dist/types/request.d.ts.map +1 -0
- package/dist/types/request.js +2 -0
- package/dist/types/request.js.map +1 -0
- package/dist/types/schema-config.d.ts +303 -0
- package/dist/types/schema-config.d.ts.map +1 -0
- package/dist/types/schema-config.js +2 -0
- package/dist/types/schema-config.js.map +1 -0
- package/dist/types/schema-core.d.ts +294 -0
- package/dist/types/schema-core.d.ts.map +1 -0
- package/dist/types/schema-core.js +2 -0
- package/dist/types/schema-core.js.map +1 -0
- package/dist/types/schema-inference.d.ts +73 -0
- package/dist/types/schema-inference.d.ts.map +1 -0
- package/dist/types/schema-inference.js +2 -0
- package/dist/types/schema-inference.js.map +1 -0
- package/dist/types/workflows.d.ts +84 -0
- package/dist/types/workflows.d.ts.map +1 -0
- package/dist/types/workflows.js +7 -0
- package/dist/types/workflows.js.map +1 -0
- package/dist/utils/admin-auth.d.ts +5 -0
- package/dist/utils/admin-auth.d.ts.map +1 -0
- package/dist/utils/admin-auth.js +39 -0
- package/dist/utils/admin-auth.js.map +1 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +86 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/hooks.d.ts.map +1 -1
- package/dist/utils/hooks.js +12 -8
- package/dist/utils/hooks.js.map +1 -1
- package/dist/utils/openapi.d.ts.map +1 -1
- package/dist/utils/openapi.js +559 -48
- package/dist/utils/openapi.js.map +1 -1
- package/dist/utils/parse-sort.d.ts +7 -0
- package/dist/utils/parse-sort.d.ts.map +1 -0
- package/dist/utils/parse-sort.js +23 -0
- package/dist/utils/parse-sort.js.map +1 -0
- package/dist/utils/swagger.d.ts +6 -0
- package/dist/utils/swagger.d.ts.map +1 -1
- package/dist/utils/swagger.js +13 -2
- package/dist/utils/swagger.js.map +1 -1
- package/dist/utils/upload-validation.d.ts +23 -0
- package/dist/utils/upload-validation.d.ts.map +1 -0
- package/dist/utils/upload-validation.js +44 -0
- package/dist/utils/upload-validation.js.map +1 -0
- package/dist/utils/where-sanitizer.d.ts.map +1 -1
- package/dist/utils/where-sanitizer.js +4 -0
- package/dist/utils/where-sanitizer.js.map +1 -1
- package/dist/workflows.d.ts +54 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +282 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +1 -1
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import * as hono from 'hono';
|
|
3
3
|
import { Hono, Context } from 'hono';
|
|
4
|
-
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-
|
|
4
|
+
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-DqCipvSI.js';
|
|
5
5
|
import * as hono_utils_http_status from 'hono/utils/http-status';
|
|
6
6
|
import * as hono_utils_types from 'hono/utils/types';
|
|
7
7
|
import 'lucide-react';
|
|
@@ -192,6 +192,8 @@ declare class CollectionController {
|
|
|
192
192
|
}, 500, "json">) | (Response & hono.TypedResponse<{
|
|
193
193
|
message: string;
|
|
194
194
|
}, 400, "json">) | (Response & hono.TypedResponse<{
|
|
195
|
+
message: string;
|
|
196
|
+
}, 413 | 415, "json">) | (Response & hono.TypedResponse<{
|
|
195
197
|
[x: string]: hono_utils_types.JSONValue;
|
|
196
198
|
}, 201, "json">) | (Response & hono.TypedResponse<{
|
|
197
199
|
id: string;
|
|
@@ -207,6 +209,8 @@ declare class CollectionController {
|
|
|
207
209
|
}, 500, "json">) | (Response & hono.TypedResponse<{
|
|
208
210
|
message: string;
|
|
209
211
|
}, 400, "json">) | (Response & hono.TypedResponse<{
|
|
212
|
+
message: string;
|
|
213
|
+
}, 413 | 415, "json">) | (Response & hono.TypedResponse<{
|
|
210
214
|
[x: string]: hono_utils_types.JSONValue;
|
|
211
215
|
}, 201, "json">)>;
|
|
212
216
|
update(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
|
|
@@ -324,6 +328,8 @@ declare class MediaController {
|
|
|
324
328
|
}, 500, "json">) | (Response & hono.TypedResponse<{
|
|
325
329
|
message: string;
|
|
326
330
|
}, 400, "json">) | (Response & hono.TypedResponse<{
|
|
331
|
+
message: string;
|
|
332
|
+
}, 413 | 415, "json">) | (Response & hono.TypedResponse<{
|
|
327
333
|
[x: string]: any;
|
|
328
334
|
id: string;
|
|
329
335
|
}, 201, "json">)>;
|
package/dist/server.js
CHANGED
|
@@ -308,6 +308,37 @@ function createReadonlyDb(db) {
|
|
|
308
308
|
});
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
// src/utils/upload-validation.ts
|
|
312
|
+
function isMimeAllowed(mimeType, allowed) {
|
|
313
|
+
const type = (mimeType || "").toLowerCase().trim();
|
|
314
|
+
return allowed.some((raw) => {
|
|
315
|
+
const pattern = (raw || "").toLowerCase().trim();
|
|
316
|
+
if (!pattern) return false;
|
|
317
|
+
if (pattern === "*" || pattern === "*/*") return true;
|
|
318
|
+
if (pattern.endsWith("/*")) return type.startsWith(pattern.slice(0, -1));
|
|
319
|
+
return type === pattern;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function validateUpload(file, config) {
|
|
323
|
+
if (!config) return null;
|
|
324
|
+
const { allowedMimeTypes, maxFileSize } = config;
|
|
325
|
+
if (allowedMimeTypes && allowedMimeTypes.length > 0) {
|
|
326
|
+
if (!isMimeAllowed(file.type || "", allowedMimeTypes)) {
|
|
327
|
+
return {
|
|
328
|
+
status: 415,
|
|
329
|
+
message: `File type "${file.type || "unknown"}" is not allowed. Allowed types: ${allowedMimeTypes.join(", ")}.`
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (typeof maxFileSize === "number" && typeof file.size === "number" && file.size > maxFileSize) {
|
|
334
|
+
return {
|
|
335
|
+
status: 413,
|
|
336
|
+
message: `File is too large (${file.size} bytes). Maximum allowed size is ${maxFileSize} bytes.`
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
|
|
311
342
|
// src/auth/jexl.ts
|
|
312
343
|
import jexl2 from "jexl";
|
|
313
344
|
async function evaluateAccess(expression, context) {
|
|
@@ -604,6 +635,11 @@ var CollectionController = class {
|
|
|
604
635
|
const formData = await c.req.formData();
|
|
605
636
|
const file = formData.get("file");
|
|
606
637
|
if (!file) return c.json({ message: "No file uploaded" }, 400);
|
|
638
|
+
const uploadConfig = typeof this.collection.upload === "object" ? this.collection.upload : void 0;
|
|
639
|
+
const validationError = validateUpload(file, uploadConfig);
|
|
640
|
+
if (validationError) {
|
|
641
|
+
return c.json({ message: validationError.message }, validationError.status);
|
|
642
|
+
}
|
|
607
643
|
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
608
644
|
const siteId = c.get("siteId");
|
|
609
645
|
const workspaceId = c.get("workspaceId");
|
|
@@ -1141,18 +1177,23 @@ var MediaController = class {
|
|
|
1141
1177
|
if (!file) {
|
|
1142
1178
|
return c.json({ message: "No file uploaded" }, 400);
|
|
1143
1179
|
}
|
|
1144
|
-
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
1145
1180
|
const siteId = c.get("siteId");
|
|
1181
|
+
let colConfig = config.collections.find((col) => col.slug === this.collection);
|
|
1182
|
+
if (!colConfig && config.onSchemaFetch && siteId) {
|
|
1183
|
+
const dynamic = await config.onSchemaFetch(siteId);
|
|
1184
|
+
colConfig = dynamic.collections?.find((col) => col.slug === this.collection);
|
|
1185
|
+
}
|
|
1186
|
+
const uploadConfig = typeof colConfig?.upload === "object" ? colConfig.upload : void 0;
|
|
1187
|
+
const validationError = validateUpload(file, uploadConfig);
|
|
1188
|
+
if (validationError) {
|
|
1189
|
+
return c.json({ message: validationError.message }, validationError.status);
|
|
1190
|
+
}
|
|
1191
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
1146
1192
|
const workspaceId = c.get("workspaceId");
|
|
1147
1193
|
const prefix = workspaceId ? `${workspaceId}/${siteId}` : siteId || "default";
|
|
1148
1194
|
let imageMetadata = {};
|
|
1149
1195
|
let imageSizes = {};
|
|
1150
1196
|
if (imageService && file.type.startsWith("image/")) {
|
|
1151
|
-
let colConfig = config.collections.find((col) => col.slug === this.collection);
|
|
1152
|
-
if (!colConfig && config.onSchemaFetch && siteId) {
|
|
1153
|
-
const dynamic = await config.onSchemaFetch(siteId);
|
|
1154
|
-
colConfig = dynamic.collections?.find((col) => col.slug === this.collection);
|
|
1155
|
-
}
|
|
1156
1197
|
try {
|
|
1157
1198
|
const processed = await imageService.process({
|
|
1158
1199
|
buffer,
|
|
@@ -2228,7 +2269,7 @@ function optionalAuth() {
|
|
|
2228
2269
|
}
|
|
2229
2270
|
|
|
2230
2271
|
// src/utils/swagger.ts
|
|
2231
|
-
function getSwaggerHtml(specUrl
|
|
2272
|
+
function getSwaggerHtml(specUrl) {
|
|
2232
2273
|
return `
|
|
2233
2274
|
<!DOCTYPE html>
|
|
2234
2275
|
<html lang="en">
|
|
@@ -2248,7 +2289,12 @@ function getSwaggerHtml(specUrl = "/api/openapi.json") {
|
|
|
2248
2289
|
// Forward the apikey query param when loading the spec and making API calls
|
|
2249
2290
|
const params = new URLSearchParams(window.location.search);
|
|
2250
2291
|
const apiKey = params.get('apikey');
|
|
2251
|
-
|
|
2292
|
+
// Resolve the spec relative to this docs page so any mount prefix
|
|
2293
|
+
// (e.g. "/dyrected/api/docs") is preserved. Falls back to an explicit URL
|
|
2294
|
+
// when one is supplied by the caller.
|
|
2295
|
+
const explicitSpecUrl = ${JSON.stringify(specUrl ?? "")};
|
|
2296
|
+
const specUrl = explicitSpecUrl || (window.location.pathname.replace(/\\/docs\\/?$/, '') + '/openapi.json');
|
|
2297
|
+
const specUrlWithKey = apiKey ? specUrl + '?apikey=' + encodeURIComponent(apiKey) : specUrl;
|
|
2252
2298
|
|
|
2253
2299
|
window.ui = SwaggerUIBundle({
|
|
2254
2300
|
url: specUrlWithKey,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const emailTokens: {
|
|
2
|
+
readonly colors: {
|
|
3
|
+
readonly canvas: "#f6f7f2";
|
|
4
|
+
readonly surface: "#ffffff";
|
|
5
|
+
readonly text: "#171717";
|
|
6
|
+
readonly muted: "#62665b";
|
|
7
|
+
readonly subtle: "#8a8f82";
|
|
8
|
+
readonly border: "#dde0d7";
|
|
9
|
+
readonly accent: "#b6ff2e";
|
|
10
|
+
readonly code: "#f1f3ec";
|
|
11
|
+
readonly dangerSurface: "#fff2f0";
|
|
12
|
+
readonly dangerBorder: "#ffc9c2";
|
|
13
|
+
readonly dangerText: "#9f251b";
|
|
14
|
+
};
|
|
15
|
+
readonly font: "Arial, 'Helvetica Neue', Helvetica, sans-serif";
|
|
16
|
+
readonly mono: "'Courier New', Courier, monospace";
|
|
17
|
+
readonly radius: {
|
|
18
|
+
readonly card: "12px";
|
|
19
|
+
readonly control: "6px";
|
|
20
|
+
};
|
|
21
|
+
readonly width: "600px";
|
|
22
|
+
};
|
|
23
|
+
export declare function escapeHtml(value: string): string;
|
|
24
|
+
export declare function heading(content: string): string;
|
|
25
|
+
export declare function paragraph(content: string, margin?: string): string;
|
|
26
|
+
export declare function sectionLabel(content: string): string;
|
|
27
|
+
export declare function divider(): string;
|
|
28
|
+
export declare function spacer(height?: number): string;
|
|
29
|
+
export declare function row(content: string, cellStyle?: string): string;
|
|
30
|
+
export declare function table(content: string, style?: string): string;
|
|
31
|
+
export declare function detailBox(content: string, monospace?: boolean): string;
|
|
32
|
+
export declare function eventList(events: ReadonlyArray<{
|
|
33
|
+
label: string;
|
|
34
|
+
value: string;
|
|
35
|
+
}>): string;
|
|
36
|
+
export declare function ctaButton(label: string, href: string): string;
|
|
37
|
+
export declare function alertBox(content: string): string;
|
|
38
|
+
interface LayoutOptions {
|
|
39
|
+
preheader: string;
|
|
40
|
+
title: string;
|
|
41
|
+
content: string;
|
|
42
|
+
footer: string;
|
|
43
|
+
}
|
|
44
|
+
export declare function layout({ preheader, title, content, footer }: LayoutOptions): string;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=email-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-template.d.ts","sourceRoot":"","sources":["../../src/services/email-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;CAkBd,CAAC;AAEX,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD;AAWD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAa,GAAG,MAAM,CAEtE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,wBAAgB,MAAM,CAAC,MAAM,SAAK,GAAG,MAAM,CAE1C;AAED,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAK,GAAG,MAAM,CAE3D;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAe,GAAG,MAAM,CAEnE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,MAAM,CAGpE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAKzF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,MAAM,CAkBnF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export const emailTokens = {
|
|
2
|
+
colors: {
|
|
3
|
+
canvas: '#f6f7f2',
|
|
4
|
+
surface: '#ffffff',
|
|
5
|
+
text: '#171717',
|
|
6
|
+
muted: '#62665b',
|
|
7
|
+
subtle: '#8a8f82',
|
|
8
|
+
border: '#dde0d7',
|
|
9
|
+
accent: '#b6ff2e',
|
|
10
|
+
code: '#f1f3ec',
|
|
11
|
+
dangerSurface: '#fff2f0',
|
|
12
|
+
dangerBorder: '#ffc9c2',
|
|
13
|
+
dangerText: '#9f251b',
|
|
14
|
+
},
|
|
15
|
+
font: "Arial, 'Helvetica Neue', Helvetica, sans-serif",
|
|
16
|
+
mono: "'Courier New', Courier, monospace",
|
|
17
|
+
radius: { card: '12px', control: '6px' },
|
|
18
|
+
width: '600px',
|
|
19
|
+
};
|
|
20
|
+
export function escapeHtml(value) {
|
|
21
|
+
return value.replace(/[&<>'"]/g, (character) => ({
|
|
22
|
+
'&': '&',
|
|
23
|
+
'<': '<',
|
|
24
|
+
'>': '>',
|
|
25
|
+
"'": ''',
|
|
26
|
+
'"': '"',
|
|
27
|
+
})[character]);
|
|
28
|
+
}
|
|
29
|
+
function safeHttpUrl(value) {
|
|
30
|
+
try {
|
|
31
|
+
const url = new URL(value);
|
|
32
|
+
return url.protocol === 'https:' || url.protocol === 'http:' ? escapeHtml(url.toString()) : undefined;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function heading(content) {
|
|
39
|
+
return `<h1 style="margin:0;font-family:${emailTokens.font};font-size:24px;line-height:1.25;font-weight:700;color:${emailTokens.colors.text}">${escapeHtml(content)}</h1>`;
|
|
40
|
+
}
|
|
41
|
+
export function paragraph(content, margin = '0 0 16px') {
|
|
42
|
+
return `<p style="margin:${margin};font-family:${emailTokens.font};font-size:15px;line-height:1.6;color:${emailTokens.colors.muted}">${escapeHtml(content)}</p>`;
|
|
43
|
+
}
|
|
44
|
+
export function sectionLabel(content) {
|
|
45
|
+
return `<p style="margin:0 0 8px;font-family:${emailTokens.font};font-size:11px;line-height:1.4;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:${emailTokens.colors.subtle}">${escapeHtml(content)}</p>`;
|
|
46
|
+
}
|
|
47
|
+
export function divider() {
|
|
48
|
+
return `<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%"><tr><td style="height:1px;background:${emailTokens.colors.border};font-size:0;line-height:0"> </td></tr></table>`;
|
|
49
|
+
}
|
|
50
|
+
export function spacer(height = 16) {
|
|
51
|
+
return table(row(' ', `height:${height}px;font-size:0;line-height:0`));
|
|
52
|
+
}
|
|
53
|
+
export function row(content, cellStyle = '') {
|
|
54
|
+
return `<tr><td style="${cellStyle}">${content}</td></tr>`;
|
|
55
|
+
}
|
|
56
|
+
export function table(content, style = 'width:100%') {
|
|
57
|
+
return `<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="${style}">${content}</table>`;
|
|
58
|
+
}
|
|
59
|
+
export function detailBox(content, monospace = false) {
|
|
60
|
+
const font = monospace ? emailTokens.mono : emailTokens.font;
|
|
61
|
+
return table(row(escapeHtml(content), `padding:14px 16px;font-family:${font};font-size:13px;line-height:1.5;font-weight:${monospace ? '400' : '700'};color:${emailTokens.colors.text};word-break:break-all`), `width:100%;background:${emailTokens.colors.code};border-radius:${emailTokens.radius.control}`);
|
|
62
|
+
}
|
|
63
|
+
export function eventList(events) {
|
|
64
|
+
return table(events.map(({ label, value }) => row(`${sectionLabel(label)}${paragraph(value, '0')}`, `padding:12px 0;border-bottom:1px solid ${emailTokens.colors.border}`)).join(''));
|
|
65
|
+
}
|
|
66
|
+
export function ctaButton(label, href) {
|
|
67
|
+
const safeHref = safeHttpUrl(href);
|
|
68
|
+
if (!safeHref)
|
|
69
|
+
return '';
|
|
70
|
+
return table(row(`<a href="${safeHref}" style="display:inline-block;padding:13px 22px;border-radius:${emailTokens.radius.control};background:${emailTokens.colors.accent};font-family:${emailTokens.font};font-size:14px;line-height:1.2;font-weight:700;color:${emailTokens.colors.text};text-decoration:none">${escapeHtml(label)}</a>`, 'padding:8px 0 24px'), 'width:auto');
|
|
71
|
+
}
|
|
72
|
+
export function alertBox(content) {
|
|
73
|
+
return table(row(escapeHtml(content), `padding:13px 16px;font-family:${emailTokens.font};font-size:13px;line-height:1.5;color:${emailTokens.colors.dangerText}`), `width:100%;background:${emailTokens.colors.dangerSurface};border:1px solid ${emailTokens.colors.dangerBorder};border-radius:${emailTokens.radius.control}`);
|
|
74
|
+
}
|
|
75
|
+
export function layout({ preheader, title, content, footer }) {
|
|
76
|
+
return `<!doctype html>
|
|
77
|
+
<html lang="en">
|
|
78
|
+
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head>
|
|
79
|
+
<body style="margin:0;padding:0;background:${emailTokens.colors.canvas}">
|
|
80
|
+
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent">${escapeHtml(preheader)}</div>
|
|
81
|
+
${table(row(table(row(' ', `height:5px;background:${emailTokens.colors.accent};font-size:0;line-height:0`) +
|
|
82
|
+
row(`${sectionLabel('Dyrected')}${heading(title)}`, 'padding:30px 32px 24px') +
|
|
83
|
+
row(content, 'padding:0 32px 32px') +
|
|
84
|
+
row(`${divider()}${paragraph(footer, '20px 0 6px')}${paragraph('Privacy: this message contains account-related information; please avoid forwarding it.', '0')}`, 'padding:0 32px 28px'), `width:100%;max-width:${emailTokens.width};background:${emailTokens.colors.surface};border:1px solid ${emailTokens.colors.border};border-radius:${emailTokens.radius.card};overflow:hidden`), 'padding:32px 12px'), `width:100%;background:${emailTokens.colors.canvas}`)}
|
|
85
|
+
</body>
|
|
86
|
+
</html>`;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=email-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-template.js","sourceRoot":"","sources":["../../src/services/email-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE;QACN,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;QACf,aAAa,EAAE,SAAS;QACxB,YAAY,EAAE,SAAS;QACvB,UAAU,EAAE,SAAS;KACtB;IACD,IAAI,EAAE,gDAAgD;IACtD,IAAI,EAAE,mCAAmC;IACzC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE;IACxC,KAAK,EAAE,OAAO;CACN,CAAC;AAEX,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC/C,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,QAAQ;KACd,CAAC,CAAC,SAAS,CAAW,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,mCAAmC,WAAW,CAAC,IAAI,0DAA0D,WAAW,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC;AAC7K,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,MAAM,GAAG,UAAU;IAC5D,OAAO,oBAAoB,MAAM,gBAAgB,WAAW,CAAC,IAAI,yCAAyC,WAAW,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;AACnK,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,wCAAwC,WAAW,CAAC,IAAI,uGAAuG,WAAW,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;AAChO,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,2HAA2H,WAAW,CAAC,MAAM,CAAC,MAAM,sDAAsD,CAAC;AACpN,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,MAAM,GAAG,EAAE;IAChC,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,MAAM,8BAA8B,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,SAAS,GAAG,EAAE;IACjD,OAAO,kBAAkB,SAAS,KAAK,OAAO,YAAY,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,KAAK,GAAG,YAAY;IACzD,OAAO,6FAA6F,KAAK,KAAK,OAAO,UAAU,CAAC;AAClI,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,SAAS,GAAG,KAAK;IAC1D,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;IAC7D,OAAO,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,iCAAiC,IAAI,+CAA+C,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,WAAW,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC,EAAE,yBAAyB,WAAW,CAAC,MAAM,CAAC,IAAI,kBAAkB,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AAChT,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAuD;IAC/E,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,GAAG,CAC/C,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAChD,0CAA0C,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CACtE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,IAAY;IACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,OAAO,KAAK,CAAC,GAAG,CACd,YAAY,QAAQ,iEAAiE,WAAW,CAAC,MAAM,CAAC,OAAO,eAAe,WAAW,CAAC,MAAM,CAAC,MAAM,gBAAgB,WAAW,CAAC,IAAI,yDAAyD,WAAW,CAAC,MAAM,CAAC,IAAI,0BAA0B,UAAU,CAAC,KAAK,CAAC,MAAM,EACxT,oBAAoB,CACrB,EAAE,YAAY,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,iCAAiC,WAAW,CAAC,IAAI,yCAAyC,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,yBAAyB,WAAW,CAAC,MAAM,CAAC,aAAa,qBAAqB,WAAW,CAAC,MAAM,CAAC,YAAY,kBAAkB,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AACjU,CAAC;AASD,MAAM,UAAU,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAiB;IACzE,OAAO;;;+CAGsC,WAAW,CAAC,MAAM,CAAC,MAAM;yFACiB,UAAU,CAAC,SAAS,CAAC;MACxG,KAAK,CAAC,GAAG,CACT,KAAK,CACH,GAAG,CAAC,QAAQ,EAAE,yBAAyB,WAAW,CAAC,MAAM,CAAC,MAAM,4BAA4B,CAAC;QAC7F,GAAG,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,wBAAwB,CAAC;QAC7E,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC;QACnC,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC,yFAAyF,EAAE,GAAG,CAAC,EAAE,EAAE,qBAAqB,CAAC,EACxL,wBAAwB,WAAW,CAAC,KAAK,eAAe,WAAW,CAAC,MAAM,CAAC,OAAO,qBAAqB,WAAW,CAAC,MAAM,CAAC,MAAM,kBAAkB,WAAW,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAC5L,EACD,mBAAmB,CACpB,EAAE,yBAAyB,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;;QAEpD,CAAC;AACT,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.service.d.ts","sourceRoot":"","sources":["../../src/services/email.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"email.service.d.ts","sourceRoot":"","sources":["../../src/services/email.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAwCxD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrD,OAAO,CAAC,IAAI,CAAC,CASf;AAMD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWnC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWnC;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAYnC;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWnC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { alertBox, ctaButton, detailBox, layout, paragraph, sectionLabel, spacer } from './email-template.js';
|
|
1
2
|
// Lazy Ethereal singleton — created once on first send in dev
|
|
2
3
|
let _devSend = null;
|
|
3
4
|
let _devSendPromise = null;
|
|
@@ -47,77 +48,24 @@ export function buildWelcomeEmail(config, args) {
|
|
|
47
48
|
const custom = config.email?.templates?.welcome?.(args);
|
|
48
49
|
return {
|
|
49
50
|
subject: custom?.subject ?? 'Welcome — your account is ready',
|
|
50
|
-
html: custom?.html ??
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<td style="padding:32px 32px 0">
|
|
57
|
-
<p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
|
|
58
|
-
<h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Welcome!</h1>
|
|
59
|
-
</td>
|
|
60
|
-
</tr>
|
|
61
|
-
<tr>
|
|
62
|
-
<td style="padding:0 32px">
|
|
63
|
-
<p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Your account has been created. You can now log in with:</p>
|
|
64
|
-
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
|
|
65
|
-
<tr>
|
|
66
|
-
<td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
|
|
67
|
-
${args.email}
|
|
68
|
-
</td>
|
|
69
|
-
</tr>
|
|
70
|
-
</table>
|
|
71
|
-
</td>
|
|
72
|
-
</tr>
|
|
73
|
-
<tr>
|
|
74
|
-
<td style="padding:32px">
|
|
75
|
-
<p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't create this account, you can safely ignore this email.</p>
|
|
76
|
-
</td>
|
|
77
|
-
</tr>
|
|
78
|
-
</table>
|
|
79
|
-
</td>
|
|
80
|
-
</tr>
|
|
81
|
-
</table>`,
|
|
51
|
+
html: custom?.html ?? layout({
|
|
52
|
+
preheader: 'Your Dyrected account is ready.',
|
|
53
|
+
title: 'Welcome — your account is ready',
|
|
54
|
+
content: `${paragraph('Your account has been created. You can now log in with:')}${detailBox(args.email)}`,
|
|
55
|
+
footer: "If you didn't create this account, you can safely ignore this email.",
|
|
56
|
+
}),
|
|
82
57
|
};
|
|
83
58
|
}
|
|
84
59
|
export function buildInviteEmail(config, args) {
|
|
85
60
|
const custom = config.email?.templates?.invite?.(args);
|
|
86
61
|
return {
|
|
87
62
|
subject: custom?.subject ?? "You've been invited",
|
|
88
|
-
html: custom?.html ??
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
<td style="padding:32px 32px 0">
|
|
95
|
-
<p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
|
|
96
|
-
<h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">You've been invited</h1>
|
|
97
|
-
</td>
|
|
98
|
-
</tr>
|
|
99
|
-
<tr>
|
|
100
|
-
<td style="padding:0 32px">
|
|
101
|
-
${args.invitedByEmail ? `<p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">You were invited by <strong style="color:#111827">${args.invitedByEmail}</strong>.</p>` : ''}
|
|
102
|
-
<p style="margin:0 0 16px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Use the token below to accept your invitation. It expires in 7 days.</p>
|
|
103
|
-
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
|
|
104
|
-
<tr>
|
|
105
|
-
<td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
|
|
106
|
-
${args.token}
|
|
107
|
-
</td>
|
|
108
|
-
</tr>
|
|
109
|
-
</table>
|
|
110
|
-
</td>
|
|
111
|
-
</tr>
|
|
112
|
-
<tr>
|
|
113
|
-
<td style="padding:32px">
|
|
114
|
-
<p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you weren't expecting this invitation, you can safely ignore this email.</p>
|
|
115
|
-
</td>
|
|
116
|
-
</tr>
|
|
117
|
-
</table>
|
|
118
|
-
</td>
|
|
119
|
-
</tr>
|
|
120
|
-
</table>`,
|
|
63
|
+
html: custom?.html ?? layout({
|
|
64
|
+
preheader: "You've been invited to join a Dyrected account.",
|
|
65
|
+
title: "You've been invited",
|
|
66
|
+
content: `${args.invitedByEmail ? paragraph(`You were invited by ${args.invitedByEmail}.`) : ''}${paragraph('Use the token below to accept your invitation. It expires in 7 days.')}${sectionLabel('Invitation token')}${detailBox(args.token, true)}`,
|
|
67
|
+
footer: "If you weren't expecting this invitation, you can safely ignore this email.",
|
|
68
|
+
}),
|
|
121
69
|
};
|
|
122
70
|
}
|
|
123
71
|
export function buildResetPasswordEmail(config, args) {
|
|
@@ -125,95 +73,24 @@ export function buildResetPasswordEmail(config, args) {
|
|
|
125
73
|
const resetLink = args.url;
|
|
126
74
|
return {
|
|
127
75
|
subject: custom?.subject ?? 'Reset your password',
|
|
128
|
-
html: custom?.html ??
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
<td style="padding:32px 32px 0">
|
|
135
|
-
<p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
|
|
136
|
-
<h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Reset your password</h1>
|
|
137
|
-
</td>
|
|
138
|
-
</tr>
|
|
139
|
-
<tr>
|
|
140
|
-
<td style="padding:0 32px">
|
|
141
|
-
<p style="margin:0 0 24px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">We received a request to reset your password. Use the button below to set a new password. It will expire in 1 hour.</p>
|
|
142
|
-
${resetLink ? `
|
|
143
|
-
<table cellpadding="0" cellspacing="0" border="0" style="margin-bottom:24px">
|
|
144
|
-
<tr>
|
|
145
|
-
<td style="border-radius:6px;background-color:#111827">
|
|
146
|
-
<a href="${resetLink}" style="display:inline-block;padding:12px 28px;font-size:14px;font-weight:600;color:#ffffff;text-decoration:none;font-family:sans-serif;border-radius:6px">
|
|
147
|
-
Reset Password
|
|
148
|
-
</a>
|
|
149
|
-
</td>
|
|
150
|
-
</tr>
|
|
151
|
-
</table>
|
|
152
|
-
` : ''}
|
|
153
|
-
<p style="margin:0 0 8px;font-size:12px;color:#9ca3af;font-family:sans-serif">Or copy and paste this token manually in the admin dashboard:</p>
|
|
154
|
-
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
|
|
155
|
-
<tr>
|
|
156
|
-
<td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
|
|
157
|
-
${args.token}
|
|
158
|
-
</td>
|
|
159
|
-
</tr>
|
|
160
|
-
</table>
|
|
161
|
-
</td>
|
|
162
|
-
</tr>
|
|
163
|
-
<tr>
|
|
164
|
-
<td style="padding:32px">
|
|
165
|
-
<p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't request a password reset, you can safely ignore this email.</p>
|
|
166
|
-
</td>
|
|
167
|
-
</tr>
|
|
168
|
-
</table>
|
|
169
|
-
</td>
|
|
170
|
-
</tr>
|
|
171
|
-
</table>`,
|
|
76
|
+
html: custom?.html ?? layout({
|
|
77
|
+
preheader: 'Reset your Dyrected password.',
|
|
78
|
+
title: 'Reset your password',
|
|
79
|
+
content: `${paragraph('We received a request to reset your password. The reset link and token expire in 1 hour.')}${resetLink ? ctaButton('Reset password', resetLink) : ''}${sectionLabel(resetLink ? 'Or use this token' : 'Reset token')}${detailBox(args.token, true)}`,
|
|
80
|
+
footer: "If you didn't request a password reset, you can safely ignore this email.",
|
|
81
|
+
}),
|
|
172
82
|
};
|
|
173
83
|
}
|
|
174
84
|
export function buildPasswordChangedEmail(config, args) {
|
|
175
85
|
const custom = config.email?.templates?.passwordChanged?.(args);
|
|
176
86
|
return {
|
|
177
87
|
subject: custom?.subject ?? 'Your password has been changed',
|
|
178
|
-
html: custom?.html ??
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
<td style="padding:32px 32px 0">
|
|
185
|
-
<p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
|
|
186
|
-
<h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Password changed</h1>
|
|
187
|
-
</td>
|
|
188
|
-
</tr>
|
|
189
|
-
<tr>
|
|
190
|
-
<td style="padding:0 32px">
|
|
191
|
-
<p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">The password for your account was just changed:</p>
|
|
192
|
-
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
|
|
193
|
-
<tr>
|
|
194
|
-
<td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
|
|
195
|
-
${args.email}
|
|
196
|
-
</td>
|
|
197
|
-
</tr>
|
|
198
|
-
</table>
|
|
199
|
-
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;margin-top:16px;background-color:#fef2f2;border-radius:6px;border:1px solid #fecaca;table-layout:fixed">
|
|
200
|
-
<tr>
|
|
201
|
-
<td style="padding:12px 16px;font-size:13px;color:#b91c1c;line-height:1.5;font-family:sans-serif">
|
|
202
|
-
If you did not make this change, please contact support immediately.
|
|
203
|
-
</td>
|
|
204
|
-
</tr>
|
|
205
|
-
</table>
|
|
206
|
-
</td>
|
|
207
|
-
</tr>
|
|
208
|
-
<tr>
|
|
209
|
-
<td style="padding:32px">
|
|
210
|
-
<p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">This is an automated security notification.</p>
|
|
211
|
-
</td>
|
|
212
|
-
</tr>
|
|
213
|
-
</table>
|
|
214
|
-
</td>
|
|
215
|
-
</tr>
|
|
216
|
-
</table>`,
|
|
88
|
+
html: custom?.html ?? layout({
|
|
89
|
+
preheader: 'Your Dyrected password was changed.',
|
|
90
|
+
title: 'Password changed',
|
|
91
|
+
content: `${paragraph('The password for this account was just changed:')}${detailBox(args.email)}${spacer()}${alertBox('If you did not make this change, please contact support immediately.')}`,
|
|
92
|
+
footer: 'This is an automated security notification.',
|
|
93
|
+
}),
|
|
217
94
|
};
|
|
218
95
|
}
|
|
219
96
|
//# sourceMappingURL=email.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../src/services/email.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../src/services/email.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"population.service.d.ts","sourceRoot":"","sources":["../../src/services/population.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"population.service.d.ts","sourceRoot":"","sources":["../../src/services/population.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAInG,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,WAAW,CAAqB;gBAE5B,EAAE,EAAE,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAKhE;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,GAAG,CAAC;QACV,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,GAAG,CAAC;IAgLhB;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAe3G"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DefaultsService } from './defaults.service.js';
|
|
2
|
+
import jexl from 'jexl';
|
|
2
3
|
export class PopulationService {
|
|
3
4
|
db;
|
|
4
5
|
collections;
|
|
@@ -112,7 +113,32 @@ export class PopulationService {
|
|
|
112
113
|
maxDepth,
|
|
113
114
|
});
|
|
114
115
|
const identifier = docWithDefaults.slug || docWithDefaults.id;
|
|
115
|
-
|
|
116
|
+
let resolvedUrl = `/collections/${value.relationTo}/${identifier}`;
|
|
117
|
+
const previewUrlPattern = relatedCollection.admin?.previewUrl || relatedCollection.admin?.urlPattern;
|
|
118
|
+
if (previewUrlPattern) {
|
|
119
|
+
if (typeof previewUrlPattern === 'function') {
|
|
120
|
+
try {
|
|
121
|
+
resolvedUrl = previewUrlPattern(docWithDefaults, { locale: 'en' }) || resolvedUrl;
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
}
|
|
125
|
+
else if (typeof previewUrlPattern === 'string') {
|
|
126
|
+
if (previewUrlPattern.includes('{{')) {
|
|
127
|
+
resolvedUrl = previewUrlPattern.replace(/{{(.*?)}}/g, (_, key) => String(docWithDefaults[key.trim()] || ''));
|
|
128
|
+
}
|
|
129
|
+
else if (previewUrlPattern.includes('+') || previewUrlPattern.includes('?') || previewUrlPattern.includes('==') || previewUrlPattern.includes('siteUrl')) {
|
|
130
|
+
try {
|
|
131
|
+
resolvedUrl = jexl.evalSync(previewUrlPattern, docWithDefaults);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ''));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ''));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
116
142
|
populatedDoc[field.name] = {
|
|
117
143
|
...value,
|
|
118
144
|
url: resolvedUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"population.service.js","sourceRoot":"","sources":["../../src/services/population.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"population.service.js","sourceRoot":"","sources":["../../src/services/population.service.ts"],"names":[],"mappings":"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"}
|