@voyantjs/notifications 0.6.8 → 0.6.9
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/README.md +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/liquid.d.ts +5 -0
- package/dist/liquid.d.ts.map +1 -0
- package/dist/liquid.js +156 -0
- package/dist/routes.d.ts +18 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +5 -1
- package/dist/service-booking-documents.d.ts.map +1 -1
- package/dist/service-booking-documents.js +11 -4
- package/dist/service-deliveries.d.ts.map +1 -1
- package/dist/service-deliveries.js +25 -7
- package/dist/service-reminders.d.ts.map +1 -1
- package/dist/service-reminders.js +98 -78
- package/dist/service-shared.d.ts +48 -3
- package/dist/service-shared.d.ts.map +1 -1
- package/dist/service-shared.js +300 -40
- package/dist/service.d.ts +3 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +3 -1
- package/dist/template-authoring.d.ts +23 -0
- package/dist/template-authoring.d.ts.map +1 -0
- package/dist/template-authoring.js +386 -0
- package/dist/validation.d.ts +23 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +21 -0
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ For finance-aware collection sends, the routes also support:
|
|
|
94
94
|
- `GET /bookings/:id/document-bundle`
|
|
95
95
|
- `POST /bookings/:id/send-documents`
|
|
96
96
|
|
|
97
|
-
Those routes resolve recipients from the payment session, invoice, and linked booking
|
|
97
|
+
Those routes resolve recipients from the payment session, invoice, and linked booking travelers, then render the selected notification template with finance context such as payment links, invoice balances, and booking references.
|
|
98
98
|
|
|
99
99
|
Booking document sends bundle the latest customer-facing contract attachment and
|
|
100
100
|
ready invoice/proforma rendition for a booking. By default they use the stored
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { HonoModule } from "@voyantjs/hono/module";
|
|
2
2
|
import { type NotificationsRoutesOptions } from "./routes.js";
|
|
3
|
+
export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
|
|
3
4
|
export type { DefaultNotificationProviderOptions } from "./provider-resolution.js";
|
|
4
5
|
export { createDefaultNotificationProviders, createResendProviderFromEnv, createTwilioProviderFromEnv, } from "./provider-resolution.js";
|
|
5
6
|
export type { LocalProviderOptions } from "./providers/local.js";
|
|
@@ -13,13 +14,15 @@ export { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATION
|
|
|
13
14
|
export type { NewNotificationDelivery, NewNotificationReminderRule, NewNotificationReminderRun, NewNotificationTemplate, NotificationDelivery, NotificationReminderRule, NotificationReminderRun, NotificationsHonoModule, NotificationTemplate, } from "./schema.js";
|
|
14
15
|
export { notificationChannelEnum, notificationDeliveries, notificationDeliveryStatusEnum, notificationReminderRules, notificationReminderRunStatusEnum, notificationReminderRuns, notificationReminderStatusEnum, notificationReminderTargetTypeEnum, notificationsModule, notificationTargetTypeEnum, notificationTemplateStatusEnum, notificationTemplates, } from "./schema.js";
|
|
15
16
|
export type { NotificationService } from "./service.js";
|
|
16
|
-
export { createDefaultBookingDocumentAttachment, createNotificationService, NotificationError, notificationsService, renderNotificationTemplate, } from "./service.js";
|
|
17
|
+
export { createDefaultBookingDocumentAttachment, createNotificationService, NotificationError, notificationsService, previewNotificationTemplate, renderNotificationTemplate, } from "./service.js";
|
|
17
18
|
export type { BookingDocumentAttachmentResolver, BookingDocumentsSentEvent, SendBookingDocumentsRuntimeOptions, } from "./service-booking-documents.js";
|
|
18
19
|
export { bookingDocumentNotificationsService } from "./service-booking-documents.js";
|
|
19
20
|
export type { NotificationTaskEnv, NotificationTaskRuntime, NotificationTaskRuntimeOptions, ReminderDeliveryJob, } from "./task-runtime.js";
|
|
20
21
|
export { buildNotificationTaskRuntime } from "./task-runtime.js";
|
|
21
22
|
export { deliverQueuedNotificationReminder, sendDueNotificationReminders } from "./tasks/index.js";
|
|
23
|
+
export type { NotificationLiquidSnippet, NotificationTemplateVariableCategory, NotificationTemplateVariableDefinition, NotificationTemplateVariableType, } from "./template-authoring.js";
|
|
24
|
+
export { notificationLiquidSnippets, notificationTemplateVariableCatalog, } from "./template-authoring.js";
|
|
22
25
|
export type { NotificationAttachment, NotificationChannel, NotificationPayload, NotificationProvider, NotificationResult, } from "./types.js";
|
|
23
|
-
export { bookingDocumentBundleItemSchema, bookingDocumentBundleSchema, insertNotificationReminderRuleSchema, insertNotificationTemplateSchema, notificationAttachmentSchema, notificationChannelSchema, notificationDeliveryListQuerySchema, notificationDeliveryStatusSchema, notificationDocumentSourceSchema, notificationDocumentTypeSchema, notificationReminderRuleListQuerySchema, notificationReminderRunDeliverySummarySchema, notificationReminderRunLinksSchema, notificationReminderRunListQuerySchema, notificationReminderRunListResponseSchema, notificationReminderRunRecordSchema, notificationReminderRunRuleSummarySchema, notificationReminderRunStatusSchema, notificationReminderStatusSchema, notificationReminderTargetTypeSchema, notificationTargetTypeSchema, notificationTemplateListQuerySchema, notificationTemplateStatusSchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
|
|
26
|
+
export { bookingDocumentBundleItemSchema, bookingDocumentBundleSchema, insertNotificationReminderRuleSchema, insertNotificationTemplateSchema, notificationAttachmentSchema, notificationChannelSchema, notificationDeliveryListQuerySchema, notificationDeliveryStatusSchema, notificationDocumentSourceSchema, notificationDocumentTypeSchema, notificationReminderRuleListQuerySchema, notificationReminderRunDeliverySummarySchema, notificationReminderRunLinksSchema, notificationReminderRunListQuerySchema, notificationReminderRunListResponseSchema, notificationReminderRunRecordSchema, notificationReminderRunRuleSummarySchema, notificationReminderRunStatusSchema, notificationReminderStatusSchema, notificationReminderTargetTypeSchema, notificationTargetTypeSchema, notificationTemplateListQuerySchema, notificationTemplateStatusSchema, previewNotificationTemplateResultSchema, previewNotificationTemplateSchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
|
|
24
27
|
export declare function createNotificationsHonoModule(options?: NotificationsRoutesOptions): HonoModule;
|
|
25
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAA;AAClF,OAAO,EACL,kCAAkC,EAClC,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,0BAA0B,CAAA;AACjC,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,YAAY,EACV,WAAW,EACX,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,YAAY,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,yCAAyC,GAC1C,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,EACzB,iCAAiC,EACjC,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,mBAAmB,EACnB,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,EACL,sCAAsC,EACtC,yBAAyB,EACzB,iBAAiB,EACjB,oBAAoB,EACpB,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,iCAAiC,EACjC,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,mCAAmC,EAAE,MAAM,gCAAgC,CAAA;AACpF,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,8BAA8B,EAC9B,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAA;AAClG,YAAY,EACV,yBAAyB,EACzB,oCAAoC,EACpC,sCAAsC,EACtC,gCAAgC,GACjC,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,0BAA0B,EAC1B,mCAAmC,GACpC,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,oCAAoC,EACpC,gCAAgC,EAChC,4BAA4B,EAC5B,yBAAyB,EACzB,mCAAmC,EACnC,gCAAgC,EAChC,gCAAgC,EAChC,8BAA8B,EAC9B,uCAAuC,EACvC,4CAA4C,EAC5C,kCAAkC,EAClC,sCAAsC,EACtC,yCAAyC,EACzC,mCAAmC,EACnC,wCAAwC,EACxC,mCAAmC,EACnC,gCAAgC,EAChC,oCAAoC,EACpC,4BAA4B,EAC5B,mCAAmC,EACnC,gCAAgC,EAChC,uCAAuC,EACvC,iCAAiC,EACjC,qBAAqB,EACrB,4CAA4C,EAC5C,sCAAsC,EACtC,6BAA6B,EAC7B,sBAAsB,EACtB,oCAAoC,EACpC,oCAAoC,EACpC,gCAAgC,GACjC,MAAM,iBAAiB,CAAA;AAExB,wBAAgB,6BAA6B,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,UAAU,CAkB9F"}
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, } from "./routes.js";
|
|
2
2
|
import { notificationsModule } from "./schema.js";
|
|
3
|
+
export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
|
|
3
4
|
export { createDefaultNotificationProviders, createResendProviderFromEnv, createTwilioProviderFromEnv, } from "./provider-resolution.js";
|
|
4
5
|
export { createLocalProvider } from "./providers/local.js";
|
|
5
6
|
export { createResendProvider } from "./providers/resend.js";
|
|
6
7
|
export { createTwilioProvider } from "./providers/twilio.js";
|
|
7
8
|
export { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, } from "./routes.js";
|
|
8
9
|
export { notificationChannelEnum, notificationDeliveries, notificationDeliveryStatusEnum, notificationReminderRules, notificationReminderRunStatusEnum, notificationReminderRuns, notificationReminderStatusEnum, notificationReminderTargetTypeEnum, notificationsModule, notificationTargetTypeEnum, notificationTemplateStatusEnum, notificationTemplates, } from "./schema.js";
|
|
9
|
-
export { createDefaultBookingDocumentAttachment, createNotificationService, NotificationError, notificationsService, renderNotificationTemplate, } from "./service.js";
|
|
10
|
+
export { createDefaultBookingDocumentAttachment, createNotificationService, NotificationError, notificationsService, previewNotificationTemplate, renderNotificationTemplate, } from "./service.js";
|
|
10
11
|
export { bookingDocumentNotificationsService } from "./service-booking-documents.js";
|
|
11
12
|
export { buildNotificationTaskRuntime } from "./task-runtime.js";
|
|
12
13
|
export { deliverQueuedNotificationReminder, sendDueNotificationReminders } from "./tasks/index.js";
|
|
13
|
-
export {
|
|
14
|
+
export { notificationLiquidSnippets, notificationTemplateVariableCatalog, } from "./template-authoring.js";
|
|
15
|
+
export { bookingDocumentBundleItemSchema, bookingDocumentBundleSchema, insertNotificationReminderRuleSchema, insertNotificationTemplateSchema, notificationAttachmentSchema, notificationChannelSchema, notificationDeliveryListQuerySchema, notificationDeliveryStatusSchema, notificationDocumentSourceSchema, notificationDocumentTypeSchema, notificationReminderRuleListQuerySchema, notificationReminderRunDeliverySummarySchema, notificationReminderRunLinksSchema, notificationReminderRunListQuerySchema, notificationReminderRunListResponseSchema, notificationReminderRunRecordSchema, notificationReminderRunRuleSummarySchema, notificationReminderRunStatusSchema, notificationReminderStatusSchema, notificationReminderTargetTypeSchema, notificationTargetTypeSchema, notificationTemplateListQuerySchema, notificationTemplateStatusSchema, previewNotificationTemplateResultSchema, previewNotificationTemplateSchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
|
|
14
16
|
export function createNotificationsHonoModule(options) {
|
|
17
|
+
const routes = createNotificationsRoutes(options);
|
|
15
18
|
const module = {
|
|
16
19
|
...notificationsModule,
|
|
17
20
|
bootstrap: ({ bindings, container }) => {
|
|
@@ -20,6 +23,7 @@ export function createNotificationsHonoModule(options) {
|
|
|
20
23
|
};
|
|
21
24
|
return {
|
|
22
25
|
module,
|
|
23
|
-
|
|
26
|
+
adminRoutes: routes,
|
|
27
|
+
routes,
|
|
24
28
|
};
|
|
25
29
|
}
|
package/dist/liquid.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Liquid } from "liquidjs";
|
|
2
|
+
declare const engine: Liquid;
|
|
3
|
+
export declare function renderLiquidTemplate(template: string | null | undefined, data: Record<string, unknown>): string | null;
|
|
4
|
+
export { engine as notificationLiquidEngine };
|
|
5
|
+
//# sourceMappingURL=liquid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liquid.d.ts","sourceRoot":"","sources":["../src/liquid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,QAAA,MAAM,MAAM,QAOV,CAAA;AAqIF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAiBf;AAED,OAAO,EAAE,MAAM,IAAI,wBAAwB,EAAE,CAAA"}
|
package/dist/liquid.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Liquid } from "liquidjs";
|
|
2
|
+
const engine = new Liquid({
|
|
3
|
+
strictFilters: false,
|
|
4
|
+
strictVariables: false,
|
|
5
|
+
trimTagLeft: false,
|
|
6
|
+
trimTagRight: false,
|
|
7
|
+
greedy: false,
|
|
8
|
+
jsTruthy: true,
|
|
9
|
+
});
|
|
10
|
+
engine.registerFilter("json", (value) => JSON.stringify(value ?? null));
|
|
11
|
+
engine.registerFilter("currency", (value, currency = "EUR", locale = "en-US") => {
|
|
12
|
+
const num = typeof value === "number" ? value : Number.parseFloat(String(value));
|
|
13
|
+
if (Number.isNaN(num))
|
|
14
|
+
return String(value ?? "");
|
|
15
|
+
return new Intl.NumberFormat(String(locale), {
|
|
16
|
+
style: "currency",
|
|
17
|
+
currency: String(currency || "EUR"),
|
|
18
|
+
}).format(num);
|
|
19
|
+
});
|
|
20
|
+
engine.registerFilter("date_format", (value, _format, locale = "en-US") => {
|
|
21
|
+
if (!value)
|
|
22
|
+
return "";
|
|
23
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
24
|
+
if (Number.isNaN(date.getTime()))
|
|
25
|
+
return String(value);
|
|
26
|
+
return date.toLocaleDateString(String(locale), {
|
|
27
|
+
year: "numeric",
|
|
28
|
+
month: "long",
|
|
29
|
+
day: "numeric",
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
engine.registerFilter("phone", (value) => {
|
|
33
|
+
if (!value)
|
|
34
|
+
return "";
|
|
35
|
+
const phone = String(value).replace(/\D/g, "");
|
|
36
|
+
if (phone.length === 10) {
|
|
37
|
+
return `(${phone.slice(0, 3)}) ${phone.slice(3, 6)}-${phone.slice(6)}`;
|
|
38
|
+
}
|
|
39
|
+
if (phone.length === 11 && phone.startsWith("1")) {
|
|
40
|
+
return `+1 (${phone.slice(1, 4)}) ${phone.slice(4, 7)}-${phone.slice(7)}`;
|
|
41
|
+
}
|
|
42
|
+
if (phone.length > 10) {
|
|
43
|
+
return `+${phone.slice(0, -9)} ${phone.slice(-9, -6)} ${phone.slice(-6, -3)} ${phone.slice(-3)}`;
|
|
44
|
+
}
|
|
45
|
+
return String(value);
|
|
46
|
+
});
|
|
47
|
+
engine.registerFilter("default", (value, defaultValue) => {
|
|
48
|
+
if (value === null || value === undefined || value === "")
|
|
49
|
+
return defaultValue;
|
|
50
|
+
return value;
|
|
51
|
+
});
|
|
52
|
+
engine.registerFilter("pluralize", (count, singular, plural) => {
|
|
53
|
+
const num = typeof count === "number" ? count : Number.parseInt(String(count), 10);
|
|
54
|
+
return num === 1 ? singular : plural;
|
|
55
|
+
});
|
|
56
|
+
function toSnakeCase(str) {
|
|
57
|
+
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
58
|
+
}
|
|
59
|
+
function normalizeKeys(obj) {
|
|
60
|
+
const result = {};
|
|
61
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
62
|
+
result[key] =
|
|
63
|
+
value && typeof value === "object" && !Array.isArray(value)
|
|
64
|
+
? normalizeKeys(value)
|
|
65
|
+
: value;
|
|
66
|
+
const snakeKey = toSnakeCase(key);
|
|
67
|
+
if (snakeKey !== key) {
|
|
68
|
+
result[snakeKey] = result[key];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
function decodeHtmlEntities(str) {
|
|
74
|
+
return str
|
|
75
|
+
.replace(/"/g, '"')
|
|
76
|
+
.replace(/'/g, "'")
|
|
77
|
+
.replace(/&/g, "&")
|
|
78
|
+
.replace(/</g, "<")
|
|
79
|
+
.replace(/>/g, ">");
|
|
80
|
+
}
|
|
81
|
+
function healBrokenTags(html) {
|
|
82
|
+
html = html.replace(/\{\{([\s\S]{1,300}?)\}\}/g, (match) => {
|
|
83
|
+
let healed = match;
|
|
84
|
+
if (/</.test(healed))
|
|
85
|
+
healed = healed.replace(/<[^>]+>/g, "").replace(/\s+/g, " ");
|
|
86
|
+
if (/&\w+;/.test(healed))
|
|
87
|
+
healed = decodeHtmlEntities(healed);
|
|
88
|
+
return healed;
|
|
89
|
+
});
|
|
90
|
+
html = html.replace(/\{%([\s\S]{1,300}?)%\}/g, (match) => {
|
|
91
|
+
let healed = match;
|
|
92
|
+
if (/</.test(healed))
|
|
93
|
+
healed = healed.replace(/<[^>]+>/g, "").replace(/\s+/g, " ");
|
|
94
|
+
if (/&\w+;/.test(healed))
|
|
95
|
+
healed = decodeHtmlEntities(healed);
|
|
96
|
+
return healed;
|
|
97
|
+
});
|
|
98
|
+
return html;
|
|
99
|
+
}
|
|
100
|
+
function healSyntax(template) {
|
|
101
|
+
let result = healBrokenTags(template);
|
|
102
|
+
result = result.replace(/\{%[-\s]*for\s+(\w+)\s*[-]?%\}/gi, (match, collection) => {
|
|
103
|
+
if (/\bfor\s+\w+\s+in\s+/i.test(match))
|
|
104
|
+
return match;
|
|
105
|
+
const singular = collection.endsWith("ies")
|
|
106
|
+
? `${collection.slice(0, -3)}y`
|
|
107
|
+
: collection.endsWith("s")
|
|
108
|
+
? collection.slice(0, -1)
|
|
109
|
+
: `${collection}_item`;
|
|
110
|
+
return `{% for ${singular} in ${collection} %}`;
|
|
111
|
+
});
|
|
112
|
+
result = result.replace(/\{%[-\s]*(endfor|endif|else|endunless|endcase|endcapture|endraw)\s*[-]?%\}/gi, (_match, tag) => `{% ${tag.toLowerCase()} %}`);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
function regexFallback(template, data) {
|
|
116
|
+
function resolve(obj, path) {
|
|
117
|
+
const parts = path.split(".");
|
|
118
|
+
let cur = obj;
|
|
119
|
+
for (const p of parts) {
|
|
120
|
+
if (cur == null || typeof cur !== "object")
|
|
121
|
+
return undefined;
|
|
122
|
+
cur = cur[p];
|
|
123
|
+
}
|
|
124
|
+
return cur;
|
|
125
|
+
}
|
|
126
|
+
let result = template;
|
|
127
|
+
result = result.replace(/\{\{\s*([^}|]+?)(?:\s*\|[^}]*)?\s*\}\}/g, (_match, rawPath) => {
|
|
128
|
+
const path = rawPath.trim();
|
|
129
|
+
const value = resolve(data, path);
|
|
130
|
+
if (value !== undefined && value !== null)
|
|
131
|
+
return String(value);
|
|
132
|
+
return _match;
|
|
133
|
+
});
|
|
134
|
+
result = result.replace(/\{%[\s\S]*?%\}/g, "");
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
export function renderLiquidTemplate(template, data) {
|
|
138
|
+
if (!template)
|
|
139
|
+
return null;
|
|
140
|
+
const normalized = normalizeKeys(data);
|
|
141
|
+
const healed = healSyntax(template);
|
|
142
|
+
try {
|
|
143
|
+
return engine.parseAndRenderSync(healed, normalized);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error("[notifications:liquid] template parsing failed, falling back to regex", error);
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
return regexFallback(healed, normalized);
|
|
150
|
+
}
|
|
151
|
+
catch (fallbackError) {
|
|
152
|
+
console.error("[notifications:liquid] regex fallback failed", fallbackError);
|
|
153
|
+
return template;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export { engine as notificationLiquidEngine };
|
package/dist/routes.d.ts
CHANGED
|
@@ -170,6 +170,24 @@ export declare function createNotificationsRoutes(options?: NotificationsRoutesO
|
|
|
170
170
|
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
171
171
|
};
|
|
172
172
|
};
|
|
173
|
+
} & {
|
|
174
|
+
"/preview": {
|
|
175
|
+
$post: {
|
|
176
|
+
input: {};
|
|
177
|
+
output: {
|
|
178
|
+
data: {
|
|
179
|
+
channel: "email" | "sms";
|
|
180
|
+
provider: string | null;
|
|
181
|
+
fromAddress: string | null;
|
|
182
|
+
subject: string | null;
|
|
183
|
+
html: string | null;
|
|
184
|
+
text: string | null;
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
outputFormat: "json";
|
|
188
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
173
191
|
} & {
|
|
174
192
|
"/deliveries": {
|
|
175
193
|
$get: {
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAIjE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAA;AACvF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAIjE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAA;AACvF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAqBtD,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC/C,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC7F,0BAA0B,CAAC,EAAE,iCAAiC,CAAA;IAC9D,iCAAiC,CAAC,EAAE,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,iCAAiC,GAAG,SAAS,CAAA;IAClD,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,GAAG,SAAS,CAAA;CAC9E,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC9C,0BAA0B,CAAC,EAAE,iCAAiC,CAAA;IAC9D,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB,CAAA;AAED,eAAO,MAAM,yCAAyC,oCAAoC,CAAA;AAE1F,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,CAAC,EAAE,0BAA0B,GACnC,yBAAyB,CAO3B;AAcD,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgM7E"}
|
package/dist/routes.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseJsonBody, parseOptionalJsonBody, parseQuery } from "@voyantjs/hono";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { createNotificationService, notificationsService } from "./service.js";
|
|
4
|
-
import { bookingDocumentBundleSchema, insertNotificationReminderRuleSchema, insertNotificationTemplateSchema, notificationDeliveryListQuerySchema, notificationReminderRuleListQuerySchema, notificationReminderRunListQuerySchema, notificationTemplateListQuerySchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
|
|
4
|
+
import { bookingDocumentBundleSchema, insertNotificationReminderRuleSchema, insertNotificationTemplateSchema, notificationDeliveryListQuerySchema, notificationReminderRuleListQuerySchema, notificationReminderRunListQuerySchema, notificationTemplateListQuerySchema, previewNotificationTemplateResultSchema, previewNotificationTemplateSchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
|
|
5
5
|
export const NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY = "providers.notifications.runtime";
|
|
6
6
|
export function buildNotificationsRouteRuntime(bindings, options) {
|
|
7
7
|
return {
|
|
@@ -39,6 +39,10 @@ export function createNotificationsRoutes(options) {
|
|
|
39
39
|
if (!row)
|
|
40
40
|
return c.json({ error: "Notification template not found" }, 404);
|
|
41
41
|
return c.json({ data: row });
|
|
42
|
+
})
|
|
43
|
+
.post("/preview", async (c) => {
|
|
44
|
+
const rendered = notificationsService.previewNotificationTemplate(await parseJsonBody(c, previewNotificationTemplateSchema));
|
|
45
|
+
return c.json({ data: previewNotificationTemplateResultSchema.parse(rendered) });
|
|
42
46
|
})
|
|
43
47
|
.get("/deliveries", async (c) => {
|
|
44
48
|
const query = parseQuery(c, notificationDeliveryListQuerySchema);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-booking-documents.d.ts","sourceRoot":"","sources":["../src/service-booking-documents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAI9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACnB,qCAAqC,EACtC,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"service-booking-documents.d.ts","sourceRoot":"","sources":["../src/service-booking-documents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAI9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACnB,qCAAqC,EACtC,MAAM,qBAAqB,CAAA;AAM5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAExD,MAAM,MAAM,iCAAiC,GAAG,CAC9C,QAAQ,EAAE,yBAAyB,KAChC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;AAE3C,MAAM,WAAW,kCAAkC;IACjD,kBAAkB,CAAC,EAAE,iCAAiC,CAAA;IACtD,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AA2BD,iBAAS,mCAAmC,CAC1C,QAAQ,EAAE,yBAAyB,GAClC,sBAAsB,GAAG,IAAI,CAU/B;AAwLD,eAAO,MAAM,mCAAmC;kCACV,kBAAkB,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;yCAkBnE,kBAAkB,cACV,mBAAmB,aACpB,MAAM,SACV,qCAAqC,YACnC,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmH9C,CAAA;AAED,OAAO,EAAE,mCAAmC,IAAI,sCAAsC,EAAE,CAAA"}
|
|
@@ -3,7 +3,7 @@ import { invoiceRenditions, invoices } from "@voyantjs/finance/schema";
|
|
|
3
3
|
import { contractAttachments, contracts } from "@voyantjs/legal/contracts";
|
|
4
4
|
import { and, desc, eq, ne, or } from "drizzle-orm";
|
|
5
5
|
import { sendNotification } from "./service-deliveries.js";
|
|
6
|
-
import { listBookingNotificationParticipants, resolveReminderRecipient } from "./service-shared.js";
|
|
6
|
+
import { listBookingNotificationItems, listBookingNotificationParticipants, resolveReminderRecipient, } from "./service-shared.js";
|
|
7
7
|
function getMetadataRecord(value) {
|
|
8
8
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
9
9
|
return null;
|
|
@@ -191,8 +191,11 @@ export const bookingDocumentNotificationsService = {
|
|
|
191
191
|
if (documents.length === 0) {
|
|
192
192
|
return { status: "no_documents" };
|
|
193
193
|
}
|
|
194
|
-
const participants = await
|
|
195
|
-
|
|
194
|
+
const [participants, items] = await Promise.all([
|
|
195
|
+
listBookingNotificationParticipants(db, bookingId),
|
|
196
|
+
listBookingNotificationItems(db, bookingId),
|
|
197
|
+
]);
|
|
198
|
+
const recipient = resolveReminderRecipient(booking, participants);
|
|
196
199
|
const to = input.to ?? recipient?.email ?? null;
|
|
197
200
|
if (!to) {
|
|
198
201
|
return { status: "no_recipient" };
|
|
@@ -225,14 +228,18 @@ export const bookingDocumentNotificationsService = {
|
|
|
225
228
|
startDate: booking.startDate,
|
|
226
229
|
endDate: booking.endDate,
|
|
227
230
|
},
|
|
228
|
-
|
|
231
|
+
traveler: recipient
|
|
229
232
|
? {
|
|
230
233
|
firstName: recipient.firstName,
|
|
231
234
|
lastName: recipient.lastName,
|
|
232
235
|
email: recipient.email,
|
|
236
|
+
participantType: recipient.participantType,
|
|
237
|
+
isPrimary: recipient.isPrimary,
|
|
233
238
|
}
|
|
234
239
|
: null,
|
|
240
|
+
travelers: participants,
|
|
235
241
|
documents,
|
|
242
|
+
items,
|
|
236
243
|
...(input.data ?? {}),
|
|
237
244
|
},
|
|
238
245
|
targetType: "booking",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-deliveries.d.ts","sourceRoot":"","sources":["../src/service-deliveries.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,6BAA6B,EAC7B,mBAAmB,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,mCAAmC,EACpC,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"service-deliveries.d.ts","sourceRoot":"","sources":["../src/service-deliveries.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,6BAA6B,EAC7B,mBAAmB,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,mCAAmC,EACpC,MAAM,qBAAqB,CAAA;AA0C5B,wBAAsB,cAAc,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgChG;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAOvE;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,KAAK,EAAE,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA8H7B;AAED,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAuG3C;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAqGpC"}
|
|
@@ -2,7 +2,7 @@ import { bookings } from "@voyantjs/bookings/schema";
|
|
|
2
2
|
import { invoices, paymentSessions } from "@voyantjs/finance";
|
|
3
3
|
import { desc, eq, sql } from "drizzle-orm";
|
|
4
4
|
import { notificationDeliveries } from "./schema.js";
|
|
5
|
-
import { buildWhereClause, listBookingNotificationParticipants, NotificationError, paginate, renderNotificationTemplate, resolveReminderRecipient, summarizeNotificationAttachments, toTimestamp, } from "./service-shared.js";
|
|
5
|
+
import { buildWhereClause, listBookingNotificationItems, listBookingNotificationParticipants, NotificationError, paginate, renderNotificationTemplate, resolveReminderRecipient, summarizeNotificationAttachments, toTimestamp, } from "./service-shared.js";
|
|
6
6
|
import { getTemplateById, getTemplateBySlug } from "./service-templates.js";
|
|
7
7
|
function normalizeAttachments(attachments) {
|
|
8
8
|
if (!attachments || attachments.length === 0) {
|
|
@@ -194,8 +194,13 @@ export async function sendPaymentSessionNotification(db, dispatcher, sessionId,
|
|
|
194
194
|
? ((await db.select().from(invoices).where(eq(invoices.id, session.invoiceId)).limit(1))[0] ??
|
|
195
195
|
null)
|
|
196
196
|
: null;
|
|
197
|
-
const participants = booking
|
|
198
|
-
|
|
197
|
+
const [participants, items] = booking
|
|
198
|
+
? await Promise.all([
|
|
199
|
+
listBookingNotificationParticipants(db, booking.id),
|
|
200
|
+
listBookingNotificationItems(db, booking.id),
|
|
201
|
+
])
|
|
202
|
+
: [[], []];
|
|
203
|
+
const recipient = resolveReminderRecipient(booking ?? null, participants);
|
|
199
204
|
const to = input.to ?? session.payerEmail ?? recipient?.email ?? null;
|
|
200
205
|
if (!to) {
|
|
201
206
|
throw new NotificationError("No recipient available for payment session notification");
|
|
@@ -247,13 +252,17 @@ export async function sendPaymentSessionNotification(db, dispatcher, sessionId,
|
|
|
247
252
|
dueDate: invoice.dueDate,
|
|
248
253
|
}
|
|
249
254
|
: null,
|
|
250
|
-
|
|
255
|
+
traveler: recipient
|
|
251
256
|
? {
|
|
252
257
|
firstName: recipient.firstName,
|
|
253
258
|
lastName: recipient.lastName,
|
|
254
259
|
email: recipient.email,
|
|
260
|
+
participantType: recipient.participantType,
|
|
261
|
+
isPrimary: recipient.isPrimary,
|
|
255
262
|
}
|
|
256
263
|
: null,
|
|
264
|
+
travelers: participants,
|
|
265
|
+
items,
|
|
257
266
|
...(input.data ?? {}),
|
|
258
267
|
},
|
|
259
268
|
targetType: "payment_session",
|
|
@@ -277,8 +286,13 @@ export async function sendInvoiceNotification(db, dispatcher, invoiceId, input)
|
|
|
277
286
|
.from(bookings)
|
|
278
287
|
.where(eq(bookings.id, invoice.bookingId))
|
|
279
288
|
.limit(1);
|
|
280
|
-
const participants = booking
|
|
281
|
-
|
|
289
|
+
const [participants, items] = booking
|
|
290
|
+
? await Promise.all([
|
|
291
|
+
listBookingNotificationParticipants(db, booking.id),
|
|
292
|
+
listBookingNotificationItems(db, booking.id),
|
|
293
|
+
])
|
|
294
|
+
: [[], []];
|
|
295
|
+
const recipient = resolveReminderRecipient(booking ?? null, participants);
|
|
282
296
|
const [latestSession] = await db
|
|
283
297
|
.select()
|
|
284
298
|
.from(paymentSessions)
|
|
@@ -335,13 +349,17 @@ export async function sendInvoiceNotification(db, dispatcher, invoiceId, input)
|
|
|
335
349
|
currency: latestSession.currency,
|
|
336
350
|
}
|
|
337
351
|
: null,
|
|
338
|
-
|
|
352
|
+
traveler: recipient
|
|
339
353
|
? {
|
|
340
354
|
firstName: recipient.firstName,
|
|
341
355
|
lastName: recipient.lastName,
|
|
342
356
|
email: recipient.email,
|
|
357
|
+
participantType: recipient.participantType,
|
|
358
|
+
isPrimary: recipient.isPrimary,
|
|
343
359
|
}
|
|
344
360
|
: null,
|
|
361
|
+
travelers: participants,
|
|
362
|
+
items,
|
|
345
363
|
...(input.data ?? {}),
|
|
346
364
|
},
|
|
347
365
|
targetType: "invoice",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-reminders.d.ts","sourceRoot":"","sources":["../src/service-reminders.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAIjE,OAAO,KAAK,EAGV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"service-reminders.d.ts","sourceRoot":"","sources":["../src/service-reminders.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAIjE,OAAO,KAAK,EAGV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;AAW5B,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAoyBnF,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,oBAAoB,YAAK,EAChC,eAAe,EAAE,wBAAwB,gCAoF1C;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,KAAK,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;UAkDjC;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,KAAK,GAAE,oBAAyB,gCA4EjC"}
|