@classytic/revenue 1.1.3 → 2.0.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 (82) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +638 -632
  3. package/dist/audit-B39B0Sdq.mjs +53 -0
  4. package/dist/audit-DZ0eTr9g.d.mts +89 -0
  5. package/dist/bridges/index.d.mts +2 -0
  6. package/dist/bridges/index.mjs +1 -0
  7. package/dist/context-DRqSeTPM.d.mts +35 -0
  8. package/dist/core/state-machines.d.mts +35 -0
  9. package/dist/core/state-machines.mjs +134 -0
  10. package/dist/engine-types-CcjIb4Fy.d.mts +611 -0
  11. package/dist/enums/index.d.mts +3 -157
  12. package/dist/enums/index.mjs +3 -55
  13. package/dist/errors-DHa8JVQ-.mjs +92 -0
  14. package/dist/escrow.schema-BBv9oVEW.mjs +322 -0
  15. package/dist/escrow.schema-CC8XuD46.d.mts +629 -0
  16. package/dist/event-constants-CEMitnIV.mjs +53 -0
  17. package/dist/events/index.d.mts +3 -0
  18. package/dist/events/index.mjs +4 -0
  19. package/dist/index.d.mts +77 -9
  20. package/dist/index.mjs +465 -29
  21. package/dist/monetization.enums-BtiU3t8o.mjs +39 -0
  22. package/dist/monetization.enums-D2xbxXJM.d.mts +34 -0
  23. package/dist/plugins/plugin.interface.d.mts +28 -0
  24. package/dist/plugins/plugin.interface.mjs +26 -0
  25. package/dist/providers/index.d.mts +2 -3
  26. package/dist/providers/index.mjs +2 -2
  27. package/dist/{base-DCoyIUj6.mjs → registry-DhFMsSn5.mjs} +34 -36
  28. package/dist/{base-CsTlVQJe.d.mts → registry-SvIGPAx_.d.mts} +73 -66
  29. package/dist/repositories/create-repositories.d.mts +21 -0
  30. package/dist/repositories/create-repositories.mjs +12 -0
  31. package/dist/revenue-bridges-sdlrR85c.d.mts +145 -0
  32. package/dist/revenue-event-catalog-BX3g7RUi.d.mts +823 -0
  33. package/dist/revenue-event-catalog-LqxPnsU_.mjs +388 -0
  34. package/dist/settlement.repository-Cy3mMWGH.mjs +771 -0
  35. package/dist/shared/index.d.mts +2 -0
  36. package/dist/shared/index.mjs +4 -0
  37. package/dist/split.enums-CQE3ekH1.mjs +172 -0
  38. package/dist/split.enums-Dw4zCrcZ.d.mts +154 -0
  39. package/dist/splits-BAfY-a9P.mjs +123 -0
  40. package/dist/validators/index.d.mts +2 -0
  41. package/dist/validators/index.mjs +3 -0
  42. package/package.json +32 -36
  43. package/dist/application/services/index.d.mts +0 -4
  44. package/dist/application/services/index.mjs +0 -3
  45. package/dist/category-resolver-DV83N8ok.mjs +0 -284
  46. package/dist/commission-split-BzB8cd39.mjs +0 -485
  47. package/dist/core/events.d.mts +0 -294
  48. package/dist/core/events.mjs +0 -100
  49. package/dist/core/index.d.mts +0 -9
  50. package/dist/core/index.mjs +0 -8
  51. package/dist/errors-CorrWz7A.d.mts +0 -787
  52. package/dist/escrow.enums-CZGrrdg7.mjs +0 -101
  53. package/dist/escrow.enums-DwdLuuve.d.mts +0 -78
  54. package/dist/idempotency-DaYcUGY1.mjs +0 -172
  55. package/dist/index-Dsp7H5Wb.d.mts +0 -471
  56. package/dist/infrastructure/plugins/index.d.mts +0 -239
  57. package/dist/infrastructure/plugins/index.mjs +0 -345
  58. package/dist/money-CvrDOijQ.mjs +0 -271
  59. package/dist/money-DPG8AtJ8.d.mts +0 -112
  60. package/dist/payment.enums-HAuAS9Pp.d.mts +0 -70
  61. package/dist/payment.enums-tEFVa-Xp.mjs +0 -69
  62. package/dist/plugin-BbK0OVHy.d.mts +0 -327
  63. package/dist/plugin-Cd_V04Em.mjs +0 -210
  64. package/dist/reconciliation/index.d.mts +0 -193
  65. package/dist/reconciliation/index.mjs +0 -192
  66. package/dist/retry-HHCOXYdn.d.mts +0 -186
  67. package/dist/revenue-9scqKSef.mjs +0 -553
  68. package/dist/schemas/index.d.mts +0 -2665
  69. package/dist/schemas/index.mjs +0 -717
  70. package/dist/schemas/validation.d.mts +0 -375
  71. package/dist/schemas/validation.mjs +0 -325
  72. package/dist/settlement.enums-DFhkqZEY.d.mts +0 -132
  73. package/dist/settlement.schema-D5uWB5tP.d.mts +0 -344
  74. package/dist/settlement.service-BxuiHpNC.d.mts +0 -594
  75. package/dist/settlement.service-CUxbUTzT.mjs +0 -2510
  76. package/dist/split.enums-BrjabxIX.mjs +0 -86
  77. package/dist/split.enums-DmskfLOM.d.mts +0 -43
  78. package/dist/tax-BoCt5cEd.d.mts +0 -61
  79. package/dist/tax-EQ15DO81.mjs +0 -162
  80. package/dist/transaction.enums-pCyMFT4Z.mjs +0 -96
  81. package/dist/utils/index.d.mts +0 -428
  82. package/dist/utils/index.mjs +0 -346
@@ -0,0 +1,611 @@
1
+ import { t as RevenueContext } from "./context-DRqSeTPM.mjs";
2
+ import { t as RevenueBridges } from "./revenue-bridges-sdlrR85c.mjs";
3
+ import { o as PaymentProvider, t as ProviderRegistry } from "./registry-SvIGPAx_.mjs";
4
+ import { RepositoryPluginBundle, RevenueRepositories } from "./repositories/create-repositories.mjs";
5
+ import { PluginType, Repository } from "@classytic/mongokit";
6
+ import { TenantConfig } from "@classytic/primitives/tenant";
7
+ import mongoose, { Connection, Model, Schema } from "mongoose";
8
+ import { EventTransport } from "@classytic/primitives/events";
9
+ import { OutboxStore } from "@classytic/primitives/outbox";
10
+
11
+ //#region src/models/transaction.schema.d.ts
12
+ interface TransactionDocument {
13
+ _id: mongoose.Types.ObjectId;
14
+ publicId: string;
15
+ organizationId?: string;
16
+ customerId?: string | null;
17
+ type: string;
18
+ flow: 'inflow' | 'outflow';
19
+ tags: string[];
20
+ amount: number;
21
+ currency: string;
22
+ fee: number;
23
+ tax: number;
24
+ net: number;
25
+ taxDetails?: {
26
+ type?: string;
27
+ rate?: number;
28
+ isInclusive?: boolean;
29
+ };
30
+ method: string;
31
+ status: string;
32
+ gateway?: {
33
+ type: string;
34
+ sessionId?: string;
35
+ paymentIntentId?: string;
36
+ chargeId?: string;
37
+ metadata?: Record<string, unknown>;
38
+ verificationData?: Record<string, unknown>;
39
+ };
40
+ paymentDetails?: Record<string, unknown>;
41
+ commission?: {
42
+ rate: number;
43
+ grossAmount: number;
44
+ gatewayFeeRate: number;
45
+ gatewayFeeAmount: number;
46
+ netAmount: number;
47
+ status: string;
48
+ };
49
+ splits?: Array<{
50
+ type: string;
51
+ recipientId: string;
52
+ recipientType: string;
53
+ rate: number;
54
+ grossAmount: number;
55
+ gatewayFeeRate: number;
56
+ gatewayFeeAmount: number;
57
+ netAmount: number;
58
+ status: string;
59
+ }>;
60
+ hold?: {
61
+ status: string;
62
+ heldAmount: number;
63
+ releasedAmount: number;
64
+ reason: string;
65
+ heldAt: Date;
66
+ holdUntil?: Date;
67
+ releasedAt?: Date;
68
+ cancelledAt?: Date;
69
+ releases: Array<{
70
+ amount: number;
71
+ recipientId: string;
72
+ recipientType: string;
73
+ releasedAt: Date;
74
+ releasedBy?: string;
75
+ reason?: string;
76
+ metadata?: Record<string, unknown>;
77
+ }>;
78
+ metadata?: Record<string, unknown>;
79
+ };
80
+ sourceId?: string;
81
+ sourceModel?: string;
82
+ relatedTransactionId?: mongoose.Types.ObjectId;
83
+ refundedAmount?: number;
84
+ refundedAt?: Date;
85
+ failureReason?: string;
86
+ failedAt?: Date;
87
+ verifiedAt?: Date;
88
+ verifiedBy?: string;
89
+ webhook?: {
90
+ eventId: string;
91
+ eventType: string;
92
+ receivedAt: Date;
93
+ processedAt: Date;
94
+ data: Record<string, unknown>;
95
+ };
96
+ idempotencyKey?: string;
97
+ metadata?: Record<string, unknown>;
98
+ deletedAt?: Date | null;
99
+ createdAt: Date;
100
+ updatedAt: Date;
101
+ }
102
+ //#endregion
103
+ //#region src/models/subscription.schema.d.ts
104
+ interface SubscriptionDocument {
105
+ _id: mongoose.Types.ObjectId;
106
+ publicId: string;
107
+ organizationId?: string;
108
+ customerId?: string | null;
109
+ planKey: string;
110
+ amount: number;
111
+ currency?: string;
112
+ status: string;
113
+ isActive: boolean;
114
+ transactionId?: mongoose.Types.ObjectId | null;
115
+ paymentIntentId?: string | null;
116
+ startDate?: Date;
117
+ endDate?: Date;
118
+ activatedAt?: Date;
119
+ pausedAt?: Date;
120
+ pauseReason?: string;
121
+ canceledAt?: Date;
122
+ cancelAt?: Date;
123
+ cancellationReason?: string;
124
+ renewalTransactionId?: mongoose.Types.ObjectId;
125
+ renewalCount: number;
126
+ metadata?: Record<string, unknown>;
127
+ deletedAt?: Date | null;
128
+ createdAt: Date;
129
+ updatedAt: Date;
130
+ }
131
+ //#endregion
132
+ //#region src/models/settlement.schema.d.ts
133
+ interface SettlementDocument {
134
+ _id: mongoose.Types.ObjectId;
135
+ publicId: string;
136
+ organizationId: string;
137
+ recipientId: string;
138
+ recipientType: string;
139
+ type: string;
140
+ status: string;
141
+ payoutMethod: string;
142
+ amount: number;
143
+ currency: string;
144
+ sourceTransactionIds: mongoose.Types.ObjectId[];
145
+ sourceSplitIds: string[];
146
+ bankTransferDetails?: Record<string, unknown>;
147
+ mobileWalletDetails?: Record<string, unknown>;
148
+ cryptoDetails?: Record<string, unknown>;
149
+ scheduledAt: Date;
150
+ processedAt?: Date;
151
+ completedAt?: Date;
152
+ failedAt?: Date;
153
+ cancelledAt?: Date;
154
+ failureReason?: string;
155
+ failureCode?: string;
156
+ retryCount: number;
157
+ notes?: string;
158
+ metadata?: Record<string, unknown>;
159
+ deletedAt?: Date | null;
160
+ createdAt: Date;
161
+ updatedAt: Date;
162
+ }
163
+ //#endregion
164
+ //#region src/models/create-models.d.ts
165
+ interface RevenueModels {
166
+ Transaction: Model<TransactionDocument>;
167
+ Subscription?: Model<SubscriptionDocument>;
168
+ Settlement?: Model<SettlementDocument>;
169
+ }
170
+ interface RevenueSchemaOptions {
171
+ transaction?: {
172
+ extraFields?: Record<string, unknown>;
173
+ extraIndexes?: Array<{
174
+ fields: Record<string, 1 | -1>;
175
+ options?: Record<string, unknown>;
176
+ }>;
177
+ };
178
+ subscription?: {
179
+ extraFields?: Record<string, unknown>;
180
+ extraIndexes?: Array<{
181
+ fields: Record<string, 1 | -1>;
182
+ options?: Record<string, unknown>;
183
+ }>;
184
+ };
185
+ settlement?: {
186
+ extraFields?: Record<string, unknown>;
187
+ extraIndexes?: Array<{
188
+ fields: Record<string, 1 | -1>;
189
+ options?: Record<string, unknown>;
190
+ }>;
191
+ };
192
+ }
193
+ //#endregion
194
+ //#region src/repositories/transaction.repository.d.ts
195
+ interface TransactionRepoDeps {
196
+ events: EventTransport;
197
+ /**
198
+ * Optional host-owned outbox store (PACKAGE_RULES §5.5 + P8). When present,
199
+ * every domain event is persisted via `outbox.save(event)` before the
200
+ * in-process `events.publish(event)` so the host's relay (arc's EventOutbox,
201
+ * a Postgres LISTEN/NOTIFY pump, Kafka Connect, …) can replay on transport
202
+ * failure. When absent, events fire through `events.publish` only.
203
+ */
204
+ outbox?: OutboxStore | undefined;
205
+ providers: ProviderRegistry;
206
+ bridges: RevenueBridges;
207
+ commission?: CommissionConfig;
208
+ defaultCurrency: string;
209
+ logger?: {
210
+ error(...args: unknown[]): void;
211
+ } | undefined;
212
+ }
213
+ /**
214
+ * TransactionRepository — extends mongokit Repository.
215
+ *
216
+ * CRUD inherited: getAll, getById, getByQuery, create, update, delete, count, exists.
217
+ * Domain verbs: createPaymentIntent, verify, refund, handleWebhook, hold, release, split.
218
+ *
219
+ * All domain verbs return raw mongokit docs — no custom envelopes.
220
+ * Composite results (refund creates a new doc) are stored in metadata on the primary doc.
221
+ */
222
+ declare class TransactionRepository extends Repository<TransactionDocument> {
223
+ private deps;
224
+ constructor(model: Model<TransactionDocument>, plugins?: PluginType[]);
225
+ inject(deps: TransactionRepoDeps): void;
226
+ /**
227
+ * Thread `ctx.organizationId` (and future ctx fields) into mongokit
228
+ * options so the `multiTenantPlugin` can auto-scope filters, queries,
229
+ * and inserts. Merges any caller-supplied extras. Centralizing this
230
+ * here means every domain verb participates in scope isolation without
231
+ * per-call boilerplate.
232
+ */
233
+ private optsFromCtx;
234
+ /**
235
+ * Save an event to the host-owned outbox, session-bound when available.
236
+ *
237
+ * When `session` is passed, the outbox row commits atomically with the
238
+ * business write (P8 true session-bound write). When absent, the save
239
+ * happens after commit — still durable via the host's relay, but with a
240
+ * small at-most-once window on process crash.
241
+ *
242
+ * Isolated try/catch: an outbox failure never throws out of this helper;
243
+ * the caller still issues a transport.publish.
244
+ */
245
+ private saveToOutbox;
246
+ /**
247
+ * Publish an event to the in-process `EventTransport` after commit.
248
+ * Transport failure is logged — the host relay will still redeliver from
249
+ * the outbox, so in-process subscribers missing an event is recoverable.
250
+ */
251
+ private publishToTransport;
252
+ /**
253
+ * Non-transactional dispatch (used by verbs that don't open their own
254
+ * `withTransaction` block): outbox.save (session-bound when ctx provides
255
+ * one) → transport.publish. Matches arc's EventOutbox + MemoryEventTransport
256
+ * wiring bit-for-bit.
257
+ */
258
+ private dispatch;
259
+ /** Creates transaction + calls provider. Returns the created transaction doc. */
260
+ createPaymentIntent(params: {
261
+ data?: Record<string, unknown>;
262
+ planKey?: string;
263
+ monetizationType?: string;
264
+ amount: number;
265
+ currency?: string;
266
+ gateway: string;
267
+ paymentData?: Record<string, unknown>;
268
+ metadata?: Record<string, unknown>;
269
+ idempotencyKey?: string;
270
+ }, ctx?: RevenueContext): Promise<TransactionDocument>;
271
+ /** Verifies payment via provider, updates status. Returns the updated doc. */
272
+ verify(paymentIntentId: string, options?: {
273
+ verifiedBy?: string;
274
+ }, ctx?: RevenueContext): Promise<TransactionDocument>;
275
+ /**
276
+ * Creates refund transaction, updates original. Returns the refund transaction doc.
277
+ *
278
+ * The provider call happens OUTSIDE the transaction — it's a non-idempotent external
279
+ * side effect we can't roll back. The two Mongo writes (create refund + update original)
280
+ * run inside `withTransaction` so they commit atomically or both abort. Bridges and
281
+ * event emission run AFTER commit because they're independent side effects; rolling
282
+ * them back would not undo external state anyway.
283
+ *
284
+ * Powered by mongokit 3.6's module-level `withTransaction` helper. Automatically
285
+ * retries on `TransientTransactionError` / `UnknownTransactionCommitResult`.
286
+ */
287
+ refund(transactionId: string, amount?: number | null, options?: {
288
+ reason?: string;
289
+ }, ctx?: RevenueContext): Promise<TransactionDocument>;
290
+ /** Handles provider webhook. Returns the updated transaction doc (or null if not found). */
291
+ handleWebhook(providerName: string, payload: unknown, headers?: Record<string, string>, ctx?: RevenueContext): Promise<TransactionDocument | null>;
292
+ /** Places hold on verified transaction. Returns the updated doc. */
293
+ hold(transactionId: string, options?: {
294
+ amount?: number;
295
+ reason?: string;
296
+ holdUntil?: Date;
297
+ metadata?: Record<string, unknown>;
298
+ }, ctx?: RevenueContext): Promise<TransactionDocument>;
299
+ /**
300
+ * Releases held funds. Returns the updated transaction doc.
301
+ *
302
+ * The hold update and the escrow_release transaction create happen inside
303
+ * `withTransaction` — a mid-flow crash can't leave the hold marked released
304
+ * without the corresponding outflow record (or vice versa).
305
+ */
306
+ release(transactionId: string, options: {
307
+ amount?: number;
308
+ recipientId: string;
309
+ recipientType: string;
310
+ reason?: string;
311
+ releasedBy?: string;
312
+ createTransaction?: boolean;
313
+ metadata?: Record<string, unknown>;
314
+ }, ctx?: RevenueContext): Promise<TransactionDocument>;
315
+ /**
316
+ * Splits payment among recipients. Returns the updated transaction doc.
317
+ *
318
+ * N + 2 writes (one create per recipient, one update on the parent, one
319
+ * platform_revenue create) all commit atomically. Partial splits are the
320
+ * worst class of bug in a payments system — this is exactly what
321
+ * `withTransaction` is for.
322
+ */
323
+ split(transactionId: string, rules: Array<{
324
+ type: string;
325
+ recipientId: string;
326
+ recipientType: string;
327
+ rate: number;
328
+ }>, ctx?: RevenueContext): Promise<TransactionDocument>;
329
+ }
330
+ //#endregion
331
+ //#region src/repositories/subscription.repository.d.ts
332
+ interface SubscriptionRepoDeps {
333
+ events: EventTransport;
334
+ /** Host-owned outbox (PACKAGE_RULES §5.5 + P8). See TransactionRepoDeps. */
335
+ outbox?: OutboxStore | undefined;
336
+ logger?: {
337
+ error(...args: unknown[]): void;
338
+ } | undefined;
339
+ }
340
+ /**
341
+ * SubscriptionRepository — data layer + domain verbs.
342
+ *
343
+ * CRUD inherited from mongokit. Domain verbs: activate, cancel, pause, resume.
344
+ *
345
+ * Events: each domain verb calls `this.deps.events.publish(createEvent(...))`
346
+ * with a fully-qualified `REVENUE_EVENTS.*` name. Hosts can subscribe glob-style
347
+ * via `revenue.events.subscribe('revenue:subscription.*', handler)` — the
348
+ * injected transport is arc-compatible (PACKAGE_RULES §13–§14).
349
+ */
350
+ declare class SubscriptionRepository extends Repository<SubscriptionDocument> {
351
+ private deps;
352
+ constructor(model: Model<SubscriptionDocument>, plugins?: PluginType[]);
353
+ inject(deps: SubscriptionRepoDeps): void;
354
+ /**
355
+ * Host-owned outbox save → in-process transport publish (PACKAGE_RULES P8).
356
+ * Session-bound when `ctx.session` is present (atomic outbox row write).
357
+ */
358
+ private dispatch;
359
+ activate(subscriptionId: string, options?: {
360
+ timestamp?: Date;
361
+ }, ctx?: RevenueContext): Promise<SubscriptionDocument>;
362
+ cancel(subscriptionId: string, options?: {
363
+ immediate?: boolean;
364
+ reason?: string;
365
+ }, ctx?: RevenueContext): Promise<SubscriptionDocument>;
366
+ pause(subscriptionId: string, options?: {
367
+ reason?: string;
368
+ }, ctx?: RevenueContext): Promise<SubscriptionDocument>;
369
+ resume(subscriptionId: string, options?: {
370
+ extendPeriod?: boolean;
371
+ }, ctx?: RevenueContext): Promise<SubscriptionDocument>;
372
+ }
373
+ //#endregion
374
+ //#region src/repositories/settlement.repository.d.ts
375
+ interface SettlementRepoDeps {
376
+ events: EventTransport;
377
+ /** Host-owned outbox (PACKAGE_RULES §5.5 + P8). See TransactionRepoDeps. */
378
+ outbox?: OutboxStore | undefined;
379
+ bridges: RevenueBridges;
380
+ logger?: {
381
+ error(...args: unknown[]): void;
382
+ } | undefined;
383
+ }
384
+ interface SettlementProcessingError {
385
+ settlementId: SettlementDocument['_id'];
386
+ error: unknown;
387
+ }
388
+ /**
389
+ * SettlementRepository — data layer + domain verbs.
390
+ *
391
+ * CRUD inherited from mongokit. Domain verbs: schedule, processPending, complete, fail.
392
+ *
393
+ * Events are published via the injected `events` transport (arc-compatible).
394
+ * Hosts subscribe glob-style via `revenue.events.subscribe('revenue:settlement.*', h)`.
395
+ * See PACKAGE_RULES §13–§14.
396
+ */
397
+ declare class SettlementRepository extends Repository<SettlementDocument> {
398
+ private deps;
399
+ constructor(model: Model<SettlementDocument>, plugins?: PluginType[]);
400
+ inject(deps: SettlementRepoDeps): void;
401
+ /**
402
+ * Host-owned outbox save → in-process transport publish (PACKAGE_RULES P8).
403
+ * Session-bound when `ctx.session` is present (atomic outbox row write).
404
+ */
405
+ private dispatch;
406
+ schedule(params: {
407
+ organizationId: string;
408
+ recipientId: string;
409
+ recipientType: string;
410
+ type: string;
411
+ amount: number;
412
+ currency: string;
413
+ payoutMethod: string;
414
+ sourceTransactionIds?: string[];
415
+ sourceSplitIds?: string[];
416
+ scheduledAt?: Date;
417
+ bankTransferDetails?: Record<string, unknown>;
418
+ mobileWalletDetails?: Record<string, unknown>;
419
+ cryptoDetails?: Record<string, unknown>;
420
+ notes?: string;
421
+ metadata?: Record<string, unknown>;
422
+ }, ctx?: RevenueContext): Promise<SettlementDocument>;
423
+ processPending(options?: {
424
+ limit?: number;
425
+ organizationId?: string;
426
+ payoutMethod?: string;
427
+ dryRun?: boolean;
428
+ }, ctx?: RevenueContext): Promise<{
429
+ processed: number;
430
+ succeeded: number;
431
+ failed: number;
432
+ settlements: SettlementDocument[];
433
+ errors: SettlementProcessingError[];
434
+ }>;
435
+ complete(settlementId: string, details?: {
436
+ transferReference?: string;
437
+ transferredAt?: Date;
438
+ transactionHash?: string;
439
+ notes?: string;
440
+ metadata?: Record<string, unknown>;
441
+ }, ctx?: RevenueContext): Promise<SettlementDocument>;
442
+ fail(settlementId: string, reason: string, options?: {
443
+ code?: string;
444
+ retry?: boolean;
445
+ }, ctx?: RevenueContext): Promise<SettlementDocument>;
446
+ }
447
+ //#endregion
448
+ //#region src/engine/engine-types.d.ts
449
+ interface CommissionConfig {
450
+ defaultRate: number;
451
+ gatewayFeeRate?: number | undefined;
452
+ categoryRates?: Record<string, number> | undefined;
453
+ gatewayRates?: Record<string, number> | undefined;
454
+ }
455
+ interface RetryConfig {
456
+ maxAttempts?: number | undefined;
457
+ baseDelay?: number | undefined;
458
+ }
459
+ interface RevenueConfig {
460
+ connection: Connection;
461
+ defaultCurrency: string;
462
+ /**
463
+ * Event transport — structurally compatible with `@classytic/arc`'s
464
+ * `EventTransport`. Drop in any arc transport (Memory/Redis/Kafka) and it
465
+ * works without an adapter. When omitted, the engine uses
466
+ * `InProcessRevenueBus` (a ~50-line match of arc's `MemoryEventTransport`).
467
+ */
468
+ eventTransport?: EventTransport | undefined;
469
+ /**
470
+ * Host-owned transactional outbox store (PACKAGE_RULES §5.5 + P8).
471
+ * Structurally identical to `@classytic/arc`'s `OutboxStore` by design —
472
+ * primitives is the source of truth for the contract and arc mirrors it.
473
+ *
474
+ * **Host responsibility.** Revenue does NOT ship a durable store. Arc 2.10
475
+ * only ships `MemoryOutboxStore` (dev) + the `OutboxStore` interface — the
476
+ * host wires durability. The canonical production wiring uses arc's
477
+ * `repositoryAsOutboxStore` adapter over a mongokit `Repository`:
478
+ *
479
+ * ```ts
480
+ * import mongoose, { Schema } from 'mongoose';
481
+ * import {
482
+ * Repository,
483
+ * methodRegistryPlugin,
484
+ * batchOperationsPlugin,
485
+ * } from '@classytic/mongokit';
486
+ * import { EventOutbox, repositoryAsOutboxStore } from '@classytic/arc/events';
487
+ * import { createRevenue } from '@classytic/revenue';
488
+ *
489
+ * // Arc owns the on-disk doc shape — strict:false forwards every field
490
+ * // (see arc's events.mdx "Why strict: false").
491
+ * const OutboxModel = mongoose.model(
492
+ * 'ArcOutbox',
493
+ * new Schema({}, { strict: false, timestamps: false, _id: false }),
494
+ * 'event_outbox',
495
+ * );
496
+ *
497
+ * // Required plugins: the adapter calls `create` / `findAll` /
498
+ * // `findOneAndUpdate` (base Repository) + `deleteMany` (batchOperations).
499
+ * const outboxRepo = new Repository(OutboxModel, [
500
+ * methodRegistryPlugin(),
501
+ * batchOperationsPlugin(),
502
+ * ]);
503
+ * const outbox = repositoryAsOutboxStore(outboxRepo);
504
+ *
505
+ * const engine = await createRevenue({
506
+ * connection: mongoose.connection,
507
+ * defaultCurrency: 'USD',
508
+ * outbox, // revenue's dispatch saves here
509
+ * eventTransport: app.events, // arc transport for in-process subscribers
510
+ * // ...
511
+ * });
512
+ *
513
+ * // Relay + DLQ live in the host, not the package:
514
+ * const relay = new EventOutbox({ store: outbox, transport: app.events });
515
+ * setInterval(() => relay.relay(), 1_000);
516
+ * ```
517
+ *
518
+ * **Session-bound atomicity.** Revenue's transactional verbs (`refund`,
519
+ * `release`, `split`) open a mongokit `withTransaction` and pass the
520
+ * mongoose `ClientSession` into `outbox.save(event, { session })`, so the
521
+ * outbox row commits atomically with the business writes. Non-transactional
522
+ * verbs (`createPaymentIntent`, `verify`, `handleWebhook`, `hold`) forward
523
+ * `ctx.session` when the host is coordinating its own transaction — pass
524
+ * `{ session }` in `RevenueContext` to participate.
525
+ *
526
+ * **Non-arc hosts.** Any `OutboxStore` works — implement the three-method
527
+ * floor (`save` / `getPending` / `acknowledge`) over Postgres / Redis /
528
+ * Kafka / SQS. When omitted, events flow to `eventTransport` only
529
+ * (durability becomes transport-level, not at-least-once).
530
+ */
531
+ outbox?: OutboxStore | undefined;
532
+ modules?: {
533
+ subscription?: boolean | undefined;
534
+ escrow?: boolean | undefined;
535
+ settlement?: boolean | undefined;
536
+ commission?: CommissionConfig | boolean | undefined;
537
+ } | undefined;
538
+ providers?: Record<string, PaymentProvider> | undefined;
539
+ bridges?: RevenueBridges | undefined;
540
+ repositoryPlugins?: RepositoryPluginBundle | undefined;
541
+ schemaOptions?: RevenueSchemaOptions | undefined;
542
+ /**
543
+ * Tenant scope configuration. Delegates to `@classytic/primitives`'
544
+ * `TenantConfig`. Field names match mongokit's `MultiTenantOptions` so
545
+ * the resolved config forwards directly into `multiTenantPlugin(...)`.
546
+ *
547
+ * - `undefined` / `true` → default field strategy, ObjectId storage.
548
+ * - `false` → single-tenant (no plugin, field still present, not required).
549
+ * - `{ fieldType: 'string' }` → string orgIds (UUID/slug hosts).
550
+ * - `{ strategy: 'custom', resolve: ... }` → composite / derived scope.
551
+ *
552
+ * See PACKAGE_RULES.md §9.
553
+ */
554
+ scope?: TenantConfig | boolean | undefined;
555
+ commission?: CommissionConfig | undefined;
556
+ retry?: RetryConfig | undefined;
557
+ circuitBreaker?: boolean | undefined;
558
+ /**
559
+ * Set `false` to disable Mongoose auto-index on boot. Indexes are then
560
+ * managed explicitly via `engine.syncIndexes()` or a deploy-time script.
561
+ */
562
+ autoIndex?: boolean | Partial<Record<'Transaction' | 'Subscription' | 'Settlement', boolean>> | undefined;
563
+ /**
564
+ * Optional prefix prepended to every physical collection this package
565
+ * creates (see PACKAGE_RULES.md §20.1). Unset → default names
566
+ * (`revenue_transactions`, `revenue_subscriptions`, `revenue_settlements`).
567
+ * Model names and `ref:` populate are unaffected.
568
+ */
569
+ collectionPrefix?: string | undefined;
570
+ /**
571
+ * When true, existing Mongoose models with revenue's names are deleted
572
+ * from the connection before re-registering. Hot-reload / test fixtures
573
+ * only. Default `false` — collision throws `RevenueModelCollisionError`.
574
+ * Hosts that need two revenue engines should use two Mongoose connections
575
+ * (`mongoose.createConnection(...)`). See PACKAGE_RULES.md §21.
576
+ */
577
+ forceRecreate?: boolean | undefined;
578
+ logger?: {
579
+ info: (...args: unknown[]) => void;
580
+ error: (...args: unknown[]) => void;
581
+ warn: (...args: unknown[]) => void;
582
+ debug: (...args: unknown[]) => void;
583
+ } | undefined;
584
+ }
585
+ /**
586
+ * RevenueEngine — no service facade.
587
+ *
588
+ * Repositories ARE the domain layer. CRUD is inherited from mongokit.
589
+ * Domain verbs (verify, refund, hold, activate, etc.) live on repositories.
590
+ * Arc's BaseController/adapter plugs into repositories directly.
591
+ *
592
+ * `events` is structurally compatible with `@classytic/arc`'s
593
+ * `EventTransport`. Hosts subscribe glob-style:
594
+ *
595
+ * await revenue.events.subscribe('revenue:payment.*', handler);
596
+ *
597
+ * and the same transport can be wired into the outbox relay for durable
598
+ * delivery (see mongokit's `outbox-recipe.ts`). See PACKAGE_RULES §13.
599
+ */
600
+ interface RevenueEngine {
601
+ config: Readonly<RevenueConfig>;
602
+ models: RevenueModels;
603
+ repositories: RevenueRepositories;
604
+ providers: ProviderRegistry;
605
+ events: EventTransport;
606
+ /** Explicitly build all schema-declared indexes. Non-destructive. */
607
+ syncIndexes(): Promise<void>;
608
+ destroy(): Promise<void>;
609
+ }
610
+ //#endregion
611
+ export { SettlementRepository as a, RevenueModels as c, SubscriptionDocument as d, TransactionDocument as f, RevenueEngine as i, RevenueSchemaOptions as l, RetryConfig as n, SubscriptionRepository as o, RevenueConfig as r, TransactionRepository as s, CommissionConfig as t, SettlementDocument as u };