@classytic/revenue 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +8 -7
  2. package/dist/application/services/index.d.mts +4 -0
  3. package/dist/application/services/index.mjs +3 -0
  4. package/dist/base-CsTlVQJe.d.mts +136 -0
  5. package/dist/base-DCoyIUj6.mjs +152 -0
  6. package/dist/category-resolver-DV83N8ok.mjs +284 -0
  7. package/dist/commission-split-BzB8cd39.mjs +485 -0
  8. package/dist/core/events.d.mts +294 -0
  9. package/dist/core/events.mjs +100 -0
  10. package/dist/core/index.d.mts +9 -0
  11. package/dist/core/index.mjs +8 -0
  12. package/dist/enums/index.d.mts +157 -0
  13. package/dist/enums/index.mjs +56 -0
  14. package/dist/errors-rRdOqnWx.d.mts +787 -0
  15. package/dist/escrow.enums-CZGrrdg7.mjs +101 -0
  16. package/dist/{escrow.enums-CE0VQsfe.d.ts → escrow.enums-DwdLuuve.d.mts} +30 -28
  17. package/dist/idempotency-DaYcUGY1.mjs +172 -0
  18. package/dist/index-Dsp7H5Wb.d.mts +471 -0
  19. package/dist/index.d.mts +9 -0
  20. package/dist/index.mjs +38 -0
  21. package/dist/infrastructure/plugins/{index.d.ts → index.d.mts} +81 -109
  22. package/dist/infrastructure/plugins/index.mjs +345 -0
  23. package/dist/money-CvrDOijQ.mjs +271 -0
  24. package/dist/money-DPG8AtJ8.d.mts +112 -0
  25. package/dist/{payment.enums-C1BiGlRa.d.ts → payment.enums-HAuAS9Pp.d.mts} +14 -13
  26. package/dist/payment.enums-tEFVa-Xp.mjs +69 -0
  27. package/dist/plugin-BbK0OVHy.d.mts +327 -0
  28. package/dist/plugin-Cd_V04Em.mjs +210 -0
  29. package/dist/providers/index.d.mts +3 -0
  30. package/dist/providers/index.mjs +3 -0
  31. package/dist/reconciliation/{index.d.ts → index.d.mts} +90 -112
  32. package/dist/reconciliation/index.mjs +192 -0
  33. package/dist/retry-HHCOXYdn.d.mts +186 -0
  34. package/dist/revenue-BhdS7nXh.mjs +553 -0
  35. package/dist/schemas/index.d.mts +2665 -0
  36. package/dist/schemas/index.mjs +717 -0
  37. package/dist/schemas/validation.d.mts +375 -0
  38. package/dist/schemas/validation.mjs +325 -0
  39. package/dist/{settlement.enums-ByC1x0ye.d.ts → settlement.enums-DFhkqZEY.d.mts} +31 -29
  40. package/dist/settlement.schema-DnNSFpGd.d.mts +344 -0
  41. package/dist/settlement.service-DjzAjezU.d.mts +594 -0
  42. package/dist/settlement.service-DmdKv0Zu.mjs +2511 -0
  43. package/dist/split.enums-BrjabxIX.mjs +86 -0
  44. package/dist/split.enums-DmskfLOM.d.mts +43 -0
  45. package/dist/tax-BoCt5cEd.d.mts +61 -0
  46. package/dist/tax-EQ15DO81.mjs +162 -0
  47. package/dist/transaction.enums-pCyMFT4Z.mjs +96 -0
  48. package/dist/utils/{index.d.ts → index.d.mts} +91 -161
  49. package/dist/utils/index.mjs +346 -0
  50. package/package.json +39 -37
  51. package/dist/application/services/index.d.ts +0 -6
  52. package/dist/application/services/index.js +0 -3288
  53. package/dist/application/services/index.js.map +0 -1
  54. package/dist/core/events.d.ts +0 -455
  55. package/dist/core/events.js +0 -122
  56. package/dist/core/events.js.map +0 -1
  57. package/dist/core/index.d.ts +0 -13
  58. package/dist/core/index.js +0 -4591
  59. package/dist/core/index.js.map +0 -1
  60. package/dist/enums/index.d.ts +0 -159
  61. package/dist/enums/index.js +0 -296
  62. package/dist/enums/index.js.map +0 -1
  63. package/dist/index-DxIK0UmZ.d.ts +0 -633
  64. package/dist/index-EnfKzDbs.d.ts +0 -806
  65. package/dist/index-cLJBLUvx.d.ts +0 -478
  66. package/dist/index.d.ts +0 -43
  67. package/dist/index.js +0 -4864
  68. package/dist/index.js.map +0 -1
  69. package/dist/infrastructure/plugins/index.js +0 -292
  70. package/dist/infrastructure/plugins/index.js.map +0 -1
  71. package/dist/money-widWVD7r.d.ts +0 -111
  72. package/dist/plugin-Bb9HOE10.d.ts +0 -336
  73. package/dist/providers/index.d.ts +0 -145
  74. package/dist/providers/index.js +0 -141
  75. package/dist/providers/index.js.map +0 -1
  76. package/dist/reconciliation/index.js +0 -140
  77. package/dist/reconciliation/index.js.map +0 -1
  78. package/dist/retry-D4hFUwVk.d.ts +0 -194
  79. package/dist/schemas/index.d.ts +0 -2655
  80. package/dist/schemas/index.js +0 -841
  81. package/dist/schemas/index.js.map +0 -1
  82. package/dist/schemas/validation.d.ts +0 -384
  83. package/dist/schemas/validation.js +0 -303
  84. package/dist/schemas/validation.js.map +0 -1
  85. package/dist/settlement.schema-CpamV7ZY.d.ts +0 -343
  86. package/dist/split.enums-DG3TxQf9.d.ts +0 -42
  87. package/dist/tax-CV8A0sxl.d.ts +0 -60
  88. package/dist/utils/index.js +0 -1202
  89. package/dist/utils/index.js.map +0 -1
@@ -1,140 +0,0 @@
1
- // @classytic/revenue - Enterprise Revenue Management System
2
-
3
- // src/reconciliation/reconciler.ts
4
- async function reconcileSettlement(gatewaySettlements, TransactionModel, options = {}) {
5
- const {
6
- organizationId,
7
- gateway,
8
- startDate,
9
- endDate,
10
- autoMatch: _autoMatch = true,
11
- amountTolerance = 1
12
- // 1 cent tolerance
13
- } = options;
14
- const query = {};
15
- if (organizationId) query.organizationId = organizationId;
16
- if (gateway) query["gateway.type"] = gateway;
17
- if (startDate || endDate) {
18
- query.createdAt = {};
19
- if (startDate) query.createdAt.$gte = startDate;
20
- if (endDate) query.createdAt.$lte = endDate;
21
- }
22
- const dbTransactions = await TransactionModel.find(query);
23
- const gatewayMap = /* @__PURE__ */ new Map();
24
- const dbMap = /* @__PURE__ */ new Map();
25
- for (const settlement of gatewaySettlements) {
26
- gatewayMap.set(settlement.transactionId, settlement);
27
- }
28
- for (const transaction of dbTransactions) {
29
- const key = transaction.gateway?.paymentIntentId || transaction._id.toString();
30
- dbMap.set(key, transaction);
31
- }
32
- const report = {
33
- summary: {
34
- totalGatewayTransactions: gatewaySettlements.length,
35
- totalDbTransactions: dbTransactions.length,
36
- matched: 0,
37
- missing: 0,
38
- extra: 0,
39
- amountMismatches: 0,
40
- totalAmountDiff: 0
41
- },
42
- missingInDb: [],
43
- missingInGateway: [],
44
- amountMismatches: [],
45
- matched: [],
46
- metadata: {
47
- reconciledAt: /* @__PURE__ */ new Date(),
48
- period: { start: startDate, end: endDate },
49
- gateway,
50
- organizationId
51
- }
52
- };
53
- for (const [gatewayTxId, gatewaySettlement] of gatewayMap.entries()) {
54
- const dbTransaction = dbMap.get(gatewayTxId);
55
- if (!dbTransaction) {
56
- report.missingInDb.push(gatewaySettlement);
57
- report.summary.missing++;
58
- } else {
59
- const amountDiff = Math.abs(dbTransaction.amount - gatewaySettlement.amount);
60
- if (amountDiff > amountTolerance) {
61
- report.amountMismatches.push({
62
- transactionId: gatewayTxId,
63
- gatewayAmount: gatewaySettlement.amount,
64
- dbAmount: dbTransaction.amount,
65
- diff: dbTransaction.amount - gatewaySettlement.amount,
66
- transaction: dbTransaction,
67
- gatewayRecord: gatewaySettlement
68
- });
69
- report.summary.amountMismatches++;
70
- report.summary.totalAmountDiff += amountDiff;
71
- } else {
72
- report.matched.push({
73
- transactionId: gatewayTxId,
74
- amount: dbTransaction.amount,
75
- transaction: dbTransaction,
76
- gatewayRecord: gatewaySettlement
77
- });
78
- report.summary.matched++;
79
- }
80
- dbMap.delete(gatewayTxId);
81
- }
82
- }
83
- for (const [_, transaction] of dbMap.entries()) {
84
- report.missingInGateway.push(transaction);
85
- report.summary.extra++;
86
- }
87
- return report;
88
- }
89
- async function findMissingTransactions(_organizationId, _dateRange, _gateway, _TransactionModel) {
90
- return {
91
- inGateway: [],
92
- // Transactions in gateway but not in DB
93
- inDb: []
94
- // Transactions in DB but not confirmed by gateway
95
- };
96
- }
97
- async function findAmountMismatches(_organizationId, _dateRange, _threshold = 1, _TransactionModel) {
98
- const mismatches = [];
99
- return mismatches;
100
- }
101
- function generateDiscrepancies(report) {
102
- const discrepancies = [];
103
- for (const gateway of report.missingInDb) {
104
- discrepancies.push({
105
- type: "missing_in_db",
106
- transactionId: gateway.transactionId,
107
- severity: "high",
108
- description: `Transaction ${gateway.transactionId} found in gateway (${gateway.amount} ${gateway.currency}) but missing in database`,
109
- gatewayData: gateway
110
- });
111
- }
112
- for (const transaction of report.missingInGateway) {
113
- discrepancies.push({
114
- type: "missing_in_gateway",
115
- transactionId: transaction._id.toString(),
116
- severity: "medium",
117
- description: `Transaction ${transaction._id} found in database but not in gateway report`,
118
- dbData: transaction
119
- });
120
- }
121
- for (const mismatch of report.amountMismatches) {
122
- const severity = Math.abs(mismatch.diff) > 1e3 ? "high" : Math.abs(mismatch.diff) > 100 ? "medium" : "low";
123
- discrepancies.push({
124
- type: "amount_mismatch",
125
- transactionId: mismatch.transactionId,
126
- severity,
127
- description: `Amount mismatch: Gateway shows ${mismatch.gatewayAmount}, DB shows ${mismatch.dbAmount} (diff: ${mismatch.diff})`,
128
- gatewayData: mismatch.gatewayRecord,
129
- dbData: mismatch.transaction,
130
- diff: mismatch.diff
131
- });
132
- }
133
- const severityOrder = { high: 0, medium: 1, low: 2 };
134
- discrepancies.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
135
- return discrepancies;
136
- }
137
-
138
- export { findAmountMismatches, findMissingTransactions, generateDiscrepancies, reconcileSettlement };
139
- //# sourceMappingURL=index.js.map
140
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/reconciliation/reconciler.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Reconciliation Utilities\n * @classytic/revenue\n *\n * Compare gateway settlement reports with database transactions\n * Find missing transactions, amount mismatches, and discrepancies\n */\n\nimport type {\n GatewaySettlement,\n ReconciliationOptions,\n ReconciliationReport,\n Discrepancy,\n} from '../shared/types/reconciliation.js';\nimport type { TransactionDocument, MongooseModel } from '../shared/types/index.js';\n\n/**\n * Reconcile gateway settlements with database transactions\n *\n * Compares payment gateway's settlement report with your database to identify:\n * - Transactions in gateway but missing in DB\n * - Transactions in DB but missing in gateway\n * - Amount mismatches between gateway and DB\n *\n * @param gatewaySettlements - Settlement data from payment gateway\n * @param TransactionModel - Mongoose Transaction model\n * @param options - Reconciliation options\n * @returns Reconciliation report with findings\n *\n * @example\n * ```typescript\n * import { reconcileSettlement } from '@classytic/revenue/reconciliation';\n *\n * // Get Stripe settlements for January\n * const stripeSettlements = await stripe.balanceTransactions.list({\n * created: { gte: jan1, lte: jan31 },\n * });\n *\n * // Reconcile with database\n * const report = await reconcileSettlement(\n * stripeSettlements.data.map(s => ({\n * settlementId: s.id,\n * transactionId: s.source,\n * amount: s.amount,\n * currency: s.currency,\n * settledAt: new Date(s.created * 1000),\n * gatewayFee: s.fee,\n * netAmount: s.net,\n * })),\n * TransactionModel,\n * { gateway: 'stripe', startDate: jan1, endDate: jan31 }\n * );\n *\n * console.log(report.summary);\n * // { matched: 1245, missing: 2, extra: 1, amountMismatches: 3 }\n * ```\n */\nexport async function reconcileSettlement(\n gatewaySettlements: GatewaySettlement[],\n TransactionModel: MongooseModel<TransactionDocument>,\n options: ReconciliationOptions = {}\n): Promise<ReconciliationReport> {\n const {\n organizationId,\n gateway,\n startDate,\n endDate,\n autoMatch: _autoMatch = true,\n amountTolerance = 1, // 1 cent tolerance\n } = options;\n\n // Build query for DB transactions\n const query: Record<string, unknown> = {};\n if (organizationId) query.organizationId = organizationId;\n if (gateway) query['gateway.type'] = gateway;\n\n if (startDate || endDate) {\n query.createdAt = {};\n if (startDate) (query.createdAt as Record<string, unknown>).$gte = startDate;\n if (endDate) (query.createdAt as Record<string, unknown>).$lte = endDate;\n }\n\n // Get database transactions\n const dbTransactions = await (TransactionModel as unknown as {\n find(filter: object): Promise<TransactionDocument[]>;\n }).find(query);\n\n // Create lookup maps\n const gatewayMap = new Map<string, GatewaySettlement>();\n const dbMap = new Map<string, TransactionDocument>();\n\n for (const settlement of gatewaySettlements) {\n gatewayMap.set(settlement.transactionId, settlement);\n }\n\n for (const transaction of dbTransactions) {\n // Use gateway.paymentIntentId as the key for matching\n const key = (transaction.gateway?.paymentIntentId || transaction._id.toString());\n dbMap.set(key, transaction);\n }\n\n // Initialize report\n const report: ReconciliationReport = {\n summary: {\n totalGatewayTransactions: gatewaySettlements.length,\n totalDbTransactions: dbTransactions.length,\n matched: 0,\n missing: 0,\n extra: 0,\n amountMismatches: 0,\n totalAmountDiff: 0,\n },\n missingInDb: [],\n missingInGateway: [],\n amountMismatches: [],\n matched: [],\n metadata: {\n reconciledAt: new Date(),\n period: { start: startDate, end: endDate },\n gateway,\n organizationId,\n },\n };\n\n // Find matches and mismatches\n for (const [gatewayTxId, gatewaySettlement] of gatewayMap.entries()) {\n const dbTransaction = dbMap.get(gatewayTxId);\n\n if (!dbTransaction) {\n // Missing in DB\n report.missingInDb.push(gatewaySettlement);\n report.summary.missing++;\n } else {\n // Found - check amount\n const amountDiff = Math.abs(dbTransaction.amount - gatewaySettlement.amount);\n\n if (amountDiff > amountTolerance) {\n // Amount mismatch\n report.amountMismatches.push({\n transactionId: gatewayTxId,\n gatewayAmount: gatewaySettlement.amount,\n dbAmount: dbTransaction.amount,\n diff: dbTransaction.amount - gatewaySettlement.amount,\n transaction: dbTransaction,\n gatewayRecord: gatewaySettlement,\n });\n report.summary.amountMismatches++;\n report.summary.totalAmountDiff += amountDiff;\n } else {\n // Matched!\n report.matched.push({\n transactionId: gatewayTxId,\n amount: dbTransaction.amount,\n transaction: dbTransaction,\n gatewayRecord: gatewaySettlement,\n });\n report.summary.matched++;\n }\n\n // Mark as processed\n dbMap.delete(gatewayTxId);\n }\n }\n\n // Remaining DB transactions = extra (not in gateway)\n for (const [_, transaction] of dbMap.entries()) {\n report.missingInGateway.push(transaction);\n report.summary.extra++;\n }\n\n return report;\n}\n\n/**\n * Find transactions missing in database\n *\n * @param organizationId - Organization to check\n * @param dateRange - Date range to search\n * @param gateway - Payment gateway\n * @param TransactionModel - Mongoose Transaction model\n * @returns Missing transaction IDs\n */\nexport async function findMissingTransactions(\n _organizationId: string,\n _dateRange: { start: Date; end: Date },\n _gateway: string,\n _TransactionModel: MongooseModel<TransactionDocument>\n): Promise<{ inGateway: string[]; inDb: string[] }> {\n // This is a simplified version - in production, you'd fetch from gateway API\n // For now, return structure for apps to implement\n return {\n inGateway: [], // Transactions in gateway but not in DB\n inDb: [], // Transactions in DB but not confirmed by gateway\n };\n}\n\n/**\n * Find amount mismatches between gateway and database\n *\n * @param organizationId - Organization to check\n * @param dateRange - Date range to search\n * @param threshold - Amount difference threshold (cents)\n * @param TransactionModel - Mongoose Transaction model\n * @returns Array of mismatches\n */\nexport async function findAmountMismatches(\n _organizationId: string,\n _dateRange: { start: Date; end: Date },\n _threshold: number = 1,\n _TransactionModel: MongooseModel<TransactionDocument>\n): Promise<Array<{ transactionId: string; diff: number }>> {\n // This is a stub function for apps to implement\n // In production, query transactions and compare with gateway data\n\n const mismatches: Array<{ transactionId: string; diff: number }> = [];\n\n return mismatches;\n}\n\n/**\n * Generate reconciliation discrepancies\n *\n * @param report - Reconciliation report\n * @returns Array of discrepancies sorted by severity\n */\nexport function generateDiscrepancies(report: ReconciliationReport): Discrepancy[] {\n const discrepancies: Discrepancy[] = [];\n\n // Missing in DB (HIGH severity)\n for (const gateway of report.missingInDb) {\n discrepancies.push({\n type: 'missing_in_db',\n transactionId: gateway.transactionId,\n severity: 'high',\n description: `Transaction ${gateway.transactionId} found in gateway (${gateway.amount} ${gateway.currency}) but missing in database`,\n gatewayData: gateway,\n });\n }\n\n // Missing in gateway (MEDIUM severity)\n for (const transaction of report.missingInGateway) {\n discrepancies.push({\n type: 'missing_in_gateway',\n transactionId: transaction._id.toString(),\n severity: 'medium',\n description: `Transaction ${transaction._id} found in database but not in gateway report`,\n dbData: transaction,\n });\n }\n\n // Amount mismatches (severity based on amount)\n for (const mismatch of report.amountMismatches) {\n const severity: 'low' | 'medium' | 'high' = Math.abs(mismatch.diff) > 1000 ? 'high' : Math.abs(mismatch.diff) > 100 ? 'medium' : 'low';\n\n discrepancies.push({\n type: 'amount_mismatch',\n transactionId: mismatch.transactionId,\n severity,\n description: `Amount mismatch: Gateway shows ${mismatch.gatewayAmount}, DB shows ${mismatch.dbAmount} (diff: ${mismatch.diff})`,\n gatewayData: mismatch.gatewayRecord,\n dbData: mismatch.transaction,\n diff: mismatch.diff,\n });\n }\n\n // Sort by severity\n const severityOrder = { high: 0, medium: 1, low: 2 };\n discrepancies.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n\n return discrepancies;\n}\n"]}
@@ -1,194 +0,0 @@
1
- /**
2
- * Result Type - Rust-inspired error handling
3
- * @classytic/revenue
4
- *
5
- * No more try/catch - explicit, type-safe error handling
6
- * Inspired by: Rust Result<T, E>, neverthrow, Effect-TS
7
- */
8
- /**
9
- * Success result
10
- */
11
- interface Ok<T> {
12
- readonly ok: true;
13
- readonly value: T;
14
- readonly error?: never;
15
- }
16
- /**
17
- * Error result
18
- */
19
- interface Err<E> {
20
- readonly ok: false;
21
- readonly error: E;
22
- readonly value?: never;
23
- }
24
- /**
25
- * Create a success result
26
- */
27
- declare function ok<T>(value: T): Ok<T>;
28
- /**
29
- * Create an error result
30
- */
31
- declare function err<E>(error: E): Err<E>;
32
- /**
33
- * Check if result is Ok
34
- */
35
- declare function isOk<T, E>(result: Result<T, E>): result is Ok<T>;
36
- /**
37
- * Check if result is Err
38
- */
39
- declare function isErr<T, E>(result: Result<T, E>): result is Err<E>;
40
- /**
41
- * Unwrap a result, throwing if it's an error
42
- * Use sparingly - prefer pattern matching
43
- */
44
- declare function unwrap<T, E>(result: Result<T, E>): T;
45
- /**
46
- * Unwrap a result with a default value
47
- */
48
- declare function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T;
49
- /**
50
- * Map over a successful result
51
- */
52
- declare function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;
53
- /**
54
- * Map over an error result
55
- */
56
- declare function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;
57
- /**
58
- * Flat map (chain) results
59
- */
60
- declare function flatMap<T, U, E>(result: Result<T, E>, fn: (value: T) => Result<U, E>): Result<U, E>;
61
- /**
62
- * Try-catch wrapper that returns Result
63
- */
64
- declare function tryCatch<T, E = Error>(fn: () => Promise<T>, mapError?: (e: unknown) => E): Promise<Result<T, E>>;
65
- /**
66
- * Synchronous try-catch wrapper
67
- */
68
- declare function tryCatchSync<T, E = Error>(fn: () => T, mapError?: (e: unknown) => E): Result<T, E>;
69
- /**
70
- * Combine multiple results - all must succeed
71
- */
72
- declare function all<T extends readonly Result<unknown, unknown>[]>(results: T): Result<{
73
- [K in keyof T]: T[K] extends Result<infer U, unknown> ? U : never;
74
- }, T[number] extends Result<unknown, infer E> ? E : never>;
75
- /**
76
- * Pattern match on result
77
- */
78
- declare function match<T, E, U>(result: Result<T, E>, handlers: {
79
- ok: (value: T) => U;
80
- err: (error: E) => U;
81
- }): U;
82
- /**
83
- * Result type - either Ok<T> or Err<E>
84
- */
85
- type Result<T, E = Error> = Ok<T> | Err<E>;
86
- declare const Result: {
87
- readonly ok: typeof ok;
88
- readonly err: typeof err;
89
- readonly isOk: typeof isOk;
90
- readonly isErr: typeof isErr;
91
- readonly unwrap: typeof unwrap;
92
- readonly unwrapOr: typeof unwrapOr;
93
- readonly map: typeof map;
94
- readonly mapErr: typeof mapErr;
95
- readonly flatMap: typeof flatMap;
96
- readonly tryCatch: typeof tryCatch;
97
- readonly tryCatchSync: typeof tryCatchSync;
98
- readonly all: typeof all;
99
- readonly match: typeof match;
100
- };
101
-
102
- /**
103
- * Retry Utilities
104
- * @classytic/revenue
105
- *
106
- * Exponential backoff with jitter for resilient operations
107
- * Inspired by: AWS SDK retry, Netflix Hystrix, resilience4j
108
- */
109
-
110
- interface RetryConfig {
111
- /** Maximum number of retry attempts (default: 3) */
112
- maxAttempts: number;
113
- /** Base delay in milliseconds (default: 1000) */
114
- baseDelay: number;
115
- /** Maximum delay in milliseconds (default: 30000) */
116
- maxDelay: number;
117
- /** Backoff multiplier (default: 2) */
118
- backoffMultiplier: number;
119
- /** Jitter factor 0-1 (default: 0.1) */
120
- jitter: number;
121
- /** Which errors are retryable */
122
- retryIf?: (error: unknown) => boolean;
123
- /** Callback on each retry */
124
- onRetry?: (error: unknown, attempt: number, delay: number) => void;
125
- }
126
- /**
127
- * Execute operation with retry logic
128
- */
129
- declare function retry<T>(operation: () => Promise<T>, config?: Partial<RetryConfig>): Promise<T>;
130
- type CircuitState = 'closed' | 'open' | 'half-open';
131
- interface CircuitBreakerConfig {
132
- /** Number of failures before opening circuit */
133
- failureThreshold: number;
134
- /** Time in ms to wait before half-opening */
135
- resetTimeout: number;
136
- /** Number of successes in half-open to close circuit */
137
- successThreshold: number;
138
- /** Monitor window in ms */
139
- monitorWindow: number;
140
- }
141
- /**
142
- * Circuit breaker for preventing cascade failures
143
- * Inspired by: Netflix Hystrix, resilience4j
144
- */
145
- declare class CircuitBreaker {
146
- private state;
147
- private failures;
148
- private successes;
149
- private lastFailure?;
150
- private config;
151
- constructor(config?: Partial<CircuitBreakerConfig>);
152
- /**
153
- * Execute operation through circuit breaker
154
- */
155
- execute<T>(operation: () => Promise<T>): Promise<T>;
156
- /**
157
- * Execute with Result type
158
- */
159
- executeWithResult<T>(operation: () => Promise<T>): Promise<Result<T, CircuitOpenError | Error>>;
160
- private onSuccess;
161
- private onFailure;
162
- private shouldAttemptReset;
163
- private cleanOldFailures;
164
- private reset;
165
- /**
166
- * Get current circuit state
167
- */
168
- getState(): CircuitState;
169
- /**
170
- * Manually reset circuit
171
- */
172
- forceReset(): void;
173
- /**
174
- * Get circuit statistics
175
- */
176
- getStats(): {
177
- state: CircuitState;
178
- failures: number;
179
- successes: number;
180
- lastFailure?: Date;
181
- };
182
- }
183
- /**
184
- * Error thrown when circuit is open
185
- */
186
- declare class CircuitOpenError extends Error {
187
- constructor(message: string);
188
- }
189
- /**
190
- * Create a circuit breaker
191
- */
192
- declare function createCircuitBreaker(config?: Partial<CircuitBreakerConfig>): CircuitBreaker;
193
-
194
- export { CircuitBreaker as C, type Err as E, type Ok as O, Result as R, isErr as a, unwrapOr as b, mapErr as c, tryCatchSync as d, err as e, flatMap as f, all as g, match as h, isOk as i, createCircuitBreaker as j, type RetryConfig as k, type CircuitBreakerConfig as l, map as m, type CircuitState as n, ok as o, retry as r, tryCatch as t, unwrap as u };