@01.software/sdk 0.51.0 → 0.65.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/CHANGELOG.md +313 -0
- package/README.md +228 -102
- package/dist/client.cjs +556 -60
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +6 -6
- package/dist/client.d.ts +6 -6
- package/dist/client.js +556 -60
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-CWAeuzV4.d.cts → collection-client-B7rsTtVj.d.cts} +6 -6
- package/dist/{collection-client-hYvVfHIm.d.ts → collection-client-C2sMvfme.d.ts} +6 -6
- package/dist/{const-JD8obaKg.d.ts → const-CRxPTDGt.d.ts} +2 -2
- package/dist/{const-D8LixhAJ.d.cts → const-D6ZRQLxI.d.cts} +2 -2
- package/dist/{index-B0Hjh3Ey.d.ts → index-1auUEYrl.d.ts} +24 -7
- package/dist/{index-Bu0kCc6o.d.cts → index-Bbpf5t-l.d.cts} +24 -7
- package/dist/index.cjs +573 -260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -12
- package/dist/index.d.ts +19 -12
- package/dist/index.js +573 -260
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-BOsckg8B.d.cts → payload-types-BnIET0xU.d.cts} +567 -438
- package/dist/{payload-types-BOsckg8B.d.ts → payload-types-BnIET0xU.d.ts} +567 -438
- package/dist/query.cjs +62 -3
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +5 -5
- package/dist/query.d.ts +5 -5
- package/dist/query.js +62 -3
- package/dist/query.js.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +557 -20
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +14 -8
- package/dist/server.d.ts +14 -8
- package/dist/server.js +557 -20
- package/dist/server.js.map +1 -1
- package/dist/{types-5ZlcAFuU.d.ts → types-D1y4TgQm.d.ts} +2 -2
- package/dist/{types-Bj8j7VHU.d.ts → types-DnRC3nLG.d.ts} +464 -16
- package/dist/{types-B14sEt1z.d.cts → types-Dp1oYpD3.d.cts} +2 -2
- package/dist/{types-CM5qiR2k.d.cts → types-Dzn0LD2N.d.cts} +464 -16
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.cjs +4 -2
- package/dist/ui/video.cjs.map +1 -1
- package/dist/ui/video.d.cts +4 -2
- package/dist/ui/video.d.ts +4 -2
- package/dist/ui/video.js +4 -2
- package/dist/ui/video.js.map +1 -1
- package/dist/webhook.cjs +13 -2
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +5 -5
- package/dist/webhook.d.ts +5 -5
- package/dist/webhook.js +13 -2
- package/dist/webhook.js.map +1 -1
- package/package.json +9 -28
- package/dist/analytics/react.cjs +0 -344
- package/dist/analytics/react.cjs.map +0 -1
- package/dist/analytics/react.d.cts +0 -24
- package/dist/analytics/react.d.ts +0 -24
- package/dist/analytics/react.js +0 -319
- package/dist/analytics/react.js.map +0 -1
- package/dist/analytics.cjs +0 -238
- package/dist/analytics.cjs.map +0 -1
- package/dist/analytics.d.cts +0 -39
- package/dist/analytics.d.ts +0 -39
- package/dist/analytics.js +0 -215
- package/dist/analytics.js.map +0 -1
package/dist/webhook.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { W as WebhookHandler } from './index-
|
|
2
|
-
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 CommerceNotificationEventHandlers, m as CommerceNotificationEventName, n as CommerceNotificationHandlerContext, o as CommerceNotificationSource, p as CommerceNotificationSourceCollection, q as CommerceNotificationWebhookEvent, r as CustomerAuthWebhookEvent, s as CustomerAuthWebhookHandlers, t as CustomerPasswordResetWebhookData, u as CustomerPasswordResetWebhookEvent, O as ORDER_CHANGED_EVENT_TYPE,
|
|
3
|
-
import { C as Collection } from './const-
|
|
4
|
-
import { C as CollectionType } from './types-
|
|
5
|
-
import { W as Webhook } from './payload-types-
|
|
1
|
+
import { W as WebhookHandler } from './index-Bbpf5t-l.cjs';
|
|
2
|
+
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 CommerceNotificationEventHandlers, m as CommerceNotificationEventName, n as CommerceNotificationHandlerContext, o as CommerceNotificationSource, p as CommerceNotificationSourceCollection, q as CommerceNotificationWebhookEvent, r as CustomerAuthWebhookEvent, s as CustomerAuthWebhookHandlers, t as CustomerPasswordResetWebhookData, u as CustomerPasswordResetWebhookEvent, M as MembershipNotificationData, v as MembershipNotificationEventName, O as ORDER_CHANGED_EVENT_TYPE, w as OrderChangedWebhookEvent, P as PaymentIncidentMoney, x as PaymentIncidentNotificationData, y as PaymentIncidentNotificationEventName, z as PaymentIncidentNotificationReason, A as PaymentIncidentNotificationSourceCollection, B as PaymentIncidentNotificationStatus, D as PaymentIncidentProviderObject, E as WebhookChange, F as WebhookCommerceNotificationChange, G as WebhookEvent, H as WebhookKnownOperation, I as WebhookOperation, J as WebhookOptions, K as WebhookOrderChange, L as WebhookOrderMoved, N as WebhookOrderScope, Q as createCommerceEmailWebhookHandler, R as createCommerceNotificationWebhookHandler, S as createCustomerAuthWebhookHandler, T as createTypedWebhookHandler, U as defineCommerceEmailConfig, V as getCommerceNotificationIdempotencyKey, X as handleWebhook, Y as isCommerceNotificationWebhookEvent, Z as isCustomerPasswordResetWebhookEvent, _ as isOrderChangedWebhookEvent, $ as isValidWebhookEvent, a0 as isWebhookCollection, a1 as isWebhookOperation } from './index-Bbpf5t-l.cjs';
|
|
3
|
+
import { C as Collection } from './const-D6ZRQLxI.cjs';
|
|
4
|
+
import { C as CollectionType } from './types-Dp1oYpD3.cjs';
|
|
5
|
+
import { W as Webhook } from './payload-types-BnIET0xU.cjs';
|
|
6
6
|
|
|
7
7
|
interface SignedWebhookOptions {
|
|
8
8
|
/** Nonblank HMAC-SHA256 signing secret for this receiver. */
|
package/dist/webhook.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { W as WebhookHandler } from './index-
|
|
2
|
-
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 CommerceNotificationEventHandlers, m as CommerceNotificationEventName, n as CommerceNotificationHandlerContext, o as CommerceNotificationSource, p as CommerceNotificationSourceCollection, q as CommerceNotificationWebhookEvent, r as CustomerAuthWebhookEvent, s as CustomerAuthWebhookHandlers, t as CustomerPasswordResetWebhookData, u as CustomerPasswordResetWebhookEvent, O as ORDER_CHANGED_EVENT_TYPE,
|
|
3
|
-
import { C as Collection } from './const-
|
|
4
|
-
import { C as CollectionType } from './types-
|
|
5
|
-
import { W as Webhook } from './payload-types-
|
|
1
|
+
import { W as WebhookHandler } from './index-1auUEYrl.js';
|
|
2
|
+
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 CommerceNotificationEventHandlers, m as CommerceNotificationEventName, n as CommerceNotificationHandlerContext, o as CommerceNotificationSource, p as CommerceNotificationSourceCollection, q as CommerceNotificationWebhookEvent, r as CustomerAuthWebhookEvent, s as CustomerAuthWebhookHandlers, t as CustomerPasswordResetWebhookData, u as CustomerPasswordResetWebhookEvent, M as MembershipNotificationData, v as MembershipNotificationEventName, O as ORDER_CHANGED_EVENT_TYPE, w as OrderChangedWebhookEvent, P as PaymentIncidentMoney, x as PaymentIncidentNotificationData, y as PaymentIncidentNotificationEventName, z as PaymentIncidentNotificationReason, A as PaymentIncidentNotificationSourceCollection, B as PaymentIncidentNotificationStatus, D as PaymentIncidentProviderObject, E as WebhookChange, F as WebhookCommerceNotificationChange, G as WebhookEvent, H as WebhookKnownOperation, I as WebhookOperation, J as WebhookOptions, K as WebhookOrderChange, L as WebhookOrderMoved, N as WebhookOrderScope, Q as createCommerceEmailWebhookHandler, R as createCommerceNotificationWebhookHandler, S as createCustomerAuthWebhookHandler, T as createTypedWebhookHandler, U as defineCommerceEmailConfig, V as getCommerceNotificationIdempotencyKey, X as handleWebhook, Y as isCommerceNotificationWebhookEvent, Z as isCustomerPasswordResetWebhookEvent, _ as isOrderChangedWebhookEvent, $ as isValidWebhookEvent, a0 as isWebhookCollection, a1 as isWebhookOperation } from './index-1auUEYrl.js';
|
|
3
|
+
import { C as Collection } from './const-CRxPTDGt.js';
|
|
4
|
+
import { C as CollectionType } from './types-D1y4TgQm.js';
|
|
5
|
+
import { W as Webhook } from './payload-types-BnIET0xU.js';
|
|
6
6
|
|
|
7
7
|
interface SignedWebhookOptions {
|
|
8
8
|
/** Nonblank HMAC-SHA256 signing secret for this receiver. */
|
package/dist/webhook.js
CHANGED
|
@@ -114,7 +114,11 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
114
114
|
"returnCanceled",
|
|
115
115
|
"returnCompleted",
|
|
116
116
|
"paymentReconciliationRequired",
|
|
117
|
-
"paymentRefundRequiresAttention"
|
|
117
|
+
"paymentRefundRequiresAttention",
|
|
118
|
+
"membershipActivated",
|
|
119
|
+
"membershipPastDue",
|
|
120
|
+
"membershipExpired",
|
|
121
|
+
"membershipCancelled"
|
|
118
122
|
];
|
|
119
123
|
function isStringOrNumber(value) {
|
|
120
124
|
return typeof value === "string" || typeof value === "number";
|
|
@@ -144,7 +148,7 @@ function isCommerceNotificationEventName(value) {
|
|
|
144
148
|
return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
|
|
145
149
|
}
|
|
146
150
|
function isCommerceNotificationSourceCollection(value) {
|
|
147
|
-
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
|
|
151
|
+
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts" || value === "customer-memberships";
|
|
148
152
|
}
|
|
149
153
|
function isCommerceNotificationData(value) {
|
|
150
154
|
if (!isRecord(value)) return false;
|
|
@@ -164,6 +168,10 @@ function isPaymentIncidentNotificationData(value, event) {
|
|
|
164
168
|
const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
|
|
165
169
|
return value.source?.collection === expectedCollection && typeof value.source.id === "string" && value.source.id.length > 0 && typeof value.paymentSessionId === "string" && value.paymentSessionId.length > 0 && isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && value.providerObject.provider.length > 0 && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string" && value.providerObject.id.length > 0 && isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string" && value.money.currency.length > 0 && value.status === expectedStatus && value.reason === expectedReason && typeof value.observedAt === "string" && value.observedAt.length > 0 && !Number.isNaN(Date.parse(value.observedAt)) && (value.checkoutId === void 0 || typeof value.checkoutId === "string" && value.checkoutId.length > 0) && (value.orderId === void 0 || typeof value.orderId === "string" && value.orderId.length > 0) && (reconciliation ? value.source.id === value.paymentSessionId && value.providerObject.kind === "payment" && value.refundAttemptId === void 0 : typeof value.refundAttemptId === "string" && value.refundAttemptId.length > 0 && value.source.id === value.refundAttemptId);
|
|
166
170
|
}
|
|
171
|
+
function isMembershipNotificationData(value, event) {
|
|
172
|
+
const expectedStatus = event === "membershipActivated" ? "active" : event === "membershipPastDue" ? "past_due" : event === "membershipExpired" ? "expired" : "cancelled";
|
|
173
|
+
return typeof value.membershipId === "string" && value.membershipId.length > 0 && typeof value.planId === "string" && value.planId.length > 0 && typeof value.customerId === "string" && value.customerId.length > 0 && typeof value.fromStatus === "string" && value.fromStatus.length > 0 && value.fromStatus !== value.toStatus && value.toStatus === expectedStatus && typeof value.occurredAt === "string" && !Number.isNaN(Date.parse(value.occurredAt));
|
|
174
|
+
}
|
|
167
175
|
function isWebhookCommerceNotificationChange(value) {
|
|
168
176
|
if (!isRecord(value)) return false;
|
|
169
177
|
return value.type === "notification" && value.source === "commerce-notifications" && isCommerceNotificationEventName(value.event) && isCommerceNotificationSourceCollection(value.sourceCollection) && isStringOrNumber(value.sourceId);
|
|
@@ -212,6 +220,9 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
212
220
|
const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
|
|
213
221
|
return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
|
|
214
222
|
}
|
|
223
|
+
if (notification.event === "membershipActivated" || notification.event === "membershipPastDue" || notification.event === "membershipExpired" || notification.event === "membershipCancelled") {
|
|
224
|
+
return sourceCollection === "customer-memberships" && isMembershipNotificationData(data, notification.event) && typeof notification.membershipId === "string" && notification.membershipId === data.membershipId && matchesOptionalId(changeSourceId, data.membershipId);
|
|
225
|
+
}
|
|
215
226
|
if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
|
|
216
227
|
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);
|
|
217
228
|
}
|
package/dist/webhook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/webhook/validation.ts","../src/core/webhook/receiver.ts","../src/core/webhook/index.ts"],"sourcesContent":["export function isValidWebhookEventData(data: unknown): boolean {\n if (typeof data !== 'object' || data === null) return false\n const event = data as Record<string, unknown>\n return (\n typeof event.collection === 'string' &&\n typeof event.operation === 'string' &&\n event.operation.length > 0 &&\n typeof event.data === 'object' &&\n event.data !== null\n )\n}\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\nimport type { WebhookEvent, WebhookHandler } from './index'\nimport { isValidWebhookEventData } from './validation'\n\nexport interface SignedWebhookOptions {\n /** Nonblank HMAC-SHA256 signing secret for this receiver. */\n secret: string\n /**\n * Max accepted skew for signed webhook delivery timestamps. Default: 300s.\n * Must be a number between 0 and 86400 inclusive; anything else is a\n * configuration error, because an unbounded or effectively unbounded window\n * would accept an arbitrarily old replay.\n */\n toleranceSeconds?: number\n}\n\nasync function verifySignature(\n rawBody: Uint8Array,\n secret: string,\n signature: string,\n timestamp: string,\n deliveryId: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const signedPrefix = encoder.encode(`${timestamp}.${deliveryId}.`)\n const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length)\n signedPayload.set(signedPrefix)\n signedPayload.set(rawBody, signedPrefix.length)\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 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 return crypto.subtle.verify('HMAC', key, sigBytes, signedPayload)\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\n/**\n * Upper bound for the signed replay window. A merely finite tolerance is not\n * enough: `Number.MAX_VALUE * 1000` overflows to `Infinity`, and even without\n * overflow a value of that size accepts an arbitrarily old capture. The sender's\n * retry and dead-letter lifecycle completes far inside a day, so anything beyond\n * this is a misconfiguration rather than clock-skew tolerance.\n */\nconst MAX_TOLERANCE_SECONDS = 86_400\n\n/**\n * A signed receiver's replay window must stay bounded. A non-finite, negative,\n * or over-bound tolerance would silently accept an old capture, so it is a\n * configuration error rather than a request-authentication failure.\n */\nfunction toleranceIsValid(\n toleranceSeconds: unknown,\n): toleranceSeconds is number {\n return (\n typeof toleranceSeconds === 'number' &&\n Number.isFinite(toleranceSeconds) &&\n toleranceSeconds >= 0 &&\n toleranceSeconds <= MAX_TOLERANCE_SECONDS\n )\n}\n\nasync function processWebhookRequest<\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 verify?: (rawBody: Uint8Array) => Promise<Response | undefined>,\n): Promise<Response> {\n try {\n const rawBody = new Uint8Array(await request.arrayBuffer())\n const verificationFailure = await verify?.(rawBody)\n if (verificationFailure) return verificationFailure\n\n const body = JSON.parse(new TextDecoder().decode(rawBody))\n if (!isValidWebhookEventData(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 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 return new Response(JSON.stringify({ error: 'Internal server error' }), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n}\n\nexport async function handleSignedWebhook<\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: SignedWebhookOptions,\n): Promise<Response> {\n // Read each configuration value exactly once. Re-reading `options` would let\n // a getter return a valid secret to the guard and a different one to the\n // verifier, so the validated bytes are the only bytes this receiver uses.\n const secret: unknown = options?.secret\n const configuredTolerance: unknown = options?.toleranceSeconds\n // `??` so an absent or null tolerance keeps the documented default, exactly as\n // before this change; only a present, out-of-contract value is rejected.\n const toleranceSeconds = configuredTolerance ?? 300\n\n if (typeof secret !== 'string' || secret.trim().length === 0) {\n return new Response(\n JSON.stringify({ error: 'Webhook signing secret is not configured' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n // Reported separately so a tolerance mistake is not misdiagnosed as a bad secret.\n if (!toleranceIsValid(toleranceSeconds)) {\n return new Response(\n JSON.stringify({ error: 'Webhook signature tolerance is not valid' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n return processWebhookRequest(request, handler, async (rawBody) => {\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 valid =\n Boolean(timestamp && deliveryId) &&\n timestampIsFresh(timestamp, toleranceSeconds) &&\n (await verifySignature(rawBody, secret, signature, timestamp, 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 })\n}\n\n/** Process a webhook only when its endpoint is intentionally unsigned. */\nexport async function handleUnsignedWebhook<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n>(request: Request, handler: WebhookHandler<T, TData>): Promise<Response> {\n return processWebhookRequest(request, handler)\n}\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\nimport { handleSignedWebhook as handleSignedWebhookInternal } from './receiver'\nimport { isValidWebhookEventData } from './validation'\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 =\n | WebhookOrderChange\n | 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\n/** @deprecated Use the signed receiver options from `@01.software/sdk/webhook`. */\nexport interface WebhookOptions {\n /** Nonblank HMAC-SHA256 signing secret for this receiver. */\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 return isValidWebhookEventData(data)\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 'returnApproved',\n 'returnRejected',\n 'returnCanceled',\n 'returnCompleted',\n 'paymentReconciliationRequired',\n 'paymentRefundRequiresAttention',\n] as const\n\nexport type CommerceNotificationEventName =\n (typeof COMMERCE_NOTIFICATION_EVENTS)[number]\n\nexport type CustomerCommerceNotificationEventName = Exclude<\n CommerceNotificationEventName,\n PaymentIncidentNotificationEventName\n>\n\nexport type CommerceNotificationSourceCollection =\n | 'orders'\n | 'fulfillments'\n | 'returns'\n | 'payment-sessions'\n | 'payment-refund-attempts'\n\nexport type CommerceNotificationSource = {\n collection: CommerceNotificationSourceCollection\n id: string | number\n}\n\nexport type PaymentIncidentNotificationEventName =\n | 'paymentReconciliationRequired'\n | 'paymentRefundRequiresAttention'\n\nexport type PaymentIncidentNotificationSourceCollection =\n | 'payment-sessions'\n | 'payment-refund-attempts'\n\nexport type PaymentIncidentNotificationReason =\n | 'orderless_capture'\n | 'local_commit_ambiguous'\n\nexport type PaymentIncidentNotificationStatus =\n | 'reconciliation_required'\n | 'requires_attention'\n\nexport type PaymentIncidentProviderObject = {\n provider: string\n kind: 'payment' | 'refund'\n id: string\n}\n\nexport type PaymentIncidentMoney = {\n amountMinor: number\n currency: string\n}\n\ntype PaymentIncidentNotificationBase = {\n paymentSessionId: string\n checkoutId?: string\n orderId?: string\n providerObject: PaymentIncidentProviderObject\n money: PaymentIncidentMoney\n observedAt: string\n}\n\nexport type PaymentReconciliationRequiredNotificationData =\n PaymentIncidentNotificationBase & {\n source: {\n collection: 'payment-sessions'\n id: string\n }\n providerObject: PaymentIncidentProviderObject & { kind: 'payment' }\n status: 'reconciliation_required'\n reason: 'orderless_capture'\n refundAttemptId?: never\n }\n\nexport type PaymentRefundRequiresAttentionNotificationData =\n PaymentIncidentNotificationBase & {\n source: { collection: 'payment-refund-attempts'; id: string }\n refundAttemptId: string\n status: 'requires_attention'\n reason: 'local_commit_ambiguous'\n }\n\nexport type PaymentIncidentNotificationData =\n | PaymentReconciliationRequiredNotificationData\n | PaymentRefundRequiresAttentionNotificationData\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 paymentSessionId?: string\n checkoutId?: string\n refundAttemptId?: string\n providerObject?: PaymentIncidentProviderObject\n money?: PaymentIncidentMoney\n reason?: PaymentIncidentNotificationReason\n observedAt?: 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 paymentSessionId?: string\n refundAttemptId?: 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<CustomerCommerceNotificationEventName, CommerceEmailEventConfig>\n >\n}\n\nexport type CommerceNotificationHandlerContext = {\n event: CommerceNotificationWebhookEvent\n idempotencyKey: string\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport type CommerceNotificationEventHandlers = Partial<\n Record<\n CommerceNotificationEventName,\n (context: CommerceNotificationHandlerContext) => MaybePromise<void>\n >\n> & {\n unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>\n}\n\nexport type CommerceEmailHandlerContext = CommerceNotificationHandlerContext\n\nexport type CommerceEmailEventHandlers = Partial<\n Record<\n CustomerCommerceNotificationEventName,\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 (\n value === 'orders' ||\n value === 'fulfillments' ||\n value === 'returns' ||\n value === 'payment-sessions' ||\n value === 'payment-refund-attempts'\n )\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 ||\n typeof value.orderNumber === 'string') &&\n (value.status === undefined || typeof value.status === 'string') &&\n (value.totalAmount === undefined ||\n 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 ||\n typeof value.completedAt === 'string') &&\n (value.paymentSessionId === undefined ||\n typeof value.paymentSessionId === 'string') &&\n (value.checkoutId === undefined || typeof value.checkoutId === 'string') &&\n (value.refundAttemptId === undefined ||\n typeof value.refundAttemptId === 'string') &&\n (value.reason === undefined || typeof value.reason === 'string') &&\n (value.observedAt === undefined || typeof value.observedAt === 'string') &&\n (value.providerObject === undefined ||\n (isRecord(value.providerObject) &&\n typeof value.providerObject.provider === 'string' &&\n (value.providerObject.kind === 'payment' ||\n value.providerObject.kind === 'refund') &&\n typeof value.providerObject.id === 'string')) &&\n (value.money === undefined ||\n (isRecord(value.money) &&\n Number.isSafeInteger(value.money.amountMinor) &&\n Number(value.money.amountMinor) > 0 &&\n typeof value.money.currency === 'string'))\n )\n}\n\nfunction isCommerceNotification(value: unknown): 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 (value.paymentSessionId === undefined ||\n typeof value.paymentSessionId === 'string') &&\n (value.refundAttemptId === undefined ||\n typeof value.refundAttemptId === 'string')\n )\n}\n\nfunction isPaymentIncidentNotificationData(\n value: CommerceNotificationData,\n event: PaymentIncidentNotificationEventName,\n): boolean {\n const reconciliation = event === 'paymentReconciliationRequired'\n const expectedCollection = reconciliation\n ? 'payment-sessions'\n : 'payment-refund-attempts'\n const expectedStatus = reconciliation\n ? 'reconciliation_required'\n : 'requires_attention'\n const expectedReason = reconciliation\n ? 'orderless_capture'\n : 'local_commit_ambiguous'\n\n return (\n value.source?.collection === expectedCollection &&\n typeof value.source.id === 'string' &&\n value.source.id.length > 0 &&\n typeof value.paymentSessionId === 'string' &&\n value.paymentSessionId.length > 0 &&\n isRecord(value.providerObject) &&\n typeof value.providerObject.provider === 'string' &&\n value.providerObject.provider.length > 0 &&\n (value.providerObject.kind === 'payment' ||\n value.providerObject.kind === 'refund') &&\n typeof value.providerObject.id === 'string' &&\n value.providerObject.id.length > 0 &&\n isRecord(value.money) &&\n Number.isSafeInteger(value.money.amountMinor) &&\n Number(value.money.amountMinor) > 0 &&\n typeof value.money.currency === 'string' &&\n value.money.currency.length > 0 &&\n value.status === expectedStatus &&\n value.reason === expectedReason &&\n typeof value.observedAt === 'string' &&\n value.observedAt.length > 0 &&\n !Number.isNaN(Date.parse(value.observedAt)) &&\n (value.checkoutId === undefined ||\n (typeof value.checkoutId === 'string' && value.checkoutId.length > 0)) &&\n (value.orderId === undefined ||\n (typeof value.orderId === 'string' && value.orderId.length > 0)) &&\n (reconciliation\n ? value.source.id === value.paymentSessionId &&\n value.providerObject.kind === 'payment' &&\n value.refundAttemptId === undefined\n : typeof value.refundAttemptId === 'string' &&\n value.refundAttemptId.length > 0 &&\n value.source.id === value.refundAttemptId)\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 (\n data.source !== undefined &&\n event.collection !== data.source.collection\n ) {\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 === 'paymentReconciliationRequired' ||\n notification.event === 'paymentRefundRequiresAttention'\n ) {\n if (!isPaymentIncidentNotificationData(data, notification.event)) {\n return false\n }\n const incidentData = data as PaymentIncidentNotificationData\n const expectedCollection =\n notification.event === 'paymentReconciliationRequired'\n ? 'payment-sessions'\n : 'payment-refund-attempts'\n const notificationSourceId =\n notification.event === 'paymentReconciliationRequired'\n ? notification.paymentSessionId\n : notification.refundAttemptId\n return (\n sourceCollection === expectedCollection &&\n typeof notification.paymentSessionId === 'string' &&\n notification.paymentSessionId === incidentData.paymentSessionId &&\n typeof notificationSourceId === 'string' &&\n notificationSourceId === incidentData.source.id &&\n matchesOptionalId(changeSourceId, incidentData.source.id)\n )\n }\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 === 'returnApproved' ||\n notification.event === 'returnRejected' ||\n notification.event === 'returnCanceled' ||\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 createCommerceNotificationWebhookHandler(\n handlers: CommerceNotificationEventHandlers,\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\nexport function createCommerceEmailWebhookHandler(\n handlers: CommerceEmailEventHandlers,\n): WebhookHandler<string, unknown> {\n return createCommerceNotificationWebhookHandler(handlers)\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\n/**\n * @deprecated Import `handleSignedWebhook()` from `@01.software/sdk/webhook`.\n * This compatibility alias is signed and fails closed when its required secret\n * is missing or blank.\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 return handleSignedWebhookInternal(request, handler, options)\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/core/webhook/validation.ts","../src/core/webhook/receiver.ts","../src/core/webhook/index.ts"],"sourcesContent":["export function isValidWebhookEventData(data: unknown): boolean {\n if (typeof data !== 'object' || data === null) return false\n const event = data as Record<string, unknown>\n return (\n typeof event.collection === 'string' &&\n typeof event.operation === 'string' &&\n event.operation.length > 0 &&\n typeof event.data === 'object' &&\n event.data !== null\n )\n}\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\nimport type { WebhookEvent, WebhookHandler } from './index'\nimport { isValidWebhookEventData } from './validation'\n\nexport interface SignedWebhookOptions {\n /** Nonblank HMAC-SHA256 signing secret for this receiver. */\n secret: string\n /**\n * Max accepted skew for signed webhook delivery timestamps. Default: 300s.\n * Must be a number between 0 and 86400 inclusive; anything else is a\n * configuration error, because an unbounded or effectively unbounded window\n * would accept an arbitrarily old replay.\n */\n toleranceSeconds?: number\n}\n\nasync function verifySignature(\n rawBody: Uint8Array,\n secret: string,\n signature: string,\n timestamp: string,\n deliveryId: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const signedPrefix = encoder.encode(`${timestamp}.${deliveryId}.`)\n const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length)\n signedPayload.set(signedPrefix)\n signedPayload.set(rawBody, signedPrefix.length)\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 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 return crypto.subtle.verify('HMAC', key, sigBytes, signedPayload)\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\n/**\n * Upper bound for the signed replay window. A merely finite tolerance is not\n * enough: `Number.MAX_VALUE * 1000` overflows to `Infinity`, and even without\n * overflow a value of that size accepts an arbitrarily old capture. The sender's\n * retry and dead-letter lifecycle completes far inside a day, so anything beyond\n * this is a misconfiguration rather than clock-skew tolerance.\n */\nconst MAX_TOLERANCE_SECONDS = 86_400\n\n/**\n * A signed receiver's replay window must stay bounded. A non-finite, negative,\n * or over-bound tolerance would silently accept an old capture, so it is a\n * configuration error rather than a request-authentication failure.\n */\nfunction toleranceIsValid(\n toleranceSeconds: unknown,\n): toleranceSeconds is number {\n return (\n typeof toleranceSeconds === 'number' &&\n Number.isFinite(toleranceSeconds) &&\n toleranceSeconds >= 0 &&\n toleranceSeconds <= MAX_TOLERANCE_SECONDS\n )\n}\n\nasync function processWebhookRequest<\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 verify?: (rawBody: Uint8Array) => Promise<Response | undefined>,\n): Promise<Response> {\n try {\n const rawBody = new Uint8Array(await request.arrayBuffer())\n const verificationFailure = await verify?.(rawBody)\n if (verificationFailure) return verificationFailure\n\n const body = JSON.parse(new TextDecoder().decode(rawBody))\n if (!isValidWebhookEventData(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 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 return new Response(JSON.stringify({ error: 'Internal server error' }), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n}\n\nexport async function handleSignedWebhook<\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: SignedWebhookOptions,\n): Promise<Response> {\n // Read each configuration value exactly once. Re-reading `options` would let\n // a getter return a valid secret to the guard and a different one to the\n // verifier, so the validated bytes are the only bytes this receiver uses.\n const secret: unknown = options?.secret\n const configuredTolerance: unknown = options?.toleranceSeconds\n // `??` so an absent or null tolerance keeps the documented default, exactly as\n // before this change; only a present, out-of-contract value is rejected.\n const toleranceSeconds = configuredTolerance ?? 300\n\n if (typeof secret !== 'string' || secret.trim().length === 0) {\n return new Response(\n JSON.stringify({ error: 'Webhook signing secret is not configured' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n // Reported separately so a tolerance mistake is not misdiagnosed as a bad secret.\n if (!toleranceIsValid(toleranceSeconds)) {\n return new Response(\n JSON.stringify({ error: 'Webhook signature tolerance is not valid' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n return processWebhookRequest(request, handler, async (rawBody) => {\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 valid =\n Boolean(timestamp && deliveryId) &&\n timestampIsFresh(timestamp, toleranceSeconds) &&\n (await verifySignature(rawBody, secret, signature, timestamp, 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 })\n}\n\n/** Process a webhook only when its endpoint is intentionally unsigned. */\nexport async function handleUnsignedWebhook<\n T extends Collection | string = Collection,\n TData = T extends Collection ? CollectionType<T> : Record<string, unknown>,\n>(request: Request, handler: WebhookHandler<T, TData>): Promise<Response> {\n return processWebhookRequest(request, handler)\n}\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\nimport { handleSignedWebhook as handleSignedWebhookInternal } from './receiver'\nimport { isValidWebhookEventData } from './validation'\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 =\n | WebhookOrderChange\n | 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\n/** @deprecated Use the signed receiver options from `@01.software/sdk/webhook`. */\nexport interface WebhookOptions {\n /** Nonblank HMAC-SHA256 signing secret for this receiver. */\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 return isValidWebhookEventData(data)\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 'returnApproved',\n 'returnRejected',\n 'returnCanceled',\n 'returnCompleted',\n 'paymentReconciliationRequired',\n 'paymentRefundRequiresAttention',\n 'membershipActivated',\n 'membershipPastDue',\n 'membershipExpired',\n 'membershipCancelled',\n] as const\n\nexport type CommerceNotificationEventName =\n (typeof COMMERCE_NOTIFICATION_EVENTS)[number]\n\nexport type CustomerCommerceNotificationEventName = Exclude<\n CommerceNotificationEventName,\n PaymentIncidentNotificationEventName | MembershipNotificationEventName\n>\n\nexport type CommerceNotificationSourceCollection =\n | 'orders'\n | 'fulfillments'\n | 'returns'\n | 'payment-sessions'\n | 'payment-refund-attempts'\n | 'customer-memberships'\n\nexport type CommerceNotificationSource = {\n collection: CommerceNotificationSourceCollection\n id: string | number\n}\n\nexport type PaymentIncidentNotificationEventName =\n | 'paymentReconciliationRequired'\n | 'paymentRefundRequiresAttention'\n\nexport type MembershipNotificationEventName =\n | 'membershipActivated'\n | 'membershipPastDue'\n | 'membershipExpired'\n | 'membershipCancelled'\n\nexport type MembershipNotificationData = {\n membershipId: string\n planId: string\n /** Tenant-scoped pseudonymous identifier; this is not a PII-free claim. */\n customerId: string\n fromStatus: string\n toStatus: 'active' | 'past_due' | 'expired' | 'cancelled'\n occurredAt: string\n}\n\nexport type PaymentIncidentNotificationSourceCollection =\n | 'payment-sessions'\n | 'payment-refund-attempts'\n\nexport type PaymentIncidentNotificationReason =\n | 'orderless_capture'\n | 'local_commit_ambiguous'\n\nexport type PaymentIncidentNotificationStatus =\n | 'reconciliation_required'\n | 'requires_attention'\n\nexport type PaymentIncidentProviderObject = {\n provider: string\n kind: 'payment' | 'refund'\n id: string\n}\n\nexport type PaymentIncidentMoney = {\n amountMinor: number\n currency: string\n}\n\ntype PaymentIncidentNotificationBase = {\n paymentSessionId: string\n checkoutId?: string\n orderId?: string\n providerObject: PaymentIncidentProviderObject\n money: PaymentIncidentMoney\n observedAt: string\n}\n\nexport type PaymentReconciliationRequiredNotificationData =\n PaymentIncidentNotificationBase & {\n source: {\n collection: 'payment-sessions'\n id: string\n }\n providerObject: PaymentIncidentProviderObject & { kind: 'payment' }\n status: 'reconciliation_required'\n reason: 'orderless_capture'\n refundAttemptId?: never\n }\n\nexport type PaymentRefundRequiresAttentionNotificationData =\n PaymentIncidentNotificationBase & {\n source: { collection: 'payment-refund-attempts'; id: string }\n refundAttemptId: string\n status: 'requires_attention'\n reason: 'local_commit_ambiguous'\n }\n\nexport type PaymentIncidentNotificationData =\n | PaymentReconciliationRequiredNotificationData\n | PaymentRefundRequiresAttentionNotificationData\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 paymentSessionId?: string\n checkoutId?: string\n refundAttemptId?: string\n providerObject?: PaymentIncidentProviderObject\n money?: PaymentIncidentMoney\n reason?: PaymentIncidentNotificationReason\n observedAt?: string\n membershipId?: string\n planId?: string\n customerId?: string\n fromStatus?: string\n toStatus?: string\n occurredAt?: 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 paymentSessionId?: string\n refundAttemptId?: string\n membershipId?: 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<CustomerCommerceNotificationEventName, CommerceEmailEventConfig>\n >\n}\n\nexport type CommerceNotificationHandlerContext = {\n event: CommerceNotificationWebhookEvent\n idempotencyKey: string\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport type CommerceNotificationEventHandlers = Partial<\n Record<\n CommerceNotificationEventName,\n (context: CommerceNotificationHandlerContext) => MaybePromise<void>\n >\n> & {\n unhandled?: (event: WebhookEvent<string, unknown>) => MaybePromise<void>\n}\n\nexport type CommerceEmailHandlerContext = CommerceNotificationHandlerContext\n\nexport type CommerceEmailEventHandlers = Partial<\n Record<\n CustomerCommerceNotificationEventName,\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 (\n value === 'orders' ||\n value === 'fulfillments' ||\n value === 'returns' ||\n value === 'payment-sessions' ||\n value === 'payment-refund-attempts' ||\n value === 'customer-memberships'\n )\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 ||\n typeof value.orderNumber === 'string') &&\n (value.status === undefined || typeof value.status === 'string') &&\n (value.totalAmount === undefined ||\n 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 ||\n typeof value.completedAt === 'string') &&\n (value.paymentSessionId === undefined ||\n typeof value.paymentSessionId === 'string') &&\n (value.checkoutId === undefined || typeof value.checkoutId === 'string') &&\n (value.refundAttemptId === undefined ||\n typeof value.refundAttemptId === 'string') &&\n (value.reason === undefined || typeof value.reason === 'string') &&\n (value.observedAt === undefined || typeof value.observedAt === 'string') &&\n (value.providerObject === undefined ||\n (isRecord(value.providerObject) &&\n typeof value.providerObject.provider === 'string' &&\n (value.providerObject.kind === 'payment' ||\n value.providerObject.kind === 'refund') &&\n typeof value.providerObject.id === 'string')) &&\n (value.money === undefined ||\n (isRecord(value.money) &&\n Number.isSafeInteger(value.money.amountMinor) &&\n Number(value.money.amountMinor) > 0 &&\n typeof value.money.currency === 'string'))\n )\n}\n\nfunction isCommerceNotification(value: unknown): 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 (value.paymentSessionId === undefined ||\n typeof value.paymentSessionId === 'string') &&\n (value.refundAttemptId === undefined ||\n typeof value.refundAttemptId === 'string')\n )\n}\n\nfunction isPaymentIncidentNotificationData(\n value: CommerceNotificationData,\n event: PaymentIncidentNotificationEventName,\n): boolean {\n const reconciliation = event === 'paymentReconciliationRequired'\n const expectedCollection = reconciliation\n ? 'payment-sessions'\n : 'payment-refund-attempts'\n const expectedStatus = reconciliation\n ? 'reconciliation_required'\n : 'requires_attention'\n const expectedReason = reconciliation\n ? 'orderless_capture'\n : 'local_commit_ambiguous'\n\n return (\n value.source?.collection === expectedCollection &&\n typeof value.source.id === 'string' &&\n value.source.id.length > 0 &&\n typeof value.paymentSessionId === 'string' &&\n value.paymentSessionId.length > 0 &&\n isRecord(value.providerObject) &&\n typeof value.providerObject.provider === 'string' &&\n value.providerObject.provider.length > 0 &&\n (value.providerObject.kind === 'payment' ||\n value.providerObject.kind === 'refund') &&\n typeof value.providerObject.id === 'string' &&\n value.providerObject.id.length > 0 &&\n isRecord(value.money) &&\n Number.isSafeInteger(value.money.amountMinor) &&\n Number(value.money.amountMinor) > 0 &&\n typeof value.money.currency === 'string' &&\n value.money.currency.length > 0 &&\n value.status === expectedStatus &&\n value.reason === expectedReason &&\n typeof value.observedAt === 'string' &&\n value.observedAt.length > 0 &&\n !Number.isNaN(Date.parse(value.observedAt)) &&\n (value.checkoutId === undefined ||\n (typeof value.checkoutId === 'string' && value.checkoutId.length > 0)) &&\n (value.orderId === undefined ||\n (typeof value.orderId === 'string' && value.orderId.length > 0)) &&\n (reconciliation\n ? value.source.id === value.paymentSessionId &&\n value.providerObject.kind === 'payment' &&\n value.refundAttemptId === undefined\n : typeof value.refundAttemptId === 'string' &&\n value.refundAttemptId.length > 0 &&\n value.source.id === value.refundAttemptId)\n )\n}\n\nfunction isMembershipNotificationData(\n value: CommerceNotificationData,\n event: MembershipNotificationEventName,\n): boolean {\n const expectedStatus =\n event === 'membershipActivated'\n ? 'active'\n : event === 'membershipPastDue'\n ? 'past_due'\n : event === 'membershipExpired'\n ? 'expired'\n : 'cancelled'\n return (\n typeof value.membershipId === 'string' &&\n value.membershipId.length > 0 &&\n typeof value.planId === 'string' &&\n value.planId.length > 0 &&\n typeof value.customerId === 'string' &&\n value.customerId.length > 0 &&\n typeof value.fromStatus === 'string' &&\n value.fromStatus.length > 0 &&\n value.fromStatus !== value.toStatus &&\n value.toStatus === expectedStatus &&\n typeof value.occurredAt === 'string' &&\n !Number.isNaN(Date.parse(value.occurredAt))\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 (\n data.source !== undefined &&\n event.collection !== data.source.collection\n ) {\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 === 'paymentReconciliationRequired' ||\n notification.event === 'paymentRefundRequiresAttention'\n ) {\n if (!isPaymentIncidentNotificationData(data, notification.event)) {\n return false\n }\n const incidentData = data as PaymentIncidentNotificationData\n const expectedCollection =\n notification.event === 'paymentReconciliationRequired'\n ? 'payment-sessions'\n : 'payment-refund-attempts'\n const notificationSourceId =\n notification.event === 'paymentReconciliationRequired'\n ? notification.paymentSessionId\n : notification.refundAttemptId\n return (\n sourceCollection === expectedCollection &&\n typeof notification.paymentSessionId === 'string' &&\n notification.paymentSessionId === incidentData.paymentSessionId &&\n typeof notificationSourceId === 'string' &&\n notificationSourceId === incidentData.source.id &&\n matchesOptionalId(changeSourceId, incidentData.source.id)\n )\n }\n\n if (\n notification.event === 'membershipActivated' ||\n notification.event === 'membershipPastDue' ||\n notification.event === 'membershipExpired' ||\n notification.event === 'membershipCancelled'\n ) {\n return (\n sourceCollection === 'customer-memberships' &&\n isMembershipNotificationData(data, notification.event) &&\n typeof notification.membershipId === 'string' &&\n notification.membershipId === data.membershipId &&\n matchesOptionalId(changeSourceId, data.membershipId)\n )\n }\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 === 'returnApproved' ||\n notification.event === 'returnRejected' ||\n notification.event === 'returnCanceled' ||\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 createCommerceNotificationWebhookHandler(\n handlers: CommerceNotificationEventHandlers,\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\nexport function createCommerceEmailWebhookHandler(\n handlers: CommerceEmailEventHandlers,\n): WebhookHandler<string, unknown> {\n return createCommerceNotificationWebhookHandler(handlers)\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\n/**\n * @deprecated Import `handleSignedWebhook()` from `@01.software/sdk/webhook`.\n * This compatibility alias is signed and fails closed when its required secret\n * is missing or blank.\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 return handleSignedWebhookInternal(request, handler, options)\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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@01.software/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.65.0",
|
|
4
4
|
"description": "01.software SDK",
|
|
5
5
|
"author": "<office@01.works>",
|
|
6
6
|
"repository": {
|
|
@@ -54,26 +54,6 @@
|
|
|
54
54
|
"default": "./dist/errors.cjs"
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
|
-
"./analytics": {
|
|
58
|
-
"import": {
|
|
59
|
-
"types": "./dist/analytics.d.ts",
|
|
60
|
-
"default": "./dist/analytics.js"
|
|
61
|
-
},
|
|
62
|
-
"require": {
|
|
63
|
-
"types": "./dist/analytics.d.cts",
|
|
64
|
-
"default": "./dist/analytics.cjs"
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
"./analytics/react": {
|
|
68
|
-
"import": {
|
|
69
|
-
"types": "./dist/analytics/react.d.ts",
|
|
70
|
-
"default": "./dist/analytics/react.js"
|
|
71
|
-
},
|
|
72
|
-
"require": {
|
|
73
|
-
"types": "./dist/analytics/react.d.cts",
|
|
74
|
-
"default": "./dist/analytics/react.cjs"
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
57
|
"./query": {
|
|
78
58
|
"import": {
|
|
79
59
|
"types": "./dist/query.d.ts",
|
|
@@ -226,22 +206,26 @@
|
|
|
226
206
|
"CHANGELOG.md"
|
|
227
207
|
],
|
|
228
208
|
"devDependencies": {
|
|
209
|
+
"@01.software/http-contracts": "0.1.0",
|
|
229
210
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
230
211
|
"@mux/mux-player-react": "^3.13.0",
|
|
231
|
-
"@payloadcms/richtext-lexical": "3.
|
|
212
|
+
"@payloadcms/richtext-lexical": "3.90.0",
|
|
213
|
+
"@repo/eslint-config": "0.0.0",
|
|
214
|
+
"@repo/typescript-config": "0.0.0",
|
|
232
215
|
"@tanstack/react-query": "5.100.9",
|
|
233
216
|
"@testing-library/jest-dom": "^6.9.1",
|
|
234
217
|
"@testing-library/react": "16.3.2",
|
|
235
218
|
"@types/node": "^22.19.18",
|
|
236
219
|
"@types/react": "^19.2.14",
|
|
237
220
|
"@types/react-dom": "^19.2.3",
|
|
238
|
-
"@vitest/coverage-v8": "4.1.
|
|
221
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
239
222
|
"@xyflow/react": "^12.11.2",
|
|
240
223
|
"eslint": "^9.39.4",
|
|
241
224
|
"hast-util-to-jsx-runtime": "^2.3.6",
|
|
242
225
|
"jsdom": "26.1.0",
|
|
243
226
|
"monaco-editor": "0.55.1",
|
|
244
|
-
"
|
|
227
|
+
"next": "16.3.8",
|
|
228
|
+
"payload": "3.90.0",
|
|
245
229
|
"postcss": "8.5.23",
|
|
246
230
|
"publint": "^0.3.20",
|
|
247
231
|
"quickjs-emscripten": "0.32.0",
|
|
@@ -252,10 +236,7 @@
|
|
|
252
236
|
"sucrase": "^3.35.1",
|
|
253
237
|
"tsup": "^8.5.1",
|
|
254
238
|
"typescript": "5.7.3",
|
|
255
|
-
"vitest": "^4.1.
|
|
256
|
-
"@01.software/http-contracts": "0.1.0",
|
|
257
|
-
"@repo/eslint-config": "0.0.0",
|
|
258
|
-
"@repo/typescript-config": "0.0.0"
|
|
239
|
+
"vitest": "^4.1.11"
|
|
259
240
|
},
|
|
260
241
|
"dependencies": {
|
|
261
242
|
"jose": "^6.2.3",
|