@codelitdev/billing 0.1.0-alpha.3 → 0.1.0-alpha.4
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/README.md +14 -14
- package/dist/adapters/drizzle/index.d.ts +2 -2
- package/dist/adapters/drizzle/index.d.ts.map +1 -1
- package/dist/adapters/drizzle/index.js.map +1 -1
- package/dist/adapters/drizzle/store.d.ts.map +1 -1
- package/dist/adapters/drizzle/store.js +26 -50
- package/dist/adapters/drizzle/store.js.map +1 -1
- package/dist/catalog/index.d.ts +3 -3
- package/dist/catalog/index.d.ts.map +1 -1
- package/dist/catalog/index.js +2 -2
- package/dist/catalog/index.js.map +1 -1
- package/dist/catalog/public-view.d.ts.map +1 -1
- package/dist/catalog/public-view.js.map +1 -1
- package/dist/catalog/revisions.d.ts.map +1 -1
- package/dist/catalog/revisions.js.map +1 -1
- package/dist/catalog/types.d.ts.map +1 -1
- package/dist/catalog/validate.d.ts.map +1 -1
- package/dist/catalog/validate.js +2 -3
- package/dist/catalog/validate.js.map +1 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +2 -4
- package/dist/cli/generate.js.map +1 -1
- package/dist/config/define.d.ts.map +1 -1
- package/dist/config/define.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/validate.d.ts.map +1 -1
- package/dist/config/validate.js +6 -13
- package/dist/config/validate.js.map +1 -1
- package/dist/core/checkout-attempt.d.ts.map +1 -1
- package/dist/core/checkout-attempt.js +4 -1
- package/dist/core/checkout-attempt.js.map +1 -1
- package/dist/core/clock.d.ts.map +1 -1
- package/dist/core/clock.js.map +1 -1
- package/dist/core/customer.d.ts.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/ids.d.ts.map +1 -1
- package/dist/core/ids.js +1 -3
- package/dist/core/ids.js.map +1 -1
- package/dist/core/index.d.ts +12 -12
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +10 -10
- package/dist/core/index.js.map +1 -1
- package/dist/core/money.d.ts.map +1 -1
- package/dist/core/money.js +1 -2
- package/dist/core/money.js.map +1 -1
- package/dist/core/plan-change-attempt.d.ts.map +1 -1
- package/dist/core/plan-change-attempt.js +4 -1
- package/dist/core/plan-change-attempt.js.map +1 -1
- package/dist/core/projection-diff.d.ts.map +1 -1
- package/dist/core/projection-diff.js.map +1 -1
- package/dist/core/reconciliation-job.d.ts.map +1 -1
- package/dist/core/reconciliation-job.js.map +1 -1
- package/dist/core/subscription.d.ts.map +1 -1
- package/dist/core/subscription.js +1 -2
- package/dist/core/subscription.js.map +1 -1
- package/dist/core/transitions.d.ts +1 -1
- package/dist/core/transitions.d.ts.map +1 -1
- package/dist/core/transitions.js +4 -23
- package/dist/core/transitions.js.map +1 -1
- package/dist/core/webhook-inbox.d.ts.map +1 -1
- package/dist/core/webhook-inbox.js.map +1 -1
- package/dist/maintenance/health.d.ts +1 -1
- package/dist/maintenance/health.d.ts.map +1 -1
- package/dist/maintenance/health.js.map +1 -1
- package/dist/maintenance/retry.d.ts.map +1 -1
- package/dist/maintenance/retry.js.map +1 -1
- package/dist/operations/index.d.ts +1 -1
- package/dist/operations/index.d.ts.map +1 -1
- package/dist/operations/index.js +1 -1
- package/dist/operations/index.js.map +1 -1
- package/dist/persistence/memory.d.ts.map +1 -1
- package/dist/persistence/memory.js +22 -39
- package/dist/persistence/memory.js.map +1 -1
- package/dist/persistence/store.d.ts.map +1 -1
- package/dist/ports/audit.d.ts.map +1 -1
- package/dist/ports/audit.js.map +1 -1
- package/dist/ports/authorization.d.ts.map +1 -1
- package/dist/ports/authorization.js.map +1 -1
- package/dist/ports/lifecycle.d.ts.map +1 -1
- package/dist/ports/sensitive-values.d.ts.map +1 -1
- package/dist/ports/sensitive-values.js.map +1 -1
- package/dist/ports/telemetry.d.ts.map +1 -1
- package/dist/ports/telemetry.js.map +1 -1
- package/dist/providers/contract.d.ts.map +1 -1
- package/dist/providers/dodo/index.d.ts +1 -1
- package/dist/providers/dodo/index.d.ts.map +1 -1
- package/dist/providers/dodo/index.js +10 -20
- package/dist/providers/dodo/index.js.map +1 -1
- package/dist/providers/dodo/normalize.d.ts.map +1 -1
- package/dist/providers/dodo/normalize.js +2 -5
- package/dist/providers/dodo/normalize.js.map +1 -1
- package/dist/providers/fake/index.d.ts.map +1 -1
- package/dist/providers/fake/index.js +3 -6
- package/dist/providers/fake/index.js.map +1 -1
- package/dist/providers/index.d.ts +2 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js.map +1 -1
- package/dist/schema/canonical.d.ts.map +1 -1
- package/dist/schema/canonical.js.map +1 -1
- package/dist/schema/generator.d.ts.map +1 -1
- package/dist/schema/generator.js +1 -4
- package/dist/schema/generator.js.map +1 -1
- package/dist/testing/clocks.d.ts +1 -1
- package/dist/testing/clocks.d.ts.map +1 -1
- package/dist/testing/clocks.js +1 -1
- package/dist/testing/clocks.js.map +1 -1
- package/dist/testing/consumer-conformance.js.map +1 -1
- package/dist/testing/fixtures.d.ts +1 -1
- package/dist/testing/fixtures.d.ts.map +1 -1
- package/dist/testing/fixtures.js.map +1 -1
- package/dist/testing/index.d.ts +5 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -5
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/provider-contract.d.ts.map +1 -1
- package/dist/testing/provider-contract.js +11 -21
- package/dist/testing/provider-contract.js.map +1 -1
- package/dist/testing/state-machine.d.ts.map +1 -1
- package/dist/testing/state-machine.js.map +1 -1
- package/dist/testing/workflow-harness.d.ts +2 -2
- package/dist/testing/workflow-harness.d.ts.map +1 -1
- package/dist/testing/workflow-harness.js +1 -1
- package/dist/testing/workflow-harness.js.map +1 -1
- package/dist/workflows/engine.d.ts +6 -7
- package/dist/workflows/engine.d.ts.map +1 -1
- package/dist/workflows/engine.js +40 -76
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/index.d.ts +6 -6
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +2 -2
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/lifecycle.d.ts.map +1 -1
- package/dist/workflows/lifecycle.js.map +1 -1
- package/docs/architecture.md +5 -5
- package/package.json +28 -28
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BillingProviderError } from "../core/errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { FAKE_BILLING_WEBHOOK_KEY, FakeBillingProvider, } from "../providers/fake/index.js";
|
|
3
3
|
function assert(condition, message) {
|
|
4
4
|
if (!condition)
|
|
5
5
|
throw new Error(message);
|
|
@@ -43,8 +43,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
43
43
|
email: "timeout@example.com",
|
|
44
44
|
name: "Timeout",
|
|
45
45
|
idempotencyKey: timeoutCustomerKey,
|
|
46
|
-
}), (error) => error instanceof BillingProviderError &&
|
|
47
|
-
error.code === "unavailable", "customer timeout");
|
|
46
|
+
}), (error) => error instanceof BillingProviderError && error.code === "unavailable", "customer timeout");
|
|
48
47
|
const recoveredCustomer = await adapter.createCustomer({
|
|
49
48
|
email: "timeout@example.com",
|
|
50
49
|
name: "Timeout",
|
|
@@ -56,8 +55,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
56
55
|
name: "Timeout",
|
|
57
56
|
idempotencyKey: timeoutCustomerKey,
|
|
58
57
|
});
|
|
59
|
-
assert(recoveredAgain.providerCustomerId ===
|
|
60
|
-
recoveredCustomer.providerCustomerId, "customer timeout retry same id");
|
|
58
|
+
assert(recoveredAgain.providerCustomerId === recoveredCustomer.providerCustomerId, "customer timeout retry same id");
|
|
61
59
|
}
|
|
62
60
|
const checkout = await adapter.createCheckout({
|
|
63
61
|
productId: helpers.productId,
|
|
@@ -82,11 +80,9 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
82
80
|
trialDays: 14,
|
|
83
81
|
idempotencyKey: "checkout:contract:1",
|
|
84
82
|
});
|
|
85
|
-
assert(checkoutAgain.providerCheckoutSessionId ===
|
|
86
|
-
checkout.providerCheckoutSessionId, "checkout idempotent");
|
|
83
|
+
assert(checkoutAgain.providerCheckoutSessionId === checkout.providerCheckoutSessionId, "checkout idempotent");
|
|
87
84
|
const unpaidSession = await adapter.retrieveCheckoutSession(checkout.providerCheckoutSessionId);
|
|
88
|
-
assert(unpaidSession.providerCheckoutSessionId ===
|
|
89
|
-
checkout.providerCheckoutSessionId, "checkout session retrieve");
|
|
85
|
+
assert(unpaidSession.providerCheckoutSessionId === checkout.providerCheckoutSessionId, "checkout session retrieve");
|
|
90
86
|
assert(unpaidSession.subscriptionId === null, "unpaid session has no sub");
|
|
91
87
|
if (helpers.injectTimeoutAfter) {
|
|
92
88
|
helpers.injectTimeoutAfter("createCheckout");
|
|
@@ -101,8 +97,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
101
97
|
catalogKey: "pro_month",
|
|
102
98
|
trialDays: 0,
|
|
103
99
|
idempotencyKey: timeoutCheckoutKey,
|
|
104
|
-
}), (error) => error instanceof BillingProviderError &&
|
|
105
|
-
error.code === "unavailable", "checkout timeout");
|
|
100
|
+
}), (error) => error instanceof BillingProviderError && error.code === "unavailable", "checkout timeout");
|
|
106
101
|
const recoveredCheckout = await adapter.createCheckout({
|
|
107
102
|
productId: helpers.productId,
|
|
108
103
|
currency: product.currency,
|
|
@@ -147,8 +142,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
147
142
|
effectiveAt: "immediately",
|
|
148
143
|
prorationMode: "prorated_immediately",
|
|
149
144
|
idempotencyKey: "plan-change:contract:timeout",
|
|
150
|
-
}), (error) => error instanceof BillingProviderError &&
|
|
151
|
-
error.code === "unavailable", "plan change timeout");
|
|
145
|
+
}), (error) => error instanceof BillingProviderError && error.code === "unavailable", "plan change timeout");
|
|
152
146
|
const recoveredChange = await adapter.changeSubscriptionPlan({
|
|
153
147
|
providerSubscriptionId: paid.providerSubscriptionId,
|
|
154
148
|
targetProviderProductId: helpers.otherProductId,
|
|
@@ -163,8 +157,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
163
157
|
prorationMode: "prorated_immediately",
|
|
164
158
|
idempotencyKey: "plan-change:contract:timeout",
|
|
165
159
|
});
|
|
166
|
-
assert(recoveredChangeAgain.providerPaymentId ===
|
|
167
|
-
recoveredChange.providerPaymentId, "plan change timeout retry same payment");
|
|
160
|
+
assert(recoveredChangeAgain.providerPaymentId === recoveredChange.providerPaymentId, "plan change timeout retry same payment");
|
|
168
161
|
}
|
|
169
162
|
else {
|
|
170
163
|
const changed = await adapter.changeSubscriptionPlan({
|
|
@@ -186,8 +179,7 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
186
179
|
assert(portal.portalUrl.startsWith("http"), "portal url");
|
|
187
180
|
if (helpers.injectTimeoutAfter) {
|
|
188
181
|
helpers.injectTimeoutAfter("cancellation");
|
|
189
|
-
await assertRejects(() => adapter.cancelSubscription(paid.providerSubscriptionId, "cancel:contract:timeout"), (error) => error instanceof BillingProviderError &&
|
|
190
|
-
error.code === "unavailable", "cancel timeout");
|
|
182
|
+
await assertRejects(() => adapter.cancelSubscription(paid.providerSubscriptionId, "cancel:contract:timeout"), (error) => error instanceof BillingProviderError && error.code === "unavailable", "cancel timeout");
|
|
191
183
|
await adapter.cancelSubscription(paid.providerSubscriptionId, "cancel:contract:timeout");
|
|
192
184
|
}
|
|
193
185
|
else {
|
|
@@ -217,11 +209,9 @@ export async function runBillingProviderContract(adapter, helpers) {
|
|
|
217
209
|
...signed.headers,
|
|
218
210
|
"webhook-signature": "v1,deadbeef",
|
|
219
211
|
},
|
|
220
|
-
}), (error) => error instanceof Error &&
|
|
221
|
-
/webhook_signature_invalid/.test(error.message), "bad signature");
|
|
212
|
+
}), (error) => error instanceof Error && /webhook_signature_invalid/.test(error.message), "bad signature");
|
|
222
213
|
const stale = helpers.signWebhook(JSON.stringify({ type: "subscription.updated", data: {} }), "evt_stale", new Date(Date.now() - 10 * 60 * 1000));
|
|
223
|
-
await assertRejects(() => adapter.parseWebhook(stale), (error) => error instanceof Error &&
|
|
224
|
-
/webhook_timestamp_stale/.test(error.message), "stale webhook");
|
|
214
|
+
await assertRejects(() => adapter.parseWebhook(stale), (error) => error instanceof Error && /webhook_timestamp_stale/.test(error.message), "stale webhook");
|
|
225
215
|
}
|
|
226
216
|
export function createContractFake() {
|
|
227
217
|
const adapter = new FakeBillingProvider({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-contract.js","sourceRoot":"","sources":["../../src/testing/provider-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,
|
|
1
|
+
{"version":3,"file":"provider-contract.js","sourceRoot":"","sources":["../../src/testing/provider-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../src/testing/state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../src/testing/state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../src/testing/state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../src/testing/state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import type { BillingOffer } from "../catalog/types.js";
|
|
2
|
+
import { MemoryBillingStore } from "../persistence/memory.js";
|
|
1
3
|
import { MemoryAuditHook } from "../ports/audit.js";
|
|
2
4
|
import { MemoryAuthorizationPort } from "../ports/authorization.js";
|
|
3
5
|
import { MemoryTelemetry } from "../ports/telemetry.js";
|
|
4
|
-
import { MemoryBillingStore } from "../persistence/memory.js";
|
|
5
6
|
import { FakeBillingProvider } from "../providers/fake/index.js";
|
|
6
|
-
import type { BillingOffer } from "../catalog/types.js";
|
|
7
7
|
export declare function createBillingFrom(store: MemoryBillingStore, fake: FakeBillingProvider, now: Date, offers: BillingOffer[], extras?: {
|
|
8
8
|
authorization?: MemoryAuthorizationPort;
|
|
9
9
|
audit?: MemoryAuditHook;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-harness.d.ts","sourceRoot":"","sources":["../../src/testing/workflow-harness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-harness.d.ts","sourceRoot":"","sources":["../../src/testing/workflow-harness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAIjE,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,kBAAkB,EACzB,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,GAAE;IACN,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,eAAe,CAAC;CACpB;;;;;;;;;iBAgEknlB,CAAC;yBAA+B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAA6lrC,CAAC;;;;aAA4vB,CAAC;;;aAA+yC,CAAC;;;;aAAwmE,CAAC;;;;;;;;aAA3tH,CAAC;;;yBAAxlY,CAAC;;;;yBAAwhkC,CAAC;;;;;;;;;;;;;;;;;yBAApl5D,CAAC;2BAAwC,CAAC;sBAAmC,CAAC;0BAAuC,CAAC;iBAA8B,CAAC;;;;;;EAjDvrkB;AAED,wBAAgB,qBAAqB,CACnC,GAAG,OAAuC,EAC1C,OAAO,GAAE;IACP,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACpB;;;;;;;;;;qBA0CknlB,CAAC;6BAA+B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA6lrC,CAAC;;;;iBAA4vB,CAAC;;;iBAA+yC,CAAC;;;;iBAAwmE,CAAC;;;;;;;;iBAA3tH,CAAC;;;6BAAxlY,CAAC;;;;6BAAwhkC,CAAC;;;;;;;;;;;;;;;;;6BAApl5D,CAAC;+BAAwC,CAAC;0BAAmC,CAAC;8BAAuC,CAAC;qBAA8B,CAAC;;;;;;;;;;;;;;EADvrkB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { frozenClock } from "../core/clock.js";
|
|
2
|
+
import { MemoryBillingStore } from "../persistence/memory.js";
|
|
2
3
|
import { MemoryAuditHook } from "../ports/audit.js";
|
|
3
4
|
import { MemoryAuthorizationPort } from "../ports/authorization.js";
|
|
4
5
|
import { MemoryTelemetry } from "../ports/telemetry.js";
|
|
5
|
-
import { MemoryBillingStore } from "../persistence/memory.js";
|
|
6
6
|
import { FakeBillingProvider } from "../providers/fake/index.js";
|
|
7
7
|
import { createBilling } from "../workflows/engine.js";
|
|
8
8
|
import { COURSELIT_OFFER_KEYS, REFERENCE_OFFERS } from "./fixtures.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-harness.js","sourceRoot":"","sources":["../../src/testing/workflow-harness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-harness.js","sourceRoot":"","sources":["../../src/testing/workflow-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import type { BillingOffer, PublicBillingCatalog } from "../catalog/types.js";
|
|
2
|
+
import type { CheckoutAttempt } from "../core/checkout-attempt.js";
|
|
2
3
|
import type { Clock } from "../core/clock.js";
|
|
4
|
+
import type { ProviderCustomer } from "../core/customer.js";
|
|
3
5
|
import type { BillableEntityRef, PayerRef } from "../core/ids.js";
|
|
6
|
+
import type { PlanChangeAttempt } from "../core/plan-change-attempt.js";
|
|
7
|
+
import type { ReconciliationJob } from "../core/reconciliation-job.js";
|
|
4
8
|
import type { SubscriptionSnapshot, VerifiedWebhookEnvelope } from "../core/subscription.js";
|
|
9
|
+
import type { BillingStore } from "../persistence/store.js";
|
|
5
10
|
import type { BillingAuditHook } from "../ports/audit.js";
|
|
6
11
|
import type { BillingActionGrant, BillingAuthorizationPort } from "../ports/authorization.js";
|
|
7
|
-
import type { BillingBlocker, PayerResponsibility } from "../ports/lifecycle.js";
|
|
12
|
+
import type { BillingBlocker, BillingLifecycleHooks, PayerResponsibility } from "../ports/lifecycle.js";
|
|
8
13
|
import type { SensitiveValuePort } from "../ports/sensitive-values.js";
|
|
9
14
|
import { type BillingTelemetry } from "../ports/telemetry.js";
|
|
10
|
-
import type { BillingStore } from "../persistence/store.js";
|
|
11
|
-
import type { CheckoutAttempt } from "../core/checkout-attempt.js";
|
|
12
|
-
import type { ProviderCustomer } from "../core/customer.js";
|
|
13
|
-
import type { PlanChangeAttempt } from "../core/plan-change-attempt.js";
|
|
14
|
-
import type { ReconciliationJob } from "../core/reconciliation-job.js";
|
|
15
|
-
import type { BillingLifecycleHooks } from "../ports/lifecycle.js";
|
|
16
15
|
import type { BillingProviderAdapter } from "../providers/contract.js";
|
|
17
16
|
import { BillingProviderRegistry } from "../providers/registry.js";
|
|
18
17
|
export type CommercialBillingState = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/workflows/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/workflows/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/workflows/engine.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { checkoutIsAvailable, toPublicCatalog
|
|
2
|
-
import { catalogMatchesProviderSnapshot, validateCatalog, } from "../catalog/validate.js";
|
|
1
|
+
import { checkoutIsAvailable, toPublicCatalog } from "../catalog/public-view.js";
|
|
3
2
|
import { canActivateRevision } from "../catalog/revisions.js";
|
|
4
|
-
import {
|
|
3
|
+
import { catalogMatchesProviderSnapshot, validateCatalog, } from "../catalog/validate.js";
|
|
4
|
+
import { BillingCompositionError, BillingProviderError, BillingWorkflowError, providerErrorSummary, } from "../core/errors.js";
|
|
5
5
|
import { retainsPaidEntitlement } from "../core/subscription.js";
|
|
6
6
|
import { decideCheckoutTransition, decideCustomerTransition, decidePlanChangeTransition, decideSubscriptionTransition, decideWebhookInboxTransition, } from "../core/transitions.js";
|
|
7
|
-
import {
|
|
7
|
+
import { billingWebhookRetry, DEFAULT_WEBHOOK_MAX_ATTEMPTS, } from "../maintenance/retry.js";
|
|
8
8
|
import { applySubscriptionProjection, MemoryBillingStore, newId, } from "../persistence/memory.js";
|
|
9
|
+
import { noopTelemetry, safeTelemetry, } from "../ports/telemetry.js";
|
|
9
10
|
import { BillingProviderRegistry } from "../providers/registry.js";
|
|
10
|
-
import { billingWebhookRetry, DEFAULT_WEBHOOK_MAX_ATTEMPTS, } from "../maintenance/retry.js";
|
|
11
11
|
const LEASE_MS = 5 * 60 * 1000;
|
|
12
12
|
export function createBilling(options) {
|
|
13
13
|
if (options.mode === "cloud" && !options.hooks?.audit) {
|
|
@@ -16,8 +16,7 @@ export function createBilling(options) {
|
|
|
16
16
|
if (options.webhookRetrieveCurrent === false) {
|
|
17
17
|
throw new BillingCompositionError("webhook_current_retrieval_required");
|
|
18
18
|
}
|
|
19
|
-
if (options.mode === "cloud" &&
|
|
20
|
-
typeof options.returnUrlValidator !== "function") {
|
|
19
|
+
if (options.mode === "cloud" && typeof options.returnUrlValidator !== "function") {
|
|
21
20
|
throw new BillingCompositionError("return_url_validator_required");
|
|
22
21
|
}
|
|
23
22
|
const store = options.database ?? new MemoryBillingStore();
|
|
@@ -41,10 +40,8 @@ export function createBilling(options) {
|
|
|
41
40
|
!Array.isArray(options.requiredOfferKeys) ||
|
|
42
41
|
options.requiredOfferKeys.length === 0 ||
|
|
43
42
|
!Array.isArray(options.offers) ||
|
|
44
|
-
new Set(options.requiredOfferKeys).size !==
|
|
45
|
-
|
|
46
|
-
options.requiredOfferKeys.some((key) => !isBoundedOpaqueId(key) ||
|
|
47
|
-
!/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/.test(key)) ||
|
|
43
|
+
new Set(options.requiredOfferKeys).size !== options.requiredOfferKeys.length ||
|
|
44
|
+
options.requiredOfferKeys.some((key) => !isBoundedOpaqueId(key) || !/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/.test(key)) ||
|
|
48
45
|
!registry.has(options.checkoutProvider))) {
|
|
49
46
|
throw new BillingCompositionError("cloud_billing_configuration_incomplete");
|
|
50
47
|
}
|
|
@@ -93,9 +90,7 @@ export function createBilling(options) {
|
|
|
93
90
|
providerProductId: item.price.providerProductId,
|
|
94
91
|
}));
|
|
95
92
|
return toPublicCatalog(active.revision.revision, offers, checkoutIsAvailable({
|
|
96
|
-
requestedRevision: providerName === options.checkoutProvider
|
|
97
|
-
? options.requestedRevision
|
|
98
|
-
: null,
|
|
93
|
+
requestedRevision: providerName === options.checkoutProvider ? options.requestedRevision : null,
|
|
99
94
|
activeRevision: active.revision.revision,
|
|
100
95
|
}));
|
|
101
96
|
}
|
|
@@ -412,8 +407,7 @@ export function createBilling(options) {
|
|
|
412
407
|
}
|
|
413
408
|
const live = await store.findLiveJob(subject);
|
|
414
409
|
if (live) {
|
|
415
|
-
if (subject.operation === "cancellation" &&
|
|
416
|
-
live.operation !== "cancellation") {
|
|
410
|
+
if (subject.operation === "cancellation" && live.operation !== "cancellation") {
|
|
417
411
|
live.operation = "cancellation";
|
|
418
412
|
await store.saveJob(live);
|
|
419
413
|
}
|
|
@@ -482,8 +476,7 @@ export function createBilling(options) {
|
|
|
482
476
|
const adapter = provider(options.checkoutProvider);
|
|
483
477
|
const checkoutIdempotencyKey = `checkout:${input.entity.id}:${input.offerKey}:${catalog.revision.revision}`;
|
|
484
478
|
const resumable = await store.findResumableCheckout(input.entity.id);
|
|
485
|
-
if (resumable?.providerCheckoutSessionId &&
|
|
486
|
-
resumable.payerId === input.payer.id) {
|
|
479
|
+
if (resumable?.providerCheckoutSessionId && resumable.payerId === input.payer.id) {
|
|
487
480
|
try {
|
|
488
481
|
const session = await callProvider(() => adapter.retrieveCheckoutSession(resumable.providerCheckoutSessionId));
|
|
489
482
|
if (session.subscriptionId) {
|
|
@@ -492,8 +485,7 @@ export function createBilling(options) {
|
|
|
492
485
|
await projectSnapshot(snapshot, {
|
|
493
486
|
checkoutAttemptId: resumable.attemptId,
|
|
494
487
|
});
|
|
495
|
-
const latest = (await store.findCheckoutById(resumable.id)) ??
|
|
496
|
-
resumable;
|
|
488
|
+
const latest = (await store.findCheckoutById(resumable.id)) ?? resumable;
|
|
497
489
|
return {
|
|
498
490
|
attempt: latest,
|
|
499
491
|
checkoutUrl: latest.returnUrl,
|
|
@@ -508,8 +500,7 @@ export function createBilling(options) {
|
|
|
508
500
|
}
|
|
509
501
|
const liveCheckout = await store.findLiveCheckout(input.entity.id);
|
|
510
502
|
let resumeAttempt;
|
|
511
|
-
if (liveCheckout &&
|
|
512
|
-
liveCheckout.expiresAt.getTime() <= clock.now().getTime()) {
|
|
503
|
+
if (liveCheckout && liveCheckout.expiresAt.getTime() <= clock.now().getTime()) {
|
|
513
504
|
liveCheckout.status = "expired";
|
|
514
505
|
liveCheckout.completedAt = clock.now();
|
|
515
506
|
liveCheckout.checkoutUrlEncrypted = null;
|
|
@@ -562,10 +553,8 @@ export function createBilling(options) {
|
|
|
562
553
|
resumeAttempt = existing;
|
|
563
554
|
}
|
|
564
555
|
}
|
|
565
|
-
if (adapter.capabilities.mutationRecovery.createCustomer ===
|
|
566
|
-
"unsupported"
|
|
567
|
-
adapter.capabilities.mutationRecovery.createCheckout ===
|
|
568
|
-
"unsupported") {
|
|
556
|
+
if (adapter.capabilities.mutationRecovery.createCustomer === "unsupported" ||
|
|
557
|
+
adapter.capabilities.mutationRecovery.createCheckout === "unsupported") {
|
|
569
558
|
throw new BillingWorkflowError("unsupported_operation");
|
|
570
559
|
}
|
|
571
560
|
let providerProduct;
|
|
@@ -573,8 +562,7 @@ export function createBilling(options) {
|
|
|
573
562
|
providerProduct = await callProvider(() => adapter.retrieveProduct(item.price.providerProductId));
|
|
574
563
|
}
|
|
575
564
|
catch (error) {
|
|
576
|
-
if (error instanceof BillingProviderError &&
|
|
577
|
-
error.code === "invalid") {
|
|
565
|
+
if (error instanceof BillingProviderError && error.code === "invalid") {
|
|
578
566
|
throw new BillingWorkflowError("catalog_changed", {
|
|
579
567
|
details: { publicCatalog: pub },
|
|
580
568
|
});
|
|
@@ -588,8 +576,7 @@ export function createBilling(options) {
|
|
|
588
576
|
details: { publicCatalog: pub },
|
|
589
577
|
});
|
|
590
578
|
}
|
|
591
|
-
if (liveCheckout?.status === "open" &&
|
|
592
|
-
!liveCheckout.checkoutUrlEncrypted) {
|
|
579
|
+
if (liveCheckout?.status === "open" && !liveCheckout.checkoutUrlEncrypted) {
|
|
593
580
|
let customer;
|
|
594
581
|
try {
|
|
595
582
|
customer = await resolveCustomer({
|
|
@@ -619,8 +606,7 @@ export function createBilling(options) {
|
|
|
619
606
|
if (options.sensitiveValues) {
|
|
620
607
|
const encrypted = await options.sensitiveValues.encrypt(remote.checkoutUrl);
|
|
621
608
|
liveCheckout.checkoutUrlEncrypted = encrypted.ciphertext;
|
|
622
|
-
liveCheckout.providerCheckoutSessionId =
|
|
623
|
-
remote.providerCheckoutSessionId;
|
|
609
|
+
liveCheckout.providerCheckoutSessionId = remote.providerCheckoutSessionId;
|
|
624
610
|
liveCheckout.providerCustomerRowId = customer.id;
|
|
625
611
|
await store.saveCheckout(liveCheckout);
|
|
626
612
|
}
|
|
@@ -745,8 +731,7 @@ export function createBilling(options) {
|
|
|
745
731
|
}
|
|
746
732
|
latest.status = "open";
|
|
747
733
|
latest.providerCustomerRowId = customer.id;
|
|
748
|
-
latest.providerCheckoutSessionId =
|
|
749
|
-
remote.providerCheckoutSessionId;
|
|
734
|
+
latest.providerCheckoutSessionId = remote.providerCheckoutSessionId;
|
|
750
735
|
latest.checkoutUrlEncrypted = encrypted?.ciphertext ?? null;
|
|
751
736
|
await store.saveCheckout(latest);
|
|
752
737
|
await requireAudit({
|
|
@@ -868,8 +853,7 @@ export function createBilling(options) {
|
|
|
868
853
|
providerProduct = await callProvider(() => adapter.retrieveProduct(target.price.providerProductId));
|
|
869
854
|
}
|
|
870
855
|
catch (error) {
|
|
871
|
-
if (error instanceof BillingProviderError &&
|
|
872
|
-
error.code === "invalid") {
|
|
856
|
+
if (error instanceof BillingProviderError && error.code === "invalid") {
|
|
873
857
|
throw new BillingWorkflowError("catalog_changed", {
|
|
874
858
|
details: {
|
|
875
859
|
publicCatalog: await publicCatalogFor(sub.provider),
|
|
@@ -892,8 +876,7 @@ export function createBilling(options) {
|
|
|
892
876
|
if (livePlanChange.subscriptionId === sub.id &&
|
|
893
877
|
livePlanChange.payerId === input.payer.id &&
|
|
894
878
|
livePlanChange.targetOfferKey === input.offerKey &&
|
|
895
|
-
livePlanChange.targetCatalogRevision ===
|
|
896
|
-
catalog.revision.revision &&
|
|
879
|
+
livePlanChange.targetCatalogRevision === catalog.revision.revision &&
|
|
897
880
|
livePlanChange.effectiveAt === input.effectiveAt &&
|
|
898
881
|
livePlanChange.prorationMode === input.prorationMode) {
|
|
899
882
|
return livePlanChange;
|
|
@@ -992,8 +975,7 @@ export function createBilling(options) {
|
|
|
992
975
|
}, input.payer.id);
|
|
993
976
|
const source = await store.findEntitlementSubscription(input.entity.id);
|
|
994
977
|
const sub = source ??
|
|
995
|
-
(await store.listSubscriptionsByEntity(input.entity.id)).find((row) => row.payerId === input.payer.id &&
|
|
996
|
-
row.status === "cancelled");
|
|
978
|
+
(await store.listSubscriptionsByEntity(input.entity.id)).find((row) => row.payerId === input.payer.id && row.status === "cancelled");
|
|
997
979
|
if (!sub)
|
|
998
980
|
throw new BillingWorkflowError("subscription_required");
|
|
999
981
|
if (sub.payerId !== input.payer.id) {
|
|
@@ -1002,8 +984,8 @@ export function createBilling(options) {
|
|
|
1002
984
|
if (sub.status === "cancelled") {
|
|
1003
985
|
return { accepted: true, subscriptionId: sub.id };
|
|
1004
986
|
}
|
|
1005
|
-
if (provider(sub.provider).capabilities.mutationRecovery
|
|
1006
|
-
|
|
987
|
+
if (provider(sub.provider).capabilities.mutationRecovery.cancellation ===
|
|
988
|
+
"unsupported") {
|
|
1007
989
|
throw new BillingWorkflowError("unsupported_operation");
|
|
1008
990
|
}
|
|
1009
991
|
await store.withTransaction(async () => {
|
|
@@ -1214,10 +1196,7 @@ export function createBilling(options) {
|
|
|
1214
1196
|
providerProductId: snapshot.providerProductId,
|
|
1215
1197
|
catalogRevision: lineageRevision,
|
|
1216
1198
|
offerKey: lineageOffer,
|
|
1217
|
-
plan: pendingChange?.targetPlan ??
|
|
1218
|
-
existing?.plan ??
|
|
1219
|
-
attempt?.plan ??
|
|
1220
|
-
price.plan,
|
|
1199
|
+
plan: pendingChange?.targetPlan ?? existing?.plan ?? attempt?.plan ?? price.plan,
|
|
1221
1200
|
interval: pendingChange?.targetInterval ??
|
|
1222
1201
|
existing?.interval ??
|
|
1223
1202
|
attempt?.interval ??
|
|
@@ -1234,9 +1213,7 @@ export function createBilling(options) {
|
|
|
1234
1213
|
providerOccurredAt: snapshot.providerOccurredAt,
|
|
1235
1214
|
providerVersion: snapshot.providerVersion,
|
|
1236
1215
|
lastObservedAt: now,
|
|
1237
|
-
lastReconciledAt: reconcile
|
|
1238
|
-
? now
|
|
1239
|
-
: (existing?.lastReconciledAt ?? null),
|
|
1216
|
+
lastReconciledAt: reconcile ? now : (existing?.lastReconciledAt ?? null),
|
|
1240
1217
|
};
|
|
1241
1218
|
const write = await applySubscriptionProjection(store, next, now, {
|
|
1242
1219
|
reconcile,
|
|
@@ -1303,8 +1280,7 @@ export function createBilling(options) {
|
|
|
1303
1280
|
const now = clock.now();
|
|
1304
1281
|
const alreadyClaimed = record.status === "processing" && record.workerId === workerId;
|
|
1305
1282
|
if (!alreadyClaimed) {
|
|
1306
|
-
if (!decideWebhookInboxTransition(record.status, "processing")
|
|
1307
|
-
.allowed) {
|
|
1283
|
+
if (!decideWebhookInboxTransition(record.status, "processing").allowed) {
|
|
1308
1284
|
return;
|
|
1309
1285
|
}
|
|
1310
1286
|
record.status = "processing";
|
|
@@ -1325,9 +1301,7 @@ export function createBilling(options) {
|
|
|
1325
1301
|
const adapter = provider(record.provider);
|
|
1326
1302
|
const snapshot = await callProvider(() => adapter.retrieveSubscription(record.subscriptionId));
|
|
1327
1303
|
await projectSnapshot(snapshot, {
|
|
1328
|
-
checkoutAttemptId: record.checkoutAttemptId ??
|
|
1329
|
-
snapshot.metadata.checkoutAttemptId ??
|
|
1330
|
-
undefined,
|
|
1304
|
+
checkoutAttemptId: record.checkoutAttemptId ?? snapshot.metadata.checkoutAttemptId ?? undefined,
|
|
1331
1305
|
});
|
|
1332
1306
|
record.status = "processed";
|
|
1333
1307
|
record.processedAt = clock.now();
|
|
@@ -1572,10 +1546,8 @@ export function createBilling(options) {
|
|
|
1572
1546
|
if (attempt.provider !== job.provider) {
|
|
1573
1547
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1574
1548
|
}
|
|
1575
|
-
if (adapter.capabilities.mutationRecovery.createCustomer ===
|
|
1576
|
-
"unsupported"
|
|
1577
|
-
adapter.capabilities.mutationRecovery.createCheckout ===
|
|
1578
|
-
"unsupported") {
|
|
1549
|
+
if (adapter.capabilities.mutationRecovery.createCustomer === "unsupported" ||
|
|
1550
|
+
adapter.capabilities.mutationRecovery.createCheckout === "unsupported") {
|
|
1579
1551
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1580
1552
|
}
|
|
1581
1553
|
if (attempt.providerCheckoutSessionId) {
|
|
@@ -1610,8 +1582,7 @@ export function createBilling(options) {
|
|
|
1610
1582
|
idempotencyKey: customer.idempotencyKey,
|
|
1611
1583
|
}));
|
|
1612
1584
|
await store.withTransaction(async () => {
|
|
1613
|
-
const latest = (await store.findCustomerById(customer.id)) ??
|
|
1614
|
-
customer;
|
|
1585
|
+
const latest = (await store.findCustomerById(customer.id)) ?? customer;
|
|
1615
1586
|
const decision = decideCustomerTransition(latest.status, "active");
|
|
1616
1587
|
if (!decision.allowed) {
|
|
1617
1588
|
throw new BillingWorkflowError("operation_quarantined");
|
|
@@ -1662,8 +1633,7 @@ export function createBilling(options) {
|
|
|
1662
1633
|
return;
|
|
1663
1634
|
}
|
|
1664
1635
|
const wasCreating = latest.status === "creating";
|
|
1665
|
-
latest.providerCheckoutSessionId =
|
|
1666
|
-
remote.providerCheckoutSessionId;
|
|
1636
|
+
latest.providerCheckoutSessionId = remote.providerCheckoutSessionId;
|
|
1667
1637
|
if (wasCreating)
|
|
1668
1638
|
latest.status = "open";
|
|
1669
1639
|
await store.saveCheckout(latest);
|
|
@@ -1692,8 +1662,7 @@ export function createBilling(options) {
|
|
|
1692
1662
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1693
1663
|
}
|
|
1694
1664
|
if (job.operation === "cancellation") {
|
|
1695
|
-
if (adapter.capabilities.mutationRecovery.cancellation ===
|
|
1696
|
-
"unsupported") {
|
|
1665
|
+
if (adapter.capabilities.mutationRecovery.cancellation === "unsupported") {
|
|
1697
1666
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1698
1667
|
}
|
|
1699
1668
|
await callProvider(() => adapter.cancelSubscription(sub.providerSubscriptionId, `cancel:${sub.id}`));
|
|
@@ -1716,8 +1685,7 @@ export function createBilling(options) {
|
|
|
1716
1685
|
(customer.status === "active" && !customer.providerCustomerId)) {
|
|
1717
1686
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1718
1687
|
}
|
|
1719
|
-
if (adapter.capabilities.mutationRecovery.createCustomer ===
|
|
1720
|
-
"unsupported") {
|
|
1688
|
+
if (adapter.capabilities.mutationRecovery.createCustomer === "unsupported") {
|
|
1721
1689
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1722
1690
|
}
|
|
1723
1691
|
const remote = await callProvider(() => adapter.createCustomer({
|
|
@@ -1770,8 +1738,7 @@ export function createBilling(options) {
|
|
|
1770
1738
|
if (target.provider !== attempt.provider) {
|
|
1771
1739
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1772
1740
|
}
|
|
1773
|
-
if (adapter.capabilities.mutationRecovery.planChange ===
|
|
1774
|
-
"unsupported") {
|
|
1741
|
+
if (adapter.capabilities.mutationRecovery.planChange === "unsupported") {
|
|
1775
1742
|
throw new BillingWorkflowError("operation_quarantined");
|
|
1776
1743
|
}
|
|
1777
1744
|
const remote = await callProvider(() => adapter.changeSubscriptionPlan({
|
|
@@ -1896,8 +1863,8 @@ export function createBilling(options) {
|
|
|
1896
1863
|
throw new BillingWorkflowError("subscription_required");
|
|
1897
1864
|
if (sub.status === "cancelled" || sub.status === "expired")
|
|
1898
1865
|
return;
|
|
1899
|
-
if (provider(sub.provider).capabilities.mutationRecovery
|
|
1900
|
-
|
|
1866
|
+
if (provider(sub.provider).capabilities.mutationRecovery.cancellation ===
|
|
1867
|
+
"unsupported") {
|
|
1901
1868
|
throw new BillingWorkflowError("unsupported_operation");
|
|
1902
1869
|
}
|
|
1903
1870
|
await store.withTransaction(async () => {
|
|
@@ -2070,8 +2037,7 @@ function workLimit(value) {
|
|
|
2070
2037
|
return Math.min(value, 1_000);
|
|
2071
2038
|
}
|
|
2072
2039
|
function isOptionalDate(value) {
|
|
2073
|
-
return
|
|
2074
|
-
(value instanceof Date && !Number.isNaN(value.getTime())));
|
|
2040
|
+
return value === null || (value instanceof Date && !Number.isNaN(value.getTime()));
|
|
2075
2041
|
}
|
|
2076
2042
|
function isCanonicalSubscriptionStatus(value) {
|
|
2077
2043
|
return (value === "pending" ||
|
|
@@ -2085,8 +2051,7 @@ function isOlderProviderSnapshot(existing, incoming) {
|
|
|
2085
2051
|
if (existing.providerVersion && incoming.providerVersion) {
|
|
2086
2052
|
const existingNumber = Number(existing.providerVersion);
|
|
2087
2053
|
const incomingNumber = Number(incoming.providerVersion);
|
|
2088
|
-
if (Number.isSafeInteger(existingNumber) &&
|
|
2089
|
-
Number.isSafeInteger(incomingNumber)) {
|
|
2054
|
+
if (Number.isSafeInteger(existingNumber) && Number.isSafeInteger(incomingNumber)) {
|
|
2090
2055
|
if (incomingNumber < existingNumber)
|
|
2091
2056
|
return true;
|
|
2092
2057
|
if (incomingNumber > existingNumber)
|
|
@@ -2094,8 +2059,7 @@ function isOlderProviderSnapshot(existing, incoming) {
|
|
|
2094
2059
|
}
|
|
2095
2060
|
}
|
|
2096
2061
|
if (existing.providerOccurredAt && incoming.providerOccurredAt) {
|
|
2097
|
-
return (incoming.providerOccurredAt.getTime() <
|
|
2098
|
-
existing.providerOccurredAt.getTime());
|
|
2062
|
+
return (incoming.providerOccurredAt.getTime() < existing.providerOccurredAt.getTime());
|
|
2099
2063
|
}
|
|
2100
2064
|
return false;
|
|
2101
2065
|
}
|