@01.software/sdk 0.32.0 → 0.34.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.
Files changed (70) hide show
  1. package/README.md +253 -38
  2. package/dist/analytics/react.cjs.map +1 -1
  3. package/dist/analytics/react.js.map +1 -1
  4. package/dist/analytics.cjs.map +1 -1
  5. package/dist/analytics.js.map +1 -1
  6. package/dist/client.cjs +368 -24
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +7 -6
  9. package/dist/client.d.ts +7 -6
  10. package/dist/client.js +368 -24
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-CORhppPb.d.cts → collection-client-CR2B8c1v.d.cts} +7 -3
  13. package/dist/{collection-client-DPGXnhoF.d.ts → collection-client-DkREjhQ9.d.ts} +7 -3
  14. package/dist/{const-DcY2_z9O.d.ts → const-BTvdrXtY.d.cts} +5 -5
  15. package/dist/{const-Brk2Ff0q.d.cts → const-CdqCauHQ.d.ts} +5 -5
  16. package/dist/index-CjA3U6X3.d.cts +186 -0
  17. package/dist/index-DK8_NXkh.d.ts +186 -0
  18. package/dist/index.cjs +1651 -260
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +74 -9
  21. package/dist/index.d.ts +74 -9
  22. package/dist/index.js +1651 -260
  23. package/dist/index.js.map +1 -1
  24. package/dist/{payload-types-DVK1QCeU.d.cts → payload-types-C7tb7Xbs.d.cts} +2115 -1833
  25. package/dist/{payload-types-DVK1QCeU.d.ts → payload-types-C7tb7Xbs.d.ts} +2115 -1833
  26. package/dist/query.cjs +194 -35
  27. package/dist/query.cjs.map +1 -1
  28. package/dist/query.d.cts +45 -18
  29. package/dist/query.d.ts +45 -18
  30. package/dist/query.js +194 -35
  31. package/dist/query.js.map +1 -1
  32. package/dist/realtime.cjs.map +1 -1
  33. package/dist/realtime.d.cts +2 -2
  34. package/dist/realtime.d.ts +2 -2
  35. package/dist/realtime.js.map +1 -1
  36. package/dist/{server-CrsPyqEc.d.cts → server-nXOezi4b.d.cts} +22 -6
  37. package/dist/{server-CrsPyqEc.d.ts → server-nXOezi4b.d.ts} +22 -6
  38. package/dist/server.cjs +474 -36
  39. package/dist/server.cjs.map +1 -1
  40. package/dist/server.d.cts +11 -179
  41. package/dist/server.d.ts +11 -179
  42. package/dist/server.js +474 -36
  43. package/dist/server.js.map +1 -1
  44. package/dist/{types-DUPC7Xn6.d.ts → types-1ylMrCuW.d.ts} +1 -1
  45. package/dist/{types-ByMrR_Z_.d.cts → types-Bx558PU6.d.cts} +1 -1
  46. package/dist/{types-CYMSBkJC.d.ts → types-Byo_Rty4.d.ts} +728 -75
  47. package/dist/{types-CAkWqIr6.d.cts → types-DDhtZI6E.d.cts} +728 -75
  48. package/dist/ui/canvas/server.cjs +231 -38
  49. package/dist/ui/canvas/server.cjs.map +1 -1
  50. package/dist/ui/canvas/server.d.cts +1 -1
  51. package/dist/ui/canvas/server.d.ts +1 -1
  52. package/dist/ui/canvas/server.js +221 -38
  53. package/dist/ui/canvas/server.js.map +1 -1
  54. package/dist/ui/canvas.cjs +320 -257
  55. package/dist/ui/canvas.cjs.map +1 -1
  56. package/dist/ui/canvas.d.cts +5 -19
  57. package/dist/ui/canvas.d.ts +5 -19
  58. package/dist/ui/canvas.js +323 -260
  59. package/dist/ui/canvas.js.map +1 -1
  60. package/dist/ui/form.d.cts +1 -1
  61. package/dist/ui/form.d.ts +1 -1
  62. package/dist/ui/video.d.cts +1 -1
  63. package/dist/ui/video.d.ts +1 -1
  64. package/dist/webhook.cjs +95 -0
  65. package/dist/webhook.cjs.map +1 -1
  66. package/dist/webhook.d.cts +20 -104
  67. package/dist/webhook.d.ts +20 -104
  68. package/dist/webhook.js +95 -0
  69. package/dist/webhook.js.map +1 -1
  70. package/package.json +4 -5
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { F as Form } from '../payload-types-DVK1QCeU.cjs';
2
+ import { F as Form } from '../payload-types-C7tb7Xbs.cjs';
3
3
  import { RichTextData } from './rich-text.cjs';
4
4
  import '@payloadcms/richtext-lexical';
5
5
  import '@payloadcms/richtext-lexical/lexical';
package/dist/ui/form.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { F as Form } from '../payload-types-DVK1QCeU.js';
2
+ import { F as Form } from '../payload-types-C7tb7Xbs.js';
3
3
  import { RichTextData } from './rich-text.js';
4
4
  import '@payloadcms/richtext-lexical';
5
5
  import '@payloadcms/richtext-lexical/lexical';
@@ -1,7 +1,7 @@
1
1
  import React, { CSSProperties } from 'react';
2
2
  import { MuxPlayerProps, MuxPlayerRefAttributes } from '@mux/mux-player-react';
3
3
  export { MuxPlayerRefAttributes as VideoPlayerRef } from '@mux/mux-player-react';
4
- import { V as Video } from '../payload-types-DVK1QCeU.cjs';
4
+ import { V as Video } from '../payload-types-C7tb7Xbs.cjs';
5
5
  export { V as VideoGifOptions, a as VideoThumbnailOptions, g as getVideoGif, b as getVideoMp4Url, c as getVideoStoryboard, d as getVideoStreamUrl, e as getVideoThumbnail } from '../video-WR_TFO9a.cjs';
6
6
 
7
7
  interface VideoPlayerCSSProperties extends CSSProperties {
@@ -1,7 +1,7 @@
1
1
  import React, { CSSProperties } from 'react';
2
2
  import { MuxPlayerProps, MuxPlayerRefAttributes } from '@mux/mux-player-react';
3
3
  export { MuxPlayerRefAttributes as VideoPlayerRef } from '@mux/mux-player-react';
4
- import { V as Video } from '../payload-types-DVK1QCeU.js';
4
+ import { V as Video } from '../payload-types-C7tb7Xbs.js';
5
5
  export { V as VideoGifOptions, a as VideoThumbnailOptions, g as getVideoGif, b as getVideoMp4Url, c as getVideoStoryboard, d as getVideoStreamUrl, e as getVideoThumbnail } from '../video-WR_TFO9a.js';
6
6
 
7
7
  interface VideoPlayerCSSProperties extends CSSProperties {
package/dist/webhook.cjs CHANGED
@@ -20,11 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/webhook.ts
21
21
  var webhook_exports = {};
22
22
  __export(webhook_exports, {
23
+ COMMERCE_NOTIFICATION_EVENTS: () => COMMERCE_NOTIFICATION_EVENTS,
24
+ COMMERCE_NOTIFICATION_EVENT_TYPE: () => COMMERCE_NOTIFICATION_EVENT_TYPE,
25
+ COMMERCE_NOTIFICATION_OPERATION: () => COMMERCE_NOTIFICATION_OPERATION,
23
26
  CUSTOMER_PASSWORD_RESET_OPERATION: () => CUSTOMER_PASSWORD_RESET_OPERATION,
24
27
  ORDER_CHANGED_EVENT_TYPE: () => ORDER_CHANGED_EVENT_TYPE,
28
+ createCommerceEmailWebhookHandler: () => createCommerceEmailWebhookHandler,
25
29
  createCustomerAuthWebhookHandler: () => createCustomerAuthWebhookHandler,
26
30
  createTypedWebhookHandler: () => createTypedWebhookHandler,
31
+ defineCommerceEmailConfig: () => defineCommerceEmailConfig,
32
+ getCommerceNotificationIdempotencyKey: () => getCommerceNotificationIdempotencyKey,
27
33
  handleWebhook: () => handleWebhook,
34
+ isCommerceNotificationWebhookEvent: () => isCommerceNotificationWebhookEvent,
28
35
  isCustomerPasswordResetWebhookEvent: () => isCustomerPasswordResetWebhookEvent,
29
36
  isOrderChangedWebhookEvent: () => isOrderChangedWebhookEvent,
30
37
  isValidWebhookEvent: () => isValidWebhookEvent,
@@ -35,11 +42,21 @@ module.exports = __toCommonJS(webhook_exports);
35
42
 
36
43
  // src/core/webhook/index.ts
37
44
  var ORDER_CHANGED_EVENT_TYPE = "collection.orderChanged";
45
+ var COMMERCE_NOTIFICATION_EVENT_TYPE = "commerce.notification";
38
46
  function isValidWebhookEvent(data) {
39
47
  if (typeof data !== "object" || data === null) return false;
40
48
  const obj = data;
41
49
  return typeof obj.collection === "string" && typeof obj.operation === "string" && obj.operation.length > 0 && typeof obj.data === "object" && obj.data !== null;
42
50
  }
51
+ var COMMERCE_NOTIFICATION_OPERATION = "notification";
52
+ var COMMERCE_NOTIFICATION_EVENTS = [
53
+ "orderPaid",
54
+ "orderCanceled",
55
+ "fulfillmentShipped",
56
+ "orderDelivered",
57
+ "returnRequested",
58
+ "returnCompleted"
59
+ ];
43
60
  function isStringOrNumber(value) {
44
61
  return typeof value === "string" || typeof value === "number";
45
62
  }
@@ -64,6 +81,30 @@ function isWebhookOrderChange(value) {
64
81
  if (!isRecord(value)) return false;
65
82
  return value.type === "order" && value.source === "payload-orderable" && (value.orderableFieldName === void 0 || typeof value.orderableFieldName === "string") && hasOptionalOrderValue(value, "previousOrder") && hasOptionalOrderValue(value, "nextOrder") && isWebhookOrderScope(value.scope) && isWebhookOrderMoved(value.moved);
66
83
  }
84
+ function isCommerceNotificationEventName(value) {
85
+ return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
86
+ }
87
+ function isCommerceNotificationSourceCollection(value) {
88
+ return value === "orders" || value === "fulfillments" || value === "returns";
89
+ }
90
+ function isCommerceNotificationData(value) {
91
+ if (!isRecord(value)) return false;
92
+ if (value.source !== void 0 && (!isRecord(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
93
+ return false;
94
+ }
95
+ return (value.orderId === void 0 || isStringOrNumber(value.orderId)) && (value.orderNumber === void 0 || typeof value.orderNumber === "string") && (value.status === void 0 || typeof value.status === "string") && (value.totalAmount === void 0 || typeof value.totalAmount === "number") && (value.currency === void 0 || typeof value.currency === "string") && (value.fulfillmentId === void 0 || isStringOrNumber(value.fulfillmentId)) && (value.fulfillmentStatus === void 0 || typeof value.fulfillmentStatus === "string") && (value.shippedAt === void 0 || typeof value.shippedAt === "string") && (value.returnId === void 0 || isStringOrNumber(value.returnId)) && (value.returnStatus === void 0 || typeof value.returnStatus === "string") && (value.refundAmount === void 0 || typeof value.refundAmount === "number") && (value.completedAt === void 0 || typeof value.completedAt === "string");
96
+ }
97
+ function isCommerceNotification(value) {
98
+ if (!isRecord(value)) return false;
99
+ return isCommerceNotificationEventName(value.event) && typeof value.intentId === "string" && value.intentId.length > 0 && typeof value.dedupeKey === "string" && value.dedupeKey.length > 0 && (value.orderId === void 0 || typeof value.orderId === "string") && (value.fulfillmentId === void 0 || typeof value.fulfillmentId === "string") && (value.returnId === void 0 || typeof value.returnId === "string");
100
+ }
101
+ function isWebhookCommerceNotificationChange(value) {
102
+ if (!isRecord(value)) return false;
103
+ return value.type === "notification" && value.source === "commerce-notifications" && isCommerceNotificationEventName(value.event) && isCommerceNotificationSourceCollection(value.sourceCollection) && isStringOrNumber(value.sourceId);
104
+ }
105
+ function matchesOptionalId(actual, expected) {
106
+ return actual === void 0 || expected === void 0 || actual === expected;
107
+ }
67
108
  function isOrderChangedWebhookEvent(event) {
68
109
  if (!isValidWebhookEvent(event) || event.operation !== "update" || event.eventType !== ORDER_CHANGED_EVENT_TYPE || !isWebhookOrderChange(event.change)) {
69
110
  return false;
@@ -76,6 +117,60 @@ function isOrderChangedWebhookEvent(event) {
76
117
  }
77
118
  return true;
78
119
  }
120
+ function isCommerceNotificationWebhookEvent(event) {
121
+ if (!isValidWebhookEvent(event) || event.operation !== COMMERCE_NOTIFICATION_OPERATION || event.eventType !== COMMERCE_NOTIFICATION_EVENT_TYPE || !isCommerceNotificationData(event.data) || !isCommerceNotification(event.notification)) {
122
+ return false;
123
+ }
124
+ const notification = event.notification;
125
+ const data = event.data;
126
+ const change = event.change;
127
+ const sourceCollection = data.source?.collection ?? event.collection;
128
+ const sourceId = data.source?.id;
129
+ if (!isCommerceNotificationSourceCollection(sourceCollection)) return false;
130
+ if (data.source !== void 0 && event.collection !== data.source.collection) {
131
+ return false;
132
+ }
133
+ if (change !== void 0) {
134
+ if (!isWebhookCommerceNotificationChange(change)) return false;
135
+ if (change.sourceCollection !== sourceCollection) return false;
136
+ if (change.event !== notification.event) return false;
137
+ if (!matchesOptionalId(change.sourceId, sourceId)) return false;
138
+ }
139
+ const changeSourceId = isWebhookCommerceNotificationChange(change) ? change.sourceId : void 0;
140
+ if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
141
+ return sourceCollection === "orders" && typeof notification.orderId === "string" && notification.orderId.length > 0 && matchesOptionalId(data.orderId, sourceId) && matchesOptionalId(notification.orderId, sourceId) && matchesOptionalId(data.orderId, notification.orderId) && matchesOptionalId(changeSourceId, data.orderId ?? notification.orderId);
142
+ }
143
+ if (notification.event === "fulfillmentShipped") {
144
+ return sourceCollection === "fulfillments" && matchesOptionalId(data.fulfillmentId, sourceId) && typeof notification.fulfillmentId === "string" && notification.fulfillmentId.length > 0 && matchesOptionalId(notification.fulfillmentId, sourceId) && matchesOptionalId(data.fulfillmentId, notification.fulfillmentId) && matchesOptionalId(changeSourceId, notification.fulfillmentId);
145
+ }
146
+ if (notification.event === "returnRequested" || notification.event === "returnCompleted") {
147
+ return sourceCollection === "returns" && matchesOptionalId(data.returnId, sourceId) && typeof notification.returnId === "string" && notification.returnId.length > 0 && matchesOptionalId(notification.returnId, sourceId) && matchesOptionalId(data.returnId, notification.returnId) && matchesOptionalId(changeSourceId, notification.returnId);
148
+ }
149
+ return false;
150
+ }
151
+ function getCommerceNotificationIdempotencyKey(event) {
152
+ return `${event.notification.intentId}:${event.notification.dedupeKey}`;
153
+ }
154
+ function defineCommerceEmailConfig(config) {
155
+ return config;
156
+ }
157
+ function createCommerceEmailWebhookHandler(handlers) {
158
+ return async (event) => {
159
+ if (!isCommerceNotificationWebhookEvent(event)) {
160
+ await handlers.unhandled?.(event);
161
+ return;
162
+ }
163
+ const handler = handlers[event.notification.event];
164
+ if (!handler) {
165
+ await handlers.unhandled?.(event);
166
+ return;
167
+ }
168
+ await handler({
169
+ event,
170
+ idempotencyKey: getCommerceNotificationIdempotencyKey(event)
171
+ });
172
+ };
173
+ }
79
174
  function isWebhookCollection(event, collection) {
80
175
  return isValidWebhookEvent(event) && event.collection === collection;
81
176
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.ts"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n createCustomerAuthWebhookHandler,\n isValidWebhookEvent,\n isCustomerPasswordResetWebhookEvent,\n isOrderChangedWebhookEvent,\n isWebhookCollection,\n isWebhookOperation,\n CUSTOMER_PASSWORD_RESET_OPERATION,\n ORDER_CHANGED_EVENT_TYPE,\n} from './core/webhook'\nexport type {\n CollectionWebhookOperation,\n CustomerAuthWebhookEvent,\n CustomerAuthWebhookHandlers,\n CustomerPasswordResetWebhookData,\n CustomerPasswordResetWebhookEvent,\n OrderChangedWebhookEvent,\n WebhookChange,\n WebhookEvent,\n WebhookHandler,\n WebhookKnownOperation,\n WebhookOperation,\n WebhookOptions,\n WebhookOrderChange,\n WebhookOrderMoved,\n WebhookOrderScope,\n} from './core/webhook'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = string\n\n/**\n * Semantic event type for manual Admin Panel ordering changes.\n *\n * Order-change webhooks remain `operation: \"update\"` events for compatibility.\n * Do not filter on or emit `operation: \"reorder\"`; use this event type with\n * `isOrderChangedWebhookEvent()` to distinguish ordering from normal content\n * updates.\n */\nexport const ORDER_CHANGED_EVENT_TYPE = 'collection.orderChanged' as const\n\n/** Collection webhook operations emitted for tenant collection writes. */\nexport type CollectionWebhookOperation = 'create' | 'update'\n\n/** Describes the ordered area affected by an order-change webhook. */\nexport type WebhookOrderScope =\n | { kind: 'collection'; collection: string }\n | { kind: 'join'; collection: string; field: string; id: string | number }\n\n/** Identifies the public moved document for the ordered scope. */\nexport type WebhookOrderMoved = {\n collection: string\n id: string | number\n relatedCollection?: string\n relatedId?: string | number\n}\n\n/** Metadata attached to `collection.orderChanged` webhook events. */\nexport type WebhookOrderChange = {\n type: 'order'\n source: 'payload-orderable'\n /**\n * Diagnostic Payload order field name.\n *\n * This may contain hidden implementation field names. Application routing\n * should use `change.scope` and `change.moved` instead.\n */\n orderableFieldName?: string\n previousOrder?: string | null\n nextOrder?: string | null\n scope: WebhookOrderScope\n moved: WebhookOrderMoved\n}\n\n/** Known semantic webhook change metadata. */\nexport type WebhookChange = WebhookOrderChange\n\nexport interface WebhookEvent<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> {\n collection: T\n operation: WebhookOperation\n data: TData\n eventType?: string\n change?: unknown\n timestamp?: string\n deliveryId?: string\n}\n\nexport type WebhookHandler<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> = (event: WebhookEvent<T, TData>) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n /** Max accepted skew for signed webhook delivery timestamps. Default: 300s. */\n toleranceSeconds?: number\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n typeof obj.operation === 'string' &&\n obj.operation.length > 0 &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\n/** Webhook event emitted when manual Admin Panel ordering changes. */\nexport type OrderChangedWebhookEvent<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> = WebhookEvent<T, TData> & {\n operation: 'update'\n eventType: typeof ORDER_CHANGED_EVENT_TYPE\n change: WebhookOrderChange\n}\n\nfunction isStringOrNumber(value: unknown): value is string | number {\n return typeof value === 'string' || typeof value === 'number'\n}\n\nfunction isWebhookOrderScope(value: unknown): value is WebhookOrderScope {\n if (!isRecord(value)) return false\n\n if (value.kind === 'collection') {\n return typeof value.collection === 'string'\n }\n\n if (value.kind === 'join') {\n return (\n typeof value.collection === 'string' &&\n typeof value.field === 'string' &&\n isStringOrNumber(value.id)\n )\n }\n\n return false\n}\n\nfunction isWebhookOrderMoved(value: unknown): value is WebhookOrderMoved {\n if (!isRecord(value)) return false\n\n return (\n typeof value.collection === 'string' &&\n isStringOrNumber(value.id) &&\n (value.relatedCollection === undefined ||\n typeof value.relatedCollection === 'string') &&\n (value.relatedId === undefined || isStringOrNumber(value.relatedId))\n )\n}\n\nfunction hasOptionalOrderValue(\n value: Record<string, unknown>,\n key: string,\n): boolean {\n return (\n value[key] === undefined ||\n value[key] === null ||\n typeof value[key] === 'string'\n )\n}\n\nfunction isWebhookOrderChange(value: unknown): value is WebhookOrderChange {\n if (!isRecord(value)) return false\n\n return (\n value.type === 'order' &&\n value.source === 'payload-orderable' &&\n (value.orderableFieldName === undefined ||\n typeof value.orderableFieldName === 'string') &&\n hasOptionalOrderValue(value, 'previousOrder') &&\n hasOptionalOrderValue(value, 'nextOrder') &&\n isWebhookOrderScope(value.scope) &&\n isWebhookOrderMoved(value.moved)\n )\n}\n\n/**\n * Returns true for semantic order-change webhooks emitted as update events.\n *\n * Use this guard with `ORDER_CHANGED_EVENT_TYPE` instead of filtering on\n * `operation: \"reorder\"`. Tenant order-change webhooks intentionally keep\n * `operation: \"update\"` for compatibility with existing webhook handlers.\n */\nexport function isOrderChangedWebhookEvent(\n event: unknown,\n): event is OrderChangedWebhookEvent<string, unknown> {\n if (\n !isValidWebhookEvent(event) ||\n event.operation !== 'update' ||\n event.eventType !== ORDER_CHANGED_EVENT_TYPE ||\n !isWebhookOrderChange(event.change)\n ) {\n return false\n }\n\n if (event.collection !== event.change.scope.collection) {\n return false\n }\n\n if (\n event.change.scope.kind === 'collection' &&\n event.change.moved.collection !== event.change.scope.collection\n ) {\n return false\n }\n\n return true\n}\n\n/** Narrows a webhook event to a specific collection. */\nexport function isWebhookCollection<TCollection extends string>(\n event: unknown,\n collection: TCollection,\n): event is WebhookEvent<TCollection, unknown> {\n return isValidWebhookEvent(event) && event.collection === collection\n}\n\n/** Narrows a webhook event to a specific operation. */\nexport function isWebhookOperation<TOperation extends string>(\n event: unknown,\n operation: TOperation,\n): event is WebhookEvent<string, unknown> & { operation: TOperation } {\n return isValidWebhookEvent(event) && event.operation === operation\n}\n\nexport const CUSTOMER_PASSWORD_RESET_OPERATION = 'password-reset' as const\n\nexport type WebhookKnownOperation =\n | CollectionWebhookOperation\n | typeof CUSTOMER_PASSWORD_RESET_OPERATION\n\nexport interface CustomerPasswordResetWebhookData {\n customerId: string | number\n email: string\n name: string\n resetPasswordToken: string\n resetPasswordExpiresAt: string\n}\n\nexport type CustomerPasswordResetWebhookEvent = WebhookEvent<\n 'customers',\n CustomerPasswordResetWebhookData\n> & {\n operation: typeof CUSTOMER_PASSWORD_RESET_OPERATION\n}\n\nexport type CustomerAuthWebhookEvent = CustomerPasswordResetWebhookEvent\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport interface CustomerAuthWebhookHandlers {\n passwordReset?: (\n data: CustomerPasswordResetWebhookData,\n event: CustomerPasswordResetWebhookEvent,\n ) => MaybePromise<void>\n unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\nfunction hasString(value: Record<string, unknown>, key: string): boolean {\n return typeof value[key] === 'string'\n}\n\nfunction hasStringOrNumber(\n value: Record<string, unknown>,\n key: string,\n): boolean {\n return typeof value[key] === 'string' || typeof value[key] === 'number'\n}\n\nexport function isCustomerPasswordResetWebhookEvent(\n event: WebhookEvent<string, unknown>,\n): event is CustomerPasswordResetWebhookEvent {\n if (\n event.collection !== 'customers' ||\n event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION ||\n !isRecord(event.data)\n ) {\n return false\n }\n\n return (\n hasStringOrNumber(event.data, 'customerId') &&\n hasString(event.data, 'email') &&\n hasString(event.data, 'name') &&\n hasString(event.data, 'resetPasswordToken') &&\n hasString(event.data, 'resetPasswordExpiresAt')\n )\n}\n\nexport function createCustomerAuthWebhookHandler(\n handlers: CustomerAuthWebhookHandlers,\n): WebhookHandler<string, unknown> {\n return async (event) => {\n if (isCustomerPasswordResetWebhookEvent(event) && handlers.passwordReset) {\n await handlers.passwordReset(event.data, event)\n return\n }\n\n await handlers.unhandled?.(event)\n }\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n timestamp: string,\n deliveryId: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n )\n // Validate and convert hex signature to Uint8Array\n if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {\n return false\n }\n const sigBytes = new Uint8Array(\n (signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16)),\n )\n // crypto.subtle.verify performs constant-time comparison internally\n return crypto.subtle.verify(\n 'HMAC',\n key,\n sigBytes,\n encoder.encode(`${timestamp}.${deliveryId}.${payload}`),\n )\n}\n\nfunction timestampIsFresh(\n timestamp: string,\n toleranceSeconds: number,\n): boolean {\n if (!/^\\d+$/.test(timestamp)) return false\n const timestampMs = Number(timestamp)\n if (!Number.isFinite(timestampMs)) return false\n const skewMs = Math.abs(Date.now() - timestampMs)\n return skewMs <= toleranceSeconds * 1000\n}\n\nexport async function handleWebhook<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n>(\n request: Request,\n handler: WebhookHandler<T, TData>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const timestamp = request.headers.get('x-webhook-timestamp') || ''\n const deliveryId = request.headers.get('x-webhook-delivery-id') || ''\n const toleranceSeconds = options.toleranceSeconds ?? 300\n const valid =\n Boolean(timestamp && deliveryId) &&\n timestampIsFresh(timestamp, toleranceSeconds) &&\n (await verifySignature(\n rawBody,\n options.secret,\n signature,\n timestamp,\n deliveryId,\n ))\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n } else {\n console.warn(\n '[@01.software/sdk] Webhook signature verification is disabled. ' +\n 'Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification.',\n )\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T, TData>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(JSON.stringify({ error: 'Internal server error' }), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(\n `Expected collection \"${collection}\", got \"${event.collection}\"`,\n )\n }\n return handler(event)\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.ts"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n createCommerceEmailWebhookHandler,\n createCustomerAuthWebhookHandler,\n defineCommerceEmailConfig,\n getCommerceNotificationIdempotencyKey,\n isValidWebhookEvent,\n isCommerceNotificationWebhookEvent,\n isCustomerPasswordResetWebhookEvent,\n isOrderChangedWebhookEvent,\n isWebhookCollection,\n isWebhookOperation,\n CUSTOMER_PASSWORD_RESET_OPERATION,\n COMMERCE_NOTIFICATION_EVENT_TYPE,\n COMMERCE_NOTIFICATION_EVENTS,\n COMMERCE_NOTIFICATION_OPERATION,\n ORDER_CHANGED_EVENT_TYPE,\n} from './core/webhook'\nexport type {\n CollectionWebhookOperation,\n CommerceEmailChannel,\n CommerceEmailConfig,\n CommerceEmailEventConfig,\n CommerceEmailEventHandlers,\n CommerceEmailHandlerContext,\n CommerceNotification,\n CommerceNotificationData,\n CommerceNotificationEventName,\n CommerceNotificationSource,\n CommerceNotificationSourceCollection,\n CommerceNotificationWebhookEvent,\n CustomerAuthWebhookEvent,\n CustomerAuthWebhookHandlers,\n CustomerPasswordResetWebhookData,\n CustomerPasswordResetWebhookEvent,\n OrderChangedWebhookEvent,\n WebhookChange,\n WebhookCommerceNotificationChange,\n WebhookEvent,\n WebhookHandler,\n WebhookKnownOperation,\n WebhookOperation,\n WebhookOptions,\n WebhookOrderChange,\n WebhookOrderMoved,\n WebhookOrderScope,\n} from './core/webhook'\nexport type {\n WebhookSigningSecretReveal,\n WebhookWithoutSecret,\n} from './webhook-types'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = string\n\n/**\n * Semantic event type for manual Admin Panel ordering changes.\n *\n * Order-change webhooks remain `operation: \"update\"` events for compatibility.\n * Do not filter on or emit `operation: \"reorder\"`; use this event type with\n * `isOrderChangedWebhookEvent()` to distinguish ordering from normal content\n * updates.\n */\nexport const ORDER_CHANGED_EVENT_TYPE = 'collection.orderChanged' as const\n\n/** Semantic event type for v1 commerce notification webhooks. */\nexport const COMMERCE_NOTIFICATION_EVENT_TYPE = 'commerce.notification' as const\n\n/** Collection webhook operations emitted for tenant collection writes. */\nexport type CollectionWebhookOperation = 'create' | 'update'\n\n/** Describes the ordered area affected by an order-change webhook. */\nexport type WebhookOrderScope =\n | { kind: 'collection'; collection: string }\n | { kind: 'join'; collection: string; field: string; id: string | number }\n\n/** Identifies the public moved document for the ordered scope. */\nexport type WebhookOrderMoved = {\n collection: string\n id: string | number\n relatedCollection?: string\n relatedId?: string | number\n}\n\n/** Metadata attached to `collection.orderChanged` webhook events. */\nexport type WebhookOrderChange = {\n type: 'order'\n source: 'payload-orderable'\n /**\n * Diagnostic Payload order field name.\n *\n * This may contain hidden implementation field names. Application routing\n * should use `change.scope` and `change.moved` instead.\n */\n orderableFieldName?: string\n previousOrder?: string | null\n nextOrder?: string | null\n scope: WebhookOrderScope\n moved: WebhookOrderMoved\n}\n\n/** Known semantic webhook change metadata. */\nexport type WebhookChange = WebhookOrderChange | WebhookCommerceNotificationChange\n\nexport interface WebhookEvent<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> {\n collection: T\n operation: WebhookOperation\n data: TData\n eventType?: string\n change?: unknown\n timestamp?: string\n deliveryId?: string\n}\n\nexport type WebhookHandler<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> = (event: WebhookEvent<T, TData>) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n /** Max accepted skew for signed webhook delivery timestamps. Default: 300s. */\n toleranceSeconds?: number\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n typeof obj.operation === 'string' &&\n obj.operation.length > 0 &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\n/** Webhook event emitted when manual Admin Panel ordering changes. */\nexport type OrderChangedWebhookEvent<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n> = WebhookEvent<T, TData> & {\n operation: 'update'\n eventType: typeof ORDER_CHANGED_EVENT_TYPE\n change: WebhookOrderChange\n}\n\nexport const COMMERCE_NOTIFICATION_OPERATION = 'notification' as const\n\nexport const COMMERCE_NOTIFICATION_EVENTS = [\n 'orderPaid',\n 'orderCanceled',\n 'fulfillmentShipped',\n 'orderDelivered',\n 'returnRequested',\n 'returnCompleted',\n] as const\n\nexport type CommerceNotificationEventName =\n (typeof COMMERCE_NOTIFICATION_EVENTS)[number]\n\nexport type CommerceNotificationSourceCollection =\n | 'orders'\n | 'fulfillments'\n | 'returns'\n\nexport type CommerceNotificationSource = {\n collection: CommerceNotificationSourceCollection\n id: string | number\n}\n\nexport type CommerceNotificationData = {\n source?: CommerceNotificationSource\n orderId?: string | number\n orderNumber?: string\n status?: string\n totalAmount?: number\n currency?: string\n fulfillmentId?: string | number\n fulfillmentStatus?: string\n shippedAt?: string\n returnId?: string | number\n returnStatus?: string\n refundAmount?: number\n completedAt?: string\n}\n\nexport type CommerceNotification = {\n event: CommerceNotificationEventName\n intentId: string\n dedupeKey: string\n orderId?: string\n fulfillmentId?: string\n returnId?: string\n}\n\nexport type WebhookCommerceNotificationChange = {\n type: 'notification'\n source: 'commerce-notifications'\n event: CommerceNotificationEventName\n sourceCollection: CommerceNotificationSourceCollection\n sourceId: string | number\n}\n\n/** Webhook event emitted for v1 commerce notification deliveries. */\nexport type CommerceNotificationWebhookEvent = WebhookEvent<\n CommerceNotificationSourceCollection,\n CommerceNotificationData\n> & {\n operation: typeof COMMERCE_NOTIFICATION_OPERATION\n eventType: typeof COMMERCE_NOTIFICATION_EVENT_TYPE\n change?: WebhookCommerceNotificationChange\n notification: CommerceNotification\n}\n\nexport type CommerceEmailChannel = 'webhook' | 'provider'\n\nexport type CommerceEmailEventConfig = {\n enabled: boolean\n channel: CommerceEmailChannel\n template?: string\n}\n\nexport type CommerceEmailConfig = {\n version: 1\n commerceNotifications: Partial<\n Record<CommerceNotificationEventName, CommerceEmailEventConfig>\n >\n}\n\nexport type CommerceEmailHandlerContext = {\n event: CommerceNotificationWebhookEvent\n idempotencyKey: string\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport type CommerceEmailEventHandlers = Partial<\n Record<\n CommerceNotificationEventName,\n (context: CommerceEmailHandlerContext) => MaybePromise<void>\n >\n> & {\n unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>\n}\n\nfunction isStringOrNumber(value: unknown): value is string | number {\n return typeof value === 'string' || typeof value === 'number'\n}\n\nfunction isWebhookOrderScope(value: unknown): value is WebhookOrderScope {\n if (!isRecord(value)) return false\n\n if (value.kind === 'collection') {\n return typeof value.collection === 'string'\n }\n\n if (value.kind === 'join') {\n return (\n typeof value.collection === 'string' &&\n typeof value.field === 'string' &&\n isStringOrNumber(value.id)\n )\n }\n\n return false\n}\n\nfunction isWebhookOrderMoved(value: unknown): value is WebhookOrderMoved {\n if (!isRecord(value)) return false\n\n return (\n typeof value.collection === 'string' &&\n isStringOrNumber(value.id) &&\n (value.relatedCollection === undefined ||\n typeof value.relatedCollection === 'string') &&\n (value.relatedId === undefined || isStringOrNumber(value.relatedId))\n )\n}\n\nfunction hasOptionalOrderValue(\n value: Record<string, unknown>,\n key: string,\n): boolean {\n return (\n value[key] === undefined ||\n value[key] === null ||\n typeof value[key] === 'string'\n )\n}\n\nfunction isWebhookOrderChange(value: unknown): value is WebhookOrderChange {\n if (!isRecord(value)) return false\n\n return (\n value.type === 'order' &&\n value.source === 'payload-orderable' &&\n (value.orderableFieldName === undefined ||\n typeof value.orderableFieldName === 'string') &&\n hasOptionalOrderValue(value, 'previousOrder') &&\n hasOptionalOrderValue(value, 'nextOrder') &&\n isWebhookOrderScope(value.scope) &&\n isWebhookOrderMoved(value.moved)\n )\n}\n\nfunction isCommerceNotificationEventName(\n value: unknown,\n): value is CommerceNotificationEventName {\n return (\n typeof value === 'string' &&\n (COMMERCE_NOTIFICATION_EVENTS as readonly string[]).includes(value)\n )\n}\n\nfunction isCommerceNotificationSourceCollection(\n value: unknown,\n): value is CommerceNotificationSourceCollection {\n return value === 'orders' || value === 'fulfillments' || value === 'returns'\n}\n\nfunction isCommerceNotificationData(\n value: unknown,\n): value is CommerceNotificationData {\n if (!isRecord(value)) return false\n if (\n value.source !== undefined &&\n (!isRecord(value.source) ||\n !isCommerceNotificationSourceCollection(value.source.collection) ||\n !isStringOrNumber(value.source.id))\n ) {\n return false\n }\n\n return (\n (value.orderId === undefined || isStringOrNumber(value.orderId)) &&\n (value.orderNumber === undefined || typeof value.orderNumber === 'string') &&\n (value.status === undefined || typeof value.status === 'string') &&\n (value.totalAmount === undefined || typeof value.totalAmount === 'number') &&\n (value.currency === undefined || typeof value.currency === 'string') &&\n (value.fulfillmentId === undefined ||\n isStringOrNumber(value.fulfillmentId)) &&\n (value.fulfillmentStatus === undefined ||\n typeof value.fulfillmentStatus === 'string') &&\n (value.shippedAt === undefined || typeof value.shippedAt === 'string') &&\n (value.returnId === undefined || isStringOrNumber(value.returnId)) &&\n (value.returnStatus === undefined ||\n typeof value.returnStatus === 'string') &&\n (value.refundAmount === undefined ||\n typeof value.refundAmount === 'number') &&\n (value.completedAt === undefined || typeof value.completedAt === 'string')\n )\n}\n\nfunction isCommerceNotification(\n value: unknown,\n): value is CommerceNotification {\n if (!isRecord(value)) return false\n return (\n isCommerceNotificationEventName(value.event) &&\n typeof value.intentId === 'string' &&\n value.intentId.length > 0 &&\n typeof value.dedupeKey === 'string' &&\n value.dedupeKey.length > 0 &&\n (value.orderId === undefined || typeof value.orderId === 'string') &&\n (value.fulfillmentId === undefined ||\n typeof value.fulfillmentId === 'string') &&\n (value.returnId === undefined || typeof value.returnId === 'string')\n )\n}\n\nfunction isWebhookCommerceNotificationChange(\n value: unknown,\n): value is WebhookCommerceNotificationChange {\n if (!isRecord(value)) return false\n return (\n value.type === 'notification' &&\n value.source === 'commerce-notifications' &&\n isCommerceNotificationEventName(value.event) &&\n isCommerceNotificationSourceCollection(value.sourceCollection) &&\n isStringOrNumber(value.sourceId)\n )\n}\n\nfunction matchesOptionalId(\n actual: string | number | undefined,\n expected: string | number | undefined,\n): boolean {\n return actual === undefined || expected === undefined || actual === expected\n}\n\n/**\n * Returns true for semantic order-change webhooks emitted as update events.\n *\n * Use this guard with `ORDER_CHANGED_EVENT_TYPE` instead of filtering on\n * `operation: \"reorder\"`. Tenant order-change webhooks intentionally keep\n * `operation: \"update\"` for compatibility with existing webhook handlers.\n */\nexport function isOrderChangedWebhookEvent(\n event: unknown,\n): event is OrderChangedWebhookEvent<string, unknown> {\n if (\n !isValidWebhookEvent(event) ||\n event.operation !== 'update' ||\n event.eventType !== ORDER_CHANGED_EVENT_TYPE ||\n !isWebhookOrderChange(event.change)\n ) {\n return false\n }\n\n if (event.collection !== event.change.scope.collection) {\n return false\n }\n\n if (\n event.change.scope.kind === 'collection' &&\n event.change.moved.collection !== event.change.scope.collection\n ) {\n return false\n }\n\n return true\n}\n\n/**\n * Returns true for semantic commerce notification webhooks.\n *\n * Use `notification.intentId` and `notification.dedupeKey` for semantic\n * idempotency. `deliveryId`, when present, identifies a delivery attempt for\n * observability and is not the semantic notification identity.\n */\nexport function isCommerceNotificationWebhookEvent(\n event: unknown,\n): event is CommerceNotificationWebhookEvent {\n if (\n !isValidWebhookEvent(event) ||\n event.operation !== COMMERCE_NOTIFICATION_OPERATION ||\n event.eventType !== COMMERCE_NOTIFICATION_EVENT_TYPE ||\n !isCommerceNotificationData(event.data) ||\n !isCommerceNotification((event as { notification?: unknown }).notification)\n ) {\n return false\n }\n\n const notification = (event as unknown as CommerceNotificationWebhookEvent)\n .notification\n const data = event.data\n const change = event.change\n const sourceCollection = data.source?.collection ?? event.collection\n const sourceId = data.source?.id\n\n if (!isCommerceNotificationSourceCollection(sourceCollection)) return false\n if (data.source !== undefined && event.collection !== data.source.collection) {\n return false\n }\n\n if (change !== undefined) {\n if (!isWebhookCommerceNotificationChange(change)) return false\n if (change.sourceCollection !== sourceCollection) return false\n if (change.event !== notification.event) return false\n if (!matchesOptionalId(change.sourceId, sourceId)) return false\n }\n const changeSourceId = isWebhookCommerceNotificationChange(change)\n ? change.sourceId\n : undefined\n\n if (\n notification.event === 'orderPaid' ||\n notification.event === 'orderCanceled' ||\n notification.event === 'orderDelivered'\n ) {\n return (\n sourceCollection === 'orders' &&\n typeof notification.orderId === 'string' &&\n notification.orderId.length > 0 &&\n matchesOptionalId(data.orderId, sourceId) &&\n matchesOptionalId(notification.orderId, sourceId) &&\n matchesOptionalId(data.orderId, notification.orderId) &&\n matchesOptionalId(changeSourceId, data.orderId ?? notification.orderId)\n )\n }\n\n if (notification.event === 'fulfillmentShipped') {\n return (\n sourceCollection === 'fulfillments' &&\n matchesOptionalId(data.fulfillmentId, sourceId) &&\n typeof notification.fulfillmentId === 'string' &&\n notification.fulfillmentId.length > 0 &&\n matchesOptionalId(notification.fulfillmentId, sourceId) &&\n matchesOptionalId(data.fulfillmentId, notification.fulfillmentId) &&\n matchesOptionalId(changeSourceId, notification.fulfillmentId)\n )\n }\n\n if (\n notification.event === 'returnRequested' ||\n notification.event === 'returnCompleted'\n ) {\n return (\n sourceCollection === 'returns' &&\n matchesOptionalId(data.returnId, sourceId) &&\n typeof notification.returnId === 'string' &&\n notification.returnId.length > 0 &&\n matchesOptionalId(notification.returnId, sourceId) &&\n matchesOptionalId(data.returnId, notification.returnId) &&\n matchesOptionalId(changeSourceId, notification.returnId)\n )\n }\n\n return false\n}\n\nexport function getCommerceNotificationIdempotencyKey(\n event: Pick<CommerceNotificationWebhookEvent, 'notification'>,\n): string {\n return `${event.notification.intentId}:${event.notification.dedupeKey}`\n}\n\nexport function defineCommerceEmailConfig<TConfig extends CommerceEmailConfig>(\n config: TConfig,\n): TConfig {\n return config\n}\n\nexport function createCommerceEmailWebhookHandler(\n handlers: CommerceEmailEventHandlers,\n): WebhookHandler<string, unknown> {\n return async (event) => {\n if (!isCommerceNotificationWebhookEvent(event)) {\n await handlers.unhandled?.(event)\n return\n }\n\n const handler = handlers[event.notification.event]\n if (!handler) {\n await handlers.unhandled?.(event)\n return\n }\n\n await handler({\n event,\n idempotencyKey: getCommerceNotificationIdempotencyKey(event),\n })\n }\n}\n\n/** Narrows a webhook event to a specific collection. */\nexport function isWebhookCollection<TCollection extends string>(\n event: unknown,\n collection: TCollection,\n): event is WebhookEvent<TCollection, unknown> {\n return isValidWebhookEvent(event) && event.collection === collection\n}\n\n/** Narrows a webhook event to a specific operation. */\nexport function isWebhookOperation<TOperation extends string>(\n event: unknown,\n operation: TOperation,\n): event is WebhookEvent<string, unknown> & { operation: TOperation } {\n return isValidWebhookEvent(event) && event.operation === operation\n}\n\nexport const CUSTOMER_PASSWORD_RESET_OPERATION = 'password-reset' as const\n\nexport type WebhookKnownOperation =\n | CollectionWebhookOperation\n | typeof CUSTOMER_PASSWORD_RESET_OPERATION\n | typeof COMMERCE_NOTIFICATION_OPERATION\n\nexport interface CustomerPasswordResetWebhookData {\n customerId: string | number\n email: string\n name: string\n resetPasswordToken: string\n resetPasswordExpiresAt: string\n}\n\nexport type CustomerPasswordResetWebhookEvent = WebhookEvent<\n 'customers',\n CustomerPasswordResetWebhookData\n> & {\n operation: typeof CUSTOMER_PASSWORD_RESET_OPERATION\n}\n\nexport type CustomerAuthWebhookEvent = CustomerPasswordResetWebhookEvent\n\nexport interface CustomerAuthWebhookHandlers {\n passwordReset?: (\n data: CustomerPasswordResetWebhookData,\n event: CustomerPasswordResetWebhookEvent,\n ) => MaybePromise<void>\n unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\nfunction hasString(value: Record<string, unknown>, key: string): boolean {\n return typeof value[key] === 'string'\n}\n\nfunction hasStringOrNumber(\n value: Record<string, unknown>,\n key: string,\n): boolean {\n return typeof value[key] === 'string' || typeof value[key] === 'number'\n}\n\nexport function isCustomerPasswordResetWebhookEvent(\n event: WebhookEvent<string, unknown>,\n): event is CustomerPasswordResetWebhookEvent {\n if (\n event.collection !== 'customers' ||\n event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION ||\n !isRecord(event.data)\n ) {\n return false\n }\n\n return (\n hasStringOrNumber(event.data, 'customerId') &&\n hasString(event.data, 'email') &&\n hasString(event.data, 'name') &&\n hasString(event.data, 'resetPasswordToken') &&\n hasString(event.data, 'resetPasswordExpiresAt')\n )\n}\n\nexport function createCustomerAuthWebhookHandler(\n handlers: CustomerAuthWebhookHandlers,\n): WebhookHandler<string, unknown> {\n return async (event) => {\n if (isCustomerPasswordResetWebhookEvent(event) && handlers.passwordReset) {\n await handlers.passwordReset(event.data, event)\n return\n }\n\n await handlers.unhandled?.(event)\n }\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n timestamp: string,\n deliveryId: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n )\n // Validate and convert hex signature to Uint8Array\n if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {\n return false\n }\n const sigBytes = new Uint8Array(\n (signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16)),\n )\n // crypto.subtle.verify performs constant-time comparison internally\n return crypto.subtle.verify(\n 'HMAC',\n key,\n sigBytes,\n encoder.encode(`${timestamp}.${deliveryId}.${payload}`),\n )\n}\n\nfunction timestampIsFresh(\n timestamp: string,\n toleranceSeconds: number,\n): boolean {\n if (!/^\\d+$/.test(timestamp)) return false\n const timestampMs = Number(timestamp)\n if (!Number.isFinite(timestampMs)) return false\n const skewMs = Math.abs(Date.now() - timestampMs)\n return skewMs <= toleranceSeconds * 1000\n}\n\nexport async function handleWebhook<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n>(\n request: Request,\n handler: WebhookHandler<T, TData>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const timestamp = request.headers.get('x-webhook-timestamp') || ''\n const deliveryId = request.headers.get('x-webhook-delivery-id') || ''\n const toleranceSeconds = options.toleranceSeconds ?? 300\n const valid =\n Boolean(timestamp && deliveryId) &&\n timestampIsFresh(timestamp, toleranceSeconds) &&\n (await verifySignature(\n rawBody,\n options.secret,\n signature,\n timestamp,\n deliveryId,\n ))\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n } else {\n console.warn(\n '[@01.software/sdk] Webhook signature verification is disabled. ' +\n 'Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification.',\n )\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T, TData>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(JSON.stringify({ error: 'Internal server error' }), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(\n `Expected collection \"${collection}\", got \"${event.collection}\"`,\n )\n }\n return handler(event)\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,111 +1,27 @@
1
- import { C as Collection } from './const-Brk2Ff0q.cjs';
2
- import { C as CollectionType } from './types-ByMrR_Z_.cjs';
3
- import './payload-types-DVK1QCeU.cjs';
1
+ export { C as COMMERCE_NOTIFICATION_EVENTS, a as COMMERCE_NOTIFICATION_EVENT_TYPE, b as COMMERCE_NOTIFICATION_OPERATION, c as CUSTOMER_PASSWORD_RESET_OPERATION, d as CollectionWebhookOperation, e as CommerceEmailChannel, f as CommerceEmailConfig, g as CommerceEmailEventConfig, h as CommerceEmailEventHandlers, i as CommerceEmailHandlerContext, j as CommerceNotification, k as CommerceNotificationData, l as CommerceNotificationEventName, m as CommerceNotificationSource, n as CommerceNotificationSourceCollection, o as CommerceNotificationWebhookEvent, p as CustomerAuthWebhookEvent, q as CustomerAuthWebhookHandlers, r as CustomerPasswordResetWebhookData, s as CustomerPasswordResetWebhookEvent, O as ORDER_CHANGED_EVENT_TYPE, t as OrderChangedWebhookEvent, W as WebhookChange, u as WebhookCommerceNotificationChange, v as WebhookEvent, w as WebhookHandler, x as WebhookKnownOperation, y as WebhookOperation, z as WebhookOptions, A as WebhookOrderChange, B as WebhookOrderMoved, D as WebhookOrderScope, E as createCommerceEmailWebhookHandler, F as createCustomerAuthWebhookHandler, G as createTypedWebhookHandler, H as defineCommerceEmailConfig, I as getCommerceNotificationIdempotencyKey, J as handleWebhook, K as isCommerceNotificationWebhookEvent, L as isCustomerPasswordResetWebhookEvent, M as isOrderChangedWebhookEvent, N as isValidWebhookEvent, P as isWebhookCollection, Q as isWebhookOperation } from './index-CjA3U6X3.cjs';
2
+ import { W as Webhook } from './payload-types-C7tb7Xbs.cjs';
3
+ import './const-BTvdrXtY.cjs';
4
+ import './types-Bx558PU6.cjs';
4
5
 
5
- type WebhookOperation = string;
6
6
  /**
7
- * Semantic event type for manual Admin Panel ordering changes.
8
- *
9
- * Order-change webhooks remain `operation: "update"` events for compatibility.
10
- * Do not filter on or emit `operation: "reorder"`; use this event type with
11
- * `isOrderChangedWebhookEvent()` to distinguish ordering from normal content
12
- * updates.
7
+ * Webhook records returned from ordinary list/find `secret` is encrypted at
8
+ * rest and omitted from API reads (`access.read: false` on the collection).
13
9
  */
14
- declare const ORDER_CHANGED_EVENT_TYPE: "collection.orderChanged";
15
- /** Collection webhook operations emitted for tenant collection writes. */
16
- type CollectionWebhookOperation = 'create' | 'update';
17
- /** Describes the ordered area affected by an order-change webhook. */
18
- type WebhookOrderScope = {
19
- kind: 'collection';
20
- collection: string;
21
- } | {
22
- kind: 'join';
23
- collection: string;
24
- field: string;
25
- id: string | number;
26
- };
27
- /** Identifies the public moved document for the ordered scope. */
28
- type WebhookOrderMoved = {
29
- collection: string;
30
- id: string | number;
31
- relatedCollection?: string;
32
- relatedId?: string | number;
33
- };
34
- /** Metadata attached to `collection.orderChanged` webhook events. */
35
- type WebhookOrderChange = {
36
- type: 'order';
37
- source: 'payload-orderable';
38
- /**
39
- * Diagnostic Payload order field name.
40
- *
41
- * This may contain hidden implementation field names. Application routing
42
- * should use `change.scope` and `change.moved` instead.
43
- */
44
- orderableFieldName?: string;
45
- previousOrder?: string | null;
46
- nextOrder?: string | null;
47
- scope: WebhookOrderScope;
48
- moved: WebhookOrderMoved;
49
- };
50
- /** Known semantic webhook change metadata. */
51
- type WebhookChange = WebhookOrderChange;
52
- interface WebhookEvent<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> {
53
- collection: T;
54
- operation: WebhookOperation;
55
- data: TData;
56
- eventType?: string;
57
- change?: unknown;
58
- timestamp?: string;
59
- deliveryId?: string;
60
- }
61
- type WebhookHandler<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> = (event: WebhookEvent<T, TData>) => Promise<void> | void;
62
- interface WebhookOptions {
63
- secret?: string;
64
- /** Max accepted skew for signed webhook delivery timestamps. Default: 300s. */
65
- toleranceSeconds?: number;
66
- }
67
- declare function isValidWebhookEvent(data: unknown): data is WebhookEvent;
68
- /** Webhook event emitted when manual Admin Panel ordering changes. */
69
- type OrderChangedWebhookEvent<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> = WebhookEvent<T, TData> & {
70
- operation: 'update';
71
- eventType: typeof ORDER_CHANGED_EVENT_TYPE;
72
- change: WebhookOrderChange;
73
- };
10
+ type WebhookWithoutSecret = Omit<Webhook, 'secret'>;
74
11
  /**
75
- * Returns true for semantic order-change webhooks emitted as update events.
76
- *
77
- * Use this guard with `ORDER_CHANGED_EVENT_TYPE` instead of filtering on
78
- * `operation: "reorder"`. Tenant order-change webhooks intentionally keep
79
- * `operation: "update"` for compatibility with existing webhook handlers.
12
+ * One-time plaintext signing secret from Console reveal/rotate Admin actions.
13
+ * Persists audit metadata on the webhook document as `secretRevealedAt` /
14
+ * `secretRotatedAt` / `secretRotatedBy` (not returned in this JSON body).
80
15
  */
81
- declare function isOrderChangedWebhookEvent(event: unknown): event is OrderChangedWebhookEvent<string, unknown>;
82
- /** Narrows a webhook event to a specific collection. */
83
- declare function isWebhookCollection<TCollection extends string>(event: unknown, collection: TCollection): event is WebhookEvent<TCollection, unknown>;
84
- /** Narrows a webhook event to a specific operation. */
85
- declare function isWebhookOperation<TOperation extends string>(event: unknown, operation: TOperation): event is WebhookEvent<string, unknown> & {
86
- operation: TOperation;
87
- };
88
- declare const CUSTOMER_PASSWORD_RESET_OPERATION: "password-reset";
89
- type WebhookKnownOperation = CollectionWebhookOperation | typeof CUSTOMER_PASSWORD_RESET_OPERATION;
90
- interface CustomerPasswordResetWebhookData {
91
- customerId: string | number;
92
- email: string;
93
- name: string;
94
- resetPasswordToken: string;
95
- resetPasswordExpiresAt: string;
96
- }
97
- type CustomerPasswordResetWebhookEvent = WebhookEvent<'customers', CustomerPasswordResetWebhookData> & {
98
- operation: typeof CUSTOMER_PASSWORD_RESET_OPERATION;
16
+ type WebhookSigningSecretReveal = {
17
+ success: boolean;
18
+ webhookId: string;
19
+ /** Plaintext hex signing secret — copy to receiver `WEBHOOK_SECRET`. */
20
+ secret: string;
21
+ /** reveal-secret response timestamp (maps to `secretRevealedAt` on save). */
22
+ revealedAt?: string;
23
+ /** rotate-secret response timestamp (maps to `secretRotatedAt` on save). */
24
+ rotatedAt?: string;
99
25
  };
100
- type CustomerAuthWebhookEvent = CustomerPasswordResetWebhookEvent;
101
- type MaybePromise<T> = T | Promise<T>;
102
- interface CustomerAuthWebhookHandlers {
103
- passwordReset?: (data: CustomerPasswordResetWebhookData, event: CustomerPasswordResetWebhookEvent) => MaybePromise<void>;
104
- unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>;
105
- }
106
- declare function isCustomerPasswordResetWebhookEvent(event: WebhookEvent<string, unknown>): event is CustomerPasswordResetWebhookEvent;
107
- declare function createCustomerAuthWebhookHandler(handlers: CustomerAuthWebhookHandlers): WebhookHandler<string, unknown>;
108
- declare function handleWebhook<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>>(request: Request, handler: WebhookHandler<T, TData>, options?: WebhookOptions): Promise<Response>;
109
- declare function createTypedWebhookHandler<T extends Collection>(collection: T, handler: (event: WebhookEvent<T>) => Promise<void> | void): WebhookHandler<T>;
110
26
 
111
- export { CUSTOMER_PASSWORD_RESET_OPERATION, type CollectionWebhookOperation, type CustomerAuthWebhookEvent, type CustomerAuthWebhookHandlers, type CustomerPasswordResetWebhookData, type CustomerPasswordResetWebhookEvent, ORDER_CHANGED_EVENT_TYPE, type OrderChangedWebhookEvent, type WebhookChange, type WebhookEvent, type WebhookHandler, type WebhookKnownOperation, type WebhookOperation, type WebhookOptions, type WebhookOrderChange, type WebhookOrderMoved, type WebhookOrderScope, createCustomerAuthWebhookHandler, createTypedWebhookHandler, handleWebhook, isCustomerPasswordResetWebhookEvent, isOrderChangedWebhookEvent, isValidWebhookEvent, isWebhookCollection, isWebhookOperation };
27
+ export type { WebhookSigningSecretReveal, WebhookWithoutSecret };
package/dist/webhook.d.ts CHANGED
@@ -1,111 +1,27 @@
1
- import { C as Collection } from './const-DcY2_z9O.js';
2
- import { C as CollectionType } from './types-DUPC7Xn6.js';
3
- import './payload-types-DVK1QCeU.js';
1
+ export { C as COMMERCE_NOTIFICATION_EVENTS, a as COMMERCE_NOTIFICATION_EVENT_TYPE, b as COMMERCE_NOTIFICATION_OPERATION, c as CUSTOMER_PASSWORD_RESET_OPERATION, d as CollectionWebhookOperation, e as CommerceEmailChannel, f as CommerceEmailConfig, g as CommerceEmailEventConfig, h as CommerceEmailEventHandlers, i as CommerceEmailHandlerContext, j as CommerceNotification, k as CommerceNotificationData, l as CommerceNotificationEventName, m as CommerceNotificationSource, n as CommerceNotificationSourceCollection, o as CommerceNotificationWebhookEvent, p as CustomerAuthWebhookEvent, q as CustomerAuthWebhookHandlers, r as CustomerPasswordResetWebhookData, s as CustomerPasswordResetWebhookEvent, O as ORDER_CHANGED_EVENT_TYPE, t as OrderChangedWebhookEvent, W as WebhookChange, u as WebhookCommerceNotificationChange, v as WebhookEvent, w as WebhookHandler, x as WebhookKnownOperation, y as WebhookOperation, z as WebhookOptions, A as WebhookOrderChange, B as WebhookOrderMoved, D as WebhookOrderScope, E as createCommerceEmailWebhookHandler, F as createCustomerAuthWebhookHandler, G as createTypedWebhookHandler, H as defineCommerceEmailConfig, I as getCommerceNotificationIdempotencyKey, J as handleWebhook, K as isCommerceNotificationWebhookEvent, L as isCustomerPasswordResetWebhookEvent, M as isOrderChangedWebhookEvent, N as isValidWebhookEvent, P as isWebhookCollection, Q as isWebhookOperation } from './index-DK8_NXkh.js';
2
+ import { W as Webhook } from './payload-types-C7tb7Xbs.js';
3
+ import './const-CdqCauHQ.js';
4
+ import './types-1ylMrCuW.js';
4
5
 
5
- type WebhookOperation = string;
6
6
  /**
7
- * Semantic event type for manual Admin Panel ordering changes.
8
- *
9
- * Order-change webhooks remain `operation: "update"` events for compatibility.
10
- * Do not filter on or emit `operation: "reorder"`; use this event type with
11
- * `isOrderChangedWebhookEvent()` to distinguish ordering from normal content
12
- * updates.
7
+ * Webhook records returned from ordinary list/find `secret` is encrypted at
8
+ * rest and omitted from API reads (`access.read: false` on the collection).
13
9
  */
14
- declare const ORDER_CHANGED_EVENT_TYPE: "collection.orderChanged";
15
- /** Collection webhook operations emitted for tenant collection writes. */
16
- type CollectionWebhookOperation = 'create' | 'update';
17
- /** Describes the ordered area affected by an order-change webhook. */
18
- type WebhookOrderScope = {
19
- kind: 'collection';
20
- collection: string;
21
- } | {
22
- kind: 'join';
23
- collection: string;
24
- field: string;
25
- id: string | number;
26
- };
27
- /** Identifies the public moved document for the ordered scope. */
28
- type WebhookOrderMoved = {
29
- collection: string;
30
- id: string | number;
31
- relatedCollection?: string;
32
- relatedId?: string | number;
33
- };
34
- /** Metadata attached to `collection.orderChanged` webhook events. */
35
- type WebhookOrderChange = {
36
- type: 'order';
37
- source: 'payload-orderable';
38
- /**
39
- * Diagnostic Payload order field name.
40
- *
41
- * This may contain hidden implementation field names. Application routing
42
- * should use `change.scope` and `change.moved` instead.
43
- */
44
- orderableFieldName?: string;
45
- previousOrder?: string | null;
46
- nextOrder?: string | null;
47
- scope: WebhookOrderScope;
48
- moved: WebhookOrderMoved;
49
- };
50
- /** Known semantic webhook change metadata. */
51
- type WebhookChange = WebhookOrderChange;
52
- interface WebhookEvent<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> {
53
- collection: T;
54
- operation: WebhookOperation;
55
- data: TData;
56
- eventType?: string;
57
- change?: unknown;
58
- timestamp?: string;
59
- deliveryId?: string;
60
- }
61
- type WebhookHandler<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> = (event: WebhookEvent<T, TData>) => Promise<void> | void;
62
- interface WebhookOptions {
63
- secret?: string;
64
- /** Max accepted skew for signed webhook delivery timestamps. Default: 300s. */
65
- toleranceSeconds?: number;
66
- }
67
- declare function isValidWebhookEvent(data: unknown): data is WebhookEvent;
68
- /** Webhook event emitted when manual Admin Panel ordering changes. */
69
- type OrderChangedWebhookEvent<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>> = WebhookEvent<T, TData> & {
70
- operation: 'update';
71
- eventType: typeof ORDER_CHANGED_EVENT_TYPE;
72
- change: WebhookOrderChange;
73
- };
10
+ type WebhookWithoutSecret = Omit<Webhook, 'secret'>;
74
11
  /**
75
- * Returns true for semantic order-change webhooks emitted as update events.
76
- *
77
- * Use this guard with `ORDER_CHANGED_EVENT_TYPE` instead of filtering on
78
- * `operation: "reorder"`. Tenant order-change webhooks intentionally keep
79
- * `operation: "update"` for compatibility with existing webhook handlers.
12
+ * One-time plaintext signing secret from Console reveal/rotate Admin actions.
13
+ * Persists audit metadata on the webhook document as `secretRevealedAt` /
14
+ * `secretRotatedAt` / `secretRotatedBy` (not returned in this JSON body).
80
15
  */
81
- declare function isOrderChangedWebhookEvent(event: unknown): event is OrderChangedWebhookEvent<string, unknown>;
82
- /** Narrows a webhook event to a specific collection. */
83
- declare function isWebhookCollection<TCollection extends string>(event: unknown, collection: TCollection): event is WebhookEvent<TCollection, unknown>;
84
- /** Narrows a webhook event to a specific operation. */
85
- declare function isWebhookOperation<TOperation extends string>(event: unknown, operation: TOperation): event is WebhookEvent<string, unknown> & {
86
- operation: TOperation;
87
- };
88
- declare const CUSTOMER_PASSWORD_RESET_OPERATION: "password-reset";
89
- type WebhookKnownOperation = CollectionWebhookOperation | typeof CUSTOMER_PASSWORD_RESET_OPERATION;
90
- interface CustomerPasswordResetWebhookData {
91
- customerId: string | number;
92
- email: string;
93
- name: string;
94
- resetPasswordToken: string;
95
- resetPasswordExpiresAt: string;
96
- }
97
- type CustomerPasswordResetWebhookEvent = WebhookEvent<'customers', CustomerPasswordResetWebhookData> & {
98
- operation: typeof CUSTOMER_PASSWORD_RESET_OPERATION;
16
+ type WebhookSigningSecretReveal = {
17
+ success: boolean;
18
+ webhookId: string;
19
+ /** Plaintext hex signing secret — copy to receiver `WEBHOOK_SECRET`. */
20
+ secret: string;
21
+ /** reveal-secret response timestamp (maps to `secretRevealedAt` on save). */
22
+ revealedAt?: string;
23
+ /** rotate-secret response timestamp (maps to `secretRotatedAt` on save). */
24
+ rotatedAt?: string;
99
25
  };
100
- type CustomerAuthWebhookEvent = CustomerPasswordResetWebhookEvent;
101
- type MaybePromise<T> = T | Promise<T>;
102
- interface CustomerAuthWebhookHandlers {
103
- passwordReset?: (data: CustomerPasswordResetWebhookData, event: CustomerPasswordResetWebhookEvent) => MaybePromise<void>;
104
- unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>;
105
- }
106
- declare function isCustomerPasswordResetWebhookEvent(event: WebhookEvent<string, unknown>): event is CustomerPasswordResetWebhookEvent;
107
- declare function createCustomerAuthWebhookHandler(handlers: CustomerAuthWebhookHandlers): WebhookHandler<string, unknown>;
108
- declare function handleWebhook<T extends Collection | string = Collection, TData = T extends Collection ? CollectionType<T> : Record<string, unknown>>(request: Request, handler: WebhookHandler<T, TData>, options?: WebhookOptions): Promise<Response>;
109
- declare function createTypedWebhookHandler<T extends Collection>(collection: T, handler: (event: WebhookEvent<T>) => Promise<void> | void): WebhookHandler<T>;
110
26
 
111
- export { CUSTOMER_PASSWORD_RESET_OPERATION, type CollectionWebhookOperation, type CustomerAuthWebhookEvent, type CustomerAuthWebhookHandlers, type CustomerPasswordResetWebhookData, type CustomerPasswordResetWebhookEvent, ORDER_CHANGED_EVENT_TYPE, type OrderChangedWebhookEvent, type WebhookChange, type WebhookEvent, type WebhookHandler, type WebhookKnownOperation, type WebhookOperation, type WebhookOptions, type WebhookOrderChange, type WebhookOrderMoved, type WebhookOrderScope, createCustomerAuthWebhookHandler, createTypedWebhookHandler, handleWebhook, isCustomerPasswordResetWebhookEvent, isOrderChangedWebhookEvent, isValidWebhookEvent, isWebhookCollection, isWebhookOperation };
27
+ export type { WebhookSigningSecretReveal, WebhookWithoutSecret };