@voyant-travel/notifications 0.111.7
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/LICENSE +201 -0
- package/README.md +179 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/liquid.d.ts +5 -0
- package/dist/liquid.d.ts.map +1 -0
- package/dist/liquid.js +156 -0
- package/dist/providers/local.d.ts +22 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/local.js +23 -0
- package/dist/providers/voyant-cloud-email.d.ts +27 -0
- package/dist/providers/voyant-cloud-email.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-email.js +73 -0
- package/dist/providers/voyant-cloud-sms.d.ts +26 -0
- package/dist/providers/voyant-cloud-sms.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-sms.js +24 -0
- package/dist/routes.d.ts +1546 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +337 -0
- package/dist/schema.d.ts +2119 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +356 -0
- package/dist/service-booking-document-lifecycle.d.ts +99 -0
- package/dist/service-booking-document-lifecycle.d.ts.map +1 -0
- package/dist/service-booking-document-lifecycle.js +259 -0
- package/dist/service-booking-documents.d.ts +256 -0
- package/dist/service-booking-documents.d.ts.map +1 -0
- package/dist/service-booking-documents.js +323 -0
- package/dist/service-deliveries.d.ts +183 -0
- package/dist/service-deliveries.d.ts.map +1 -0
- package/dist/service-deliveries.js +413 -0
- package/dist/service-delivery-metadata.d.ts +42 -0
- package/dist/service-delivery-metadata.d.ts.map +1 -0
- package/dist/service-delivery-metadata.js +114 -0
- package/dist/service-reminder-authoring.d.ts +33 -0
- package/dist/service-reminder-authoring.d.ts.map +1 -0
- package/dist/service-reminder-authoring.js +247 -0
- package/dist/service-reminder-booking-context.d.ts +94 -0
- package/dist/service-reminder-booking-context.d.ts.map +1 -0
- package/dist/service-reminder-booking-context.js +164 -0
- package/dist/service-reminder-events.d.ts +33 -0
- package/dist/service-reminder-events.d.ts.map +1 -0
- package/dist/service-reminder-events.js +178 -0
- package/dist/service-reminder-run-state.d.ts +114 -0
- package/dist/service-reminder-run-state.d.ts.map +1 -0
- package/dist/service-reminder-run-state.js +100 -0
- package/dist/service-reminder-stage-runs.d.ts +6 -0
- package/dist/service-reminder-stage-runs.d.ts.map +1 -0
- package/dist/service-reminder-stage-runs.js +310 -0
- package/dist/service-reminders.d.ts +30 -0
- package/dist/service-reminders.d.ts.map +1 -0
- package/dist/service-reminders.js +189 -0
- package/dist/service-sequence-targets.d.ts +50 -0
- package/dist/service-sequence-targets.d.ts.map +1 -0
- package/dist/service-sequence-targets.js +136 -0
- package/dist/service-sequence.d.ts +68 -0
- package/dist/service-sequence.d.ts.map +1 -0
- package/dist/service-sequence.js +316 -0
- package/dist/service-shared.d.ts +107 -0
- package/dist/service-shared.d.ts.map +1 -0
- package/dist/service-shared.js +159 -0
- package/dist/service-stages.d.ts +23 -0
- package/dist/service-stages.d.ts.map +1 -0
- package/dist/service-stages.js +203 -0
- package/dist/service-template-data.d.ts +19 -0
- package/dist/service-template-data.d.ts.map +1 -0
- package/dist/service-template-data.js +278 -0
- package/dist/service-templates.d.ts +260 -0
- package/dist/service-templates.d.ts.map +1 -0
- package/dist/service-templates.js +293 -0
- package/dist/service.d.ts +273 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +51 -0
- package/dist/task-runtime.d.ts +19 -0
- package/dist/task-runtime.d.ts.map +1 -0
- package/dist/task-runtime.js +11 -0
- package/dist/tasks/deliver-reminder.d.ts +9 -0
- package/dist/tasks/deliver-reminder.d.ts.map +1 -0
- package/dist/tasks/deliver-reminder.js +12 -0
- package/dist/tasks/index.d.ts +3 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +2 -0
- package/dist/tasks/send-due-reminders.d.ts +7 -0
- package/dist/tasks/send-due-reminders.d.ts.map +1 -0
- package/dist/tasks/send-due-reminders.js +31 -0
- 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/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/validation.d.ts +1093 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +451 -0
- package/package.json +102 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
// agent-quality: file-size exception -- owner: notifications; existing schema contract stays co-located until a dedicated split preserves behavior and tests.
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export const notificationChannelSchema = z.enum(["email", "sms"]);
|
|
4
|
+
export const notificationTemplateStatusSchema = z.enum(["draft", "active", "archived"]);
|
|
5
|
+
export const notificationDeliveryStatusSchema = z.enum(["pending", "sent", "failed", "cancelled"]);
|
|
6
|
+
export const notificationTargetTypeSchema = z.enum([
|
|
7
|
+
"booking",
|
|
8
|
+
"booking_payment_schedule",
|
|
9
|
+
"booking_guarantee",
|
|
10
|
+
"invoice",
|
|
11
|
+
"payment_session",
|
|
12
|
+
"person",
|
|
13
|
+
"organization",
|
|
14
|
+
"other",
|
|
15
|
+
]);
|
|
16
|
+
export const notificationReminderStatusSchema = z.enum(["draft", "active", "archived"]);
|
|
17
|
+
export const notificationReminderTargetTypeSchema = z.enum([
|
|
18
|
+
"booking_confirmed",
|
|
19
|
+
"booking_payment_schedule",
|
|
20
|
+
"payment_complete",
|
|
21
|
+
"booking_cancelled_non_payment",
|
|
22
|
+
"invoice",
|
|
23
|
+
]);
|
|
24
|
+
export const notificationReminderRunStatusSchema = z.enum([
|
|
25
|
+
"queued",
|
|
26
|
+
"processing",
|
|
27
|
+
"sent",
|
|
28
|
+
"skipped",
|
|
29
|
+
"failed",
|
|
30
|
+
]);
|
|
31
|
+
export const notificationReminderStageAnchorSchema = z.enum([
|
|
32
|
+
"due_date",
|
|
33
|
+
"booking_created_at",
|
|
34
|
+
"departure_date",
|
|
35
|
+
"invoice_issued_at",
|
|
36
|
+
"last_send_at",
|
|
37
|
+
]);
|
|
38
|
+
export const notificationReminderStageCadenceKindSchema = z.enum([
|
|
39
|
+
"once",
|
|
40
|
+
"every_n_days",
|
|
41
|
+
"escalating",
|
|
42
|
+
]);
|
|
43
|
+
export const notificationStageRecipientKindSchema = z.enum(["primary", "cc", "bcc"]);
|
|
44
|
+
export const notificationReminderStageCadenceIntervalSchema = z.object({
|
|
45
|
+
whenDaysUntilDueGT: z.coerce.number().int().optional().nullable(),
|
|
46
|
+
whenDaysUntilDueLT: z.coerce.number().int().optional().nullable(),
|
|
47
|
+
repeatEveryDays: z.coerce.number().int().min(1).max(365),
|
|
48
|
+
});
|
|
49
|
+
export const notificationDocumentTypeSchema = z.enum([
|
|
50
|
+
"contract",
|
|
51
|
+
"invoice",
|
|
52
|
+
"proforma",
|
|
53
|
+
"brochure",
|
|
54
|
+
]);
|
|
55
|
+
export const notificationDocumentSourceSchema = z.enum(["legal", "finance", "products"]);
|
|
56
|
+
export const notificationAttachmentSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
filename: z.string().min(1).max(500),
|
|
59
|
+
contentBase64: z.string().min(1).optional().nullable(),
|
|
60
|
+
path: z.string().min(1).max(4000).optional().nullable(),
|
|
61
|
+
contentType: z.string().max(255).optional().nullable(),
|
|
62
|
+
disposition: z.enum(["attachment", "inline"]).optional().nullable(),
|
|
63
|
+
contentId: z.string().max(255).optional().nullable(),
|
|
64
|
+
})
|
|
65
|
+
.refine((value) => Boolean(value.contentBase64 || value.path), {
|
|
66
|
+
message: "contentBase64 or path is required",
|
|
67
|
+
path: ["contentBase64"],
|
|
68
|
+
});
|
|
69
|
+
const paginationSchema = z.object({
|
|
70
|
+
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
71
|
+
offset: z.coerce.number().int().min(0).default(0),
|
|
72
|
+
});
|
|
73
|
+
const notificationTemplateCoreSchema = z.object({
|
|
74
|
+
slug: z.string().min(1).max(255),
|
|
75
|
+
name: z.string().min(1).max(255),
|
|
76
|
+
channel: notificationChannelSchema,
|
|
77
|
+
provider: z.string().max(255).optional().nullable(),
|
|
78
|
+
status: notificationTemplateStatusSchema.default("draft"),
|
|
79
|
+
subjectTemplate: z.string().max(2000).optional().nullable(),
|
|
80
|
+
htmlTemplate: z.string().optional().nullable(),
|
|
81
|
+
textTemplate: z.string().optional().nullable(),
|
|
82
|
+
fromAddress: z.string().max(500).optional().nullable(),
|
|
83
|
+
isSystem: z.boolean().default(false),
|
|
84
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
85
|
+
});
|
|
86
|
+
export const insertNotificationTemplateSchema = notificationTemplateCoreSchema;
|
|
87
|
+
export const updateNotificationTemplateSchema = notificationTemplateCoreSchema.partial();
|
|
88
|
+
export const notificationTemplateListQuerySchema = paginationSchema.extend({
|
|
89
|
+
channel: notificationChannelSchema.optional(),
|
|
90
|
+
provider: z.string().optional(),
|
|
91
|
+
status: notificationTemplateStatusSchema.optional(),
|
|
92
|
+
search: z.string().optional(),
|
|
93
|
+
});
|
|
94
|
+
export const notificationDeliveryListQuerySchema = paginationSchema.extend({
|
|
95
|
+
channel: notificationChannelSchema.optional(),
|
|
96
|
+
provider: z.string().optional(),
|
|
97
|
+
status: notificationDeliveryStatusSchema.optional(),
|
|
98
|
+
templateSlug: z.string().optional(),
|
|
99
|
+
targetType: notificationTargetTypeSchema.optional(),
|
|
100
|
+
targetId: z.string().optional(),
|
|
101
|
+
bookingId: z.string().optional(),
|
|
102
|
+
invoiceId: z.string().optional(),
|
|
103
|
+
paymentSessionId: z.string().optional(),
|
|
104
|
+
personId: z.string().optional(),
|
|
105
|
+
organizationId: z.string().optional(),
|
|
106
|
+
});
|
|
107
|
+
const notificationReminderRuleCoreSchema = z.object({
|
|
108
|
+
slug: z.string().min(1).max(255),
|
|
109
|
+
name: z.string().min(1).max(255),
|
|
110
|
+
status: notificationReminderStatusSchema.default("draft"),
|
|
111
|
+
targetType: notificationReminderTargetTypeSchema,
|
|
112
|
+
channel: notificationChannelSchema,
|
|
113
|
+
provider: z.string().max(255).optional().nullable(),
|
|
114
|
+
templateId: z.string().optional().nullable(),
|
|
115
|
+
templateSlug: z.string().max(255).optional().nullable(),
|
|
116
|
+
priority: z.coerce.number().int().min(0).max(1000).default(0),
|
|
117
|
+
suppressionGroup: z.string().max(255).optional().nullable(),
|
|
118
|
+
isSystem: z.boolean().default(false),
|
|
119
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
120
|
+
});
|
|
121
|
+
// templateId / templateSlug are both optional now: stage channels carry
|
|
122
|
+
// their own templates and override the rule-level default. A rule with no
|
|
123
|
+
// template is valid as long as it has stages (or the legacy
|
|
124
|
+
// relativeDaysFromDueDate path stays unused).
|
|
125
|
+
export const insertNotificationReminderRuleSchema = notificationReminderRuleCoreSchema;
|
|
126
|
+
export const updateNotificationReminderRuleSchema = notificationReminderRuleCoreSchema.partial();
|
|
127
|
+
export const notificationReminderRuleStageBaseSchema = z.object({
|
|
128
|
+
name: z.string().max(255).optional().nullable(),
|
|
129
|
+
orderIndex: z.coerce.number().int().min(0).max(1000),
|
|
130
|
+
anchor: notificationReminderStageAnchorSchema,
|
|
131
|
+
windowStartDays: z.coerce.number().int().min(-3650).max(3650),
|
|
132
|
+
windowEndDays: z.coerce.number().int().min(-3650).max(3650),
|
|
133
|
+
cadenceKind: notificationReminderStageCadenceKindSchema,
|
|
134
|
+
cadenceEveryDays: z.coerce.number().int().min(1).max(365).optional().nullable(),
|
|
135
|
+
cadenceIntervals: z
|
|
136
|
+
.array(notificationReminderStageCadenceIntervalSchema)
|
|
137
|
+
.min(1)
|
|
138
|
+
.max(20)
|
|
139
|
+
.optional()
|
|
140
|
+
.nullable(),
|
|
141
|
+
maxSendsInStage: z.coerce.number().int().min(1).max(100).optional().nullable(),
|
|
142
|
+
respectQuietHours: z.boolean().default(true),
|
|
143
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
144
|
+
});
|
|
145
|
+
export const insertNotificationReminderRuleStageSchema = notificationReminderRuleStageBaseSchema.superRefine((value, ctx) => {
|
|
146
|
+
if (value.windowEndDays < value.windowStartDays) {
|
|
147
|
+
ctx.addIssue({
|
|
148
|
+
code: "custom",
|
|
149
|
+
path: ["windowEndDays"],
|
|
150
|
+
message: "windowEndDays must be >= windowStartDays",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (value.cadenceKind === "every_n_days" && !value.cadenceEveryDays) {
|
|
154
|
+
ctx.addIssue({
|
|
155
|
+
code: "custom",
|
|
156
|
+
path: ["cadenceEveryDays"],
|
|
157
|
+
message: "cadenceEveryDays is required when cadenceKind=every_n_days",
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (value.cadenceKind === "escalating" &&
|
|
161
|
+
(!value.cadenceIntervals || value.cadenceIntervals.length === 0)) {
|
|
162
|
+
ctx.addIssue({
|
|
163
|
+
code: "custom",
|
|
164
|
+
path: ["cadenceIntervals"],
|
|
165
|
+
message: "cadenceIntervals is required when cadenceKind=escalating",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
export const updateNotificationReminderRuleStageSchema = notificationReminderRuleStageBaseSchema.partial();
|
|
170
|
+
export const reorderReminderRuleStagesSchema = z.object({
|
|
171
|
+
stageIds: z.array(z.string().min(1)).min(1).max(50),
|
|
172
|
+
});
|
|
173
|
+
export const notificationReminderStageChannelBaseSchema = z.object({
|
|
174
|
+
orderIndex: z.coerce.number().int().min(0).max(50).default(0),
|
|
175
|
+
channel: notificationChannelSchema,
|
|
176
|
+
provider: z.string().max(255).optional().nullable(),
|
|
177
|
+
templateId: z.string().optional().nullable(),
|
|
178
|
+
templateSlug: z.string().max(255).optional().nullable(),
|
|
179
|
+
recipientKind: notificationStageRecipientKindSchema.default("primary"),
|
|
180
|
+
recipientRole: z.string().max(255).optional().nullable(),
|
|
181
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
182
|
+
});
|
|
183
|
+
export const insertNotificationReminderStageChannelSchema = notificationReminderStageChannelBaseSchema.refine((value) => Boolean(value.templateId || value.templateSlug), {
|
|
184
|
+
message: "templateId or templateSlug is required",
|
|
185
|
+
path: ["templateId"],
|
|
186
|
+
});
|
|
187
|
+
export const updateNotificationReminderStageChannelSchema = notificationReminderStageChannelBaseSchema.partial();
|
|
188
|
+
export const composeNotificationReminderRuleStageSchema = notificationReminderRuleStageBaseSchema.extend({
|
|
189
|
+
channels: z.array(notificationReminderStageChannelBaseSchema).min(1).max(50),
|
|
190
|
+
});
|
|
191
|
+
export const composeNotificationReminderRuleSchema = z.object({
|
|
192
|
+
rule: insertNotificationReminderRuleSchema,
|
|
193
|
+
stages: z.array(composeNotificationReminderRuleStageSchema).min(1).max(50),
|
|
194
|
+
idempotencyKey: z.string().min(1).max(255).optional(),
|
|
195
|
+
});
|
|
196
|
+
const notificationQuietHoursConfigSchema = z.object({
|
|
197
|
+
start: z.string().regex(/^\d{2}:\d{2}$/),
|
|
198
|
+
end: z.string().regex(/^\d{2}:\d{2}$/),
|
|
199
|
+
tz: z.string().min(1).max(255),
|
|
200
|
+
});
|
|
201
|
+
const notificationSettingsCoreSchema = z.object({
|
|
202
|
+
scope: z.string().min(1).max(64).default("default"),
|
|
203
|
+
quietHoursLocal: notificationQuietHoursConfigSchema.nullable().optional(),
|
|
204
|
+
blackoutDates: z
|
|
205
|
+
.array(z.string().regex(/^\d{4}-\d{2}-\d{2}$/))
|
|
206
|
+
.max(366)
|
|
207
|
+
.nullable()
|
|
208
|
+
.optional(),
|
|
209
|
+
skipWeekends: z.boolean().default(false),
|
|
210
|
+
recipientRateLimitPerDay: z.coerce.number().int().min(1).max(10000).nullable().optional(),
|
|
211
|
+
suppressionWindowHours: z.coerce.number().int().min(0).max(720).default(24),
|
|
212
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
213
|
+
});
|
|
214
|
+
export const updateNotificationSettingsSchema = notificationSettingsCoreSchema.partial();
|
|
215
|
+
export const previewRemindersQuerySchema = z.object({
|
|
216
|
+
date: z
|
|
217
|
+
.string()
|
|
218
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
219
|
+
.optional(),
|
|
220
|
+
ruleId: z.string().optional(),
|
|
221
|
+
targetId: z.string().optional(),
|
|
222
|
+
});
|
|
223
|
+
export const notificationReminderRuleListQuerySchema = paginationSchema.extend({
|
|
224
|
+
status: notificationReminderStatusSchema.optional(),
|
|
225
|
+
targetType: notificationReminderTargetTypeSchema.optional(),
|
|
226
|
+
channel: notificationChannelSchema.optional(),
|
|
227
|
+
search: z.string().optional(),
|
|
228
|
+
});
|
|
229
|
+
export const notificationReminderRunListQuerySchema = paginationSchema.extend({
|
|
230
|
+
reminderRuleId: z.string().optional(),
|
|
231
|
+
targetType: notificationReminderTargetTypeSchema.optional(),
|
|
232
|
+
targetId: z.string().optional(),
|
|
233
|
+
scheduleId: z.string().optional(),
|
|
234
|
+
invoiceId: z.string().optional(),
|
|
235
|
+
bookingId: z.string().optional(),
|
|
236
|
+
paymentSessionId: z.string().optional(),
|
|
237
|
+
notificationDeliveryId: z.string().optional(),
|
|
238
|
+
personId: z.string().optional(),
|
|
239
|
+
organizationId: z.string().optional(),
|
|
240
|
+
recipient: z.string().optional(),
|
|
241
|
+
status: notificationReminderRunStatusSchema.optional(),
|
|
242
|
+
});
|
|
243
|
+
export const notificationReminderRunRuleSummarySchema = z.object({
|
|
244
|
+
id: z.string(),
|
|
245
|
+
slug: z.string(),
|
|
246
|
+
name: z.string(),
|
|
247
|
+
status: notificationReminderStatusSchema,
|
|
248
|
+
targetType: notificationReminderTargetTypeSchema,
|
|
249
|
+
channel: notificationChannelSchema,
|
|
250
|
+
provider: z.string().nullable(),
|
|
251
|
+
templateId: z.string().nullable(),
|
|
252
|
+
templateSlug: z.string().nullable(),
|
|
253
|
+
});
|
|
254
|
+
export const notificationReminderRunDeliverySummarySchema = z.object({
|
|
255
|
+
id: z.string(),
|
|
256
|
+
status: notificationDeliveryStatusSchema,
|
|
257
|
+
channel: notificationChannelSchema,
|
|
258
|
+
provider: z.string(),
|
|
259
|
+
toAddress: z.string(),
|
|
260
|
+
subject: z.string().nullable(),
|
|
261
|
+
sentAt: z.string().nullable(),
|
|
262
|
+
failedAt: z.string().nullable(),
|
|
263
|
+
errorMessage: z.string().nullable(),
|
|
264
|
+
});
|
|
265
|
+
export const notificationReminderRunLinksSchema = z.object({
|
|
266
|
+
bookingId: z.string().nullable(),
|
|
267
|
+
bookingPaymentScheduleId: z.string().nullable(),
|
|
268
|
+
invoiceId: z.string().nullable(),
|
|
269
|
+
paymentSessionId: z.string().nullable(),
|
|
270
|
+
personId: z.string().nullable(),
|
|
271
|
+
organizationId: z.string().nullable(),
|
|
272
|
+
notificationDeliveryId: z.string().nullable(),
|
|
273
|
+
});
|
|
274
|
+
export const notificationReminderRunRecordSchema = z.object({
|
|
275
|
+
id: z.string(),
|
|
276
|
+
reminderRuleId: z.string(),
|
|
277
|
+
targetType: notificationReminderTargetTypeSchema,
|
|
278
|
+
targetId: z.string(),
|
|
279
|
+
dedupeKey: z.string(),
|
|
280
|
+
status: notificationReminderRunStatusSchema,
|
|
281
|
+
recipient: z.string().nullable(),
|
|
282
|
+
scheduledFor: z.string(),
|
|
283
|
+
processedAt: z.string(),
|
|
284
|
+
errorMessage: z.string().nullable(),
|
|
285
|
+
metadata: z.record(z.string(), z.unknown()).nullable(),
|
|
286
|
+
createdAt: z.string(),
|
|
287
|
+
updatedAt: z.string(),
|
|
288
|
+
links: notificationReminderRunLinksSchema,
|
|
289
|
+
reminderRule: notificationReminderRunRuleSummarySchema,
|
|
290
|
+
delivery: notificationReminderRunDeliverySummarySchema.nullable(),
|
|
291
|
+
});
|
|
292
|
+
export const notificationReminderRunListResponseSchema = z.object({
|
|
293
|
+
data: z.array(notificationReminderRunRecordSchema),
|
|
294
|
+
total: z.number().int(),
|
|
295
|
+
limit: z.number().int(),
|
|
296
|
+
offset: z.number().int(),
|
|
297
|
+
});
|
|
298
|
+
export const runDueRemindersSchema = z.object({
|
|
299
|
+
now: z.string().datetime().optional().nullable(),
|
|
300
|
+
});
|
|
301
|
+
const transportNotificationCoreSchema = z.object({
|
|
302
|
+
templateId: z.string().optional().nullable(),
|
|
303
|
+
templateSlug: z.string().optional().nullable(),
|
|
304
|
+
channel: notificationChannelSchema.default("email"),
|
|
305
|
+
provider: z.string().optional().nullable(),
|
|
306
|
+
to: z.string().min(1).optional().nullable(),
|
|
307
|
+
from: z.string().max(500).optional().nullable(),
|
|
308
|
+
subject: z.string().max(2000).optional().nullable(),
|
|
309
|
+
html: z.string().optional().nullable(),
|
|
310
|
+
text: z.string().optional().nullable(),
|
|
311
|
+
attachments: z.array(notificationAttachmentSchema).optional().nullable(),
|
|
312
|
+
data: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
313
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
314
|
+
scheduledFor: z.string().optional().nullable(),
|
|
315
|
+
paymentLinkBaseUrl: z.string().optional().nullable(),
|
|
316
|
+
});
|
|
317
|
+
export const sendPaymentSessionNotificationSchema = transportNotificationCoreSchema.refine((value) => Boolean(value.templateId || value.templateSlug || value.subject || value.html || value.text), {
|
|
318
|
+
message: "templateId, templateSlug, or direct content is required",
|
|
319
|
+
});
|
|
320
|
+
export const sendInvoiceNotificationSchema = transportNotificationCoreSchema.refine((value) => Boolean(value.templateId || value.templateSlug || value.subject || value.html || value.text), {
|
|
321
|
+
message: "templateId, templateSlug, or direct content is required",
|
|
322
|
+
});
|
|
323
|
+
export const sendNotificationSchema = z
|
|
324
|
+
.object({
|
|
325
|
+
templateId: z.string().optional().nullable(),
|
|
326
|
+
templateSlug: z.string().optional().nullable(),
|
|
327
|
+
channel: notificationChannelSchema.optional(),
|
|
328
|
+
provider: z.string().optional().nullable(),
|
|
329
|
+
to: z.string().min(1),
|
|
330
|
+
from: z.string().max(500).optional().nullable(),
|
|
331
|
+
subject: z.string().max(2000).optional().nullable(),
|
|
332
|
+
html: z.string().optional().nullable(),
|
|
333
|
+
text: z.string().optional().nullable(),
|
|
334
|
+
attachments: z.array(notificationAttachmentSchema).optional().nullable(),
|
|
335
|
+
data: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
336
|
+
targetType: notificationTargetTypeSchema.default("other"),
|
|
337
|
+
targetId: z.string().optional().nullable(),
|
|
338
|
+
bookingId: z.string().optional().nullable(),
|
|
339
|
+
invoiceId: z.string().optional().nullable(),
|
|
340
|
+
paymentSessionId: z.string().optional().nullable(),
|
|
341
|
+
personId: z.string().optional().nullable(),
|
|
342
|
+
organizationId: z.string().optional().nullable(),
|
|
343
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
344
|
+
scheduledFor: z.string().optional().nullable(),
|
|
345
|
+
})
|
|
346
|
+
.refine((value) => Boolean(value.templateId || value.templateSlug || value.subject || value.html || value.text), {
|
|
347
|
+
message: "templateId, templateSlug, or direct content is required",
|
|
348
|
+
});
|
|
349
|
+
export const previewNotificationTemplateSchema = z
|
|
350
|
+
.object({
|
|
351
|
+
channel: notificationChannelSchema,
|
|
352
|
+
provider: z.string().optional().nullable(),
|
|
353
|
+
subjectTemplate: z.string().max(2000).optional().nullable(),
|
|
354
|
+
htmlTemplate: z.string().optional().nullable(),
|
|
355
|
+
textTemplate: z.string().optional().nullable(),
|
|
356
|
+
fromAddress: z.string().max(500).optional().nullable(),
|
|
357
|
+
data: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
358
|
+
})
|
|
359
|
+
.refine((value) => Boolean(value.subjectTemplate || value.htmlTemplate || value.textTemplate), {
|
|
360
|
+
message: "subjectTemplate, htmlTemplate, or textTemplate is required",
|
|
361
|
+
});
|
|
362
|
+
export const previewNotificationTemplateResultSchema = z.object({
|
|
363
|
+
channel: notificationChannelSchema,
|
|
364
|
+
provider: z.string().nullable(),
|
|
365
|
+
fromAddress: z.string().nullable(),
|
|
366
|
+
subject: z.string().nullable(),
|
|
367
|
+
html: z.string().nullable(),
|
|
368
|
+
text: z.string().nullable(),
|
|
369
|
+
});
|
|
370
|
+
export const bookingDocumentBundleItemSchema = z.object({
|
|
371
|
+
key: z.string().min(1),
|
|
372
|
+
source: notificationDocumentSourceSchema,
|
|
373
|
+
documentType: notificationDocumentTypeSchema,
|
|
374
|
+
bookingId: z.string().min(1),
|
|
375
|
+
contractId: z.string().optional().nullable(),
|
|
376
|
+
invoiceId: z.string().optional().nullable(),
|
|
377
|
+
attachmentId: z.string().optional().nullable(),
|
|
378
|
+
renditionId: z.string().optional().nullable(),
|
|
379
|
+
contractStatus: z.string().optional().nullable(),
|
|
380
|
+
invoiceStatus: z.string().optional().nullable(),
|
|
381
|
+
name: z.string().min(1),
|
|
382
|
+
format: z.string().optional().nullable(),
|
|
383
|
+
mimeType: z.string().optional().nullable(),
|
|
384
|
+
storageKey: z.string().optional().nullable(),
|
|
385
|
+
downloadUrl: z.string().url().optional().nullable(),
|
|
386
|
+
language: z.string().optional().nullable(),
|
|
387
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
388
|
+
createdAt: z.string().datetime(),
|
|
389
|
+
});
|
|
390
|
+
export const bookingDocumentBundleSchema = z.object({
|
|
391
|
+
bookingId: z.string().min(1),
|
|
392
|
+
documents: z.array(bookingDocumentBundleItemSchema),
|
|
393
|
+
});
|
|
394
|
+
export const sendBookingDocumentsNotificationSchema = z.object({
|
|
395
|
+
templateId: z.string().optional().nullable(),
|
|
396
|
+
templateSlug: z.string().optional().nullable(),
|
|
397
|
+
provider: z.string().optional().nullable(),
|
|
398
|
+
to: z.string().min(1).optional().nullable(),
|
|
399
|
+
from: z.string().max(500).optional().nullable(),
|
|
400
|
+
subject: z.string().max(2000).optional().nullable(),
|
|
401
|
+
html: z.string().optional().nullable(),
|
|
402
|
+
text: z.string().optional().nullable(),
|
|
403
|
+
data: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
404
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
405
|
+
scheduledFor: z.string().optional().nullable(),
|
|
406
|
+
documentTypes: z.array(notificationDocumentTypeSchema).optional().nullable(),
|
|
407
|
+
});
|
|
408
|
+
export const sendBookingDocumentsNotificationResultSchema = z.object({
|
|
409
|
+
bookingId: z.string().min(1),
|
|
410
|
+
recipient: z.string().min(1),
|
|
411
|
+
documents: z.array(bookingDocumentBundleItemSchema),
|
|
412
|
+
deliveryId: z.string().min(1),
|
|
413
|
+
provider: z.string().optional().nullable(),
|
|
414
|
+
status: notificationDeliveryStatusSchema,
|
|
415
|
+
});
|
|
416
|
+
/**
|
|
417
|
+
* Confirm-and-dispatch — single orchestrated request that lists the booking's
|
|
418
|
+
* document bundle and (optionally) sends it to the client in one round-trip.
|
|
419
|
+
*
|
|
420
|
+
* `sendNotification: false` turns the call into a preview: the bundle comes
|
|
421
|
+
* back but no delivery is attempted. Templates use the preview to render the
|
|
422
|
+
* "here's what's ready" checkbox list before the operator confirms.
|
|
423
|
+
*/
|
|
424
|
+
export const confirmAndDispatchBookingSchema = sendBookingDocumentsNotificationSchema.extend({
|
|
425
|
+
sendNotification: z.boolean().default(true),
|
|
426
|
+
});
|
|
427
|
+
export const confirmAndDispatchBookingResultSchema = z.object({
|
|
428
|
+
bookingId: z.string().min(1),
|
|
429
|
+
documents: z.array(bookingDocumentBundleItemSchema),
|
|
430
|
+
/**
|
|
431
|
+
* Non-null when `sendNotification` was true and a delivery actually went
|
|
432
|
+
* out. Null when either the operator asked for a preview only, or the send
|
|
433
|
+
* couldn't proceed (no recipient / no attachments / no matching documents).
|
|
434
|
+
*/
|
|
435
|
+
notification: z
|
|
436
|
+
.object({
|
|
437
|
+
recipient: z.string().min(1),
|
|
438
|
+
deliveryId: z.string().min(1),
|
|
439
|
+
provider: z.string().optional().nullable(),
|
|
440
|
+
status: notificationDeliveryStatusSchema,
|
|
441
|
+
})
|
|
442
|
+
.nullable(),
|
|
443
|
+
/**
|
|
444
|
+
* When `sendNotification` was true but the dispatcher declined to send,
|
|
445
|
+
* this captures which guard tripped so the UI can explain it — e.g.
|
|
446
|
+
* "No recipient on file, add an email to the lead traveler and retry".
|
|
447
|
+
*/
|
|
448
|
+
skipReason: z
|
|
449
|
+
.enum(["preview_only", "no_documents", "no_recipient", "no_attachments", "send_failed"])
|
|
450
|
+
.nullable(),
|
|
451
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voyant-travel/notifications",
|
|
3
|
+
"version": "0.111.7",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./schema": {
|
|
13
|
+
"types": "./dist/schema.d.ts",
|
|
14
|
+
"import": "./dist/schema.js",
|
|
15
|
+
"default": "./dist/schema.js"
|
|
16
|
+
},
|
|
17
|
+
"./types": {
|
|
18
|
+
"types": "./dist/types.d.ts",
|
|
19
|
+
"import": "./dist/types.js",
|
|
20
|
+
"default": "./dist/types.js"
|
|
21
|
+
},
|
|
22
|
+
"./validation": {
|
|
23
|
+
"types": "./dist/validation.d.ts",
|
|
24
|
+
"import": "./dist/validation.js",
|
|
25
|
+
"default": "./dist/validation.js"
|
|
26
|
+
},
|
|
27
|
+
"./routes": {
|
|
28
|
+
"types": "./dist/routes.d.ts",
|
|
29
|
+
"import": "./dist/routes.js",
|
|
30
|
+
"default": "./dist/routes.js"
|
|
31
|
+
},
|
|
32
|
+
"./service": {
|
|
33
|
+
"types": "./dist/service.d.ts",
|
|
34
|
+
"import": "./dist/service.js",
|
|
35
|
+
"default": "./dist/service.js"
|
|
36
|
+
},
|
|
37
|
+
"./tasks": {
|
|
38
|
+
"types": "./dist/tasks/index.d.ts",
|
|
39
|
+
"import": "./dist/tasks/index.js",
|
|
40
|
+
"default": "./dist/tasks/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./providers/local": {
|
|
43
|
+
"types": "./dist/providers/local.d.ts",
|
|
44
|
+
"import": "./dist/providers/local.js",
|
|
45
|
+
"default": "./dist/providers/local.js"
|
|
46
|
+
},
|
|
47
|
+
"./providers/voyant-cloud-email": {
|
|
48
|
+
"types": "./dist/providers/voyant-cloud-email.d.ts",
|
|
49
|
+
"import": "./dist/providers/voyant-cloud-email.js",
|
|
50
|
+
"default": "./dist/providers/voyant-cloud-email.js"
|
|
51
|
+
},
|
|
52
|
+
"./providers/voyant-cloud-sms": {
|
|
53
|
+
"types": "./dist/providers/voyant-cloud-sms.d.ts",
|
|
54
|
+
"import": "./dist/providers/voyant-cloud-sms.js",
|
|
55
|
+
"default": "./dist/providers/voyant-cloud-sms.js"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@voyant-travel/cloud-sdk": "npm:@voyantjs/cloud-sdk@^0.8.0",
|
|
60
|
+
"drizzle-orm": "^0.45.2",
|
|
61
|
+
"hono": "^4.12.10",
|
|
62
|
+
"liquidjs": "^10.26.0",
|
|
63
|
+
"zod": "^4.3.6",
|
|
64
|
+
"@voyant-travel/bookings": "^0.119.3",
|
|
65
|
+
"@voyant-travel/finance": "^0.119.5",
|
|
66
|
+
"@voyant-travel/core": "^0.109.0",
|
|
67
|
+
"@voyant-travel/db": "^0.108.0",
|
|
68
|
+
"@voyant-travel/legal": "^0.119.2",
|
|
69
|
+
"@voyant-travel/hono": "^0.109.1"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"typescript": "^6.0.2",
|
|
73
|
+
"vitest": "^4.1.2",
|
|
74
|
+
"@voyant-travel/voyant-typescript-config": "^0.1.0"
|
|
75
|
+
},
|
|
76
|
+
"files": [
|
|
77
|
+
"dist"
|
|
78
|
+
],
|
|
79
|
+
"publishConfig": {
|
|
80
|
+
"access": "public"
|
|
81
|
+
},
|
|
82
|
+
"repository": {
|
|
83
|
+
"type": "git",
|
|
84
|
+
"url": "https://github.com/voyant-travel/voyant.git",
|
|
85
|
+
"directory": "packages/notifications"
|
|
86
|
+
},
|
|
87
|
+
"voyant": {
|
|
88
|
+
"schema": "./schema",
|
|
89
|
+
"requiresSchemas": [
|
|
90
|
+
"@voyant-travel/db"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"scripts": {
|
|
94
|
+
"typecheck": "tsc --noEmit",
|
|
95
|
+
"lint": "biome check src/",
|
|
96
|
+
"test": "vitest run",
|
|
97
|
+
"build": "tsc -p tsconfig.json",
|
|
98
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
99
|
+
},
|
|
100
|
+
"main": "./dist/index.js",
|
|
101
|
+
"types": "./dist/index.d.ts"
|
|
102
|
+
}
|