@capsara/sdk 1.0.1
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/LICENSE +74 -0
- package/README.md +230 -0
- package/dist/builder/capsa-builder.d.ts +167 -0
- package/dist/builder/capsa-builder.d.ts.map +1 -0
- package/dist/builder/capsa-builder.js +489 -0
- package/dist/builder/capsa-builder.js.map +1 -0
- package/dist/client/capsara-client.d.ts +96 -0
- package/dist/client/capsara-client.d.ts.map +1 -0
- package/dist/client/capsara-client.js +266 -0
- package/dist/client/capsara-client.js.map +1 -0
- package/dist/errors/account-error.d.ts +73 -0
- package/dist/errors/account-error.d.ts.map +1 -0
- package/dist/errors/account-error.js +155 -0
- package/dist/errors/account-error.js.map +1 -0
- package/dist/errors/audit-error.d.ts +34 -0
- package/dist/errors/audit-error.d.ts.map +1 -0
- package/dist/errors/audit-error.js +93 -0
- package/dist/errors/audit-error.js.map +1 -0
- package/dist/errors/auth-error.d.ts +38 -0
- package/dist/errors/auth-error.d.ts.map +1 -0
- package/dist/errors/auth-error.js +87 -0
- package/dist/errors/auth-error.js.map +1 -0
- package/dist/errors/capsa-error.d.ts +64 -0
- package/dist/errors/capsa-error.d.ts.map +1 -0
- package/dist/errors/capsa-error.js +172 -0
- package/dist/errors/capsa-error.js.map +1 -0
- package/dist/errors/capsara-error.d.ts +52 -0
- package/dist/errors/capsara-error.d.ts.map +1 -0
- package/dist/errors/capsara-error.js +83 -0
- package/dist/errors/capsara-error.js.map +1 -0
- package/dist/errors/index.d.ts +8 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/capsa-cache.d.ts +49 -0
- package/dist/internal/capsa-cache.d.ts.map +1 -0
- package/dist/internal/capsa-cache.js +118 -0
- package/dist/internal/capsa-cache.js.map +1 -0
- package/dist/internal/config/http-client.d.ts +37 -0
- package/dist/internal/config/http-client.d.ts.map +1 -0
- package/dist/internal/config/http-client.js +63 -0
- package/dist/internal/config/http-client.js.map +1 -0
- package/dist/internal/config/retry-interceptor.d.ts +18 -0
- package/dist/internal/config/retry-interceptor.d.ts.map +1 -0
- package/dist/internal/config/retry-interceptor.js +103 -0
- package/dist/internal/config/retry-interceptor.js.map +1 -0
- package/dist/internal/crypto/compression.d.ts +15 -0
- package/dist/internal/crypto/compression.d.ts.map +1 -0
- package/dist/internal/crypto/compression.js +34 -0
- package/dist/internal/crypto/compression.js.map +1 -0
- package/dist/internal/crypto/key-generator.d.ts +23 -0
- package/dist/internal/crypto/key-generator.d.ts.map +1 -0
- package/dist/internal/crypto/key-generator.js +65 -0
- package/dist/internal/crypto/key-generator.js.map +1 -0
- package/dist/internal/crypto/primitives.d.ts +67 -0
- package/dist/internal/crypto/primitives.d.ts.map +1 -0
- package/dist/internal/crypto/primitives.js +230 -0
- package/dist/internal/crypto/primitives.js.map +1 -0
- package/dist/internal/crypto/signatures.d.ts +30 -0
- package/dist/internal/crypto/signatures.d.ts.map +1 -0
- package/dist/internal/crypto/signatures.js +153 -0
- package/dist/internal/crypto/signatures.js.map +1 -0
- package/dist/internal/decryptor/capsa-decryptor.d.ts +89 -0
- package/dist/internal/decryptor/capsa-decryptor.d.ts.map +1 -0
- package/dist/internal/decryptor/capsa-decryptor.js +263 -0
- package/dist/internal/decryptor/capsa-decryptor.js.map +1 -0
- package/dist/internal/http-factory.d.ts +78 -0
- package/dist/internal/http-factory.d.ts.map +1 -0
- package/dist/internal/http-factory.js +201 -0
- package/dist/internal/http-factory.js.map +1 -0
- package/dist/internal/index.d.ts +5 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +5 -0
- package/dist/internal/index.js.map +1 -0
- package/dist/internal/retry-executor.d.ts +74 -0
- package/dist/internal/retry-executor.d.ts.map +1 -0
- package/dist/internal/retry-executor.js +204 -0
- package/dist/internal/retry-executor.js.map +1 -0
- package/dist/internal/services/account-service.d.ts +56 -0
- package/dist/internal/services/account-service.d.ts.map +1 -0
- package/dist/internal/services/account-service.js +114 -0
- package/dist/internal/services/account-service.js.map +1 -0
- package/dist/internal/services/audit-service.d.ts +25 -0
- package/dist/internal/services/audit-service.d.ts.map +1 -0
- package/dist/internal/services/audit-service.js +43 -0
- package/dist/internal/services/audit-service.js.map +1 -0
- package/dist/internal/services/auth-service.d.ts +44 -0
- package/dist/internal/services/auth-service.d.ts.map +1 -0
- package/dist/internal/services/auth-service.js +170 -0
- package/dist/internal/services/auth-service.js.map +1 -0
- package/dist/internal/services/capsa-service.d.ts +40 -0
- package/dist/internal/services/capsa-service.d.ts.map +1 -0
- package/dist/internal/services/capsa-service.js +82 -0
- package/dist/internal/services/capsa-service.js.map +1 -0
- package/dist/internal/services/download-service.d.ts +62 -0
- package/dist/internal/services/download-service.d.ts.map +1 -0
- package/dist/internal/services/download-service.js +114 -0
- package/dist/internal/services/download-service.js.map +1 -0
- package/dist/internal/services/key-service.d.ts +28 -0
- package/dist/internal/services/key-service.d.ts.map +1 -0
- package/dist/internal/services/key-service.js +45 -0
- package/dist/internal/services/key-service.js.map +1 -0
- package/dist/internal/services/limits-service.d.ts +30 -0
- package/dist/internal/services/limits-service.d.ts.map +1 -0
- package/dist/internal/services/limits-service.js +73 -0
- package/dist/internal/services/limits-service.js.map +1 -0
- package/dist/internal/services/upload-service.d.ts +61 -0
- package/dist/internal/services/upload-service.d.ts.map +1 -0
- package/dist/internal/services/upload-service.js +258 -0
- package/dist/internal/services/upload-service.js.map +1 -0
- package/dist/internal/types.d.ts +74 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +3 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/internal/upload/multipart-builder.d.ts +57 -0
- package/dist/internal/upload/multipart-builder.d.ts.map +1 -0
- package/dist/internal/upload/multipart-builder.js +139 -0
- package/dist/internal/upload/multipart-builder.js.map +1 -0
- package/dist/internal/utils/id-generator.d.ts +8 -0
- package/dist/internal/utils/id-generator.d.ts.map +1 -0
- package/dist/internal/utils/id-generator.js +20 -0
- package/dist/internal/utils/id-generator.js.map +1 -0
- package/dist/internal/utils/mimetype-lookup.d.ts +8 -0
- package/dist/internal/utils/mimetype-lookup.d.ts.map +1 -0
- package/dist/internal/utils/mimetype-lookup.js +118 -0
- package/dist/internal/utils/mimetype-lookup.js.map +1 -0
- package/dist/internal/version.d.ts +20 -0
- package/dist/internal/version.d.ts.map +1 -0
- package/dist/internal/version.js +25 -0
- package/dist/internal/version.js.map +1 -0
- package/dist/types/index.d.ts +143 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +20 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/** Capsa decryption utilities for client-side decryption of API responses. */
|
|
2
|
+
import * as crypto from 'crypto';
|
|
3
|
+
import { decryptAES, decryptMasterKey } from '../crypto/primitives.js';
|
|
4
|
+
import { buildCanonicalString, verifyCapsaSignature } from '../crypto/signatures.js';
|
|
5
|
+
import { decompressData } from '../crypto/compression.js';
|
|
6
|
+
function findKeychainEntry(capsa, partyId) {
|
|
7
|
+
return capsa.keychain.keys.find((key) => key.party === partyId) || null;
|
|
8
|
+
}
|
|
9
|
+
function findDelegateEntry(capsa, partyId) {
|
|
10
|
+
return (capsa.keychain.keys.find((key) => key.actingFor && key.actingFor.includes(partyId)) || null);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Decrypt capsa using party's private key
|
|
14
|
+
*
|
|
15
|
+
* SECURITY FEATURES:
|
|
16
|
+
* - Verifies capsa signature before decryption
|
|
17
|
+
* - Requires auth tags for all AES-GCM decryption
|
|
18
|
+
* - Validates keychain entry exists
|
|
19
|
+
*
|
|
20
|
+
* NOTE: partyId is optional. If not provided, uses the first keychain entry
|
|
21
|
+
* (which is the authenticated party's key when retrieved from API).
|
|
22
|
+
*
|
|
23
|
+
* @param capsa - Encrypted capsa from API
|
|
24
|
+
* @param privateKey - Party's RSA private key in PEM format
|
|
25
|
+
* @param partyId - Party ID (optional - auto-detected from keychain if omitted)
|
|
26
|
+
* @param creatorPublicKey - Creator's RSA public key in PEM format (for signature verification)
|
|
27
|
+
* @param verifySignature - Whether to verify signature (default: true, set false to skip)
|
|
28
|
+
* @returns Decrypted capsa data
|
|
29
|
+
* @throws Error if signature invalid, party not in keychain, or decryption fails
|
|
30
|
+
*/
|
|
31
|
+
export function decryptCapsa(capsa, privateKey, partyId, creatorPublicKey, verifySignature = true) {
|
|
32
|
+
// SECURITY: Verify capsa signature before decrypting
|
|
33
|
+
if (verifySignature) {
|
|
34
|
+
if (!creatorPublicKey) {
|
|
35
|
+
throw new Error('creatorPublicKey is required for signature verification. Pass verifySignature=false to skip (not recommended).');
|
|
36
|
+
}
|
|
37
|
+
// SECURITY VALIDATION: Verify signature object exists with required fields
|
|
38
|
+
if (!capsa.signature || typeof capsa.signature !== 'object' || !capsa.signature.signature) {
|
|
39
|
+
throw new Error(`Capsa signature is missing or invalid (capsa: ${capsa.id}). Capsa may be corrupted or created with an old SDK version.`);
|
|
40
|
+
}
|
|
41
|
+
// Validate signature format (RSA-SHA256 produces 512-byte signature, base64url-encoded)
|
|
42
|
+
try {
|
|
43
|
+
const signatureBuffer = Buffer.from(capsa.signature.signature, 'base64url');
|
|
44
|
+
if (signatureBuffer.length !== 512) {
|
|
45
|
+
throw new Error(`Signature length validation failed: expected 512 bytes (RSA-4096-SHA256), got ${signatureBuffer.length} bytes (capsa: ${capsa.id}). Possible data corruption.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error instanceof Error && error.message.includes('Signature length validation')) {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Signature format validation failed: invalid base64url encoding (capsa: ${capsa.id}).`);
|
|
53
|
+
}
|
|
54
|
+
if (!creatorPublicKey.includes('BEGIN') || !creatorPublicKey.includes('PUBLIC KEY')) {
|
|
55
|
+
throw new Error(`Creator public key format validation failed: missing PEM headers (creator: ${capsa.creator}).`);
|
|
56
|
+
}
|
|
57
|
+
// Build canonical string from capsa data (createdAt excluded - not part of signature)
|
|
58
|
+
const canonicalString = buildCanonicalString({
|
|
59
|
+
packageId: capsa.id,
|
|
60
|
+
totalSize: capsa.totalSize,
|
|
61
|
+
algorithm: capsa.keychain.algorithm,
|
|
62
|
+
files: capsa.files,
|
|
63
|
+
structuredIV: capsa.structuredIV,
|
|
64
|
+
subjectIV: capsa.subjectIV,
|
|
65
|
+
bodyIV: capsa.bodyIV,
|
|
66
|
+
});
|
|
67
|
+
const signatureValid = verifyCapsaSignature(capsa.signature, canonicalString, creatorPublicKey);
|
|
68
|
+
if (!signatureValid) {
|
|
69
|
+
throw new Error(`Signature verification failed: capsa data does not match signature (capsa: ${capsa.id}, creator: ${capsa.creator}). Capsa may have been tampered with or corrupted.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let keychainEntry;
|
|
73
|
+
if (partyId) {
|
|
74
|
+
const foundEntry = findKeychainEntry(capsa, partyId);
|
|
75
|
+
if (!foundEntry) {
|
|
76
|
+
const delegateEntry = findDelegateEntry(capsa, partyId);
|
|
77
|
+
if (!delegateEntry) {
|
|
78
|
+
throw new Error(`Party ${partyId} not found in capsa keychain. Cannot decrypt.`);
|
|
79
|
+
}
|
|
80
|
+
keychainEntry = delegateEntry;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
keychainEntry = foundEntry;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// No partyId - use first keychain entry (API returns only authenticated party's key)
|
|
88
|
+
if (!capsa.keychain.keys || capsa.keychain.keys.length === 0) {
|
|
89
|
+
throw new Error('No keychain entries found in capsa. Cannot decrypt.');
|
|
90
|
+
}
|
|
91
|
+
const firstEntry = capsa.keychain.keys[0];
|
|
92
|
+
if (!firstEntry) {
|
|
93
|
+
throw new Error('First keychain entry is undefined. Cannot decrypt.');
|
|
94
|
+
}
|
|
95
|
+
keychainEntry = firstEntry;
|
|
96
|
+
}
|
|
97
|
+
if (!keychainEntry.encryptedKey) {
|
|
98
|
+
const partyInfo = partyId || keychainEntry.party;
|
|
99
|
+
throw new Error(`Party ${partyInfo} has no encrypted key in keychain. This party may be a delegated recipient without direct access.`);
|
|
100
|
+
}
|
|
101
|
+
// SECURITY VALIDATION: Verify encrypted key format and integrity
|
|
102
|
+
// RSA-4096-OAEP outputs exactly 512 bytes, base64url-encoded
|
|
103
|
+
const encryptedKeyBuffer = Buffer.from(keychainEntry.encryptedKey, 'base64url');
|
|
104
|
+
if (encryptedKeyBuffer.length !== 512) {
|
|
105
|
+
throw new Error(`Encrypted key length validation failed: expected 512 bytes (RSA-4096), got ${encryptedKeyBuffer.length} bytes (capsa: ${capsa.id}, party: ${partyId || keychainEntry.party}). Possible data corruption.`);
|
|
106
|
+
}
|
|
107
|
+
if (!privateKey || typeof privateKey !== 'string') {
|
|
108
|
+
throw new Error('Private key is invalid or missing');
|
|
109
|
+
}
|
|
110
|
+
if (!privateKey.includes('BEGIN') || !privateKey.includes('PRIVATE KEY')) {
|
|
111
|
+
throw new Error(`Private key format validation failed: missing PEM headers. Key may be corrupted.`);
|
|
112
|
+
}
|
|
113
|
+
let masterKey;
|
|
114
|
+
try {
|
|
115
|
+
masterKey = decryptMasterKey(keychainEntry.encryptedKey, privateKey);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// Preserve original error details for diagnostics
|
|
119
|
+
const originalMessage = error instanceof Error ? error.message : String(error);
|
|
120
|
+
throw new Error(`RSA master key decryption failed: ${originalMessage} (capsa: ${capsa.id}, party: ${partyId || keychainEntry.party}, encryptedKeyLength: ${encryptedKeyBuffer.length})`);
|
|
121
|
+
}
|
|
122
|
+
// SECURITY VALIDATION: Verify decrypted master key is correct size
|
|
123
|
+
// AES-256 requires exactly 32 bytes
|
|
124
|
+
if (masterKey.length !== 32) {
|
|
125
|
+
throw new Error(`Master key size validation failed: expected 32 bytes (AES-256), got ${masterKey.length} bytes. RSA decryption may have succeeded with wrong key.`);
|
|
126
|
+
}
|
|
127
|
+
let subject;
|
|
128
|
+
let body;
|
|
129
|
+
let structured;
|
|
130
|
+
if (capsa.encryptedSubject && capsa.subjectIV) {
|
|
131
|
+
if (!capsa.subjectAuthTag) {
|
|
132
|
+
// eslint-disable-next-line no-console
|
|
133
|
+
console.warn('WARNING: encryptedSubject missing authTag - skipping decryption for security');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const subjectBuffer = decryptAES(capsa.encryptedSubject, masterKey, capsa.subjectIV, capsa.subjectAuthTag);
|
|
137
|
+
subject = subjectBuffer.toString('utf-8');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (capsa.encryptedBody && capsa.bodyIV) {
|
|
141
|
+
if (!capsa.bodyAuthTag) {
|
|
142
|
+
// eslint-disable-next-line no-console
|
|
143
|
+
console.warn('WARNING: encryptedBody missing authTag - skipping decryption for security');
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const bodyBuffer = decryptAES(capsa.encryptedBody, masterKey, capsa.bodyIV, capsa.bodyAuthTag);
|
|
147
|
+
body = bodyBuffer.toString('utf-8');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (capsa.encryptedStructured && capsa.structuredIV) {
|
|
151
|
+
if (!capsa.structuredAuthTag) {
|
|
152
|
+
// eslint-disable-next-line no-console
|
|
153
|
+
console.warn('WARNING: encryptedStructured missing authTag - skipping decryption for security');
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const structuredBuffer = decryptAES(capsa.encryptedStructured, masterKey, capsa.structuredIV, capsa.structuredAuthTag);
|
|
157
|
+
structured = JSON.parse(structuredBuffer.toString('utf-8'));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Map soft_deleted to expired for SDK consumers (soft_deleted is internal server status)
|
|
161
|
+
const status = capsa.status === 'soft_deleted' ? 'expired' :
|
|
162
|
+
capsa.status === 'expired' ? 'expired' : 'active';
|
|
163
|
+
const decryptedCapsa = {
|
|
164
|
+
id: capsa.id,
|
|
165
|
+
creator: capsa.creator,
|
|
166
|
+
createdAt: capsa.createdAt,
|
|
167
|
+
updatedAt: capsa.updatedAt,
|
|
168
|
+
status,
|
|
169
|
+
subject,
|
|
170
|
+
body,
|
|
171
|
+
structured,
|
|
172
|
+
files: capsa.files,
|
|
173
|
+
accessControl: capsa.accessControl,
|
|
174
|
+
keychain: capsa.keychain,
|
|
175
|
+
signature: capsa.signature,
|
|
176
|
+
metadata: capsa.metadata,
|
|
177
|
+
stats: {
|
|
178
|
+
totalSize: capsa.totalSize,
|
|
179
|
+
fileCount: capsa.files?.length ?? 0,
|
|
180
|
+
},
|
|
181
|
+
_encrypted: capsa,
|
|
182
|
+
_masterKey: masterKey, // Placeholder, will be redefined as non-enumerable
|
|
183
|
+
clearMasterKey: function () {
|
|
184
|
+
// Implementation added below
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
// Non-enumerable to prevent serialization
|
|
188
|
+
Object.defineProperty(decryptedCapsa, '_masterKey', {
|
|
189
|
+
value: masterKey,
|
|
190
|
+
enumerable: false, // Hidden from enumeration
|
|
191
|
+
writable: false, // Immutable
|
|
192
|
+
configurable: true // Allow clearMasterKey() to replace with zeroed buffer
|
|
193
|
+
});
|
|
194
|
+
decryptedCapsa.clearMasterKey = function () {
|
|
195
|
+
if (this._masterKey && this._masterKey.length > 0) {
|
|
196
|
+
// Overwrite master key buffer with cryptographically random data
|
|
197
|
+
crypto.randomFillSync(this._masterKey);
|
|
198
|
+
Object.defineProperty(this, '_masterKey', {
|
|
199
|
+
value: Buffer.alloc(0),
|
|
200
|
+
enumerable: false,
|
|
201
|
+
writable: false,
|
|
202
|
+
configurable: false // Lock down after clearing
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
return decryptedCapsa;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Decrypt a file from a capsa
|
|
210
|
+
*
|
|
211
|
+
* SECURITY: Requires non-empty authTag for AES-GCM integrity verification
|
|
212
|
+
*
|
|
213
|
+
* @param encryptedFileData - Encrypted file data (base64url)
|
|
214
|
+
* @param masterKey - Decrypted master key
|
|
215
|
+
* @param iv - Initialization vector for file
|
|
216
|
+
* @param authTag - Authentication tag for file (REQUIRED)
|
|
217
|
+
* @returns Decrypted file buffer
|
|
218
|
+
* @throws Error if authTag is missing or decryption fails
|
|
219
|
+
*/
|
|
220
|
+
export async function decryptFile(encryptedFileData, masterKey, iv, authTag, compressed) {
|
|
221
|
+
// SECURITY: Validate authTag is present
|
|
222
|
+
if (!authTag || authTag.trim() === '') {
|
|
223
|
+
throw new Error('SECURITY ERROR: authTag is required for file decryption. Missing authTag indicates potential tampering.');
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const decryptedData = decryptAES(encryptedFileData, masterKey, iv, authTag);
|
|
227
|
+
if (compressed) {
|
|
228
|
+
return await decompressData(decryptedData);
|
|
229
|
+
}
|
|
230
|
+
return decryptedData;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
234
|
+
throw new Error(`Failed to decrypt file: ${message}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Decrypt filename from capsa
|
|
239
|
+
*
|
|
240
|
+
* SECURITY: Requires non-empty authTag for AES-GCM integrity verification
|
|
241
|
+
*
|
|
242
|
+
* @param encryptedFilename - Encrypted filename (base64url)
|
|
243
|
+
* @param masterKey - Decrypted master key
|
|
244
|
+
* @param iv - Initialization vector for filename
|
|
245
|
+
* @param authTag - Authentication tag for filename (REQUIRED)
|
|
246
|
+
* @returns Decrypted filename
|
|
247
|
+
* @throws Error if authTag is missing or decryption fails
|
|
248
|
+
*/
|
|
249
|
+
export function decryptFilename(encryptedFilename, masterKey, iv, authTag) {
|
|
250
|
+
// SECURITY: Validate authTag is present
|
|
251
|
+
if (!authTag || authTag.trim() === '') {
|
|
252
|
+
throw new Error('SECURITY ERROR: authTag is required for filename decryption. Missing authTag indicates potential tampering.');
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
const filenameBuffer = decryptAES(encryptedFilename, masterKey, iv, authTag);
|
|
256
|
+
return filenameBuffer.toString('utf-8');
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
260
|
+
throw new Error(`Failed to decrypt filename: ${message}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=capsa-decryptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capsa-decryptor.js","sourceRoot":"","sources":["../../../src/internal/decryptor/capsa-decryptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client factory - eliminates HTTP setup duplication across services
|
|
3
|
+
* @file capsara.sdk/typescript/src/internal/http-factory.ts
|
|
4
|
+
*/
|
|
5
|
+
import { AxiosInstance } from 'axios';
|
|
6
|
+
import * as http from 'http';
|
|
7
|
+
import * as https from 'https';
|
|
8
|
+
import type { RetryConfig } from './config/retry-interceptor.js';
|
|
9
|
+
/**
|
|
10
|
+
* HTTP client timeout configuration
|
|
11
|
+
*/
|
|
12
|
+
export interface HttpTimeoutConfig {
|
|
13
|
+
/** Timeout for standard API requests (ms) */
|
|
14
|
+
apiTimeout: number;
|
|
15
|
+
/** Timeout for multipart envelope uploads (ms) */
|
|
16
|
+
uploadTimeout: number;
|
|
17
|
+
/** Timeout for file downloads (ms) */
|
|
18
|
+
downloadTimeout: number;
|
|
19
|
+
/** Socket connection timeout (ms) */
|
|
20
|
+
connectTimeout: number;
|
|
21
|
+
/** Keep-alive probe interval (ms) */
|
|
22
|
+
keepAliveInterval: number;
|
|
23
|
+
/** Maximum concurrent sockets per host */
|
|
24
|
+
maxSockets: number;
|
|
25
|
+
/** Maximum idle sockets to keep alive */
|
|
26
|
+
maxFreeSockets: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Default timeout configuration
|
|
30
|
+
*
|
|
31
|
+
* CRITICAL: SDK timeouts must EXCEED server timeouts to prevent ECONNRESET errors
|
|
32
|
+
*
|
|
33
|
+
* vault.api server timeouts:
|
|
34
|
+
* - Server request timeout: 10 minutes
|
|
35
|
+
* - Server keepAlive: 11 minutes
|
|
36
|
+
* - MongoDB socket timeout: 30 seconds
|
|
37
|
+
* - Circuit breaker timeout: 30 seconds
|
|
38
|
+
*/
|
|
39
|
+
export declare const DEFAULT_TIMEOUT_CONFIG: HttpTimeoutConfig;
|
|
40
|
+
/**
|
|
41
|
+
* Options for creating an HTTP client
|
|
42
|
+
*/
|
|
43
|
+
export interface HttpClientOptions {
|
|
44
|
+
/** API base URL */
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
/** Timeout configuration */
|
|
47
|
+
timeout?: Partial<HttpTimeoutConfig>;
|
|
48
|
+
/** Retry configuration */
|
|
49
|
+
retry?: RetryConfig;
|
|
50
|
+
/** Function to get auth token (for authenticated requests) */
|
|
51
|
+
getToken?: () => string | null;
|
|
52
|
+
/** Custom user agent string to append to default SDK user agent */
|
|
53
|
+
userAgent?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Logger interface for retry interceptor
|
|
57
|
+
*/
|
|
58
|
+
export interface RetryLogger {
|
|
59
|
+
log: (message: string) => void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a configured axios instance with retry and optional auth
|
|
63
|
+
*
|
|
64
|
+
* This factory eliminates the HTTP setup duplication found in AuthClient,
|
|
65
|
+
* KeyManager, LimitsManager, AccountClient, and CapsaraClient.
|
|
66
|
+
*
|
|
67
|
+
* @param options - HTTP client configuration
|
|
68
|
+
* @returns Configured axios instance
|
|
69
|
+
*/
|
|
70
|
+
export declare function createHttpClient(options: HttpClientOptions): AxiosInstance;
|
|
71
|
+
/**
|
|
72
|
+
* Create HTTP/HTTPS agent for raw requests with custom timeout
|
|
73
|
+
* @param protocol - 'http:' or 'https:'
|
|
74
|
+
* @param timeout - Request timeout in milliseconds
|
|
75
|
+
* @param config - Timeout configuration
|
|
76
|
+
*/
|
|
77
|
+
export declare function createAgentForProtocol(protocol: string, timeout: number, config?: HttpTimeoutConfig): http.Agent | https.Agent;
|
|
78
|
+
//# sourceMappingURL=http-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-factory.d.ts","sourceRoot":"","sources":["../../src/internal/http-factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAGjE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAQpC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrC,0BAA0B;IAC1B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AA0HD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAgC1E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,iBAA0C,GACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAY1B"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client factory - eliminates HTTP setup duplication across services
|
|
3
|
+
* @file capsara.sdk/typescript/src/internal/http-factory.ts
|
|
4
|
+
*/
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
import * as http from 'http';
|
|
7
|
+
import * as https from 'https';
|
|
8
|
+
import { SDK_VERSION, buildUserAgent } from './version.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default timeout configuration
|
|
11
|
+
*
|
|
12
|
+
* CRITICAL: SDK timeouts must EXCEED server timeouts to prevent ECONNRESET errors
|
|
13
|
+
*
|
|
14
|
+
* vault.api server timeouts:
|
|
15
|
+
* - Server request timeout: 10 minutes
|
|
16
|
+
* - Server keepAlive: 11 minutes
|
|
17
|
+
* - MongoDB socket timeout: 30 seconds
|
|
18
|
+
* - Circuit breaker timeout: 30 seconds
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_TIMEOUT_CONFIG = {
|
|
21
|
+
apiTimeout: 12 * 60 * 1000, // 12 minutes (exceeds server 10 min timeout)
|
|
22
|
+
uploadTimeout: 15 * 60 * 1000, // 15 minutes for multipart uploads
|
|
23
|
+
downloadTimeout: 60 * 1000, // 1 minute for file downloads
|
|
24
|
+
connectTimeout: 30 * 1000, // 30 seconds for socket connection
|
|
25
|
+
keepAliveInterval: 30 * 1000, // 30 seconds keep-alive probe interval
|
|
26
|
+
maxSockets: 50, // Max 50 concurrent sockets per host
|
|
27
|
+
maxFreeSockets: 10, // Keep 10 idle sockets alive
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Create HTTP agent with keep-alive and timeout configuration
|
|
31
|
+
*/
|
|
32
|
+
function createHttpAgent(config) {
|
|
33
|
+
return new http.Agent({
|
|
34
|
+
keepAlive: true,
|
|
35
|
+
keepAliveMsecs: config.keepAliveInterval,
|
|
36
|
+
timeout: config.apiTimeout,
|
|
37
|
+
maxSockets: config.maxSockets,
|
|
38
|
+
maxFreeSockets: config.maxFreeSockets,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create HTTPS agent with keep-alive and timeout configuration
|
|
43
|
+
*/
|
|
44
|
+
function createHttpsAgent(config) {
|
|
45
|
+
return new https.Agent({
|
|
46
|
+
keepAlive: true,
|
|
47
|
+
keepAliveMsecs: config.keepAliveInterval,
|
|
48
|
+
timeout: config.apiTimeout,
|
|
49
|
+
maxSockets: config.maxSockets,
|
|
50
|
+
maxFreeSockets: config.maxFreeSockets,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Default retry configuration
|
|
55
|
+
*/
|
|
56
|
+
const DEFAULT_RETRY_CONFIG = {
|
|
57
|
+
maxRetries: 3,
|
|
58
|
+
baseDelay: 1000,
|
|
59
|
+
maxDelay: 30000,
|
|
60
|
+
enableLogging: false,
|
|
61
|
+
// eslint-disable-next-line no-console
|
|
62
|
+
logger: { log: (msg) => console.log(msg) },
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Calculate retry delay using exponential backoff
|
|
66
|
+
*/
|
|
67
|
+
function calculateExponentialBackoff(retryCount, baseDelay, maxDelay) {
|
|
68
|
+
const exponentialDelay = baseDelay * Math.pow(2, retryCount);
|
|
69
|
+
const jitter = Math.random() * 0.3 * exponentialDelay;
|
|
70
|
+
return Math.min(Math.floor(exponentialDelay + jitter), maxDelay);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Sleep for specified duration
|
|
74
|
+
*/
|
|
75
|
+
function sleep(ms) {
|
|
76
|
+
return new Promise(resolve => globalThis.setTimeout(resolve, ms));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if error is retryable (503 or 429)
|
|
80
|
+
*/
|
|
81
|
+
function isRetryableStatus(status) {
|
|
82
|
+
return status === 503 || status === 429;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Extract retry delay from server response
|
|
86
|
+
*/
|
|
87
|
+
function getServerSuggestedDelay(response) {
|
|
88
|
+
// Check response body for retryAfter field
|
|
89
|
+
const data = response.data;
|
|
90
|
+
if (data?.error?.retryAfter && typeof data.error.retryAfter === 'number') {
|
|
91
|
+
return data.error.retryAfter * 1000;
|
|
92
|
+
}
|
|
93
|
+
// Check Retry-After header
|
|
94
|
+
const retryAfter = response.headers?.['retry-after'];
|
|
95
|
+
if (retryAfter) {
|
|
96
|
+
const seconds = parseInt(retryAfter, 10);
|
|
97
|
+
if (!isNaN(seconds)) {
|
|
98
|
+
return seconds * 1000;
|
|
99
|
+
}
|
|
100
|
+
const date = new Date(retryAfter);
|
|
101
|
+
if (!isNaN(date.getTime())) {
|
|
102
|
+
const delay = date.getTime() - Date.now();
|
|
103
|
+
return delay > 0 ? delay : 0;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Add retry interceptor to axios instance
|
|
110
|
+
*/
|
|
111
|
+
function addRetryInterceptor(axiosInstance, config = {}) {
|
|
112
|
+
const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
113
|
+
axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
114
|
+
// Type guard for axios error structure
|
|
115
|
+
const axiosError = error;
|
|
116
|
+
const requestConfig = axiosError.config;
|
|
117
|
+
if (!requestConfig) {
|
|
118
|
+
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
119
|
+
}
|
|
120
|
+
if (requestConfig.__retryCount === undefined) {
|
|
121
|
+
requestConfig.__retryCount = 0;
|
|
122
|
+
}
|
|
123
|
+
const status = axiosError.response?.status;
|
|
124
|
+
if (!status || !isRetryableStatus(status) || requestConfig.__retryCount >= retryConfig.maxRetries) {
|
|
125
|
+
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
126
|
+
}
|
|
127
|
+
requestConfig.__retryCount++;
|
|
128
|
+
let retryDelay;
|
|
129
|
+
const serverDelay = axiosError.response ? getServerSuggestedDelay(axiosError.response) : null;
|
|
130
|
+
if (serverDelay !== null) {
|
|
131
|
+
retryDelay = Math.min(serverDelay, retryConfig.maxDelay);
|
|
132
|
+
if (retryConfig.enableLogging) {
|
|
133
|
+
retryConfig.logger.log(`[Capsara SDK] Retry ${requestConfig.__retryCount}/${retryConfig.maxRetries} for ${status} - waiting ${retryDelay}ms (server suggested)`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
retryDelay = calculateExponentialBackoff(requestConfig.__retryCount - 1, retryConfig.baseDelay, retryConfig.maxDelay);
|
|
138
|
+
if (retryConfig.enableLogging) {
|
|
139
|
+
retryConfig.logger.log(`[Capsara SDK] Retry ${requestConfig.__retryCount}/${retryConfig.maxRetries} for ${status} - waiting ${retryDelay}ms (exponential backoff)`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
await sleep(retryDelay);
|
|
143
|
+
return axiosInstance.request(requestConfig);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create a configured axios instance with retry and optional auth
|
|
148
|
+
*
|
|
149
|
+
* This factory eliminates the HTTP setup duplication found in AuthClient,
|
|
150
|
+
* KeyManager, LimitsManager, AccountClient, and CapsaraClient.
|
|
151
|
+
*
|
|
152
|
+
* @param options - HTTP client configuration
|
|
153
|
+
* @returns Configured axios instance
|
|
154
|
+
*/
|
|
155
|
+
export function createHttpClient(options) {
|
|
156
|
+
const timeoutConfig = { ...DEFAULT_TIMEOUT_CONFIG, ...options.timeout };
|
|
157
|
+
const axiosConfig = {
|
|
158
|
+
baseURL: options.baseUrl,
|
|
159
|
+
timeout: timeoutConfig.apiTimeout,
|
|
160
|
+
httpAgent: createHttpAgent(timeoutConfig),
|
|
161
|
+
httpsAgent: createHttpsAgent(timeoutConfig),
|
|
162
|
+
headers: {
|
|
163
|
+
'User-Agent': buildUserAgent(options.userAgent),
|
|
164
|
+
'X-SDK-Version': SDK_VERSION,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
const axiosInstance = axios.create(axiosConfig);
|
|
168
|
+
// Add retry interceptor
|
|
169
|
+
addRetryInterceptor(axiosInstance, options.retry);
|
|
170
|
+
// Add auth interceptor if token getter provided
|
|
171
|
+
if (options.getToken) {
|
|
172
|
+
const getToken = options.getToken;
|
|
173
|
+
axiosInstance.interceptors.request.use((config) => {
|
|
174
|
+
const token = getToken();
|
|
175
|
+
if (token) {
|
|
176
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
177
|
+
}
|
|
178
|
+
return config;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return axiosInstance;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Create HTTP/HTTPS agent for raw requests with custom timeout
|
|
185
|
+
* @param protocol - 'http:' or 'https:'
|
|
186
|
+
* @param timeout - Request timeout in milliseconds
|
|
187
|
+
* @param config - Timeout configuration
|
|
188
|
+
*/
|
|
189
|
+
export function createAgentForProtocol(protocol, timeout, config = DEFAULT_TIMEOUT_CONFIG) {
|
|
190
|
+
const agentConfig = {
|
|
191
|
+
keepAlive: true,
|
|
192
|
+
keepAliveMsecs: config.keepAliveInterval,
|
|
193
|
+
timeout,
|
|
194
|
+
maxSockets: config.maxSockets,
|
|
195
|
+
maxFreeSockets: config.maxFreeSockets,
|
|
196
|
+
};
|
|
197
|
+
return protocol === 'https:'
|
|
198
|
+
? new https.Agent(agentConfig)
|
|
199
|
+
: new http.Agent(agentConfig);
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=http-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-factory.js","sourceRoot":"","sources":["../../src/internal/http-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Internal module exports. */
|
|
2
|
+
export { createHttpClient, createAgentForProtocol, DEFAULT_TIMEOUT_CONFIG, type HttpClientOptions, type HttpTimeoutConfig, type RetryLogger, } from './http-factory.js';
|
|
3
|
+
export { RetryExecutor, createRetryExecutor, type RetryConfig, type RawHttpOptions, type RawHttpResponse, } from './retry-executor.js';
|
|
4
|
+
export { DecryptedCapsaCache, createCapsaCache, type CachedCapsa, type CachedFileMetadata, type CapsaCacheConfig, } from './capsa-cache.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Internal module exports. */
|
|
2
|
+
export { createHttpClient, createAgentForProtocol, DEFAULT_TIMEOUT_CONFIG, } from './http-factory.js';
|
|
3
|
+
export { RetryExecutor, createRetryExecutor, } from './retry-executor.js';
|
|
4
|
+
export { DecryptedCapsaCache, createCapsaCache, } from './capsa-cache.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,GAIvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GAIjB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified retry executor - eliminates retry logic duplication
|
|
3
|
+
* @file capsara.sdk/typescript/src/internal/retry-executor.ts
|
|
4
|
+
*
|
|
5
|
+
* This module provides a unified retry mechanism that can be used for:
|
|
6
|
+
* - Axios HTTP requests (via interceptor in http-factory)
|
|
7
|
+
* - Raw HTTP/HTTPS requests (for multipart uploads)
|
|
8
|
+
* - Generic async operations
|
|
9
|
+
*/
|
|
10
|
+
import * as http from 'http';
|
|
11
|
+
import { type HttpTimeoutConfig } from './http-factory.js';
|
|
12
|
+
/**
|
|
13
|
+
* Logger interface for retry operations
|
|
14
|
+
*/
|
|
15
|
+
export interface RetryLogger {
|
|
16
|
+
log: (message: string) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Retry configuration
|
|
20
|
+
*/
|
|
21
|
+
export interface RetryConfig {
|
|
22
|
+
maxRetries?: number;
|
|
23
|
+
baseDelay?: number;
|
|
24
|
+
maxDelay?: number;
|
|
25
|
+
enableLogging?: boolean;
|
|
26
|
+
logger?: RetryLogger;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for raw HTTP requests
|
|
30
|
+
*/
|
|
31
|
+
export interface RawHttpOptions {
|
|
32
|
+
url: string;
|
|
33
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
body?: Buffer | string;
|
|
36
|
+
timeout?: number;
|
|
37
|
+
timeoutConfig?: HttpTimeoutConfig;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Response from raw HTTP request
|
|
41
|
+
*/
|
|
42
|
+
export interface RawHttpResponse {
|
|
43
|
+
statusCode: number;
|
|
44
|
+
headers: http.IncomingHttpHeaders;
|
|
45
|
+
body: Buffer;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Unified retry executor for both axios and raw HTTP requests
|
|
49
|
+
*/
|
|
50
|
+
export declare class RetryExecutor {
|
|
51
|
+
private config;
|
|
52
|
+
constructor(config?: RetryConfig);
|
|
53
|
+
/**
|
|
54
|
+
* Execute a generic async operation with retry
|
|
55
|
+
*/
|
|
56
|
+
execute<T>(operation: () => Promise<T>, isRetryable?: (error: unknown) => boolean): Promise<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Execute a raw HTTP request with retry (for multipart uploads)
|
|
59
|
+
*
|
|
60
|
+
* This replaces the duplicated retry logic in:
|
|
61
|
+
* - CapsaraClient#sendCapsasWithRetry (121 lines)
|
|
62
|
+
* - CapsaraClient#downloadFileWithRetry (54 lines)
|
|
63
|
+
*/
|
|
64
|
+
executeRawHttp(options: RawHttpOptions): Promise<RawHttpResponse>;
|
|
65
|
+
/**
|
|
66
|
+
* Make a single raw HTTP request
|
|
67
|
+
*/
|
|
68
|
+
private makeRawRequest;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a retry executor with default or custom configuration
|
|
72
|
+
*/
|
|
73
|
+
export declare function createRetryExecutor(config?: RetryConfig): RetryExecutor;
|
|
74
|
+
//# sourceMappingURL=retry-executor.d.ts.map
|