@adonis-agora/payments 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/commands/main.d.ts +16 -0
- package/dist/commands/main.d.ts.map +1 -0
- package/dist/commands/main.js +17 -0
- package/dist/commands/main.js.map +1 -0
- package/dist/commands/make_billable.d.ts +16 -0
- package/dist/commands/make_billable.d.ts.map +1 -0
- package/dist/commands/make_billable.js +30 -0
- package/dist/commands/make_billable.js.map +1 -0
- package/dist/commands/make_webhook_handler.d.ts +20 -0
- package/dist/commands/make_webhook_handler.d.ts.map +1 -0
- package/dist/commands/make_webhook_handler.js +34 -0
- package/dist/commands/make_webhook_handler.js.map +1 -0
- package/dist/commands/payments_sync.d.ts +20 -0
- package/dist/commands/payments_sync.d.ts.map +1 -0
- package/dist/commands/payments_sync.js +95 -0
- package/dist/commands/payments_sync.js.map +1 -0
- package/dist/commands/payments_webhook.d.ts +19 -0
- package/dist/commands/payments_webhook.d.ts.map +1 -0
- package/dist/commands/payments_webhook.js +123 -0
- package/dist/commands/payments_webhook.js.map +1 -0
- package/dist/configure.d.ts +12 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +34 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/payments_provider.d.ts +15 -0
- package/dist/providers/payments_provider.d.ts.map +1 -0
- package/dist/providers/payments_provider.js +155 -0
- package/dist/providers/payments_provider.js.map +1 -0
- package/dist/src/billing/billing_overview.d.ts +26 -0
- package/dist/src/billing/billing_overview.d.ts.map +1 -0
- package/dist/src/billing/billing_overview.js +27 -0
- package/dist/src/billing/billing_overview.js.map +1 -0
- package/dist/src/billing/billing_store.d.ts +73 -0
- package/dist/src/billing/billing_store.d.ts.map +1 -0
- package/dist/src/billing/billing_store.js +2 -0
- package/dist/src/billing/billing_store.js.map +1 -0
- package/dist/src/billing/index.d.ts +8 -0
- package/dist/src/billing/index.d.ts.map +1 -0
- package/dist/src/billing/index.js +6 -0
- package/dist/src/billing/index.js.map +1 -0
- package/dist/src/billing/lucid_billing_store.d.ts +84 -0
- package/dist/src/billing/lucid_billing_store.d.ts.map +1 -0
- package/dist/src/billing/lucid_billing_store.js +143 -0
- package/dist/src/billing/lucid_billing_store.js.map +1 -0
- package/dist/src/billing/metered_bill.d.ts +60 -0
- package/dist/src/billing/metered_bill.d.ts.map +1 -0
- package/dist/src/billing/metered_bill.js +46 -0
- package/dist/src/billing/metered_bill.js.map +1 -0
- package/dist/src/billing/mixins/index.d.ts +6 -0
- package/dist/src/billing/mixins/index.d.ts.map +1 -0
- package/dist/src/billing/mixins/index.js +6 -0
- package/dist/src/billing/mixins/index.js.map +1 -0
- package/dist/src/billing/mixins/with_billable.d.ts +23 -0
- package/dist/src/billing/mixins/with_billable.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_billable.js +33 -0
- package/dist/src/billing/mixins/with_billable.js.map +1 -0
- package/dist/src/billing/mixins/with_payment.d.ts +45 -0
- package/dist/src/billing/mixins/with_payment.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_payment.js +94 -0
- package/dist/src/billing/mixins/with_payment.js.map +1 -0
- package/dist/src/billing/mixins/with_subscription.d.ts +50 -0
- package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_subscription.js +95 -0
- package/dist/src/billing/mixins/with_subscription.js.map +1 -0
- package/dist/src/billing/mixins/with_usage_event.d.ts +22 -0
- package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_usage_event.js +39 -0
- package/dist/src/billing/mixins/with_usage_event.js.map +1 -0
- package/dist/src/billing/mixins/with_webhook_event.d.ts +21 -0
- package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_webhook_event.js +42 -0
- package/dist/src/billing/mixins/with_webhook_event.js.map +1 -0
- package/dist/src/billing/webhook_dispatcher.d.ts +79 -0
- package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -0
- package/dist/src/billing/webhook_dispatcher.js +125 -0
- package/dist/src/billing/webhook_dispatcher.js.map +1 -0
- package/dist/src/billing/webhook_events.d.ts +49 -0
- package/dist/src/billing/webhook_events.d.ts.map +1 -0
- package/dist/src/billing/webhook_events.js +44 -0
- package/dist/src/billing/webhook_events.js.map +1 -0
- package/dist/src/billing/webhook_processor.d.ts +39 -0
- package/dist/src/billing/webhook_processor.d.ts.map +1 -0
- package/dist/src/billing/webhook_processor.js +209 -0
- package/dist/src/billing/webhook_processor.js.map +1 -0
- package/dist/src/define_config.d.ts +251 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +67 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/diagnostics.d.ts +155 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +153 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/driver.d.ts +222 -0
- package/dist/src/driver.d.ts.map +1 -0
- package/dist/src/driver.js +2 -0
- package/dist/src/driver.js.map +1 -0
- package/dist/src/drivers/abacate.d.ts +35 -0
- package/dist/src/drivers/abacate.d.ts.map +1 -0
- package/dist/src/drivers/abacate.js +381 -0
- package/dist/src/drivers/abacate.js.map +1 -0
- package/dist/src/drivers/asaas.d.ts +36 -0
- package/dist/src/drivers/asaas.d.ts.map +1 -0
- package/dist/src/drivers/asaas.js +455 -0
- package/dist/src/drivers/asaas.js.map +1 -0
- package/dist/src/drivers/stripe.d.ts +36 -0
- package/dist/src/drivers/stripe.d.ts.map +1 -0
- package/dist/src/drivers/stripe.js +392 -0
- package/dist/src/drivers/stripe.js.map +1 -0
- package/dist/src/drivers/woovi.d.ts +49 -0
- package/dist/src/drivers/woovi.d.ts.map +1 -0
- package/dist/src/drivers/woovi.js +339 -0
- package/dist/src/drivers/woovi.js.map +1 -0
- package/dist/src/ensure_customer.d.ts +23 -0
- package/dist/src/ensure_customer.d.ts.map +1 -0
- package/dist/src/ensure_customer.js +25 -0
- package/dist/src/ensure_customer.js.map +1 -0
- package/dist/src/hooks/webhook_handlers.d.ts +50 -0
- package/dist/src/hooks/webhook_handlers.d.ts.map +1 -0
- package/dist/src/hooks/webhook_handlers.js +53 -0
- package/dist/src/hooks/webhook_handlers.js.map +1 -0
- package/dist/src/http.d.ts +24 -0
- package/dist/src/http.d.ts.map +1 -0
- package/dist/src/http.js +52 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/index.d.ts +29 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/invoice/drivers/asaas.d.ts +23 -0
- package/dist/src/invoice/drivers/asaas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/asaas.js +85 -0
- package/dist/src/invoice/drivers/asaas.js.map +1 -0
- package/dist/src/invoice/drivers/enotas.d.ts +23 -0
- package/dist/src/invoice/drivers/enotas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/enotas.js +83 -0
- package/dist/src/invoice/drivers/enotas.js.map +1 -0
- package/dist/src/invoice/drivers/focus.d.ts +23 -0
- package/dist/src/invoice/drivers/focus.d.ts.map +1 -0
- package/dist/src/invoice/drivers/focus.js +90 -0
- package/dist/src/invoice/drivers/focus.js.map +1 -0
- package/dist/src/invoice/drivers/plugnotas.d.ts +22 -0
- package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/plugnotas.js +81 -0
- package/dist/src/invoice/drivers/plugnotas.js.map +1 -0
- package/dist/src/invoice/drivers/tecnospeed.d.ts +29 -0
- package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -0
- package/dist/src/invoice/drivers/tecnospeed.js +87 -0
- package/dist/src/invoice/drivers/tecnospeed.js.map +1 -0
- package/dist/src/invoice/emit_invoice.d.ts +45 -0
- package/dist/src/invoice/emit_invoice.d.ts.map +1 -0
- package/dist/src/invoice/emit_invoice.js +72 -0
- package/dist/src/invoice/emit_invoice.js.map +1 -0
- package/dist/src/invoice/invoice_manager.d.ts +12 -0
- package/dist/src/invoice/invoice_manager.d.ts.map +1 -0
- package/dist/src/invoice/invoice_manager.js +35 -0
- package/dist/src/invoice/invoice_manager.js.map +1 -0
- package/dist/src/invoice/invoice_provider.d.ts +48 -0
- package/dist/src/invoice/invoice_provider.d.ts.map +1 -0
- package/dist/src/invoice/invoice_provider.js +2 -0
- package/dist/src/invoice/invoice_provider.js.map +1 -0
- package/dist/src/money.d.ts +11 -0
- package/dist/src/money.d.ts.map +1 -0
- package/dist/src/money.js +14 -0
- package/dist/src/money.js.map +1 -0
- package/dist/src/payments_manager.d.ts +40 -0
- package/dist/src/payments_manager.d.ts.map +1 -0
- package/dist/src/payments_manager.js +94 -0
- package/dist/src/payments_manager.js.map +1 -0
- package/dist/src/services/main.d.ts +6 -0
- package/dist/src/services/main.d.ts.map +1 -0
- package/dist/src/services/main.js +17 -0
- package/dist/src/services/main.js.map +1 -0
- package/dist/src/telescope/index.d.ts +3 -0
- package/dist/src/telescope/index.d.ts.map +1 -0
- package/dist/src/telescope/index.js +2 -0
- package/dist/src/telescope/index.js.map +1 -0
- package/dist/src/telescope/payments_watcher.d.ts +27 -0
- package/dist/src/telescope/payments_watcher.d.ts.map +1 -0
- package/dist/src/telescope/payments_watcher.js +58 -0
- package/dist/src/telescope/payments_watcher.js.map +1 -0
- package/dist/src/telescope/telescope-sdk.d.ts +21 -0
- package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
- package/dist/src/telescope/telescope-sdk.js +11 -0
- package/dist/src/telescope/telescope-sdk.js.map +1 -0
- package/dist/src/testing/fake_payments_driver.d.ts +64 -0
- package/dist/src/testing/fake_payments_driver.d.ts.map +1 -0
- package/dist/src/testing/fake_payments_driver.js +171 -0
- package/dist/src/testing/fake_payments_driver.js.map +1 -0
- package/dist/src/testing/in_memory_billing_store.d.ts +110 -0
- package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -0
- package/dist/src/testing/in_memory_billing_store.js +136 -0
- package/dist/src/testing/in_memory_billing_store.js.map +1 -0
- package/dist/src/testing/index.d.ts +6 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +4 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/mutable_clock.d.ts +12 -0
- package/dist/src/testing/mutable_clock.d.ts.map +1 -0
- package/dist/src/testing/mutable_clock.js +20 -0
- package/dist/src/testing/mutable_clock.js.map +1 -0
- package/dist/src/types.d.ts +178 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/webhook_handlers.d.ts +76 -0
- package/dist/src/webhook_handlers.d.ts.map +1 -0
- package/dist/src/webhook_handlers.js +128 -0
- package/dist/src/webhook_handlers.js.map +1 -0
- package/dist/src/webhook_security.d.ts +29 -0
- package/dist/src/webhook_security.d.ts.map +1 -0
- package/dist/src/webhook_security.js +53 -0
- package/dist/src/webhook_security.js.map +1 -0
- package/dist/stubs/config/payments.stub +101 -0
- package/dist/stubs/database/migrations/create_billing_tables.stub +90 -0
- package/dist/stubs/main.d.ts +9 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +16 -0
- package/dist/stubs/main.js.map +1 -0
- package/dist/stubs/make/billable/main.stub +28 -0
- package/dist/stubs/make/webhook_handler/main.stub +29 -0
- package/package.json +150 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { subscribe, unsubscribe } from 'node:diagnostics_channel';
|
|
2
|
+
import { PAYMENTS_DIAGNOSTIC_EVENTS, claimPaymentsDiagnostics, } from '../diagnostics.js';
|
|
3
|
+
/** All payments milestones are low-frequency — record every one of them. */
|
|
4
|
+
const RECORDED_EVENTS = [...PAYMENTS_DIAGNOSTIC_EVENTS];
|
|
5
|
+
/** The `agora:payments:<event>` `node:diagnostics_channel` name — the cross-repo wire contract, replicated structurally (payments never imports `@adonis-agora/diagnostics`). */
|
|
6
|
+
function paymentsChannelName(event) {
|
|
7
|
+
return `agora:payments:${event}`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A payments-specific Telescope watcher: records a typed `payments` entry for every
|
|
11
|
+
* milestone `agora:payments:*` event the library emits (charges, refunds,
|
|
12
|
+
* subscriptions, invoice emission, webhook lifecycle), flattening the event's payload
|
|
13
|
+
* into structured content rather than storing the raw envelope like the generic
|
|
14
|
+
* diagnostics bridge does.
|
|
15
|
+
*
|
|
16
|
+
* Zero coupling: payments publishes via the structural `@adonis-agora/diagnostics`
|
|
17
|
+
* emit slot; this subscribes to the same `node:diagnostics_channel` channels — neither
|
|
18
|
+
* package is imported.
|
|
19
|
+
*
|
|
20
|
+
* De-dup: `register()` CLAIMS every recorded channel via
|
|
21
|
+
* {@link claimPaymentsDiagnostics} (the reference-counted
|
|
22
|
+
* `Symbol.for('@agora/diagnostics:claims')` registry), so the generic
|
|
23
|
+
* `DiagnosticsWatcher` (its `recordClaimed: false` default) skips them and no event is
|
|
24
|
+
* recorded twice. `dispose()` releases the claim and detaches every subscription.
|
|
25
|
+
*/
|
|
26
|
+
export class PaymentsWatcher {
|
|
27
|
+
type = 'payments';
|
|
28
|
+
disposers = [];
|
|
29
|
+
/** Claim the recorded channels and start recording a typed `payments` entry per event. */
|
|
30
|
+
register(ctx) {
|
|
31
|
+
this.disposers.push(claimPaymentsDiagnostics(RECORDED_EVENTS));
|
|
32
|
+
for (const event of RECORDED_EVENTS) {
|
|
33
|
+
const channel = paymentsChannelName(event);
|
|
34
|
+
const onMessage = (message) => {
|
|
35
|
+
const envelope = message;
|
|
36
|
+
if (envelope === null || typeof envelope !== 'object')
|
|
37
|
+
return;
|
|
38
|
+
ctx.record({
|
|
39
|
+
type: this.type,
|
|
40
|
+
content: {
|
|
41
|
+
event: envelope.event,
|
|
42
|
+
...(envelope.ts !== undefined ? { ts: envelope.ts } : {}),
|
|
43
|
+
...(envelope.traceId !== undefined ? { traceId: envelope.traceId } : {}),
|
|
44
|
+
...(envelope.payload ?? {}),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
subscribe(channel, onMessage);
|
|
49
|
+
this.disposers.push(() => unsubscribe(channel, onMessage));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Release the channel claims and detach every subscription (e.g. on shutdown). */
|
|
53
|
+
dispose() {
|
|
54
|
+
while (this.disposers.length)
|
|
55
|
+
this.disposers.pop()?.();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=payments_watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payments_watcher.js","sourceRoot":"","sources":["../../../src/telescope/payments_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,0BAA0B,EAE1B,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,4EAA4E;AAC5E,MAAM,eAAe,GAA8B,CAAC,GAAG,0BAA0B,CAAC,CAAC;AAEnF,iLAAiL;AACjL,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,kBAAkB,KAAK,EAAE,CAAC;AACnC,CAAC;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IACV,SAAS,GAAsB,EAAE,CAAC;IAEnD,0FAA0F;IAC1F,QAAQ,CAAC,GAAmB;QAC1B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,CAAC;QAE/D,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,SAAS,GAAG,CAAC,OAAgB,EAAE,EAAE;gBACrC,MAAM,QAAQ,GAAG,OAAqC,CAAC;gBACvD,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ;oBAAE,OAAO;gBAC9D,GAAG,CAAC,MAAM,CAAC;oBACT,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE;wBACP,KAAK,EAAE,QAAQ,CAAC,KAAK;wBACrB,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACzD,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACxE,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;qBAC5B;iBACF,CAAC,CAAC;YACL,CAAC,CAAC;YACF,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,mFAAmF;IACnF,OAAO;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM;YAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A local, structural mirror of the `@adonis-agora/telescope` watcher contract.
|
|
3
|
+
*
|
|
4
|
+
* We deliberately do NOT import `@adonis-agora/telescope` — it lives in a separate repo,
|
|
5
|
+
* and is only an OPTIONAL peer (a host may run `@adonis-agora/payments` without any
|
|
6
|
+
* observability at all). Same cross-repo decoupling as the payments diagnostics slot
|
|
7
|
+
* itself and `@adonis-agora/media`'s `src/telescope/telescope-sdk.ts`. Keep these in
|
|
8
|
+
* lockstep with `@adonis-agora/telescope`'s watcher types.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The recording surface a {@link PaymentsWatcher} is handed on `register`. Mirror of
|
|
12
|
+
* telescope's `WatcherContext` — a host wires the watcher to a real telescope store's
|
|
13
|
+
* `record`.
|
|
14
|
+
*/
|
|
15
|
+
export interface WatcherContext {
|
|
16
|
+
record(entry: {
|
|
17
|
+
type: string;
|
|
18
|
+
content: unknown;
|
|
19
|
+
}): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=telescope-sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telescope-sdk.d.ts","sourceRoot":"","sources":["../../../src/telescope/telescope-sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACzD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A local, structural mirror of the `@adonis-agora/telescope` watcher contract.
|
|
3
|
+
*
|
|
4
|
+
* We deliberately do NOT import `@adonis-agora/telescope` — it lives in a separate repo,
|
|
5
|
+
* and is only an OPTIONAL peer (a host may run `@adonis-agora/payments` without any
|
|
6
|
+
* observability at all). Same cross-repo decoupling as the payments diagnostics slot
|
|
7
|
+
* itself and `@adonis-agora/media`'s `src/telescope/telescope-sdk.ts`. Keep these in
|
|
8
|
+
* lockstep with `@adonis-agora/telescope`'s watcher types.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=telescope-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telescope-sdk.js","sourceRoot":"","sources":["../../../src/telescope/telescope-sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { PaymentsDriver, UpdateSubscriptionInput } from '../driver.js';
|
|
2
|
+
import type { CheckoutSession, Customer, Invoice, Payment, Refund, Subscription, WebhookEvent } from '../types.js';
|
|
3
|
+
export interface FakePaymentsDriverOptions {
|
|
4
|
+
provider?: string;
|
|
5
|
+
/** Queue of webhook events `parseWebhook` returns (in order). */
|
|
6
|
+
webhookEvents?: WebhookEvent[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* In-memory {@link PaymentsDriver} for tests and local development. Records every call and
|
|
10
|
+
* returns canned responses, so billing flows can be exercised without a gateway.
|
|
11
|
+
*/
|
|
12
|
+
export declare class FakePaymentsDriver implements PaymentsDriver {
|
|
13
|
+
readonly provider: string;
|
|
14
|
+
readonly supportedMethods: readonly ["pix", "credit_card", "boleto", "debit_card", "undefined"];
|
|
15
|
+
/** Canned webhook events returned by `parseWebhook`, in order. */
|
|
16
|
+
webhookEvents: WebhookEvent[];
|
|
17
|
+
createCustomerCalls: {
|
|
18
|
+
input: Parameters<PaymentsDriver['createCustomer']>[0];
|
|
19
|
+
}[];
|
|
20
|
+
chargeCalls: {
|
|
21
|
+
input: Parameters<PaymentsDriver['charge']>[0];
|
|
22
|
+
}[];
|
|
23
|
+
refundCalls: {
|
|
24
|
+
paymentGatewayId: string;
|
|
25
|
+
amount?: number;
|
|
26
|
+
}[];
|
|
27
|
+
createCheckoutCalls: {
|
|
28
|
+
input: Parameters<PaymentsDriver['createCheckout']>[0];
|
|
29
|
+
}[];
|
|
30
|
+
createSubscriptionCalls: {
|
|
31
|
+
input: Parameters<PaymentsDriver['createSubscription']>[0];
|
|
32
|
+
}[];
|
|
33
|
+
cancelSubscriptionCalls: {
|
|
34
|
+
id: string;
|
|
35
|
+
options?: {
|
|
36
|
+
atPeriodEnd?: boolean;
|
|
37
|
+
};
|
|
38
|
+
}[];
|
|
39
|
+
updateSubscriptionCalls: {
|
|
40
|
+
id: string;
|
|
41
|
+
input: UpdateSubscriptionInput;
|
|
42
|
+
}[];
|
|
43
|
+
customers: Map<string, Customer>;
|
|
44
|
+
payments: Map<string, Payment>;
|
|
45
|
+
subscriptions: Map<string, Subscription>;
|
|
46
|
+
invoices: Invoice[];
|
|
47
|
+
constructor(options?: FakePaymentsDriverOptions);
|
|
48
|
+
createCustomer(input: Parameters<PaymentsDriver['createCustomer']>[0]): Promise<Customer>;
|
|
49
|
+
findCustomer(customerId: string): Promise<Customer | null>;
|
|
50
|
+
updateCustomer(customerId: string, input: Parameters<PaymentsDriver['updateCustomer']>[1]): Promise<Customer>;
|
|
51
|
+
charge(input: Parameters<PaymentsDriver['charge']>[0]): Promise<Payment>;
|
|
52
|
+
findPayment(gatewayId: string): Promise<Payment | null>;
|
|
53
|
+
refund(paymentGatewayId: string, amount?: number): Promise<Refund>;
|
|
54
|
+
createCheckout(input: Parameters<PaymentsDriver['createCheckout']>[0]): Promise<CheckoutSession>;
|
|
55
|
+
createSubscription(input: Parameters<PaymentsDriver['createSubscription']>[0]): Promise<Subscription>;
|
|
56
|
+
cancelSubscription(subscriptionGatewayId: string, options?: {
|
|
57
|
+
atPeriodEnd?: boolean;
|
|
58
|
+
}): Promise<Subscription>;
|
|
59
|
+
findSubscription(gatewayId: string): Promise<Subscription | null>;
|
|
60
|
+
updateSubscription(subscriptionGatewayId: string, input: UpdateSubscriptionInput): Promise<Subscription>;
|
|
61
|
+
listInvoices(_customerId: string): Promise<Invoice[]>;
|
|
62
|
+
parseWebhook(_rawBody: string, _headers: Record<string, string | string[] | undefined>): WebhookEvent;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=fake_payments_driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake_payments_driver.d.ts","sourceRoot":"","sources":["../../../src/testing/fake_payments_driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory {@link PaymentsDriver} for tests and local development. Records every call and
|
|
3
|
+
* returns canned responses, so billing flows can be exercised without a gateway.
|
|
4
|
+
*/
|
|
5
|
+
export class FakePaymentsDriver {
|
|
6
|
+
provider;
|
|
7
|
+
supportedMethods = ['pix', 'credit_card', 'boleto', 'debit_card', 'undefined'];
|
|
8
|
+
/** Canned webhook events returned by `parseWebhook`, in order. */
|
|
9
|
+
webhookEvents;
|
|
10
|
+
// Call records for assertions.
|
|
11
|
+
createCustomerCalls = [];
|
|
12
|
+
chargeCalls = [];
|
|
13
|
+
refundCalls = [];
|
|
14
|
+
createCheckoutCalls = [];
|
|
15
|
+
createSubscriptionCalls = [];
|
|
16
|
+
cancelSubscriptionCalls = [];
|
|
17
|
+
updateSubscriptionCalls = [];
|
|
18
|
+
// Canned results.
|
|
19
|
+
customers = new Map();
|
|
20
|
+
payments = new Map();
|
|
21
|
+
subscriptions = new Map();
|
|
22
|
+
invoices = [];
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.provider = options.provider ?? 'fake';
|
|
25
|
+
this.webhookEvents = options.webhookEvents ?? [];
|
|
26
|
+
}
|
|
27
|
+
async createCustomer(input) {
|
|
28
|
+
this.createCustomerCalls.push({ input });
|
|
29
|
+
const customer = {
|
|
30
|
+
id: `cus_${this.customers.size + 1}`,
|
|
31
|
+
...(input.email !== undefined ? { email: input.email } : {}),
|
|
32
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
33
|
+
...(input.taxId !== undefined ? { taxId: input.taxId } : {}),
|
|
34
|
+
};
|
|
35
|
+
this.customers.set(customer.id, customer);
|
|
36
|
+
return customer;
|
|
37
|
+
}
|
|
38
|
+
async findCustomer(customerId) {
|
|
39
|
+
return this.customers.get(customerId) ?? null;
|
|
40
|
+
}
|
|
41
|
+
async updateCustomer(customerId, input) {
|
|
42
|
+
const existing = this.customers.get(customerId) ?? { id: customerId };
|
|
43
|
+
const updated = {
|
|
44
|
+
id: customerId,
|
|
45
|
+
...(input.email !== undefined ? { email: input.email } : {}),
|
|
46
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
47
|
+
...(input.taxId !== undefined ? { taxId: input.taxId } : {}),
|
|
48
|
+
};
|
|
49
|
+
void existing;
|
|
50
|
+
this.customers.set(customerId, updated);
|
|
51
|
+
return updated;
|
|
52
|
+
}
|
|
53
|
+
async charge(input) {
|
|
54
|
+
this.chargeCalls.push({ input });
|
|
55
|
+
const payment = {
|
|
56
|
+
id: `pi_${this.payments.size + 1}`,
|
|
57
|
+
gatewayId: `pi_${this.payments.size + 1}`,
|
|
58
|
+
provider: this.provider,
|
|
59
|
+
amount: { amount: input.amount, currency: input.currency ?? 'brl' },
|
|
60
|
+
status: 'paid',
|
|
61
|
+
...(input.customerId !== undefined ? { customerId: input.customerId } : {}),
|
|
62
|
+
payload: {},
|
|
63
|
+
createdAt: new Date().toISOString(),
|
|
64
|
+
paidAt: new Date().toISOString(),
|
|
65
|
+
};
|
|
66
|
+
this.payments.set(payment.gatewayId, payment);
|
|
67
|
+
return payment;
|
|
68
|
+
}
|
|
69
|
+
async findPayment(gatewayId) {
|
|
70
|
+
return this.payments.get(gatewayId) ?? null;
|
|
71
|
+
}
|
|
72
|
+
async refund(paymentGatewayId, amount) {
|
|
73
|
+
this.refundCalls.push(amount !== undefined ? { paymentGatewayId, amount } : { paymentGatewayId });
|
|
74
|
+
const payment = this.payments.get(paymentGatewayId);
|
|
75
|
+
return {
|
|
76
|
+
id: `re_${this.refundCalls.length}`,
|
|
77
|
+
gatewayId: `re_${this.refundCalls.length}`,
|
|
78
|
+
provider: this.provider,
|
|
79
|
+
amount: {
|
|
80
|
+
amount: amount ?? payment?.amount.amount ?? 0,
|
|
81
|
+
currency: payment?.amount.currency ?? 'brl',
|
|
82
|
+
},
|
|
83
|
+
status: 'succeeded',
|
|
84
|
+
createdAt: new Date().toISOString(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async createCheckout(input) {
|
|
88
|
+
this.createCheckoutCalls.push({ input });
|
|
89
|
+
return {
|
|
90
|
+
id: `cs_${this.createCheckoutCalls.length}`,
|
|
91
|
+
gatewayId: `cs_${this.createCheckoutCalls.length}`,
|
|
92
|
+
provider: this.provider,
|
|
93
|
+
url: 'https://checkout.example.test/session',
|
|
94
|
+
status: 'open',
|
|
95
|
+
...(input.customerId !== undefined ? { customerId: input.customerId } : {}),
|
|
96
|
+
...(input.planId !== undefined
|
|
97
|
+
? { subscriptionId: `sub_${this.createCheckoutCalls.length}` }
|
|
98
|
+
: {}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async createSubscription(input) {
|
|
102
|
+
this.createSubscriptionCalls.push({ input });
|
|
103
|
+
const subscription = {
|
|
104
|
+
id: `sub_${this.subscriptions.size + 1}`,
|
|
105
|
+
gatewayId: `sub_${this.subscriptions.size + 1}`,
|
|
106
|
+
provider: this.provider,
|
|
107
|
+
customerId: input.customerId,
|
|
108
|
+
status: 'active',
|
|
109
|
+
planId: input.planId,
|
|
110
|
+
payload: {},
|
|
111
|
+
createdAt: new Date().toISOString(),
|
|
112
|
+
};
|
|
113
|
+
this.subscriptions.set(subscription.gatewayId, subscription);
|
|
114
|
+
return subscription;
|
|
115
|
+
}
|
|
116
|
+
async cancelSubscription(subscriptionGatewayId, options) {
|
|
117
|
+
this.cancelSubscriptionCalls.push(options !== undefined
|
|
118
|
+
? { id: subscriptionGatewayId, options }
|
|
119
|
+
: { id: subscriptionGatewayId });
|
|
120
|
+
const existing = this.subscriptions.get(subscriptionGatewayId);
|
|
121
|
+
const canceled = {
|
|
122
|
+
...(existing ?? {
|
|
123
|
+
id: subscriptionGatewayId,
|
|
124
|
+
gatewayId: subscriptionGatewayId,
|
|
125
|
+
provider: this.provider,
|
|
126
|
+
customerId: '',
|
|
127
|
+
status: 'canceled',
|
|
128
|
+
planId: '',
|
|
129
|
+
payload: {},
|
|
130
|
+
createdAt: new Date().toISOString(),
|
|
131
|
+
}),
|
|
132
|
+
status: 'canceled',
|
|
133
|
+
...(options?.atPeriodEnd === false ? { endsAt: new Date().toISOString() } : {}),
|
|
134
|
+
};
|
|
135
|
+
this.subscriptions.set(subscriptionGatewayId, canceled);
|
|
136
|
+
return canceled;
|
|
137
|
+
}
|
|
138
|
+
async findSubscription(gatewayId) {
|
|
139
|
+
return this.subscriptions.get(gatewayId) ?? null;
|
|
140
|
+
}
|
|
141
|
+
async updateSubscription(subscriptionGatewayId, input) {
|
|
142
|
+
this.updateSubscriptionCalls.push({ id: subscriptionGatewayId, input });
|
|
143
|
+
const existing = this.subscriptions.get(subscriptionGatewayId);
|
|
144
|
+
const updated = {
|
|
145
|
+
...(existing ?? {
|
|
146
|
+
id: subscriptionGatewayId,
|
|
147
|
+
gatewayId: subscriptionGatewayId,
|
|
148
|
+
provider: this.provider,
|
|
149
|
+
customerId: '',
|
|
150
|
+
status: 'active',
|
|
151
|
+
planId: '',
|
|
152
|
+
payload: {},
|
|
153
|
+
createdAt: new Date().toISOString(),
|
|
154
|
+
}),
|
|
155
|
+
...(input.amount !== undefined ? { amount: { amount: input.amount, currency: 'brl' } } : {}),
|
|
156
|
+
};
|
|
157
|
+
this.subscriptions.set(subscriptionGatewayId, updated);
|
|
158
|
+
return updated;
|
|
159
|
+
}
|
|
160
|
+
async listInvoices(_customerId) {
|
|
161
|
+
return this.invoices;
|
|
162
|
+
}
|
|
163
|
+
parseWebhook(_rawBody, _headers) {
|
|
164
|
+
const event = this.webhookEvents.shift();
|
|
165
|
+
if (!event) {
|
|
166
|
+
throw new Error('[payments] FakePaymentsDriver.parseWebhook: no webhookEvents queued.');
|
|
167
|
+
}
|
|
168
|
+
return event;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=fake_payments_driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake_payments_driver.js","sourceRoot":"","sources":["../../../src/testing/fake_payments_driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { BillingStore } from '../billing/billing_store.js';
|
|
2
|
+
/** A minimal in-memory row shape (mirrors the Lucid models' columns). */
|
|
3
|
+
export interface InMemorySubscriptionRow {
|
|
4
|
+
id: string;
|
|
5
|
+
gatewayId: string;
|
|
6
|
+
provider: string;
|
|
7
|
+
customerId: string;
|
|
8
|
+
status: string;
|
|
9
|
+
planId: string;
|
|
10
|
+
trialEndsAt: Date | null;
|
|
11
|
+
endsAt: Date | null;
|
|
12
|
+
payload: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface InMemoryPaymentRow {
|
|
15
|
+
id: string;
|
|
16
|
+
gatewayId: string;
|
|
17
|
+
provider: string;
|
|
18
|
+
status: string;
|
|
19
|
+
amount: number;
|
|
20
|
+
currency: string;
|
|
21
|
+
customerId: string | null;
|
|
22
|
+
subscriptionId: string | null;
|
|
23
|
+
paidAt: Date | null;
|
|
24
|
+
payload: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
export interface InMemoryWebhookEventRow {
|
|
27
|
+
id: string;
|
|
28
|
+
gatewayEventId: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
type: string;
|
|
31
|
+
status: 'received' | 'processed' | 'failed';
|
|
32
|
+
payload: Record<string, unknown>;
|
|
33
|
+
error: string | null;
|
|
34
|
+
}
|
|
35
|
+
/** A plain in-memory metered-usage row (mirrors the Lucid model's columns). */
|
|
36
|
+
export interface InMemoryUsageEventRow {
|
|
37
|
+
id: string;
|
|
38
|
+
subscriptionId: string | null;
|
|
39
|
+
customerId: string | null;
|
|
40
|
+
meter: string;
|
|
41
|
+
quantity: number;
|
|
42
|
+
metadata?: Record<string, unknown>;
|
|
43
|
+
recordedAt: Date;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* In-memory {@link BillingStore} for tests — no database required. Mirrors the shape of
|
|
47
|
+
* the Lucid models so the billing layer behaves identically.
|
|
48
|
+
*/
|
|
49
|
+
export declare class InMemoryBillingStore implements BillingStore<InMemorySubscriptionRow, InMemoryPaymentRow, InMemoryWebhookEventRow, InMemoryUsageEventRow> {
|
|
50
|
+
#private;
|
|
51
|
+
subscriptions: Map<string, InMemorySubscriptionRow>;
|
|
52
|
+
payments: Map<string, InMemoryPaymentRow>;
|
|
53
|
+
webhookEvents: Map<string, InMemoryWebhookEventRow>;
|
|
54
|
+
usageEvents: Map<string, InMemoryUsageEventRow>;
|
|
55
|
+
saveSubscription(sub: {
|
|
56
|
+
gatewayId: string;
|
|
57
|
+
provider: string;
|
|
58
|
+
customerId: string;
|
|
59
|
+
status: string;
|
|
60
|
+
planId: string;
|
|
61
|
+
trialEndsAt?: Date | null;
|
|
62
|
+
endsAt?: Date | null;
|
|
63
|
+
payload?: Record<string, unknown>;
|
|
64
|
+
}): Promise<InMemorySubscriptionRow>;
|
|
65
|
+
findSubscriptionByGatewayId(gatewayId: string): Promise<InMemorySubscriptionRow | null>;
|
|
66
|
+
savePayment(payment: {
|
|
67
|
+
gatewayId: string;
|
|
68
|
+
provider: string;
|
|
69
|
+
status: string;
|
|
70
|
+
amount: number;
|
|
71
|
+
currency: string;
|
|
72
|
+
customerId?: string | null;
|
|
73
|
+
subscriptionId?: string | null;
|
|
74
|
+
paidAt?: Date | null;
|
|
75
|
+
payload?: Record<string, unknown>;
|
|
76
|
+
}): Promise<InMemoryPaymentRow>;
|
|
77
|
+
findPaymentByGatewayId(gatewayId: string): Promise<InMemoryPaymentRow | null>;
|
|
78
|
+
recordWebhookEvent(event: {
|
|
79
|
+
gatewayEventId: string;
|
|
80
|
+
provider: string;
|
|
81
|
+
type: string;
|
|
82
|
+
payload: Record<string, unknown>;
|
|
83
|
+
}): Promise<InMemoryWebhookEventRow | null>;
|
|
84
|
+
markWebhookProcessed(id: string): Promise<void>;
|
|
85
|
+
markWebhookFailed(id: string, error: string): Promise<void>;
|
|
86
|
+
recordUsage(event: {
|
|
87
|
+
subscriptionId?: string | null;
|
|
88
|
+
customerId?: string;
|
|
89
|
+
meter: string;
|
|
90
|
+
quantity: number;
|
|
91
|
+
metadata?: Record<string, unknown>;
|
|
92
|
+
recordedAt?: Date;
|
|
93
|
+
}): Promise<InMemoryUsageEventRow>;
|
|
94
|
+
usageReport(query: {
|
|
95
|
+
subscriptionId?: string;
|
|
96
|
+
customerId?: string;
|
|
97
|
+
meter?: string;
|
|
98
|
+
from?: Date;
|
|
99
|
+
to?: Date;
|
|
100
|
+
}): Promise<Array<{
|
|
101
|
+
meter: string;
|
|
102
|
+
quantity: number;
|
|
103
|
+
}>>;
|
|
104
|
+
revenue(query: {
|
|
105
|
+
from?: Date;
|
|
106
|
+
to?: Date;
|
|
107
|
+
}): Promise<number>;
|
|
108
|
+
countActiveSubscriptions(): Promise<number>;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=in_memory_billing_store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in_memory_billing_store.d.ts","sourceRoot":"","sources":["../../../src/testing/in_memory_billing_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,oBACX,YACE,YAAY,CACV,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,CACtB;;IAEH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAa;IAChE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAa;IACtD,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAa;IAChE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAa;IAItD,gBAAgB,CAAC,GAAG,EAAE;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;QAC1B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAiB9B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAIvF,WAAW,CAAC,OAAO,EAAE;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkBzB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAI7E,kBAAkB,CAAC,KAAK,EAAE;QAC9B,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAgBrC,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU3D,WAAW,CAAC,KAAK,EAAE;QACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,UAAU,CAAC,EAAE,IAAI,CAAC;KACnB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAc5B,WAAW,CAAC,KAAK,EAAE;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,EAAE,CAAC,EAAE,IAAI,CAAC;KACX,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAgBjD,OAAO,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,IAAI,CAAC;QAAC,EAAE,CAAC,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAW3D,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC;CAOlD"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory {@link BillingStore} for tests — no database required. Mirrors the shape of
|
|
3
|
+
* the Lucid models so the billing layer behaves identically.
|
|
4
|
+
*/
|
|
5
|
+
export class InMemoryBillingStore {
|
|
6
|
+
subscriptions = new Map();
|
|
7
|
+
payments = new Map();
|
|
8
|
+
webhookEvents = new Map();
|
|
9
|
+
usageEvents = new Map();
|
|
10
|
+
#nextId = 1;
|
|
11
|
+
async saveSubscription(sub) {
|
|
12
|
+
const existing = this.subscriptions.get(sub.gatewayId);
|
|
13
|
+
const row = {
|
|
14
|
+
id: existing?.id ?? `sub_${this.#nextId++}`,
|
|
15
|
+
gatewayId: sub.gatewayId,
|
|
16
|
+
provider: sub.provider,
|
|
17
|
+
customerId: sub.customerId,
|
|
18
|
+
status: sub.status,
|
|
19
|
+
planId: sub.planId,
|
|
20
|
+
trialEndsAt: sub.trialEndsAt ?? null,
|
|
21
|
+
endsAt: sub.endsAt ?? null,
|
|
22
|
+
payload: sub.payload ?? {},
|
|
23
|
+
};
|
|
24
|
+
this.subscriptions.set(sub.gatewayId, row);
|
|
25
|
+
return row;
|
|
26
|
+
}
|
|
27
|
+
async findSubscriptionByGatewayId(gatewayId) {
|
|
28
|
+
return this.subscriptions.get(gatewayId) ?? null;
|
|
29
|
+
}
|
|
30
|
+
async savePayment(payment) {
|
|
31
|
+
const existing = this.payments.get(payment.gatewayId);
|
|
32
|
+
const row = {
|
|
33
|
+
id: existing?.id ?? `pay_${this.#nextId++}`,
|
|
34
|
+
gatewayId: payment.gatewayId,
|
|
35
|
+
provider: payment.provider,
|
|
36
|
+
status: payment.status,
|
|
37
|
+
amount: payment.amount,
|
|
38
|
+
currency: payment.currency,
|
|
39
|
+
customerId: payment.customerId ?? null,
|
|
40
|
+
subscriptionId: payment.subscriptionId ?? null,
|
|
41
|
+
paidAt: payment.paidAt ?? null,
|
|
42
|
+
payload: payment.payload ?? {},
|
|
43
|
+
};
|
|
44
|
+
this.payments.set(payment.gatewayId, row);
|
|
45
|
+
return row;
|
|
46
|
+
}
|
|
47
|
+
async findPaymentByGatewayId(gatewayId) {
|
|
48
|
+
return this.payments.get(gatewayId) ?? null;
|
|
49
|
+
}
|
|
50
|
+
async recordWebhookEvent(event) {
|
|
51
|
+
const existing = this.webhookEvents.get(event.gatewayEventId);
|
|
52
|
+
if (existing)
|
|
53
|
+
return null;
|
|
54
|
+
const row = {
|
|
55
|
+
id: `wh_${this.#nextId++}`,
|
|
56
|
+
gatewayEventId: event.gatewayEventId,
|
|
57
|
+
provider: event.provider,
|
|
58
|
+
type: event.type,
|
|
59
|
+
status: 'received',
|
|
60
|
+
payload: event.payload,
|
|
61
|
+
error: null,
|
|
62
|
+
};
|
|
63
|
+
this.webhookEvents.set(event.gatewayEventId, row);
|
|
64
|
+
return row;
|
|
65
|
+
}
|
|
66
|
+
async markWebhookProcessed(id) {
|
|
67
|
+
for (const row of this.webhookEvents.values()) {
|
|
68
|
+
if (row.id === id) {
|
|
69
|
+
row.status = 'processed';
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async markWebhookFailed(id, error) {
|
|
75
|
+
for (const row of this.webhookEvents.values()) {
|
|
76
|
+
if (row.id === id) {
|
|
77
|
+
row.status = 'failed';
|
|
78
|
+
row.error = error;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async recordUsage(event) {
|
|
84
|
+
const row = {
|
|
85
|
+
id: `usage_${this.#nextId++}`,
|
|
86
|
+
subscriptionId: event.subscriptionId ?? null,
|
|
87
|
+
customerId: event.customerId ?? null,
|
|
88
|
+
meter: event.meter,
|
|
89
|
+
quantity: event.quantity,
|
|
90
|
+
...(event.metadata !== undefined ? { metadata: event.metadata } : {}),
|
|
91
|
+
recordedAt: event.recordedAt ?? new Date(),
|
|
92
|
+
};
|
|
93
|
+
this.usageEvents.set(row.id, row);
|
|
94
|
+
return row;
|
|
95
|
+
}
|
|
96
|
+
async usageReport(query) {
|
|
97
|
+
const totals = new Map();
|
|
98
|
+
for (const row of this.usageEvents.values()) {
|
|
99
|
+
if (query.subscriptionId !== undefined && row.subscriptionId !== query.subscriptionId)
|
|
100
|
+
continue;
|
|
101
|
+
if (query.customerId !== undefined && row.customerId !== query.customerId) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (query.meter !== undefined && row.meter !== query.meter)
|
|
105
|
+
continue;
|
|
106
|
+
if (query.from !== undefined && row.recordedAt < query.from)
|
|
107
|
+
continue;
|
|
108
|
+
if (query.to !== undefined && row.recordedAt >= query.to)
|
|
109
|
+
continue;
|
|
110
|
+
totals.set(row.meter, (totals.get(row.meter) ?? 0) + row.quantity);
|
|
111
|
+
}
|
|
112
|
+
return [...totals.entries()].map(([meter, quantity]) => ({ meter, quantity }));
|
|
113
|
+
}
|
|
114
|
+
async revenue(query) {
|
|
115
|
+
let total = 0;
|
|
116
|
+
for (const row of this.payments.values()) {
|
|
117
|
+
if (row.status !== 'paid')
|
|
118
|
+
continue;
|
|
119
|
+
if (query.from !== undefined && row.paidAt !== null && row.paidAt < query.from)
|
|
120
|
+
continue;
|
|
121
|
+
if (query.to !== undefined && row.paidAt !== null && row.paidAt >= query.to)
|
|
122
|
+
continue;
|
|
123
|
+
total += row.amount;
|
|
124
|
+
}
|
|
125
|
+
return total;
|
|
126
|
+
}
|
|
127
|
+
async countActiveSubscriptions() {
|
|
128
|
+
let count = 0;
|
|
129
|
+
for (const row of this.subscriptions.values()) {
|
|
130
|
+
if (row.status === 'active' || row.status === 'trialing')
|
|
131
|
+
count += 1;
|
|
132
|
+
}
|
|
133
|
+
return count;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=in_memory_billing_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in_memory_billing_store.js","sourceRoot":"","sources":["../../../src/testing/in_memory_billing_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { FakePaymentsDriver } from './fake_payments_driver.js';
|
|
2
|
+
export type { FakePaymentsDriverOptions } from './fake_payments_driver.js';
|
|
3
|
+
export { InMemoryBillingStore } from './in_memory_billing_store.js';
|
|
4
|
+
export type { InMemorySubscriptionRow, InMemoryPaymentRow, InMemoryWebhookEventRow, } from './in_memory_billing_store.js';
|
|
5
|
+
export { MutableClock } from './mutable_clock.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EACV,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAMpE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|