@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.
- package/README.md +8 -7
- package/dist/application/services/index.d.mts +4 -0
- package/dist/application/services/index.mjs +3 -0
- package/dist/base-CsTlVQJe.d.mts +136 -0
- package/dist/base-DCoyIUj6.mjs +152 -0
- package/dist/category-resolver-DV83N8ok.mjs +284 -0
- package/dist/commission-split-BzB8cd39.mjs +485 -0
- package/dist/core/events.d.mts +294 -0
- package/dist/core/events.mjs +100 -0
- package/dist/core/index.d.mts +9 -0
- package/dist/core/index.mjs +8 -0
- package/dist/enums/index.d.mts +157 -0
- package/dist/enums/index.mjs +56 -0
- package/dist/errors-rRdOqnWx.d.mts +787 -0
- package/dist/escrow.enums-CZGrrdg7.mjs +101 -0
- package/dist/{escrow.enums-CE0VQsfe.d.ts → escrow.enums-DwdLuuve.d.mts} +30 -28
- package/dist/idempotency-DaYcUGY1.mjs +172 -0
- package/dist/index-Dsp7H5Wb.d.mts +471 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.mjs +38 -0
- package/dist/infrastructure/plugins/{index.d.ts → index.d.mts} +81 -109
- package/dist/infrastructure/plugins/index.mjs +345 -0
- package/dist/money-CvrDOijQ.mjs +271 -0
- package/dist/money-DPG8AtJ8.d.mts +112 -0
- package/dist/{payment.enums-C1BiGlRa.d.ts → payment.enums-HAuAS9Pp.d.mts} +14 -13
- package/dist/payment.enums-tEFVa-Xp.mjs +69 -0
- package/dist/plugin-BbK0OVHy.d.mts +327 -0
- package/dist/plugin-Cd_V04Em.mjs +210 -0
- package/dist/providers/index.d.mts +3 -0
- package/dist/providers/index.mjs +3 -0
- package/dist/reconciliation/{index.d.ts → index.d.mts} +90 -112
- package/dist/reconciliation/index.mjs +192 -0
- package/dist/retry-HHCOXYdn.d.mts +186 -0
- package/dist/revenue-BhdS7nXh.mjs +553 -0
- package/dist/schemas/index.d.mts +2665 -0
- package/dist/schemas/index.mjs +717 -0
- package/dist/schemas/validation.d.mts +375 -0
- package/dist/schemas/validation.mjs +325 -0
- package/dist/{settlement.enums-ByC1x0ye.d.ts → settlement.enums-DFhkqZEY.d.mts} +31 -29
- package/dist/settlement.schema-DnNSFpGd.d.mts +344 -0
- package/dist/settlement.service-DjzAjezU.d.mts +594 -0
- package/dist/settlement.service-DmdKv0Zu.mjs +2511 -0
- package/dist/split.enums-BrjabxIX.mjs +86 -0
- package/dist/split.enums-DmskfLOM.d.mts +43 -0
- package/dist/tax-BoCt5cEd.d.mts +61 -0
- package/dist/tax-EQ15DO81.mjs +162 -0
- package/dist/transaction.enums-pCyMFT4Z.mjs +96 -0
- package/dist/utils/{index.d.ts → index.d.mts} +91 -161
- package/dist/utils/index.mjs +346 -0
- package/package.json +39 -37
- package/dist/application/services/index.d.ts +0 -6
- package/dist/application/services/index.js +0 -3288
- package/dist/application/services/index.js.map +0 -1
- package/dist/core/events.d.ts +0 -455
- package/dist/core/events.js +0 -122
- package/dist/core/events.js.map +0 -1
- package/dist/core/index.d.ts +0 -13
- package/dist/core/index.js +0 -4591
- package/dist/core/index.js.map +0 -1
- package/dist/enums/index.d.ts +0 -159
- package/dist/enums/index.js +0 -296
- package/dist/enums/index.js.map +0 -1
- package/dist/index-DxIK0UmZ.d.ts +0 -633
- package/dist/index-EnfKzDbs.d.ts +0 -806
- package/dist/index-cLJBLUvx.d.ts +0 -478
- package/dist/index.d.ts +0 -43
- package/dist/index.js +0 -4864
- package/dist/index.js.map +0 -1
- package/dist/infrastructure/plugins/index.js +0 -292
- package/dist/infrastructure/plugins/index.js.map +0 -1
- package/dist/money-widWVD7r.d.ts +0 -111
- package/dist/plugin-Bb9HOE10.d.ts +0 -336
- package/dist/providers/index.d.ts +0 -145
- package/dist/providers/index.js +0 -141
- package/dist/providers/index.js.map +0 -1
- package/dist/reconciliation/index.js +0 -140
- package/dist/reconciliation/index.js.map +0 -1
- package/dist/retry-D4hFUwVk.d.ts +0 -194
- package/dist/schemas/index.d.ts +0 -2655
- package/dist/schemas/index.js +0 -841
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/validation.d.ts +0 -384
- package/dist/schemas/validation.js +0 -303
- package/dist/schemas/validation.js.map +0 -1
- package/dist/settlement.schema-CpamV7ZY.d.ts +0 -343
- package/dist/split.enums-DG3TxQf9.d.ts +0 -42
- package/dist/tax-CV8A0sxl.d.ts +0 -60
- package/dist/utils/index.js +0 -1202
- 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"]}
|
package/dist/retry-D4hFUwVk.d.ts
DELETED
|
@@ -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 };
|