@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 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 participants, then render the selected notification template with finance context such as payment links, invoice balances, and booking references.
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
@@ -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":"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"}
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 { 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";
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
- routes: createNotificationsRoutes(options),
26
+ adminRoutes: routes,
27
+ routes,
24
28
  };
25
29
  }
@@ -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(/&quot;/g, '"')
76
+ .replace(/&#39;/g, "'")
77
+ .replace(/&amp;/g, "&")
78
+ .replace(/&lt;/g, "<")
79
+ .replace(/&gt;/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: {
@@ -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;AAmBtD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0L7E"}
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;AAE5B,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4G9C,CAAA;AAED,OAAO,EAAE,mCAAmC,IAAI,sCAAsC,EAAE,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 listBookingNotificationParticipants(db, bookingId);
195
- const recipient = resolveReminderRecipient(participants);
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
- participant: recipient
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;AAyC5B,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA8F3C;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,mBAAmB,EAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA4FpC"}
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 ? await listBookingNotificationParticipants(db, booking.id) : [];
198
- const recipient = resolveReminderRecipient(participants);
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
- participant: recipient
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 ? await listBookingNotificationParticipants(db, booking.id) : [];
281
- const recipient = resolveReminderRecipient(participants);
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
- participant: recipient
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;AAU5B,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAgxBnF,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"}
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"}