better-ship 0.36.0 → 0.38.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 (118) hide show
  1. package/dist/{application-B5hnNUdI.js → application-Dsz-o9Aj.js} +8 -5
  2. package/dist/{application-B5hnNUdI.js.map → application-Dsz-o9Aj.js.map} +1 -1
  3. package/dist/application.d.ts +3 -3
  4. package/dist/application.js +3 -2
  5. package/dist/{auth-secondary-storage-b9ptwPSB.d.ts → auth-secondary-storage-CcNkkEk0.d.ts} +2 -2
  6. package/dist/{auth-secondary-storage-b9ptwPSB.d.ts.map → auth-secondary-storage-CcNkkEk0.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/browser-user.d.ts +14 -0
  20. package/dist/browser-user.d.ts.map +1 -0
  21. package/dist/browser-user.js +25 -0
  22. package/dist/browser-user.js.map +1 -0
  23. package/dist/cloudflare/auth-secondary-storage.d.ts +1 -1
  24. package/dist/cloudflare/auth-secondary-storage.js +1 -1
  25. package/dist/cloudflare/durable-object-client.js +2 -2
  26. package/dist/cloudflare/durable-object-errors.d.ts +1 -1
  27. package/dist/cloudflare/durable-object-errors.js +1 -1
  28. package/dist/cloudflare/kv-client.js +2 -2
  29. package/dist/cloudflare/kv-errors.d.ts +1 -1
  30. package/dist/cloudflare/kv-errors.js +1 -1
  31. package/dist/cloudflare/queue.d.ts +2 -2
  32. package/dist/cloudflare/queue.js +2 -2
  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-BiN6S_cm.js → core-DOBZeYSX.js} +2 -7
  45. package/dist/core-DOBZeYSX.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-DkMFXQnK.js → durable-object-errors-CcfTu0PQ.js} +2 -2
  49. package/dist/{durable-object-errors-DkMFXQnK.js.map → durable-object-errors-CcfTu0PQ.js.map} +1 -1
  50. package/dist/{floor-Cuw8EIhg.js → floor-BTBtPI9_.js} +2 -2
  51. package/dist/{floor-Cuw8EIhg.js.map → floor-BTBtPI9_.js.map} +1 -1
  52. package/dist/http.d.ts +2 -2
  53. package/dist/http.js +2 -2
  54. package/dist/{index-CbvNd665.d.ts → index-BMY7ylgk.d.ts} +25 -7
  55. package/dist/index-BMY7ylgk.d.ts.map +1 -0
  56. package/dist/{index-DUFS0SJ_.d.ts → index-CtIdbnEZ.d.ts} +17 -11
  57. package/dist/index-CtIdbnEZ.d.ts.map +1 -0
  58. package/dist/{kv-errors-BUTpFy0t.js → kv-errors-B2k_2lyY.js} +2 -2
  59. package/dist/{kv-errors-BUTpFy0t.js.map → kv-errors-B2k_2lyY.js.map} +1 -1
  60. package/dist/{metrics-DXhrc6ii.d.ts → metrics-CdTF_lWR.d.ts} +2 -2
  61. package/dist/{metrics-DXhrc6ii.d.ts.map → metrics-CdTF_lWR.d.ts.map} +1 -1
  62. package/dist/{outbox-repository-options-BNpCWTht.js → outbox-repository-options-Ca67c3c9.js} +2 -2
  63. package/dist/{outbox-repository-options-BNpCWTht.js.map → outbox-repository-options-Ca67c3c9.js.map} +1 -1
  64. package/dist/{outbox-repository-options-gk3JOjLB.d.ts → outbox-repository-options-q-CGUoCr.d.ts} +3 -3
  65. package/dist/{outbox-repository-options-gk3JOjLB.d.ts.map → outbox-repository-options-q-CGUoCr.d.ts.map} +1 -1
  66. package/dist/{payment-service.error-CqF7GkNp.js → payment-service.error-BR10zqxk.js} +2 -2
  67. package/dist/{payment-service.error-CqF7GkNp.js.map → payment-service.error-BR10zqxk.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 +6 -6
  72. package/dist/posthog/server.d.ts.map +1 -1
  73. package/dist/posthog/server.js +15 -13
  74. package/dist/posthog/server.js.map +1 -1
  75. package/dist/{r2-errors-rk7n7rvk.js → r2-errors-BF49eqU_.js} +2 -2
  76. package/dist/{r2-errors-rk7n7rvk.js.map → r2-errors-BF49eqU_.js.map} +1 -1
  77. package/dist/{request-4vJEWxyZ.js → request-BYQodKDU.js} +2 -2
  78. package/dist/{request-4vJEWxyZ.js.map → request-BYQodKDU.js.map} +1 -1
  79. package/dist/request-user-B4rh1c2-.js +19 -0
  80. package/dist/request-user-B4rh1c2-.js.map +1 -0
  81. package/dist/resend.d.ts +3 -3
  82. package/dist/resend.js +2 -2
  83. package/dist/sentry/client.d.ts +1 -1
  84. package/dist/sentry/client.js +1 -1
  85. package/dist/sentry/server.d.ts +6 -3
  86. package/dist/sentry/server.d.ts.map +1 -1
  87. package/dist/sentry/server.js +9 -1
  88. package/dist/sentry/server.js.map +1 -1
  89. package/dist/sentry/tanstack.d.ts +1 -1
  90. package/dist/stripe/payment-service.error.d.ts +1 -1
  91. package/dist/stripe/payment-service.error.js +1 -1
  92. package/dist/stripe/payment-service.js +1 -1
  93. package/dist/stripe/payment-webhook.d.ts +1 -1
  94. package/dist/stripe/payment-webhook.js +1 -1
  95. package/dist/stripe/request.js +1 -1
  96. package/dist/tanstack.d.ts +2 -2
  97. package/dist/tanstack.d.ts.map +1 -1
  98. package/dist/tanstack.js +4 -2
  99. package/dist/tanstack.js.map +1 -1
  100. package/dist/testing/outbox-repository.d.ts +2 -2
  101. package/dist/testing/payment-service.js +1 -1
  102. package/dist/{webhook-verification-lWso44-q.js → webhook-verification-C4R6OO7f.js} +2 -2
  103. package/dist/{webhook-verification-lWso44-q.js.map → webhook-verification-C4R6OO7f.js.map} +1 -1
  104. package/dist/{webhook-verification-D1c7BY4q.d.ts → webhook-verification-DL4L3zbu.d.ts} +2 -2
  105. package/dist/{webhook-verification-D1c7BY4q.d.ts.map → webhook-verification-DL4L3zbu.d.ts.map} +1 -1
  106. package/package.json +2 -1
  107. package/src/application/analytics-service.ts +35 -8
  108. package/src/application/index.ts +6 -1
  109. package/src/application/request-user.ts +18 -0
  110. package/src/core/analytics-event.ts +17 -13
  111. package/src/core/index.ts +1 -3
  112. package/src/infrastructure/observability/browser-user.ts +24 -0
  113. package/src/infrastructure/posthog/server.ts +28 -17
  114. package/src/infrastructure/sentry/server.ts +11 -1
  115. package/src/infrastructure/tanstack/auth.middleware.ts +3 -1
  116. package/dist/core-BiN6S_cm.js.map +0 -1
  117. package/dist/index-CbvNd665.d.ts.map +0 -1
  118. package/dist/index-DUFS0SJ_.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"outbox-repository-options-BNpCWTht.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 and delay defaults for both database adapters. */\nexport const OUTBOX_REPOSITORY_DEFAULTS = {\n leaseMs: 60_000,\n retryBaseDelayMs: 1_000,\n retryMaxDelayMs: 60_000,\n}\n\n/** Override lease and delay limits 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;CACxC,SAAS;CACT,kBAAkB;CAClB,iBAAiB;AACnB"}
1
+ {"version":3,"file":"outbox-repository-options-Ca67c3c9.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 and delay defaults for both database adapters. */\nexport const OUTBOX_REPOSITORY_DEFAULTS = {\n leaseMs: 60_000,\n retryBaseDelayMs: 1_000,\n retryMaxDelayMs: 60_000,\n}\n\n/** Override lease and delay limits 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;CACxC,SAAS;CACT,kBAAkB;CAClB,iBAAiB;AACnB"}
@@ -1,5 +1,5 @@
1
- import "./index-DUFS0SJ_.js";
2
- import { F as IEventCollector } from "./index-CbvNd665.js";
1
+ import "./index-CtIdbnEZ.js";
2
+ import { F as IEventCollector } from "./index-BMY7ylgk.js";
3
3
  import { BatchItem } from "drizzle-orm/batch";
4
4
  //#region src/infrastructure/drizzle-schema.d.ts
5
5
  /**
@@ -23,4 +23,4 @@ declare const OUTBOX_REPOSITORY_DEFAULTS: {
23
23
  type OutboxRepositoryOptions = Readonly<Partial<typeof OUTBOX_REPOSITORY_DEFAULTS>>;
24
24
  //#endregion
25
25
  export { eventCollector as n, DrizzleSchema as r, OutboxRepositoryOptions as t };
26
- //# sourceMappingURL=outbox-repository-options-gk3JOjLB.d.ts.map
26
+ //# sourceMappingURL=outbox-repository-options-q-CGUoCr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"outbox-repository-options-gk3JOjLB.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;EACA;EACA;;;KAIU,0BAA0B,SAAS,eAAe"}
1
+ {"version":3,"file":"outbox-repository-options-q-CGUoCr.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;EACA;EACA;;;KAIU,0BAA0B,SAAS,eAAe"}
@@ -1,4 +1,4 @@
1
- import { nt as AppError } from "./core-BiN6S_cm.js";
1
+ import { tt as AppError } from "./core-DOBZeYSX.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-CqF7GkNp.js.map
30
+ //# sourceMappingURL=payment-service.error-BR10zqxk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payment-service.error-CqF7GkNp.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-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,6 +1,6 @@
1
- import { W as DomainEvent, Xt as AppError, nt as DatabaseFailure, q as MessageId, tt as DatabaseError } from "./index-DUFS0SJ_.js";
2
- import { A as IOutboxRepository, M as OutboxClaim, N as OutboxMessage, P as IMessageStore, k as DeadLetterReason, w as ITransaction } from "./index-CbvNd665.js";
3
- import { n as eventCollector, r as DrizzleSchema, t as OutboxRepositoryOptions } from "./outbox-repository-options-gk3JOjLB.js";
1
+ import { Jt as AppError, W as DomainEvent, nt as DatabaseFailure, q as MessageId, tt as DatabaseError } from "./index-CtIdbnEZ.js";
2
+ import { A as IOutboxRepository, M as OutboxClaim, N as OutboxMessage, P as IMessageStore, k as DeadLetterReason, w as ITransaction } from "./index-BMY7ylgk.js";
3
+ import { n as eventCollector, r as DrizzleSchema, t as OutboxRepositoryOptions } from "./outbox-repository-options-q-CGUoCr.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, nt as AppError, s as exponentialDelayCapMs } from "./core-BiN6S_cm.js";
2
- import { o as MessageAlreadyProcessedError } from "./application-B5hnNUdI.js";
3
- import { i as runWithUnitOfWorkContext, r as eventCollector, t as OUTBOX_REPOSITORY_DEFAULTS } from "./outbox-repository-options-BNpCWTht.js";
1
+ import { O as DatabaseError, s as exponentialDelayCapMs, tt as AppError } from "./core-DOBZeYSX.js";
2
+ import { o as MessageAlreadyProcessedError } from "./application-Dsz-o9Aj.js";
3
+ import { i as runWithUnitOfWorkContext, r as eventCollector, t as OUTBOX_REPOSITORY_DEFAULTS } from "./outbox-repository-options-Ca67c3c9.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-DXhrc6ii.js";
1
+ import { t as PostHogMetricsService } from "../metrics-CdTF_lWR.js";
2
2
  export { PostHogMetricsService };
@@ -1,6 +1,6 @@
1
- import { Gt as AnalyticsEventIdentity, Kt as AnalyticsEventInput, qt as AnalyticsProperties } from "../index-DUFS0SJ_.js";
2
- import { $ as AnalyticsService } from "../index-CbvNd665.js";
3
- import { t as PostHogMetricsService } from "../metrics-DXhrc6ii.js";
1
+ import { Kt as AnalyticsTarget, Ut as AnalyticsEventInput, Wt as AnalyticsProperties } from "../index-CtIdbnEZ.js";
2
+ import { nt as AnalyticsService } from "../index-BMY7ylgk.js";
3
+ import { t as PostHogMetricsService } from "../metrics-CdTF_lWR.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. */
@@ -27,10 +27,10 @@ export declare class PostHogAnalyticsService implements AnalyticsService {
27
27
  identify(distinctId: string, properties?: AnalyticsProperties): void;
28
28
  /** Schedule an irreversible person merge; only alias IDs the application proves belong to one person. */
29
29
  alias(distinctId: string, previousDistinctId: string): void;
30
- /** Schedule an event; omit identity for SDK-generated UUID and capture time. */
31
- track(event: AnalyticsEventInput, distinctId: string, identity?: AnalyticsEventIdentity): void;
30
+ /** Schedule an event; without an event ID the SDK sets a new UUID and the capture time. */
31
+ track(name: string, properties: AnalyticsEventInput['properties'], target: AnalyticsTarget): void;
32
32
  /** Schedule an event without creating a person profile for an attempt or resource ID. */
33
- trackAnonymous(event: AnalyticsEventInput, distinctId: string, identity?: AnalyticsEventIdentity): void;
33
+ trackAnonymous(name: string, properties: AnalyticsEventInput['properties'], target: AnalyticsTarget): void;
34
34
  private capture;
35
35
  }
36
36
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/infrastructure/posthog/server.ts"],"mappings":";;;;;;iBAaiB;WACN;WACA;WACA;WACA,YAAY,SAAS;WACrB,UAAU,KACjB;aAGS,UAAU,KAAK,YAAY;;;;qBAK3B,mCAAmC;;WAMnC,SAAS;mBACD;;WALV,SAAS;UAEX;;SASA,OAAO,QAAQ,yBAAyB;;EAqB/C,SAAS,oBAAoB,aAAa;;EAO1C,MAAM,oBAAoB;;EAK1B,MAAM,OAAO,qBAAqB,oBAAoB,WAAW;;EAKjE,eACE,OAAO,qBACP,oBACA,WAAW;UAKL"}
1
+ {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/infrastructure/posthog/server.ts"],"mappings":";;;;;;iBAiBiB;WACN;WACA;WACA;WACA,YAAY,SAAS;WACrB,UAAU,KACjB;aAGS,UAAU,KAAK,YAAY;;;;qBAK3B,mCAAmC;;WAMnC,SAAS;mBACD;;WALV,SAAS;UAEX;;SASA,OAAO,QAAQ,yBAAyB;;EAqB/C,SAAS,oBAAoB,aAAa;;EAO1C,MAAM,oBAAoB;;EAK1B,MACE,cACA,YAAY,mCACZ,QAAQ;;EAMV,eACE,cACA,YAAY,mCACZ,QAAQ;UAKF"}
@@ -1,8 +1,10 @@
1
- import { tt as MissingConfigurationError } from "../core-BiN6S_cm.js";
1
+ import { et as MissingConfigurationError } from "../core-DOBZeYSX.js";
2
2
  import { t as PostHogMetricsService } from "../metrics-CWv37yf9.js";
3
+ import { v5, validate } from "uuid";
3
4
  import { PostHog } from "posthog-node";
4
5
 
5
6
  //#region src/infrastructure/posthog/server.ts
7
+ const EVENT_ID_NAMESPACE = "53d7af30-65cb-4176-b2c9-f1ed42367ab1";
6
8
  /** Worker analytics ported from Typist; disabled applications select Porte's NULL_ANALYTICS instead. */
7
9
  var PostHogAnalyticsService = class PostHogAnalyticsService {
8
10
  posthog;
@@ -49,28 +51,28 @@ var PostHogAnalyticsService = class PostHogAnalyticsService {
49
51
  alias: previousDistinctId
50
52
  }));
51
53
  }
52
- /** Schedule an event; omit identity for SDK-generated UUID and capture time. */
53
- track(event, distinctId, identity) {
54
- this.capture(event, distinctId, "person", identity);
54
+ /** Schedule an event; without an event ID the SDK sets a new UUID and the capture time. */
55
+ track(name, properties, target) {
56
+ this.capture(name, properties, target, "person");
55
57
  }
56
58
  /** Schedule an event without creating a person profile for an attempt or resource ID. */
57
- trackAnonymous(event, distinctId, identity) {
58
- this.capture(event, distinctId, "anonymous", identity);
59
+ trackAnonymous(name, properties, target) {
60
+ this.capture(name, properties, target, "anonymous");
59
61
  }
60
- capture(event, distinctId, profile, identity) {
61
- const properties = { ...event.properties };
62
+ capture(name, eventProperties, target, profile) {
63
+ const properties = { ...eventProperties };
62
64
  const payload = {
63
- distinctId,
64
- event: event.name,
65
+ distinctId: target.distinctId,
66
+ event: name,
65
67
  properties
66
68
  };
67
69
  if (profile === "anonymous") payload.properties = {
68
70
  ...properties,
69
71
  $process_person_profile: false
70
72
  };
71
- if (identity !== void 0) {
72
- payload.uuid = identity.uuid;
73
- payload.timestamp = identity.timestamp;
73
+ if (target.eventId !== void 0) {
74
+ payload.uuid = validate(target.eventId) ? target.eventId : v5(target.eventId, EVENT_ID_NAMESPACE);
75
+ payload.timestamp = new Date(target.occurredAt);
74
76
  }
75
77
  this.waitUntil(this.posthog.captureImmediate(payload));
76
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../../src/infrastructure/posthog/server.ts"],"sourcesContent":["import { PostHog, type PostHogOptions } from 'posthog-node'\n\nimport type { AnalyticsService } from '@/application'\nimport {\n MissingConfigurationError,\n type AnalyticsEventIdentity,\n type AnalyticsEventInput,\n type AnalyticsProperties,\n} from '@/core'\n\nimport { PostHogMetricsService } from './metrics.ts'\n\n/** Deployment values and SDK options; the runtime owns delivery promises. */\nexport interface PostHogAnalyticsConfig {\n readonly apiKey: string\n readonly environment: string\n readonly source: string\n readonly waitUntil: (promise: Promise<unknown>) => void\n readonly options?: Omit<\n PostHogOptions,\n 'waitUntil' | 'flushAt' | 'flushInterval' | 'metrics' | 'disabled'\n > & {\n readonly metrics?: Omit<NonNullable<PostHogOptions['metrics']>, 'serviceName' | 'environment'>\n }\n}\n\n/** Worker analytics ported from Typist; disabled applications select Porte's NULL_ANALYTICS instead. */\nexport class PostHogAnalyticsService implements AnalyticsService {\n /** Metrics share this service's SDK client and delivery lifetime. */\n readonly metrics: PostHogMetricsService\n\n private constructor(\n /** Raw SDK access for integrations such as PostHog AI tracing. */\n readonly posthog: PostHog,\n private readonly waitUntil: (promise: Promise<unknown>) => void,\n ) {\n this.metrics = new PostHogMetricsService(posthog, waitUntil)\n }\n\n /** Construct once per Worker invocation; a blank key throws MissingConfigurationError. */\n static create(config: PostHogAnalyticsConfig): PostHogAnalyticsService {\n const apiKey = config.apiKey.trim()\n if (apiKey.length === 0) throw new MissingConfigurationError('POSTHOG_API_KEY')\n const client = new PostHog(apiKey, {\n host: 'https://us.i.posthog.com',\n ...config.options,\n flushAt: 1,\n flushInterval: 0,\n waitUntil: config.waitUntil,\n metrics: {\n ...config.options?.metrics,\n environment: config.environment,\n serviceName: config.source,\n },\n })\n // The SDK applies in-memory super properties synchronously before this promise resolves.\n void client.register({ environment: config.environment, source: config.source })\n return new PostHogAnalyticsService(client, config.waitUntil)\n }\n\n /** Schedule person properties; the SDK's waitUntil option protects queued delivery. */\n identify(distinctId: string, properties?: AnalyticsProperties): void {\n const payload: Parameters<PostHog['identify']>[0] = { distinctId }\n if (properties !== undefined) payload.properties = properties\n this.posthog.identify(payload)\n }\n\n /** Schedule an irreversible person merge; only alias IDs the application proves belong to one person. */\n alias(distinctId: string, previousDistinctId: string): void {\n this.waitUntil(this.posthog.aliasImmediate({ distinctId, alias: previousDistinctId }))\n }\n\n /** Schedule an event; omit identity for SDK-generated UUID and capture time. */\n track(event: AnalyticsEventInput, distinctId: string, identity?: AnalyticsEventIdentity): void {\n this.capture(event, distinctId, 'person', identity)\n }\n\n /** Schedule an event without creating a person profile for an attempt or resource ID. */\n trackAnonymous(\n event: AnalyticsEventInput,\n distinctId: string,\n identity?: AnalyticsEventIdentity,\n ): void {\n this.capture(event, distinctId, 'anonymous', identity)\n }\n\n private capture(\n event: AnalyticsEventInput,\n distinctId: string,\n profile: 'person' | 'anonymous',\n identity?: AnalyticsEventIdentity,\n ): void {\n const properties = { ...event.properties }\n const payload: Parameters<PostHog['captureImmediate']>[0] = {\n distinctId,\n event: event.name,\n properties,\n }\n if (profile === 'anonymous')\n payload.properties = { ...properties, $process_person_profile: false }\n if (identity !== undefined) {\n payload.uuid = identity.uuid\n payload.timestamp = identity.timestamp\n }\n this.waitUntil(this.posthog.captureImmediate(payload))\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,0BAAb,MAAa,wBAAoD;CAMpD;CACQ;;CALnB,AAAS;CAET,AAAQ,YAEN,AAAS,SACT,AAAiB,WACjB;EAFS;EACQ;EAEjB,KAAK,UAAU,IAAI,sBAAsB,SAAS,SAAS;CAC7D;;CAGA,OAAO,OAAO,QAAyD;EACrE,MAAM,SAAS,OAAO,OAAO,KAAK;EAClC,IAAI,OAAO,WAAW,GAAG,MAAM,IAAI,0BAA0B,iBAAiB;EAC9E,MAAM,SAAS,IAAI,QAAQ,QAAQ;GACjC,MAAM;GACN,GAAG,OAAO;GACV,SAAS;GACT,eAAe;GACf,WAAW,OAAO;GAClB,SAAS;IACP,GAAG,OAAO,SAAS;IACnB,aAAa,OAAO;IACpB,aAAa,OAAO;GACtB;EACF,CAAC;EAED,AAAK,OAAO,SAAS;GAAE,aAAa,OAAO;GAAa,QAAQ,OAAO;EAAO,CAAC;EAC/E,OAAO,IAAI,wBAAwB,QAAQ,OAAO,SAAS;CAC7D;;CAGA,SAAS,YAAoB,YAAwC;EACnE,MAAM,UAA8C,EAAE,WAAW;EACjE,IAAI,eAAe,QAAW,QAAQ,aAAa;EACnD,KAAK,QAAQ,SAAS,OAAO;CAC/B;;CAGA,MAAM,YAAoB,oBAAkC;EAC1D,KAAK,UAAU,KAAK,QAAQ,eAAe;GAAE;GAAY,OAAO;EAAmB,CAAC,CAAC;CACvF;;CAGA,MAAM,OAA4B,YAAoB,UAAyC;EAC7F,KAAK,QAAQ,OAAO,YAAY,UAAU,QAAQ;CACpD;;CAGA,eACE,OACA,YACA,UACM;EACN,KAAK,QAAQ,OAAO,YAAY,aAAa,QAAQ;CACvD;CAEA,AAAQ,QACN,OACA,YACA,SACA,UACM;EACN,MAAM,aAAa,EAAE,GAAG,MAAM,WAAW;EACzC,MAAM,UAAsD;GAC1D;GACA,OAAO,MAAM;GACb;EACF;EACA,IAAI,YAAY,aACd,QAAQ,aAAa;GAAE,GAAG;GAAY,yBAAyB;EAAM;EACvE,IAAI,aAAa,QAAW;GAC1B,QAAQ,OAAO,SAAS;GACxB,QAAQ,YAAY,SAAS;EAC/B;EACA,KAAK,UAAU,KAAK,QAAQ,iBAAiB,OAAO,CAAC;CACvD;AACF"}
1
+ {"version":3,"file":"server.js","names":["isUuid","uuidv5"],"sources":["../../src/infrastructure/posthog/server.ts"],"sourcesContent":["import { PostHog, type PostHogOptions } from 'posthog-node'\nimport { validate as isUuid, v5 as uuidv5 } from 'uuid'\n\nimport type { AnalyticsService } from '@/application'\nimport {\n MissingConfigurationError,\n type AnalyticsEventInput,\n type AnalyticsProperties,\n type AnalyticsTarget,\n} from '@/core'\n\nimport { PostHogMetricsService } from './metrics.ts'\n\n// Fixed forever: changing it changes every derived UUID, so PostHog would keep a repeat.\nconst EVENT_ID_NAMESPACE = '53d7af30-65cb-4176-b2c9-f1ed42367ab1'\n\n/** Deployment values and SDK options; the runtime owns delivery promises. */\nexport interface PostHogAnalyticsConfig {\n readonly apiKey: string\n readonly environment: string\n readonly source: string\n readonly waitUntil: (promise: Promise<unknown>) => void\n readonly options?: Omit<\n PostHogOptions,\n 'waitUntil' | 'flushAt' | 'flushInterval' | 'metrics' | 'disabled'\n > & {\n readonly metrics?: Omit<NonNullable<PostHogOptions['metrics']>, 'serviceName' | 'environment'>\n }\n}\n\n/** Worker analytics ported from Typist; disabled applications select Porte's NULL_ANALYTICS instead. */\nexport class PostHogAnalyticsService implements AnalyticsService {\n /** Metrics share this service's SDK client and delivery lifetime. */\n readonly metrics: PostHogMetricsService\n\n private constructor(\n /** Raw SDK access for integrations such as PostHog AI tracing. */\n readonly posthog: PostHog,\n private readonly waitUntil: (promise: Promise<unknown>) => void,\n ) {\n this.metrics = new PostHogMetricsService(posthog, waitUntil)\n }\n\n /** Construct once per Worker invocation; a blank key throws MissingConfigurationError. */\n static create(config: PostHogAnalyticsConfig): PostHogAnalyticsService {\n const apiKey = config.apiKey.trim()\n if (apiKey.length === 0) throw new MissingConfigurationError('POSTHOG_API_KEY')\n const client = new PostHog(apiKey, {\n host: 'https://us.i.posthog.com',\n ...config.options,\n flushAt: 1,\n flushInterval: 0,\n waitUntil: config.waitUntil,\n metrics: {\n ...config.options?.metrics,\n environment: config.environment,\n serviceName: config.source,\n },\n })\n // The SDK applies in-memory super properties synchronously before this promise resolves.\n void client.register({ environment: config.environment, source: config.source })\n return new PostHogAnalyticsService(client, config.waitUntil)\n }\n\n /** Schedule person properties; the SDK's waitUntil option protects queued delivery. */\n identify(distinctId: string, properties?: AnalyticsProperties): void {\n const payload: Parameters<PostHog['identify']>[0] = { distinctId }\n if (properties !== undefined) payload.properties = properties\n this.posthog.identify(payload)\n }\n\n /** Schedule an irreversible person merge; only alias IDs the application proves belong to one person. */\n alias(distinctId: string, previousDistinctId: string): void {\n this.waitUntil(this.posthog.aliasImmediate({ distinctId, alias: previousDistinctId }))\n }\n\n /** Schedule an event; without an event ID the SDK sets a new UUID and the capture time. */\n track(\n name: string,\n properties: AnalyticsEventInput['properties'],\n target: AnalyticsTarget,\n ): void {\n this.capture(name, properties, target, 'person')\n }\n\n /** Schedule an event without creating a person profile for an attempt or resource ID. */\n trackAnonymous(\n name: string,\n properties: AnalyticsEventInput['properties'],\n target: AnalyticsTarget,\n ): void {\n this.capture(name, properties, target, 'anonymous')\n }\n\n private capture(\n name: string,\n eventProperties: AnalyticsEventInput['properties'],\n target: AnalyticsTarget,\n profile: 'person' | 'anonymous',\n ): void {\n const properties = { ...eventProperties }\n const payload: Parameters<PostHog['captureImmediate']>[0] = {\n distinctId: target.distinctId,\n event: name,\n properties,\n }\n if (profile === 'anonymous')\n payload.properties = { ...properties, $process_person_profile: false }\n if (target.eventId !== undefined) {\n // PostHog drops a repeat only when its uuid and timestamp match the first event.\n payload.uuid = isUuid(target.eventId)\n ? target.eventId\n : uuidv5(target.eventId, EVENT_ID_NAMESPACE)\n payload.timestamp = new Date(target.occurredAt)\n }\n this.waitUntil(this.posthog.captureImmediate(payload))\n }\n}\n"],"mappings":";;;;;;AAcA,MAAM,qBAAqB;;AAiB3B,IAAa,0BAAb,MAAa,wBAAoD;CAMpD;CACQ;;CALnB,AAAS;CAET,AAAQ,YAEN,AAAS,SACT,AAAiB,WACjB;EAFS;EACQ;EAEjB,KAAK,UAAU,IAAI,sBAAsB,SAAS,SAAS;CAC7D;;CAGA,OAAO,OAAO,QAAyD;EACrE,MAAM,SAAS,OAAO,OAAO,KAAK;EAClC,IAAI,OAAO,WAAW,GAAG,MAAM,IAAI,0BAA0B,iBAAiB;EAC9E,MAAM,SAAS,IAAI,QAAQ,QAAQ;GACjC,MAAM;GACN,GAAG,OAAO;GACV,SAAS;GACT,eAAe;GACf,WAAW,OAAO;GAClB,SAAS;IACP,GAAG,OAAO,SAAS;IACnB,aAAa,OAAO;IACpB,aAAa,OAAO;GACtB;EACF,CAAC;EAED,AAAK,OAAO,SAAS;GAAE,aAAa,OAAO;GAAa,QAAQ,OAAO;EAAO,CAAC;EAC/E,OAAO,IAAI,wBAAwB,QAAQ,OAAO,SAAS;CAC7D;;CAGA,SAAS,YAAoB,YAAwC;EACnE,MAAM,UAA8C,EAAE,WAAW;EACjE,IAAI,eAAe,QAAW,QAAQ,aAAa;EACnD,KAAK,QAAQ,SAAS,OAAO;CAC/B;;CAGA,MAAM,YAAoB,oBAAkC;EAC1D,KAAK,UAAU,KAAK,QAAQ,eAAe;GAAE;GAAY,OAAO;EAAmB,CAAC,CAAC;CACvF;;CAGA,MACE,MACA,YACA,QACM;EACN,KAAK,QAAQ,MAAM,YAAY,QAAQ,QAAQ;CACjD;;CAGA,eACE,MACA,YACA,QACM;EACN,KAAK,QAAQ,MAAM,YAAY,QAAQ,WAAW;CACpD;CAEA,AAAQ,QACN,MACA,iBACA,QACA,SACM;EACN,MAAM,aAAa,EAAE,GAAG,gBAAgB;EACxC,MAAM,UAAsD;GAC1D,YAAY,OAAO;GACnB,OAAO;GACP;EACF;EACA,IAAI,YAAY,aACd,QAAQ,aAAa;GAAE,GAAG;GAAY,yBAAyB;EAAM;EACvE,IAAI,OAAO,YAAY,QAAW;GAEhC,QAAQ,OAAOA,SAAO,OAAO,OAAO,IAChC,OAAO,UACPC,GAAO,OAAO,SAAS,kBAAkB;GAC7C,QAAQ,YAAY,IAAI,KAAK,OAAO,UAAU;EAChD;EACA,KAAK,UAAU,KAAK,QAAQ,iBAAiB,OAAO,CAAC;CACvD;AACF"}
@@ -1,4 +1,4 @@
1
- import { nt as AppError, u as classifyBoundaryError, v as isAbortError } from "./core-BiN6S_cm.js";
1
+ import { tt as AppError, u as classifyBoundaryError, v as isAbortError } from "./core-DOBZeYSX.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-rk7n7rvk.js.map
90
+ //# sourceMappingURL=r2-errors-BF49eqU_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"r2-errors-rk7n7rvk.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-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,4 +1,4 @@
1
- import { t as PaymentServiceError } from "./payment-service.error-CqF7GkNp.js";
1
+ import { t as PaymentServiceError } from "./payment-service.error-BR10zqxk.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-4vJEWxyZ.js.map
21
+ //# sourceMappingURL=request-BYQodKDU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-4vJEWxyZ.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-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"}
@@ -0,0 +1,19 @@
1
+ //#region src/application/request-user.ts
2
+ /**
3
+ * Process-wide request user hook.
4
+ * The Sentry server entry sets it once. Auth middleware calls it after a session resolves.
5
+ * The hook does not store a user id. The adapter writes the id on the current isolation scope.
6
+ */
7
+ let observabilityUserHook = null;
8
+ /** Set or clear the process-wide request user hook. */
9
+ function setObservabilityUserHook(hook) {
10
+ observabilityUserHook = hook;
11
+ }
12
+ /** Attribute the current execution to this user. No hook means the call does nothing. */
13
+ function applyObservabilityUser(user) {
14
+ observabilityUserHook?.(user);
15
+ }
16
+
17
+ //#endregion
18
+ export { setObservabilityUserHook as n, applyObservabilityUser as t };
19
+ //# sourceMappingURL=request-user-B4rh1c2-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-user-B4rh1c2-.js","names":[],"sources":["../src/application/request-user.ts"],"sourcesContent":["import type { ObservabilityUser } from './observability-service.ts'\n\n/**\n * Process-wide request user hook.\n * The Sentry server entry sets it once. Auth middleware calls it after a session resolves.\n * The hook does not store a user id. The adapter writes the id on the current isolation scope.\n */\nlet observabilityUserHook: ((user: ObservabilityUser) => void) | null = null\n\n/** Set or clear the process-wide request user hook. */\nexport function setObservabilityUserHook(hook: ((user: ObservabilityUser) => void) | null): void {\n observabilityUserHook = hook\n}\n\n/** Attribute the current execution to this user. No hook means the call does nothing. */\nexport function applyObservabilityUser(user: ObservabilityUser): void {\n observabilityUserHook?.(user)\n}\n"],"mappings":";;;;;;AAOA,IAAI,wBAAoE;;AAGxE,SAAgB,yBAAyB,MAAwD;CAC/F,wBAAwB;AAC1B;;AAGA,SAAgB,uBAAuB,MAA+B;CACpE,wBAAwB,IAAI;AAC9B"}
package/dist/resend.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { jt as BounceType } from "./index-DUFS0SJ_.js";
2
- import { B as OutboundEmail, H as ReceivedContent, I as EmailAccepted, R as IEmailService, U as ReceivedEmail } from "./index-CbvNd665.js";
3
- import { n as WebhookVerifier } from "./webhook-verification-D1c7BY4q.js";
1
+ import { jt as BounceType } from "./index-CtIdbnEZ.js";
2
+ import { B as OutboundEmail, H as ReceivedContent, I as EmailAccepted, R as IEmailService, U as ReceivedEmail } from "./index-BMY7ylgk.js";
3
+ import { n as WebhookVerifier } from "./webhook-verification-DL4L3zbu.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-BiN6S_cm.js";
2
- import { t as WebhookVerificationError } from "./webhook-verification-lWso44-q.js";
1
+ import { $ as EmailAddressSchema, J as parseBounceType, X as EmailServiceError } from "./core-DOBZeYSX.js";
2
+ import { t as WebhookVerificationError } from "./webhook-verification-C4R6OO7f.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-DUFS0SJ_.js";
1
+ import { u as LoggerErrorHook } from "../index-CtIdbnEZ.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-BiN6S_cm.js";
1
+ import { a as setLoggerErrorHook } from "../core-DOBZeYSX.js";
2
2
  import * as Sentry from "@sentry/tanstackstart-react";
3
3
  import { isNotFound, isRedirect } from "@tanstack/react-router";
4
4
 
@@ -1,5 +1,5 @@
1
- import { u as LoggerErrorHook } from "../index-DUFS0SJ_.js";
2
- import { G as ObservabilityScope, K as ObservabilityService, q as ObservabilityUser } from "../index-CbvNd665.js";
1
+ import { u as LoggerErrorHook } from "../index-CtIdbnEZ.js";
2
+ import { J as ObservabilityService, Y as ObservabilityUser, q as ObservabilityScope } from "../index-BMY7ylgk.js";
3
3
  import * as Sentry from "@sentry/cloudflare";
4
4
  //#region src/infrastructure/sentry/server.d.ts
5
5
  /** Application-owned deployment settings with the full Cloudflare SDK option contract. */
@@ -8,7 +8,10 @@ export type SentryServerOptions = Sentry.CloudflareOptions & {
8
8
  readonly environment: string;
9
9
  readonly enabled: boolean;
10
10
  };
11
- /** Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults. */
11
+ /**
12
+ * Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults.
13
+ * Registers the request user hook so auth middleware can set `{ id }` on the current isolation scope.
14
+ */
12
15
  export declare function createSentryOptions(options: SentryServerOptions): Sentry.CloudflareOptions;
13
16
  /** Register with setLoggerErrorHook once at startup; an explicit user applies only to this report. */
14
17
  export declare function createSentryLoggerErrorHook(): LoggerErrorHook;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/infrastructure/sentry/server.ts"],"mappings":";;;;;YAMY,sBAAsB,OAAO;WAC9B;WACA;WACA;;;wBAIK,oBAAoB,SAAS,sBAAsB,OAAO;;wBAK1D,+BAA+B;;qBAWlC,sCAAsC;;EAEjD,QAAQ,MAAM;;EAKR,mBAAmB,GAAG,WAAW,OAAO,uBAAuB,IAAI,QAAQ,KAAK,QAAQ"}
1
+ {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/infrastructure/sentry/server.ts"],"mappings":";;;;;YAQY,sBAAsB,OAAO;WAC9B;WACA;WACA;;;;;;wBAOK,oBAAoB,SAAS,sBAAsB,OAAO;;wBAU1D,+BAA+B;;qBAWlC,sCAAsC;;EAEjD,QAAQ,MAAM;;EAKR,mBAAmB,GAAG,WAAW,OAAO,uBAAuB,IAAI,QAAQ,KAAK,QAAQ"}
@@ -1,8 +1,16 @@
1
+ import { n as setObservabilityUserHook } from "../request-user-B4rh1c2-.js";
1
2
  import * as Sentry from "@sentry/cloudflare";
2
3
 
3
4
  //#region src/infrastructure/sentry/server.ts
4
- /** Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults. */
5
+ /**
6
+ * Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults.
7
+ * Registers the request user hook so auth middleware can set `{ id }` on the current isolation scope.
8
+ */
5
9
  function createSentryOptions(options) {
10
+ setObservabilityUserHook((user) => {
11
+ if (!Sentry.isEnabled()) return;
12
+ Sentry.setUser({ id: user.id });
13
+ });
6
14
  return options;
7
15
  }
8
16
  /** Register with setLoggerErrorHook once at startup; an explicit user applies only to this report. */
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../../src/infrastructure/sentry/server.ts"],"sourcesContent":["import * as Sentry from '@sentry/cloudflare'\n\nimport type { ObservabilityScope, ObservabilityService, ObservabilityUser } from '@/application'\nimport type { LoggerErrorHook } from '@/core'\n\n/** Application-owned deployment settings with the full Cloudflare SDK option contract. */\nexport type SentryServerOptions = Sentry.CloudflareOptions & {\n readonly dsn: string\n readonly environment: string\n readonly enabled: boolean\n}\n\n/** Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults. */\nexport function createSentryOptions(options: SentryServerOptions): Sentry.CloudflareOptions {\n return options\n}\n\n/** Register with setLoggerErrorHook once at startup; an explicit user applies only to this report. */\nexport function createSentryLoggerErrorHook(): LoggerErrorHook {\n return ({ error, userId, attributes }) => {\n if (userId !== undefined) {\n Sentry.captureException(error, { extra: attributes, user: { id: userId } })\n return\n }\n Sentry.captureException(error, { extra: attributes })\n }\n}\n\n/** Identity and scope adapter from Typist and Porte; call inside Sentry's instrumented runtime. */\nexport class SentryObservabilityService implements ObservabilityService {\n /** Attribute subsequent reports in the current isolation scope. */\n setUser(user: ObservabilityUser): void {\n Sentry.setUser({ id: user.id })\n }\n\n /** Await work in a separate scope for each queue message or concurrent operation. */\n async withIsolationScope<T>(callback: (scope: ObservabilityScope) => T | Promise<T>): Promise<T> {\n return await Sentry.withIsolationScope((scope) =>\n callback({ setUser: (user) => scope.setUser({ id: user.id }) }),\n )\n }\n}\n\nexport { Sentry }\n"],"mappings":";;;;AAaA,SAAgB,oBAAoB,SAAwD;CAC1F,OAAO;AACT;;AAGA,SAAgB,8BAA+C;CAC7D,QAAQ,EAAE,OAAO,QAAQ,iBAAiB;EACxC,IAAI,WAAW,QAAW;GACxB,OAAO,iBAAiB,OAAO;IAAE,OAAO;IAAY,MAAM,EAAE,IAAI,OAAO;GAAE,CAAC;GAC1E;EACF;EACA,OAAO,iBAAiB,OAAO,EAAE,OAAO,WAAW,CAAC;CACtD;AACF;;AAGA,IAAa,6BAAb,MAAwE;;CAEtE,QAAQ,MAA+B;EACrC,OAAO,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC;CAChC;;CAGA,MAAM,mBAAsB,UAAqE;EAC/F,OAAO,MAAM,OAAO,oBAAoB,UACtC,SAAS,EAAE,UAAU,SAAS,MAAM,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,CAChE;CACF;AACF"}
1
+ {"version":3,"file":"server.js","names":[],"sources":["../../src/infrastructure/sentry/server.ts"],"sourcesContent":["import * as Sentry from '@sentry/cloudflare'\n\nimport type { ObservabilityScope, ObservabilityService, ObservabilityUser } from '@/application'\nimport type { LoggerErrorHook } from '@/core'\n\nimport { setObservabilityUserHook } from '../../application/request-user.ts'\n\n/** Application-owned deployment settings with the full Cloudflare SDK option contract. */\nexport type SentryServerOptions = Sentry.CloudflareOptions & {\n readonly dsn: string\n readonly environment: string\n readonly enabled: boolean\n}\n\n/**\n * Pass application options to Workers, Durable Objects, and Workflows with the SDK defaults.\n * Registers the request user hook so auth middleware can set `{ id }` on the current isolation scope.\n */\nexport function createSentryOptions(options: SentryServerOptions): Sentry.CloudflareOptions {\n // Auth middleware cannot import this SDK. The hook writes `{ id }` only when Sentry is enabled.\n setObservabilityUserHook((user) => {\n if (!Sentry.isEnabled()) return\n Sentry.setUser({ id: user.id })\n })\n return options\n}\n\n/** Register with setLoggerErrorHook once at startup; an explicit user applies only to this report. */\nexport function createSentryLoggerErrorHook(): LoggerErrorHook {\n return ({ error, userId, attributes }) => {\n if (userId !== undefined) {\n Sentry.captureException(error, { extra: attributes, user: { id: userId } })\n return\n }\n Sentry.captureException(error, { extra: attributes })\n }\n}\n\n/** Identity and scope adapter from Typist and Porte; call inside Sentry's instrumented runtime. */\nexport class SentryObservabilityService implements ObservabilityService {\n /** Attribute subsequent reports in the current isolation scope. */\n setUser(user: ObservabilityUser): void {\n Sentry.setUser({ id: user.id })\n }\n\n /** Await work in a separate scope for each queue message or concurrent operation. */\n async withIsolationScope<T>(callback: (scope: ObservabilityScope) => T | Promise<T>): Promise<T> {\n return await Sentry.withIsolationScope((scope) =>\n callback({ setUser: (user) => scope.setUser({ id: user.id }) }),\n )\n }\n}\n\nexport { Sentry }\n"],"mappings":";;;;;;;;AAkBA,SAAgB,oBAAoB,SAAwD;CAE1F,0BAA0B,SAAS;EACjC,IAAI,CAAC,OAAO,UAAU,GAAG;EACzB,OAAO,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC;CAChC,CAAC;CACD,OAAO;AACT;;AAGA,SAAgB,8BAA+C;CAC7D,QAAQ,EAAE,OAAO,QAAQ,iBAAiB;EACxC,IAAI,WAAW,QAAW;GACxB,OAAO,iBAAiB,OAAO;IAAE,OAAO;IAAY,MAAM,EAAE,IAAI,OAAO;GAAE,CAAC;GAC1E;EACF;EACA,OAAO,iBAAiB,OAAO,EAAE,OAAO,WAAW,CAAC;CACtD;AACF;;AAGA,IAAa,6BAAb,MAAwE;;CAEtE,QAAQ,MAA+B;EACrC,OAAO,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC;CAChC;;CAGA,MAAM,mBAAsB,UAAqE;EAC/F,OAAO,MAAM,OAAO,oBAAoB,UACtC,SAAS,EAAE,UAAU,SAAS,MAAM,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,CAChE;CACF;AACF"}
@@ -1,4 +1,4 @@
1
- import { ot as ErrorTable } from "../index-DUFS0SJ_.js";
1
+ import { ot as ErrorTable } from "../index-CtIdbnEZ.js";
2
2
  import { ErrorEvent, EventHint } from "@sentry/cloudflare";
3
3
  //#region src/infrastructure/sentry/tanstack.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { Xt as AppError, Zt as FailureClassification } from "../index-DUFS0SJ_.js";
1
+ import { Jt as AppError, Yt as FailureClassification } from "../index-CtIdbnEZ.js";
2
2
  import Stripe from "stripe";
3
3
  //#region src/infrastructure/stripe/payment-service.error.d.ts
4
4
  /** A final Stripe request failure. The caller logs once; native details remain in cause. */
@@ -1,3 +1,3 @@
1
- import { t as PaymentServiceError } from "../payment-service.error-CqF7GkNp.js";
1
+ import { t as PaymentServiceError } from "../payment-service.error-BR10zqxk.js";
2
2
 
3
3
  export { PaymentServiceError };
@@ -1,4 +1,4 @@
1
- import { t as stripeRequest } from "../request-4vJEWxyZ.js";
1
+ import { t as stripeRequest } from "../request-BYQodKDU.js";
2
2
 
3
3
  //#region src/infrastructure/stripe/payment-service.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { n as WebhookVerifier } from "../webhook-verification-D1c7BY4q.js";
1
+ import { n as WebhookVerifier } from "../webhook-verification-DL4L3zbu.js";
2
2
  import Stripe from "stripe";
3
3
  //#region src/infrastructure/stripe/payment-webhook.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as WebhookVerificationError } from "../webhook-verification-lWso44-q.js";
1
+ import { t as WebhookVerificationError } from "../webhook-verification-C4R6OO7f.js";
2
2
  import Stripe from "stripe";
3
3
 
4
4
  //#region src/infrastructure/stripe/payment-webhook.ts
@@ -1,3 +1,3 @@
1
- import { t as stripeRequest } from "../request-4vJEWxyZ.js";
1
+ import { t as stripeRequest } from "../request-BYQodKDU.js";
2
2
 
3
3
  export { stripeRequest };
@@ -1,4 +1,4 @@
1
- import { ot as ErrorTable } from "./index-DUFS0SJ_.js";
1
+ import { ot as ErrorTable } from "./index-CtIdbnEZ.js";
2
2
  import { Register } from "@tanstack/react-start";
3
3
  import { BetterAuthCookies } from "better-auth";
4
4
  //#region src/infrastructure/tanstack/request-context.d.ts
@@ -55,7 +55,7 @@ type AuthMiddlewareOptions<Session extends AuthSession> = {
55
55
  /**
56
56
  * Preserve Porte's function and request middleware contracts with application-owned services.
57
57
  * Optional lookup failures log once and continue as guests. Required lookup failures propagate.
58
- * `onAuthenticated` runs after a session resolves and before the rest of the chain.
58
+ * A resolved session applies `{ id }` on the observability hook, then runs `onAuthenticated`, before the handler.
59
59
  */
60
60
  export declare function createAuthMiddleware<Session extends AuthSession>(options: AuthMiddlewareOptions<Session>): {
61
61
  extractAuth: import("@tanstack/react-start").FunctionMiddlewareAfterServer<{}, unknown, undefined, AuthContext<Session>, undefined, undefined, undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"tanstack.d.ts","names":[],"sources":["../src/infrastructure/tanstack/request-context.ts","../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/error.middleware.ts","../src/infrastructure/tanstack/function-tracing.middleware.ts"],"mappings":";;;;;;;;;;KAQY,iBAAiB;EAAmB;IAAU,sBAAsB;;IAC5E;;;;KCCQ;WACD;aAAiB;;WACjB;aAAoB;;;;KAInB,oBAAoB,gBAAgB;WACrC,MAAM;WACN,SAAS;;;KAIR,YAAY,gBAAgB,eACpC,oBAAoB;WAET;WACA;;;KAIH,qBAAqB,gBAAgB;WACtC,MAAM;WACN,SAAS;WACT,gBAAgB;;;KAIf,sBAAsB,gBAAgB;WACvC,UAAU,SAAS;aACjB;eACE,aAAa;QAAW,SAAS;YAAc,QAAQ;;;;WAI3D,mBAAmB,SAAS,qBAAqB;;;;;;;wBAc5C,qBAAqB,gBAAgB,aACnD,SAAS,sBAAsB;;;;;;;;KC/CrB;WACD,UAAU;aAAmB,aAAa;;;;KAIzC,uBAAuB;WACxB,QAAQ,WAAW;;WAEnB;;WAEA,UAAU,SAAS,mBAAmB;;;;;;wBAOjC,sBAAsB,SAAS,SAAS,uBAAuB;;;;;;;;;;;;;;;;;;;;;wBCnB/D,gCAAgC,aAAa,SAAS,mBAAmB,0CAAO"}
1
+ {"version":3,"file":"tanstack.d.ts","names":[],"sources":["../src/infrastructure/tanstack/request-context.ts","../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/error.middleware.ts","../src/infrastructure/tanstack/function-tracing.middleware.ts"],"mappings":";;;;;;;;;;KAQY,iBAAiB;EAAmB;IAAU,sBAAsB;;IAC5E;;;;KCEQ;WACD;aAAiB;;WACjB;aAAoB;;;;KAInB,oBAAoB,gBAAgB;WACrC,MAAM;WACN,SAAS;;;KAIR,YAAY,gBAAgB,eACpC,oBAAoB;WAET;WACA;;;KAIH,qBAAqB,gBAAgB;WACtC,MAAM;WACN,SAAS;WACT,gBAAgB;;;KAIf,sBAAsB,gBAAgB;WACvC,UAAU,SAAS;aACjB;eACE,aAAa;QAAW,SAAS;YAAc,QAAQ;;;;WAI3D,mBAAmB,SAAS,qBAAqB;;;;;;;wBAc5C,qBAAqB,gBAAgB,aACnD,SAAS,sBAAsB;;;;;;;;KChDrB;WACD,UAAU;aAAmB,aAAa;;;;KAIzC,uBAAuB;WACxB,QAAQ,WAAW;;WAEnB;;WAEA,UAAU,SAAS,mBAAmB;;;;;;wBAOjC,sBAAsB,SAAS,SAAS,uBAAuB;;;;;;;;;;;;;;;;;;;;;wBCnB/D,gCAAgC,aAAa,SAAS,mBAAmB,0CAAO"}
package/dist/tanstack.js CHANGED
@@ -1,4 +1,5 @@
1
- import { H as StaleSessionError, R as ValidationError, W as AuthenticationError, nt as AppError, r as createLogger } from "./core-BiN6S_cm.js";
1
+ import { H as StaleSessionError, R as ValidationError, W as AuthenticationError, r as createLogger, tt as AppError } from "./core-DOBZeYSX.js";
2
+ import { t as applyObservabilityUser } from "./request-user-B4rh1c2-.js";
2
3
  import { n as withSpan } from "./tracing-C_7B_odV.js";
3
4
  import { z } from "zod";
4
5
  import { getReasonPhrase } from "http-status-codes";
@@ -15,10 +16,11 @@ const requestHeaders = async () => {
15
16
  /**
16
17
  * Preserve Porte's function and request middleware contracts with application-owned services.
17
18
  * Optional lookup failures log once and continue as guests. Required lookup failures propagate.
18
- * `onAuthenticated` runs after a session resolves and before the rest of the chain.
19
+ * A resolved session applies `{ id }` on the observability hook, then runs `onAuthenticated`, before the handler.
19
20
  */
20
21
  function createAuthMiddleware(options) {
21
22
  function notifyAuthenticated(requestContext, resolved) {
23
+ applyObservabilityUser({ id: resolved.user.id });
22
24
  options.onAuthenticated?.({
23
25
  user: resolved.user,
24
26
  session: resolved.session,