@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.
Files changed (222) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/commands/main.d.ts +16 -0
  3. package/dist/commands/main.d.ts.map +1 -0
  4. package/dist/commands/main.js +17 -0
  5. package/dist/commands/main.js.map +1 -0
  6. package/dist/commands/make_billable.d.ts +16 -0
  7. package/dist/commands/make_billable.d.ts.map +1 -0
  8. package/dist/commands/make_billable.js +30 -0
  9. package/dist/commands/make_billable.js.map +1 -0
  10. package/dist/commands/make_webhook_handler.d.ts +20 -0
  11. package/dist/commands/make_webhook_handler.d.ts.map +1 -0
  12. package/dist/commands/make_webhook_handler.js +34 -0
  13. package/dist/commands/make_webhook_handler.js.map +1 -0
  14. package/dist/commands/payments_sync.d.ts +20 -0
  15. package/dist/commands/payments_sync.d.ts.map +1 -0
  16. package/dist/commands/payments_sync.js +95 -0
  17. package/dist/commands/payments_sync.js.map +1 -0
  18. package/dist/commands/payments_webhook.d.ts +19 -0
  19. package/dist/commands/payments_webhook.d.ts.map +1 -0
  20. package/dist/commands/payments_webhook.js +123 -0
  21. package/dist/commands/payments_webhook.js.map +1 -0
  22. package/dist/configure.d.ts +12 -0
  23. package/dist/configure.d.ts.map +1 -0
  24. package/dist/configure.js +34 -0
  25. package/dist/configure.js.map +1 -0
  26. package/dist/providers/payments_provider.d.ts +15 -0
  27. package/dist/providers/payments_provider.d.ts.map +1 -0
  28. package/dist/providers/payments_provider.js +155 -0
  29. package/dist/providers/payments_provider.js.map +1 -0
  30. package/dist/src/billing/billing_overview.d.ts +26 -0
  31. package/dist/src/billing/billing_overview.d.ts.map +1 -0
  32. package/dist/src/billing/billing_overview.js +27 -0
  33. package/dist/src/billing/billing_overview.js.map +1 -0
  34. package/dist/src/billing/billing_store.d.ts +73 -0
  35. package/dist/src/billing/billing_store.d.ts.map +1 -0
  36. package/dist/src/billing/billing_store.js +2 -0
  37. package/dist/src/billing/billing_store.js.map +1 -0
  38. package/dist/src/billing/index.d.ts +8 -0
  39. package/dist/src/billing/index.d.ts.map +1 -0
  40. package/dist/src/billing/index.js +6 -0
  41. package/dist/src/billing/index.js.map +1 -0
  42. package/dist/src/billing/lucid_billing_store.d.ts +84 -0
  43. package/dist/src/billing/lucid_billing_store.d.ts.map +1 -0
  44. package/dist/src/billing/lucid_billing_store.js +143 -0
  45. package/dist/src/billing/lucid_billing_store.js.map +1 -0
  46. package/dist/src/billing/metered_bill.d.ts +60 -0
  47. package/dist/src/billing/metered_bill.d.ts.map +1 -0
  48. package/dist/src/billing/metered_bill.js +46 -0
  49. package/dist/src/billing/metered_bill.js.map +1 -0
  50. package/dist/src/billing/mixins/index.d.ts +6 -0
  51. package/dist/src/billing/mixins/index.d.ts.map +1 -0
  52. package/dist/src/billing/mixins/index.js +6 -0
  53. package/dist/src/billing/mixins/index.js.map +1 -0
  54. package/dist/src/billing/mixins/with_billable.d.ts +23 -0
  55. package/dist/src/billing/mixins/with_billable.d.ts.map +1 -0
  56. package/dist/src/billing/mixins/with_billable.js +33 -0
  57. package/dist/src/billing/mixins/with_billable.js.map +1 -0
  58. package/dist/src/billing/mixins/with_payment.d.ts +45 -0
  59. package/dist/src/billing/mixins/with_payment.d.ts.map +1 -0
  60. package/dist/src/billing/mixins/with_payment.js +94 -0
  61. package/dist/src/billing/mixins/with_payment.js.map +1 -0
  62. package/dist/src/billing/mixins/with_subscription.d.ts +50 -0
  63. package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -0
  64. package/dist/src/billing/mixins/with_subscription.js +95 -0
  65. package/dist/src/billing/mixins/with_subscription.js.map +1 -0
  66. package/dist/src/billing/mixins/with_usage_event.d.ts +22 -0
  67. package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -0
  68. package/dist/src/billing/mixins/with_usage_event.js +39 -0
  69. package/dist/src/billing/mixins/with_usage_event.js.map +1 -0
  70. package/dist/src/billing/mixins/with_webhook_event.d.ts +21 -0
  71. package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -0
  72. package/dist/src/billing/mixins/with_webhook_event.js +42 -0
  73. package/dist/src/billing/mixins/with_webhook_event.js.map +1 -0
  74. package/dist/src/billing/webhook_dispatcher.d.ts +79 -0
  75. package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -0
  76. package/dist/src/billing/webhook_dispatcher.js +125 -0
  77. package/dist/src/billing/webhook_dispatcher.js.map +1 -0
  78. package/dist/src/billing/webhook_events.d.ts +49 -0
  79. package/dist/src/billing/webhook_events.d.ts.map +1 -0
  80. package/dist/src/billing/webhook_events.js +44 -0
  81. package/dist/src/billing/webhook_events.js.map +1 -0
  82. package/dist/src/billing/webhook_processor.d.ts +39 -0
  83. package/dist/src/billing/webhook_processor.d.ts.map +1 -0
  84. package/dist/src/billing/webhook_processor.js +209 -0
  85. package/dist/src/billing/webhook_processor.js.map +1 -0
  86. package/dist/src/define_config.d.ts +251 -0
  87. package/dist/src/define_config.d.ts.map +1 -0
  88. package/dist/src/define_config.js +67 -0
  89. package/dist/src/define_config.js.map +1 -0
  90. package/dist/src/diagnostics.d.ts +155 -0
  91. package/dist/src/diagnostics.d.ts.map +1 -0
  92. package/dist/src/diagnostics.js +153 -0
  93. package/dist/src/diagnostics.js.map +1 -0
  94. package/dist/src/driver.d.ts +222 -0
  95. package/dist/src/driver.d.ts.map +1 -0
  96. package/dist/src/driver.js +2 -0
  97. package/dist/src/driver.js.map +1 -0
  98. package/dist/src/drivers/abacate.d.ts +35 -0
  99. package/dist/src/drivers/abacate.d.ts.map +1 -0
  100. package/dist/src/drivers/abacate.js +381 -0
  101. package/dist/src/drivers/abacate.js.map +1 -0
  102. package/dist/src/drivers/asaas.d.ts +36 -0
  103. package/dist/src/drivers/asaas.d.ts.map +1 -0
  104. package/dist/src/drivers/asaas.js +455 -0
  105. package/dist/src/drivers/asaas.js.map +1 -0
  106. package/dist/src/drivers/stripe.d.ts +36 -0
  107. package/dist/src/drivers/stripe.d.ts.map +1 -0
  108. package/dist/src/drivers/stripe.js +392 -0
  109. package/dist/src/drivers/stripe.js.map +1 -0
  110. package/dist/src/drivers/woovi.d.ts +49 -0
  111. package/dist/src/drivers/woovi.d.ts.map +1 -0
  112. package/dist/src/drivers/woovi.js +339 -0
  113. package/dist/src/drivers/woovi.js.map +1 -0
  114. package/dist/src/ensure_customer.d.ts +23 -0
  115. package/dist/src/ensure_customer.d.ts.map +1 -0
  116. package/dist/src/ensure_customer.js +25 -0
  117. package/dist/src/ensure_customer.js.map +1 -0
  118. package/dist/src/hooks/webhook_handlers.d.ts +50 -0
  119. package/dist/src/hooks/webhook_handlers.d.ts.map +1 -0
  120. package/dist/src/hooks/webhook_handlers.js +53 -0
  121. package/dist/src/hooks/webhook_handlers.js.map +1 -0
  122. package/dist/src/http.d.ts +24 -0
  123. package/dist/src/http.d.ts.map +1 -0
  124. package/dist/src/http.js +52 -0
  125. package/dist/src/http.js.map +1 -0
  126. package/dist/src/index.d.ts +29 -0
  127. package/dist/src/index.d.ts.map +1 -0
  128. package/dist/src/index.js +15 -0
  129. package/dist/src/index.js.map +1 -0
  130. package/dist/src/invoice/drivers/asaas.d.ts +23 -0
  131. package/dist/src/invoice/drivers/asaas.d.ts.map +1 -0
  132. package/dist/src/invoice/drivers/asaas.js +85 -0
  133. package/dist/src/invoice/drivers/asaas.js.map +1 -0
  134. package/dist/src/invoice/drivers/enotas.d.ts +23 -0
  135. package/dist/src/invoice/drivers/enotas.d.ts.map +1 -0
  136. package/dist/src/invoice/drivers/enotas.js +83 -0
  137. package/dist/src/invoice/drivers/enotas.js.map +1 -0
  138. package/dist/src/invoice/drivers/focus.d.ts +23 -0
  139. package/dist/src/invoice/drivers/focus.d.ts.map +1 -0
  140. package/dist/src/invoice/drivers/focus.js +90 -0
  141. package/dist/src/invoice/drivers/focus.js.map +1 -0
  142. package/dist/src/invoice/drivers/plugnotas.d.ts +22 -0
  143. package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -0
  144. package/dist/src/invoice/drivers/plugnotas.js +81 -0
  145. package/dist/src/invoice/drivers/plugnotas.js.map +1 -0
  146. package/dist/src/invoice/drivers/tecnospeed.d.ts +29 -0
  147. package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -0
  148. package/dist/src/invoice/drivers/tecnospeed.js +87 -0
  149. package/dist/src/invoice/drivers/tecnospeed.js.map +1 -0
  150. package/dist/src/invoice/emit_invoice.d.ts +45 -0
  151. package/dist/src/invoice/emit_invoice.d.ts.map +1 -0
  152. package/dist/src/invoice/emit_invoice.js +72 -0
  153. package/dist/src/invoice/emit_invoice.js.map +1 -0
  154. package/dist/src/invoice/invoice_manager.d.ts +12 -0
  155. package/dist/src/invoice/invoice_manager.d.ts.map +1 -0
  156. package/dist/src/invoice/invoice_manager.js +35 -0
  157. package/dist/src/invoice/invoice_manager.js.map +1 -0
  158. package/dist/src/invoice/invoice_provider.d.ts +48 -0
  159. package/dist/src/invoice/invoice_provider.d.ts.map +1 -0
  160. package/dist/src/invoice/invoice_provider.js +2 -0
  161. package/dist/src/invoice/invoice_provider.js.map +1 -0
  162. package/dist/src/money.d.ts +11 -0
  163. package/dist/src/money.d.ts.map +1 -0
  164. package/dist/src/money.js +14 -0
  165. package/dist/src/money.js.map +1 -0
  166. package/dist/src/payments_manager.d.ts +40 -0
  167. package/dist/src/payments_manager.d.ts.map +1 -0
  168. package/dist/src/payments_manager.js +94 -0
  169. package/dist/src/payments_manager.js.map +1 -0
  170. package/dist/src/services/main.d.ts +6 -0
  171. package/dist/src/services/main.d.ts.map +1 -0
  172. package/dist/src/services/main.js +17 -0
  173. package/dist/src/services/main.js.map +1 -0
  174. package/dist/src/telescope/index.d.ts +3 -0
  175. package/dist/src/telescope/index.d.ts.map +1 -0
  176. package/dist/src/telescope/index.js +2 -0
  177. package/dist/src/telescope/index.js.map +1 -0
  178. package/dist/src/telescope/payments_watcher.d.ts +27 -0
  179. package/dist/src/telescope/payments_watcher.d.ts.map +1 -0
  180. package/dist/src/telescope/payments_watcher.js +58 -0
  181. package/dist/src/telescope/payments_watcher.js.map +1 -0
  182. package/dist/src/telescope/telescope-sdk.d.ts +21 -0
  183. package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
  184. package/dist/src/telescope/telescope-sdk.js +11 -0
  185. package/dist/src/telescope/telescope-sdk.js.map +1 -0
  186. package/dist/src/testing/fake_payments_driver.d.ts +64 -0
  187. package/dist/src/testing/fake_payments_driver.d.ts.map +1 -0
  188. package/dist/src/testing/fake_payments_driver.js +171 -0
  189. package/dist/src/testing/fake_payments_driver.js.map +1 -0
  190. package/dist/src/testing/in_memory_billing_store.d.ts +110 -0
  191. package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -0
  192. package/dist/src/testing/in_memory_billing_store.js +136 -0
  193. package/dist/src/testing/in_memory_billing_store.js.map +1 -0
  194. package/dist/src/testing/index.d.ts +6 -0
  195. package/dist/src/testing/index.d.ts.map +1 -0
  196. package/dist/src/testing/index.js +4 -0
  197. package/dist/src/testing/index.js.map +1 -0
  198. package/dist/src/testing/mutable_clock.d.ts +12 -0
  199. package/dist/src/testing/mutable_clock.d.ts.map +1 -0
  200. package/dist/src/testing/mutable_clock.js +20 -0
  201. package/dist/src/testing/mutable_clock.js.map +1 -0
  202. package/dist/src/types.d.ts +178 -0
  203. package/dist/src/types.d.ts.map +1 -0
  204. package/dist/src/types.js +9 -0
  205. package/dist/src/types.js.map +1 -0
  206. package/dist/src/webhook_handlers.d.ts +76 -0
  207. package/dist/src/webhook_handlers.d.ts.map +1 -0
  208. package/dist/src/webhook_handlers.js +128 -0
  209. package/dist/src/webhook_handlers.js.map +1 -0
  210. package/dist/src/webhook_security.d.ts +29 -0
  211. package/dist/src/webhook_security.d.ts.map +1 -0
  212. package/dist/src/webhook_security.js +53 -0
  213. package/dist/src/webhook_security.js.map +1 -0
  214. package/dist/stubs/config/payments.stub +101 -0
  215. package/dist/stubs/database/migrations/create_billing_tables.stub +90 -0
  216. package/dist/stubs/main.d.ts +9 -0
  217. package/dist/stubs/main.d.ts.map +1 -0
  218. package/dist/stubs/main.js +16 -0
  219. package/dist/stubs/main.js.map +1 -0
  220. package/dist/stubs/make/billable/main.stub +28 -0
  221. package/dist/stubs/make/webhook_handler/main.stub +29 -0
  222. 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":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,OAAO,EACP,MAAM,EACN,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,uEAAwE;IAEjG,kEAAkE;IAClE,aAAa,EAAE,YAAY,EAAE,CAAC;IAG9B,mBAAmB,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,EAAE,CAAM;IACvF,WAAW,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,EAAE,CAAM;IACvE,WAAW,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAClE,mBAAmB,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,EAAE,CAAM;IACvF,uBAAuB,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,EAAE,CAAM;IAC/F,uBAAuB,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,EAAE,CAAM;IACpF,uBAAuB,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,uBAAuB,CAAA;KAAE,EAAE,CAAM;IAG/E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;IAC7C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;IAC3C,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAa;IACrD,QAAQ,EAAE,OAAO,EAAE,CAAM;gBAEb,OAAO,GAAE,yBAA8B;IAK7C,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;IAYzF,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAI1D,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GACrD,OAAO,CAAC,QAAQ,CAAC;IAad,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBxE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIvD,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBlE,cAAc,CAClB,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GACrD,OAAO,CAAC,eAAe,CAAC;IAerB,kBAAkB,CACtB,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC;IAgBlB,kBAAkB,CACtB,qBAAqB,EAAE,MAAM,EAC7B,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAClC,OAAO,CAAC,YAAY,CAAC;IAyBlB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAIjE,kBAAkB,CACtB,qBAAqB,EAAE,MAAM,EAC7B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAoBlB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAI3D,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACtD,YAAY;CAOhB"}
@@ -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":"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"}
@@ -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,4 @@
1
+ export { FakePaymentsDriver } from './fake_payments_driver.js';
2
+ export { InMemoryBillingStore } from './in_memory_billing_store.js';
3
+ export { MutableClock } from './mutable_clock.js';
4
+ //# sourceMappingURL=index.js.map
@@ -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"}