@lunora/payment 1.0.0-alpha.22 → 1.0.0-alpha.23
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 +2 -9
- package/dist/index.d.ts +2 -9
- package/dist/index.mjs +5 -5
- package/dist/packem_shared/{adapter.d-iFA55DzU.d.mts → adapter.d-SULGy2QF.d.mts} +11 -2
- package/dist/packem_shared/{adapter.d-iFA55DzU.d.ts → adapter.d-SULGy2QF.d.ts} +11 -2
- package/dist/packem_shared/{createPayment-DzX-ji34.mjs → createPayment-CKQAznOL.mjs} +10 -12
- package/dist/packem_shared/idempotencyKey-BzaHGdHD.mjs +9 -0
- package/dist/packem_shared/{json-DhcPm8EO.mjs → json-D0Cb5aMv.mjs} +19 -1
- package/dist/packem_shared/{lunoraDatabaseToPaymentDatabase-CL2vdAXq.mjs → lunoraDatabaseToPaymentDatabase-DTsgPvfO.mjs} +1 -1
- package/dist/packem_shared/paymentTables-D4TbhaIk.mjs +59 -0
- package/dist/packem_shared/{reconcile-Dtn_ErbJ.mjs → reconcile-qE3ERi3D.mjs} +13 -1
- package/dist/providers/autumn-features.mjs +1 -1
- package/dist/providers/autumn.d.mts +1 -1
- package/dist/providers/autumn.d.ts +1 -1
- package/dist/providers/autumn.mjs +3 -22
- package/dist/providers/creem.d.mts +1 -1
- package/dist/providers/creem.d.ts +1 -1
- package/dist/providers/creem.mjs +11 -11
- package/dist/providers/dodopayments.d.mts +1 -1
- package/dist/providers/dodopayments.d.ts +1 -1
- package/dist/providers/dodopayments.mjs +2 -2
- package/dist/providers/polar.d.mts +1 -1
- package/dist/providers/polar.d.ts +1 -1
- package/dist/providers/polar.mjs +13 -3
- package/dist/providers/stripe.d.mts +1 -1
- package/dist/providers/stripe.d.ts +1 -1
- package/dist/providers/stripe.mjs +2 -2
- package/package.json +4 -4
- package/dist/packem_shared/idempotencyKey-BFzDCA7g.mjs +0 -3
- package/dist/packem_shared/paymentTables-DccHwWr_.mjs +0 -127
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-SULGy2QF.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-SULGy2QF.mjs";
|
|
3
3
|
import { LunoraError } from '@lunora/errors';
|
|
4
4
|
import { TableDefinition } from '@lunora/server';
|
|
5
5
|
interface PaymentStore {
|
|
@@ -233,13 +233,6 @@ declare class LunoraPaymentError extends LunoraError {
|
|
|
233
233
|
readonly code: PaymentErrorCode;
|
|
234
234
|
constructor(code: PaymentErrorCode, message: string);
|
|
235
235
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Outbound idempotency keys.
|
|
238
|
-
*
|
|
239
|
-
* Every mutating provider call carries a stable key derived from our own operation + inputs, so
|
|
240
|
-
* a Worker retry can never double-charge. Distinct from inbound webhook dedupe (keyed on the
|
|
241
|
-
* provider event id).
|
|
242
|
-
*/
|
|
243
236
|
/** Build a deterministic idempotency key from an operation name and stable parts. */
|
|
244
237
|
declare const idempotencyKey: (operation: string, ...parts: ReadonlyArray<number | string>) => string;
|
|
245
238
|
/** True when the currency has no minor unit (e.g. JPY). */
|
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-SULGy2QF.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-SULGy2QF.js";
|
|
3
3
|
import { LunoraError } from '@lunora/errors';
|
|
4
4
|
import { TableDefinition } from '@lunora/server';
|
|
5
5
|
interface PaymentStore {
|
|
@@ -233,13 +233,6 @@ declare class LunoraPaymentError extends LunoraError {
|
|
|
233
233
|
readonly code: PaymentErrorCode;
|
|
234
234
|
constructor(code: PaymentErrorCode, message: string);
|
|
235
235
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Outbound idempotency keys.
|
|
238
|
-
*
|
|
239
|
-
* Every mutating provider call carries a stable key derived from our own operation + inputs, so
|
|
240
|
-
* a Worker retry can never double-charge. Distinct from inbound webhook dedupe (keyed on the
|
|
241
|
-
* provider event id).
|
|
242
|
-
*/
|
|
243
236
|
/** Build a deterministic idempotency key from an operation name and stable parts. */
|
|
244
237
|
declare const idempotencyKey: (operation: string, ...parts: ReadonlyArray<number | string>) => string;
|
|
245
238
|
/** True when the currency has no minor unit (e.g. JPY). */
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { createAdapterRegistry } from './packem_shared/createAdapterRegistry-Ds7bx_TK.mjs';
|
|
2
|
-
export { lunoraDatabaseToPaymentDatabase, paymentsFromContext } from './packem_shared/lunoraDatabaseToPaymentDatabase-
|
|
3
|
-
export { createPayment } from './packem_shared/createPayment-
|
|
2
|
+
export { lunoraDatabaseToPaymentDatabase, paymentsFromContext } from './packem_shared/lunoraDatabaseToPaymentDatabase-DTsgPvfO.mjs';
|
|
3
|
+
export { createPayment } from './packem_shared/createPayment-CKQAznOL.mjs';
|
|
4
4
|
export { createDatabasePaymentStore } from './packem_shared/createDatabasePaymentStore-C0NUCj1H.mjs';
|
|
5
5
|
export { entitlementsForReference, featureNames, hasActivePrice, resolveEntitlements, usagePeriodStart } from './packem_shared/entitlementsForReference-CzZGXPoZ.mjs';
|
|
6
6
|
export { LunoraPaymentError } from './packem_shared/LunoraPaymentError-BeQlhkZj.mjs';
|
|
7
|
-
export {
|
|
7
|
+
export { idempotencyKey } from './packem_shared/idempotencyKey-BzaHGdHD.mjs';
|
|
8
8
|
export { addMoney, allocateMoney, compareMoney, formatMoney, fromMoneyJSON, isZeroDecimalCurrency, isZeroMoney, money, subtractMoney, toMoneyJSON, zeroMoney } from './packem_shared/addMoney-jSh_7TfF.mjs';
|
|
9
|
-
export { reconcile } from './packem_shared/reconcile-
|
|
10
|
-
export { default as paymentTables } from './packem_shared/paymentTables-
|
|
9
|
+
export { reconcile } from './packem_shared/reconcile-qE3ERi3D.mjs';
|
|
10
|
+
export { default as paymentTables } from './packem_shared/paymentTables-D4TbhaIk.mjs';
|
|
11
11
|
export { PAYMENT_TERMINAL_STATES, SUBSCRIPTION_TERMINAL_STATES, canTransitionPayment, canTransitionSubscription, nextPaymentState, nextSubscriptionState } from './packem_shared/PAYMENT_TERMINAL_STATES-DrxV0clv.mjs';
|
|
12
12
|
export { MemoryPaymentStore } from './packem_shared/MemoryPaymentStore-DvgdWa3C.mjs';
|
|
13
13
|
export { default as applyWebhookAction } from './packem_shared/applyWebhookAction-CLAx4svt.mjs';
|
|
@@ -73,7 +73,11 @@ interface CustomerRef {
|
|
|
73
73
|
}
|
|
74
74
|
interface CheckoutInput {
|
|
75
75
|
readonly cancelUrl: string;
|
|
76
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Ignored at runtime (kept for backward-compat). The provider customer is always derived from the store for the
|
|
78
|
+
* authorized `referenceId` (never caller-supplied) to prevent cross-tenant checkout attachment (IDOR).
|
|
79
|
+
* Retained on the type only for backward compatibility; setting it has no effect.
|
|
80
|
+
*/
|
|
77
81
|
readonly customerId?: string;
|
|
78
82
|
/**
|
|
79
83
|
* Customer email, used when the reference has no provider customer yet. Some Merchant-of-Record
|
|
@@ -123,7 +127,12 @@ interface TrackInput {
|
|
|
123
127
|
readonly featureId: string;
|
|
124
128
|
/** Caller-supplied dedupe key; a fresh one is generated when omitted (so each call records). */
|
|
125
129
|
readonly idempotencyKey?: string;
|
|
126
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* `"add"` (default) increments usage by `quantity`; `"set"` reconciles the period total to `quantity`.
|
|
132
|
+
* `"set"` is a non-atomic read-modify-write (it reads the current total, then appends the delta), so
|
|
133
|
+
* concurrent `"set"` calls for the same reference can over- or under-count — call it only from a
|
|
134
|
+
* serialized context (a single Durable Object or per-reference lock). `"add"` is always safe.
|
|
135
|
+
*/
|
|
127
136
|
readonly mode?: "add" | "set";
|
|
128
137
|
/** Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`). */
|
|
129
138
|
readonly quantity?: number;
|
|
@@ -73,7 +73,11 @@ interface CustomerRef {
|
|
|
73
73
|
}
|
|
74
74
|
interface CheckoutInput {
|
|
75
75
|
readonly cancelUrl: string;
|
|
76
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Ignored at runtime (kept for backward-compat). The provider customer is always derived from the store for the
|
|
78
|
+
* authorized `referenceId` (never caller-supplied) to prevent cross-tenant checkout attachment (IDOR).
|
|
79
|
+
* Retained on the type only for backward compatibility; setting it has no effect.
|
|
80
|
+
*/
|
|
77
81
|
readonly customerId?: string;
|
|
78
82
|
/**
|
|
79
83
|
* Customer email, used when the reference has no provider customer yet. Some Merchant-of-Record
|
|
@@ -123,7 +127,12 @@ interface TrackInput {
|
|
|
123
127
|
readonly featureId: string;
|
|
124
128
|
/** Caller-supplied dedupe key; a fresh one is generated when omitted (so each call records). */
|
|
125
129
|
readonly idempotencyKey?: string;
|
|
126
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* `"add"` (default) increments usage by `quantity`; `"set"` reconciles the period total to `quantity`.
|
|
132
|
+
* `"set"` is a non-atomic read-modify-write (it reads the current total, then appends the delta), so
|
|
133
|
+
* concurrent `"set"` calls for the same reference can over- or under-count — call it only from a
|
|
134
|
+
* serialized context (a single Durable Object or per-reference lock). `"add"` is always safe.
|
|
135
|
+
*/
|
|
127
136
|
readonly mode?: "add" | "set";
|
|
128
137
|
/** Usage amount to add, or the absolute period total when `mode` is `"set"` (defaults to `1`). */
|
|
129
138
|
readonly quantity?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { toErrorBody } from '@lunora/errors';
|
|
2
2
|
import { usagePeriodStart, resolveEntitlements, featureNames, hasActivePrice } from './entitlementsForReference-CzZGXPoZ.mjs';
|
|
3
3
|
import { LunoraPaymentError } from './LunoraPaymentError-BeQlhkZj.mjs';
|
|
4
|
-
import idempotencyKey from './idempotencyKey-
|
|
4
|
+
import { idempotencyKey, derivedIdempotencyKey } from './idempotencyKey-BzaHGdHD.mjs';
|
|
5
5
|
import { n as notifyObserver } from './observability-CvhJ205g.mjs';
|
|
6
6
|
import applyWebhookAction from './applyWebhookAction-CLAx4svt.mjs';
|
|
7
7
|
|
|
@@ -27,18 +27,16 @@ const createPayment = (options) => {
|
|
|
27
27
|
const startCheckout = async (input) => {
|
|
28
28
|
await ensureAuthorized(input.referenceId);
|
|
29
29
|
const metadata = stripReferenceId(input.metadata);
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
await store.upsertCustomer(customer);
|
|
39
|
-
}
|
|
30
|
+
let customerId;
|
|
31
|
+
const existing = await store.getCustomerByReference(adapter.identifier, input.referenceId);
|
|
32
|
+
if (existing) {
|
|
33
|
+
customerId = existing.id;
|
|
34
|
+
} else {
|
|
35
|
+
const customer = await adapter.getOrCreateCustomer({ email: input.email, referenceId: input.referenceId });
|
|
36
|
+
customerId = customer.id;
|
|
37
|
+
await store.upsertCustomer(customer);
|
|
40
38
|
}
|
|
41
|
-
const key = input.idempotencyKey ??
|
|
39
|
+
const key = input.idempotencyKey ?? await derivedIdempotencyKey(
|
|
42
40
|
"checkout",
|
|
43
41
|
adapter.identifier,
|
|
44
42
|
input.referenceId,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const encoder = new TextEncoder();
|
|
2
|
+
const sha256Hex = async (value) => [...new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(value)))].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3
|
+
const idempotencyKey = (operation, ...parts) => [operation, ...parts.map(String)].join(":");
|
|
4
|
+
const derivedIdempotencyKey = async (operation, provider, ...parts) => {
|
|
5
|
+
const digest = await sha256Hex(JSON.stringify([provider, ...parts.map(String)]));
|
|
6
|
+
return `${operation}:${provider}:${digest}`;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { derivedIdempotencyKey, idempotencyKey };
|
|
@@ -2,10 +2,28 @@ const asRecord = (value) => typeof value === "object" && value !== null ? value
|
|
|
2
2
|
const readString = (object, key) => typeof object[key] === "string" ? object[key] : void 0;
|
|
3
3
|
const readNumber = (object, key) => typeof object[key] === "number" ? object[key] : void 0;
|
|
4
4
|
const readBoolean = (object, key) => typeof object[key] === "boolean" ? object[key] : void 0;
|
|
5
|
+
const readAny = (object, ...keys) => {
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
const value = readString(object, key);
|
|
8
|
+
if (value !== void 0) {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return void 0;
|
|
13
|
+
};
|
|
14
|
+
const readAnyNumber = (object, ...keys) => {
|
|
15
|
+
for (const key of keys) {
|
|
16
|
+
const value = readNumber(object, key);
|
|
17
|
+
if (value !== void 0) {
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return void 0;
|
|
22
|
+
};
|
|
5
23
|
const referenceFromMetadata = (object) => readString(asRecord(object.metadata), "referenceId");
|
|
6
24
|
const parseTimestamp = (value) => {
|
|
7
25
|
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
8
26
|
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
9
27
|
};
|
|
10
28
|
|
|
11
|
-
export { asRecord as a, readNumber as b,
|
|
29
|
+
export { asRecord as a, readNumber as b, readAny as c, readAnyNumber as d, readBoolean as e, referenceFromMetadata as f, parseTimestamp as p, readString as r };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPayment } from './createPayment-
|
|
1
|
+
import { createPayment } from './createPayment-CKQAznOL.mjs';
|
|
2
2
|
import { createDatabasePaymentStore } from './createDatabasePaymentStore-C0NUCj1H.mjs';
|
|
3
3
|
|
|
4
4
|
const lunoraDatabaseToPaymentDatabase = (database) => {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineTable } from '@lunora/server';
|
|
2
|
+
import { v } from '@lunora/values';
|
|
3
|
+
|
|
4
|
+
const customers = defineTable({
|
|
5
|
+
createdAt: v.number(),
|
|
6
|
+
email: v.optional(v.string()),
|
|
7
|
+
provider: v.string(),
|
|
8
|
+
providerCustomerId: v.string(),
|
|
9
|
+
referenceId: v.string()
|
|
10
|
+
}).index("by_provider_customer", ["provider", "providerCustomerId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
11
|
+
const subscriptions = defineTable({
|
|
12
|
+
cancelAtPeriodEnd: v.boolean(),
|
|
13
|
+
createdAt: v.number(),
|
|
14
|
+
currentPeriodEnd: v.optional(v.number()),
|
|
15
|
+
currentPeriodStart: v.optional(v.number()),
|
|
16
|
+
priceId: v.string(),
|
|
17
|
+
provider: v.string(),
|
|
18
|
+
providerSubscriptionId: v.string(),
|
|
19
|
+
quantity: v.number(),
|
|
20
|
+
referenceId: v.string(),
|
|
21
|
+
state: v.string(),
|
|
22
|
+
updatedAt: v.number()
|
|
23
|
+
}).index("by_provider_subscription", ["provider", "providerSubscriptionId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
24
|
+
const paymentSessions = defineTable({
|
|
25
|
+
amountMinor: v.bigint(),
|
|
26
|
+
capturedMinor: v.bigint(),
|
|
27
|
+
createdAt: v.number(),
|
|
28
|
+
currency: v.string(),
|
|
29
|
+
provider: v.string(),
|
|
30
|
+
providerSessionId: v.string(),
|
|
31
|
+
referenceId: v.string(),
|
|
32
|
+
refundedMinor: v.bigint(),
|
|
33
|
+
state: v.string(),
|
|
34
|
+
updatedAt: v.number()
|
|
35
|
+
}).index("by_provider_session", ["provider", "providerSessionId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
36
|
+
const events = defineTable({
|
|
37
|
+
processedAt: v.number(),
|
|
38
|
+
provider: v.string(),
|
|
39
|
+
providerEventId: v.string(),
|
|
40
|
+
type: v.string()
|
|
41
|
+
}).index("by_provider_event", ["provider", "providerEventId"], { unique: true });
|
|
42
|
+
const usageEvents = defineTable({
|
|
43
|
+
createdAt: v.number(),
|
|
44
|
+
featureId: v.string(),
|
|
45
|
+
idempotencyKey: v.string(),
|
|
46
|
+
provider: v.string(),
|
|
47
|
+
quantity: v.number(),
|
|
48
|
+
referenceId: v.string(),
|
|
49
|
+
reportedToProvider: v.boolean()
|
|
50
|
+
}).index("by_idempotency", ["provider", "idempotencyKey"], { unique: true }).index("by_reference_feature", ["referenceId", "featureId"]);
|
|
51
|
+
const paymentTables = {
|
|
52
|
+
customers,
|
|
53
|
+
events,
|
|
54
|
+
paymentSessions,
|
|
55
|
+
subscriptions,
|
|
56
|
+
usageEvents
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { paymentTables as default };
|
|
@@ -4,6 +4,17 @@ import { n as notifyObserver } from './observability-CvhJ205g.mjs';
|
|
|
4
4
|
const sameCurrencyAmount = (a, b) => a.currency === b.currency && compareMoney(a, b) === 0;
|
|
5
5
|
const subscriptionDrifted = (existing, current) => existing?.state !== current.state || existing.cancelAtPeriodEnd !== current.cancelAtPeriodEnd || existing.currentPeriodEnd !== current.currentPeriodEnd || existing.priceId !== current.priceId || existing.quantity !== current.quantity;
|
|
6
6
|
const paymentDrifted = (existing, current) => existing?.state !== current.state || !sameCurrencyAmount(existing.capturedAmount, current.capturedAmount) || !sameCurrencyAmount(existing.refundedAmount, current.refundedAmount);
|
|
7
|
+
const REFUND_STATES = /* @__PURE__ */ new Set(["partially_refunded", "refunded"]);
|
|
8
|
+
const mergePaymentTruth = (existing, current) => {
|
|
9
|
+
if (!existing) {
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
const sameRefundCurrency = existing.refundedAmount.currency === current.refundedAmount.currency;
|
|
13
|
+
const refundedAmount = sameRefundCurrency && compareMoney(existing.refundedAmount, current.refundedAmount) > 0 ? existing.refundedAmount : current.refundedAmount;
|
|
14
|
+
const state = current.state === "captured" && REFUND_STATES.has(existing.state) ? existing.state : current.state;
|
|
15
|
+
const referenceId = current.referenceId === "" ? existing.referenceId : current.referenceId;
|
|
16
|
+
return { ...current, referenceId, refundedAmount, state };
|
|
17
|
+
};
|
|
7
18
|
const reconcileSubscription = async (adapter, store, id, observer) => {
|
|
8
19
|
const current = await adapter.getSubscriptionStatus(id);
|
|
9
20
|
const existing = await store.getSubscription(adapter.identifier, id);
|
|
@@ -15,8 +26,9 @@ const reconcileSubscription = async (adapter, store, id, observer) => {
|
|
|
15
26
|
return true;
|
|
16
27
|
};
|
|
17
28
|
const reconcilePayment = async (adapter, store, id, observer) => {
|
|
18
|
-
const
|
|
29
|
+
const providerTruth = await adapter.getPaymentStatus(id);
|
|
19
30
|
const existing = await store.getPaymentSession(adapter.identifier, id);
|
|
31
|
+
const current = mergePaymentTruth(existing, providerTruth);
|
|
20
32
|
if (!paymentDrifted(existing, current)) {
|
|
21
33
|
return false;
|
|
22
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as asRecord, r as readString, b as readNumber } from '../packem_shared/json-
|
|
1
|
+
import { a as asRecord, r as readString, b as readNumber } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
2
2
|
|
|
3
3
|
const toFeatureId = (featureId) => typeof featureId === "string" ? featureId : [...featureId];
|
|
4
4
|
const entityFrom = (record) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PaymentAdapter } from "../packem_shared/adapter.d-
|
|
1
|
+
import { P as PaymentAdapter } from "../packem_shared/adapter.d-SULGy2QF.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-SULGy2QF.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,7 +1,8 @@
|
|
|
1
1
|
import { LunoraPaymentError } from '../packem_shared/LunoraPaymentError-BeQlhkZj.mjs';
|
|
2
|
-
import { a as asRecord, c as
|
|
2
|
+
import { a as asRecord, c as readAny, d as readAnyNumber, e as readBoolean, r as readString } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
3
3
|
import { money } from '../packem_shared/addMoney-jSh_7TfF.mjs';
|
|
4
4
|
import { verifyStandardWebhook } from '../packem_shared/constantTimeEqual-BQjoW85H.mjs';
|
|
5
|
+
import { m as makeNotSupported } from '../packem_shared/not-supported-C0onRyia.mjs';
|
|
5
6
|
import { s as stateToEventType } from '../packem_shared/subscription-event-CwEsWRCK.mjs';
|
|
6
7
|
|
|
7
8
|
const SUBSCRIPTION_STATE_BY_AUTUMN_STATUS = {
|
|
@@ -21,9 +22,7 @@ const SUBSCRIPTION_STATE_BY_AUTUMN_ACTION = {
|
|
|
21
22
|
scheduled: "paused"
|
|
22
23
|
};
|
|
23
24
|
const SUBSCRIPTION_ID_SEPARATOR = "::";
|
|
24
|
-
const notSupported = (
|
|
25
|
-
throw new LunoraPaymentError("PROVIDER_ERROR", `autumn manages billing through the underlying processor and does not support ${operation}`);
|
|
26
|
-
};
|
|
25
|
+
const notSupported = makeNotSupported("autumn");
|
|
27
26
|
const autumnSubscriptionId = (customerId, productId) => `${customerId}${SUBSCRIPTION_ID_SEPARATOR}${productId}`;
|
|
28
27
|
const parseAutumnSubscriptionId = (subscriptionId) => {
|
|
29
28
|
const index = subscriptionId.lastIndexOf(SUBSCRIPTION_ID_SEPARATOR);
|
|
@@ -32,24 +31,6 @@ const parseAutumnSubscriptionId = (subscriptionId) => {
|
|
|
32
31
|
}
|
|
33
32
|
return { customerId: subscriptionId.slice(0, index), productId: subscriptionId.slice(index + SUBSCRIPTION_ID_SEPARATOR.length) };
|
|
34
33
|
};
|
|
35
|
-
const readAny = (object, ...keys) => {
|
|
36
|
-
for (const key of keys) {
|
|
37
|
-
const value = readString(object, key);
|
|
38
|
-
if (value !== void 0) {
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return void 0;
|
|
43
|
-
};
|
|
44
|
-
const readAnyNumber = (object, ...keys) => {
|
|
45
|
-
for (const key of keys) {
|
|
46
|
-
const value = readNumber(object, key);
|
|
47
|
-
if (value !== void 0) {
|
|
48
|
-
return value;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return void 0;
|
|
52
|
-
};
|
|
53
34
|
const isCanceling = (product) => readAnyNumber(product, "canceled_at", "canceledAt") !== void 0 || readAny(product, "status") === "scheduled";
|
|
54
35
|
const productToSubscription = (customerId, product) => {
|
|
55
36
|
const now = Date.now();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PaymentAdapter } from "../packem_shared/adapter.d-
|
|
1
|
+
import { P as PaymentAdapter } from "../packem_shared/adapter.d-SULGy2QF.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-SULGy2QF.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,4 +1,4 @@
|
|
|
1
|
-
import { a as asRecord, r as readString,
|
|
1
|
+
import { a as asRecord, c as readAny, r as readString, f as referenceFromMetadata, b as readNumber, p as parseTimestamp, e as readBoolean, d as readAnyNumber } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
2
2
|
import { money, zeroMoney } from '../packem_shared/addMoney-jSh_7TfF.mjs';
|
|
3
3
|
import { verifyCreemSignature } from '../packem_shared/constantTimeEqual-BQjoW85H.mjs';
|
|
4
4
|
import { m as makeNotSupported } from '../packem_shared/not-supported-C0onRyia.mjs';
|
|
@@ -32,8 +32,8 @@ const SUBSCRIPTION_STATE_BY_CREEM_STATUS = {
|
|
|
32
32
|
};
|
|
33
33
|
const notSupported = makeNotSupported("creem (merchant-of-record)");
|
|
34
34
|
const idOf = (value) => typeof value === "string" ? value : readString(asRecord(value), "id");
|
|
35
|
-
const readCheckoutUrl = (checkout) =>
|
|
36
|
-
const isCanceling = (subscription) =>
|
|
35
|
+
const readCheckoutUrl = (checkout) => readAny(checkout, "checkout_url", "checkoutUrl") ?? "";
|
|
36
|
+
const isCanceling = (subscription) => readAny(subscription, "canceled_at", "canceledAt") !== void 0 || readString(subscription, "status") === "scheduled_cancel";
|
|
37
37
|
const subscriptionFromCreem = (input) => {
|
|
38
38
|
const subscription = asRecord(input);
|
|
39
39
|
const now = Date.now();
|
|
@@ -41,8 +41,8 @@ const subscriptionFromCreem = (input) => {
|
|
|
41
41
|
return {
|
|
42
42
|
cancelAtPeriodEnd: isCanceling(subscription),
|
|
43
43
|
createdAt: now,
|
|
44
|
-
currentPeriodEnd: parseTimestamp(
|
|
45
|
-
currentPeriodStart: parseTimestamp(
|
|
44
|
+
currentPeriodEnd: parseTimestamp(readAny(subscription, "current_period_end_date", "currentPeriodEndDate")),
|
|
45
|
+
currentPeriodStart: parseTimestamp(readAny(subscription, "current_period_start_date", "currentPeriodStartDate")),
|
|
46
46
|
id: readString(subscription, "id") ?? "",
|
|
47
47
|
priceId: idOf(subscription.product) ?? "",
|
|
48
48
|
provider: "creem",
|
|
@@ -93,8 +93,8 @@ const mapEvent = (eventId, eventType, object) => {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
case "refund.created": {
|
|
96
|
-
const amount =
|
|
97
|
-
const refundCurrency =
|
|
96
|
+
const amount = readAnyNumber(object, "refund_amount", "refundAmount", "amount") ?? readNumber(order, "amount");
|
|
97
|
+
const refundCurrency = readAny(object, "refund_currency", "refundCurrency") ?? currency;
|
|
98
98
|
return {
|
|
99
99
|
...base,
|
|
100
100
|
amount: amount === void 0 ? void 0 : money(BigInt(Math.round(amount)), refundCurrency),
|
|
@@ -117,8 +117,8 @@ const mapEvent = (eventId, eventType, object) => {
|
|
|
117
117
|
return {
|
|
118
118
|
...base,
|
|
119
119
|
cancelAtPeriodEnd: readBoolean(object, "cancel_at_period_end") ?? isCanceling(object),
|
|
120
|
-
currentPeriodEnd: parseTimestamp(
|
|
121
|
-
currentPeriodStart: parseTimestamp(
|
|
120
|
+
currentPeriodEnd: parseTimestamp(readAny(object, "current_period_end_date", "currentPeriodEndDate")),
|
|
121
|
+
currentPeriodStart: parseTimestamp(readAny(object, "current_period_start_date", "currentPeriodStartDate")),
|
|
122
122
|
customerId: idOf(object.customer),
|
|
123
123
|
priceId: idOf(object.product),
|
|
124
124
|
referenceId: referenceFromMetadata(object) ?? idOf(object.customer),
|
|
@@ -159,7 +159,7 @@ const createCreemAdapter = (options) => {
|
|
|
159
159
|
},
|
|
160
160
|
createPortalSession: async (input) => {
|
|
161
161
|
const link = await client.customers.generateBillingLinks({ customerId: input.customerId });
|
|
162
|
-
return { url:
|
|
162
|
+
return { url: readAny(link, "customer_portal_link", "customerPortalLink") ?? "" };
|
|
163
163
|
},
|
|
164
164
|
getOrCreateCustomer: async (ref) => {
|
|
165
165
|
const toCustomer = (record) => {
|
|
@@ -186,7 +186,7 @@ const createCreemAdapter = (options) => {
|
|
|
186
186
|
parseWebhook: async ({ headers, payload }) => {
|
|
187
187
|
await verifyCreemSignature({ payload, secret: webhookSecret, signature: headers.get("creem-signature") ?? "" });
|
|
188
188
|
const event = asRecord(JSON.parse(payload));
|
|
189
|
-
return mapEvent(readString(event, "id") ?? "",
|
|
189
|
+
return mapEvent(readString(event, "id") ?? "", readAny(event, "eventType", "type") ?? "", asRecord(event.object));
|
|
190
190
|
},
|
|
191
191
|
// Creem refunds are issued from the dashboard; there is no SDK endpoint to initiate one.
|
|
192
192
|
refundPayment: () => notSupported("programmatic refunds"),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PaymentAdapter } from "../packem_shared/adapter.d-
|
|
1
|
+
import { P as PaymentAdapter } from "../packem_shared/adapter.d-SULGy2QF.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-SULGy2QF.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,6 +1,6 @@
|
|
|
1
1
|
import { LunoraPaymentError } from '../packem_shared/LunoraPaymentError-BeQlhkZj.mjs';
|
|
2
|
-
import idempotencyKey from '../packem_shared/idempotencyKey-
|
|
3
|
-
import { a as asRecord, b as readNumber, r as readString,
|
|
2
|
+
import { idempotencyKey } from '../packem_shared/idempotencyKey-BzaHGdHD.mjs';
|
|
3
|
+
import { a as asRecord, b as readNumber, r as readString, f as referenceFromMetadata, p as parseTimestamp, e as readBoolean } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
4
4
|
import { money, zeroMoney } from '../packem_shared/addMoney-jSh_7TfF.mjs';
|
|
5
5
|
import { verifyStandardWebhook } from '../packem_shared/constantTimeEqual-BQjoW85H.mjs';
|
|
6
6
|
import { m as makeNotSupported } from '../packem_shared/not-supported-C0onRyia.mjs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PaymentAdapter } from "../packem_shared/adapter.d-
|
|
1
|
+
import { P as PaymentAdapter } from "../packem_shared/adapter.d-SULGy2QF.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-SULGy2QF.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,4 +1,4 @@
|
|
|
1
|
-
import { a as asRecord, r as readString,
|
|
1
|
+
import { a as asRecord, r as readString, f as referenceFromMetadata, e as readBoolean, p as parseTimestamp, b as readNumber } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
2
2
|
import { money, zeroMoney } from '../packem_shared/addMoney-jSh_7TfF.mjs';
|
|
3
3
|
import { verifyStandardWebhook } from '../packem_shared/constantTimeEqual-BQjoW85H.mjs';
|
|
4
4
|
import { m as makeNotSupported } from '../packem_shared/not-supported-C0onRyia.mjs';
|
|
@@ -61,7 +61,9 @@ const orderToSession = (input) => {
|
|
|
61
61
|
createdAt: now,
|
|
62
62
|
id: readString(order, "id") ?? "",
|
|
63
63
|
provider: "polar",
|
|
64
|
-
|
|
64
|
+
// Polar copies checkout metadata onto the order, so recover the framework-pinned `referenceId`
|
|
65
|
+
// rather than blanking it — a reconcile sweep would otherwise orphan the row from `by_reference`.
|
|
66
|
+
referenceId: referenceFromMetadata(order) ?? "",
|
|
65
67
|
refundedAmount: state === "refunded" ? amount : zeroMoney(currency),
|
|
66
68
|
state,
|
|
67
69
|
updatedAt: now
|
|
@@ -132,10 +134,18 @@ const createPolarAdapter = (options) => {
|
|
|
132
134
|
capturePayment: (_input) => notSupported("manual capture"),
|
|
133
135
|
createCheckout: async (input) => {
|
|
134
136
|
const checkout = await client.checkouts.create({
|
|
135
|
-
|
|
137
|
+
// Bind the checkout to the customer the facade already reused/minted for this reference,
|
|
138
|
+
// else Polar mints a SECOND orphan customer at completion (leaving the stored customer
|
|
139
|
+
// with no subscription — its portal empty, its metered usage misrouted). `externalCustomerId`
|
|
140
|
+
// carries our reference for the direct-adapter path; `customerEmail` pre-fills when neither is known.
|
|
141
|
+
customerEmail: input.customerId ? void 0 : input.email,
|
|
142
|
+
customerId: input.customerId,
|
|
143
|
+
externalCustomerId: input.referenceId,
|
|
136
144
|
// Pin the framework-controlled `referenceId` LAST so caller metadata can never override it.
|
|
137
145
|
metadata: { ...input.metadata, referenceId: input.referenceId },
|
|
138
146
|
products: [input.priceId],
|
|
147
|
+
// Polar shows a back button to this URL; map the caller's cancel URL onto it.
|
|
148
|
+
returnUrl: input.cancelUrl,
|
|
139
149
|
successUrl: input.successUrl
|
|
140
150
|
});
|
|
141
151
|
return { id: checkout.id, provider: "polar", url: checkout.url };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PaymentAdapter } from "../packem_shared/adapter.d-
|
|
1
|
+
import { P as PaymentAdapter } from "../packem_shared/adapter.d-SULGy2QF.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-SULGy2QF.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,6 +1,6 @@
|
|
|
1
1
|
import { LunoraPaymentError } from '../packem_shared/LunoraPaymentError-BeQlhkZj.mjs';
|
|
2
|
-
import idempotencyKey from '../packem_shared/idempotencyKey-
|
|
3
|
-
import { r as readString,
|
|
2
|
+
import { idempotencyKey } from '../packem_shared/idempotencyKey-BzaHGdHD.mjs';
|
|
3
|
+
import { r as readString, e as readBoolean, b as readNumber, a as asRecord } from '../packem_shared/json-D0Cb5aMv.mjs';
|
|
4
4
|
import { compareMoney, money, zeroMoney } from '../packem_shared/addMoney-jSh_7TfF.mjs';
|
|
5
5
|
import { s as stateToEventType } from '../packem_shared/subscription-event-CwEsWRCK.mjs';
|
|
6
6
|
|
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.23",
|
|
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.4",
|
|
75
|
+
"@lunora/server": "1.0.0-alpha.23",
|
|
76
|
+
"@lunora/values": "1.0.0-alpha.7",
|
|
77
77
|
"dinero.js": "2.0.2"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { defineTable } from '@lunora/server';
|
|
2
|
-
import { v } from '@lunora/values';
|
|
3
|
-
|
|
4
|
-
const products = defineTable({
|
|
5
|
-
description: v.optional(v.string()),
|
|
6
|
-
name: v.string(),
|
|
7
|
-
provider: v.string(),
|
|
8
|
-
providerProductId: v.string()
|
|
9
|
-
}).index("by_provider_product", ["provider", "providerProductId"], { unique: true });
|
|
10
|
-
const prices = defineTable({
|
|
11
|
-
active: v.boolean(),
|
|
12
|
-
amountMinor: v.bigint(),
|
|
13
|
-
currency: v.string(),
|
|
14
|
-
interval: v.optional(v.string()),
|
|
15
|
-
provider: v.string(),
|
|
16
|
-
providerPriceId: v.string(),
|
|
17
|
-
providerProductId: v.string()
|
|
18
|
-
}).index("by_provider_price", ["provider", "providerPriceId"], { unique: true });
|
|
19
|
-
const customers = defineTable({
|
|
20
|
-
createdAt: v.number(),
|
|
21
|
-
email: v.optional(v.string()),
|
|
22
|
-
provider: v.string(),
|
|
23
|
-
providerCustomerId: v.string(),
|
|
24
|
-
referenceId: v.string()
|
|
25
|
-
}).index("by_provider_customer", ["provider", "providerCustomerId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
26
|
-
const subscriptions = defineTable({
|
|
27
|
-
cancelAtPeriodEnd: v.boolean(),
|
|
28
|
-
createdAt: v.number(),
|
|
29
|
-
currentPeriodEnd: v.optional(v.number()),
|
|
30
|
-
currentPeriodStart: v.optional(v.number()),
|
|
31
|
-
priceId: v.string(),
|
|
32
|
-
provider: v.string(),
|
|
33
|
-
providerSubscriptionId: v.string(),
|
|
34
|
-
quantity: v.number(),
|
|
35
|
-
referenceId: v.string(),
|
|
36
|
-
state: v.string(),
|
|
37
|
-
updatedAt: v.number()
|
|
38
|
-
}).index("by_provider_subscription", ["provider", "providerSubscriptionId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
39
|
-
const checkouts = defineTable({
|
|
40
|
-
createdAt: v.number(),
|
|
41
|
-
mode: v.string(),
|
|
42
|
-
priceId: v.string(),
|
|
43
|
-
provider: v.string(),
|
|
44
|
-
providerCheckoutId: v.string(),
|
|
45
|
-
referenceId: v.string(),
|
|
46
|
-
url: v.string()
|
|
47
|
-
}).index("by_provider_checkout", ["provider", "providerCheckoutId"], { unique: true });
|
|
48
|
-
const paymentSessions = defineTable({
|
|
49
|
-
amountMinor: v.bigint(),
|
|
50
|
-
capturedMinor: v.bigint(),
|
|
51
|
-
createdAt: v.number(),
|
|
52
|
-
currency: v.string(),
|
|
53
|
-
provider: v.string(),
|
|
54
|
-
providerSessionId: v.string(),
|
|
55
|
-
referenceId: v.string(),
|
|
56
|
-
refundedMinor: v.bigint(),
|
|
57
|
-
state: v.string(),
|
|
58
|
-
updatedAt: v.number()
|
|
59
|
-
}).index("by_provider_session", ["provider", "providerSessionId"], { unique: true }).index("by_reference", ["referenceId"]);
|
|
60
|
-
const payments = defineTable({
|
|
61
|
-
amountMinor: v.bigint(),
|
|
62
|
-
createdAt: v.number(),
|
|
63
|
-
currency: v.string(),
|
|
64
|
-
provider: v.string(),
|
|
65
|
-
providerPaymentId: v.string(),
|
|
66
|
-
referenceId: v.string(),
|
|
67
|
-
sessionId: v.string(),
|
|
68
|
-
status: v.string()
|
|
69
|
-
}).index("by_provider_payment", ["provider", "providerPaymentId"], { unique: true });
|
|
70
|
-
const captures = defineTable({
|
|
71
|
-
amountMinor: v.bigint(),
|
|
72
|
-
createdAt: v.number(),
|
|
73
|
-
currency: v.string(),
|
|
74
|
-
provider: v.string(),
|
|
75
|
-
providerCaptureId: v.string(),
|
|
76
|
-
sessionId: v.string()
|
|
77
|
-
}).index("by_session", ["sessionId"]);
|
|
78
|
-
const refunds = defineTable({
|
|
79
|
-
amountMinor: v.bigint(),
|
|
80
|
-
createdAt: v.number(),
|
|
81
|
-
currency: v.string(),
|
|
82
|
-
provider: v.string(),
|
|
83
|
-
providerRefundId: v.string(),
|
|
84
|
-
reason: v.optional(v.string()),
|
|
85
|
-
sessionId: v.string()
|
|
86
|
-
}).index("by_session", ["sessionId"]);
|
|
87
|
-
const invoices = defineTable({
|
|
88
|
-
amountMinor: v.bigint(),
|
|
89
|
-
createdAt: v.number(),
|
|
90
|
-
currency: v.string(),
|
|
91
|
-
provider: v.string(),
|
|
92
|
-
providerInvoiceId: v.string(),
|
|
93
|
-
referenceId: v.string(),
|
|
94
|
-
status: v.string(),
|
|
95
|
-
subscriptionId: v.optional(v.string())
|
|
96
|
-
}).index("by_provider_invoice", ["provider", "providerInvoiceId"], { unique: true });
|
|
97
|
-
const events = defineTable({
|
|
98
|
-
processedAt: v.number(),
|
|
99
|
-
provider: v.string(),
|
|
100
|
-
providerEventId: v.string(),
|
|
101
|
-
type: v.string()
|
|
102
|
-
}).index("by_provider_event", ["provider", "providerEventId"], { unique: true });
|
|
103
|
-
const usageEvents = defineTable({
|
|
104
|
-
createdAt: v.number(),
|
|
105
|
-
featureId: v.string(),
|
|
106
|
-
idempotencyKey: v.string(),
|
|
107
|
-
provider: v.string(),
|
|
108
|
-
quantity: v.number(),
|
|
109
|
-
referenceId: v.string(),
|
|
110
|
-
reportedToProvider: v.boolean()
|
|
111
|
-
}).index("by_idempotency", ["provider", "idempotencyKey"], { unique: true }).index("by_reference_feature", ["referenceId", "featureId"]);
|
|
112
|
-
const paymentTables = {
|
|
113
|
-
captures,
|
|
114
|
-
checkouts,
|
|
115
|
-
customers,
|
|
116
|
-
events,
|
|
117
|
-
invoices,
|
|
118
|
-
paymentSessions,
|
|
119
|
-
payments,
|
|
120
|
-
prices,
|
|
121
|
-
products,
|
|
122
|
-
refunds,
|
|
123
|
-
subscriptions,
|
|
124
|
-
usageEvents
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
export { paymentTables as default };
|