@voyantjs/notifications 0.6.9 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { HonoModule } from "@voyantjs/hono/module";
2
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
3
  import { type NotificationsRoutesOptions } from "./routes.js";
3
4
  export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
4
5
  export type { DefaultNotificationProviderOptions } from "./provider-resolution.js";
@@ -24,5 +25,25 @@ export type { NotificationLiquidSnippet, NotificationTemplateVariableCategory, N
24
25
  export { notificationLiquidSnippets, notificationTemplateVariableCatalog, } from "./template-authoring.js";
25
26
  export type { NotificationAttachment, NotificationChannel, NotificationPayload, NotificationProvider, NotificationResult, } from "./types.js";
26
27
  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";
27
- export declare function createNotificationsHonoModule(options?: NotificationsRoutesOptions): HonoModule;
28
+ /**
29
+ * Auto-dispatch policy for the `booking.confirmed` subscriber. Set `enabled:
30
+ * false` (or leave the option off entirely) to opt out.
31
+ */
32
+ export interface NotificationsAutoConfirmAndDispatchOptions {
33
+ enabled?: boolean;
34
+ /** Notification template slug used when the handler fires. */
35
+ templateSlug?: string;
36
+ /** Optional allowlist of document types to attach; defaults to all. */
37
+ documentTypes?: Array<"contract" | "invoice" | "proforma">;
38
+ }
39
+ export interface CreateNotificationsHonoModuleOptions extends NotificationsRoutesOptions {
40
+ /**
41
+ * Resolves a database from runtime bindings. Required for
42
+ * `autoConfirmAndDispatch` — the `booking.confirmed` subscriber fires
43
+ * outside a request scope and needs its own db handle.
44
+ */
45
+ resolveDb?: (bindings: Record<string, unknown>) => PostgresJsDatabase;
46
+ autoConfirmAndDispatch?: NotificationsAutoConfirmAndDispatchOptions;
47
+ }
48
+ export declare function createNotificationsHonoModule(options?: CreateNotificationsHonoModuleOptions): HonoModule;
28
49
  //# 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,5 +1,7 @@
1
1
  import { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, } from "./routes.js";
2
2
  import { notificationsModule } from "./schema.js";
3
+ import { createNotificationService } from "./service.js";
4
+ import { bookingDocumentNotificationsService } from "./service-booking-documents.js";
3
5
  export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
4
6
  export { createDefaultNotificationProviders, createResendProviderFromEnv, createTwilioProviderFromEnv, } from "./provider-resolution.js";
5
7
  export { createLocalProvider } from "./providers/local.js";
@@ -17,8 +19,38 @@ export function createNotificationsHonoModule(options) {
17
19
  const routes = createNotificationsRoutes(options);
18
20
  const module = {
19
21
  ...notificationsModule,
20
- bootstrap: ({ bindings, container }) => {
22
+ bootstrap: ({ bindings, container, eventBus }) => {
21
23
  container.register(NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, buildNotificationsRouteRuntime(bindings, options));
24
+ // Auto-dispatch wiring — opt-in. When enabled, every `booking.confirmed`
25
+ // event triggers a `confirmAndDispatchBooking` call so the operator
26
+ // doesn't have to click a second button. The handler runs in the same
27
+ // process as the emitter (the in-process event bus) but outside the
28
+ // request scope, so we resolve our own db handle from bindings.
29
+ if (options?.autoConfirmAndDispatch?.enabled && options.resolveDb) {
30
+ const resolveDb = options.resolveDb;
31
+ const autoOptions = options.autoConfirmAndDispatch;
32
+ const runtime = buildNotificationsRouteRuntime(bindings, options);
33
+ const dispatcher = createNotificationService(runtime.providers);
34
+ eventBus.subscribe("booking.confirmed", async (event) => {
35
+ try {
36
+ const db = resolveDb(bindings);
37
+ await bookingDocumentNotificationsService.confirmAndDispatchBooking(db, dispatcher, event.data.bookingId, {
38
+ templateSlug: autoOptions.templateSlug ?? null,
39
+ documentTypes: autoOptions.documentTypes ?? null,
40
+ }, {
41
+ attachmentResolver: runtime.documentAttachmentResolver,
42
+ eventBus,
43
+ });
44
+ }
45
+ catch (error) {
46
+ // Per the EventBus contract, handler failures are logged, not
47
+ // rethrown. We surface the context so ops can diagnose without
48
+ // digging through stack traces.
49
+ const message = error instanceof Error ? error.message : String(error);
50
+ console.error(`[notifications] auto-dispatch failed for booking ${event.data.bookingId}: ${message}`);
51
+ }
52
+ });
53
+ }
22
54
  },
23
55
  };
24
56
  return {
package/dist/routes.d.ts CHANGED
@@ -448,7 +448,7 @@ export declare function createNotificationsRoutes(options?: NotificationsRoutesO
448
448
  targetType: "invoice" | "booking_payment_schedule";
449
449
  targetId: string;
450
450
  dedupeKey: string;
451
- status: "failed" | "sent" | "processing" | "queued" | "skipped";
451
+ status: "failed" | "sent" | "processing" | "skipped" | "queued";
452
452
  recipient: string | null;
453
453
  scheduledFor: string;
454
454
  processedAt: string;
@@ -525,7 +525,7 @@ export declare function createNotificationsRoutes(options?: NotificationsRoutesO
525
525
  targetType: "invoice" | "booking_payment_schedule";
526
526
  targetId: string;
527
527
  dedupeKey: string;
528
- status: "failed" | "sent" | "processing" | "queued" | "skipped";
528
+ status: "failed" | "sent" | "processing" | "skipped" | "queued";
529
529
  recipient: string | null;
530
530
  scheduledFor: string;
531
531
  processedAt: string;
@@ -784,6 +784,74 @@ export declare function createNotificationsRoutes(options?: NotificationsRoutesO
784
784
  status: import("hono/utils/http-status").ContentfulStatusCode;
785
785
  };
786
786
  };
787
+ } & {
788
+ "/bookings/:id/confirm-and-dispatch": {
789
+ $post: {
790
+ input: {
791
+ param: {
792
+ id: string;
793
+ };
794
+ };
795
+ output: {
796
+ error: string;
797
+ };
798
+ outputFormat: "json";
799
+ status: 404;
800
+ } | {
801
+ input: {
802
+ param: {
803
+ id: string;
804
+ };
805
+ };
806
+ output: {
807
+ data: {
808
+ bookingId: string;
809
+ documents: {
810
+ key: string;
811
+ source: "finance" | "legal";
812
+ documentType: "invoice" | "proforma" | "contract";
813
+ bookingId: string;
814
+ name: string;
815
+ createdAt: string;
816
+ contractId?: string | null | undefined;
817
+ invoiceId?: string | null | undefined;
818
+ attachmentId?: string | null | undefined;
819
+ renditionId?: string | null | undefined;
820
+ contractStatus?: string | null | undefined;
821
+ invoiceStatus?: string | null | undefined;
822
+ format?: string | null | undefined;
823
+ mimeType?: string | null | undefined;
824
+ storageKey?: string | null | undefined;
825
+ downloadUrl?: string | null | undefined;
826
+ language?: string | null | undefined;
827
+ metadata?: {
828
+ [x: string]: import("hono/utils/types").JSONValue;
829
+ } | null | undefined;
830
+ }[];
831
+ notification: {
832
+ recipient: string;
833
+ deliveryId: string;
834
+ status: "pending" | "cancelled" | "failed" | "sent";
835
+ provider?: string | null | undefined;
836
+ } | null;
837
+ skipReason: "preview_only" | "no_documents" | "no_recipient" | "no_attachments" | "send_failed" | null;
838
+ };
839
+ };
840
+ outputFormat: "json";
841
+ status: import("hono/utils/http-status").ContentfulStatusCode;
842
+ } | {
843
+ input: {
844
+ param: {
845
+ id: string;
846
+ };
847
+ };
848
+ output: {
849
+ error: string;
850
+ };
851
+ outputFormat: "json";
852
+ status: 400;
853
+ };
854
+ };
787
855
  } & {
788
856
  "/bookings/:id/send-documents": {
789
857
  $post: {
@@ -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;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"}
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;AAuBtD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwP7E"}
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, previewNotificationTemplateResultSchema, previewNotificationTemplateSchema, runDueRemindersSchema, sendBookingDocumentsNotificationResultSchema, sendBookingDocumentsNotificationSchema, sendInvoiceNotificationSchema, sendNotificationSchema, sendPaymentSessionNotificationSchema, updateNotificationReminderRuleSchema, updateNotificationTemplateSchema, } from "./validation.js";
4
+ import { bookingDocumentBundleSchema, confirmAndDispatchBookingResultSchema, confirmAndDispatchBookingSchema, 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 {
@@ -129,6 +129,55 @@ export function createNotificationsRoutes(options) {
129
129
  if (!bundle)
130
130
  return c.json({ error: "Booking not found" }, 404);
131
131
  return c.json({ data: bookingDocumentBundleSchema.parse(bundle) });
132
+ })
133
+ .post("/bookings/:id/confirm-and-dispatch", async (c) => {
134
+ try {
135
+ const runtime = getRuntime(c.env, options, (key) => c.var.container.resolve(key));
136
+ const dispatcher = createNotificationService(runtime.providers);
137
+ const result = await notificationsService.confirmAndDispatchBooking(c.get("db"), dispatcher, c.req.param("id"), await parseOptionalJsonBody(c, confirmAndDispatchBookingSchema), {
138
+ attachmentResolver: runtime.documentAttachmentResolver,
139
+ eventBus: runtime.eventBus,
140
+ });
141
+ if (result.status === "not_found")
142
+ return c.json({ error: "Booking not found" }, 404);
143
+ if (result.status === "preview") {
144
+ return c.json({
145
+ data: confirmAndDispatchBookingResultSchema.parse({
146
+ bookingId: result.bookingId,
147
+ documents: result.documents,
148
+ notification: null,
149
+ skipReason: "preview_only",
150
+ }),
151
+ });
152
+ }
153
+ if (result.status === "skipped") {
154
+ return c.json({
155
+ data: confirmAndDispatchBookingResultSchema.parse({
156
+ bookingId: result.bookingId,
157
+ documents: result.documents,
158
+ notification: null,
159
+ skipReason: result.skipReason,
160
+ }),
161
+ });
162
+ }
163
+ return c.json({
164
+ data: confirmAndDispatchBookingResultSchema.parse({
165
+ bookingId: result.bookingId,
166
+ documents: result.documents,
167
+ notification: {
168
+ recipient: result.recipient,
169
+ deliveryId: result.delivery.id,
170
+ provider: result.delivery.provider,
171
+ status: result.delivery.status,
172
+ },
173
+ skipReason: null,
174
+ }),
175
+ }, 201);
176
+ }
177
+ catch (error) {
178
+ const message = error instanceof Error ? error.message : "Confirm-and-dispatch failed";
179
+ return c.json({ error: message }, 400);
180
+ }
132
181
  })
133
182
  .post("/bookings/:id/send-documents", async (c) => {
134
183
  try {
package/dist/schema.d.ts CHANGED
@@ -1156,7 +1156,7 @@ export declare const notificationReminderRuns: import("drizzle-orm/pg-core").PgT
1156
1156
  tableName: "notification_reminder_runs";
1157
1157
  dataType: "string";
1158
1158
  columnType: "PgEnumColumn";
1159
- data: "failed" | "sent" | "processing" | "queued" | "skipped";
1159
+ data: "failed" | "sent" | "processing" | "skipped" | "queued";
1160
1160
  driverParam: string;
1161
1161
  notNull: true;
1162
1162
  hasDefault: false;
@@ -123,6 +123,134 @@ export declare const bookingDocumentNotificationsService: {
123
123
  updatedAt: Date;
124
124
  };
125
125
  }>;
126
+ /**
127
+ * Confirm-and-dispatch — single orchestrated call for the operator flow
128
+ * that wants "list the booking's documents, then send them to the client"
129
+ * to be one action instead of two round-trips.
130
+ *
131
+ * With `sendNotification: false`, the caller gets the bundle back without
132
+ * attempting a send — useful for rendering a preview/checkbox list before
133
+ * the operator confirms. With `sendNotification: true`, the same send
134
+ * guards as `sendBookingDocumentsNotification` apply (no_documents,
135
+ * no_recipient, no_attachments, send_failed); the result keeps the bundle
136
+ * regardless so the UI always has something to show.
137
+ */
138
+ confirmAndDispatchBooking(db: PostgresJsDatabase, dispatcher: NotificationService, bookingId: string, input: {
139
+ sendNotification?: boolean;
140
+ } & SendBookingDocumentsNotificationInput, runtime?: SendBookingDocumentsRuntimeOptions): Promise<{
141
+ status: "not_found";
142
+ bookingId?: undefined;
143
+ documents?: undefined;
144
+ skipReason?: undefined;
145
+ recipient?: undefined;
146
+ delivery?: undefined;
147
+ } | {
148
+ status: "preview";
149
+ bookingId: string;
150
+ documents: {
151
+ key: string;
152
+ source: "finance" | "legal";
153
+ documentType: "invoice" | "proforma" | "contract";
154
+ bookingId: string;
155
+ name: string;
156
+ createdAt: string;
157
+ contractId?: string | null | undefined;
158
+ invoiceId?: string | null | undefined;
159
+ attachmentId?: string | null | undefined;
160
+ renditionId?: string | null | undefined;
161
+ contractStatus?: string | null | undefined;
162
+ invoiceStatus?: string | null | undefined;
163
+ format?: string | null | undefined;
164
+ mimeType?: string | null | undefined;
165
+ storageKey?: string | null | undefined;
166
+ downloadUrl?: string | null | undefined;
167
+ language?: string | null | undefined;
168
+ metadata?: Record<string, unknown> | null | undefined;
169
+ }[];
170
+ skipReason?: undefined;
171
+ recipient?: undefined;
172
+ delivery?: undefined;
173
+ } | {
174
+ status: "skipped";
175
+ bookingId: string;
176
+ documents: {
177
+ key: string;
178
+ source: "finance" | "legal";
179
+ documentType: "invoice" | "proforma" | "contract";
180
+ bookingId: string;
181
+ name: string;
182
+ createdAt: string;
183
+ contractId?: string | null | undefined;
184
+ invoiceId?: string | null | undefined;
185
+ attachmentId?: string | null | undefined;
186
+ renditionId?: string | null | undefined;
187
+ contractStatus?: string | null | undefined;
188
+ invoiceStatus?: string | null | undefined;
189
+ format?: string | null | undefined;
190
+ mimeType?: string | null | undefined;
191
+ storageKey?: string | null | undefined;
192
+ downloadUrl?: string | null | undefined;
193
+ language?: string | null | undefined;
194
+ metadata?: Record<string, unknown> | null | undefined;
195
+ }[];
196
+ skipReason: "no_documents" | "no_recipient" | "no_attachments" | "send_failed";
197
+ recipient?: undefined;
198
+ delivery?: undefined;
199
+ } | {
200
+ status: "dispatched";
201
+ bookingId: string;
202
+ documents: {
203
+ key: string;
204
+ source: "finance" | "legal";
205
+ documentType: "invoice" | "proforma" | "contract";
206
+ bookingId: string;
207
+ name: string;
208
+ createdAt: string;
209
+ contractId?: string | null | undefined;
210
+ invoiceId?: string | null | undefined;
211
+ attachmentId?: string | null | undefined;
212
+ renditionId?: string | null | undefined;
213
+ contractStatus?: string | null | undefined;
214
+ invoiceStatus?: string | null | undefined;
215
+ format?: string | null | undefined;
216
+ mimeType?: string | null | undefined;
217
+ storageKey?: string | null | undefined;
218
+ downloadUrl?: string | null | undefined;
219
+ language?: string | null | undefined;
220
+ metadata?: Record<string, unknown> | null | undefined;
221
+ }[];
222
+ recipient: string;
223
+ delivery: {
224
+ id: string;
225
+ templateId: string | null;
226
+ templateSlug: string | null;
227
+ targetType: "organization" | "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "person" | "payment_session";
228
+ targetId: string | null;
229
+ personId: string | null;
230
+ organizationId: string | null;
231
+ bookingId: string | null;
232
+ invoiceId: string | null;
233
+ paymentSessionId: string | null;
234
+ channel: "email" | "sms";
235
+ provider: string;
236
+ providerMessageId: string | null;
237
+ status: "pending" | "cancelled" | "failed" | "sent";
238
+ toAddress: string;
239
+ fromAddress: string | null;
240
+ subject: string | null;
241
+ htmlBody: string | null;
242
+ textBody: string | null;
243
+ payloadData: Record<string, unknown> | null;
244
+ metadata: Record<string, unknown> | null;
245
+ errorMessage: string | null;
246
+ scheduledFor: Date | null;
247
+ sentAt: Date | null;
248
+ failedAt: Date | null;
249
+ createdAt: Date;
250
+ updatedAt: Date;
251
+ };
252
+ skipReason?: undefined;
253
+ }>;
126
254
  };
127
255
  export { createDefaultAttachmentFromDocument as createDefaultBookingDocumentAttachment };
128
256
  //# sourceMappingURL=service-booking-documents.d.ts.map
@@ -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;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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoH7C;;;;;;;;;;;OAWG;kCAEG,kBAAkB,cACV,mBAAmB,aACpB,MAAM,SACV;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,qCAAqC,YACpE,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4C9C,CAAA;AAED,OAAO,EAAE,mCAAmC,IAAI,sCAAsC,EAAE,CAAA"}
@@ -274,5 +274,50 @@ export const bookingDocumentNotificationsService = {
274
274
  delivery,
275
275
  };
276
276
  },
277
+ /**
278
+ * Confirm-and-dispatch — single orchestrated call for the operator flow
279
+ * that wants "list the booking's documents, then send them to the client"
280
+ * to be one action instead of two round-trips.
281
+ *
282
+ * With `sendNotification: false`, the caller gets the bundle back without
283
+ * attempting a send — useful for rendering a preview/checkbox list before
284
+ * the operator confirms. With `sendNotification: true`, the same send
285
+ * guards as `sendBookingDocumentsNotification` apply (no_documents,
286
+ * no_recipient, no_attachments, send_failed); the result keeps the bundle
287
+ * regardless so the UI always has something to show.
288
+ */
289
+ async confirmAndDispatchBooking(db, dispatcher, bookingId, input, runtime = {}) {
290
+ const bundle = await this.listBookingDocumentBundle(db, bookingId);
291
+ if (!bundle)
292
+ return { status: "not_found" };
293
+ const documents = bundle.documents;
294
+ const sendNotification = input.sendNotification ?? true;
295
+ if (!sendNotification) {
296
+ return {
297
+ status: "preview",
298
+ bookingId,
299
+ documents,
300
+ };
301
+ }
302
+ const result = await this.sendBookingDocumentsNotification(db, dispatcher, bookingId, input, runtime);
303
+ if (result.status === "not_found") {
304
+ return { status: "not_found" };
305
+ }
306
+ if (result.status !== "sent") {
307
+ return {
308
+ status: "skipped",
309
+ bookingId,
310
+ documents,
311
+ skipReason: result.status,
312
+ };
313
+ }
314
+ return {
315
+ status: "dispatched",
316
+ bookingId: result.bookingId,
317
+ documents: result.documents,
318
+ recipient: result.recipient,
319
+ delivery: result.delivery,
320
+ };
321
+ },
277
322
  };
278
323
  export { createDefaultAttachmentFromDocument as createDefaultBookingDocumentAttachment };
@@ -17,7 +17,7 @@ export declare function deliverReminderRun(db: PostgresJsDatabase, dispatcher: N
17
17
  organizationId: string | null;
18
18
  paymentSessionId: string | null;
19
19
  notificationDeliveryId: string | null;
20
- status: "failed" | "sent" | "processing" | "queued" | "skipped";
20
+ status: "failed" | "sent" | "processing" | "skipped" | "queued";
21
21
  recipient: string | null;
22
22
  scheduledFor: Date;
23
23
  processedAt: Date;
@@ -161,7 +161,7 @@ export declare function listReminderRuns(db: PostgresJsDatabase, query: Notifica
161
161
  targetType: "invoice" | "booking_payment_schedule";
162
162
  targetId: string;
163
163
  dedupeKey: string;
164
- status: "failed" | "sent" | "processing" | "queued" | "skipped";
164
+ status: "failed" | "sent" | "processing" | "skipped" | "queued";
165
165
  recipient: string | null;
166
166
  scheduledFor: string;
167
167
  processedAt: string;
@@ -212,7 +212,7 @@ export declare function getReminderRunById(db: PostgresJsDatabase, id: string):
212
212
  targetType: "invoice" | "booking_payment_schedule";
213
213
  targetId: string;
214
214
  dedupeKey: string;
215
- status: "failed" | "sent" | "processing" | "queued" | "skipped";
215
+ status: "failed" | "sent" | "processing" | "skipped" | "queued";
216
216
  recipient: string | null;
217
217
  scheduledFor: string;
218
218
  processedAt: string;
package/dist/service.d.ts CHANGED
@@ -132,6 +132,122 @@ export declare const notificationsService: {
132
132
  updatedAt: Date;
133
133
  };
134
134
  }>;
135
+ confirmAndDispatchBooking: (db: import("drizzle-orm/postgres-js").PostgresJsDatabase, dispatcher: import("./service-shared.js").NotificationService, bookingId: string, input: {
136
+ sendNotification?: boolean;
137
+ } & import("./service-shared.js").SendBookingDocumentsNotificationInput, runtime?: import("./service-booking-documents.js").SendBookingDocumentsRuntimeOptions) => Promise<{
138
+ status: "not_found";
139
+ bookingId?: undefined;
140
+ documents?: undefined;
141
+ skipReason?: undefined;
142
+ recipient?: undefined;
143
+ delivery?: undefined;
144
+ } | {
145
+ status: "preview";
146
+ bookingId: string;
147
+ documents: {
148
+ key: string;
149
+ source: "finance" | "legal";
150
+ documentType: "invoice" | "proforma" | "contract";
151
+ bookingId: string;
152
+ name: string;
153
+ createdAt: string;
154
+ contractId?: string | null | undefined;
155
+ invoiceId?: string | null | undefined;
156
+ attachmentId?: string | null | undefined;
157
+ renditionId?: string | null | undefined;
158
+ contractStatus?: string | null | undefined;
159
+ invoiceStatus?: string | null | undefined;
160
+ format?: string | null | undefined;
161
+ mimeType?: string | null | undefined;
162
+ storageKey?: string | null | undefined;
163
+ downloadUrl?: string | null | undefined;
164
+ language?: string | null | undefined;
165
+ metadata?: Record<string, unknown> | null | undefined;
166
+ }[];
167
+ skipReason?: undefined;
168
+ recipient?: undefined;
169
+ delivery?: undefined;
170
+ } | {
171
+ status: "skipped";
172
+ bookingId: string;
173
+ documents: {
174
+ key: string;
175
+ source: "finance" | "legal";
176
+ documentType: "invoice" | "proforma" | "contract";
177
+ bookingId: string;
178
+ name: string;
179
+ createdAt: string;
180
+ contractId?: string | null | undefined;
181
+ invoiceId?: string | null | undefined;
182
+ attachmentId?: string | null | undefined;
183
+ renditionId?: string | null | undefined;
184
+ contractStatus?: string | null | undefined;
185
+ invoiceStatus?: string | null | undefined;
186
+ format?: string | null | undefined;
187
+ mimeType?: string | null | undefined;
188
+ storageKey?: string | null | undefined;
189
+ downloadUrl?: string | null | undefined;
190
+ language?: string | null | undefined;
191
+ metadata?: Record<string, unknown> | null | undefined;
192
+ }[];
193
+ skipReason: "no_documents" | "no_recipient" | "no_attachments" | "send_failed";
194
+ recipient?: undefined;
195
+ delivery?: undefined;
196
+ } | {
197
+ status: "dispatched";
198
+ bookingId: string;
199
+ documents: {
200
+ key: string;
201
+ source: "finance" | "legal";
202
+ documentType: "invoice" | "proforma" | "contract";
203
+ bookingId: string;
204
+ name: string;
205
+ createdAt: string;
206
+ contractId?: string | null | undefined;
207
+ invoiceId?: string | null | undefined;
208
+ attachmentId?: string | null | undefined;
209
+ renditionId?: string | null | undefined;
210
+ contractStatus?: string | null | undefined;
211
+ invoiceStatus?: string | null | undefined;
212
+ format?: string | null | undefined;
213
+ mimeType?: string | null | undefined;
214
+ storageKey?: string | null | undefined;
215
+ downloadUrl?: string | null | undefined;
216
+ language?: string | null | undefined;
217
+ metadata?: Record<string, unknown> | null | undefined;
218
+ }[];
219
+ recipient: string;
220
+ delivery: {
221
+ id: string;
222
+ templateId: string | null;
223
+ templateSlug: string | null;
224
+ targetType: "organization" | "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "person" | "payment_session";
225
+ targetId: string | null;
226
+ personId: string | null;
227
+ organizationId: string | null;
228
+ bookingId: string | null;
229
+ invoiceId: string | null;
230
+ paymentSessionId: string | null;
231
+ channel: "email" | "sms";
232
+ provider: string;
233
+ providerMessageId: string | null;
234
+ status: "pending" | "cancelled" | "failed" | "sent";
235
+ toAddress: string;
236
+ fromAddress: string | null;
237
+ subject: string | null;
238
+ htmlBody: string | null;
239
+ textBody: string | null;
240
+ payloadData: Record<string, unknown> | null;
241
+ metadata: Record<string, unknown> | null;
242
+ errorMessage: string | null;
243
+ scheduledFor: Date | null;
244
+ sentAt: Date | null;
245
+ failedAt: Date | null;
246
+ createdAt: Date;
247
+ updatedAt: Date;
248
+ };
249
+ skipReason?: undefined;
250
+ }>;
135
251
  createDefaultBookingDocumentAttachment: typeof createDefaultBookingDocumentAttachment;
136
252
  };
137
253
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sCAAsC,EAAE,MAAM,gCAAgC,CAAA;AACvF,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAEL,sCAAsC,EACvC,MAAM,gCAAgC,CAAA;AACvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,8BAA8B,EAC/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACf,MAAM,wBAAwB,CAAA;AAE/B,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBhC,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sCAAsC,EAAE,MAAM,gCAAgC,CAAA;AACvF,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAEL,sCAAsC,EACvC,MAAM,gCAAgC,CAAA;AACvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,8BAA8B,EAC/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACf,MAAM,wBAAwB,CAAA;AAE/B,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAyBumV,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CADxoV,CAAA"}
package/dist/service.js CHANGED
@@ -26,5 +26,6 @@ export const notificationsService = {
26
26
  sendInvoiceNotification,
27
27
  listBookingDocumentBundle: bookingDocumentNotificationsService.listBookingDocumentBundle,
28
28
  sendBookingDocumentsNotification: bookingDocumentNotificationsService.sendBookingDocumentsNotification,
29
+ confirmAndDispatchBooking: bookingDocumentNotificationsService.confirmAndDispatchBooking,
29
30
  createDefaultBookingDocumentAttachment,
30
31
  };
@@ -4,6 +4,6 @@ export declare function deliverQueuedNotificationReminder(db: PostgresJsDatabase
4
4
  reminderRunId: string;
5
5
  }, options?: NotificationTaskRuntimeOptions): Promise<{
6
6
  reminderRunId: string;
7
- status: "failed" | "sent" | "processing" | "queued" | "skipped" | null;
7
+ status: "failed" | "sent" | "processing" | "skipped" | "queued" | null;
8
8
  }>;
9
9
  //# sourceMappingURL=deliver-reminder.d.ts.map
@@ -37,8 +37,8 @@ export declare const notificationReminderRunStatusSchema: z.ZodEnum<{
37
37
  failed: "failed";
38
38
  sent: "sent";
39
39
  processing: "processing";
40
- queued: "queued";
41
40
  skipped: "skipped";
41
+ queued: "queued";
42
42
  }>;
43
43
  export declare const notificationDocumentTypeSchema: z.ZodEnum<{
44
44
  invoice: "invoice";
@@ -232,8 +232,8 @@ export declare const notificationReminderRunListQuerySchema: z.ZodObject<{
232
232
  failed: "failed";
233
233
  sent: "sent";
234
234
  processing: "processing";
235
- queued: "queued";
236
235
  skipped: "skipped";
236
+ queued: "queued";
237
237
  }>>;
238
238
  }, z.core.$strip>;
239
239
  export declare const notificationReminderRunRuleSummarySchema: z.ZodObject<{
@@ -299,8 +299,8 @@ export declare const notificationReminderRunRecordSchema: z.ZodObject<{
299
299
  failed: "failed";
300
300
  sent: "sent";
301
301
  processing: "processing";
302
- queued: "queued";
303
302
  skipped: "skipped";
303
+ queued: "queued";
304
304
  }>;
305
305
  recipient: z.ZodNullable<z.ZodString>;
306
306
  scheduledFor: z.ZodString;
@@ -374,8 +374,8 @@ export declare const notificationReminderRunListResponseSchema: z.ZodObject<{
374
374
  failed: "failed";
375
375
  sent: "sent";
376
376
  processing: "processing";
377
- queued: "queued";
378
377
  skipped: "skipped";
378
+ queued: "queued";
379
379
  }>;
380
380
  recipient: z.ZodNullable<z.ZodString>;
381
381
  scheduledFor: z.ZodString;
@@ -679,4 +679,79 @@ export declare const sendBookingDocumentsNotificationResultSchema: z.ZodObject<{
679
679
  sent: "sent";
680
680
  }>;
681
681
  }, z.core.$strip>;
682
+ /**
683
+ * Confirm-and-dispatch — single orchestrated request that lists the booking's
684
+ * document bundle and (optionally) sends it to the client in one round-trip.
685
+ *
686
+ * `sendNotification: false` turns the call into a preview: the bundle comes
687
+ * back but no delivery is attempted. Templates use the preview to render the
688
+ * "here's what's ready" checkbox list before the operator confirms.
689
+ */
690
+ export declare const confirmAndDispatchBookingSchema: z.ZodObject<{
691
+ templateId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
692
+ templateSlug: z.ZodNullable<z.ZodOptional<z.ZodString>>;
693
+ provider: z.ZodNullable<z.ZodOptional<z.ZodString>>;
694
+ to: z.ZodNullable<z.ZodOptional<z.ZodString>>;
695
+ from: z.ZodNullable<z.ZodOptional<z.ZodString>>;
696
+ subject: z.ZodNullable<z.ZodOptional<z.ZodString>>;
697
+ html: z.ZodNullable<z.ZodOptional<z.ZodString>>;
698
+ text: z.ZodNullable<z.ZodOptional<z.ZodString>>;
699
+ data: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
700
+ metadata: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
701
+ scheduledFor: z.ZodNullable<z.ZodOptional<z.ZodString>>;
702
+ documentTypes: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodEnum<{
703
+ invoice: "invoice";
704
+ proforma: "proforma";
705
+ contract: "contract";
706
+ }>>>>;
707
+ sendNotification: z.ZodDefault<z.ZodBoolean>;
708
+ }, z.core.$strip>;
709
+ export declare const confirmAndDispatchBookingResultSchema: z.ZodObject<{
710
+ bookingId: z.ZodString;
711
+ documents: z.ZodArray<z.ZodObject<{
712
+ key: z.ZodString;
713
+ source: z.ZodEnum<{
714
+ finance: "finance";
715
+ legal: "legal";
716
+ }>;
717
+ documentType: z.ZodEnum<{
718
+ invoice: "invoice";
719
+ proforma: "proforma";
720
+ contract: "contract";
721
+ }>;
722
+ bookingId: z.ZodString;
723
+ contractId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
724
+ invoiceId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
725
+ attachmentId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
726
+ renditionId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
727
+ contractStatus: z.ZodNullable<z.ZodOptional<z.ZodString>>;
728
+ invoiceStatus: z.ZodNullable<z.ZodOptional<z.ZodString>>;
729
+ name: z.ZodString;
730
+ format: z.ZodNullable<z.ZodOptional<z.ZodString>>;
731
+ mimeType: z.ZodNullable<z.ZodOptional<z.ZodString>>;
732
+ storageKey: z.ZodNullable<z.ZodOptional<z.ZodString>>;
733
+ downloadUrl: z.ZodNullable<z.ZodOptional<z.ZodString>>;
734
+ language: z.ZodNullable<z.ZodOptional<z.ZodString>>;
735
+ metadata: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
736
+ createdAt: z.ZodString;
737
+ }, z.core.$strip>>;
738
+ notification: z.ZodNullable<z.ZodObject<{
739
+ recipient: z.ZodString;
740
+ deliveryId: z.ZodString;
741
+ provider: z.ZodNullable<z.ZodOptional<z.ZodString>>;
742
+ status: z.ZodEnum<{
743
+ pending: "pending";
744
+ cancelled: "cancelled";
745
+ failed: "failed";
746
+ sent: "sent";
747
+ }>;
748
+ }, z.core.$strip>>;
749
+ skipReason: z.ZodNullable<z.ZodEnum<{
750
+ preview_only: "preview_only";
751
+ no_documents: "no_documents";
752
+ no_recipient: "no_recipient";
753
+ no_attachments: "no_attachments";
754
+ send_failed: "send_failed";
755
+ }>>;
756
+ }, z.core.$strip>;
682
757
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,yBAAyB;;;EAA2B,CAAA;AACjE,eAAO,MAAM,gCAAgC;;;;EAA0C,CAAA;AACvF,eAAO,MAAM,gCAAgC;;;;;EAAqD,CAAA;AAClG,eAAO,MAAM,4BAA4B;;;;;;;;;EASvC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;EAA0C,CAAA;AACvF,eAAO,MAAM,oCAAoC;;;EAAkD,CAAA;AACnG,eAAO,MAAM,mCAAmC;;;;;;EAM9C,CAAA;AACF,eAAO,MAAM,8BAA8B;;;;EAA8C,CAAA;AACzF,eAAO,MAAM,gCAAgC;;;EAA+B,CAAA;AAC5E,eAAO,MAAM,4BAA4B;;;;;;;;;;iBAYrC,CAAA;AAqBJ,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAA2C,CAAA;AAExF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;iBAK9C,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAY9C,CAAA;AAgBF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;iBAMhD,CAAA;AAED,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;iBAI7C,CAAA;AAEJ,eAAO,MAAM,uCAAuC;;;;;;;;;;;;;;;;;iBAKlD,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;;;;;;;;;;iBAajD,CAAA;AAEF,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;iBAWnD,CAAA;AAEF,eAAO,MAAM,4CAA4C;;;;;;;;;;;;;;;;;;iBAUvD,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;iBAQ7C,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiB9C,CAAA;AAEF,eAAO,MAAM,yCAAyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKpD,CAAA;AAEF,eAAO,MAAM,qBAAqB;;iBAEhC,CAAA;AAkBF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMhD,CAAA;AAED,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMzC,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BhC,CAAA;AAEH,eAAO,MAAM,iCAAiC;;;;;;;;;;;iBAY1C,CAAA;AAEJ,eAAO,MAAM,uCAAuC;;;;;;;;;;iBAOlD,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmB1C,CAAA;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGtC,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;;;iBAajD,CAAA;AAEF,eAAO,MAAM,4CAA4C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOvD,CAAA"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,yBAAyB;;;EAA2B,CAAA;AACjE,eAAO,MAAM,gCAAgC;;;;EAA0C,CAAA;AACvF,eAAO,MAAM,gCAAgC;;;;;EAAqD,CAAA;AAClG,eAAO,MAAM,4BAA4B;;;;;;;;;EASvC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;EAA0C,CAAA;AACvF,eAAO,MAAM,oCAAoC;;;EAAkD,CAAA;AACnG,eAAO,MAAM,mCAAmC;;;;;;EAM9C,CAAA;AACF,eAAO,MAAM,8BAA8B;;;;EAA8C,CAAA;AACzF,eAAO,MAAM,gCAAgC;;;EAA+B,CAAA;AAC5E,eAAO,MAAM,4BAA4B;;;;;;;;;;iBAYrC,CAAA;AAqBJ,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAA2C,CAAA;AAExF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;iBAK9C,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAY9C,CAAA;AAgBF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;iBAMhD,CAAA;AAED,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;iBAI7C,CAAA;AAEJ,eAAO,MAAM,uCAAuC;;;;;;;;;;;;;;;;;iBAKlD,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;;;;;;;;;;iBAajD,CAAA;AAEF,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;iBAWnD,CAAA;AAEF,eAAO,MAAM,4CAA4C;;;;;;;;;;;;;;;;;;iBAUvD,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;iBAQ7C,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiB9C,CAAA;AAEF,eAAO,MAAM,yCAAyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKpD,CAAA;AAEF,eAAO,MAAM,qBAAqB;;iBAEhC,CAAA;AAkBF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMhD,CAAA;AAED,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMzC,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BhC,CAAA;AAEH,eAAO,MAAM,iCAAiC;;;;;;;;;;;iBAY1C,CAAA;AAEJ,eAAO,MAAM,uCAAuC;;;;;;;;;;iBAOlD,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmB1C,CAAA;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGtC,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;;;iBAajD,CAAA;AAEF,eAAO,MAAM,4CAA4C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOvD,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;iBAE1C,CAAA;AAEF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBhD,CAAA"}
@@ -289,3 +289,39 @@ export const sendBookingDocumentsNotificationResultSchema = z.object({
289
289
  provider: z.string().optional().nullable(),
290
290
  status: notificationDeliveryStatusSchema,
291
291
  });
292
+ /**
293
+ * Confirm-and-dispatch — single orchestrated request that lists the booking's
294
+ * document bundle and (optionally) sends it to the client in one round-trip.
295
+ *
296
+ * `sendNotification: false` turns the call into a preview: the bundle comes
297
+ * back but no delivery is attempted. Templates use the preview to render the
298
+ * "here's what's ready" checkbox list before the operator confirms.
299
+ */
300
+ export const confirmAndDispatchBookingSchema = sendBookingDocumentsNotificationSchema.extend({
301
+ sendNotification: z.boolean().default(true),
302
+ });
303
+ export const confirmAndDispatchBookingResultSchema = z.object({
304
+ bookingId: z.string().min(1),
305
+ documents: z.array(bookingDocumentBundleItemSchema),
306
+ /**
307
+ * Non-null when `sendNotification` was true and a delivery actually went
308
+ * out. Null when either the operator asked for a preview only, or the send
309
+ * couldn't proceed (no recipient / no attachments / no matching documents).
310
+ */
311
+ notification: z
312
+ .object({
313
+ recipient: z.string().min(1),
314
+ deliveryId: z.string().min(1),
315
+ provider: z.string().optional().nullable(),
316
+ status: notificationDeliveryStatusSchema,
317
+ })
318
+ .nullable(),
319
+ /**
320
+ * When `sendNotification` was true but the dispatcher declined to send,
321
+ * this captures which guard tripped so the UI can explain it — e.g.
322
+ * "No recipient on file, add an email to the lead traveler and retry".
323
+ */
324
+ skipReason: z
325
+ .enum(["preview_only", "no_documents", "no_recipient", "no_attachments", "send_failed"])
326
+ .nullable(),
327
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/notifications",
3
- "version": "0.6.9",
3
+ "version": "0.8.0",
4
4
  "license": "FSL-1.1-Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -50,12 +50,12 @@
50
50
  "hono": "^4.12.10",
51
51
  "liquidjs": "^10.24.0",
52
52
  "zod": "^4.3.6",
53
- "@voyantjs/bookings": "0.6.9",
54
- "@voyantjs/core": "0.6.9",
55
- "@voyantjs/db": "0.6.9",
56
- "@voyantjs/finance": "0.6.9",
57
- "@voyantjs/hono": "0.6.9",
58
- "@voyantjs/legal": "0.6.9"
53
+ "@voyantjs/bookings": "0.8.0",
54
+ "@voyantjs/core": "0.8.0",
55
+ "@voyantjs/db": "0.8.0",
56
+ "@voyantjs/finance": "0.8.0",
57
+ "@voyantjs/hono": "0.8.0",
58
+ "@voyantjs/legal": "0.8.0"
59
59
  },
60
60
  "devDependencies": {
61
61
  "typescript": "^6.0.2",