@lunora/payment 1.0.0-alpha.65 → 1.0.0-alpha.67

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 (38) hide show
  1. package/dist/index.d.mts +20 -4
  2. package/dist/index.d.ts +20 -4
  3. package/dist/index.mjs +1 -1
  4. package/dist/packem_shared/LunoraPaymentError-C8uAUIzQ.mjs +1 -0
  5. package/dist/packem_shared/MemoryPaymentStore-CkXqJEe2.mjs +1 -0
  6. package/dist/packem_shared/{adapter.d-CMjjkTGB.d.mts → adapter.d-xBfAhqVC.d.mts} +22 -4
  7. package/dist/packem_shared/{adapter.d-CMjjkTGB.d.ts → adapter.d-xBfAhqVC.d.ts} +22 -4
  8. package/dist/packem_shared/{addMoney-JN0UrVXA.mjs → addMoney-BKfsSf0H.mjs} +1 -1
  9. package/dist/packem_shared/{applyWebhookAction-6JwJo2XL.mjs → applyWebhookAction-Bwvycl00.mjs} +1 -1
  10. package/dist/packem_shared/{constantTimeEqual-DG_4PS78.mjs → constantTimeEqual-B4DP75aY.mjs} +1 -1
  11. package/dist/packem_shared/{createAdapterRegistry-CafjyQwx.mjs → createAdapterRegistry-SoXdsiQd.mjs} +1 -1
  12. package/dist/packem_shared/createDatabasePaymentStore-DxChfP5X.mjs +1 -0
  13. package/dist/packem_shared/createPayment-Cj0tRPRZ.mjs +1 -0
  14. package/dist/packem_shared/{lunoraDatabaseToPaymentDatabase-Bn3aBIoh.mjs → lunoraDatabaseToPaymentDatabase-CW1VjW4D.mjs} +1 -1
  15. package/dist/packem_shared/not-supported-BBbwyP_u.mjs +1 -0
  16. package/dist/packem_shared/{paymentTables-BMtUrXkM.mjs → paymentTables-Be-_11ux.mjs} +1 -1
  17. package/dist/packem_shared/{reconcile-y9d1yiVb.mjs → reconcile-BjWV0mB0.mjs} +1 -1
  18. package/dist/providers/autumn.d.mts +1 -1
  19. package/dist/providers/autumn.d.ts +1 -1
  20. package/dist/providers/autumn.mjs +1 -1
  21. package/dist/providers/creem.d.mts +1 -1
  22. package/dist/providers/creem.d.ts +1 -1
  23. package/dist/providers/creem.mjs +1 -1
  24. package/dist/providers/dodopayments.d.mts +1 -1
  25. package/dist/providers/dodopayments.d.ts +1 -1
  26. package/dist/providers/dodopayments.mjs +1 -1
  27. package/dist/providers/polar.d.mts +1 -1
  28. package/dist/providers/polar.d.ts +1 -1
  29. package/dist/providers/polar.mjs +1 -1
  30. package/dist/providers/stripe.d.mts +1 -1
  31. package/dist/providers/stripe.d.ts +1 -1
  32. package/dist/providers/stripe.mjs +1 -1
  33. package/package.json +2 -2
  34. package/dist/packem_shared/LunoraPaymentError-35kSImFc.mjs +0 -1
  35. package/dist/packem_shared/MemoryPaymentStore-BICI1RdZ.mjs +0 -1
  36. package/dist/packem_shared/createDatabasePaymentStore-4l41pJ0l.mjs +0 -1
  37. package/dist/packem_shared/createPayment-BW6jnMP_.mjs +0 -1
  38. package/dist/packem_shared/not-supported-Cqa8vy-R.mjs +0 -1
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as ProviderId, C as Customer, b as PaymentSession, S as Subscription, U as UsageEvent, W as WebhookActionType, A as ApplyResult, P as PaymentAdapter, c as AttachInput, d as CheckoutResult, e as CancelSubscriptionOptions, f as CheckInput, g as CheckResult, h as CheckoutInput, F as FeatureBalance, T as TrackInput, i as TrackResult, j as CurrencyCode, M as Money, k as PaymentState, l as SubscriptionState, m as WebhookAction } from "./packem_shared/adapter.d-CMjjkTGB.mjs";
2
- export { type n as AdapterRegistry, type o as CaptureInput, type p as CustomerRef, type q as PortalInput, type r as ProviderCapabilities, type R as RefundAmountKind, type s as RefundInput, type t as ReportUsageInput, type u as SubscriptionPatch, type v as WebhookHeaders, type w as WebhookInput, x as createAdapterRegistry } from "./packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { a as ProviderId, C as Customer, b as PaymentSession, S as Subscription, U as UsageEvent, W as WebhookActionType, A as ApplyResult, P as PaymentAdapter, c as AttachInput, d as CheckoutResult, e as CancelSubscriptionOptions, f as CheckInput, g as CheckResult, h as CheckoutInput, F as FeatureBalance, T as TrackInput, i as TrackResult, j as CurrencyCode, M as Money, k as PaymentState, l as SubscriptionState, m as WebhookAction } from "./packem_shared/adapter.d-xBfAhqVC.mjs";
2
+ export { type n as AdapterRegistry, type o as CaptureInput, type p as CustomerRef, type q as PortalInput, type r as ProviderCapabilities, type R as RefundAmountKind, type s as RefundInput, type t as ReportUsageInput, type u as SubscriptionPatch, type v as WebhookHeaders, type w as WebhookInput, x as createAdapterRegistry } from "./packem_shared/adapter.d-xBfAhqVC.mjs";
3
3
  import { LunoraError } from '@lunora/errors';
4
4
  import { TableDefinition } from '@lunora/server';
5
5
  /**
@@ -31,7 +31,23 @@ interface PaymentStore {
31
31
  * is rolled back on failure. A no-op if the id was never claimed.
32
32
  */
33
33
  releaseEvent: (provider: ProviderId, eventId: string) => Promise<void>;
34
- /** Sum recorded usage `quantity` for a `(referenceId, featureId)` pair since `since` (epoch ms). */
34
+ /**
35
+ * The period total for a `(referenceId, featureId)` pair since `since` (epoch ms).
36
+ *
37
+ * NOT a plain sum: events are folded in `createdAt` order (ties broken by
38
+ * `idempotencyKey`, so every store agrees on the same order for events stamped
39
+ * in the same millisecond). An `"add"` event increments the running total; a
40
+ * `"set"` event RESETS it to that event's `quantity`, discarding everything
41
+ * earlier in the period. Use {@link foldUsage} so the two implementations
42
+ * cannot drift.
43
+ *
44
+ * This fold is what lets `track({ mode: "set" })` be append-only. Reconciling by
45
+ * writing `target - current` instead would be a read-modify-write across two
46
+ * un-transacted store calls: two interleaved `set`s would both read the same
47
+ * total, both append a delta, and leave the period over- or under-counted —
48
+ * inflating `balance = limit - used`. Here a concurrent pair simply resolves
49
+ * last-writer-wins, and a replayed `set` is idempotent by construction.
50
+ */
35
51
  sumUsage: (referenceId: string, featureId: string, since: number) => Promise<number>;
36
52
  upsertCustomer: (customer: Customer) => Promise<void>;
37
53
  upsertPaymentSession: (session: PaymentSession) => Promise<void>;
@@ -313,7 +329,7 @@ declare const paymentsFromContext: (context: PaymentContextLike, options: Paymen
313
329
  * `PaymentErrorCode` is part of the experimental `@lunora/payment` API and may change without a major version bump.
314
330
  * @experimental
315
331
  */
316
- type PaymentErrorCode = "CONFIG_INVALID" | "CURRENCY_MISMATCH" | "FORBIDDEN" | "INVALID_TRANSITION" | "NOT_FOUND" | "PROVIDER_ERROR" | "WEBHOOK_EVENT_ID_MISSING" | "WEBHOOK_SIGNATURE_INVALID" | "WEBHOOK_TIMESTAMP_INVALID";
332
+ type PaymentErrorCode = "CONFIG_INVALID" | "CURRENCY_MISMATCH" | "FORBIDDEN" | "INVALID_TRANSITION" | "NOT_FOUND" | "PROVIDER_ERROR" | "VALIDATION_ERROR" | "WEBHOOK_EVENT_ID_MISSING" | "WEBHOOK_SIGNATURE_INVALID" | "WEBHOOK_TIMESTAMP_INVALID";
317
333
  /**
318
334
  * Typed error for all `@lunora/payment` failures. A `LunoraError` subclass; `status` maps onto an HTTP response.
319
335
  * @experimental
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as ProviderId, C as Customer, b as PaymentSession, S as Subscription, U as UsageEvent, W as WebhookActionType, A as ApplyResult, P as PaymentAdapter, c as AttachInput, d as CheckoutResult, e as CancelSubscriptionOptions, f as CheckInput, g as CheckResult, h as CheckoutInput, F as FeatureBalance, T as TrackInput, i as TrackResult, j as CurrencyCode, M as Money, k as PaymentState, l as SubscriptionState, m as WebhookAction } from "./packem_shared/adapter.d-CMjjkTGB.js";
2
- export { type n as AdapterRegistry, type o as CaptureInput, type p as CustomerRef, type q as PortalInput, type r as ProviderCapabilities, type R as RefundAmountKind, type s as RefundInput, type t as ReportUsageInput, type u as SubscriptionPatch, type v as WebhookHeaders, type w as WebhookInput, x as createAdapterRegistry } from "./packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { a as ProviderId, C as Customer, b as PaymentSession, S as Subscription, U as UsageEvent, W as WebhookActionType, A as ApplyResult, P as PaymentAdapter, c as AttachInput, d as CheckoutResult, e as CancelSubscriptionOptions, f as CheckInput, g as CheckResult, h as CheckoutInput, F as FeatureBalance, T as TrackInput, i as TrackResult, j as CurrencyCode, M as Money, k as PaymentState, l as SubscriptionState, m as WebhookAction } from "./packem_shared/adapter.d-xBfAhqVC.js";
2
+ export { type n as AdapterRegistry, type o as CaptureInput, type p as CustomerRef, type q as PortalInput, type r as ProviderCapabilities, type R as RefundAmountKind, type s as RefundInput, type t as ReportUsageInput, type u as SubscriptionPatch, type v as WebhookHeaders, type w as WebhookInput, x as createAdapterRegistry } from "./packem_shared/adapter.d-xBfAhqVC.js";
3
3
  import { LunoraError } from '@lunora/errors';
4
4
  import { TableDefinition } from '@lunora/server';
5
5
  /**
@@ -31,7 +31,23 @@ interface PaymentStore {
31
31
  * is rolled back on failure. A no-op if the id was never claimed.
32
32
  */
33
33
  releaseEvent: (provider: ProviderId, eventId: string) => Promise<void>;
34
- /** Sum recorded usage `quantity` for a `(referenceId, featureId)` pair since `since` (epoch ms). */
34
+ /**
35
+ * The period total for a `(referenceId, featureId)` pair since `since` (epoch ms).
36
+ *
37
+ * NOT a plain sum: events are folded in `createdAt` order (ties broken by
38
+ * `idempotencyKey`, so every store agrees on the same order for events stamped
39
+ * in the same millisecond). An `"add"` event increments the running total; a
40
+ * `"set"` event RESETS it to that event's `quantity`, discarding everything
41
+ * earlier in the period. Use {@link foldUsage} so the two implementations
42
+ * cannot drift.
43
+ *
44
+ * This fold is what lets `track({ mode: "set" })` be append-only. Reconciling by
45
+ * writing `target - current` instead would be a read-modify-write across two
46
+ * un-transacted store calls: two interleaved `set`s would both read the same
47
+ * total, both append a delta, and leave the period over- or under-counted —
48
+ * inflating `balance = limit - used`. Here a concurrent pair simply resolves
49
+ * last-writer-wins, and a replayed `set` is idempotent by construction.
50
+ */
35
51
  sumUsage: (referenceId: string, featureId: string, since: number) => Promise<number>;
36
52
  upsertCustomer: (customer: Customer) => Promise<void>;
37
53
  upsertPaymentSession: (session: PaymentSession) => Promise<void>;
@@ -313,7 +329,7 @@ declare const paymentsFromContext: (context: PaymentContextLike, options: Paymen
313
329
  * `PaymentErrorCode` is part of the experimental `@lunora/payment` API and may change without a major version bump.
314
330
  * @experimental
315
331
  */
316
- type PaymentErrorCode = "CONFIG_INVALID" | "CURRENCY_MISMATCH" | "FORBIDDEN" | "INVALID_TRANSITION" | "NOT_FOUND" | "PROVIDER_ERROR" | "WEBHOOK_EVENT_ID_MISSING" | "WEBHOOK_SIGNATURE_INVALID" | "WEBHOOK_TIMESTAMP_INVALID";
332
+ type PaymentErrorCode = "CONFIG_INVALID" | "CURRENCY_MISMATCH" | "FORBIDDEN" | "INVALID_TRANSITION" | "NOT_FOUND" | "PROVIDER_ERROR" | "VALIDATION_ERROR" | "WEBHOOK_EVENT_ID_MISSING" | "WEBHOOK_SIGNATURE_INVALID" | "WEBHOOK_TIMESTAMP_INVALID";
317
333
  /**
318
334
  * Typed error for all `@lunora/payment` failures. A `LunoraError` subclass; `status` maps onto an HTTP response.
319
335
  * @experimental
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createAdapterRegistry as r}from"./packem_shared/createAdapterRegistry-CafjyQwx.mjs";import{lunoraDatabaseToPaymentDatabase as a,paymentsFromContext as n}from"./packem_shared/lunoraDatabaseToPaymentDatabase-Bn3aBIoh.mjs";import{createPayment as y}from"./packem_shared/createPayment-BW6jnMP_.mjs";import{createDatabasePaymentStore as p}from"./packem_shared/createDatabasePaymentStore-4l41pJ0l.mjs";import{entitlementsForReference as s,featureNames as c,hasActivePrice as x,resolveEntitlements as S,usagePeriodStart as l}from"./packem_shared/entitlementsForReference-BbEOKu5d.mjs";import{LunoraPaymentError as T}from"./packem_shared/LunoraPaymentError-35kSImFc.mjs";import{idempotencyKey as P}from"./packem_shared/idempotencyKey-CfJKqcE3.mjs";import{addMoney as d,allocateMoney as A,compareMoney as E,formatMoney as N,fromMoneyJSON as h,isZeroDecimalCurrency as R,isZeroMoney as v,money as C,subtractMoney as D,toMoneyJSON as I,zeroMoney as _}from"./packem_shared/addMoney-JN0UrVXA.mjs";import{reconcile as L}from"./packem_shared/reconcile-y9d1yiVb.mjs";import{default as k}from"./packem_shared/paymentTables-BMtUrXkM.mjs";import{PAYMENT_TERMINAL_STATES as J,SUBSCRIPTION_TERMINAL_STATES as W,canTransitionPayment as Z,canTransitionSubscription as q,nextPaymentState as z,nextSubscriptionState as B}from"./packem_shared/PAYMENT_TERMINAL_STATES-DVNbZxBy.mjs";import{MemoryPaymentStore as K}from"./packem_shared/MemoryPaymentStore-BICI1RdZ.mjs";import{default as Y}from"./packem_shared/applyWebhookAction-6JwJo2XL.mjs";import{constantTimeEqual as w,hmacSha256Hex as G,verifyCreemSignature as Q,verifyStandardWebhook as V}from"./packem_shared/constantTimeEqual-DG_4PS78.mjs";export{T as LunoraPaymentError,K as MemoryPaymentStore,J as PAYMENT_TERMINAL_STATES,W as SUBSCRIPTION_TERMINAL_STATES,d as addMoney,A as allocateMoney,Y as applyWebhookAction,Z as canTransitionPayment,q as canTransitionSubscription,E as compareMoney,w as constantTimeEqual,r as createAdapterRegistry,p as createDatabasePaymentStore,y as createPayment,s as entitlementsForReference,c as featureNames,N as formatMoney,h as fromMoneyJSON,x as hasActivePrice,G as hmacSha256Hex,P as idempotencyKey,R as isZeroDecimalCurrency,v as isZeroMoney,a as lunoraDatabaseToPaymentDatabase,C as money,z as nextPaymentState,B as nextSubscriptionState,k as paymentTables,n as paymentsFromContext,L as reconcile,S as resolveEntitlements,D as subtractMoney,I as toMoneyJSON,l as usagePeriodStart,Q as verifyCreemSignature,V as verifyStandardWebhook,_ as zeroMoney};
1
+ import{createAdapterRegistry as r}from"./packem_shared/createAdapterRegistry-SoXdsiQd.mjs";import{lunoraDatabaseToPaymentDatabase as a,paymentsFromContext as n}from"./packem_shared/lunoraDatabaseToPaymentDatabase-CW1VjW4D.mjs";import{createPayment as y}from"./packem_shared/createPayment-Cj0tRPRZ.mjs";import{createDatabasePaymentStore as p}from"./packem_shared/createDatabasePaymentStore-DxChfP5X.mjs";import{entitlementsForReference as s,featureNames as c,hasActivePrice as x,resolveEntitlements as S,usagePeriodStart as l}from"./packem_shared/entitlementsForReference-BbEOKu5d.mjs";import{LunoraPaymentError as T}from"./packem_shared/LunoraPaymentError-C8uAUIzQ.mjs";import{idempotencyKey as P}from"./packem_shared/idempotencyKey-CfJKqcE3.mjs";import{addMoney as d,allocateMoney as A,compareMoney as E,formatMoney as N,fromMoneyJSON as h,isZeroDecimalCurrency as R,isZeroMoney as v,money as C,subtractMoney as D,toMoneyJSON as I,zeroMoney as _}from"./packem_shared/addMoney-BKfsSf0H.mjs";import{reconcile as L}from"./packem_shared/reconcile-BjWV0mB0.mjs";import{default as k}from"./packem_shared/paymentTables-Be-_11ux.mjs";import{PAYMENT_TERMINAL_STATES as J,SUBSCRIPTION_TERMINAL_STATES as W,canTransitionPayment as Z,canTransitionSubscription as q,nextPaymentState as z,nextSubscriptionState as B}from"./packem_shared/PAYMENT_TERMINAL_STATES-DVNbZxBy.mjs";import{MemoryPaymentStore as K}from"./packem_shared/MemoryPaymentStore-CkXqJEe2.mjs";import{default as Y}from"./packem_shared/applyWebhookAction-Bwvycl00.mjs";import{constantTimeEqual as w,hmacSha256Hex as G,verifyCreemSignature as Q,verifyStandardWebhook as V}from"./packem_shared/constantTimeEqual-B4DP75aY.mjs";export{T as LunoraPaymentError,K as MemoryPaymentStore,J as PAYMENT_TERMINAL_STATES,W as SUBSCRIPTION_TERMINAL_STATES,d as addMoney,A as allocateMoney,Y as applyWebhookAction,Z as canTransitionPayment,q as canTransitionSubscription,E as compareMoney,w as constantTimeEqual,r as createAdapterRegistry,p as createDatabasePaymentStore,y as createPayment,s as entitlementsForReference,c as featureNames,N as formatMoney,h as fromMoneyJSON,x as hasActivePrice,G as hmacSha256Hex,P as idempotencyKey,R as isZeroDecimalCurrency,v as isZeroMoney,a as lunoraDatabaseToPaymentDatabase,C as money,z as nextPaymentState,B as nextSubscriptionState,k as paymentTables,n as paymentsFromContext,L as reconcile,S as resolveEntitlements,D as subtractMoney,I as toMoneyJSON,l as usagePeriodStart,Q as verifyCreemSignature,V as verifyStandardWebhook,_ as zeroMoney};
@@ -0,0 +1 @@
1
+ import{LunoraError as N}from"@lunora/errors";const O={CONFIG_INVALID:500,CURRENCY_MISMATCH:400,FORBIDDEN:403,INVALID_TRANSITION:409,NOT_FOUND:404,PROVIDER_ERROR:502,VALIDATION_ERROR:400,WEBHOOK_EVENT_ID_MISSING:400,WEBHOOK_SIGNATURE_INVALID:400,WEBHOOK_TIMESTAMP_INVALID:400};class _ extends N{constructor(I,r){super(I,r,{name:"LunoraPaymentError",status:O[I]})}}export{_ as LunoraPaymentError};
@@ -0,0 +1 @@
1
+ const u=(n,e)=>`${n}:${e}`,o=(n,e)=>`${n}:${e}`,c=n=>{const e=n.toSorted((r,t)=>r.createdAt-t.createdAt||r.idempotencyKey.localeCompare(t.idempotencyKey));let s=0;for(const r of e)s=r.mode==="set"?r.quantity:s+r.quantity;return s};class a{customers=new Map;processedEvents=new Set;sessions=new Map;subscriptions=new Map;usageEvents=new Map;getCustomerByReference(e,s){return Promise.resolve(this.customers.get(u(e,s)))}getPaymentSession(e,s){return Promise.resolve(this.sessions.get(o(e,s)))}getSubscription(e,s){return Promise.resolve(this.subscriptions.get(o(e,s)))}listSubscriptionsByReference(e){return Promise.resolve([...this.subscriptions.values()].filter(s=>s.referenceId===e))}markEventProcessed(e,s){const r=o(e,s);return this.processedEvents.has(r)?Promise.resolve(!1):(this.processedEvents.add(r),Promise.resolve(!0))}releaseEvent(e,s){return this.processedEvents.delete(o(e,s)),Promise.resolve()}markUsageReported(e,s){const r=o(e,s),t=this.usageEvents.get(r);return t&&this.usageEvents.set(r,{...t,reportedToProvider:!0}),Promise.resolve()}recordUsage(e){const s=o(e.provider,e.idempotencyKey);return this.usageEvents.has(s)?Promise.resolve(!1):(this.usageEvents.set(s,e),Promise.resolve(!0))}sumUsage(e,s,r){const t=[];for(const i of this.usageEvents.values())i.referenceId===e&&i.featureId===s&&i.createdAt>=r&&t.push(i);return Promise.resolve(c(t))}upsertCustomer(e){return this.customers.set(u(e.provider,e.referenceId),e),Promise.resolve()}upsertPaymentSession(e){return this.sessions.set(o(e.provider,e.id),e),Promise.resolve()}upsertSubscription(e){return this.subscriptions.set(o(e.provider,e.id),e),Promise.resolve()}}export{a as MemoryPaymentStore,c as foldUsage};
@@ -164,7 +164,19 @@ interface UsageEvent {
164
164
  readonly featureId: string;
165
165
  /** Caller-stable dedupe key — recording the same key twice is a no-op (exactly-once `track`). */
166
166
  readonly idempotencyKey: string;
167
+ /**
168
+ * How the period total absorbs this event: `"add"` (the default, and the value
169
+ * assumed for rows written before this field existed) increments it, `"set"`
170
+ * RESETS it to `quantity` and discards everything recorded earlier in the
171
+ * period.
172
+ *
173
+ * The ledger stays append-only either way — a `"set"` is a marker, not a
174
+ * computed delta — which is what makes `track({ mode: "set" })` safe to call
175
+ * concurrently. `PaymentStore.sumUsage` (via `foldUsage`) applies the fold.
176
+ */
177
+ readonly mode?: "add" | "set";
167
178
  readonly provider: ProviderId;
179
+ /** For `"add"`, the increment. For `"set"`, the absolute period total this event declares. */
168
180
  readonly quantity: number;
169
181
  readonly referenceId: string;
170
182
  /** Whether the event was successfully forwarded to the provider's metering API. */
@@ -180,12 +192,18 @@ interface TrackInput {
180
192
  readonly idempotencyKey?: string;
181
193
  /**
182
194
  * `"add"` (default) increments usage by `quantity`; `"set"` reconciles the period total to `quantity`.
183
- * `"set"` is a non-atomic read-modify-write (it reads the current total, then appends the delta), so
184
- * concurrent `"set"` calls for the same reference can over- or under-count call it only from a
185
- * serialized context (a single Durable Object or per-reference lock). `"add"` is always safe.
195
+ *
196
+ * Both are a single append: a `"set"` records the absolute target as a marker that the period fold
197
+ * resets to, rather than reading the current total and appending a delta. Concurrent `"set"` calls
198
+ * for the same reference therefore resolve last-writer-wins instead of over- or under-counting, and
199
+ * a replayed `"set"` is idempotent — neither mode needs a serialized context or a per-reference lock.
186
200
  */
187
201
  readonly mode?: "add" | "set";
188
- /** Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`). */
202
+ /**
203
+ * Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`).
204
+ * Must be a non-negative safe integer — a negative value would drive the summed period usage
205
+ * below zero and hand the reference an unbounded metered balance, so it is rejected.
206
+ */
189
207
  readonly quantity?: number;
190
208
  readonly referenceId: string;
191
209
  }
@@ -164,7 +164,19 @@ interface UsageEvent {
164
164
  readonly featureId: string;
165
165
  /** Caller-stable dedupe key — recording the same key twice is a no-op (exactly-once `track`). */
166
166
  readonly idempotencyKey: string;
167
+ /**
168
+ * How the period total absorbs this event: `"add"` (the default, and the value
169
+ * assumed for rows written before this field existed) increments it, `"set"`
170
+ * RESETS it to `quantity` and discards everything recorded earlier in the
171
+ * period.
172
+ *
173
+ * The ledger stays append-only either way — a `"set"` is a marker, not a
174
+ * computed delta — which is what makes `track({ mode: "set" })` safe to call
175
+ * concurrently. `PaymentStore.sumUsage` (via `foldUsage`) applies the fold.
176
+ */
177
+ readonly mode?: "add" | "set";
167
178
  readonly provider: ProviderId;
179
+ /** For `"add"`, the increment. For `"set"`, the absolute period total this event declares. */
168
180
  readonly quantity: number;
169
181
  readonly referenceId: string;
170
182
  /** Whether the event was successfully forwarded to the provider's metering API. */
@@ -180,12 +192,18 @@ interface TrackInput {
180
192
  readonly idempotencyKey?: string;
181
193
  /**
182
194
  * `"add"` (default) increments usage by `quantity`; `"set"` reconciles the period total to `quantity`.
183
- * `"set"` is a non-atomic read-modify-write (it reads the current total, then appends the delta), so
184
- * concurrent `"set"` calls for the same reference can over- or under-count call it only from a
185
- * serialized context (a single Durable Object or per-reference lock). `"add"` is always safe.
195
+ *
196
+ * Both are a single append: a `"set"` records the absolute target as a marker that the period fold
197
+ * resets to, rather than reading the current total and appending a delta. Concurrent `"set"` calls
198
+ * for the same reference therefore resolve last-writer-wins instead of over- or under-counting, and
199
+ * a replayed `"set"` is idempotent — neither mode needs a serialized context or a per-reference lock.
186
200
  */
187
201
  readonly mode?: "add" | "set";
188
- /** Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`). */
202
+ /**
203
+ * Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`).
204
+ * Must be a non-negative safe integer — a negative value would drive the summed period usage
205
+ * below zero and hand the reference an unbounded metered balance, so it is rejected.
206
+ */
189
207
  readonly quantity?: number;
190
208
  readonly referenceId: string;
191
209
  }
@@ -1 +1 @@
1
- import{toSnapshot as u}from"dinero.js";import{add as m,allocate as s,compare as p,subtract as U,dinero as M}from"dinero.js/bigint";import{LunoraPaymentError as C}from"./LunoraPaymentError-35kSImFc.mjs";const F=new Set(["BIF","CLP","DJF","GNF","JPY","KMF","KRW","MGA","PYG","RWF","UGX","VND","VUV","XAF","XOF","XPF"]),d=new Set(["BHD","IQD","JOD","KWD","LYD","OMR","TND"]),t=r=>F.has(r)?0n:d.has(r)?3n:2n,D=r=>({base:10n,code:r.toUpperCase(),exponent:t(r.toUpperCase())}),n=r=>M({amount:r.minorUnits,currency:D(r.currency)}),c=r=>{const e=u(r);return{currency:e.currency.code,minorUnits:e.amount}},y=(r,e)=>{if(r.currency!==e.currency)throw new C("CURRENCY_MISMATCH",`cannot combine ${r.currency} with ${e.currency}`)},S=r=>t(r.toUpperCase())===0n,i=(r,e)=>{const o=typeof r=="bigint"?r:BigInt(Math.trunc(r));return{currency:e.toUpperCase(),minorUnits:o}},h=r=>i(0n,r),l=(r,e="en-US")=>{const o=Number(t(r.currency.toUpperCase())),a=Number(r.minorUnits)/10**o;try{return new Intl.NumberFormat(e,{currency:r.currency,style:"currency"}).format(a)}catch{return`${a.toFixed(o)} ${r.currency}`}},w=(r,e)=>(y(r,e),c(m(n(r),n(e)))),I=(r,e)=>(y(r,e),c(U(n(r),n(e)))),O=(r,e)=>(y(r,e),p(n(r),n(e))),J=(r,e)=>s(n(r),[...e]).map(o=>c(o)),P=r=>r.minorUnits===0n,R=r=>({currency:r.currency,minorUnits:r.minorUnits.toString()}),g=r=>i(BigInt(r.minorUnits),r.currency);export{w as addMoney,J as allocateMoney,O as compareMoney,l as formatMoney,g as fromMoneyJSON,S as isZeroDecimalCurrency,P as isZeroMoney,i as money,I as subtractMoney,R as toMoneyJSON,h as zeroMoney};
1
+ import{toSnapshot as u}from"dinero.js";import{add as m,allocate as s,compare as p,subtract as U,dinero as M}from"dinero.js/bigint";import{LunoraPaymentError as C}from"./LunoraPaymentError-C8uAUIzQ.mjs";const F=new Set(["BIF","CLP","DJF","GNF","JPY","KMF","KRW","MGA","PYG","RWF","UGX","VND","VUV","XAF","XOF","XPF"]),N=new Set(["BHD","IQD","JOD","KWD","LYD","OMR","TND"]),t=r=>F.has(r)?0n:N.has(r)?3n:2n,d=r=>({base:10n,code:r.toUpperCase(),exponent:t(r.toUpperCase())}),n=r=>M({amount:r.minorUnits,currency:d(r.currency)}),c=r=>{const e=u(r);return{currency:e.currency.code,minorUnits:e.amount}},y=(r,e)=>{if(r.currency!==e.currency)throw new C("CURRENCY_MISMATCH",`cannot combine ${r.currency} with ${e.currency}`)},S=r=>t(r.toUpperCase())===0n,i=(r,e)=>{const o=typeof r=="bigint"?r:BigInt(Math.trunc(r));return{currency:e.toUpperCase(),minorUnits:o}},h=r=>i(0n,r),l=(r,e="en-US")=>{const o=Number(t(r.currency.toUpperCase())),a=Number(r.minorUnits)/10**o;try{return new Intl.NumberFormat(e,{currency:r.currency,style:"currency"}).format(a)}catch{return`${a.toFixed(o)} ${r.currency}`}},w=(r,e)=>(y(r,e),c(m(n(r),n(e)))),I=(r,e)=>(y(r,e),c(U(n(r),n(e)))),J=(r,e)=>(y(r,e),p(n(r),n(e))),O=(r,e)=>s(n(r),[...e]).map(o=>c(o)),P=r=>r.minorUnits===0n,R=r=>({currency:r.currency,minorUnits:r.minorUnits.toString()}),g=r=>i(BigInt(r.minorUnits),r.currency);export{w as addMoney,O as allocateMoney,J as compareMoney,l as formatMoney,g as fromMoneyJSON,S as isZeroDecimalCurrency,P as isZeroMoney,i as money,I as subtractMoney,R as toMoneyJSON,h as zeroMoney};
@@ -1 +1 @@
1
- import{LunoraPaymentError as v}from"./LunoraPaymentError-35kSImFc.mjs";import{compareMoney as l,zeroMoney as c,addMoney as P}from"./addMoney-JN0UrVXA.mjs";import{n as s}from"./observability-C9tz8mj_.mjs";import{nextPaymentState as b,nextSubscriptionState as A}from"./PAYMENT_TERMINAL_STATES-DVNbZxBy.mjs";const E={"payment.authorized":"authorize","payment.captured":"capture","payment.failed":"fail","payment.refunded":"refund"},w={"subscription.active":"active","subscription.canceled":"canceled","subscription.past_due":"past_due","subscription.paused":"paused"},S={"subscription.active":"activate","subscription.canceled":"cancel","subscription.past_due":"mark_past_due","subscription.paused":"pause"},_=(t,e)=>l(t,e)>0?t:e,I=(t,e)=>{if(!e.amount||t.refundedAmount.currency!==e.amount.currency||t.capturedAmount.currency!==e.amount.currency)return;const r=e.amountKind==="absolute"?_(e.amount,t.refundedAmount):P(t.refundedAmount,e.amount);if(!(l(r,t.capturedAmount)>0))return r},h=async(t,e,r)=>{if(!e.sessionId)return{applied:!1,reason:"unhandled"};const n=await t.getPaymentSession(e.provider,e.sessionId),a=n?.state??"initiated",d=Date.now(),i=e.amount?.currency??n?.amount.currency??"USD";let o=r;if(r==="refund"&&n){const u=I(n,e);u&&l(u,n.capturedAmount)<0&&(o="partial_refund")}const f=b(a,o);if(!f)return{applied:!1,reason:"illegal_transition"};const p=n??{amount:e.amount??c(i),capturedAmount:c(i),createdAt:d,id:e.sessionId,provider:e.provider,referenceId:e.referenceId??"",refundedAmount:c(i),state:a,updatedAt:d};let{capturedAmount:m,refundedAmount:y}=p;if(o==="capture"&&e.amount&&(m=e.amount),(o==="partial_refund"||o==="refund")&&e.amount){const u=I(p,e);if(!u)return{applied:!1,reason:"invalid_refund_amount"};y=u}return await t.upsertPaymentSession({...p,capturedAmount:m,referenceId:e.referenceId??p.referenceId,refundedAmount:y,state:f,updatedAt:d}),{applied:!0,reason:"ok"}},k=async(t,e)=>{if(!e.subscriptionId)return{applied:!1,reason:"unhandled"};const r=await t.getSubscription(e.provider,e.subscriptionId),n=Date.now();if(e.type==="subscription.updated")return r?(await t.upsertSubscription({...r,cancelAtPeriodEnd:e.cancelAtPeriodEnd??r.cancelAtPeriodEnd,currentPeriodEnd:e.currentPeriodEnd??r.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??r.currentPeriodStart,priceId:e.priceId??r.priceId,quantity:e.quantity??r.quantity,updatedAt:n}),{applied:!0,reason:"ok"}):{applied:!1,reason:"unhandled"};const a=w[e.type];if(!a)return{applied:!1,reason:"unhandled"};if(!r)return await t.upsertSubscription({cancelAtPeriodEnd:e.cancelAtPeriodEnd??!1,createdAt:n,currentPeriodEnd:e.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??n,id:e.subscriptionId,priceId:e.priceId??"",provider:e.provider,quantity:e.quantity??1,referenceId:e.referenceId??"",state:a,updatedAt:n}),{applied:!0,reason:"ok"};const d=r.state==="active"&&a==="active"?"renew":S[e.type],i=d?A(r.state,d):void 0;return i?(await t.upsertSubscription({...r,cancelAtPeriodEnd:e.cancelAtPeriodEnd??r.cancelAtPeriodEnd,currentPeriodEnd:e.currentPeriodEnd??r.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??r.currentPeriodStart,priceId:e.priceId??r.priceId,quantity:e.quantity??r.quantity,state:i,updatedAt:n}),{applied:!0,reason:"ok"}):{applied:!1,reason:"illegal_transition"}},O=async(t,e,r)=>{if(e.type==="unhandled")return{applied:!1,reason:"unhandled"};if(!e.eventId?.trim())throw new v("WEBHOOK_EVENT_ID_MISSING",`webhook event id is missing or blank for provider "${e.provider}"`);if(!await t.markEventProcessed(e.provider,e.eventId))return s(r,{eventId:e.eventId,provider:e.provider,type:"webhook.duplicate"}),{applied:!1,reason:"duplicate"};const n=E[e.type];let a;try{a=n?await h(t,e,n):await k(t,e)}catch(d){throw await t.releaseEvent(e.provider,e.eventId),d}return s(r,{action:e.type,eventId:e.eventId,provider:e.provider,reason:a.reason,type:"webhook.applied"}),e.type==="payment.failed"?s(r,{provider:e.provider,referenceId:e.referenceId,sessionId:e.sessionId,type:"payment.failed"}):e.type==="subscription.past_due"&&s(r,{provider:e.provider,referenceId:e.referenceId,subscriptionId:e.subscriptionId,type:"subscription.past_due"}),a};export{O as default};
1
+ import{LunoraPaymentError as v}from"./LunoraPaymentError-C8uAUIzQ.mjs";import{compareMoney as l,zeroMoney as c,addMoney as P}from"./addMoney-BKfsSf0H.mjs";import{n as s}from"./observability-C9tz8mj_.mjs";import{nextPaymentState as b,nextSubscriptionState as A}from"./PAYMENT_TERMINAL_STATES-DVNbZxBy.mjs";const E={"payment.authorized":"authorize","payment.captured":"capture","payment.failed":"fail","payment.refunded":"refund"},w={"subscription.active":"active","subscription.canceled":"canceled","subscription.past_due":"past_due","subscription.paused":"paused"},S={"subscription.active":"activate","subscription.canceled":"cancel","subscription.past_due":"mark_past_due","subscription.paused":"pause"},_=(t,e)=>l(t,e)>0?t:e,I=(t,e)=>{if(!e.amount||t.refundedAmount.currency!==e.amount.currency||t.capturedAmount.currency!==e.amount.currency)return;const r=e.amountKind==="absolute"?_(e.amount,t.refundedAmount):P(t.refundedAmount,e.amount);if(!(l(r,t.capturedAmount)>0))return r},h=async(t,e,r)=>{if(!e.sessionId)return{applied:!1,reason:"unhandled"};const n=await t.getPaymentSession(e.provider,e.sessionId),a=n?.state??"initiated",d=Date.now(),i=e.amount?.currency??n?.amount.currency??"USD";let o=r;if(r==="refund"&&n){const u=I(n,e);u&&l(u,n.capturedAmount)<0&&(o="partial_refund")}const f=b(a,o);if(!f)return{applied:!1,reason:"illegal_transition"};const p=n??{amount:e.amount??c(i),capturedAmount:c(i),createdAt:d,id:e.sessionId,provider:e.provider,referenceId:e.referenceId??"",refundedAmount:c(i),state:a,updatedAt:d};let{capturedAmount:m,refundedAmount:y}=p;if(o==="capture"&&e.amount&&(m=e.amount),(o==="partial_refund"||o==="refund")&&e.amount){const u=I(p,e);if(!u)return{applied:!1,reason:"invalid_refund_amount"};y=u}return await t.upsertPaymentSession({...p,capturedAmount:m,referenceId:e.referenceId??p.referenceId,refundedAmount:y,state:f,updatedAt:d}),{applied:!0,reason:"ok"}},k=async(t,e)=>{if(!e.subscriptionId)return{applied:!1,reason:"unhandled"};const r=await t.getSubscription(e.provider,e.subscriptionId),n=Date.now();if(e.type==="subscription.updated")return r?(await t.upsertSubscription({...r,cancelAtPeriodEnd:e.cancelAtPeriodEnd??r.cancelAtPeriodEnd,currentPeriodEnd:e.currentPeriodEnd??r.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??r.currentPeriodStart,priceId:e.priceId??r.priceId,quantity:e.quantity??r.quantity,updatedAt:n}),{applied:!0,reason:"ok"}):{applied:!1,reason:"unhandled"};const a=w[e.type];if(!a)return{applied:!1,reason:"unhandled"};if(!r)return await t.upsertSubscription({cancelAtPeriodEnd:e.cancelAtPeriodEnd??!1,createdAt:n,currentPeriodEnd:e.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??n,id:e.subscriptionId,priceId:e.priceId??"",provider:e.provider,quantity:e.quantity??1,referenceId:e.referenceId??"",state:a,updatedAt:n}),{applied:!0,reason:"ok"};const d=r.state==="active"&&a==="active"?"renew":S[e.type],i=d?A(r.state,d):void 0;return i?(await t.upsertSubscription({...r,cancelAtPeriodEnd:e.cancelAtPeriodEnd??r.cancelAtPeriodEnd,currentPeriodEnd:e.currentPeriodEnd??r.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart??r.currentPeriodStart,priceId:e.priceId??r.priceId,quantity:e.quantity??r.quantity,state:i,updatedAt:n}),{applied:!0,reason:"ok"}):{applied:!1,reason:"illegal_transition"}},x=async(t,e,r)=>{if(e.type==="unhandled")return{applied:!1,reason:"unhandled"};if(!e.eventId?.trim())throw new v("WEBHOOK_EVENT_ID_MISSING",`webhook event id is missing or blank for provider "${e.provider}"`);if(!await t.markEventProcessed(e.provider,e.eventId))return s(r,{eventId:e.eventId,provider:e.provider,type:"webhook.duplicate"}),{applied:!1,reason:"duplicate"};const n=E[e.type];let a;try{a=n?await h(t,e,n):await k(t,e)}catch(d){throw await t.releaseEvent(e.provider,e.eventId),d}return s(r,{action:e.type,eventId:e.eventId,provider:e.provider,reason:a.reason,type:"webhook.applied"}),e.type==="payment.failed"?s(r,{provider:e.provider,referenceId:e.referenceId,sessionId:e.sessionId,type:"payment.failed"}):e.type==="subscription.past_due"&&s(r,{provider:e.provider,referenceId:e.referenceId,subscriptionId:e.subscriptionId,type:"subscription.past_due"}),a};export{x as default};
@@ -1 +1 @@
1
- import{LunoraPaymentError as r}from"./LunoraPaymentError-35kSImFc.mjs";const m=(t,e)=>{const a=Math.max(t.length,e.length);let o=t.length^e.length;for(let n=0;n<a;n+=1){const s=n<t.length?t.charCodeAt(n):0,c=n<e.length?e.charCodeAt(n):0;o|=s^c}return o===0},h=new TextEncoder,I=t=>[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,"0")).join(""),g="whsec_",d=t=>new Uint8Array(Array.from(atob(t),e=>e.codePointAt(0)??0)),u=t=>btoa(String.fromCodePoint(...new Uint8Array(t))),A=async(t,e)=>{const a=await crypto.subtle.importKey("raw",t,{hash:"SHA-256",name:"HMAC"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",a,h.encode(e));return u(o)},l=m,f=async(t,e)=>{const a=await crypto.subtle.importKey("raw",h.encode(t),{hash:"SHA-256",name:"HMAC"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",a,h.encode(e));return I(o)},y=async t=>{if(!t.secret)throw new r("CONFIG_INVALID","webhook secret not configured");const e=t.toleranceSeconds??300,a=t.now??Date.now(),o=Number(t.webhookTimestamp);if(!t.webhookId||!t.webhookSignature||!Number.isFinite(o))throw new r("WEBHOOK_SIGNATURE_INVALID","missing standard-webhooks headers");if(Math.abs(Math.floor(a/1e3)-o)>e)throw new r("WEBHOOK_TIMESTAMP_INVALID","signature timestamp outside tolerance");const n=t.secret.startsWith(g)?t.secret.slice(g.length):t.secret;if(!n)throw new r("CONFIG_INVALID","webhook secret not configured");const s=d(n);if(s.length===0)throw new r("CONFIG_INVALID","webhook secret not configured");const c=await A(s,`${t.webhookId}.${t.webhookTimestamp}.${t.payload}`);if(!t.webhookSignature.split(" ").map(i=>{const w=i.indexOf(",");return w===-1?"":i.slice(w+1)}).filter(Boolean).some(i=>l(i,c)))throw new r("WEBHOOK_SIGNATURE_INVALID","no matching signature")},N=async t=>{if(!t.secret)throw new r("CONFIG_INVALID","webhook secret not configured");if(!t.signature)throw new r("WEBHOOK_SIGNATURE_INVALID","missing creem-signature header");const e=await f(t.secret,t.payload);if(!l(t.signature,e))throw new r("WEBHOOK_SIGNATURE_INVALID","no matching signature")};export{l as constantTimeEqual,f as hmacSha256Hex,N as verifyCreemSignature,y as verifyStandardWebhook};
1
+ import{LunoraPaymentError as r}from"./LunoraPaymentError-C8uAUIzQ.mjs";const m=(t,e)=>{const a=Math.max(t.length,e.length);let o=t.length^e.length;for(let n=0;n<a;n+=1){const s=n<t.length?t.charCodeAt(n):0,c=n<e.length?e.charCodeAt(n):0;o|=s^c}return o===0},h=new TextEncoder,I=t=>[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,"0")).join(""),g="whsec_",d=t=>new Uint8Array(Array.from(atob(t),e=>e.codePointAt(0)??0)),u=t=>btoa(String.fromCodePoint(...new Uint8Array(t))),A=async(t,e)=>{const a=await crypto.subtle.importKey("raw",t,{hash:"SHA-256",name:"HMAC"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",a,h.encode(e));return u(o)},l=m,f=async(t,e)=>{const a=await crypto.subtle.importKey("raw",h.encode(t),{hash:"SHA-256",name:"HMAC"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",a,h.encode(e));return I(o)},y=async t=>{if(!t.secret)throw new r("CONFIG_INVALID","webhook secret not configured");const e=t.toleranceSeconds??300,a=t.now??Date.now(),o=Number(t.webhookTimestamp);if(!t.webhookId||!t.webhookSignature||!Number.isFinite(o))throw new r("WEBHOOK_SIGNATURE_INVALID","missing standard-webhooks headers");if(Math.abs(Math.floor(a/1e3)-o)>e)throw new r("WEBHOOK_TIMESTAMP_INVALID","signature timestamp outside tolerance");const n=t.secret.startsWith(g)?t.secret.slice(g.length):t.secret;if(!n)throw new r("CONFIG_INVALID","webhook secret not configured");const s=d(n);if(s.length===0)throw new r("CONFIG_INVALID","webhook secret not configured");const c=await A(s,`${t.webhookId}.${t.webhookTimestamp}.${t.payload}`);if(!t.webhookSignature.split(" ").map(i=>{const w=i.indexOf(",");return w===-1?"":i.slice(w+1)}).filter(Boolean).some(i=>l(i,c)))throw new r("WEBHOOK_SIGNATURE_INVALID","no matching signature")},N=async t=>{if(!t.secret)throw new r("CONFIG_INVALID","webhook secret not configured");if(!t.signature)throw new r("WEBHOOK_SIGNATURE_INVALID","missing creem-signature header");const e=await f(t.secret,t.payload);if(!l(t.signature,e))throw new r("WEBHOOK_SIGNATURE_INVALID","no matching signature")};export{l as constantTimeEqual,f as hmacSha256Hex,N as verifyCreemSignature,y as verifyStandardWebhook};
@@ -1 +1 @@
1
- import{LunoraPaymentError as o}from"./LunoraPaymentError-35kSImFc.mjs";const n=i=>{const e=new Map;for(const r of i){if(e.has(r.identifier))throw new o("CONFIG_INVALID",`duplicate adapter for provider "${r.identifier}"`);e.set(r.identifier,r)}return{all:()=>[...e.values()],get:r=>{const t=e.get(r);if(!t)throw new o("CONFIG_INVALID",`no adapter registered for provider "${r}"`);return t},has:r=>e.has(r)}};export{n as createAdapterRegistry};
1
+ import{LunoraPaymentError as o}from"./LunoraPaymentError-C8uAUIzQ.mjs";const n=i=>{const e=new Map;for(const r of i){if(e.has(r.identifier))throw new o("CONFIG_INVALID",`duplicate adapter for provider "${r.identifier}"`);e.set(r.identifier,r)}return{all:()=>[...e.values()],get:r=>{const t=e.get(r);if(!t)throw new o("CONFIG_INVALID",`no adapter registered for provider "${r}"`);return t},has:r=>e.has(r)}};export{n as createAdapterRegistry};
@@ -0,0 +1 @@
1
+ import{money as c}from"./addMoney-BKfsSf0H.mjs";import{foldUsage as y}from"./MemoryPaymentStore-CkXqJEe2.mjs";const n=(e,t)=>typeof e[t]=="string"?e[t]:"",m=(e,t)=>typeof e[t]=="string"?e[t]:void 0,o=(e,t)=>typeof e[t]=="number"?e[t]:0,u=(e,t)=>typeof e[t]=="number"?e[t]:void 0,f=(e,t)=>e[t]===!0,p=(e,t)=>{const r=e[t];return typeof r=="bigint"?r:typeof r=="number"||typeof r=="string"?BigInt(r):0n},I=e=>({createdAt:e.createdAt,email:e.email,provider:e.provider,providerCustomerId:e.id,referenceId:e.referenceId}),A=e=>({createdAt:o(e,"createdAt"),email:m(e,"email"),id:n(e,"providerCustomerId"),provider:n(e,"provider"),referenceId:n(e,"referenceId")}),S=e=>({amountMinor:e.amount.minorUnits,capturedMinor:e.capturedAmount.minorUnits,createdAt:e.createdAt,currency:e.amount.currency,provider:e.provider,providerSessionId:e.id,referenceId:e.referenceId,refundedMinor:e.refundedAmount.minorUnits,state:e.state,updatedAt:e.updatedAt}),P=e=>{const t=n(e,"currency");return{amount:c(p(e,"amountMinor"),t),capturedAmount:c(p(e,"capturedMinor"),t),createdAt:o(e,"createdAt"),id:n(e,"providerSessionId"),provider:n(e,"provider"),referenceId:n(e,"referenceId"),refundedAmount:c(p(e,"refundedMinor"),t),state:n(e,"state"),updatedAt:o(e,"updatedAt")}},g=e=>({cancelAtPeriodEnd:e.cancelAtPeriodEnd,createdAt:e.createdAt,currentPeriodEnd:e.currentPeriodEnd,currentPeriodStart:e.currentPeriodStart,priceId:e.priceId,provider:e.provider,providerSubscriptionId:e.id,quantity:e.quantity,referenceId:e.referenceId,state:e.state,updatedAt:e.updatedAt}),v=e=>({cancelAtPeriodEnd:f(e,"cancelAtPeriodEnd"),createdAt:o(e,"createdAt"),currentPeriodEnd:u(e,"currentPeriodEnd"),currentPeriodStart:u(e,"currentPeriodStart"),id:n(e,"providerSubscriptionId"),priceId:n(e,"priceId"),provider:n(e,"provider"),quantity:o(e,"quantity"),referenceId:n(e,"referenceId"),state:n(e,"state"),updatedAt:o(e,"updatedAt")}),w=e=>({createdAt:e.createdAt,featureId:e.featureId,idempotencyKey:e.idempotencyKey,...e.mode==="set"?{mode:"set"}:{},provider:e.provider,quantity:e.quantity,referenceId:e.referenceId,reportedToProvider:e.reportedToProvider}),l=e=>{const t=async(r,i,d)=>{const s=await e.findFirst(r,i);if(s){await e.patch(s._id,d);return}await e.insert(r,d)};return{getCustomerByReference:async(r,i)=>{const d=await e.findFirst("customers",{provider:r,referenceId:i});return d?A(d):void 0},getPaymentSession:async(r,i)=>{const d=await e.findFirst("paymentSessions",{provider:r,providerSessionId:i});return d?P(d):void 0},getSubscription:async(r,i)=>{const d=await e.findFirst("subscriptions",{provider:r,providerSubscriptionId:i});return d?v(d):void 0},listSubscriptionsByReference:async r=>(await e.findMany("subscriptions",{referenceId:r})).map(i=>v(i)),markEventProcessed:async(r,i)=>await e.findFirst("events",{provider:r,providerEventId:i})?!1:(await e.insert("events",{processedAt:Date.now(),provider:r,providerEventId:i,type:""}),!0),releaseEvent:async(r,i)=>{const d=await e.findFirst("events",{provider:r,providerEventId:i});d&&await e.delete(d._id)},markUsageReported:async(r,i)=>{const d=await e.findFirst("usageEvents",{idempotencyKey:i,provider:r});d&&await e.patch(d._id,{reportedToProvider:!0})},recordUsage:async r=>await e.findFirst("usageEvents",{idempotencyKey:r.idempotencyKey,provider:r.provider})?!1:(await e.insert("usageEvents",w(r)),!0),sumUsage:async(r,i,d)=>{const s=(await e.findMany("usageEvents",{featureId:i,referenceId:r})).filter(a=>o(a,"createdAt")>=d).map(a=>({createdAt:o(a,"createdAt"),idempotencyKey:typeof a.idempotencyKey=="string"?a.idempotencyKey:"",mode:a.mode==="set"?"set":"add",quantity:o(a,"quantity")}));return y(s)},upsertCustomer:async r=>t("customers",{provider:r.provider,providerCustomerId:r.id},I(r)),upsertPaymentSession:async r=>t("paymentSessions",{provider:r.provider,providerSessionId:r.id},S(r)),upsertSubscription:async r=>t("subscriptions",{provider:r.provider,providerSubscriptionId:r.id},g(r))}};export{l as createDatabasePaymentStore};
@@ -0,0 +1 @@
1
+ import{toErrorBody as b}from"@lunora/errors";import{usagePeriodStart as w,resolveEntitlements as h,featureNames as g,hasActivePrice as v}from"./entitlementsForReference-BbEOKu5d.mjs";import{LunoraPaymentError as d}from"./LunoraPaymentError-C8uAUIzQ.mjs";import{idempotencyKey as N,derivedIdempotencyKey as O}from"./idempotencyKey-CfJKqcE3.mjs";import{n as S}from"./observability-C9tz8mj_.mjs";import k from"./applyWebhookAction-Bwvycl00.mjs";const p=(a,t=200,o)=>Response.json(a,{headers:{"content-type":"application/json",...o},status:t});let m=0;const R=()=>{const a=Date.now();return m=a>m?a:m+1,m},B=a=>a&&"referenceId"in a?Object.fromEntries(Object.entries(a).filter(([t])=>t!=="referenceId")):a,_=a=>{const{adapter:t,store:o}=a,f=async e=>{if(!a.authorize)return;let r;try{r=await a.authorize(e)}catch{throw new d("FORBIDDEN",`caller not authorized for reference "${e}"`)}if(!r)throw new d("FORBIDDEN",`caller not authorized for reference "${e}"`)},y=async e=>{await f(e.referenceId);const r=B(e.metadata);let i;const n=await o.getCustomerByReference(t.identifier,e.referenceId);if(n)i=n.id;else{const s=await t.getOrCreateCustomer({email:e.email,referenceId:e.referenceId});i=s.id,await o.upsertCustomer(s)}const c=e.idempotencyKey??await O("checkout",t.identifier,e.referenceId,e.priceId,e.mode,String(e.quantity??1),e.successUrl,e.cancelUrl,r?JSON.stringify(r):"");return t.createCheckout({...e,customerId:i,idempotencyKey:c,metadata:r})},I=async(e,r,i,n,c)=>{const s=e.limit(n);if(s!==void 0){const u=await o.sumUsage(i,n,w(r)),l=s-u;return{allowed:l>=c,balance:l,limit:s,unlimited:!1,used:u}}return{allowed:e.has(n),unlimited:e.has(n)}};return{adapter:t,attach:async e=>y({...e,mode:e.mode??"subscription"}),cancelSubscription:async(e,r)=>{const i=await o.getSubscription(t.identifier,e);if(!i)throw new d("NOT_FOUND",`subscription "${e}" not found`);try{await f(i.referenceId)}catch{throw new d("NOT_FOUND",`subscription "${e}" not found`)}const n=r?.idempotencyKey??N("cancel_subscription",t.identifier,e),c=await t.cancelSubscription(e,{...r,idempotencyKey:n});return await o.upsertSubscription(c),c},check:async e=>{if(await f(e.referenceId),e.featureId===void 0&&e.priceId===void 0)throw new d("CONFIG_INVALID","check() requires a featureId or priceId");if(t.checkEntitlement)return t.checkEntitlement(e);const r=await o.listSubscriptionsByReference(e.referenceId);if(e.priceId!==void 0)return{allowed:v(r,e.priceId),unlimited:!1};if(e.featureId===void 0)throw new d("CONFIG_INVALID","check() requires a featureId or priceId");if(!a.entitlements)throw new d("CONFIG_INVALID","check() requires `entitlements` to be configured");const i=h(a.entitlements,r);return I(i,r,e.referenceId,e.featureId,e.quantity??1)},createCheckout:async e=>y(e),createPortalSession:async(e,r)=>{await f(e);const i=await o.getCustomerByReference(t.identifier,e);if(!i)throw new d("NOT_FOUND",`no customer for reference "${e}"`);return t.createPortalSession({customerId:i.id,returnUrl:r})},handleWebhook:async e=>{let r;try{const n=await e.text();r=await t.parseWebhook({headers:e.headers,payload:n})}catch(n){if(n instanceof d){const{body:c,status:s}=b(n);return p({error:c.message},s)}return p({error:"webhook error"},400)}const i=await k(o,r,a.observability);return p({applied:i.applied,reason:i.reason},200)},listBalances:async e=>{if(await f(e),t.getBalances)return t.getBalances(e);if(!a.entitlements)throw new d("CONFIG_INVALID","listBalances() requires `entitlements` to be configured");const r=await o.listSubscriptionsByReference(e),i=h(a.entitlements,r);return Promise.all(g(a.entitlements).map(async n=>({featureId:n,...await I(i,r,e,n,1)})))},listSubscriptions:async e=>(await f(e),o.listSubscriptionsByReference(e)),store:o,track:async e=>{await f(e.referenceId);const r=e.quantity===void 0?1:e.quantity;if(!Number.isSafeInteger(r)||r<0)throw new d("VALIDATION_ERROR",`track(): \`quantity\` must be a non-negative safe integer (got ${String(e.quantity)})`);const i=e.idempotencyKey??crypto.randomUUID(),n=e.mode==="set",c=n?await o.listSubscriptionsByReference(e.referenceId):void 0,s=c===void 0?0:await o.sumUsage(e.referenceId,e.featureId,w(c));if(n?r===s:r===0)return{recorded:!1,reportedToProvider:!1};const u=n?r-s:r;if(!await o.recordUsage({createdAt:R(),featureId:e.featureId,idempotencyKey:i,...n?{mode:"set"}:{},provider:t.identifier,quantity:r,referenceId:e.referenceId,reportedToProvider:!1}))return{recorded:!1,reportedToProvider:!1};if(u<=0||!t.capabilities.usageMetering||!t.reportUsage)return{recorded:!0,reportedToProvider:!1};try{const l=await o.getCustomerByReference(t.identifier,e.referenceId);return await t.reportUsage({customerId:l?.id,featureId:e.featureId,idempotencyKey:i,quantity:u,referenceId:e.referenceId}),await o.markUsageReported(t.identifier,i),{recorded:!0,reportedToProvider:!0}}catch{return S(a.observability,{featureId:e.featureId,provider:t.identifier,referenceId:e.referenceId,type:"usage.report_failed"}),{recorded:!0,reportedToProvider:!1}}}}};export{_ as createPayment};
@@ -1 +1 @@
1
- import{createPayment as i}from"./createPayment-BW6jnMP_.mjs";import{createDatabasePaymentStore as n}from"./createDatabasePaymentStore-4l41pJ0l.mjs";const s=e=>({delete:async t=>e.delete(t),findFirst:async(t,a)=>await e.findFirst(t,{where:a}),findMany:async(t,a)=>(await e.findMany(t,{where:a})).page,insert:async(t,a)=>e.insert(t,a),patch:async(t,a)=>e.patch(t,a)}),d=(e,t)=>{const a=e.auth?.userId??void 0;return i({adapter:t.adapter,authorize:t.authorize??(r=>r.trim()!==""&&a!==void 0&&r===a),entitlements:t.entitlements,observability:t.observability,store:n(s(e.db))})};export{s as lunoraDatabaseToPaymentDatabase,d as paymentsFromContext};
1
+ import{createPayment as i}from"./createPayment-Cj0tRPRZ.mjs";import{createDatabasePaymentStore as n}from"./createDatabasePaymentStore-DxChfP5X.mjs";const s=e=>({delete:async t=>e.delete(t),findFirst:async(t,a)=>await e.findFirst(t,{where:a}),findMany:async(t,a)=>(await e.findMany(t,{where:a})).page,insert:async(t,a)=>e.insert(t,a),patch:async(t,a)=>e.patch(t,a)}),d=(e,t)=>{const a=e.auth?.userId??void 0;return i({adapter:t.adapter,authorize:t.authorize??(r=>r.trim()!==""&&a!==void 0&&r===a),entitlements:t.entitlements,observability:t.observability,store:n(s(e.db))})};export{s as lunoraDatabaseToPaymentDatabase,d as paymentsFromContext};
@@ -0,0 +1 @@
1
+ import{LunoraPaymentError as t}from"./LunoraPaymentError-C8uAUIzQ.mjs";const n=o=>r=>{throw new t("PROVIDER_ERROR",`${o} does not support ${r}`)};export{n as e};
@@ -1 +1 @@
1
- import{defineTable as r}from"@lunora/server";import{v as e}from"@lunora/values";const n=r({createdAt:e.number(),email:e.optional(e.string()),provider:e.string(),providerCustomerId:e.string(),referenceId:e.string()}).index("by_provider_customer",["provider","providerCustomerId"],{unique:!0}).index("by_reference",["referenceId"]),i=r({cancelAtPeriodEnd:e.boolean(),createdAt:e.number(),currentPeriodEnd:e.optional(e.number()),currentPeriodStart:e.optional(e.number()),priceId:e.string(),provider:e.string(),providerSubscriptionId:e.string(),quantity:e.number(),referenceId:e.string(),state:e.string(),updatedAt:e.number()}).index("by_provider_subscription",["provider","providerSubscriptionId"],{unique:!0}).index("by_reference",["referenceId"]),t=r({amountMinor:e.bigint(),capturedMinor:e.bigint(),createdAt:e.number(),currency:e.string(),provider:e.string(),providerSessionId:e.string(),referenceId:e.string(),refundedMinor:e.bigint(),state:e.string(),updatedAt:e.number()}).index("by_provider_session",["provider","providerSessionId"],{unique:!0}).index("by_reference",["referenceId"]),d=r({processedAt:e.number(),provider:e.string(),providerEventId:e.string(),type:e.string()}).index("by_provider_event",["provider","providerEventId"],{unique:!0}),o=r({createdAt:e.number(),featureId:e.string(),idempotencyKey:e.string(),provider:e.string(),quantity:e.number(),referenceId:e.string(),reportedToProvider:e.boolean()}).index("by_idempotency",["provider","idempotencyKey"],{unique:!0}).index("by_reference_feature",["referenceId","featureId"]),p={customers:n,events:d,paymentSessions:t,subscriptions:i,usageEvents:o};export{p as default};
1
+ import{defineTable as r}from"@lunora/server";import{v as e}from"@lunora/values";const n=r({createdAt:e.number(),email:e.optional(e.string()),provider:e.string(),providerCustomerId:e.string(),referenceId:e.string()}).index("by_provider_customer",["provider","providerCustomerId"],{unique:!0}).index("by_reference",["referenceId"]),i=r({cancelAtPeriodEnd:e.boolean(),createdAt:e.number(),currentPeriodEnd:e.optional(e.number()),currentPeriodStart:e.optional(e.number()),priceId:e.string(),provider:e.string(),providerSubscriptionId:e.string(),quantity:e.number(),referenceId:e.string(),state:e.string(),updatedAt:e.number()}).index("by_provider_subscription",["provider","providerSubscriptionId"],{unique:!0}).index("by_reference",["referenceId"]),t=r({amountMinor:e.bigint(),capturedMinor:e.bigint(),createdAt:e.number(),currency:e.string(),provider:e.string(),providerSessionId:e.string(),referenceId:e.string(),refundedMinor:e.bigint(),state:e.string(),updatedAt:e.number()}).index("by_provider_session",["provider","providerSessionId"],{unique:!0}).index("by_reference",["referenceId"]),d=r({processedAt:e.number(),provider:e.string(),providerEventId:e.string(),type:e.string()}).index("by_provider_event",["provider","providerEventId"],{unique:!0}),o=r({createdAt:e.number(),featureId:e.string(),idempotencyKey:e.string(),mode:e.optional(e.string()),provider:e.string(),quantity:e.number(),referenceId:e.string(),reportedToProvider:e.boolean()}).index("by_idempotency",["provider","idempotencyKey"],{unique:!0}).index("by_reference_feature",["referenceId","featureId"]),p={customers:n,events:d,paymentSessions:t,subscriptions:i,usageEvents:o};export{p as default};
@@ -1 +1 @@
1
- import{compareMoney as l}from"./addMoney-JN0UrVXA.mjs";import{n as c}from"./observability-C9tz8mj_.mjs";const p=(t,e)=>t.currency===e.currency&&l(t,e)===0,m=(t,e)=>t?.state!==e.state||t.cancelAtPeriodEnd!==e.cancelAtPeriodEnd||t.currentPeriodEnd!==e.currentPeriodEnd||t.priceId!==e.priceId||t.quantity!==e.quantity,y=(t,e)=>t?.state!==e.state||!p(t.capturedAmount,e.capturedAmount)||!p(t.refundedAmount,e.refundedAmount),A=new Set(["partially_refunded","refunded"]),S=(t,e)=>{if(!t)return e;const r=t.refundedAmount.currency===e.refundedAmount.currency&&l(t.refundedAmount,e.refundedAmount)>0?t.refundedAmount:e.refundedAmount,a=e.state==="captured"&&A.has(t.state)?t.state:e.state,n=e.referenceId===""?t.referenceId:e.referenceId;return{...e,referenceId:n,refundedAmount:r,state:a}},b=async(t,e,r,a)=>{const n=await t.getSubscriptionStatus(r),d=await e.getSubscription(t.identifier,r);return m(d,n)?(await e.upsertSubscription({...n,createdAt:d?.createdAt??n.createdAt}),c(a,{id:r,kind:"subscription",provider:t.identifier,type:"reconcile.drift"}),!0):!1},P=async(t,e,r,a)=>{const n=await t.getPaymentStatus(r),d=await e.getPaymentSession(t.identifier,r),i=S(d,n);return y(d,i)?(await e.upsertPaymentSession({...i,createdAt:d?.createdAt??i.createdAt}),c(a,{id:r,kind:"payment",provider:t.identifier,type:"reconcile.drift"}),!0):!1},f=async(t,e,r,a,n)=>{const d=await Promise.allSettled(t.map(u=>r(u)));let i=0,s=0;for(const[u,o]of d.entries())o.status==="fulfilled"?o.value&&(i+=1):(s+=1,c(n,{error:o.reason,id:t[u]??"",kind:e,provider:a.identifier,type:"reconcile.error"}));return{failed:s,updated:i}},v=async t=>{const{adapter:e,observability:r,store:a}=t,n=t.subscriptionIds??[],d=t.paymentSessionIds??[],i=await f(n,"subscription",u=>b(e,a,u,r),e,r),s=await f(d,"payment",u=>P(e,a,u,r),e,r);return c(r,{failedPayments:s.failed,failedSubscriptions:i.failed,provider:e.identifier,type:"reconcile.completed",updatedPayments:s.updated,updatedSubscriptions:i.updated}),{checkedPayments:d.length,checkedSubscriptions:n.length,failedPayments:s.failed,failedSubscriptions:i.failed,updatedPayments:s.updated,updatedSubscriptions:i.updated}};export{v as reconcile};
1
+ import{compareMoney as l}from"./addMoney-BKfsSf0H.mjs";import{n as c}from"./observability-C9tz8mj_.mjs";const p=(t,e)=>t.currency===e.currency&&l(t,e)===0,m=(t,e)=>t?.state!==e.state||t.cancelAtPeriodEnd!==e.cancelAtPeriodEnd||t.currentPeriodEnd!==e.currentPeriodEnd||t.priceId!==e.priceId||t.quantity!==e.quantity,y=(t,e)=>t?.state!==e.state||!p(t.capturedAmount,e.capturedAmount)||!p(t.refundedAmount,e.refundedAmount),A=new Set(["partially_refunded","refunded"]),S=(t,e)=>{if(!t)return e;const r=t.refundedAmount.currency===e.refundedAmount.currency&&l(t.refundedAmount,e.refundedAmount)>0?t.refundedAmount:e.refundedAmount,a=e.state==="captured"&&A.has(t.state)?t.state:e.state,n=e.referenceId===""?t.referenceId:e.referenceId;return{...e,referenceId:n,refundedAmount:r,state:a}},b=async(t,e,r,a)=>{const n=await t.getSubscriptionStatus(r),d=await e.getSubscription(t.identifier,r);return m(d,n)?(await e.upsertSubscription({...n,createdAt:d?.createdAt??n.createdAt}),c(a,{id:r,kind:"subscription",provider:t.identifier,type:"reconcile.drift"}),!0):!1},P=async(t,e,r,a)=>{const n=await t.getPaymentStatus(r),d=await e.getPaymentSession(t.identifier,r),i=S(d,n);return y(d,i)?(await e.upsertPaymentSession({...i,createdAt:d?.createdAt??i.createdAt}),c(a,{id:r,kind:"payment",provider:t.identifier,type:"reconcile.drift"}),!0):!1},f=async(t,e,r,a,n)=>{const d=await Promise.allSettled(t.map(u=>r(u)));let i=0,s=0;for(const[u,o]of d.entries())o.status==="fulfilled"?o.value&&(i+=1):(s+=1,c(n,{error:o.reason,id:t[u]??"",kind:e,provider:a.identifier,type:"reconcile.error"}));return{failed:s,updated:i}},v=async t=>{const{adapter:e,observability:r,store:a}=t,n=t.subscriptionIds??[],d=t.paymentSessionIds??[],i=await f(n,"subscription",u=>b(e,a,u,r),e,r),s=await f(d,"payment",u=>P(e,a,u,r),e,r);return c(r,{failedPayments:s.failed,failedSubscriptions:i.failed,provider:e.identifier,type:"reconcile.completed",updatedPayments:s.updated,updatedSubscriptions:i.updated}),{checkedPayments:d.length,checkedSubscriptions:n.length,failedPayments:s.failed,failedSubscriptions:i.failed,updatedPayments:s.updated,updatedSubscriptions:i.updated}};export{v as reconcile};
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.mjs";
2
2
  /**
3
3
  * The `autumn-js` SDK surface the adapter uses, as a structural type — a real `Autumn` instance
4
4
  * satisfies it without a cast. Resources/methods are `unknown` (the adapter re-types the client as
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.js";
2
2
  /**
3
3
  * The `autumn-js` SDK surface the adapter uses, as a structural type — a real `Autumn` instance
4
4
  * satisfies it without a cast. Resources/methods are `unknown` (the adapter re-types the client as
@@ -1 +1 @@
1
- import{LunoraPaymentError as C}from"../packem_shared/LunoraPaymentError-35kSImFc.mjs";import{a as u,c as o,d as s,e as l,r as D}from"../packem_shared/json-D85Nbd92.mjs";import{money as A}from"../packem_shared/addMoney-JN0UrVXA.mjs";import{verifyStandardWebhook as B}from"../packem_shared/constantTimeEqual-DG_4PS78.mjs";import{e as j}from"../packem_shared/not-supported-Cqa8vy-R.mjs";import{i as E}from"../packem_shared/subscription-event-BosLshSM.mjs";const h={active:"active",canceled:"canceled",expired:"canceled",past_due:"past_due",scheduled:"paused",trialing:"trialing"},$={activated:"active",canceled:"canceled",cancelled:"canceled",expired:"canceled",scheduled:"paused"},b="::",y=j("autumn"),f=(a,c)=>`${a}${b}${c}`,v=a=>{const c=a.lastIndexOf(b);if(c===-1)throw new C("PROVIDER_ERROR",`malformed autumn subscription id "${a}" (expected "<customerId>::<productId>")`);return{customerId:a.slice(0,c),productId:a.slice(c+b.length)}},P=a=>s(a,"canceled_at","canceledAt")!==void 0||o(a,"status")==="scheduled",k=(a,c)=>{const r=Date.now(),e=o(c,"id","product_id","productId","plan_id","planId")??"",d=o(c,"status")??"active",t=l(c,"past_due")??l(c,"pastDue")??!1;return{cancelAtPeriodEnd:P(c),createdAt:r,currentPeriodEnd:s(c,"current_period_end","currentPeriodEnd")??void 0,currentPeriodStart:s(c,"current_period_start","currentPeriodStart")??void 0,id:f(a,e),priceId:e,provider:"autumn",quantity:s(c,"quantity")??1,referenceId:a,state:t?"past_due":h[d]??"past_due",updatedAt:r}},w=a=>Array.isArray(a)?a.map(c=>u(c)):[],x=(a,c)=>[...w(a.products),...w(a.subscriptions)].find(r=>(o(r,"id","product_id","productId","plan_id","planId")??"")===c),S=a=>({balance:s(a,"remaining","balance"),limit:s(a,"granted","included_usage","limit"),unlimited:l(a,"unlimited")??!1,used:s(a,"usage","used")}),O=(a,c,r,e)=>{const d=Date.now();return{cancelAtPeriodEnd:e,createdAt:d,id:f(a,c),priceId:c,provider:"autumn",quantity:1,referenceId:a,state:r,updatedAt:d}},g=async(a,c,r)=>{const e=u(await a.customers.get({customerId:c})),d=x(e,r);return d?k(c,d):O(c,r,"canceled",!1)},I=a=>o(a,"customer_id","customerId"),M=(a,c)=>{const r={eventId:a,provider:"autumn",raw:{object:c,type:"billing.updated"}},e=I(c),d=w(c.plan_changes)[0]??c,t=d.subscription?u(d.subscription):d,n=o(t,"plan_id","planId","product_id","productId","id"),i=o(t,"status"),m=o(d,"action"),p=l(t,"past_due")??l(t,"pastDue")??!1,_=i===void 0?void 0:h[i],q=m===void 0?void 0:$[m],R=p?"past_due":_??q;return{...r,cancelAtPeriodEnd:l(t,"cancel_at_period_end")??P(t),currentPeriodEnd:s(t,"current_period_end","currentPeriodEnd"),currentPeriodStart:s(t,"current_period_start","currentPeriodStart"),customerId:e,priceId:n,referenceId:e,subscriptionId:e===void 0||n===void 0?void 0:f(e,n),type:E(R)}},N=(a,c,r)=>{const e={eventId:a,provider:"autumn",raw:{object:r,type:c}},d=o(r,"currency")??"usd";switch(c){case"billing.auto_topup_succeeded":{const t=u(r.invoice),n=s(t,"total","amount")??s(r,"total","amount"),i=o(t,"currency")??d;return{...e,amount:n===void 0?void 0:A(BigInt(Math.round(n)),i),customerId:I(r),referenceId:I(r),sessionId:o(t,"id","stripe_id","invoice_id")??o(r,"id"),type:"payment.captured"}}case"billing.updated":return M(a,r);case"customer.product.added":case"customer.product.canceled":case"customer.product.expired":case"customer.product.updated":case"product.attached":{const t=r.product?u(r.product):r,n=c==="customer.product.canceled"||c==="customer.product.expired"?"canceled":o(t,"status"),i=I(r)??I(t);return{...e,cancelAtPeriodEnd:l(t,"cancel_at_period_end")??P(t),currentPeriodEnd:s(t,"current_period_end","currentPeriodEnd"),currentPeriodStart:s(t,"current_period_start","currentPeriodStart"),customerId:i,priceId:o(t,"id","product_id","productId"),referenceId:i,subscriptionId:i===void 0?void 0:f(i,o(t,"id","product_id","productId")??""),type:E(h[n??""])}}case"invoice.paid":case"payment.succeeded":{const t=s(r,"total","amount","amount_paid");return{...e,amount:t===void 0?void 0:A(BigInt(Math.round(t)),d),customerId:I(r),referenceId:I(r),sessionId:o(r,"id","invoice_id","stripe_id"),type:"payment.captured"}}default:return{...e,type:"unhandled"}}},T=a=>o(a,"checkout_url","checkoutUrl","payment_url","paymentUrl","url")??"",z=a=>{const{webhookSecret:c}=a,r=a.client;return{cancelPayment:()=>y("manual payment cancellation"),cancelSubscription:async(e,d)=>{const{customerId:t,productId:n}=v(e);return await r.billing.update({cancelAction:d?.atPeriodEnd?"cancel_end_of_cycle":"cancel_immediately",customerId:t,planId:n}),d?.atPeriodEnd?{...await g(r,t,n),cancelAtPeriodEnd:!0}:O(t,n,"canceled",!1)},capabilities:{merchantOfRecord:!1,portal:!0,usageMetering:!0},capturePayment:e=>y("manual capture"),checkEntitlement:async e=>{if(e.featureId===void 0){const m=u(await r.customers.get({customerId:e.referenceId})),p=x(m,e.priceId??""),_=p?k(e.referenceId,p).state:void 0;return{allowed:_==="active"||_==="trialing",unlimited:!1}}const d=u(await r.check({customerId:e.referenceId,featureId:e.featureId,requiredBalance:e.quantity??1})),t=l(d,"allowed")??!1,n=d.balance,i=typeof n=="object"&&n!==null?u(n):d;return{allowed:t,...S(i)}},createCheckout:async e=>{const d=u(await r.billing.attach({customerId:e.referenceId,planId:e.priceId}));return{id:f(e.referenceId,e.priceId),provider:"autumn",url:T(d)}},createPortalSession:async e=>{const d=u(await r.billing.openCustomerPortal({customerId:e.customerId}));return{url:o(d,"url")??""}},getBalances:async e=>{const d=u(await r.customers.get({customerId:e})),t=u(d.balances??d.features);return Object.entries(t).map(([n,i])=>{const m=u(i),p=S(m);return{allowed:p.unlimited||(p.balance??0)>0,featureId:o(m,"featureId","feature_id")??n,...p}})},getOrCreateCustomer:async e=>{const d=u(await r.customers.getOrCreate({customerId:e.referenceId,email:e.email,name:e.metadata?.name}));return{createdAt:Date.now(),email:o(d,"email")??e.email,id:o(d,"id")??e.referenceId,provider:"autumn",referenceId:e.referenceId}},getPaymentStatus:()=>y("payment-session reconciliation"),getSubscriptionStatus:async e=>{const{customerId:d,productId:t}=v(e);return g(r,d,t)},identifier:"autumn",parseWebhook:async({headers:e,payload:d})=>{const t=e.get("svix-id")??e.get("webhook-id")??"";await B({payload:d,secret:c,toleranceSeconds:a.webhookToleranceSeconds,webhookId:t,webhookSignature:e.get("svix-signature")??e.get("webhook-signature")??"",webhookTimestamp:e.get("svix-timestamp")??e.get("webhook-timestamp")??""});const n=u(JSON.parse(d));return N(t,D(n,"type")??"",u(n.data))},refundPayment:()=>y("refunds"),reportUsage:async e=>{await r.track({customerId:e.referenceId,featureId:e.featureId,value:e.quantity})},resumeSubscription:async e=>{const{customerId:d,productId:t}=v(e);return await r.billing.update({cancelAction:"uncancel",customerId:d,planId:t}),{...await g(r,d,t),cancelAtPeriodEnd:!1}},updateSubscription:async(e,d)=>{const{customerId:t,productId:n}=v(e),i=d.priceId??n;return await r.billing.attach({customerId:t,planId:i}),g(r,t,i)}}};export{z as createAutumnAdapter};
1
+ import{LunoraPaymentError as C}from"../packem_shared/LunoraPaymentError-C8uAUIzQ.mjs";import{a as u,c as o,d as s,e as l,r as D}from"../packem_shared/json-D85Nbd92.mjs";import{money as A}from"../packem_shared/addMoney-BKfsSf0H.mjs";import{verifyStandardWebhook as B}from"../packem_shared/constantTimeEqual-B4DP75aY.mjs";import{e as $}from"../packem_shared/not-supported-BBbwyP_u.mjs";import{i as E}from"../packem_shared/subscription-event-BosLshSM.mjs";const h={active:"active",canceled:"canceled",expired:"canceled",past_due:"past_due",scheduled:"paused",trialing:"trialing"},j={activated:"active",canceled:"canceled",cancelled:"canceled",expired:"canceled",scheduled:"paused"},b="::",y=$("autumn"),f=(a,c)=>`${a}${b}${c}`,v=a=>{const c=a.lastIndexOf(b);if(c===-1)throw new C("PROVIDER_ERROR",`malformed autumn subscription id "${a}" (expected "<customerId>::<productId>")`);return{customerId:a.slice(0,c),productId:a.slice(c+b.length)}},P=a=>s(a,"canceled_at","canceledAt")!==void 0||o(a,"status")==="scheduled",k=(a,c)=>{const r=Date.now(),e=o(c,"id","product_id","productId","plan_id","planId")??"",d=o(c,"status")??"active",t=l(c,"past_due")??l(c,"pastDue")??!1;return{cancelAtPeriodEnd:P(c),createdAt:r,currentPeriodEnd:s(c,"current_period_end","currentPeriodEnd")??void 0,currentPeriodStart:s(c,"current_period_start","currentPeriodStart")??void 0,id:f(a,e),priceId:e,provider:"autumn",quantity:s(c,"quantity")??1,referenceId:a,state:t?"past_due":h[d]??"past_due",updatedAt:r}},w=a=>Array.isArray(a)?a.map(c=>u(c)):[],x=(a,c)=>[...w(a.products),...w(a.subscriptions)].find(r=>(o(r,"id","product_id","productId","plan_id","planId")??"")===c),S=a=>({balance:s(a,"remaining","balance"),limit:s(a,"granted","included_usage","limit"),unlimited:l(a,"unlimited")??!1,used:s(a,"usage","used")}),O=(a,c,r,e)=>{const d=Date.now();return{cancelAtPeriodEnd:e,createdAt:d,id:f(a,c),priceId:c,provider:"autumn",quantity:1,referenceId:a,state:r,updatedAt:d}},g=async(a,c,r)=>{const e=u(await a.customers.get({customerId:c})),d=x(e,r);return d?k(c,d):O(c,r,"canceled",!1)},I=a=>o(a,"customer_id","customerId"),N=(a,c)=>{const r={eventId:a,provider:"autumn",raw:{object:c,type:"billing.updated"}},e=I(c),d=w(c.plan_changes)[0]??c,t=d.subscription?u(d.subscription):d,n=o(t,"plan_id","planId","product_id","productId","id"),i=o(t,"status"),m=o(d,"action"),p=l(t,"past_due")??l(t,"pastDue")??!1,_=i===void 0?void 0:h[i],q=m===void 0?void 0:j[m],R=p?"past_due":_??q;return{...r,cancelAtPeriodEnd:l(t,"cancel_at_period_end")??P(t),currentPeriodEnd:s(t,"current_period_end","currentPeriodEnd"),currentPeriodStart:s(t,"current_period_start","currentPeriodStart"),customerId:e,priceId:n,referenceId:e,subscriptionId:e===void 0||n===void 0?void 0:f(e,n),type:E(R)}},M=(a,c,r)=>{const e={eventId:a,provider:"autumn",raw:{object:r,type:c}},d=o(r,"currency")??"usd";switch(c){case"billing.auto_topup_succeeded":{const t=u(r.invoice),n=s(t,"total","amount")??s(r,"total","amount"),i=o(t,"currency")??d;return{...e,amount:n===void 0?void 0:A(BigInt(Math.round(n)),i),customerId:I(r),referenceId:I(r),sessionId:o(t,"id","stripe_id","invoice_id")??o(r,"id"),type:"payment.captured"}}case"billing.updated":return N(a,r);case"customer.product.added":case"customer.product.canceled":case"customer.product.expired":case"customer.product.updated":case"product.attached":{const t=r.product?u(r.product):r,n=c==="customer.product.canceled"||c==="customer.product.expired"?"canceled":o(t,"status"),i=I(r)??I(t);return{...e,cancelAtPeriodEnd:l(t,"cancel_at_period_end")??P(t),currentPeriodEnd:s(t,"current_period_end","currentPeriodEnd"),currentPeriodStart:s(t,"current_period_start","currentPeriodStart"),customerId:i,priceId:o(t,"id","product_id","productId"),referenceId:i,subscriptionId:i===void 0?void 0:f(i,o(t,"id","product_id","productId")??""),type:E(h[n??""])}}case"invoice.paid":case"payment.succeeded":{const t=s(r,"total","amount","amount_paid");return{...e,amount:t===void 0?void 0:A(BigInt(Math.round(t)),d),customerId:I(r),referenceId:I(r),sessionId:o(r,"id","invoice_id","stripe_id"),type:"payment.captured"}}default:return{...e,type:"unhandled"}}},T=a=>o(a,"checkout_url","checkoutUrl","payment_url","paymentUrl","url")??"",z=a=>{const{webhookSecret:c}=a,r=a.client;return{cancelPayment:()=>y("manual payment cancellation"),cancelSubscription:async(e,d)=>{const{customerId:t,productId:n}=v(e);return await r.billing.update({cancelAction:d?.atPeriodEnd?"cancel_end_of_cycle":"cancel_immediately",customerId:t,planId:n}),d?.atPeriodEnd?{...await g(r,t,n),cancelAtPeriodEnd:!0}:O(t,n,"canceled",!1)},capabilities:{merchantOfRecord:!1,portal:!0,usageMetering:!0},capturePayment:e=>y("manual capture"),checkEntitlement:async e=>{if(e.featureId===void 0){const m=u(await r.customers.get({customerId:e.referenceId})),p=x(m,e.priceId??""),_=p?k(e.referenceId,p).state:void 0;return{allowed:_==="active"||_==="trialing",unlimited:!1}}const d=u(await r.check({customerId:e.referenceId,featureId:e.featureId,requiredBalance:e.quantity??1})),t=l(d,"allowed")??!1,n=d.balance,i=typeof n=="object"&&n!==null?u(n):d;return{allowed:t,...S(i)}},createCheckout:async e=>{const d=u(await r.billing.attach({customerId:e.referenceId,planId:e.priceId}));return{id:f(e.referenceId,e.priceId),provider:"autumn",url:T(d)}},createPortalSession:async e=>{const d=u(await r.billing.openCustomerPortal({customerId:e.customerId}));return{url:o(d,"url")??""}},getBalances:async e=>{const d=u(await r.customers.get({customerId:e})),t=u(d.balances??d.features);return Object.entries(t).map(([n,i])=>{const m=u(i),p=S(m);return{allowed:p.unlimited||(p.balance??0)>0,featureId:o(m,"featureId","feature_id")??n,...p}})},getOrCreateCustomer:async e=>{const d=u(await r.customers.getOrCreate({customerId:e.referenceId,email:e.email,name:e.metadata?.name}));return{createdAt:Date.now(),email:o(d,"email")??e.email,id:o(d,"id")??e.referenceId,provider:"autumn",referenceId:e.referenceId}},getPaymentStatus:()=>y("payment-session reconciliation"),getSubscriptionStatus:async e=>{const{customerId:d,productId:t}=v(e);return g(r,d,t)},identifier:"autumn",parseWebhook:async({headers:e,payload:d})=>{const t=e.get("svix-id")??e.get("webhook-id")??"";await B({payload:d,secret:c,toleranceSeconds:a.webhookToleranceSeconds,webhookId:t,webhookSignature:e.get("svix-signature")??e.get("webhook-signature")??"",webhookTimestamp:e.get("svix-timestamp")??e.get("webhook-timestamp")??""});const n=u(JSON.parse(d));return M(t,D(n,"type")??"",u(n.data))},refundPayment:()=>y("refunds"),reportUsage:async e=>{await r.track({customerId:e.referenceId,featureId:e.featureId,value:e.quantity})},resumeSubscription:async e=>{const{customerId:d,productId:t}=v(e);return await r.billing.update({cancelAction:"uncancel",customerId:d,planId:t}),{...await g(r,d,t),cancelAtPeriodEnd:!1}},updateSubscription:async(e,d)=>{const{customerId:t,productId:n}=v(e),i=d.priceId??n;return await r.billing.attach({customerId:t,planId:i}),g(r,t,i)}}};export{z as createAutumnAdapter};
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.mjs";
2
2
  /**
3
3
  * The `creem` SDK surface the adapter uses, as a structural type — a real `Creem` instance satisfies
4
4
  * it without a cast. Resources are `unknown` (the adapter re-types the client as the real `Creem`
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.js";
2
2
  /**
3
3
  * The `creem` SDK surface the adapter uses, as a structural type — a real `Creem` instance satisfies
4
4
  * it without a cast. Resources are `unknown` (the adapter re-types the client as the real `Creem`
@@ -1 +1 @@
1
- import{a as o,c as u,f as p,r as n,b as m,p as f,e as v,d as w}from"../packem_shared/json-D85Nbd92.mjs";import{money as I,zeroMoney as b}from"../packem_shared/addMoney-JN0UrVXA.mjs";import{verifyCreemSignature as P}from"../packem_shared/constantTimeEqual-DG_4PS78.mjs";import{e as S}from"../packem_shared/not-supported-Cqa8vy-R.mjs";import{i as A}from"../packem_shared/subscription-event-BosLshSM.mjs";const k=/already exists/iu,E={canceled:"canceled",completed:"captured",expired:"canceled",paid:"captured",partially_refunded:"partially_refunded",pending:"initiated",refunded:"refunded"},_={active:"active",canceled:"canceled",cancelled:"canceled",expired:"canceled",incomplete:"past_due",paid:"active",past_due:"past_due",paused:"paused",scheduled_cancel:"active",trialing:"trialing",unpaid:"past_due"},y=S("creem (merchant-of-record)"),s=c=>typeof c=="string"?c:n(o(c),"id"),C=c=>u(c,"checkout_url","checkoutUrl")??"",g=c=>u(c,"canceled_at","canceledAt")!==void 0||n(c,"status")==="scheduled_cancel",D=c=>{if(!(c instanceof Error))return!1;const{statusCode:t}=c;return typeof t=="number"&&t!==400&&t!==409?!1:k.test(c.message)},l=c=>{const t=o(c),r=Date.now(),e=n(t,"status")??"";return{cancelAtPeriodEnd:g(t),createdAt:r,currentPeriodEnd:f(u(t,"current_period_end_date","currentPeriodEndDate")),currentPeriodStart:f(u(t,"current_period_start_date","currentPeriodStartDate")),id:n(t,"id")??"",priceId:s(t.product)??"",provider:"creem",quantity:m(t,"units")??1,referenceId:p(t)??s(t.customer)??"",state:_[e]??"past_due",updatedAt:r}},x=c=>{const t=o(c),r=Date.now(),e=o(t.order),a=n(e,"currency")??n(t,"currency")??"usd",d=I(BigInt(Math.round(m(e,"amount")??m(t,"amount")??0)),a),i=E[n(e,"status")??n(t,"status")??""]??"initiated";return{amount:d,capturedAmount:i==="captured"||i==="partially_refunded"||i==="refunded"?d:b(a),createdAt:r,id:n(t,"id")??"",provider:"creem",referenceId:p(t)??"",refundedAmount:i==="refunded"?d:b(a),state:i,updatedAt:r}},B=(c,t,r)=>{const e={eventId:c,provider:"creem",raw:{object:r,type:t}},a=o(r.order),d=n(a,"currency")??n(r,"currency")??"usd";switch(t){case"checkout.completed":{const i=m(a,"amount")??m(r,"amount");return{...e,amount:i===void 0?void 0:I(BigInt(Math.round(i)),d),customerId:s(r.customer),referenceId:p(r),sessionId:n(r,"id"),subscriptionId:s(r.subscription),type:"payment.captured"}}case"refund.created":{const i=w(r,"refund_amount","refundAmount","amount")??m(a,"amount"),h=u(r,"refund_currency","refundCurrency")??d;return{...e,amount:i===void 0?void 0:I(BigInt(Math.round(i)),h),referenceId:p(r),sessionId:s(r.transaction)??s(r.subscription)??s(r.order)??s(r.checkout)??n(r,"id"),type:"payment.refunded"}}case"subscription.active":case"subscription.canceled":case"subscription.expired":case"subscription.paid":case"subscription.past_due":case"subscription.paused":case"subscription.scheduled_cancel":case"subscription.trialing":case"subscription.unpaid":case"subscription.update":{const i=t==="subscription.scheduled_cancel"?"scheduled_cancel":n(r,"status");return{...e,cancelAtPeriodEnd:v(r,"cancel_at_period_end")??g(r),currentPeriodEnd:f(u(r,"current_period_end_date","currentPeriodEndDate")),currentPeriodStart:f(u(r,"current_period_start_date","currentPeriodStartDate")),customerId:s(r.customer),priceId:s(r.product),referenceId:p(r)??s(r.customer),subscriptionId:n(r,"id"),type:A(_[i??""])}}default:return{...e,type:"unhandled"}}},T=c=>{const{webhookSecret:t}=c,r=c.client;return{cancelPayment:()=>y("manual payment cancellation"),cancelSubscription:async(e,a)=>l(await r.subscriptions.cancel(e,{mode:a?.atPeriodEnd===!0?"scheduled":"immediate"})),capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!1},capturePayment:e=>y("manual capture"),createCheckout:async e=>{const a=await r.checkouts.create({customer:e.customerId?{id:e.customerId}:void 0,metadata:{...e.metadata,referenceId:e.referenceId},productId:e.priceId,requestId:e.idempotencyKey,successUrl:e.successUrl,units:e.quantity});return{id:n(a,"id")??"",provider:"creem",url:C(a)}},createPortalSession:async e=>{const a=await r.customers.generateBillingLinks({customerId:e.customerId});return{url:u(a,"customer_portal_link","customerPortalLink")??""}},getOrCreateCustomer:async e=>{const a=d=>({createdAt:Date.now(),email:n(d,"email")??e.email,id:n(d,"id")??"",provider:"creem",referenceId:e.referenceId});try{return a(o(await r.customers.create({email:e.email??"",metadata:{...e.metadata,referenceId:e.referenceId},name:e.metadata?.name??e.referenceId})))}catch(d){if(e.email!==void 0&&D(d)){const i=o(await r.customers.retrieve(void 0,e.email));if(p(i)!==e.referenceId)throw new Error(`Creem customer for email "${e.email}" already belongs to a different reference; refusing to bind it to "${e.referenceId}".`,{cause:d});return a(i)}throw d}},getPaymentStatus:async e=>x(await r.checkouts.retrieve(e)),getSubscriptionStatus:async e=>l(await r.subscriptions.get(e)),identifier:"creem",parseWebhook:async({headers:e,payload:a})=>{await P({payload:a,secret:t,signature:e.get("creem-signature")??""});const d=o(JSON.parse(a));return B(u(d,"id","event_id","eventId")??"",u(d,"eventType","type")??"",o(d.object))},refundPayment:()=>y("programmatic refunds"),resumeSubscription:async e=>l(await r.subscriptions.resume(e)),updateSubscription:async(e,a)=>a.priceId?l(await r.subscriptions.upgrade(e,{productId:a.priceId,updateBehavior:"proration-charge-immediately"})):l(await r.subscriptions.get(e))}};export{T as createCreemAdapter};
1
+ import{a as o,c as u,f as p,r as n,b as m,p as f,e as v,d as w}from"../packem_shared/json-D85Nbd92.mjs";import{money as I,zeroMoney as b}from"../packem_shared/addMoney-BKfsSf0H.mjs";import{verifyCreemSignature as P}from"../packem_shared/constantTimeEqual-B4DP75aY.mjs";import{e as S}from"../packem_shared/not-supported-BBbwyP_u.mjs";import{i as A}from"../packem_shared/subscription-event-BosLshSM.mjs";const k=/already exists/iu,E={canceled:"canceled",completed:"captured",expired:"canceled",paid:"captured",partially_refunded:"partially_refunded",pending:"initiated",refunded:"refunded"},_={active:"active",canceled:"canceled",cancelled:"canceled",expired:"canceled",incomplete:"past_due",paid:"active",past_due:"past_due",paused:"paused",scheduled_cancel:"active",trialing:"trialing",unpaid:"past_due"},y=S("creem (merchant-of-record)"),s=c=>typeof c=="string"?c:n(o(c),"id"),C=c=>u(c,"checkout_url","checkoutUrl")??"",g=c=>u(c,"canceled_at","canceledAt")!==void 0||n(c,"status")==="scheduled_cancel",D=c=>{if(!(c instanceof Error))return!1;const{statusCode:t}=c;return typeof t=="number"&&t!==400&&t!==409?!1:k.test(c.message)},l=c=>{const t=o(c),r=Date.now(),e=n(t,"status")??"";return{cancelAtPeriodEnd:g(t),createdAt:r,currentPeriodEnd:f(u(t,"current_period_end_date","currentPeriodEndDate")),currentPeriodStart:f(u(t,"current_period_start_date","currentPeriodStartDate")),id:n(t,"id")??"",priceId:s(t.product)??"",provider:"creem",quantity:m(t,"units")??1,referenceId:p(t)??s(t.customer)??"",state:_[e]??"past_due",updatedAt:r}},x=c=>{const t=o(c),r=Date.now(),e=o(t.order),a=n(e,"currency")??n(t,"currency")??"usd",d=I(BigInt(Math.round(m(e,"amount")??m(t,"amount")??0)),a),i=E[n(e,"status")??n(t,"status")??""]??"initiated";return{amount:d,capturedAmount:i==="captured"||i==="partially_refunded"||i==="refunded"?d:b(a),createdAt:r,id:n(t,"id")??"",provider:"creem",referenceId:p(t)??"",refundedAmount:i==="refunded"?d:b(a),state:i,updatedAt:r}},B=(c,t,r)=>{const e={eventId:c,provider:"creem",raw:{object:r,type:t}},a=o(r.order),d=n(a,"currency")??n(r,"currency")??"usd";switch(t){case"checkout.completed":{const i=m(a,"amount")??m(r,"amount");return{...e,amount:i===void 0?void 0:I(BigInt(Math.round(i)),d),customerId:s(r.customer),referenceId:p(r),sessionId:n(r,"id"),subscriptionId:s(r.subscription),type:"payment.captured"}}case"refund.created":{const i=w(r,"refund_amount","refundAmount","amount")??m(a,"amount"),h=u(r,"refund_currency","refundCurrency")??d;return{...e,amount:i===void 0?void 0:I(BigInt(Math.round(i)),h),referenceId:p(r),sessionId:s(r.transaction)??s(r.subscription)??s(r.order)??s(r.checkout)??n(r,"id"),type:"payment.refunded"}}case"subscription.active":case"subscription.canceled":case"subscription.expired":case"subscription.paid":case"subscription.past_due":case"subscription.paused":case"subscription.scheduled_cancel":case"subscription.trialing":case"subscription.unpaid":case"subscription.update":{const i=t==="subscription.scheduled_cancel"?"scheduled_cancel":n(r,"status");return{...e,cancelAtPeriodEnd:v(r,"cancel_at_period_end")??g(r),currentPeriodEnd:f(u(r,"current_period_end_date","currentPeriodEndDate")),currentPeriodStart:f(u(r,"current_period_start_date","currentPeriodStartDate")),customerId:s(r.customer),priceId:s(r.product),referenceId:p(r)??s(r.customer),subscriptionId:n(r,"id"),type:A(_[i??""])}}default:return{...e,type:"unhandled"}}},T=c=>{const{webhookSecret:t}=c,r=c.client;return{cancelPayment:()=>y("manual payment cancellation"),cancelSubscription:async(e,a)=>l(await r.subscriptions.cancel(e,{mode:a?.atPeriodEnd===!0?"scheduled":"immediate"})),capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!1},capturePayment:e=>y("manual capture"),createCheckout:async e=>{const a=await r.checkouts.create({customer:e.customerId?{id:e.customerId}:void 0,metadata:{...e.metadata,referenceId:e.referenceId},productId:e.priceId,requestId:e.idempotencyKey,successUrl:e.successUrl,units:e.quantity});return{id:n(a,"id")??"",provider:"creem",url:C(a)}},createPortalSession:async e=>{const a=await r.customers.generateBillingLinks({customerId:e.customerId});return{url:u(a,"customer_portal_link","customerPortalLink")??""}},getOrCreateCustomer:async e=>{const a=d=>({createdAt:Date.now(),email:n(d,"email")??e.email,id:n(d,"id")??"",provider:"creem",referenceId:e.referenceId});try{return a(o(await r.customers.create({email:e.email??"",metadata:{...e.metadata,referenceId:e.referenceId},name:e.metadata?.name??e.referenceId})))}catch(d){if(e.email!==void 0&&D(d)){const i=o(await r.customers.retrieve(void 0,e.email));if(p(i)!==e.referenceId)throw new Error(`Creem customer for email "${e.email}" already belongs to a different reference; refusing to bind it to "${e.referenceId}".`,{cause:d});return a(i)}throw d}},getPaymentStatus:async e=>x(await r.checkouts.retrieve(e)),getSubscriptionStatus:async e=>l(await r.subscriptions.get(e)),identifier:"creem",parseWebhook:async({headers:e,payload:a})=>{await P({payload:a,secret:t,signature:e.get("creem-signature")??""});const d=o(JSON.parse(a));return B(u(d,"id","event_id","eventId")??"",u(d,"eventType","type")??"",o(d.object))},refundPayment:()=>y("programmatic refunds"),resumeSubscription:async e=>l(await r.subscriptions.resume(e)),updateSubscription:async(e,a)=>a.priceId?l(await r.subscriptions.upgrade(e,{productId:a.priceId,updateBehavior:"proration-charge-immediately"})):l(await r.subscriptions.get(e))}};export{T as createCreemAdapter};
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.mjs";
2
2
  /**
3
3
  * The `dodopayments` SDK surface the adapter uses, as a structural type — a real `DodoPayments`
4
4
  * instance satisfies it without a cast. Resources are `unknown` (the adapter re-types the client as
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.js";
2
2
  /**
3
3
  * The `dodopayments` SDK surface the adapter uses, as a structural type — a real `DodoPayments`
4
4
  * instance satisfies it without a cast. Resources are `unknown` (the adapter re-types the client as
@@ -1 +1 @@
1
- import{LunoraPaymentError as g}from"../packem_shared/LunoraPaymentError-35kSImFc.mjs";import{idempotencyKey as v}from"../packem_shared/idempotencyKey-CfJKqcE3.mjs";import{a as o,b as s,r,f as u,p as l,e as I}from"../packem_shared/json-D85Nbd92.mjs";import{money as y,zeroMoney as f}from"../packem_shared/addMoney-JN0UrVXA.mjs";import{verifyStandardWebhook as w}from"../packem_shared/constantTimeEqual-DG_4PS78.mjs";import{e as S}from"../packem_shared/not-supported-Cqa8vy-R.mjs";import{i as q}from"../packem_shared/subscription-event-BosLshSM.mjs";const P={cancelled:"canceled",failed:"failed",partially_captured:"captured",partially_captured_and_capturable:"captured",processing:"initiated",requires_capture:"authorized",requires_confirmation:"initiated",requires_customer_action:"authorized",requires_merchant_action:"authorized",requires_payment_method:"initiated",succeeded:"captured"},h={active:"active",cancelled:"canceled",expired:"canceled",failed:"past_due",on_hold:"past_due",paused:"paused",pending:"past_due"},b=S("dodopayments (merchant-of-record)"),m=d=>r(o(d.customer),"customer_id")??r(d,"customer_id"),p=d=>{const n=o(d),t=Date.now(),e=r(n,"status")??"";return{cancelAtPeriodEnd:I(n,"cancel_at_next_billing_date")??!1,createdAt:t,currentPeriodEnd:l(r(n,"next_billing_date")),currentPeriodStart:l(r(n,"previous_billing_date")),id:r(n,"subscription_id")??"",priceId:r(n,"product_id")??"",provider:"dodopayments",quantity:s(n,"quantity")??1,referenceId:u(n)??m(n)??"",state:h[e]??"past_due",updatedAt:t}},A=d=>{const n=o(d),t=Date.now(),e=r(n,"currency")??"usd",a=y(BigInt(Math.round(s(n,"total_amount")??0)),e),i=P[r(n,"status")??""]??"initiated";return{amount:a,capturedAmount:i==="captured"?a:f(e),createdAt:t,id:r(n,"payment_id")??"",provider:"dodopayments",referenceId:u(n)??"",refundedAmount:f(e),state:i,updatedAt:t}},k=(d,n,t)=>{const e={eventId:d,provider:"dodopayments",raw:{object:t,type:n}},a=r(t,"currency")??"usd";switch(n){case"dispute.lost":case"refund.succeeded":return{...e,amount:y(BigInt(Math.round(s(t,"amount")??0)),a),referenceId:u(t),sessionId:r(t,"payment_id"),type:"payment.refunded"};case"payment.cancelled":case"payment.failed":return{...e,referenceId:u(t),sessionId:r(t,"payment_id"),type:"payment.failed"};case"payment.succeeded":return{...e,amount:y(BigInt(Math.round(s(t,"total_amount")??0)),a),customerId:m(t),referenceId:u(t),sessionId:r(t,"payment_id"),subscriptionId:r(t,"subscription_id"),type:"payment.captured"};case"subscription.active":case"subscription.cancelled":case"subscription.expired":case"subscription.failed":case"subscription.on_hold":case"subscription.paused":case"subscription.plan_changed":case"subscription.renewed":case"subscription.updated":{const i=r(t,"status");return{...e,cancelAtPeriodEnd:I(t,"cancel_at_next_billing_date"),currentPeriodEnd:l(r(t,"next_billing_date")),currentPeriodStart:l(r(t,"previous_billing_date")),customerId:m(t),priceId:r(t,"product_id"),quantity:s(t,"quantity"),referenceId:u(t)??m(t),subscriptionId:r(t,"subscription_id"),type:q(h[i??""])}}default:return{...e,type:"unhandled"}}},z=d=>{const{webhookSecret:n}=d,t=d.client;return{cancelPayment:()=>b("manual payment cancellation"),cancelSubscription:async(e,a)=>{const i=a?.atPeriodEnd?{cancel_at_next_billing_date:!0}:{status:"cancelled"};return p(await t.subscriptions.update(e,i))},capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!0},capturePayment:e=>b("manual capture"),createCheckout:async e=>{const a=o(await t.checkoutSessions.create({customer:e.customerId?{customer_id:e.customerId}:void 0,metadata:{...e.metadata,referenceId:e.referenceId},product_cart:[{product_id:e.priceId,quantity:e.quantity??1}],return_url:e.successUrl}));return{id:r(a,"session_id")??"",provider:"dodopayments",url:r(a,"checkout_url")??""}},createPortalSession:async e=>{const a=o(await t.customers.customerPortal.create(e.customerId,{return_url:e.returnUrl}));return{url:r(a,"link")??r(a,"url")??""}},getOrCreateCustomer:async e=>{const a=o(await t.customers.create({email:e.email??"",name:e.metadata?.name??e.referenceId},{idempotencyKey:v("customer","dodopayments",e.referenceId)}));return{createdAt:Date.now(),email:r(a,"email")??e.email,id:r(a,"customer_id")??"",provider:"dodopayments",referenceId:e.referenceId}},getPaymentStatus:async e=>A(await t.payments.retrieve(e)),getSubscriptionStatus:async e=>p(await t.subscriptions.retrieve(e)),identifier:"dodopayments",parseWebhook:async({headers:e,payload:a})=>{const i=e.get("webhook-id")??"";await w({payload:a,secret:n,toleranceSeconds:d.webhookToleranceSeconds,webhookId:i,webhookSignature:e.get("webhook-signature")??"",webhookTimestamp:e.get("webhook-timestamp")??""});const c=o(JSON.parse(a));return k(i,r(c,"type")??"",o(c.data))},refundPayment:async e=>{if(e.amount!==void 0)throw new g("PROVIDER_ERROR","dodopayments refunds a payment in full; partial refunds require line items and aren't supported here");const a=o(await t.refunds.create({payment_id:e.sessionId,reason:e.reason})),i=r(a,"currency")??"usd",c=y(BigInt(Math.round(s(a,"amount")??0)),i);let _="captured";return r(a,"status")==="succeeded"&&(_="refunded"),{amount:c,capturedAmount:c,createdAt:Date.now(),id:e.sessionId,provider:"dodopayments",referenceId:"",refundedAmount:c,state:_,updatedAt:Date.now()}},reportUsage:async e=>{await t.usageEvents.ingest({events:[{customer_id:e.customerId??e.referenceId,event_id:e.idempotencyKey,event_name:e.featureId,metadata:{value:e.quantity},timestamp:e.timestamp===void 0?void 0:new Date(e.timestamp).toISOString()}]})},resumeSubscription:async e=>{const a=await t.subscriptions.update(e,{cancel_at_next_billing_date:!1});return p(a)},updateSubscription:async(e,a)=>{if(a.priceId!==void 0||a.quantity!==void 0){const i=o(a.priceId!==void 0&&a.quantity!==void 0?void 0:await t.subscriptions.retrieve(e));await t.subscriptions.changePlan(e,{product_id:a.priceId??r(i,"product_id")??"",proration_billing_mode:"prorated_immediately",quantity:a.quantity??s(i,"quantity")??1})}return p(await t.subscriptions.retrieve(e))}}};export{z as createDodoPaymentsAdapter};
1
+ import{LunoraPaymentError as g}from"../packem_shared/LunoraPaymentError-C8uAUIzQ.mjs";import{idempotencyKey as v}from"../packem_shared/idempotencyKey-CfJKqcE3.mjs";import{a as o,b as s,r,f as u,p as l,e as I}from"../packem_shared/json-D85Nbd92.mjs";import{money as y,zeroMoney as f}from"../packem_shared/addMoney-BKfsSf0H.mjs";import{verifyStandardWebhook as w}from"../packem_shared/constantTimeEqual-B4DP75aY.mjs";import{e as S}from"../packem_shared/not-supported-BBbwyP_u.mjs";import{i as q}from"../packem_shared/subscription-event-BosLshSM.mjs";const P={cancelled:"canceled",failed:"failed",partially_captured:"captured",partially_captured_and_capturable:"captured",processing:"initiated",requires_capture:"authorized",requires_confirmation:"initiated",requires_customer_action:"authorized",requires_merchant_action:"authorized",requires_payment_method:"initiated",succeeded:"captured"},h={active:"active",cancelled:"canceled",expired:"canceled",failed:"past_due",on_hold:"past_due",paused:"paused",pending:"past_due"},b=S("dodopayments (merchant-of-record)"),m=d=>r(o(d.customer),"customer_id")??r(d,"customer_id"),p=d=>{const n=o(d),t=Date.now(),e=r(n,"status")??"";return{cancelAtPeriodEnd:I(n,"cancel_at_next_billing_date")??!1,createdAt:t,currentPeriodEnd:l(r(n,"next_billing_date")),currentPeriodStart:l(r(n,"previous_billing_date")),id:r(n,"subscription_id")??"",priceId:r(n,"product_id")??"",provider:"dodopayments",quantity:s(n,"quantity")??1,referenceId:u(n)??m(n)??"",state:h[e]??"past_due",updatedAt:t}},A=d=>{const n=o(d),t=Date.now(),e=r(n,"currency")??"usd",a=y(BigInt(Math.round(s(n,"total_amount")??0)),e),i=P[r(n,"status")??""]??"initiated";return{amount:a,capturedAmount:i==="captured"?a:f(e),createdAt:t,id:r(n,"payment_id")??"",provider:"dodopayments",referenceId:u(n)??"",refundedAmount:f(e),state:i,updatedAt:t}},k=(d,n,t)=>{const e={eventId:d,provider:"dodopayments",raw:{object:t,type:n}},a=r(t,"currency")??"usd";switch(n){case"dispute.lost":case"refund.succeeded":return{...e,amount:y(BigInt(Math.round(s(t,"amount")??0)),a),referenceId:u(t),sessionId:r(t,"payment_id"),type:"payment.refunded"};case"payment.cancelled":case"payment.failed":return{...e,referenceId:u(t),sessionId:r(t,"payment_id"),type:"payment.failed"};case"payment.succeeded":return{...e,amount:y(BigInt(Math.round(s(t,"total_amount")??0)),a),customerId:m(t),referenceId:u(t),sessionId:r(t,"payment_id"),subscriptionId:r(t,"subscription_id"),type:"payment.captured"};case"subscription.active":case"subscription.cancelled":case"subscription.expired":case"subscription.failed":case"subscription.on_hold":case"subscription.paused":case"subscription.plan_changed":case"subscription.renewed":case"subscription.updated":{const i=r(t,"status");return{...e,cancelAtPeriodEnd:I(t,"cancel_at_next_billing_date"),currentPeriodEnd:l(r(t,"next_billing_date")),currentPeriodStart:l(r(t,"previous_billing_date")),customerId:m(t),priceId:r(t,"product_id"),quantity:s(t,"quantity"),referenceId:u(t)??m(t),subscriptionId:r(t,"subscription_id"),type:q(h[i??""])}}default:return{...e,type:"unhandled"}}},z=d=>{const{webhookSecret:n}=d,t=d.client;return{cancelPayment:()=>b("manual payment cancellation"),cancelSubscription:async(e,a)=>{const i=a?.atPeriodEnd?{cancel_at_next_billing_date:!0}:{status:"cancelled"};return p(await t.subscriptions.update(e,i))},capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!0},capturePayment:e=>b("manual capture"),createCheckout:async e=>{const a=o(await t.checkoutSessions.create({customer:e.customerId?{customer_id:e.customerId}:void 0,metadata:{...e.metadata,referenceId:e.referenceId},product_cart:[{product_id:e.priceId,quantity:e.quantity??1}],return_url:e.successUrl}));return{id:r(a,"session_id")??"",provider:"dodopayments",url:r(a,"checkout_url")??""}},createPortalSession:async e=>{const a=o(await t.customers.customerPortal.create(e.customerId,{return_url:e.returnUrl}));return{url:r(a,"link")??r(a,"url")??""}},getOrCreateCustomer:async e=>{const a=o(await t.customers.create({email:e.email??"",name:e.metadata?.name??e.referenceId},{idempotencyKey:v("customer","dodopayments",e.referenceId)}));return{createdAt:Date.now(),email:r(a,"email")??e.email,id:r(a,"customer_id")??"",provider:"dodopayments",referenceId:e.referenceId}},getPaymentStatus:async e=>A(await t.payments.retrieve(e)),getSubscriptionStatus:async e=>p(await t.subscriptions.retrieve(e)),identifier:"dodopayments",parseWebhook:async({headers:e,payload:a})=>{const i=e.get("webhook-id")??"";await w({payload:a,secret:n,toleranceSeconds:d.webhookToleranceSeconds,webhookId:i,webhookSignature:e.get("webhook-signature")??"",webhookTimestamp:e.get("webhook-timestamp")??""});const c=o(JSON.parse(a));return k(i,r(c,"type")??"",o(c.data))},refundPayment:async e=>{if(e.amount!==void 0)throw new g("PROVIDER_ERROR","dodopayments refunds a payment in full; partial refunds require line items and aren't supported here");const a=o(await t.refunds.create({payment_id:e.sessionId,reason:e.reason})),i=r(a,"currency")??"usd",c=y(BigInt(Math.round(s(a,"amount")??0)),i);let _="captured";return r(a,"status")==="succeeded"&&(_="refunded"),{amount:c,capturedAmount:c,createdAt:Date.now(),id:e.sessionId,provider:"dodopayments",referenceId:"",refundedAmount:c,state:_,updatedAt:Date.now()}},reportUsage:async e=>{await t.usageEvents.ingest({events:[{customer_id:e.customerId??e.referenceId,event_id:e.idempotencyKey,event_name:e.featureId,metadata:{value:e.quantity},timestamp:e.timestamp===void 0?void 0:new Date(e.timestamp).toISOString()}]})},resumeSubscription:async e=>{const a=await t.subscriptions.update(e,{cancel_at_next_billing_date:!1});return p(a)},updateSubscription:async(e,a)=>{if(a.priceId!==void 0||a.quantity!==void 0){const i=o(a.priceId!==void 0&&a.quantity!==void 0?void 0:await t.subscriptions.retrieve(e));await t.subscriptions.changePlan(e,{product_id:a.priceId??r(i,"product_id")??"",proration_billing_mode:"prorated_immediately",quantity:a.quantity??s(i,"quantity")??1})}return p(await t.subscriptions.retrieve(e))}}};export{z as createDodoPaymentsAdapter};
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.mjs";
2
2
  /**
3
3
  * The `@polar-sh/sdk` surface the adapter uses, as a structural type — a real `Polar` instance
4
4
  * satisfies it without a cast. Resources are `unknown` (the adapter re-types the client as the real
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.js";
2
2
  /**
3
3
  * The `@polar-sh/sdk` surface the adapter uses, as a structural type — a real `Polar` instance
4
4
  * satisfies it without a cast. Resources are `unknown` (the adapter re-types the client as the real
@@ -1 +1 @@
1
- import{a as p,r as n,f as i,e as w,p as I,b as s}from"../packem_shared/json-D85Nbd92.mjs";import{money as m,zeroMoney as f}from"../packem_shared/addMoney-JN0UrVXA.mjs";import{verifyStandardWebhook as _}from"../packem_shared/constantTimeEqual-DG_4PS78.mjs";import{e as h}from"../packem_shared/not-supported-Cqa8vy-R.mjs";import{i as P}from"../packem_shared/subscription-event-BosLshSM.mjs";const y=o=>o instanceof Date?o.getTime():I(typeof o=="string"?o:void 0),v={draft:"initiated",paid:"captured",partially_refunded:"partially_refunded",pending:"initiated",refunded:"refunded",void:"canceled"},g={active:"active",canceled:"canceled",incomplete:"past_due",incomplete_expired:"canceled",past_due:"past_due",trialing:"trialing",unpaid:"past_due"},b=h("polar (merchant-of-record)"),u=o=>{const a=p(o),t=Date.now();return{cancelAtPeriodEnd:w(a,"cancelAtPeriodEnd")??!1,createdAt:t,currentPeriodEnd:y(a.currentPeriodEnd),currentPeriodStart:y(a.currentPeriodStart),id:n(a,"id")??"",priceId:n(a,"productId")??"",provider:"polar",quantity:1,referenceId:i(a)??"",state:g[n(a,"status")??""]??"active",updatedAt:t}},A=o=>{const a=p(o),t=Date.now(),e=n(a,"currency")??"usd",r=m(BigInt(Math.round(s(a,"totalAmount")??s(a,"amount")??0)),e),d=v[n(a,"status")??""]??"initiated";return{amount:r,capturedAmount:d==="captured"||d==="partially_refunded"||d==="refunded"?r:f(e),createdAt:t,id:n(a,"id")??"",provider:"polar",referenceId:i(a)??"",refundedAmount:d==="refunded"?r:f(e),state:d,updatedAt:t}},S=(o,a,t)=>{const e={eventId:o,provider:"polar",raw:{object:t,type:a}},r=n(t,"currency")??"usd";switch(a){case"order.created":case"order.paid":return a==="order.created"&&v[n(t,"status")??""]!=="captured"?{...e,type:"unhandled"}:{...e,amount:m(BigInt(s(t,"total_amount")??s(t,"amount")??0),r),customerId:n(t,"customer_id"),referenceId:i(t),sessionId:n(t,"id"),subscriptionId:n(t,"subscription_id"),type:"payment.captured"};case"refund.created":return{...e,amount:m(BigInt(s(t,"amount")??0),r),referenceId:i(t),sessionId:n(t,"order_id")??n(t,"id"),type:"payment.refunded"};case"subscription.active":case"subscription.canceled":case"subscription.created":case"subscription.revoked":case"subscription.uncanceled":case"subscription.updated":{const d=a==="subscription.revoked"?"subscription.canceled":P(g[n(t,"status")??""]);return{...e,cancelAtPeriodEnd:w(t,"cancel_at_period_end"),currentPeriodEnd:I(n(t,"current_period_end")),currentPeriodStart:I(n(t,"current_period_start")),customerId:n(t,"customer_id"),priceId:n(t,"product_id"),referenceId:i(t),subscriptionId:n(t,"id"),type:d}}default:return{...e,type:"unhandled"}}},B=o=>{const{webhookSecret:a}=o,t=o.client;return{cancelPayment:()=>b("manual payment cancellation"),cancelSubscription:async(e,r)=>{const d=r?.atPeriodEnd?await t.subscriptions.update({id:e,subscriptionUpdate:{cancelAtPeriodEnd:!0}}):await t.subscriptions.revoke({id:e});return u(d)},capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!0},capturePayment:e=>b("manual capture"),createCheckout:async e=>{const r=await t.checkouts.create({customerEmail:e.customerId?void 0:e.email,customerId:e.customerId,externalCustomerId:e.referenceId,metadata:{...e.metadata,referenceId:e.referenceId},products:[e.priceId],returnUrl:e.cancelUrl,successUrl:e.successUrl});return{id:r.id,provider:"polar",url:r.url}},createPortalSession:async e=>({url:(await t.customerSessions.create({customerId:e.customerId})).customerPortalUrl}),getOrCreateCustomer:async e=>{const r=await t.customers.create({email:e.email??"",externalId:e.referenceId,metadata:{...e.metadata,referenceId:e.referenceId},type:"individual"});return{createdAt:Date.now(),email:r.email??void 0,id:r.id,provider:"polar",referenceId:e.referenceId}},getPaymentStatus:async e=>A(await t.orders.get({id:e})),getSubscriptionStatus:async e=>u(await t.subscriptions.get({id:e})),identifier:"polar",parseWebhook:async({headers:e,payload:r})=>{const d=e.get("webhook-id")??"";await _({payload:r,secret:a,toleranceSeconds:o.webhookToleranceSeconds,webhookId:d,webhookSignature:e.get("webhook-signature")??"",webhookTimestamp:e.get("webhook-timestamp")??""});const c=p(JSON.parse(r));return S(d,n(c,"type")??"",p(c.data))},refundPayment:async e=>{const r=e.amount?void 0:await t.orders.get({id:e.sessionId}),d=e.amount?.currency??r?.currency??"usd",c=e.amount?Number(e.amount.minorUnits):r?.totalAmount??0;await t.refunds.create({amount:c,orderId:e.sessionId,reason:e.reason??"customer_request"});const l=e.amount??m(BigInt(Math.round(c)),d);return{amount:l,capturedAmount:l,createdAt:Date.now(),id:e.sessionId,provider:"polar",referenceId:"",refundedAmount:l,state:"refunded",updatedAt:Date.now()}},reportUsage:async e=>{await t.events.ingest({events:[{externalCustomerId:e.referenceId,metadata:{value:e.quantity},name:e.featureId,timestamp:e.timestamp===void 0?void 0:new Date(e.timestamp)}]})},resumeSubscription:async e=>{const r=await t.subscriptions.update({id:e,subscriptionUpdate:{cancelAtPeriodEnd:!1}});return u(r)},updateSubscription:async(e,r)=>{const d=await t.subscriptions.update({id:e,subscriptionUpdate:r.priceId?{productId:r.priceId}:{}});return u(d)}}};export{B as createPolarAdapter};
1
+ import{a as p,r as n,f as i,e as w,p as I,b as s}from"../packem_shared/json-D85Nbd92.mjs";import{money as m,zeroMoney as f}from"../packem_shared/addMoney-BKfsSf0H.mjs";import{verifyStandardWebhook as _}from"../packem_shared/constantTimeEqual-B4DP75aY.mjs";import{e as h}from"../packem_shared/not-supported-BBbwyP_u.mjs";import{i as P}from"../packem_shared/subscription-event-BosLshSM.mjs";const y=o=>o instanceof Date?o.getTime():I(typeof o=="string"?o:void 0),v={draft:"initiated",paid:"captured",partially_refunded:"partially_refunded",pending:"initiated",refunded:"refunded",void:"canceled"},g={active:"active",canceled:"canceled",incomplete:"past_due",incomplete_expired:"canceled",past_due:"past_due",trialing:"trialing",unpaid:"past_due"},b=h("polar (merchant-of-record)"),u=o=>{const a=p(o),t=Date.now();return{cancelAtPeriodEnd:w(a,"cancelAtPeriodEnd")??!1,createdAt:t,currentPeriodEnd:y(a.currentPeriodEnd),currentPeriodStart:y(a.currentPeriodStart),id:n(a,"id")??"",priceId:n(a,"productId")??"",provider:"polar",quantity:1,referenceId:i(a)??"",state:g[n(a,"status")??""]??"active",updatedAt:t}},A=o=>{const a=p(o),t=Date.now(),e=n(a,"currency")??"usd",r=m(BigInt(Math.round(s(a,"totalAmount")??s(a,"amount")??0)),e),d=v[n(a,"status")??""]??"initiated";return{amount:r,capturedAmount:d==="captured"||d==="partially_refunded"||d==="refunded"?r:f(e),createdAt:t,id:n(a,"id")??"",provider:"polar",referenceId:i(a)??"",refundedAmount:d==="refunded"?r:f(e),state:d,updatedAt:t}},S=(o,a,t)=>{const e={eventId:o,provider:"polar",raw:{object:t,type:a}},r=n(t,"currency")??"usd";switch(a){case"order.created":case"order.paid":return a==="order.created"&&v[n(t,"status")??""]!=="captured"?{...e,type:"unhandled"}:{...e,amount:m(BigInt(s(t,"total_amount")??s(t,"amount")??0),r),customerId:n(t,"customer_id"),referenceId:i(t),sessionId:n(t,"id"),subscriptionId:n(t,"subscription_id"),type:"payment.captured"};case"refund.created":return{...e,amount:m(BigInt(s(t,"amount")??0),r),referenceId:i(t),sessionId:n(t,"order_id")??n(t,"id"),type:"payment.refunded"};case"subscription.active":case"subscription.canceled":case"subscription.created":case"subscription.revoked":case"subscription.uncanceled":case"subscription.updated":{const d=a==="subscription.revoked"?"subscription.canceled":P(g[n(t,"status")??""]);return{...e,cancelAtPeriodEnd:w(t,"cancel_at_period_end"),currentPeriodEnd:I(n(t,"current_period_end")),currentPeriodStart:I(n(t,"current_period_start")),customerId:n(t,"customer_id"),priceId:n(t,"product_id"),referenceId:i(t),subscriptionId:n(t,"id"),type:d}}default:return{...e,type:"unhandled"}}},B=o=>{const{webhookSecret:a}=o,t=o.client;return{cancelPayment:()=>b("manual payment cancellation"),cancelSubscription:async(e,r)=>{const d=r?.atPeriodEnd?await t.subscriptions.update({id:e,subscriptionUpdate:{cancelAtPeriodEnd:!0}}):await t.subscriptions.revoke({id:e});return u(d)},capabilities:{merchantOfRecord:!0,portal:!0,usageMetering:!0},capturePayment:e=>b("manual capture"),createCheckout:async e=>{const r=await t.checkouts.create({customerEmail:e.customerId?void 0:e.email,customerId:e.customerId,externalCustomerId:e.referenceId,metadata:{...e.metadata,referenceId:e.referenceId},products:[e.priceId],returnUrl:e.cancelUrl,successUrl:e.successUrl});return{id:r.id,provider:"polar",url:r.url}},createPortalSession:async e=>({url:(await t.customerSessions.create({customerId:e.customerId})).customerPortalUrl}),getOrCreateCustomer:async e=>{const r=await t.customers.create({email:e.email??"",externalId:e.referenceId,metadata:{...e.metadata,referenceId:e.referenceId},type:"individual"});return{createdAt:Date.now(),email:r.email??void 0,id:r.id,provider:"polar",referenceId:e.referenceId}},getPaymentStatus:async e=>A(await t.orders.get({id:e})),getSubscriptionStatus:async e=>u(await t.subscriptions.get({id:e})),identifier:"polar",parseWebhook:async({headers:e,payload:r})=>{const d=e.get("webhook-id")??"";await _({payload:r,secret:a,toleranceSeconds:o.webhookToleranceSeconds,webhookId:d,webhookSignature:e.get("webhook-signature")??"",webhookTimestamp:e.get("webhook-timestamp")??""});const c=p(JSON.parse(r));return S(d,n(c,"type")??"",p(c.data))},refundPayment:async e=>{const r=e.amount?void 0:await t.orders.get({id:e.sessionId}),d=e.amount?.currency??r?.currency??"usd",c=e.amount?Number(e.amount.minorUnits):r?.totalAmount??0;await t.refunds.create({amount:c,orderId:e.sessionId,reason:e.reason??"customer_request"});const l=e.amount??m(BigInt(Math.round(c)),d);return{amount:l,capturedAmount:l,createdAt:Date.now(),id:e.sessionId,provider:"polar",referenceId:"",refundedAmount:l,state:"refunded",updatedAt:Date.now()}},reportUsage:async e=>{await t.events.ingest({events:[{externalCustomerId:e.referenceId,metadata:{value:e.quantity},name:e.featureId,timestamp:e.timestamp===void 0?void 0:new Date(e.timestamp)}]})},resumeSubscription:async e=>{const r=await t.subscriptions.update({id:e,subscriptionUpdate:{cancelAtPeriodEnd:!1}});return u(r)},updateSubscription:async(e,r)=>{const d=await t.subscriptions.update({id:e,subscriptionUpdate:r.priceId?{productId:r.priceId}:{}});return u(d)}}};export{B as createPolarAdapter};
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.mjs";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.mjs";
2
2
  /**
3
3
  * The Stripe SDK surface the adapter uses, as a structural type — a real `Stripe` instance satisfies
4
4
  * it without a cast. Resources are `unknown` here (the adapter re-types the client as the real
@@ -1,4 +1,4 @@
1
- import { P as PaymentAdapter } from "../packem_shared/adapter.d-CMjjkTGB.js";
1
+ import { P as PaymentAdapter } from "../packem_shared/adapter.d-xBfAhqVC.js";
2
2
  /**
3
3
  * The Stripe SDK surface the adapter uses, as a structural type — a real `Stripe` instance satisfies
4
4
  * it without a cast. Resources are `unknown` here (the adapter re-types the client as the real
@@ -1 +1 @@
1
- import{LunoraPaymentError as A}from"../packem_shared/LunoraPaymentError-35kSImFc.mjs";import{idempotencyKey as P}from"../packem_shared/idempotencyKey-CfJKqcE3.mjs";import{r as a,e as b,b as o,a as u}from"../packem_shared/json-D85Nbd92.mjs";import{compareMoney as S,money as m,zeroMoney as f}from"../packem_shared/addMoney-JN0UrVXA.mjs";import{i as q}from"../packem_shared/subscription-event-BosLshSM.mjs";const E={canceled:"canceled",processing:"authorized",requires_action:"authorized",requires_capture:"authorized",requires_confirmation:"initiated",requires_payment_method:"initiated",succeeded:"captured"},v={active:"active",canceled:"canceled",incomplete:"past_due",incomplete_expired:"canceled",past_due:"past_due",paused:"paused",trialing:"trialing",unpaid:"past_due"},s=i=>a(u(i.metadata),"referenceId")??a(i,"client_reference_id"),_=i=>{const n=u(i.items),t=Array.isArray(n.data)?n.data:[];return u(t[0])},h=i=>a(u(_(i).price),"id"),w=i=>o(_(i),"quantity"),g=i=>{const n=o(_(i),"current_period_end")??o(i,"current_period_end");return n===void 0?void 0:n*1e3},K=i=>{const n=o(_(i),"current_period_start")??o(i,"current_period_start");return n===void 0?void 0:n*1e3},y=i=>{const n=u(i),t=a(n,"currency")??"usd",e=o(n,"amount")??0,r=m(BigInt(Math.round(e)),t),c=E[a(n,"status")??""]??"initiated",d=Date.now();return{amount:r,capturedAmount:c==="captured"?m(BigInt(Math.round(o(n,"amount_received")??e)),t):f(t),createdAt:d,id:a(n,"id")??"",provider:"stripe",referenceId:s(n)??"",refundedAmount:f(t),state:c,updatedAt:d}},l=i=>{const n=u(i),t=Date.now();return{cancelAtPeriodEnd:b(n,"cancel_at_period_end")??!1,createdAt:t,currentPeriodEnd:g(n),currentPeriodStart:K(n),id:a(n,"id")??"",priceId:h(n)??"",provider:"stripe",quantity:w(n)??1,referenceId:s(n)??"",state:v[a(n,"status")??""]??"active",updatedAt:t}},M=(i,n,t)=>{const e={eventId:i,provider:"stripe",raw:{object:t,type:n}},r=a(t,"currency")??"usd";switch(n){case"charge.refunded":return{...e,amount:m(BigInt(Math.round(o(t,"amount_refunded")??0)),r),amountKind:"absolute",referenceId:s(t),sessionId:a(t,"payment_intent")??a(t,"id"),type:"payment.refunded"};case"checkout.session.completed":{if(a(t,"mode")==="subscription"){const d=a(t,"payment_status"),p=d==="paid"||d==="no_payment_required";return{...e,customerId:a(t,"customer"),referenceId:s(t),subscriptionId:a(t,"subscription"),type:p?"subscription.active":"subscription.updated"}}const c=o(t,"amount_total");return{...e,amount:c===void 0?void 0:m(BigInt(Math.round(c)),r),customerId:a(t,"customer"),referenceId:s(t),sessionId:a(t,"payment_intent")??a(t,"id"),type:"payment.captured"}}case"customer.subscription.created":case"customer.subscription.updated":return{...e,cancelAtPeriodEnd:b(t,"cancel_at_period_end"),currentPeriodEnd:g(t),currentPeriodStart:K(t),customerId:a(t,"customer"),priceId:h(t),quantity:w(t),referenceId:s(t),subscriptionId:a(t,"id"),type:q(v[a(t,"status")??""])};case"customer.subscription.deleted":return{...e,referenceId:s(t),subscriptionId:a(t,"id"),type:"subscription.canceled"};case"payment_intent.amount_capturable_updated":return{...e,amount:m(BigInt(Math.round(o(t,"amount")??0)),r),referenceId:s(t),sessionId:a(t,"id"),type:"payment.authorized"};case"payment_intent.payment_failed":return{...e,referenceId:s(t),sessionId:a(t,"id"),type:"payment.failed"};case"payment_intent.succeeded":return{...e,amount:m(BigInt(Math.round(o(t,"amount_received")??o(t,"amount")??0)),r),customerId:a(t,"customer"),referenceId:s(t),sessionId:a(t,"id"),type:"payment.captured"};default:return{...e,type:"unhandled"}}},O=i=>{const{webhookSecret:n}=i,t=i.client;return{cancelPayment:async(e,r)=>{const c=await t.paymentIntents.cancel(e,void 0,{idempotencyKey:r?.idempotencyKey});return y(c)},cancelSubscription:async(e,r)=>{const c=r?.atPeriodEnd?await t.subscriptions.update(e,{cancel_at_period_end:!0},{idempotencyKey:r.idempotencyKey}):await t.subscriptions.cancel(e,void 0,{idempotencyKey:r?.idempotencyKey});return l(c)},capabilities:{merchantOfRecord:!1,portal:!0,usageMetering:!0},capturePayment:async e=>{const r=await t.paymentIntents.capture(e.sessionId,e.amount?{amount_to_capture:Number(e.amount.minorUnits)}:void 0,{idempotencyKey:e.idempotencyKey});return y(r)},createCheckout:async e=>{const r=await t.checkout.sessions.create({cancel_url:e.cancelUrl,client_reference_id:e.referenceId,customer:e.customerId,line_items:[{price:e.priceId,quantity:e.quantity??1}],metadata:{...e.metadata,referenceId:e.referenceId},mode:e.mode,subscription_data:e.mode==="subscription"?{metadata:{referenceId:e.referenceId}}:void 0,success_url:e.successUrl},{idempotencyKey:e.idempotencyKey});return{id:r.id,provider:"stripe",url:r.url??""}},createPortalSession:async e=>({url:(await t.billingPortal.sessions.create({customer:e.customerId,return_url:e.returnUrl})).url}),getOrCreateCustomer:async e=>{const r=await t.customers.create({email:e.email,metadata:{...e.metadata,referenceId:e.referenceId}},{idempotencyKey:P("customer","stripe",e.referenceId)});return{createdAt:Date.now(),email:r.email??void 0,id:r.id,provider:"stripe",referenceId:e.referenceId}},getPaymentStatus:async e=>y(await t.paymentIntents.retrieve(e)),getSubscriptionStatus:async e=>l(await t.subscriptions.retrieve(e)),identifier:"stripe",parseWebhook:async({headers:e,payload:r})=>{const c=e.get("stripe-signature")??"";let d;try{d=await t.webhooks.constructEventAsync(r,c,n,i.webhookToleranceSeconds)}catch(I){throw new A("WEBHOOK_SIGNATURE_INVALID",I instanceof Error?I.message:"invalid webhook signature")}const p=u(u(d.data).object);return M(d.id,d.type,p)},refundPayment:async e=>{await t.refunds.create({amount:e.amount?Number(e.amount.minorUnits):void 0,payment_intent:e.sessionId,reason:e.reason},{idempotencyKey:e.idempotencyKey});const r=await t.paymentIntents.retrieve(e.sessionId),c=y(r),d=e.amount??c.capturedAmount,p=e.amount!==void 0&&S(e.amount,c.capturedAmount)<0;return{...c,refundedAmount:d,state:p?"partially_refunded":"refunded"}},reportUsage:async e=>{await t.billing.meterEvents.create({event_name:e.featureId,identifier:e.idempotencyKey,payload:{stripe_customer_id:e.customerId??"",value:String(e.quantity)},timestamp:e.timestamp===void 0?void 0:Math.floor(e.timestamp/1e3)},{idempotencyKey:e.idempotencyKey})},resumeSubscription:async e=>{const r=await t.subscriptions.update(e,{cancel_at_period_end:!1});return l(r)},updateSubscription:async(e,r)=>{const c={};if(r.priceId!==void 0||r.quantity!==void 0){const p=await t.subscriptions.retrieve(e);c.items=[{id:p.items.data[0]?.id,price:r.priceId,quantity:r.quantity}]}const d=await t.subscriptions.update(e,c);return l(d)}}};export{O as createStripeAdapter};
1
+ import{LunoraPaymentError as A}from"../packem_shared/LunoraPaymentError-C8uAUIzQ.mjs";import{idempotencyKey as P}from"../packem_shared/idempotencyKey-CfJKqcE3.mjs";import{r as a,e as b,b as o,a as u}from"../packem_shared/json-D85Nbd92.mjs";import{compareMoney as S,money as m,zeroMoney as f}from"../packem_shared/addMoney-BKfsSf0H.mjs";import{i as q}from"../packem_shared/subscription-event-BosLshSM.mjs";const E={canceled:"canceled",processing:"authorized",requires_action:"authorized",requires_capture:"authorized",requires_confirmation:"initiated",requires_payment_method:"initiated",succeeded:"captured"},v={active:"active",canceled:"canceled",incomplete:"past_due",incomplete_expired:"canceled",past_due:"past_due",paused:"paused",trialing:"trialing",unpaid:"past_due"},s=i=>a(u(i.metadata),"referenceId")??a(i,"client_reference_id"),_=i=>{const n=u(i.items),t=Array.isArray(n.data)?n.data:[];return u(t[0])},h=i=>a(u(_(i).price),"id"),w=i=>o(_(i),"quantity"),g=i=>{const n=o(_(i),"current_period_end")??o(i,"current_period_end");return n===void 0?void 0:n*1e3},K=i=>{const n=o(_(i),"current_period_start")??o(i,"current_period_start");return n===void 0?void 0:n*1e3},y=i=>{const n=u(i),t=a(n,"currency")??"usd",e=o(n,"amount")??0,r=m(BigInt(Math.round(e)),t),c=E[a(n,"status")??""]??"initiated",d=Date.now();return{amount:r,capturedAmount:c==="captured"?m(BigInt(Math.round(o(n,"amount_received")??e)),t):f(t),createdAt:d,id:a(n,"id")??"",provider:"stripe",referenceId:s(n)??"",refundedAmount:f(t),state:c,updatedAt:d}},l=i=>{const n=u(i),t=Date.now();return{cancelAtPeriodEnd:b(n,"cancel_at_period_end")??!1,createdAt:t,currentPeriodEnd:g(n),currentPeriodStart:K(n),id:a(n,"id")??"",priceId:h(n)??"",provider:"stripe",quantity:w(n)??1,referenceId:s(n)??"",state:v[a(n,"status")??""]??"active",updatedAt:t}},M=(i,n,t)=>{const e={eventId:i,provider:"stripe",raw:{object:t,type:n}},r=a(t,"currency")??"usd";switch(n){case"charge.refunded":return{...e,amount:m(BigInt(Math.round(o(t,"amount_refunded")??0)),r),amountKind:"absolute",referenceId:s(t),sessionId:a(t,"payment_intent")??a(t,"id"),type:"payment.refunded"};case"checkout.session.completed":{if(a(t,"mode")==="subscription"){const d=a(t,"payment_status"),p=d==="paid"||d==="no_payment_required";return{...e,customerId:a(t,"customer"),referenceId:s(t),subscriptionId:a(t,"subscription"),type:p?"subscription.active":"subscription.updated"}}const c=o(t,"amount_total");return{...e,amount:c===void 0?void 0:m(BigInt(Math.round(c)),r),customerId:a(t,"customer"),referenceId:s(t),sessionId:a(t,"payment_intent")??a(t,"id"),type:"payment.captured"}}case"customer.subscription.created":case"customer.subscription.updated":return{...e,cancelAtPeriodEnd:b(t,"cancel_at_period_end"),currentPeriodEnd:g(t),currentPeriodStart:K(t),customerId:a(t,"customer"),priceId:h(t),quantity:w(t),referenceId:s(t),subscriptionId:a(t,"id"),type:q(v[a(t,"status")??""])};case"customer.subscription.deleted":return{...e,referenceId:s(t),subscriptionId:a(t,"id"),type:"subscription.canceled"};case"payment_intent.amount_capturable_updated":return{...e,amount:m(BigInt(Math.round(o(t,"amount")??0)),r),referenceId:s(t),sessionId:a(t,"id"),type:"payment.authorized"};case"payment_intent.payment_failed":return{...e,referenceId:s(t),sessionId:a(t,"id"),type:"payment.failed"};case"payment_intent.succeeded":return{...e,amount:m(BigInt(Math.round(o(t,"amount_received")??o(t,"amount")??0)),r),customerId:a(t,"customer"),referenceId:s(t),sessionId:a(t,"id"),type:"payment.captured"};default:return{...e,type:"unhandled"}}},D=i=>{const{webhookSecret:n}=i,t=i.client;return{cancelPayment:async(e,r)=>{const c=await t.paymentIntents.cancel(e,void 0,{idempotencyKey:r?.idempotencyKey});return y(c)},cancelSubscription:async(e,r)=>{const c=r?.atPeriodEnd?await t.subscriptions.update(e,{cancel_at_period_end:!0},{idempotencyKey:r.idempotencyKey}):await t.subscriptions.cancel(e,void 0,{idempotencyKey:r?.idempotencyKey});return l(c)},capabilities:{merchantOfRecord:!1,portal:!0,usageMetering:!0},capturePayment:async e=>{const r=await t.paymentIntents.capture(e.sessionId,e.amount?{amount_to_capture:Number(e.amount.minorUnits)}:void 0,{idempotencyKey:e.idempotencyKey});return y(r)},createCheckout:async e=>{const r=await t.checkout.sessions.create({cancel_url:e.cancelUrl,client_reference_id:e.referenceId,customer:e.customerId,line_items:[{price:e.priceId,quantity:e.quantity??1}],metadata:{...e.metadata,referenceId:e.referenceId},mode:e.mode,subscription_data:e.mode==="subscription"?{metadata:{referenceId:e.referenceId}}:void 0,success_url:e.successUrl},{idempotencyKey:e.idempotencyKey});return{id:r.id,provider:"stripe",url:r.url??""}},createPortalSession:async e=>({url:(await t.billingPortal.sessions.create({customer:e.customerId,return_url:e.returnUrl})).url}),getOrCreateCustomer:async e=>{const r=await t.customers.create({email:e.email,metadata:{...e.metadata,referenceId:e.referenceId}},{idempotencyKey:P("customer","stripe",e.referenceId)});return{createdAt:Date.now(),email:r.email??void 0,id:r.id,provider:"stripe",referenceId:e.referenceId}},getPaymentStatus:async e=>y(await t.paymentIntents.retrieve(e)),getSubscriptionStatus:async e=>l(await t.subscriptions.retrieve(e)),identifier:"stripe",parseWebhook:async({headers:e,payload:r})=>{const c=e.get("stripe-signature")??"";let d;try{d=await t.webhooks.constructEventAsync(r,c,n,i.webhookToleranceSeconds)}catch(I){throw new A("WEBHOOK_SIGNATURE_INVALID",I instanceof Error?I.message:"invalid webhook signature")}const p=u(u(d.data).object);return M(d.id,d.type,p)},refundPayment:async e=>{await t.refunds.create({amount:e.amount?Number(e.amount.minorUnits):void 0,payment_intent:e.sessionId,reason:e.reason},{idempotencyKey:e.idempotencyKey});const r=await t.paymentIntents.retrieve(e.sessionId),c=y(r),d=e.amount??c.capturedAmount,p=e.amount!==void 0&&S(e.amount,c.capturedAmount)<0;return{...c,refundedAmount:d,state:p?"partially_refunded":"refunded"}},reportUsage:async e=>{await t.billing.meterEvents.create({event_name:e.featureId,identifier:e.idempotencyKey,payload:{stripe_customer_id:e.customerId??"",value:String(e.quantity)},timestamp:e.timestamp===void 0?void 0:Math.floor(e.timestamp/1e3)},{idempotencyKey:e.idempotencyKey})},resumeSubscription:async e=>{const r=await t.subscriptions.update(e,{cancel_at_period_end:!1});return l(r)},updateSubscription:async(e,r)=>{const c={};if(r.priceId!==void 0||r.quantity!==void 0){const p=await t.subscriptions.retrieve(e);c.items=[{id:p.items.data[0]?.id,price:r.priceId,quantity:r.quantity}]}const d=await t.subscriptions.update(e,c);return l(d)}}};export{D as createStripeAdapter};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/payment",
3
- "version": "1.0.0-alpha.65",
3
+ "version": "1.0.0-alpha.67",
4
4
  "description": "Provider-agnostic payments for Lunora: Stripe-first adapter, webhook sync, and subscription/payment state machine",
5
5
  "keywords": [
6
6
  "billing",
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@lunora/errors": "1.0.0-alpha.16",
75
- "@lunora/server": "1.0.0-alpha.64",
75
+ "@lunora/server": "1.0.0-alpha.66",
76
76
  "@lunora/values": "1.0.0-alpha.21",
77
77
  "dinero.js": "2.0.2"
78
78
  },
@@ -1 +0,0 @@
1
- import{LunoraError as N}from"@lunora/errors";const E={CONFIG_INVALID:500,CURRENCY_MISMATCH:400,FORBIDDEN:403,INVALID_TRANSITION:409,NOT_FOUND:404,PROVIDER_ERROR:502,WEBHOOK_EVENT_ID_MISSING:400,WEBHOOK_SIGNATURE_INVALID:400,WEBHOOK_TIMESTAMP_INVALID:400};class _ extends N{constructor(I,r){super(I,r,{name:"LunoraPaymentError",status:E[I]})}}export{_ as LunoraPaymentError};
@@ -1 +0,0 @@
1
- const u=(i,e)=>`${i}:${e}`,r=(i,e)=>`${i}:${e}`;class v{customers=new Map;processedEvents=new Set;sessions=new Map;subscriptions=new Map;usageEvents=new Map;getCustomerByReference(e,s){return Promise.resolve(this.customers.get(u(e,s)))}getPaymentSession(e,s){return Promise.resolve(this.sessions.get(r(e,s)))}getSubscription(e,s){return Promise.resolve(this.subscriptions.get(r(e,s)))}listSubscriptionsByReference(e){return Promise.resolve([...this.subscriptions.values()].filter(s=>s.referenceId===e))}markEventProcessed(e,s){const t=r(e,s);return this.processedEvents.has(t)?Promise.resolve(!1):(this.processedEvents.add(t),Promise.resolve(!0))}releaseEvent(e,s){return this.processedEvents.delete(r(e,s)),Promise.resolve()}markUsageReported(e,s){const t=r(e,s),o=this.usageEvents.get(t);return o&&this.usageEvents.set(t,{...o,reportedToProvider:!0}),Promise.resolve()}recordUsage(e){const s=r(e.provider,e.idempotencyKey);return this.usageEvents.has(s)?Promise.resolve(!1):(this.usageEvents.set(s,e),Promise.resolve(!0))}sumUsage(e,s,t){let o=0;for(const n of this.usageEvents.values())n.referenceId===e&&n.featureId===s&&n.createdAt>=t&&(o+=n.quantity);return Promise.resolve(o)}upsertCustomer(e){return this.customers.set(u(e.provider,e.referenceId),e),Promise.resolve()}upsertPaymentSession(e){return this.sessions.set(r(e.provider,e.id),e),Promise.resolve()}upsertSubscription(e){return this.subscriptions.set(r(e.provider,e.id),e),Promise.resolve()}}export{v as MemoryPaymentStore};
@@ -1 +0,0 @@
1
- import{money as s}from"./addMoney-JN0UrVXA.mjs";const n=(r,t)=>typeof r[t]=="string"?r[t]:"",f=(r,t)=>typeof r[t]=="string"?r[t]:void 0,o=(r,t)=>typeof r[t]=="number"?r[t]:0,v=(r,t)=>typeof r[t]=="number"?r[t]:void 0,m=(r,t)=>r[t]===!0,c=(r,t)=>{const e=r[t];return typeof e=="bigint"?e:typeof e=="number"||typeof e=="string"?BigInt(e):0n},I=r=>({createdAt:r.createdAt,email:r.email,provider:r.provider,providerCustomerId:r.id,referenceId:r.referenceId}),A=r=>({createdAt:o(r,"createdAt"),email:f(r,"email"),id:n(r,"providerCustomerId"),provider:n(r,"provider"),referenceId:n(r,"referenceId")}),S=r=>({amountMinor:r.amount.minorUnits,capturedMinor:r.capturedAmount.minorUnits,createdAt:r.createdAt,currency:r.amount.currency,provider:r.provider,providerSessionId:r.id,referenceId:r.referenceId,refundedMinor:r.refundedAmount.minorUnits,state:r.state,updatedAt:r.updatedAt}),P=r=>{const t=n(r,"currency");return{amount:s(c(r,"amountMinor"),t),capturedAmount:s(c(r,"capturedMinor"),t),createdAt:o(r,"createdAt"),id:n(r,"providerSessionId"),provider:n(r,"provider"),referenceId:n(r,"referenceId"),refundedAmount:s(c(r,"refundedMinor"),t),state:n(r,"state"),updatedAt:o(r,"updatedAt")}},w=r=>({cancelAtPeriodEnd:r.cancelAtPeriodEnd,createdAt:r.createdAt,currentPeriodEnd:r.currentPeriodEnd,currentPeriodStart:r.currentPeriodStart,priceId:r.priceId,provider:r.provider,providerSubscriptionId:r.id,quantity:r.quantity,referenceId:r.referenceId,state:r.state,updatedAt:r.updatedAt}),y=r=>({cancelAtPeriodEnd:m(r,"cancelAtPeriodEnd"),createdAt:o(r,"createdAt"),currentPeriodEnd:v(r,"currentPeriodEnd"),currentPeriodStart:v(r,"currentPeriodStart"),id:n(r,"providerSubscriptionId"),priceId:n(r,"priceId"),provider:n(r,"provider"),quantity:o(r,"quantity"),referenceId:n(r,"referenceId"),state:n(r,"state"),updatedAt:o(r,"updatedAt")}),E=r=>({createdAt:r.createdAt,featureId:r.featureId,idempotencyKey:r.idempotencyKey,provider:r.provider,quantity:r.quantity,referenceId:r.referenceId,reportedToProvider:r.reportedToProvider}),b=r=>{const t=async(e,i,d)=>{const a=await r.findFirst(e,i);if(a){await r.patch(a._id,d);return}await r.insert(e,d)};return{getCustomerByReference:async(e,i)=>{const d=await r.findFirst("customers",{provider:e,referenceId:i});return d?A(d):void 0},getPaymentSession:async(e,i)=>{const d=await r.findFirst("paymentSessions",{provider:e,providerSessionId:i});return d?P(d):void 0},getSubscription:async(e,i)=>{const d=await r.findFirst("subscriptions",{provider:e,providerSubscriptionId:i});return d?y(d):void 0},listSubscriptionsByReference:async e=>(await r.findMany("subscriptions",{referenceId:e})).map(i=>y(i)),markEventProcessed:async(e,i)=>await r.findFirst("events",{provider:e,providerEventId:i})?!1:(await r.insert("events",{processedAt:Date.now(),provider:e,providerEventId:i,type:""}),!0),releaseEvent:async(e,i)=>{const d=await r.findFirst("events",{provider:e,providerEventId:i});d&&await r.delete(d._id)},markUsageReported:async(e,i)=>{const d=await r.findFirst("usageEvents",{idempotencyKey:i,provider:e});d&&await r.patch(d._id,{reportedToProvider:!0})},recordUsage:async e=>await r.findFirst("usageEvents",{idempotencyKey:e.idempotencyKey,provider:e.provider})?!1:(await r.insert("usageEvents",E(e)),!0),sumUsage:async(e,i,d)=>{const a=await r.findMany("usageEvents",{featureId:i,referenceId:e});let p=0;for(const u of a)o(u,"createdAt")>=d&&(p+=o(u,"quantity"));return p},upsertCustomer:async e=>t("customers",{provider:e.provider,providerCustomerId:e.id},I(e)),upsertPaymentSession:async e=>t("paymentSessions",{provider:e.provider,providerSessionId:e.id},S(e)),upsertSubscription:async e=>t("subscriptions",{provider:e.provider,providerSubscriptionId:e.id},w(e))}};export{b as createDatabasePaymentStore};
@@ -1 +0,0 @@
1
- import{toErrorBody as h}from"@lunora/errors";import{usagePeriodStart as I,resolveEntitlements as w,featureNames as b,hasActivePrice as g}from"./entitlementsForReference-BbEOKu5d.mjs";import{LunoraPaymentError as d}from"./LunoraPaymentError-35kSImFc.mjs";import{idempotencyKey as v,derivedIdempotencyKey as N}from"./idempotencyKey-CfJKqcE3.mjs";import{n as O}from"./observability-C9tz8mj_.mjs";import S from"./applyWebhookAction-6JwJo2XL.mjs";const u=(a,r=200,o)=>Response.json(a,{headers:{"content-type":"application/json",...o},status:r}),k=a=>a&&"referenceId"in a?Object.fromEntries(Object.entries(a).filter(([r])=>r!=="referenceId")):a,T=a=>{const{adapter:r,store:o}=a,f=async e=>{if(!a.authorize)return;let t;try{t=await a.authorize(e)}catch{throw new d("FORBIDDEN",`caller not authorized for reference "${e}"`)}if(!t)throw new d("FORBIDDEN",`caller not authorized for reference "${e}"`)},l=async e=>{await f(e.referenceId);const t=k(e.metadata);let n;const i=await o.getCustomerByReference(r.identifier,e.referenceId);if(i)n=i.id;else{const s=await r.getOrCreateCustomer({email:e.email,referenceId:e.referenceId});n=s.id,await o.upsertCustomer(s)}const c=e.idempotencyKey??await N("checkout",r.identifier,e.referenceId,e.priceId,e.mode,String(e.quantity??1),e.successUrl,e.cancelUrl,t?JSON.stringify(t):"");return r.createCheckout({...e,customerId:n,idempotencyKey:c,metadata:t})},p=async(e,t,n,i,c)=>{const s=e.limit(i);if(s!==void 0){const m=await o.sumUsage(n,i,I(t)),y=s-m;return{allowed:y>=c,balance:y,limit:s,unlimited:!1,used:m}}return{allowed:e.has(i),unlimited:e.has(i)}};return{adapter:r,attach:async e=>l({...e,mode:e.mode??"subscription"}),cancelSubscription:async(e,t)=>{const n=await o.getSubscription(r.identifier,e);if(!n)throw new d("NOT_FOUND",`subscription "${e}" not found`);try{await f(n.referenceId)}catch{throw new d("NOT_FOUND",`subscription "${e}" not found`)}const i=t?.idempotencyKey??v("cancel_subscription",r.identifier,e),c=await r.cancelSubscription(e,{...t,idempotencyKey:i});return await o.upsertSubscription(c),c},check:async e=>{if(await f(e.referenceId),e.featureId===void 0&&e.priceId===void 0)throw new d("CONFIG_INVALID","check() requires a featureId or priceId");if(r.checkEntitlement)return r.checkEntitlement(e);const t=await o.listSubscriptionsByReference(e.referenceId);if(e.priceId!==void 0)return{allowed:g(t,e.priceId),unlimited:!1};if(e.featureId===void 0)throw new d("CONFIG_INVALID","check() requires a featureId or priceId");if(!a.entitlements)throw new d("CONFIG_INVALID","check() requires `entitlements` to be configured");const n=w(a.entitlements,t);return p(n,t,e.referenceId,e.featureId,e.quantity??1)},createCheckout:async e=>l(e),createPortalSession:async(e,t)=>{await f(e);const n=await o.getCustomerByReference(r.identifier,e);if(!n)throw new d("NOT_FOUND",`no customer for reference "${e}"`);return r.createPortalSession({customerId:n.id,returnUrl:t})},handleWebhook:async e=>{let t;try{const i=await e.text();t=await r.parseWebhook({headers:e.headers,payload:i})}catch(i){if(i instanceof d){const{body:c,status:s}=h(i);return u({error:c.message},s)}return u({error:"webhook error"},400)}const n=await S(o,t,a.observability);return u({applied:n.applied,reason:n.reason},200)},listBalances:async e=>{if(await f(e),r.getBalances)return r.getBalances(e);if(!a.entitlements)throw new d("CONFIG_INVALID","listBalances() requires `entitlements` to be configured");const t=await o.listSubscriptionsByReference(e),n=w(a.entitlements,t);return Promise.all(b(a.entitlements).map(async i=>({featureId:i,...await p(n,t,e,i,1)})))},listSubscriptions:async e=>(await f(e),o.listSubscriptionsByReference(e)),store:o,track:async e=>{await f(e.referenceId);const t=e.quantity??1,n=e.idempotencyKey??crypto.randomUUID();let i=t;if(e.mode==="set"){const c=await o.listSubscriptionsByReference(e.referenceId),s=await o.sumUsage(e.referenceId,e.featureId,I(c));i=t-s}if(i===0)return{recorded:!1,reportedToProvider:!1};if(!await o.recordUsage({createdAt:Date.now(),featureId:e.featureId,idempotencyKey:n,provider:r.identifier,quantity:i,referenceId:e.referenceId,reportedToProvider:!1}))return{recorded:!1,reportedToProvider:!1};if(i<=0||!r.capabilities.usageMetering||!r.reportUsage)return{recorded:!0,reportedToProvider:!1};try{const c=await o.getCustomerByReference(r.identifier,e.referenceId);return await r.reportUsage({customerId:c?.id,featureId:e.featureId,idempotencyKey:n,quantity:i,referenceId:e.referenceId}),await o.markUsageReported(r.identifier,n),{recorded:!0,reportedToProvider:!0}}catch{return O(a.observability,{featureId:e.featureId,provider:r.identifier,referenceId:e.referenceId,type:"usage.report_failed"}),{recorded:!0,reportedToProvider:!1}}}}};export{T as createPayment};
@@ -1 +0,0 @@
1
- import{LunoraPaymentError as t}from"./LunoraPaymentError-35kSImFc.mjs";const n=o=>r=>{throw new t("PROVIDER_ERROR",`${o} does not support ${r}`)};export{n as e};