@lunora/payment 1.0.0-alpha.64 → 1.0.0-alpha.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/LunoraPaymentError-C8uAUIzQ.mjs +1 -0
- package/dist/packem_shared/MemoryPaymentStore-CkXqJEe2.mjs +1 -0
- package/dist/packem_shared/{adapter.d-CMjjkTGB.d.mts → adapter.d-xBfAhqVC.d.mts} +22 -4
- package/dist/packem_shared/{adapter.d-CMjjkTGB.d.ts → adapter.d-xBfAhqVC.d.ts} +22 -4
- package/dist/packem_shared/{addMoney-JN0UrVXA.mjs → addMoney-BKfsSf0H.mjs} +1 -1
- package/dist/packem_shared/{applyWebhookAction-6JwJo2XL.mjs → applyWebhookAction-Bwvycl00.mjs} +1 -1
- package/dist/packem_shared/{constantTimeEqual-DG_4PS78.mjs → constantTimeEqual-B4DP75aY.mjs} +1 -1
- package/dist/packem_shared/{createAdapterRegistry-CafjyQwx.mjs → createAdapterRegistry-SoXdsiQd.mjs} +1 -1
- package/dist/packem_shared/createDatabasePaymentStore-DxChfP5X.mjs +1 -0
- package/dist/packem_shared/createPayment-Cj0tRPRZ.mjs +1 -0
- package/dist/packem_shared/{lunoraDatabaseToPaymentDatabase-Bn3aBIoh.mjs → lunoraDatabaseToPaymentDatabase-CW1VjW4D.mjs} +1 -1
- package/dist/packem_shared/not-supported-BBbwyP_u.mjs +1 -0
- package/dist/packem_shared/{paymentTables-BMtUrXkM.mjs → paymentTables-Be-_11ux.mjs} +1 -1
- package/dist/packem_shared/{reconcile-y9d1yiVb.mjs → reconcile-BjWV0mB0.mjs} +1 -1
- package/dist/providers/autumn.d.mts +1 -1
- package/dist/providers/autumn.d.ts +1 -1
- package/dist/providers/autumn.mjs +1 -1
- package/dist/providers/creem.d.mts +1 -1
- package/dist/providers/creem.d.ts +1 -1
- package/dist/providers/creem.mjs +1 -1
- package/dist/providers/dodopayments.d.mts +1 -1
- package/dist/providers/dodopayments.d.ts +1 -1
- package/dist/providers/dodopayments.mjs +1 -1
- package/dist/providers/polar.d.mts +1 -1
- package/dist/providers/polar.d.ts +1 -1
- package/dist/providers/polar.mjs +1 -1
- package/dist/providers/stripe.d.mts +1 -1
- package/dist/providers/stripe.d.ts +1 -1
- package/dist/providers/stripe.mjs +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/LunoraPaymentError-35kSImFc.mjs +0 -1
- package/dist/packem_shared/MemoryPaymentStore-BICI1RdZ.mjs +0 -1
- package/dist/packem_shared/createDatabasePaymentStore-4l41pJ0l.mjs +0 -1
- package/dist/packem_shared/createPayment-BW6jnMP_.mjs +0 -1
- 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-
|
|
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-
|
|
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
|
-
/**
|
|
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-
|
|
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-
|
|
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
|
-
/**
|
|
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-
|
|
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
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
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
|
-
/**
|
|
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-
|
|
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};
|
package/dist/packem_shared/{applyWebhookAction-6JwJo2XL.mjs → applyWebhookAction-Bwvycl00.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraPaymentError as v}from"./LunoraPaymentError-
|
|
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};
|
package/dist/packem_shared/{constantTimeEqual-DG_4PS78.mjs → constantTimeEqual-B4DP75aY.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraPaymentError as r}from"./LunoraPaymentError-
|
|
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};
|
package/dist/packem_shared/{createAdapterRegistry-CafjyQwx.mjs → createAdapterRegistry-SoXdsiQd.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraPaymentError as o}from"./LunoraPaymentError-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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`
|
package/dist/providers/creem.mjs
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
package/dist/providers/polar.mjs
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
3
|
+
"version": "1.0.0-alpha.66",
|
|
4
4
|
"description": "Provider-agnostic payments for Lunora: Stripe-first adapter, webhook sync, and subscription/payment state machine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"billing",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
75
|
-
"@lunora/server": "1.0.0-alpha.
|
|
76
|
-
"@lunora/values": "1.0.0-alpha.
|
|
74
|
+
"@lunora/errors": "1.0.0-alpha.16",
|
|
75
|
+
"@lunora/server": "1.0.0-alpha.65",
|
|
76
|
+
"@lunora/values": "1.0.0-alpha.21",
|
|
77
77
|
"dinero.js": "2.0.2"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
@@ -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};
|