better-ship 0.40.0 → 0.41.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 (119) hide show
  1. package/dist/{application-xXTCe8o0.js → application-CnsIQX8h.js} +55 -10
  2. package/dist/application-CnsIQX8h.js.map +1 -0
  3. package/dist/application.d.ts +3 -3
  4. package/dist/application.js +2 -2
  5. package/dist/{auth-secondary-storage-CcNkkEk0.d.ts → auth-secondary-storage-DlzjamBm.d.ts} +2 -2
  6. package/dist/{auth-secondary-storage-CcNkkEk0.d.ts.map → auth-secondary-storage-DlzjamBm.d.ts.map} +1 -1
  7. package/dist/better-auth/apple-client-secret.d.ts +1 -1
  8. package/dist/better-auth/apple-client-secret.js +1 -1
  9. package/dist/better-auth/auth-client.js +1 -1
  10. package/dist/better-auth/rate-limit.d.ts +1 -1
  11. package/dist/better-auth/rate-limit.js +1 -1
  12. package/dist/better-auth/secondary-storage.d.ts +1 -1
  13. package/dist/better-auth.js +1 -1
  14. package/dist/billing/client.d.ts +1 -1
  15. package/dist/billing/client.js +1 -1
  16. package/dist/browser-support/floor.d.ts +1 -1
  17. package/dist/browser-support/floor.js +1 -1
  18. package/dist/browser-support/oxlint.js +1 -1
  19. package/dist/client-BZgpmuSp.js +27 -0
  20. package/dist/client-BZgpmuSp.js.map +1 -0
  21. package/dist/cloudflare/auth-secondary-storage.d.ts +1 -1
  22. package/dist/cloudflare/auth-secondary-storage.js +1 -1
  23. package/dist/cloudflare/durable-object-client.js +2 -2
  24. package/dist/cloudflare/durable-object-errors.d.ts +1 -1
  25. package/dist/cloudflare/durable-object-errors.js +1 -1
  26. package/dist/cloudflare/kv-client.js +2 -2
  27. package/dist/cloudflare/kv-errors.d.ts +1 -1
  28. package/dist/cloudflare/kv-errors.js +1 -1
  29. package/dist/cloudflare/queue.d.ts +3 -21
  30. package/dist/cloudflare/queue.d.ts.map +1 -1
  31. package/dist/cloudflare/queue.js +11 -52
  32. package/dist/cloudflare/queue.js.map +1 -1
  33. package/dist/cloudflare/r2-client.js +2 -2
  34. package/dist/cloudflare/r2-errors.d.ts +1 -1
  35. package/dist/cloudflare/r2-errors.js +1 -1
  36. package/dist/cloudflare/rate-limiter.d.ts +1 -1
  37. package/dist/cloudflare/rate-limiter.js +1 -1
  38. package/dist/cloudflare/scheduled.d.ts +1 -1
  39. package/dist/cloudflare/scheduled.js +1 -1
  40. package/dist/cloudflare/turnstile.d.ts +1 -1
  41. package/dist/cloudflare/turnstile.js +1 -1
  42. package/dist/cloudflare.d.ts +3 -3
  43. package/dist/cloudflare.js +3 -3
  44. package/dist/{core-DOBZeYSX.js → core-CV8SQv01.js} +65 -4
  45. package/dist/core-CV8SQv01.js.map +1 -0
  46. package/dist/core.d.ts +2 -2
  47. package/dist/core.js +2 -2
  48. package/dist/{durable-object-errors-CcfTu0PQ.js → durable-object-errors-C7e7essH.js} +2 -2
  49. package/dist/{durable-object-errors-CcfTu0PQ.js.map → durable-object-errors-C7e7essH.js.map} +1 -1
  50. package/dist/{floor-BTBtPI9_.js → floor-BdRTO_LO.js} +2 -2
  51. package/dist/{floor-BTBtPI9_.js.map → floor-BdRTO_LO.js.map} +1 -1
  52. package/dist/http.d.ts +2 -2
  53. package/dist/http.js +2 -2
  54. package/dist/{index-Db2GV9ZP.d.ts → index-DaiY8xJJ.d.ts} +32 -4
  55. package/dist/index-DaiY8xJJ.d.ts.map +1 -0
  56. package/dist/{index-CtIdbnEZ.d.ts → index-tJzJUgTh.d.ts} +30 -4
  57. package/dist/index-tJzJUgTh.d.ts.map +1 -0
  58. package/dist/{kv-errors-B2k_2lyY.js → kv-errors-DXbnO7cB.js} +2 -2
  59. package/dist/{kv-errors-B2k_2lyY.js.map → kv-errors-DXbnO7cB.js.map} +1 -1
  60. package/dist/{metrics-DRCoGBNF.d.ts → metrics-DzSCDk-u.d.ts} +2 -2
  61. package/dist/{metrics-DRCoGBNF.d.ts.map → metrics-DzSCDk-u.d.ts.map} +1 -1
  62. package/dist/{outbox-repository-options-Cmf0vbBQ.d.ts → outbox-repository-options-BPsuMSwA.d.ts} +3 -3
  63. package/dist/{outbox-repository-options-Cmf0vbBQ.d.ts.map → outbox-repository-options-BPsuMSwA.d.ts.map} +1 -1
  64. package/dist/{outbox-repository-options-Dd-s5SxA.js → outbox-repository-options-DTsXMiR1.js} +2 -2
  65. package/dist/{outbox-repository-options-Dd-s5SxA.js.map → outbox-repository-options-DTsXMiR1.js.map} +1 -1
  66. package/dist/{payment-service.error-BR10zqxk.js → payment-service.error-oW2bKAfU.js} +2 -2
  67. package/dist/{payment-service.error-BR10zqxk.js.map → payment-service.error-oW2bKAfU.js.map} +1 -1
  68. package/dist/postgres.d.ts +3 -3
  69. package/dist/postgres.js +3 -3
  70. package/dist/posthog/metrics.d.ts +1 -1
  71. package/dist/posthog/server.d.ts +3 -3
  72. package/dist/posthog/server.js +1 -1
  73. package/dist/{r2-errors-BF49eqU_.js → r2-errors-DzpOvciV.js} +2 -2
  74. package/dist/{r2-errors-BF49eqU_.js.map → r2-errors-DzpOvciV.js.map} +1 -1
  75. package/dist/{request-BYQodKDU.js → request-C5k8ME_7.js} +2 -2
  76. package/dist/{request-BYQodKDU.js.map → request-C5k8ME_7.js.map} +1 -1
  77. package/dist/resend.d.ts +3 -3
  78. package/dist/resend.js +2 -2
  79. package/dist/sentry/client.d.ts +1 -1
  80. package/dist/sentry/client.js +1 -1
  81. package/dist/sentry/server.d.ts +2 -2
  82. package/dist/sentry/tanstack.d.ts +1 -1
  83. package/dist/stripe/client.d.ts +7 -2
  84. package/dist/stripe/client.d.ts.map +1 -1
  85. package/dist/stripe/client.js +1 -1
  86. package/dist/stripe/payment-service.error.d.ts +1 -1
  87. package/dist/stripe/payment-service.error.js +1 -1
  88. package/dist/stripe/payment-service.js +1 -1
  89. package/dist/stripe/payment-webhook.d.ts +1 -1
  90. package/dist/stripe/payment-webhook.js +1 -1
  91. package/dist/stripe/request.js +1 -1
  92. package/dist/{stripe-fixture-yFUknTJO.js → stripe-fixture-11EmnD6F.js} +2 -2
  93. package/dist/{stripe-fixture-yFUknTJO.js.map → stripe-fixture-11EmnD6F.js.map} +1 -1
  94. package/dist/tanstack.d.ts +1 -1
  95. package/dist/tanstack.js +1 -1
  96. package/dist/testing/outbox-repository.d.ts +2 -2
  97. package/dist/testing/payment-service.js +2 -2
  98. package/dist/testing/stripe.js +1 -1
  99. package/dist/{webhook-verification-C4R6OO7f.js → webhook-verification-B8v3-LQ2.js} +2 -2
  100. package/dist/{webhook-verification-C4R6OO7f.js.map → webhook-verification-B8v3-LQ2.js.map} +1 -1
  101. package/dist/{webhook-verification-DL4L3zbu.d.ts → webhook-verification-Cy4Z5djk.d.ts} +2 -2
  102. package/dist/{webhook-verification-DL4L3zbu.d.ts.map → webhook-verification-Cy4Z5djk.d.ts.map} +1 -1
  103. package/package.json +1 -1
  104. package/src/application/index.ts +5 -0
  105. package/src/application/outbox-relay.ts +18 -13
  106. package/src/application/queue-or-rpc-publisher.ts +64 -0
  107. package/src/core/classify-failure.ts +12 -2
  108. package/src/core/index.ts +6 -0
  109. package/src/core/redelivery-policy.ts +66 -0
  110. package/src/infrastructure/cloudflare/queue/index.ts +0 -1
  111. package/src/infrastructure/cloudflare/queue/queue-consumer.ts +11 -4
  112. package/src/infrastructure/stripe/client.ts +7 -3
  113. package/dist/application-xXTCe8o0.js.map +0 -1
  114. package/dist/client-Dv1Ch7yY.js +0 -20
  115. package/dist/client-Dv1Ch7yY.js.map +0 -1
  116. package/dist/core-DOBZeYSX.js.map +0 -1
  117. package/dist/index-CtIdbnEZ.d.ts.map +0 -1
  118. package/dist/index-Db2GV9ZP.d.ts.map +0 -1
  119. package/src/infrastructure/cloudflare/queue/redelivery-policy.ts +0 -64
@@ -1 +1 @@
1
- {"version":3,"file":"durable-object-errors-CcfTu0PQ.js","names":[],"sources":["../src/infrastructure/cloudflare/durable-object-errors.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport {\n AppError,\n isAbortError,\n isCloudflareOverloadedError,\n isCloudflareRetryableError,\n isTransientCloudflareRuntimeError,\n isTransientTransportError,\n type FailureClassification,\n} from '@/core'\n\n/** Stable tag for a failed Durable Object call. */\nexport const DURABLE_OBJECT_CALL_ERROR = 'DurableObjectCallError'\n\nconst RemoteClassifiedErrorSchema = z.object({\n _tag: z.string(),\n classification: z.enum(['transient', 'terminal', 'unknown']),\n remote: z.literal(true),\n})\n\nconst RemoteCallErrorSchema = RemoteClassifiedErrorSchema.extend({\n _tag: z.literal(DURABLE_OBJECT_CALL_ERROR),\n cause: z.unknown(),\n})\n\n/** Recognize a judged local or remote error without admitting its tag to the public error table. */\nexport function isClassifiedDurableObjectError(\n cause: unknown,\n): cause is AppError | (Error & z.output<typeof RemoteClassifiedErrorSchema>) {\n return (\n cause instanceof AppError ||\n (cause instanceof Error && RemoteClassifiedErrorSchema.safeParse(cause).success)\n )\n}\n\n/** Classify the error itself. Its cause remains diagnostic evidence, not a second retry decision. */\nexport function classifyDurableObjectError(cause: unknown): FailureClassification {\n if (isAbortError(cause)) return 'terminal'\n if (isClassifiedDurableObjectError(cause)) return cause.classification\n if (isCloudflareOverloadedError(cause)) return 'terminal'\n if (\n isCloudflareRetryableError(cause) ||\n isTransientCloudflareRuntimeError(cause) ||\n isTransientTransportError(cause)\n )\n return 'transient'\n return 'unknown'\n}\n\n/** Identify a local call error or its validated Workers RPC representation. */\nexport function isDurableObjectCallError(\n cause: unknown,\n): cause is DurableObjectCallError | (Error & z.output<typeof RemoteCallErrorSchema>) {\n return (\n cause instanceof DurableObjectCallError ||\n (cause instanceof Error && RemoteCallErrorSchema.safeParse(cause).success)\n )\n}\n\n/** A call failed after retries stopped. Classification does not establish repeat safety. */\nexport class DurableObjectCallError extends AppError {\n readonly _tag = DURABLE_OBJECT_CALL_ERROR\n readonly classification: FailureClassification\n\n constructor(args: { readonly cause: unknown }) {\n super('Durable Object call failed', { cause: args.cause })\n this.classification = classifyDurableObjectError(args.cause)\n }\n}\n"],"mappings":";;;;;AAaA,MAAa,4BAA4B;AAEzC,MAAM,8BAA8B,EAAE,OAAO;CAC3C,MAAM,EAAE,OAAO;CACf,gBAAgB,EAAE,KAAK;EAAC;EAAa;EAAY;CAAS,CAAC;CAC3D,QAAQ,EAAE,QAAQ,IAAI;AACxB,CAAC;AAED,MAAM,wBAAwB,4BAA4B,OAAO;CAC/D,MAAM,EAAE,QAAQ,yBAAyB;CACzC,OAAO,EAAE,QAAQ;AACnB,CAAC;;AAGD,SAAgB,+BACd,OAC4E;CAC5E,OACE,iBAAiB,YAChB,iBAAiB,SAAS,4BAA4B,UAAU,KAAK,CAAC,CAAC;AAE5E;;AAGA,SAAgB,2BAA2B,OAAuC;CAChF,IAAI,aAAa,KAAK,GAAG,OAAO;CAChC,IAAI,+BAA+B,KAAK,GAAG,OAAO,MAAM;CACxD,IAAI,4BAA4B,KAAK,GAAG,OAAO;CAC/C,IACE,2BAA2B,KAAK,KAChC,kCAAkC,KAAK,KACvC,0BAA0B,KAAK,GAE/B,OAAO;CACT,OAAO;AACT;;AAGA,SAAgB,yBACd,OACoF;CACpF,OACE,iBAAiB,0BAChB,iBAAiB,SAAS,sBAAsB,UAAU,KAAK,CAAC,CAAC;AAEtE;;AAGA,IAAa,yBAAb,cAA4C,SAAS;CACnD,AAAS,OAAO;CAChB,AAAS;CAET,YAAY,MAAmC;EAC7C,MAAM,8BAA8B,EAAE,OAAO,KAAK,MAAM,CAAC;EACzD,KAAK,iBAAiB,2BAA2B,KAAK,KAAK;CAC7D;AACF"}
1
+ {"version":3,"file":"durable-object-errors-C7e7essH.js","names":[],"sources":["../src/infrastructure/cloudflare/durable-object-errors.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport {\n AppError,\n isAbortError,\n isCloudflareOverloadedError,\n isCloudflareRetryableError,\n isTransientCloudflareRuntimeError,\n isTransientTransportError,\n type FailureClassification,\n} from '@/core'\n\n/** Stable tag for a failed Durable Object call. */\nexport const DURABLE_OBJECT_CALL_ERROR = 'DurableObjectCallError'\n\nconst RemoteClassifiedErrorSchema = z.object({\n _tag: z.string(),\n classification: z.enum(['transient', 'terminal', 'unknown']),\n remote: z.literal(true),\n})\n\nconst RemoteCallErrorSchema = RemoteClassifiedErrorSchema.extend({\n _tag: z.literal(DURABLE_OBJECT_CALL_ERROR),\n cause: z.unknown(),\n})\n\n/** Recognize a judged local or remote error without admitting its tag to the public error table. */\nexport function isClassifiedDurableObjectError(\n cause: unknown,\n): cause is AppError | (Error & z.output<typeof RemoteClassifiedErrorSchema>) {\n return (\n cause instanceof AppError ||\n (cause instanceof Error && RemoteClassifiedErrorSchema.safeParse(cause).success)\n )\n}\n\n/** Classify the error itself. Its cause remains diagnostic evidence, not a second retry decision. */\nexport function classifyDurableObjectError(cause: unknown): FailureClassification {\n if (isAbortError(cause)) return 'terminal'\n if (isClassifiedDurableObjectError(cause)) return cause.classification\n if (isCloudflareOverloadedError(cause)) return 'terminal'\n if (\n isCloudflareRetryableError(cause) ||\n isTransientCloudflareRuntimeError(cause) ||\n isTransientTransportError(cause)\n )\n return 'transient'\n return 'unknown'\n}\n\n/** Identify a local call error or its validated Workers RPC representation. */\nexport function isDurableObjectCallError(\n cause: unknown,\n): cause is DurableObjectCallError | (Error & z.output<typeof RemoteCallErrorSchema>) {\n return (\n cause instanceof DurableObjectCallError ||\n (cause instanceof Error && RemoteCallErrorSchema.safeParse(cause).success)\n )\n}\n\n/** A call failed after retries stopped. Classification does not establish repeat safety. */\nexport class DurableObjectCallError extends AppError {\n readonly _tag = DURABLE_OBJECT_CALL_ERROR\n readonly classification: FailureClassification\n\n constructor(args: { readonly cause: unknown }) {\n super('Durable Object call failed', { cause: args.cause })\n this.classification = classifyDurableObjectError(args.cause)\n }\n}\n"],"mappings":";;;;;AAaA,MAAa,4BAA4B;AAEzC,MAAM,8BAA8B,EAAE,OAAO;CAC3C,MAAM,EAAE,OAAO;CACf,gBAAgB,EAAE,KAAK;EAAC;EAAa;EAAY;CAAS,CAAC;CAC3D,QAAQ,EAAE,QAAQ,IAAI;AACxB,CAAC;AAED,MAAM,wBAAwB,4BAA4B,OAAO;CAC/D,MAAM,EAAE,QAAQ,yBAAyB;CACzC,OAAO,EAAE,QAAQ;AACnB,CAAC;;AAGD,SAAgB,+BACd,OAC4E;CAC5E,OACE,iBAAiB,YAChB,iBAAiB,SAAS,4BAA4B,UAAU,KAAK,CAAC,CAAC;AAE5E;;AAGA,SAAgB,2BAA2B,OAAuC;CAChF,IAAI,aAAa,KAAK,GAAG,OAAO;CAChC,IAAI,+BAA+B,KAAK,GAAG,OAAO,MAAM;CACxD,IAAI,4BAA4B,KAAK,GAAG,OAAO;CAC/C,IACE,2BAA2B,KAAK,KAChC,kCAAkC,KAAK,KACvC,0BAA0B,KAAK,GAE/B,OAAO;CACT,OAAO;AACT;;AAGA,SAAgB,yBACd,OACoF;CACpF,OACE,iBAAiB,0BAChB,iBAAiB,SAAS,sBAAsB,UAAU,KAAK,CAAC,CAAC;AAEtE;;AAGA,IAAa,yBAAb,cAA4C,SAAS;CACnD,AAAS,OAAO;CAChB,AAAS;CAET,YAAY,MAAmC;EAC7C,MAAM,8BAA8B,EAAE,OAAO,KAAK,MAAM,CAAC;EACzD,KAAK,iBAAiB,2BAA2B,KAAK,KAAK;CAC7D;AACF"}
@@ -1,4 +1,4 @@
1
- import { tt as AppError } from "./core-DOBZeYSX.js";
1
+ import { rt as AppError } from "./core-CV8SQv01.js";
2
2
  import browserslist from "browserslist";
3
3
 
4
4
  //#region src/infrastructure/browser-support/browser-floor.error.ts
@@ -143,4 +143,4 @@ function browserLabel(browser) {
143
143
 
144
144
  //#endregion
145
145
  export { BrowserFloorError as i, buildTargets as n, updateScreenCopy as r, browserFloor as t };
146
- //# sourceMappingURL=floor-BTBtPI9_.js.map
146
+ //# sourceMappingURL=floor-BdRTO_LO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"floor-BTBtPI9_.js","names":[],"sources":["../src/infrastructure/browser-support/browser-floor.error.ts","../src/infrastructure/browser-support/floor.ts"],"sourcesContent":["import { AppError } from '@/core'\n\n/** The browserslist file is missing, empty, or not a query browserslist can resolve. */\nexport class BrowserFloorError extends AppError {\n readonly _tag = 'BrowserFloorError'\n readonly classification = 'terminal'\n\n /**\n * `path` is the file or directory passed to `browserFloor`.\n * `reason` is `missing` when no config is found, `empty` when the query matches no browsers,\n * and `invalid` when browserslist rejects the query. `cause` is that rejection.\n */\n constructor(\n readonly path: string,\n readonly reason: 'missing' | 'empty' | 'invalid',\n cause?: unknown,\n ) {\n super(floorMessage(reason, path), { cause })\n }\n}\n\nfunction floorMessage(reason: 'missing' | 'empty' | 'invalid', path: string): string {\n switch (reason) {\n case 'missing':\n return `No browserslist config at ${path}`\n case 'empty':\n return `The browserslist config at ${path} matches no browsers`\n case 'invalid':\n return `The browserslist config at ${path} is invalid`\n }\n}\n","import browserslist from 'browserslist'\n\nimport { BrowserFloorError } from './browser-floor.error.ts'\n\nexport { BrowserFloorError }\n\n/** Oldest and newest version of one browser that the floor still includes. */\nexport type BrowserFloorRelease = {\n readonly browser: string\n readonly minimum: string\n readonly maximum: string\n}\n\n/** Title and body for the update screen, taken from the floor versions. */\nexport type UpdateScreenCopy = {\n readonly title: string\n readonly body: string\n}\n\n/**\n * Resolve the minimum and maximum version of each browser in the browserslist config.\n * The path is a config file or any file inside the project that owns `.browserslistrc`.\n * Throws `BrowserFloorError` when the config is missing, empty, or invalid.\n */\nexport function browserFloor(path: string): readonly BrowserFloorRelease[] {\n const queries = loadQueries(path)\n if (queries === undefined) throw new BrowserFloorError(path, 'missing')\n if (queries.length === 0) throw new BrowserFloorError(path, 'empty')\n let resolved: readonly string[]\n try {\n resolved = browserslist(queries, { path })\n } catch (cause) {\n throw new BrowserFloorError(path, 'invalid', cause)\n }\n const releases = floorReleases(resolved)\n if (releases.length === 0) throw new BrowserFloorError(path, 'empty')\n return releases\n}\n\n/**\n * Vite `environments.client.build.target` values for the browserslist config at `path`.\n * Throws `BrowserFloorError` when the config is missing, empty, or invalid.\n */\nexport function buildTargets(path: string): readonly string[] {\n return browserFloor(path).map((release) => `${viteBrowser(release.browser)}${release.minimum}`)\n}\n\n/** Sentence that names the floor versions. Pass the result of `browserFloor`. */\nexport function updateScreenCopy(releases: readonly BrowserFloorRelease[]): UpdateScreenCopy {\n const versions = releases\n .map((release) => `${browserLabel(release.browser)} ${release.minimum}`)\n .join(', ')\n return {\n title: 'Update your browser',\n body: `This application needs ${versions}.`,\n }\n}\n\nfunction loadQueries(path: string): readonly string[] | undefined {\n try {\n return browserslist.loadConfig({ path })\n } catch (cause) {\n throw new BrowserFloorError(path, 'invalid', cause)\n }\n}\n\nfunction floorReleases(resolved: readonly string[]): BrowserFloorRelease[] {\n const ranges = new Map<string, { minimum: string; maximum: string }>()\n for (const entry of resolved) {\n const release = splitRelease(entry)\n if (release === undefined) continue\n const current = ranges.get(release.browser)\n if (current === undefined) {\n ranges.set(release.browser, { minimum: release.version, maximum: release.version })\n continue\n }\n if (compareVersionText(release.version, current.minimum) < 0) current.minimum = release.version\n if (compareVersionText(release.version, current.maximum) > 0) current.maximum = release.version\n }\n return [...ranges.entries()]\n .map(([browser, range]) => ({ browser, minimum: range.minimum, maximum: range.maximum }))\n .sort((left, right) => compareText(left.browser, right.browser))\n}\n\nfunction splitRelease(\n entry: string,\n): { readonly browser: string; readonly version: string } | undefined {\n const space = entry.indexOf(' ')\n if (space === -1) return undefined\n const browser = entry.slice(0, space)\n const version = entry.slice(space + 1)\n if (versionParts(version) === undefined) return undefined\n return { browser, version }\n}\n\nfunction compareVersionText(left: string, right: string): number {\n const leftParts = versionParts(left)\n const rightParts = versionParts(right)\n if (leftParts === undefined || rightParts === undefined) return 0\n return compareVersions(leftParts, rightParts)\n}\n\nfunction versionParts(version: string): readonly number[] | undefined {\n const normalized =\n version.startsWith('≤') || version.startsWith('<=') ? version.replace(/^≤|^<=/, '') : version\n if (!/^\\d+(?:\\.\\d+)*$/.test(normalized)) return undefined\n return normalized.split('.').map((part) => Number(part))\n}\n\nfunction compareVersions(left: readonly number[], right: readonly number[]): number {\n const length = Math.max(left.length, right.length)\n for (let index = 0; index < length; index += 1) {\n const difference = (left[index] ?? 0) - (right[index] ?? 0)\n if (difference !== 0) return difference\n }\n return 0\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1\n if (left > right) return 1\n return 0\n}\n\nfunction viteBrowser(browser: string): string {\n if (browser === 'ios_saf') return 'ios'\n return browser\n}\n\nfunction browserLabel(browser: string): string {\n switch (browser) {\n case 'chrome':\n return 'Chrome'\n case 'edge':\n return 'Edge'\n case 'firefox':\n return 'Firefox'\n case 'safari':\n return 'Safari'\n case 'ios_saf':\n return 'iOS'\n default:\n return browser\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"floor-BdRTO_LO.js","names":[],"sources":["../src/infrastructure/browser-support/browser-floor.error.ts","../src/infrastructure/browser-support/floor.ts"],"sourcesContent":["import { AppError } from '@/core'\n\n/** The browserslist file is missing, empty, or not a query browserslist can resolve. */\nexport class BrowserFloorError extends AppError {\n readonly _tag = 'BrowserFloorError'\n readonly classification = 'terminal'\n\n /**\n * `path` is the file or directory passed to `browserFloor`.\n * `reason` is `missing` when no config is found, `empty` when the query matches no browsers,\n * and `invalid` when browserslist rejects the query. `cause` is that rejection.\n */\n constructor(\n readonly path: string,\n readonly reason: 'missing' | 'empty' | 'invalid',\n cause?: unknown,\n ) {\n super(floorMessage(reason, path), { cause })\n }\n}\n\nfunction floorMessage(reason: 'missing' | 'empty' | 'invalid', path: string): string {\n switch (reason) {\n case 'missing':\n return `No browserslist config at ${path}`\n case 'empty':\n return `The browserslist config at ${path} matches no browsers`\n case 'invalid':\n return `The browserslist config at ${path} is invalid`\n }\n}\n","import browserslist from 'browserslist'\n\nimport { BrowserFloorError } from './browser-floor.error.ts'\n\nexport { BrowserFloorError }\n\n/** Oldest and newest version of one browser that the floor still includes. */\nexport type BrowserFloorRelease = {\n readonly browser: string\n readonly minimum: string\n readonly maximum: string\n}\n\n/** Title and body for the update screen, taken from the floor versions. */\nexport type UpdateScreenCopy = {\n readonly title: string\n readonly body: string\n}\n\n/**\n * Resolve the minimum and maximum version of each browser in the browserslist config.\n * The path is a config file or any file inside the project that owns `.browserslistrc`.\n * Throws `BrowserFloorError` when the config is missing, empty, or invalid.\n */\nexport function browserFloor(path: string): readonly BrowserFloorRelease[] {\n const queries = loadQueries(path)\n if (queries === undefined) throw new BrowserFloorError(path, 'missing')\n if (queries.length === 0) throw new BrowserFloorError(path, 'empty')\n let resolved: readonly string[]\n try {\n resolved = browserslist(queries, { path })\n } catch (cause) {\n throw new BrowserFloorError(path, 'invalid', cause)\n }\n const releases = floorReleases(resolved)\n if (releases.length === 0) throw new BrowserFloorError(path, 'empty')\n return releases\n}\n\n/**\n * Vite `environments.client.build.target` values for the browserslist config at `path`.\n * Throws `BrowserFloorError` when the config is missing, empty, or invalid.\n */\nexport function buildTargets(path: string): readonly string[] {\n return browserFloor(path).map((release) => `${viteBrowser(release.browser)}${release.minimum}`)\n}\n\n/** Sentence that names the floor versions. Pass the result of `browserFloor`. */\nexport function updateScreenCopy(releases: readonly BrowserFloorRelease[]): UpdateScreenCopy {\n const versions = releases\n .map((release) => `${browserLabel(release.browser)} ${release.minimum}`)\n .join(', ')\n return {\n title: 'Update your browser',\n body: `This application needs ${versions}.`,\n }\n}\n\nfunction loadQueries(path: string): readonly string[] | undefined {\n try {\n return browserslist.loadConfig({ path })\n } catch (cause) {\n throw new BrowserFloorError(path, 'invalid', cause)\n }\n}\n\nfunction floorReleases(resolved: readonly string[]): BrowserFloorRelease[] {\n const ranges = new Map<string, { minimum: string; maximum: string }>()\n for (const entry of resolved) {\n const release = splitRelease(entry)\n if (release === undefined) continue\n const current = ranges.get(release.browser)\n if (current === undefined) {\n ranges.set(release.browser, { minimum: release.version, maximum: release.version })\n continue\n }\n if (compareVersionText(release.version, current.minimum) < 0) current.minimum = release.version\n if (compareVersionText(release.version, current.maximum) > 0) current.maximum = release.version\n }\n return [...ranges.entries()]\n .map(([browser, range]) => ({ browser, minimum: range.minimum, maximum: range.maximum }))\n .sort((left, right) => compareText(left.browser, right.browser))\n}\n\nfunction splitRelease(\n entry: string,\n): { readonly browser: string; readonly version: string } | undefined {\n const space = entry.indexOf(' ')\n if (space === -1) return undefined\n const browser = entry.slice(0, space)\n const version = entry.slice(space + 1)\n if (versionParts(version) === undefined) return undefined\n return { browser, version }\n}\n\nfunction compareVersionText(left: string, right: string): number {\n const leftParts = versionParts(left)\n const rightParts = versionParts(right)\n if (leftParts === undefined || rightParts === undefined) return 0\n return compareVersions(leftParts, rightParts)\n}\n\nfunction versionParts(version: string): readonly number[] | undefined {\n const normalized =\n version.startsWith('≤') || version.startsWith('<=') ? version.replace(/^≤|^<=/, '') : version\n if (!/^\\d+(?:\\.\\d+)*$/.test(normalized)) return undefined\n return normalized.split('.').map((part) => Number(part))\n}\n\nfunction compareVersions(left: readonly number[], right: readonly number[]): number {\n const length = Math.max(left.length, right.length)\n for (let index = 0; index < length; index += 1) {\n const difference = (left[index] ?? 0) - (right[index] ?? 0)\n if (difference !== 0) return difference\n }\n return 0\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1\n if (left > right) return 1\n return 0\n}\n\nfunction viteBrowser(browser: string): string {\n if (browser === 'ios_saf') return 'ios'\n return browser\n}\n\nfunction browserLabel(browser: string): string {\n switch (browser) {\n case 'chrome':\n return 'Chrome'\n case 'edge':\n return 'Edge'\n case 'firefox':\n return 'Firefox'\n case 'safari':\n return 'Safari'\n case 'ios_saf':\n return 'iOS'\n default:\n return browser\n }\n}\n"],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { l as Logger } from "./index-CtIdbnEZ.js";
2
- import { n as WebhookVerifier, t as WebhookVerificationError } from "./webhook-verification-DL4L3zbu.js";
1
+ import { l as Logger } from "./index-tJzJUgTh.js";
2
+ import { n as WebhookVerifier, t as WebhookVerificationError } from "./webhook-verification-Cy4Z5djk.js";
3
3
  //#region src/infrastructure/http/webhook-handler.d.ts
4
4
  /** Application policy and diagnostics for one webhook body. */
5
5
  type WebhookHandlerOptions = {
package/dist/http.js CHANGED
@@ -1,5 +1,5 @@
1
- import { r as createLogger } from "./core-DOBZeYSX.js";
2
- import { t as WebhookVerificationError } from "./webhook-verification-C4R6OO7f.js";
1
+ import { r as createLogger } from "./core-CV8SQv01.js";
2
+ import { t as WebhookVerificationError } from "./webhook-verification-B8v3-LQ2.js";
3
3
  import { StatusCodes } from "http-status-codes";
4
4
 
5
5
  //#region src/infrastructure/http/webhook-handler.ts
@@ -1,4 +1,4 @@
1
- import { G as DomainMessage, Jt as AppError, K as DomainQuery, Kt as AnalyticsTarget, Rt as EmailIdempotencyKey, U as DomainCommand, Ut as AnalyticsEventInput, Vt as EmailAddress, W as DomainEvent, Wt as AnalyticsProperties, jt as BounceType, kt as RecordEmailEventPayload, q as MessageId } from "./index-CtIdbnEZ.js";
1
+ import { Ft as BounceType, Gt as EmailAddress, Ht as EmailIdempotencyKey, J as DomainEvent, Jt as AnalyticsProperties, Nt as RecordEmailEventPayload, Qt as AppError, X as DomainQuery, Xt as AnalyticsTarget, Y as DomainMessage, Z as MessageId, q as DomainCommand, qt as AnalyticsEventInput } from "./index-tJzJUgTh.js";
2
2
  //#region src/application/handlers.d.ts
3
3
  /**
4
4
  * Handles one command with the dependency container and returns the caller's value.
@@ -372,7 +372,7 @@ type OutboxRelayOptions = {
372
372
  readonly batchSize?: number;
373
373
  readonly maxBatches?: number;
374
374
  readonly maxAttempts?: number;
375
- /** The wait before the first retry; each later retry doubles it. */
375
+ /** The longest wait before the first retry; each later retry doubles it. Jitter picks between half and all of it. */
376
376
  readonly retryBaseDelayMs?: number;
377
377
  /** The longest wait before a retry. */
378
378
  readonly retryMaxDelayMs?: number;
@@ -408,6 +408,7 @@ declare class OutboxRelay {
408
408
  private failOrRetry;
409
409
  /** Releases rows for another attempt. Each row waits longer the more attempts it has used. */
410
410
  private releaseForRetry;
411
+ private get delays();
411
412
  /** Splits claimed rows: rows whose last run crashed with no attempt left, and rows that may run now. */
412
413
  private splitByAttemptsLeft;
413
414
  /** Splits failed rows: rows that just used their last attempt, and rows that may retry. */
@@ -420,6 +421,33 @@ declare class OutboxRelay {
420
421
  private markFailed;
421
422
  }
422
423
  //#endregion
424
+ //#region src/application/queue-or-rpc-publisher.d.ts
425
+ /** A client for a consumer that runs one event when called over RPC; it rejects when the event fails. */
426
+ interface IEventConsumerClient {
427
+ consume(event: DomainEvent): Promise<void>;
428
+ }
429
+ /** The two clients, the app's rule for choosing between them, and the RPC budget. */
430
+ type QueueOrRpcPublisherOptions = {
431
+ readonly queue: IOutboxPublisher;
432
+ readonly consumer: IEventConsumerClient;
433
+ /** The app's rule: which events go over RPC. */
434
+ readonly usesRpc: (event: DomainEvent) => boolean;
435
+ /** RPC calls in one request. Cloudflare allows 32 Worker invocations per request. */
436
+ readonly callsPerRequest?: number;
437
+ };
438
+ /**
439
+ * Publishes each event over RPC or to the queue. Events that the rule picks are consumed over RPC,
440
+ * in parallel, until the request's call budget is used; every other event goes to the queue.
441
+ * Build one per request, so the budget counts that request's calls. A failed call or queue send
442
+ * rejects only its own events.
443
+ */
444
+ declare class QueueOrRpcPublisher implements IOutboxPublisher {
445
+ private readonly options;
446
+ private callsLeft;
447
+ constructor(options: QueueOrRpcPublisherOptions);
448
+ publish(events: ReadonlyArray<DomainEvent>): Promise<readonly RejectedMessage<DomainEvent>[]>;
449
+ }
450
+ //#endregion
423
451
  //#region src/application/outbox-retention.d.ts
424
452
  /** Typist's retention defaults; receipt retention must cover the application's supported replay period. */
425
453
  type OutboxRetentionOptions = {
@@ -466,5 +494,5 @@ declare class UnitOfWorkAlreadyActiveError extends AppError {
466
494
  constructor();
467
495
  }
468
496
  //#endregion
469
- export { MetricOptions as $, IUnitOfWork as A, MimeType as B, RegistryMessage as C, RecordEmailEventDeps as D, RecordEmailEventCommand as E, IMessageStore as F, RecordingEmailService as G, ReceivedAttachment as H, IEventCollector as I, ObservabilityScope as J, applyObservabilityUser as K, EmailAccepted as L, UnitOfWorkDeps as M, ITransaction as N, RecordEmailEventRepos as O, IOutboxWake as P, MetricAttributes as Q, EmailAttachment as R, QueryRegistry as S, IEmailDeliverabilityStore as T, ReceivedContent as U, OutboundEmail as V, ReceivedEmail as W, ObservabilityUser as X, ObservabilityService as Y, MetricAttributeValue as Z, CommandRegistry as _, OutboxRetentionResult as a, CommandHandler as at, MessageRegistry as b, IOutboxRepository as c, OutboxFailureReason as d, MetricsService as et, OutboxRow as f, MessageBus as g, IMessageBus as h, OutboxRetentionOptions as i, NULL_ANALYTICS as it, UnitOfWork as j, recordEmailEvent as k, IOutboxRetentionRepository as l, RejectedMessage as m, MessageAlreadyProcessedError as n, AnalyticsPropertiesOf as nt, OutboxRelay as o, EventHandler as ot, IOutboxPublisher as p, setObservabilityUserHook as q, OutboxRetention as r, AnalyticsService as rt, OutboxRelayOptions as s, QueryHandler as st, UnitOfWorkAlreadyActiveError as t, NULL_METRICS_SERVICE as tt, OutboxBatch as u, EventRegistry as v, EmailBounceRecord as w, MessageResult as x, Handlers as y, IEmailService as z };
470
- //# sourceMappingURL=index-Db2GV9ZP.d.ts.map
497
+ export { ObservabilityUser as $, RecordEmailEventDeps as A, EmailAccepted as B, MessageRegistry as C, EmailBounceRecord as D, RegistryMessage as E, UnitOfWorkDeps as F, ReceivedAttachment as G, IEmailService as H, ITransaction as I, RecordingEmailService as J, ReceivedContent as K, IOutboxWake as L, recordEmailEvent as M, IUnitOfWork as N, IEmailDeliverabilityStore as O, UnitOfWork as P, ObservabilityService as Q, IMessageStore as R, Handlers as S, QueryRegistry as T, MimeType as U, EmailAttachment as V, OutboundEmail as W, setObservabilityUserHook as X, applyObservabilityUser as Y, ObservabilityScope as Z, RejectedMessage as _, OutboxRetentionResult as a, AnalyticsPropertiesOf as at, CommandRegistry as b, QueueOrRpcPublisherOptions as c, CommandHandler as ct, IOutboxRepository as d, MetricAttributeValue as et, IOutboxRetentionRepository as f, IOutboxPublisher as g, OutboxRow as h, OutboxRetentionOptions as i, NULL_METRICS_SERVICE as it, RecordEmailEventRepos as j, RecordEmailEventCommand as k, OutboxRelay as l, EventHandler as lt, OutboxFailureReason as m, MessageAlreadyProcessedError as n, MetricOptions as nt, IEventConsumerClient as o, AnalyticsService as ot, OutboxBatch as p, ReceivedEmail as q, OutboxRetention as r, MetricsService as rt, QueueOrRpcPublisher as s, NULL_ANALYTICS as st, UnitOfWorkAlreadyActiveError as t, MetricAttributes as tt, OutboxRelayOptions as u, QueryHandler as ut, IMessageBus as v, MessageResult as w, EventRegistry as x, MessageBus as y, IEventCollector as z };
498
+ //# sourceMappingURL=index-DaiY8xJJ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DaiY8xJJ.d.ts","names":[],"sources":["../src/application/handlers.ts","../src/application/analytics-service.ts","../src/application/metrics-service.ts","../src/application/observability-service.ts","../src/application/request-user.ts","../src/application/email-service.ts","../src/application/event-collector.ts","../src/application/message-store.ts","../src/application/outbox-wake.ts","../src/application/transaction.ts","../src/application/unit-of-work.ts","../src/application/record-email-event.ts","../src/application/registry.ts","../src/application/message-bus.ts","../src/application/outbox-publisher.ts","../src/application/outbox-repository.ts","../src/application/outbox-relay.ts","../src/application/queue-or-rpc-publisher.ts","../src/application/outbox-retention.ts","../src/application/message-already-processed.error.ts","../src/application/unit-of-work.errors.ts"],"mappings":";;;;;;KAMY,eAAe,iBAAiB,eAAe,MAAM,UAC/D,SAAS,UACT,MAAM,SACH,QAAQ;;;;;KAMD,aAAa,eAAe,aAAa,WAAW,UAC9D,OAAO,QACP,MAAM,cACH,QAAQ;;KAGD,aAAa,eAAe,aAAa,SACnD,OAAO,QACP,MAAM,SACH;;;;KCrBO,sBACV,eAAe,qBACf,cAAc,iCACG,iBACf,uBACA,QAAQ;WAAmB,MAAM;;;UAGpB,iBAAiB,eAAe,sBAAsB;;EAErE,SAAS,oBAAoB,aAAa;;EAE1C,MAAM,oBAAoB;;EAE1B,MAAM,cAAc,gBAClB,MAAM,OACN,YAAY,sBAAsB,QAAQ,QAC1C,QAAQ;;EAGV,eAAe,cAAc,gBAC3B,MAAM,OACN,YAAY,sBAAsB,QAAQ,QAC1C,QAAQ;;;;;;cAQC;;;EAIF,QAAA,eAAM,aACA,mCAAiC,SACrC;EAGF,iBAAA,eAAM,aACA,mCAAiC,SACrC;;;;;KC5CD;;KAGA,mBAAmB,SAAS,eAAe;;UAGtC;WACN,aAAa;WACb;;;UAIM,eAAe;;EAE9B,MAAM,MAAM,OAAO,gBAAgB,UAAU;;EAE7C,MAAM,MAAM,OAAO,eAAe,UAAU;;EAE5C,UAAU,MAAM,OAAO,eAAe,UAAU;;;cAIrC,sBAAsB;;;;UCtBlB;WACN;;;UAIM;;EAEf,QAAQ,MAAM;;;UAIC,6BAA6B;;EAE5C,mBAAmB,GAAG,WAAW,OAAO,uBAAuB,IAAI,QAAQ,KAAK,QAAQ;;;;;iBCJ1E,yBAAyB,QAAQ,MAAM;;iBAKvC,uBAAuB,MAAM;;;;KCZjC;;KAGA;WACD;WACA,kBAAkB;;WAElB,cAAc;;;;;;;KAQb;;WAED;WACA;WACA;WACA;;WAEA,iBAAiB;;WAEjB;WACA;;WAEA,OAAO,SAAS;WAChB,uBAAuB;;;KAItB;WAA2B,SAAS,SAAS;;;KAG7C;WACD;WACA;WACA;WACA;WACA;;;KAIC;;WAED;WACA;WACA,sBAAsB;;;KAIrB;WAA2B;;;;;;UAMtB;;EAEf,UAAU,OAAO,gBAAgB,QAAQ;;;cAI9B,iCAAiC;;WAEnC,MAAM;;EAGT,UAAU,OAAO,gBAAgB,QAAQ;;;;;UCrEhC;EACf,KAAK,OAAO;EACZ,WAAW,cAAc;;;;;;;;UCCV;;EAEf,MAAM,WAAW,YAAY;;EAE7B,cAAc,QAAQ,cAAc,eAAe;;;;;;;;;UCLpC;EACf;;;;;;;;UCFe,aAAa;EAC5B,YAAY,GAAG,OAAO,IAAI,OAAO,QAAQ,KAAK,QAAQ;;;;;;;;;UCQvC,YAAY;EAC3B,IAAI,GAAG,WAAW,WAAW,OAAO,OAAO,UAAU,QAAQ,KAAK,QAAQ;;KAGhE,eAAe,IAAI;WACpB,aAAa,aAAa;;WAE1B,eAAe,IAAI,OAAO;;WAE1B,qBAAqB,IAAI,OAAO;WAChC,gBAAgB;WAChB,OAAO;;;cAIL,WAAW,IAAI,kBAAkB,YAAY;mBAC3B;EAA7B,YAA6B,MAAM,eAAe,IAAI;EAEhD,IAAI,GAAG,WAAW,WAAW,OAAO,OAAO,UAAU,QAAQ,KAAK,QAAQ;;;;;KC1BtE;WACD,MAAM;WACN;;;;;;UAOM;;EAEf,aAAa,SAAS,cAAc,QAAQ,oBAAoB;;EAEhE,gBAAgB,SAAS,eAAe;;;KAI9B;WAAmC,qBAAqB;;;KAGxD;WAAkC,KAAK,YAAY;;;KAGnD,0BAA0B,gBAAgB;;;;;iBAMhC,iBACpB,SAAS,yBACT,MAAM,uBACL;;;;KChCS,gBAAgB,iBAAiB,eAAe,oBAChD,KAAK,YAAY,YAAY,eAAe,GAAG;;KAI/C,cAAc,eAAe,aAAa,yBAC1C,KAAK,UAAU,YAAY,aAAa,GAAG;;;;;KAO3C,cAAc,eAAe,aAAa,oBAC1C,KAAK,UAAU,aAAa,cAAc,aAAa,GAAG;;;;;;KAQ1D,gBAAgB,iBAAiB,eAAe,aAAa,WAAW;WACzE,UAAU,gBAAgB,QAAQ,UAAU,gBAAgB;WAC5D,SAAS,cAAc,QAAQ,UAAU,cAAc;WACvD,QAAQ,cAAc,QAAQ,UAAU,cAAc;;KAK5D,KAAK;EAAU,OAAO,SAAS,eAAe,MAAM,OAAO;;KAC3D,aAAa;EAAU,OAAO,OAAO,aAAa,MAAM,OAAO;;;;;;KAMxD,SAAS;WACV,UAAU,SAAS,eAAe,KAAK;WACvC,SAAS,SAAS,eAAe,KAAK;WACtC,QAAQ,SAAS,QAAQ,eAAe,cAAc,aAAa;;KAGzE,YAAY,UAAU,WAAW,QAAQ,aAAa,SAAS;KAE/D,oBAAoB,UACvB,YAAY,aAAa,iBAAiB,oBAAoB,iBAC1D,WAAW,QAAQ,eAAe;;KAI5B,gBAAgB,kBAAkB,mBAC1C,YAAY,yBACZ,YAAY,wBACZ,oBAAoB;KAEnB,UAAU,QAAQ,wBAAwB,oBAAoB,SAC/D,QAAQ,WAAW,QAAQ,OAAO,QAAQ;;KAIlC,cACV,iBAAiB,eACjB,kBAAkB,mBAChB,iBAAiB,gBACjB,UAAU,uBAAuB,oBACjC,iBAAiB,cACf,UAAU,sBAAsB;;;;UCvDrB,YAAY,kBAAkB;EAC7C,OAAO,iBAAiB,gBAAgB,gBAAgB,YACtD,SAAS,WACR,QAAQ,cAAc,UAAU;;;;;;cAOxB,WAAW,MAAM,kBAAkB,SAAS,kBAAkB,YAAY;mBAElE;mBACA;EAFnB,YACmB,MAAM,MACN,UAAU;;EAIvB,OAAO,iBAAiB,gBAAgB,gBAAgB,YAC5D,SAAS,WACR,QAAQ,cAAc,UAAU;UAM3B;UASA;UASA;;;;;;UAWM;;;;;KCpEJ,gBAAgB,SAAS;WAC1B,SAAS;WACT,OAAO;;;UAID;;EAEf,QACE,UAAU,cAAc,eACvB,QAAQ,cAAc,gBAAgB;;;;;KCV/B;WACD,SAAS;WACT;;;KAIC;WACD;WACA,MAAM,cAAc;;;KAInB;;UAGK;;EAEf,sBAAsB,QAAQ,MAAM,oBAAoB;;EAExD,mBAAmB,QAAQ,MAAM,oBAAoB;;EAErD,qBAAqB,QAAQ,MAAM,oBAAoB;;;;;;UAOxC,0BAA0B;;EAEzC,aAAa,gBAAgB,QAAQ;;EAErC,cAAc,oBAAoB,MAAM,cAAc,aAAa;;EAEnE,aAAa,oBAAoB,MAAM,cAAc,YAAY,aAAa,OAAO;;EAErF,WACE,oBACA,MAAM,cAAc,YACpB,QAAQ,qBACR,uBACC;;;;;KCtCO;WACD;WACA;WACA;;WAEA;;WAEA;;;;;;cASE;mBAIQ;mBACA;mBAEA;mBANF;EAEjB,YACmB,WAAW,kBACX,YAAY,mBAC7B,UAAS,oBACQ,YAAW;;;;;EAexB,SAAS;;UAUD;;UAeA;;;;;EAeR,SAAS;;;;;UAeD;;UAiBA;cAgBF;;UAKJ;;UAQA;;UAQA;;UAMA;;UAKM;;;;;UC/JC;EACf,QAAQ,OAAO,cAAc;;;KAInB;WACD,OAAO;WACP,UAAU;;WAEV,UAAU,OAAO;;WAEjB;;;;;;;;cAWE,+BAA+B;mBAGb;UAFrB;EAER,YAA6B,SAAS;EAIhC,QACJ,QAAQ,cAAc,eACrB,iBAAiB,gBAAgB;;;;;KCjC1B;WACD;WACA;WACA;WACA;WACA;;;KAIC;WACD;WACA;WACA;;;cAIE;mBAIQ;mBAHF;EAEjB,YACmB,YAAY,4BAC7B,UAAS;;EAYL,MAAM,IAAI,OAAO,QAAQ;UAcjB;;;;;cC/CH,qCAAqC;WAKrC,WAAW;WAJb;WACA;EAET,YACW,WAAW,WACpB;aAAqB;;;SAMhB,KAAK,gBAAgB,WAAW,YAAY;;;;;cCZxC,qCAAqC;WACvC;WACA;EAET"}
@@ -666,8 +666,9 @@ declare function classifyBoundaryError(args: {
666
666
  readonly includeCloudflare: boolean;
667
667
  }): FailureClassification;
668
668
  /**
669
- * Judge a final failure for its durable retry owner. An `AppError` carries its own answer.
670
- * A raw throw nobody judged is unknown, so an immediate owner stops and a durable one may repeat.
669
+ * Judge a final failure for its durable retry owner. An `AppError` carries its own answer, also
670
+ * after Workers RPC. A raw throw nobody judged is unknown, so an immediate owner stops and a
671
+ * durable one may repeat.
671
672
  */
672
673
  declare function classifyFailure(cause: unknown): FailureClassification;
673
674
  /** Read a positive server-advertised retry delay in seconds, such as `RateLimitError.retryAfter`. */
@@ -684,6 +685,31 @@ declare function exponentialEqualJitterMs(baseDelayMs: number, maxDelayMs: numbe
684
685
  /** Capped exponential delay for a durable retry recorded in storage. */
685
686
  declare function exponentialDelayCapMs(baseDelayMs: number, maxDelayMs: number, attempt: number): number;
686
687
  //#endregion
688
+ //#region src/core/redelivery-policy.d.ts
689
+ /** The exponential backoff for a durable retry: the first wait, and the longest wait. */
690
+ type RedeliveryDelays = {
691
+ readonly baseDelayMs: number;
692
+ readonly maxDelayMs: number;
693
+ };
694
+ /** The queue consumer's backoff: 5 s, doubling, up to 120 s. */
695
+ declare const DEFAULT_REDELIVERY_DELAYS: RedeliveryDelays;
696
+ /** How to settle one failed message: stop for good, or deliver it again after a delay. */
697
+ type RedeliveryDecision = {
698
+ readonly action: 'ack';
699
+ readonly classification: 'terminal';
700
+ } | {
701
+ readonly action: 'retry';
702
+ readonly classification: Exclude<FailureClassification, 'terminal'>;
703
+ readonly delayMs: number;
704
+ };
705
+ /**
706
+ * Decide whether a failed message stops or is delivered again. A terminal failure stops. Transient
707
+ * and unknown failures retry: after the advertised wait plus a spread when the error carries one,
708
+ * else with exponential equal-jitter backoff. An `AggregateError` from event delivery retries when
709
+ * any member does, after the longest wait. The queue consumer and the outbox relay both use it.
710
+ */
711
+ declare function decideRedelivery(cause: unknown, attempt: number, delays?: RedeliveryDelays): RedeliveryDecision;
712
+ //#endregion
687
713
  //#region src/core/console-log-sink.d.ts
688
714
  /** Write one structured record or one readable development entry to `console`. */
689
715
  declare const consoleSink: LogSink;
@@ -748,5 +774,5 @@ declare function setLoggerErrorHook(hook: LoggerErrorHook | null): void;
748
774
  /** Create a logger for one module. */
749
775
  declare function createLogger(module: string): Logger;
750
776
  //#endregion
751
- export { unreachable as $, isTransientTransportError as A, RecordEmailEventPayloadSchema as At, QueryOf as B, emailIdempotencyKey as Bt, retryAfterSecondsOf as C, InternalServerError as Ct, isCloudflareRetryableError as D, RateLimitError as Dt, isCloudflareOverloadedError as E, StaleSessionError as Et, EventOf as F, shouldUpdateBounce as Ft, DomainMessage as G, AnalyticsProperty as Gt, defineMessages as H, EmailAddressSchema as Ht, MessageCollection as I, EmailSendFailureReason as It, Id as J, AppError as Jt, DomainQuery as K, AnalyticsTarget as Kt, MessageDefinition as L, EmailServiceError as Lt, EntityData as M, BounceTypeSchema as Mt, CommandOf as N, isEmailDeliverable as Nt, isTransientCloudflareRuntimeError as O, AuthenticationError as Ot, DuplicateMessageNameError as P, parseBounceType as Pt, notImplemented as Q, MessageOf as R, EmailIdempotencyKey as Rt, classifyFailure as S, ValidationProblemErrorSchema as St, isCloudflareObjectResetError as T, NotAuthorizedError as Tt, DomainCommand as U, AnalyticsEventInput as Ut, combineMessages as V, EmailAddress as Vt, DomainEvent as W, AnalyticsProperties as Wt, IdOf as X, RetryOwner as Xt, IdDefinition as Y, FailureClassification as Yt, defineId as Z, shouldRetryFailure as Zt, exponentialDelayCapMs as _, ProblemDetails as _t, LogLevel as a, ErrorPayloadOf as at, BoundaryErrorClassifier as b, ValidationProblemDetailsSchema as bt, LogValue as c, ResolvedError as ct, LoggerSettings as d, MalformedRequestError as dt, D1ConstraintKind as et, configureLogger as f, RequestTimeoutError as ft, consoleSink as g, ValidationIssue as gt, setLoggerErrorHook as h, ValidationError as ht, LogFormat as i, ErrorEntry as it, Entity as j, BounceType as jt, isAbortError as k, RecordEmailEventPayload as kt, Logger as l, defineErrors as lt, setLogSink as m, UpgradeRequiredError as mt, LogEntry as n, DatabaseFailure as nt, LogSink as o, ErrorTable as ot, createLogger as p, ResourceNotFoundError as pt, MessageId as q, MissingConfigurationError as qt, LogFields as r, ErrorEntries as rt, LogThreshold as s, ErrorTagOf as st, ErrorCaptureEntry as t, DatabaseError as tt, LoggerErrorHook as u, sharedErrors as ut, exponentialEqualJitterMs as v, ProblemDetailsSchema as vt, CLOUDFLARE_TRANSIENT_ERROR_PATTERNS as w, ServiceUnavailableError as wt, classifyBoundaryError as x, ValidationProblemError as xt, spreadJitterMs as y, ValidationProblemDetails as yt, PayloadSchemas as z, InvalidEmailIdempotencyKeyError as zt };
752
- //# sourceMappingURL=index-CtIdbnEZ.d.ts.map
777
+ export { IdDefinition as $, FailureClassification as $t, isCloudflareOverloadedError as A, StaleSessionError as At, MessageCollection as B, EmailSendFailureReason as Bt, spreadJitterMs as C, ValidationProblemDetails as Ct, retryAfterSecondsOf as D, InternalServerError as Dt, classifyFailure as E, ValidationProblemErrorSchema as Et, Entity as F, BounceType as Ft, combineMessages as G, EmailAddress as Gt, MessageOf as H, EmailIdempotencyKey as Ht, EntityData as I, BounceTypeSchema as It, DomainEvent as J, AnalyticsProperties as Jt, defineMessages as K, EmailAddressSchema as Kt, CommandOf as L, isEmailDeliverable as Lt, isTransientCloudflareRuntimeError as M, AuthenticationError as Mt, isAbortError as N, RecordEmailEventPayload as Nt, CLOUDFLARE_TRANSIENT_ERROR_PATTERNS as O, ServiceUnavailableError as Ot, isTransientTransportError as P, RecordEmailEventPayloadSchema as Pt, Id as Q, AppError as Qt, DuplicateMessageNameError as R, parseBounceType as Rt, exponentialEqualJitterMs as S, ProblemDetailsSchema as St, classifyBoundaryError as T, ValidationProblemError as Tt, PayloadSchemas as U, InvalidEmailIdempotencyKeyError as Ut, MessageDefinition as V, EmailServiceError as Vt, QueryOf as W, emailIdempotencyKey as Wt, DomainQuery as X, AnalyticsTarget as Xt, DomainMessage as Y, AnalyticsProperty as Yt, MessageId as Z, MissingConfigurationError as Zt, DEFAULT_REDELIVERY_DELAYS as _, ResourceNotFoundError as _t, LogLevel as a, DatabaseError as at, decideRedelivery as b, ValidationIssue as bt, LogValue as c, ErrorEntry as ct, LoggerSettings as d, ErrorTagOf as dt, RetryOwner as en, IdOf as et, configureLogger as f, ResolvedError as ft, consoleSink as g, RequestTimeoutError as gt, setLoggerErrorHook as h, MalformedRequestError as ht, LogFormat as i, D1ConstraintKind as it, isCloudflareRetryableError as j, RateLimitError as jt, isCloudflareObjectResetError as k, NotAuthorizedError as kt, Logger as l, ErrorPayloadOf as lt, setLogSink as m, sharedErrors as mt, LogEntry as n, notImplemented as nt, LogSink as o, DatabaseFailure as ot, createLogger as p, defineErrors as pt, DomainCommand as q, AnalyticsEventInput as qt, LogFields as r, unreachable as rt, LogThreshold as s, ErrorEntries as st, ErrorCaptureEntry as t, shouldRetryFailure as tn, defineId as tt, LoggerErrorHook as u, ErrorTable as ut, RedeliveryDecision as v, UpgradeRequiredError as vt, BoundaryErrorClassifier as w, ValidationProblemDetailsSchema as wt, exponentialDelayCapMs as x, ProblemDetails as xt, RedeliveryDelays as y, ValidationError as yt, EventOf as z, shouldUpdateBounce as zt };
778
+ //# sourceMappingURL=index-tJzJUgTh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-tJzJUgTh.d.ts","names":[],"sources":["../src/core/failure-classification.ts","../src/core/app-error.ts","../src/core/missing-configuration.error.ts","../src/core/analytics-event.ts","../src/core/email-address.ts","../src/core/email-idempotency-key.ts","../src/core/email-service.error.ts","../src/core/email-deliverability.ts","../src/core/record-email-event.ts","../src/core/authentication.error.ts","../src/core/rate-limit.error.ts","../src/core/stale-session.error.ts","../src/core/not-authorized.error.ts","../src/core/internal.errors.ts","../src/core/problem-details.ts","../src/core/request.errors.ts","../src/core/error-table.ts","../src/core/database.error.ts","../src/core/defects.ts","../src/core/identity.ts","../src/core/messages.ts","../src/core/define-messages.ts","../src/core/entity.ts","../src/core/transport-classification.ts","../src/core/cloudflare-classification.ts","../src/core/classify-failure.ts","../src/core/backoff.ts","../src/core/redelivery-policy.ts","../src/core/console-log-sink.ts","../src/core/logger.ts"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { g as isCloudflareRetryableError, h as isCloudflareOverloadedError, tt as AppError, y as isTransientTransportError } from "./core-DOBZeYSX.js";
1
+ import { _ as isCloudflareOverloadedError, rt as AppError, v as isCloudflareRetryableError, x as isTransientTransportError } from "./core-CV8SQv01.js";
2
2
 
3
3
  //#region src/infrastructure/cloudflare/kv-errors.ts
4
4
  /** Extract Typist's verified KV message formats, including nested causes. */
@@ -141,4 +141,4 @@ function getDeepErrorMessage(cause) {
141
141
 
142
142
  //#endregion
143
143
  export { isRetryableKVError as a, isKVPutRateLimitError as i, decideKVRetry as n, isTerminalKVError as o, extractKVMeta as r, isTransientKVError as s, KVError as t };
144
- //# sourceMappingURL=kv-errors-B2k_2lyY.js.map
144
+ //# sourceMappingURL=kv-errors-DXbnO7cB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kv-errors-B2k_2lyY.js","names":[],"sources":["../src/infrastructure/cloudflare/kv-errors.ts"],"sourcesContent":["import {\n AppError,\n isCloudflareOverloadedError,\n isCloudflareRetryableError,\n isTransientTransportError,\n type FailureClassification,\n} from '@/core'\n\n/** KV operations recognized in binding error messages. */\nexport type KVOperation = 'get' | 'put' | 'delete' | 'list'\n\n/** KV failure kinds retained from Typist's binding tests. */\nexport type KVErrorKind =\n | 'invalid_key'\n | 'key_too_large'\n | 'invalid_expiration_ttl'\n | 'invalid_expiration'\n | 'invalid_cache_ttl'\n | 'invalid_list_limit'\n | 'value_too_large'\n | 'client_error'\n | 'rate_limited'\n | 'server_error'\n\n/** Evidence extracted from a KV error and its causes. */\nexport interface KVErrorMeta {\n kind: KVErrorKind\n message: string\n status?: number | undefined\n operation?: Uppercase<KVOperation> | undefined\n}\n\n/** Extract Typist's verified KV message formats, including nested causes. */\nexport function extractKVMeta(cause: unknown): KVErrorMeta | undefined {\n const message = getDeepErrorMessage(cause)\n if (!message) return undefined\n const statusMatch = message.match(/\\bKV\\s+(GET|PUT|DELETE|LIST)\\s+failed:\\s+(\\d{3})\\b/)\n // SAFETY: The regular expression permits only uppercase KV operation names in this capture.\n const operation = statusMatch?.[1] as Uppercase<KVOperation> | undefined\n const status = statusMatch ? Number(statusMatch[2]) : undefined\n\n if (/Key name cannot be empty/i.test(message)) {\n return { kind: 'invalid_key', message, status, operation }\n }\n if (/exceeds key length limit/i.test(message)) {\n return { kind: 'key_too_large', message, status, operation }\n }\n if (/Invalid expiration_ttl/i.test(message)) {\n return { kind: 'invalid_expiration_ttl', message, status, operation }\n }\n if (/Invalid expiration of/i.test(message)) {\n return { kind: 'invalid_expiration', message, status, operation }\n }\n if (/Invalid cache_ttl/i.test(message)) {\n return { kind: 'invalid_cache_ttl', message, status, operation }\n }\n if (/Invalid key_count_limit/i.test(message)) {\n return { kind: 'invalid_list_limit', message, status, operation }\n }\n if (/value.*(too large|exceeds)|exceeds.*value/i.test(message)) {\n return { kind: 'value_too_large', message, status, operation }\n }\n if (status === 429) return { kind: 'rate_limited', message, status, operation }\n if (status !== undefined && status >= 500) {\n return { kind: 'server_error', message, status, operation }\n }\n if (status !== undefined && status >= 400) {\n return { kind: 'client_error', message, status, operation }\n }\n return undefined\n}\n\n/** Identify recognized KV failures that another attempt cannot resolve. */\nexport function isTerminalKVError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n if (!meta) return false\n if (meta.kind === 'rate_limited' || meta.kind === 'server_error') return false\n if (meta.status === 408) return false\n return true\n}\n\n/** Identify a PUT rate limit that requires at least one second before retrying. */\nexport function isKVPutRateLimitError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n return meta?.operation === 'PUT' && meta.kind === 'rate_limited'\n}\n\n/** Identify PUT rate limits, server failures, and request timeouts. */\nexport function isTransientKVError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n if (!meta) return false\n return isKVPutRateLimitError(cause) || meta.kind === 'server_error' || meta.status === 408\n}\n\n/** Apply Typist's KV, overload, platform, and transport checks in their original order. */\nexport function isRetryableKVError(cause: unknown): boolean {\n if (isTerminalKVError(cause)) return false\n if (isTransientKVError(cause)) return true\n if (isCloudflareOverloadedError(cause)) return false\n return isCloudflareRetryableError(cause) || isTransientTransportError(cause)\n}\n\n/** Return the existing retry decision and minimum delay in milliseconds. */\nexport function decideKVRetry(\n cause: unknown,\n): { retry: false } | { retry: true; retryAfterMs: number } {\n if (!isRetryableKVError(cause)) return { retry: false }\n return { retry: true, retryAfterMs: isKVPutRateLimitError(cause) ? 1_000 : 0 }\n}\n\n/** A final KV failure with Typist's diagnostics and Better Ship's error classification. */\nexport class KVError extends AppError {\n readonly _tag = 'KVError'\n readonly classification: FailureClassification\n retryable: boolean\n readonly operation: KVOperation\n readonly key?: string | undefined\n override readonly cause: unknown\n readonly kv?: KVErrorMeta | undefined\n readonly context: {\n operation: KVOperation\n key?: string | undefined\n kv?: KVErrorMeta | undefined\n }\n\n constructor(args: { operation: KVOperation; key?: string | undefined; cause: unknown }) {\n const kv = extractKVMeta(args.cause)\n const causeMessage = getDeepErrorMessage(args.cause) || String(args.cause)\n const keyContext = args.key === undefined ? '' : ` for key \"${args.key}\"`\n super(`KV ${args.operation} failed${keyContext}: ${causeMessage}`, { cause: args.cause })\n this.operation = args.operation\n this.key = args.key\n this.cause = args.cause\n this.kv = kv\n this.context = { operation: args.operation, key: args.key, kv }\n this.retryable = isRetryableKVError(args.cause)\n this.classification = isTerminalKVError(args.cause)\n ? 'terminal'\n : this.retryable\n ? 'transient'\n : 'unknown'\n }\n}\n\n// oxlint-disable anti-slop/no-runtime-typeof -- Preserve Typist's primitive messages and nested causes at the raw binding boundary.\nfunction getDeepErrorMessage(cause: unknown): string {\n if (typeof cause === 'string') return cause\n if (cause === null || cause === undefined) return ''\n if (typeof cause === 'number' || typeof cause === 'boolean' || typeof cause === 'bigint') {\n return String(cause)\n }\n if (typeof cause !== 'object') return ''\n const message = 'message' in cause && typeof cause.message === 'string' ? cause.message : ''\n const causeMessage = 'cause' in cause ? getDeepErrorMessage(cause.cause) : ''\n return `${message} ${causeMessage}`.trim()\n}\n// oxlint-enable anti-slop/no-runtime-typeof\n"],"mappings":"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"}
1
+ {"version":3,"file":"kv-errors-DXbnO7cB.js","names":[],"sources":["../src/infrastructure/cloudflare/kv-errors.ts"],"sourcesContent":["import {\n AppError,\n isCloudflareOverloadedError,\n isCloudflareRetryableError,\n isTransientTransportError,\n type FailureClassification,\n} from '@/core'\n\n/** KV operations recognized in binding error messages. */\nexport type KVOperation = 'get' | 'put' | 'delete' | 'list'\n\n/** KV failure kinds retained from Typist's binding tests. */\nexport type KVErrorKind =\n | 'invalid_key'\n | 'key_too_large'\n | 'invalid_expiration_ttl'\n | 'invalid_expiration'\n | 'invalid_cache_ttl'\n | 'invalid_list_limit'\n | 'value_too_large'\n | 'client_error'\n | 'rate_limited'\n | 'server_error'\n\n/** Evidence extracted from a KV error and its causes. */\nexport interface KVErrorMeta {\n kind: KVErrorKind\n message: string\n status?: number | undefined\n operation?: Uppercase<KVOperation> | undefined\n}\n\n/** Extract Typist's verified KV message formats, including nested causes. */\nexport function extractKVMeta(cause: unknown): KVErrorMeta | undefined {\n const message = getDeepErrorMessage(cause)\n if (!message) return undefined\n const statusMatch = message.match(/\\bKV\\s+(GET|PUT|DELETE|LIST)\\s+failed:\\s+(\\d{3})\\b/)\n // SAFETY: The regular expression permits only uppercase KV operation names in this capture.\n const operation = statusMatch?.[1] as Uppercase<KVOperation> | undefined\n const status = statusMatch ? Number(statusMatch[2]) : undefined\n\n if (/Key name cannot be empty/i.test(message)) {\n return { kind: 'invalid_key', message, status, operation }\n }\n if (/exceeds key length limit/i.test(message)) {\n return { kind: 'key_too_large', message, status, operation }\n }\n if (/Invalid expiration_ttl/i.test(message)) {\n return { kind: 'invalid_expiration_ttl', message, status, operation }\n }\n if (/Invalid expiration of/i.test(message)) {\n return { kind: 'invalid_expiration', message, status, operation }\n }\n if (/Invalid cache_ttl/i.test(message)) {\n return { kind: 'invalid_cache_ttl', message, status, operation }\n }\n if (/Invalid key_count_limit/i.test(message)) {\n return { kind: 'invalid_list_limit', message, status, operation }\n }\n if (/value.*(too large|exceeds)|exceeds.*value/i.test(message)) {\n return { kind: 'value_too_large', message, status, operation }\n }\n if (status === 429) return { kind: 'rate_limited', message, status, operation }\n if (status !== undefined && status >= 500) {\n return { kind: 'server_error', message, status, operation }\n }\n if (status !== undefined && status >= 400) {\n return { kind: 'client_error', message, status, operation }\n }\n return undefined\n}\n\n/** Identify recognized KV failures that another attempt cannot resolve. */\nexport function isTerminalKVError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n if (!meta) return false\n if (meta.kind === 'rate_limited' || meta.kind === 'server_error') return false\n if (meta.status === 408) return false\n return true\n}\n\n/** Identify a PUT rate limit that requires at least one second before retrying. */\nexport function isKVPutRateLimitError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n return meta?.operation === 'PUT' && meta.kind === 'rate_limited'\n}\n\n/** Identify PUT rate limits, server failures, and request timeouts. */\nexport function isTransientKVError(cause: unknown): boolean {\n const meta = extractKVMeta(cause)\n if (!meta) return false\n return isKVPutRateLimitError(cause) || meta.kind === 'server_error' || meta.status === 408\n}\n\n/** Apply Typist's KV, overload, platform, and transport checks in their original order. */\nexport function isRetryableKVError(cause: unknown): boolean {\n if (isTerminalKVError(cause)) return false\n if (isTransientKVError(cause)) return true\n if (isCloudflareOverloadedError(cause)) return false\n return isCloudflareRetryableError(cause) || isTransientTransportError(cause)\n}\n\n/** Return the existing retry decision and minimum delay in milliseconds. */\nexport function decideKVRetry(\n cause: unknown,\n): { retry: false } | { retry: true; retryAfterMs: number } {\n if (!isRetryableKVError(cause)) return { retry: false }\n return { retry: true, retryAfterMs: isKVPutRateLimitError(cause) ? 1_000 : 0 }\n}\n\n/** A final KV failure with Typist's diagnostics and Better Ship's error classification. */\nexport class KVError extends AppError {\n readonly _tag = 'KVError'\n readonly classification: FailureClassification\n retryable: boolean\n readonly operation: KVOperation\n readonly key?: string | undefined\n override readonly cause: unknown\n readonly kv?: KVErrorMeta | undefined\n readonly context: {\n operation: KVOperation\n key?: string | undefined\n kv?: KVErrorMeta | undefined\n }\n\n constructor(args: { operation: KVOperation; key?: string | undefined; cause: unknown }) {\n const kv = extractKVMeta(args.cause)\n const causeMessage = getDeepErrorMessage(args.cause) || String(args.cause)\n const keyContext = args.key === undefined ? '' : ` for key \"${args.key}\"`\n super(`KV ${args.operation} failed${keyContext}: ${causeMessage}`, { cause: args.cause })\n this.operation = args.operation\n this.key = args.key\n this.cause = args.cause\n this.kv = kv\n this.context = { operation: args.operation, key: args.key, kv }\n this.retryable = isRetryableKVError(args.cause)\n this.classification = isTerminalKVError(args.cause)\n ? 'terminal'\n : this.retryable\n ? 'transient'\n : 'unknown'\n }\n}\n\n// oxlint-disable anti-slop/no-runtime-typeof -- Preserve Typist's primitive messages and nested causes at the raw binding boundary.\nfunction getDeepErrorMessage(cause: unknown): string {\n if (typeof cause === 'string') return cause\n if (cause === null || cause === undefined) return ''\n if (typeof cause === 'number' || typeof cause === 'boolean' || typeof cause === 'bigint') {\n return String(cause)\n }\n if (typeof cause !== 'object') return ''\n const message = 'message' in cause && typeof cause.message === 'string' ? cause.message : ''\n const causeMessage = 'cause' in cause ? getDeepErrorMessage(cause.cause) : ''\n return `${message} ${causeMessage}`.trim()\n}\n// oxlint-enable anti-slop/no-runtime-typeof\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { $ as MetricOptions, et as MetricsService } from "./index-Db2GV9ZP.js";
1
+ import { nt as MetricOptions, rt as MetricsService } from "./index-DaiY8xJJ.js";
2
2
  import { PostHog } from "posthog-node";
3
3
  //#region src/infrastructure/posthog/metrics.d.ts
4
4
  /** PostHog Metrics with Worker lifetime management, ported from Typist's metrics-service.ts. */
@@ -16,4 +16,4 @@ declare class PostHogMetricsService implements MetricsService {
16
16
  }
17
17
  //#endregion
18
18
  export { PostHogMetricsService as t };
19
- //# sourceMappingURL=metrics-DRCoGBNF.d.ts.map
19
+ //# sourceMappingURL=metrics-DzSCDk-u.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics-DRCoGBNF.d.ts","names":[],"sources":["../src/infrastructure/posthog/metrics.ts"],"mappings":";;;;cAKa,iCAAiC;mBAGzB;mBACA;;EAFnB,YACmB,QAAQ,KAAK,qBACb,YAAY,SAAS;;EAIxC,MAAM,cAAc,gBAAW,UAAU;;EAMzC,MAAM,cAAc,eAAe,UAAU;;EAM7C,UAAU,cAAc,eAAe,UAAU"}
1
+ {"version":3,"file":"metrics-DzSCDk-u.d.ts","names":[],"sources":["../src/infrastructure/posthog/metrics.ts"],"mappings":";;;;cAKa,iCAAiC;mBAGzB;mBACA;;EAFnB,YACmB,QAAQ,KAAK,qBACb,YAAY,SAAS;;EAIxC,MAAM,cAAc,gBAAW,UAAU;;EAMzC,MAAM,cAAc,eAAe,UAAU;;EAM7C,UAAU,cAAc,eAAe,UAAU"}
@@ -1,5 +1,5 @@
1
- import "./index-CtIdbnEZ.js";
2
- import { I as IEventCollector } from "./index-Db2GV9ZP.js";
1
+ import "./index-tJzJUgTh.js";
2
+ import { z as IEventCollector } from "./index-DaiY8xJJ.js";
3
3
  import { BatchItem } from "drizzle-orm/batch";
4
4
  //#region src/infrastructure/drizzle-schema.d.ts
5
5
  /**
@@ -21,4 +21,4 @@ declare const OUTBOX_REPOSITORY_DEFAULTS: {
21
21
  type OutboxRepositoryOptions = Readonly<Partial<typeof OUTBOX_REPOSITORY_DEFAULTS>>;
22
22
  //#endregion
23
23
  export { eventCollector as n, DrizzleSchema as r, OutboxRepositoryOptions as t };
24
- //# sourceMappingURL=outbox-repository-options-Cmf0vbBQ.d.ts.map
24
+ //# sourceMappingURL=outbox-repository-options-BPsuMSwA.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"outbox-repository-options-Cmf0vbBQ.d.ts","names":[],"sources":["../src/infrastructure/drizzle-schema.ts","../src/infrastructure/unit-of-work-context.ts","../src/infrastructure/outbox-repository-options.ts"],"mappings":";;;;;;;;KAKY,gBAAgB;;;;cCuBf,gBAAgB;;;;cC3BhB;EACX;;;KAIU,0BAA0B,SAAS,eAAe"}
1
+ {"version":3,"file":"outbox-repository-options-BPsuMSwA.d.ts","names":[],"sources":["../src/infrastructure/drizzle-schema.ts","../src/infrastructure/unit-of-work-context.ts","../src/infrastructure/outbox-repository-options.ts"],"mappings":";;;;;;;;KAKY,gBAAgB;;;;cCuBf,gBAAgB;;;;cC3BhB;EACX;;;KAIU,0BAA0B,SAAS,eAAe"}
@@ -1,4 +1,4 @@
1
- import { t as UnitOfWorkAlreadyActiveError } from "./application-xXTCe8o0.js";
1
+ import { t as UnitOfWorkAlreadyActiveError } from "./application-CnsIQX8h.js";
2
2
  import { panic } from "better-result";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
 
@@ -50,4 +50,4 @@ const OUTBOX_REPOSITORY_DEFAULTS = { leaseMs: 6e4 };
50
50
 
51
51
  //#endregion
52
52
  export { stageD1Statement as a, runWithUnitOfWorkContext as i, collectD1Statements as n, eventCollector as r, OUTBOX_REPOSITORY_DEFAULTS as t };
53
- //# sourceMappingURL=outbox-repository-options-Dd-s5SxA.js.map
53
+ //# sourceMappingURL=outbox-repository-options-DTsXMiR1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"outbox-repository-options-Dd-s5SxA.js","names":[],"sources":["../src/infrastructure/unit-of-work-context.ts","../src/infrastructure/outbox-repository-options.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { panic } from 'better-result'\nimport type { BatchItem } from 'drizzle-orm/batch'\n\nimport { UnitOfWorkAlreadyActiveError, type IEventCollector } from '@/application'\nimport type { DomainEvent } from '@/core'\n\ntype UnitOfWorkContext = { readonly events: DomainEvent[] } & (\n | { readonly database: 'd1'; readonly statements: BatchItem<'sqlite'>[] }\n | { readonly database: 'postgres' }\n)\n\n// One async scope isolates events and D1 statements and rejects nesting across both adapters.\nconst storage = new AsyncLocalStorage<UnitOfWorkContext>()\n\n/** Reject nested transactions before database work starts; preserve independent concurrent execution. */\nexport async function runWithUnitOfWorkContext<T>(\n database: UnitOfWorkContext['database'],\n work: () => Promise<T>,\n): Promise<T> {\n if (storage.getStore() !== undefined) throw new UnitOfWorkAlreadyActiveError()\n const context: UnitOfWorkContext =\n database === 'd1' ? { database, events: [], statements: [] } : { database, events: [] }\n return storage.run(context, work)\n}\n\n/** Inject this shared scope into the unit of work and expose its emitter to application handlers. */\nexport const eventCollector: IEventCollector = {\n emit(event) {\n currentContext().events.push(event)\n },\n collect() {\n return [...currentContext().events]\n },\n}\n\n/** Queue one native D1 statement for the active batch; other contexts cannot accept D1 writes. */\nexport function stageD1Statement(statement: BatchItem<'sqlite'>): void {\n d1Context().statements.push(statement)\n}\n\n/** Read the active D1 batch in staging order for commit. */\nexport function collectD1Statements(): ReadonlyArray<BatchItem<'sqlite'>> {\n return [...d1Context().statements]\n}\n\nfunction d1Context(): Extract<UnitOfWorkContext, { database: 'd1' }> {\n const context = currentContext()\n if (context.database !== 'd1') return panic('D1 statements require a D1 unit of work')\n return context\n}\n\nfunction currentContext(): UnitOfWorkContext {\n return storage.getStore() ?? panic('operation requires an active unit of work')\n}\n","/** Shared lease default for both database adapters. */\nexport const OUTBOX_REPOSITORY_DEFAULTS = {\n leaseMs: 60_000,\n}\n\n/** Override the lease length at the composition root. */\nexport type OutboxRepositoryOptions = Readonly<Partial<typeof OUTBOX_REPOSITORY_DEFAULTS>>\n"],"mappings":";;;;;AAcA,MAAM,UAAU,IAAI,kBAAqC;;AAGzD,eAAsB,yBACpB,UACA,MACY;CACZ,IAAI,QAAQ,SAAS,MAAM,QAAW,MAAM,IAAI,6BAA6B;CAC7E,MAAM,UACJ,aAAa,OAAO;EAAE;EAAU,QAAQ,CAAC;EAAG,YAAY,CAAC;CAAE,IAAI;EAAE;EAAU,QAAQ,CAAC;CAAE;CACxF,OAAO,QAAQ,IAAI,SAAS,IAAI;AAClC;;AAGA,MAAa,iBAAkC;CAC7C,KAAK,OAAO;EACV,eAAe,CAAC,CAAC,OAAO,KAAK,KAAK;CACpC;CACA,UAAU;EACR,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC,MAAM;CACpC;AACF;;AAGA,SAAgB,iBAAiB,WAAsC;CACrE,UAAU,CAAC,CAAC,WAAW,KAAK,SAAS;AACvC;;AAGA,SAAgB,sBAA0D;CACxE,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU;AACnC;AAEA,SAAS,YAA4D;CACnE,MAAM,UAAU,eAAe;CAC/B,IAAI,QAAQ,aAAa,MAAM,OAAO,MAAM,yCAAyC;CACrF,OAAO;AACT;AAEA,SAAS,iBAAoC;CAC3C,OAAO,QAAQ,SAAS,KAAK,MAAM,2CAA2C;AAChF;;;;;ACtDA,MAAa,6BAA6B,EACxC,SAAS,IACX"}
1
+ {"version":3,"file":"outbox-repository-options-DTsXMiR1.js","names":[],"sources":["../src/infrastructure/unit-of-work-context.ts","../src/infrastructure/outbox-repository-options.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { panic } from 'better-result'\nimport type { BatchItem } from 'drizzle-orm/batch'\n\nimport { UnitOfWorkAlreadyActiveError, type IEventCollector } from '@/application'\nimport type { DomainEvent } from '@/core'\n\ntype UnitOfWorkContext = { readonly events: DomainEvent[] } & (\n | { readonly database: 'd1'; readonly statements: BatchItem<'sqlite'>[] }\n | { readonly database: 'postgres' }\n)\n\n// One async scope isolates events and D1 statements and rejects nesting across both adapters.\nconst storage = new AsyncLocalStorage<UnitOfWorkContext>()\n\n/** Reject nested transactions before database work starts; preserve independent concurrent execution. */\nexport async function runWithUnitOfWorkContext<T>(\n database: UnitOfWorkContext['database'],\n work: () => Promise<T>,\n): Promise<T> {\n if (storage.getStore() !== undefined) throw new UnitOfWorkAlreadyActiveError()\n const context: UnitOfWorkContext =\n database === 'd1' ? { database, events: [], statements: [] } : { database, events: [] }\n return storage.run(context, work)\n}\n\n/** Inject this shared scope into the unit of work and expose its emitter to application handlers. */\nexport const eventCollector: IEventCollector = {\n emit(event) {\n currentContext().events.push(event)\n },\n collect() {\n return [...currentContext().events]\n },\n}\n\n/** Queue one native D1 statement for the active batch; other contexts cannot accept D1 writes. */\nexport function stageD1Statement(statement: BatchItem<'sqlite'>): void {\n d1Context().statements.push(statement)\n}\n\n/** Read the active D1 batch in staging order for commit. */\nexport function collectD1Statements(): ReadonlyArray<BatchItem<'sqlite'>> {\n return [...d1Context().statements]\n}\n\nfunction d1Context(): Extract<UnitOfWorkContext, { database: 'd1' }> {\n const context = currentContext()\n if (context.database !== 'd1') return panic('D1 statements require a D1 unit of work')\n return context\n}\n\nfunction currentContext(): UnitOfWorkContext {\n return storage.getStore() ?? panic('operation requires an active unit of work')\n}\n","/** Shared lease default for both database adapters. */\nexport const OUTBOX_REPOSITORY_DEFAULTS = {\n leaseMs: 60_000,\n}\n\n/** Override the lease length at the composition root. */\nexport type OutboxRepositoryOptions = Readonly<Partial<typeof OUTBOX_REPOSITORY_DEFAULTS>>\n"],"mappings":";;;;;AAcA,MAAM,UAAU,IAAI,kBAAqC;;AAGzD,eAAsB,yBACpB,UACA,MACY;CACZ,IAAI,QAAQ,SAAS,MAAM,QAAW,MAAM,IAAI,6BAA6B;CAC7E,MAAM,UACJ,aAAa,OAAO;EAAE;EAAU,QAAQ,CAAC;EAAG,YAAY,CAAC;CAAE,IAAI;EAAE;EAAU,QAAQ,CAAC;CAAE;CACxF,OAAO,QAAQ,IAAI,SAAS,IAAI;AAClC;;AAGA,MAAa,iBAAkC;CAC7C,KAAK,OAAO;EACV,eAAe,CAAC,CAAC,OAAO,KAAK,KAAK;CACpC;CACA,UAAU;EACR,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC,MAAM;CACpC;AACF;;AAGA,SAAgB,iBAAiB,WAAsC;CACrE,UAAU,CAAC,CAAC,WAAW,KAAK,SAAS;AACvC;;AAGA,SAAgB,sBAA0D;CACxE,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU;AACnC;AAEA,SAAS,YAA4D;CACnE,MAAM,UAAU,eAAe;CAC/B,IAAI,QAAQ,aAAa,MAAM,OAAO,MAAM,yCAAyC;CACrF,OAAO;AACT;AAEA,SAAS,iBAAoC;CAC3C,OAAO,QAAQ,SAAS,KAAK,MAAM,2CAA2C;AAChF;;;;;ACtDA,MAAa,6BAA6B,EACxC,SAAS,IACX"}
@@ -1,4 +1,4 @@
1
- import { tt as AppError } from "./core-DOBZeYSX.js";
1
+ import { rt as AppError } from "./core-CV8SQv01.js";
2
2
  import Stripe from "stripe";
3
3
 
4
4
  //#region src/infrastructure/stripe/payment-service.error.ts
@@ -27,4 +27,4 @@ function classifyStripeError(error) {
27
27
 
28
28
  //#endregion
29
29
  export { PaymentServiceError as t };
30
- //# sourceMappingURL=payment-service.error-BR10zqxk.js.map
30
+ //# sourceMappingURL=payment-service.error-oW2bKAfU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payment-service.error-BR10zqxk.js","names":[],"sources":["../src/infrastructure/stripe/payment-service.error.ts"],"sourcesContent":["import Stripe from 'stripe'\n\nimport { AppError, type FailureClassification } from '@/core'\n\n/** A final Stripe request failure. The caller logs once; native details remain in cause. */\nexport class PaymentServiceError extends AppError {\n readonly _tag = 'PaymentServiceError'\n readonly classification: FailureClassification\n\n /** Classify the final SDK error without scheduling another payment attempt. */\n constructor(\n readonly operation: string,\n cause: Stripe.errors.StripeError,\n ) {\n super(`Stripe request failed: ${operation}`, { cause })\n this.classification = classifyStripeError(cause)\n }\n}\n\nfunction classifyStripeError(error: Stripe.errors.StripeError): FailureClassification {\n if (error.headers?.['stripe-should-retry'] === 'false') return 'terminal'\n const status = error.statusCode\n if (status !== undefined && status >= 400 && status < 500 && status !== 409 && status !== 429)\n return 'terminal'\n if (\n error instanceof Stripe.errors.StripeAuthenticationError ||\n error instanceof Stripe.errors.StripePermissionError ||\n error instanceof Stripe.errors.StripeInvalidRequestError ||\n error instanceof Stripe.errors.StripeIdempotencyError ||\n error instanceof Stripe.errors.StripeCardError\n )\n return 'terminal'\n if (error.headers?.['stripe-should-retry'] === 'true') return 'transient'\n if (status === 409 || status === 429 || (status !== undefined && status >= 500))\n return 'transient'\n if (\n error instanceof Stripe.errors.StripeConnectionError ||\n error instanceof Stripe.errors.StripeAPIError ||\n error instanceof Stripe.errors.StripeRateLimitError\n )\n return 'transient'\n return 'unknown'\n}\n"],"mappings":";;;;;AAKA,IAAa,sBAAb,cAAyC,SAAS;CAMrC;CALX,AAAS,OAAO;CAChB,AAAS;;CAGT,YACE,AAAS,WACT,OACA;EACA,MAAM,0BAA0B,aAAa,EAAE,MAAM,CAAC;EAH7C;EAIT,KAAK,iBAAiB,oBAAoB,KAAK;CACjD;AACF;AAEA,SAAS,oBAAoB,OAAyD;CACpF,IAAI,MAAM,UAAU,2BAA2B,SAAS,OAAO;CAC/D,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,UAAa,UAAU,OAAO,SAAS,OAAO,WAAW,OAAO,WAAW,KACxF,OAAO;CACT,IACE,iBAAiB,OAAO,OAAO,6BAC/B,iBAAiB,OAAO,OAAO,yBAC/B,iBAAiB,OAAO,OAAO,6BAC/B,iBAAiB,OAAO,OAAO,0BAC/B,iBAAiB,OAAO,OAAO,iBAE/B,OAAO;CACT,IAAI,MAAM,UAAU,2BAA2B,QAAQ,OAAO;CAC9D,IAAI,WAAW,OAAO,WAAW,OAAQ,WAAW,UAAa,UAAU,KACzE,OAAO;CACT,IACE,iBAAiB,OAAO,OAAO,yBAC/B,iBAAiB,OAAO,OAAO,kBAC/B,iBAAiB,OAAO,OAAO,sBAE/B,OAAO;CACT,OAAO;AACT"}
1
+ {"version":3,"file":"payment-service.error-oW2bKAfU.js","names":[],"sources":["../src/infrastructure/stripe/payment-service.error.ts"],"sourcesContent":["import Stripe from 'stripe'\n\nimport { AppError, type FailureClassification } from '@/core'\n\n/** A final Stripe request failure. The caller logs once; native details remain in cause. */\nexport class PaymentServiceError extends AppError {\n readonly _tag = 'PaymentServiceError'\n readonly classification: FailureClassification\n\n /** Classify the final SDK error without scheduling another payment attempt. */\n constructor(\n readonly operation: string,\n cause: Stripe.errors.StripeError,\n ) {\n super(`Stripe request failed: ${operation}`, { cause })\n this.classification = classifyStripeError(cause)\n }\n}\n\nfunction classifyStripeError(error: Stripe.errors.StripeError): FailureClassification {\n if (error.headers?.['stripe-should-retry'] === 'false') return 'terminal'\n const status = error.statusCode\n if (status !== undefined && status >= 400 && status < 500 && status !== 409 && status !== 429)\n return 'terminal'\n if (\n error instanceof Stripe.errors.StripeAuthenticationError ||\n error instanceof Stripe.errors.StripePermissionError ||\n error instanceof Stripe.errors.StripeInvalidRequestError ||\n error instanceof Stripe.errors.StripeIdempotencyError ||\n error instanceof Stripe.errors.StripeCardError\n )\n return 'terminal'\n if (error.headers?.['stripe-should-retry'] === 'true') return 'transient'\n if (status === 409 || status === 429 || (status !== undefined && status >= 500))\n return 'transient'\n if (\n error instanceof Stripe.errors.StripeConnectionError ||\n error instanceof Stripe.errors.StripeAPIError ||\n error instanceof Stripe.errors.StripeRateLimitError\n )\n return 'transient'\n return 'unknown'\n}\n"],"mappings":";;;;;AAKA,IAAa,sBAAb,cAAyC,SAAS;CAMrC;CALX,AAAS,OAAO;CAChB,AAAS;;CAGT,YACE,AAAS,WACT,OACA;EACA,MAAM,0BAA0B,aAAa,EAAE,MAAM,CAAC;EAH7C;EAIT,KAAK,iBAAiB,oBAAoB,KAAK;CACjD;AACF;AAEA,SAAS,oBAAoB,OAAyD;CACpF,IAAI,MAAM,UAAU,2BAA2B,SAAS,OAAO;CAC/D,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,UAAa,UAAU,OAAO,SAAS,OAAO,WAAW,OAAO,WAAW,KACxF,OAAO;CACT,IACE,iBAAiB,OAAO,OAAO,6BAC/B,iBAAiB,OAAO,OAAO,yBAC/B,iBAAiB,OAAO,OAAO,6BAC/B,iBAAiB,OAAO,OAAO,0BAC/B,iBAAiB,OAAO,OAAO,iBAE/B,OAAO;CACT,IAAI,MAAM,UAAU,2BAA2B,QAAQ,OAAO;CAC9D,IAAI,WAAW,OAAO,WAAW,OAAQ,WAAW,UAAa,UAAU,KACzE,OAAO;CACT,IACE,iBAAiB,OAAO,OAAO,yBAC/B,iBAAiB,OAAO,OAAO,kBAC/B,iBAAiB,OAAO,OAAO,sBAE/B,OAAO;CACT,OAAO;AACT"}
@@ -1,6 +1,6 @@
1
- import { Jt as AppError, W as DomainEvent, nt as DatabaseFailure, q as MessageId, tt as DatabaseError } from "./index-CtIdbnEZ.js";
2
- import { F as IMessageStore, N as ITransaction, c as IOutboxRepository, d as OutboxFailureReason, f as OutboxRow, u as OutboxBatch } from "./index-Db2GV9ZP.js";
3
- import { n as eventCollector, r as DrizzleSchema, t as OutboxRepositoryOptions } from "./outbox-repository-options-Cmf0vbBQ.js";
1
+ import { J as DomainEvent, Qt as AppError, Z as MessageId, at as DatabaseError, ot as DatabaseFailure } from "./index-tJzJUgTh.js";
2
+ import { I as ITransaction, R as IMessageStore, d as IOutboxRepository, h as OutboxRow, m as OutboxFailureReason, p as OutboxBatch } from "./index-DaiY8xJJ.js";
3
+ import { n as eventCollector, r as DrizzleSchema, t as OutboxRepositoryOptions } from "./outbox-repository-options-BPsuMSwA.js";
4
4
  import { ExtractTablesWithRelations } from "drizzle-orm";
5
5
  import { NodePgDatabase, NodePgTransaction } from "drizzle-orm/node-postgres";
6
6
  import { Pool } from "pg";
package/dist/postgres.js CHANGED
@@ -1,6 +1,6 @@
1
- import { O as DatabaseError, tt as AppError } from "./core-DOBZeYSX.js";
2
- import { o as MessageAlreadyProcessedError } from "./application-xXTCe8o0.js";
3
- import { i as runWithUnitOfWorkContext, r as eventCollector, t as OUTBOX_REPOSITORY_DEFAULTS } from "./outbox-repository-options-Dd-s5SxA.js";
1
+ import { A as DatabaseError, rt as AppError } from "./core-CV8SQv01.js";
2
+ import { s as MessageAlreadyProcessedError } from "./application-CnsIQX8h.js";
3
+ import { i as runWithUnitOfWorkContext, r as eventCollector, t as OUTBOX_REPOSITORY_DEFAULTS } from "./outbox-repository-options-DTsXMiR1.js";
4
4
  import { Result } from "better-result";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { DrizzleQueryError } from "drizzle-orm/errors";
@@ -1,2 +1,2 @@
1
- import { t as PostHogMetricsService } from "../metrics-DRCoGBNF.js";
1
+ import { t as PostHogMetricsService } from "../metrics-DzSCDk-u.js";
2
2
  export { PostHogMetricsService };
@@ -1,6 +1,6 @@
1
- import { Kt as AnalyticsTarget, Ut as AnalyticsEventInput, Wt as AnalyticsProperties } from "../index-CtIdbnEZ.js";
2
- import { rt as AnalyticsService } from "../index-Db2GV9ZP.js";
3
- import { t as PostHogMetricsService } from "../metrics-DRCoGBNF.js";
1
+ import { Jt as AnalyticsProperties, Xt as AnalyticsTarget, qt as AnalyticsEventInput } from "../index-tJzJUgTh.js";
2
+ import { ot as AnalyticsService } from "../index-DaiY8xJJ.js";
3
+ import { t as PostHogMetricsService } from "../metrics-DzSCDk-u.js";
4
4
  import { PostHog, PostHogOptions } from "posthog-node";
5
5
  //#region src/infrastructure/posthog/server.d.ts
6
6
  /** Deployment values and SDK options; the runtime owns delivery promises. */
@@ -1,4 +1,4 @@
1
- import { et as MissingConfigurationError } from "../core-DOBZeYSX.js";
1
+ import { nt as MissingConfigurationError } from "../core-CV8SQv01.js";
2
2
  import { t as PostHogMetricsService } from "../metrics-CWv37yf9.js";
3
3
  import { v5, validate } from "uuid";
4
4
  import { PostHog } from "posthog-node";
@@ -1,4 +1,4 @@
1
- import { tt as AppError, u as classifyBoundaryError, v as isAbortError } from "./core-DOBZeYSX.js";
1
+ import { b as isAbortError, f as classifyBoundaryError, rt as AppError } from "./core-CV8SQv01.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/infrastructure/cloudflare/r2-errors.ts
@@ -87,4 +87,4 @@ var R2JsonError = class extends AppError {
87
87
 
88
88
  //#endregion
89
89
  export { R2JsonError as n, R2Error as t };
90
- //# sourceMappingURL=r2-errors-BF49eqU_.js.map
90
+ //# sourceMappingURL=r2-errors-DzpOvciV.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"r2-errors-BF49eqU_.js","names":[],"sources":["../src/infrastructure/cloudflare/r2-errors.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { AppError, classifyBoundaryError, isAbortError, type FailureClassification } from '@/core'\n\n/** The storage operation that failed. */\nexport type R2Operation =\n | 'head'\n | 'get'\n | 'getJson'\n | 'put'\n | 'delete'\n | 'list'\n | 'createMultipartUpload'\n | 'uploadPart'\n | 'complete'\n | 'abort'\n\n/** Provider diagnostics from the outer failure, without request bodies or credentials. */\nexport type R2Failure = {\n readonly code: number\n readonly action?: string | undefined\n}\n\nconst R2FailureSchema = z.object({\n code: z.number().int().positive(),\n action: z.string().optional(),\n})\n\n// R2 codes describe failures; the caller owns retry decisions and repeat safety.\nconst classifications: ReadonlyMap<number, FailureClassification> = new Map([\n [10001, 'transient'],\n [10043, 'transient'],\n [10054, 'transient'],\n [10058, 'transient'],\n [10013, 'transient'],\n [10002, 'terminal'],\n [10003, 'terminal'],\n [10018, 'terminal'],\n [10035, 'terminal'],\n [10042, 'terminal'],\n [10005, 'terminal'],\n [10006, 'terminal'],\n [10008, 'terminal'],\n [10009, 'terminal'],\n [10073, 'terminal'],\n [10007, 'terminal'],\n [10020, 'terminal'],\n [100100, 'terminal'],\n [10012, 'terminal'],\n [10069, 'terminal'],\n [10033, 'terminal'],\n [10014, 'terminal'],\n [10037, 'terminal'],\n [10039, 'terminal'],\n [10031, 'terminal'],\n [10011, 'terminal'],\n [10024, 'terminal'],\n [10025, 'terminal'],\n [10048, 'terminal'],\n])\n\nfunction extractR2Failure(cause: unknown): R2Failure | undefined {\n if (!(cause instanceof Error)) return undefined\n const parsed = R2FailureSchema.safeParse(cause)\n if (parsed.success) return parsed.data\n // Cloudflare documents the numeric suffix for bindings that omit structured fields.\n const match = /\\((\\d{5,6})\\)\\s*$/.exec(cause.message)\n return match?.[1] === undefined ? undefined : { code: Number(match[1]) }\n}\n\nfunction classifyR2Code(cause: unknown): FailureClassification | undefined {\n const failure = extractR2Failure(cause)\n return failure === undefined ? undefined : (classifications.get(failure.code) ?? 'unknown')\n}\n\nfunction classifyR2Error(cause: unknown): FailureClassification {\n if (isAbortError(cause)) return 'terminal'\n if (cause instanceof AppError) return cause.classification\n return classifyBoundaryError({ cause, classifyBoundary: classifyR2Code, includeCloudflare: true })\n}\n\n/** A raw binding failure after one attempt. Classification does not establish whether a mutation committed. */\nexport class R2Error extends AppError {\n readonly _tag = 'R2Error'\n readonly classification: FailureClassification\n readonly operation: R2Operation\n readonly r2?: R2Failure | undefined\n override readonly cause: unknown\n\n constructor(input: { operation: R2Operation; cause: unknown }) {\n super(`R2 ${input.operation} failed`, { cause: input.cause })\n this.operation = input.operation\n this.cause = input.cause\n this.r2 = extractR2Failure(input.cause)\n this.classification = classifyR2Error(input.cause)\n }\n}\n\n/** JSON serialization or syntax failed. Binding and body-read failures use R2Error. */\nexport class R2JsonError extends AppError {\n readonly _tag = 'R2JsonError'\n readonly classification = 'terminal'\n readonly operation: 'encode' | 'decode'\n override readonly cause: unknown\n\n constructor(input: { operation: 'encode' | 'decode'; cause: unknown }) {\n super(`R2 JSON ${input.operation} failed`, { cause: input.cause })\n this.operation = input.operation\n this.cause = input.cause\n }\n}\n"],"mappings":";;;;AAuBA,MAAM,kBAAkB,EAAE,OAAO;CAC/B,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CAChC,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;AAC9B,CAAC;AAGD,MAAM,kCAA8D,IAAI,IAAI;CAC1E,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,QAAQ,UAAU;CACnB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;AACpB,CAAC;AAED,SAAS,iBAAiB,OAAuC;CAC/D,IAAI,EAAE,iBAAiB,QAAQ,OAAO;CACtC,MAAM,SAAS,gBAAgB,UAAU,KAAK;CAC9C,IAAI,OAAO,SAAS,OAAO,OAAO;CAElC,MAAM,QAAQ,oBAAoB,KAAK,MAAM,OAAO;CACpD,OAAO,QAAQ,OAAO,SAAY,SAAY,EAAE,MAAM,OAAO,MAAM,EAAE,EAAE;AACzE;AAEA,SAAS,eAAe,OAAmD;CACzE,MAAM,UAAU,iBAAiB,KAAK;CACtC,OAAO,YAAY,SAAY,SAAa,gBAAgB,IAAI,QAAQ,IAAI,KAAK;AACnF;AAEA,SAAS,gBAAgB,OAAuC;CAC9D,IAAI,aAAa,KAAK,GAAG,OAAO;CAChC,IAAI,iBAAiB,UAAU,OAAO,MAAM;CAC5C,OAAO,sBAAsB;EAAE;EAAO,kBAAkB;EAAgB,mBAAmB;CAAK,CAAC;AACnG;;AAGA,IAAa,UAAb,cAA6B,SAAS;CACpC,AAAS,OAAO;CAChB,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAkB;CAElB,YAAY,OAAmD;EAC7D,MAAM,MAAM,MAAM,UAAU,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC;EAC5D,KAAK,YAAY,MAAM;EACvB,KAAK,QAAQ,MAAM;EACnB,KAAK,KAAK,iBAAiB,MAAM,KAAK;EACtC,KAAK,iBAAiB,gBAAgB,MAAM,KAAK;CACnD;AACF;;AAGA,IAAa,cAAb,cAAiC,SAAS;CACxC,AAAS,OAAO;CAChB,AAAS,iBAAiB;CAC1B,AAAS;CACT,AAAkB;CAElB,YAAY,OAA2D;EACrE,MAAM,WAAW,MAAM,UAAU,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC;EACjE,KAAK,YAAY,MAAM;EACvB,KAAK,QAAQ,MAAM;CACrB;AACF"}
1
+ {"version":3,"file":"r2-errors-DzpOvciV.js","names":[],"sources":["../src/infrastructure/cloudflare/r2-errors.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { AppError, classifyBoundaryError, isAbortError, type FailureClassification } from '@/core'\n\n/** The storage operation that failed. */\nexport type R2Operation =\n | 'head'\n | 'get'\n | 'getJson'\n | 'put'\n | 'delete'\n | 'list'\n | 'createMultipartUpload'\n | 'uploadPart'\n | 'complete'\n | 'abort'\n\n/** Provider diagnostics from the outer failure, without request bodies or credentials. */\nexport type R2Failure = {\n readonly code: number\n readonly action?: string | undefined\n}\n\nconst R2FailureSchema = z.object({\n code: z.number().int().positive(),\n action: z.string().optional(),\n})\n\n// R2 codes describe failures; the caller owns retry decisions and repeat safety.\nconst classifications: ReadonlyMap<number, FailureClassification> = new Map([\n [10001, 'transient'],\n [10043, 'transient'],\n [10054, 'transient'],\n [10058, 'transient'],\n [10013, 'transient'],\n [10002, 'terminal'],\n [10003, 'terminal'],\n [10018, 'terminal'],\n [10035, 'terminal'],\n [10042, 'terminal'],\n [10005, 'terminal'],\n [10006, 'terminal'],\n [10008, 'terminal'],\n [10009, 'terminal'],\n [10073, 'terminal'],\n [10007, 'terminal'],\n [10020, 'terminal'],\n [100100, 'terminal'],\n [10012, 'terminal'],\n [10069, 'terminal'],\n [10033, 'terminal'],\n [10014, 'terminal'],\n [10037, 'terminal'],\n [10039, 'terminal'],\n [10031, 'terminal'],\n [10011, 'terminal'],\n [10024, 'terminal'],\n [10025, 'terminal'],\n [10048, 'terminal'],\n])\n\nfunction extractR2Failure(cause: unknown): R2Failure | undefined {\n if (!(cause instanceof Error)) return undefined\n const parsed = R2FailureSchema.safeParse(cause)\n if (parsed.success) return parsed.data\n // Cloudflare documents the numeric suffix for bindings that omit structured fields.\n const match = /\\((\\d{5,6})\\)\\s*$/.exec(cause.message)\n return match?.[1] === undefined ? undefined : { code: Number(match[1]) }\n}\n\nfunction classifyR2Code(cause: unknown): FailureClassification | undefined {\n const failure = extractR2Failure(cause)\n return failure === undefined ? undefined : (classifications.get(failure.code) ?? 'unknown')\n}\n\nfunction classifyR2Error(cause: unknown): FailureClassification {\n if (isAbortError(cause)) return 'terminal'\n if (cause instanceof AppError) return cause.classification\n return classifyBoundaryError({ cause, classifyBoundary: classifyR2Code, includeCloudflare: true })\n}\n\n/** A raw binding failure after one attempt. Classification does not establish whether a mutation committed. */\nexport class R2Error extends AppError {\n readonly _tag = 'R2Error'\n readonly classification: FailureClassification\n readonly operation: R2Operation\n readonly r2?: R2Failure | undefined\n override readonly cause: unknown\n\n constructor(input: { operation: R2Operation; cause: unknown }) {\n super(`R2 ${input.operation} failed`, { cause: input.cause })\n this.operation = input.operation\n this.cause = input.cause\n this.r2 = extractR2Failure(input.cause)\n this.classification = classifyR2Error(input.cause)\n }\n}\n\n/** JSON serialization or syntax failed. Binding and body-read failures use R2Error. */\nexport class R2JsonError extends AppError {\n readonly _tag = 'R2JsonError'\n readonly classification = 'terminal'\n readonly operation: 'encode' | 'decode'\n override readonly cause: unknown\n\n constructor(input: { operation: 'encode' | 'decode'; cause: unknown }) {\n super(`R2 JSON ${input.operation} failed`, { cause: input.cause })\n this.operation = input.operation\n this.cause = input.cause\n }\n}\n"],"mappings":";;;;AAuBA,MAAM,kBAAkB,EAAE,OAAO;CAC/B,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CAChC,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;AAC9B,CAAC;AAGD,MAAM,kCAA8D,IAAI,IAAI;CAC1E,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,WAAW;CACnB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,QAAQ,UAAU;CACnB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;CAClB,CAAC,OAAO,UAAU;AACpB,CAAC;AAED,SAAS,iBAAiB,OAAuC;CAC/D,IAAI,EAAE,iBAAiB,QAAQ,OAAO;CACtC,MAAM,SAAS,gBAAgB,UAAU,KAAK;CAC9C,IAAI,OAAO,SAAS,OAAO,OAAO;CAElC,MAAM,QAAQ,oBAAoB,KAAK,MAAM,OAAO;CACpD,OAAO,QAAQ,OAAO,SAAY,SAAY,EAAE,MAAM,OAAO,MAAM,EAAE,EAAE;AACzE;AAEA,SAAS,eAAe,OAAmD;CACzE,MAAM,UAAU,iBAAiB,KAAK;CACtC,OAAO,YAAY,SAAY,SAAa,gBAAgB,IAAI,QAAQ,IAAI,KAAK;AACnF;AAEA,SAAS,gBAAgB,OAAuC;CAC9D,IAAI,aAAa,KAAK,GAAG,OAAO;CAChC,IAAI,iBAAiB,UAAU,OAAO,MAAM;CAC5C,OAAO,sBAAsB;EAAE;EAAO,kBAAkB;EAAgB,mBAAmB;CAAK,CAAC;AACnG;;AAGA,IAAa,UAAb,cAA6B,SAAS;CACpC,AAAS,OAAO;CAChB,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAkB;CAElB,YAAY,OAAmD;EAC7D,MAAM,MAAM,MAAM,UAAU,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC;EAC5D,KAAK,YAAY,MAAM;EACvB,KAAK,QAAQ,MAAM;EACnB,KAAK,KAAK,iBAAiB,MAAM,KAAK;EACtC,KAAK,iBAAiB,gBAAgB,MAAM,KAAK;CACnD;AACF;;AAGA,IAAa,cAAb,cAAiC,SAAS;CACxC,AAAS,OAAO;CAChB,AAAS,iBAAiB;CAC1B,AAAS;CACT,AAAkB;CAElB,YAAY,OAA2D;EACrE,MAAM,WAAW,MAAM,UAAU,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC;EACjE,KAAK,YAAY,MAAM;EACvB,KAAK,QAAQ,MAAM;CACrB;AACF"}
@@ -1,4 +1,4 @@
1
- import { t as PaymentServiceError } from "./payment-service.error-BR10zqxk.js";
1
+ import { t as PaymentServiceError } from "./payment-service.error-oW2bKAfU.js";
2
2
  import Stripe from "stripe";
3
3
 
4
4
  //#region src/infrastructure/stripe/request.ts
@@ -18,4 +18,4 @@ async function stripeRequest(operation, work) {
18
18
 
19
19
  //#endregion
20
20
  export { stripeRequest as t };
21
- //# sourceMappingURL=request-BYQodKDU.js.map
21
+ //# sourceMappingURL=request-C5k8ME_7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-BYQodKDU.js","names":[],"sources":["../src/infrastructure/stripe/request.ts"],"sourcesContent":["import Stripe from 'stripe'\n\nimport { PaymentServiceError } from './payment-service.error.ts'\n\n/**\n * Invoke one SDK operation; the SDK owns retries configured on its client or request.\n * Convert every Stripe error to PaymentServiceError without logging; preserve the original error in cause.\n * Non-Stripe failures propagate unchanged.\n */\nexport async function stripeRequest<T>(operation: string, work: () => Promise<T>): Promise<T> {\n try {\n return await work()\n } catch (cause) {\n if (!(cause instanceof Stripe.errors.StripeError)) throw cause\n throw new PaymentServiceError(operation, cause)\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,cAAiB,WAAmB,MAAoC;CAC5F,IAAI;EACF,OAAO,MAAM,KAAK;CACpB,SAAS,OAAO;EACd,IAAI,EAAE,iBAAiB,OAAO,OAAO,cAAc,MAAM;EACzD,MAAM,IAAI,oBAAoB,WAAW,KAAK;CAChD;AACF"}
1
+ {"version":3,"file":"request-C5k8ME_7.js","names":[],"sources":["../src/infrastructure/stripe/request.ts"],"sourcesContent":["import Stripe from 'stripe'\n\nimport { PaymentServiceError } from './payment-service.error.ts'\n\n/**\n * Invoke one SDK operation; the SDK owns retries configured on its client or request.\n * Convert every Stripe error to PaymentServiceError without logging; preserve the original error in cause.\n * Non-Stripe failures propagate unchanged.\n */\nexport async function stripeRequest<T>(operation: string, work: () => Promise<T>): Promise<T> {\n try {\n return await work()\n } catch (cause) {\n if (!(cause instanceof Stripe.errors.StripeError)) throw cause\n throw new PaymentServiceError(operation, cause)\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,cAAiB,WAAmB,MAAoC;CAC5F,IAAI;EACF,OAAO,MAAM,KAAK;CACpB,SAAS,OAAO;EACd,IAAI,EAAE,iBAAiB,OAAO,OAAO,cAAc,MAAM;EACzD,MAAM,IAAI,oBAAoB,WAAW,KAAK;CAChD;AACF"}
package/dist/resend.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { jt as BounceType } from "./index-CtIdbnEZ.js";
2
- import { L as EmailAccepted, U as ReceivedContent, V as OutboundEmail, W as ReceivedEmail, z as IEmailService } from "./index-Db2GV9ZP.js";
3
- import { n as WebhookVerifier } from "./webhook-verification-DL4L3zbu.js";
1
+ import { Ft as BounceType } from "./index-tJzJUgTh.js";
2
+ import { B as EmailAccepted, H as IEmailService, K as ReceivedContent, W as OutboundEmail, q as ReceivedEmail } from "./index-DaiY8xJJ.js";
3
+ import { n as WebhookVerifier } from "./webhook-verification-Cy4Z5djk.js";
4
4
  import "resend";
5
5
  //#region src/infrastructure/resend/resend-email-service.d.ts
6
6
  /**
package/dist/resend.js CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as EmailAddressSchema, J as parseBounceType, X as EmailServiceError } from "./core-DOBZeYSX.js";
2
- import { t as WebhookVerificationError } from "./webhook-verification-C4R6OO7f.js";
1
+ import { Q as EmailServiceError, X as parseBounceType, tt as EmailAddressSchema } from "./core-CV8SQv01.js";
2
+ import { t as WebhookVerificationError } from "./webhook-verification-B8v3-LQ2.js";
3
3
  import { z } from "zod";
4
4
  import { Buffer } from "node:buffer";
5
5
 
@@ -1,4 +1,4 @@
1
- import { u as LoggerErrorHook } from "../index-CtIdbnEZ.js";
1
+ import { u as LoggerErrorHook } from "../index-tJzJUgTh.js";
2
2
  import * as Sentry from "@sentry/tanstackstart-react";
3
3
  //#region src/infrastructure/sentry/client.d.ts
4
4
  /** Application settings use Sentry's names; enablement and environment belong to the application. */
@@ -1,4 +1,4 @@
1
- import { a as setLoggerErrorHook } from "../core-DOBZeYSX.js";
1
+ import { a as setLoggerErrorHook } from "../core-CV8SQv01.js";
2
2
  import * as Sentry from "@sentry/tanstackstart-react";
3
3
  import { isNotFound, isRedirect } from "@tanstack/react-router";
4
4