vesant-sdk 1.2.0 → 1.3.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.
- package/dist/{client-BWp5FI3x.d.ts → client-B6fUFAUM.d.mts} +2 -1
- package/dist/{client-BIfLMfuC.d.mts → client-DoczGA6L.d.ts} +2 -1
- package/dist/client-DzElM7u-.d.mts +238 -0
- package/dist/client-DzElM7u-.d.ts +238 -0
- package/dist/compliance/index.d.mts +5 -4
- package/dist/compliance/index.d.ts +5 -4
- package/dist/compliance/index.js +306 -98
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +306 -98
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/decisions/index.d.mts +100 -0
- package/dist/decisions/index.d.ts +100 -0
- package/dist/decisions/index.js +607 -0
- package/dist/decisions/index.js.map +1 -0
- package/dist/decisions/index.mjs +605 -0
- package/dist/decisions/index.mjs.map +1 -0
- package/dist/geolocation/index.d.mts +4 -3
- package/dist/geolocation/index.d.ts +4 -3
- package/dist/geolocation/index.js +306 -98
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +306 -98
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index.d.mts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +641 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +632 -91
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +3 -2
- package/dist/kyc/core.d.ts +3 -2
- package/dist/kyc/core.js +249 -29
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +249 -29
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +3 -2
- package/dist/kyc/index.d.ts +3 -2
- package/dist/kyc/index.js +249 -29
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +249 -29
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +4 -3
- package/dist/react.d.ts +4 -3
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1 -1
- package/dist/react.mjs.map +1 -1
- package/dist/risk-profile/index.d.mts +4 -4
- package/dist/risk-profile/index.d.ts +4 -4
- package/dist/risk-profile/index.js +249 -29
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +249 -29
- package/dist/risk-profile/index.mjs.map +1 -1
- package/dist/scores/index.d.mts +96 -0
- package/dist/scores/index.d.ts +96 -0
- package/dist/scores/index.js +594 -0
- package/dist/scores/index.js.map +1 -0
- package/dist/scores/index.mjs +591 -0
- package/dist/scores/index.mjs.map +1 -0
- package/dist/{types-DfHLp_tz.d.ts → types-DLC7Sfy5.d.ts} +1 -1
- package/dist/types-DZHongaK.d.mts +61 -0
- package/dist/types-DZHongaK.d.ts +61 -0
- package/dist/{types-DKCQN4C5.d.mts → types-jaLuzruy.d.mts} +1 -1
- package/dist/webhooks/index.d.mts +176 -0
- package/dist/webhooks/index.d.ts +176 -0
- package/dist/webhooks/index.js +193 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +188 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +16 -1
- package/dist/types-BpKxSXGF.d.mts +0 -177
- package/dist/types-BpKxSXGF.d.ts +0 -177
package/dist/kyc/index.js
CHANGED
|
@@ -56,6 +56,146 @@ var TimeoutError = class _TimeoutError extends CGSError {
|
|
|
56
56
|
Object.setPrototypeOf(this, _TimeoutError.prototype);
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
|
+
var CircuitBreakerOpenError = class _CircuitBreakerOpenError extends CGSError {
|
|
60
|
+
constructor() {
|
|
61
|
+
super("Circuit breaker is open \u2014 requests are temporarily blocked", "CIRCUIT_BREAKER_OPEN", 503);
|
|
62
|
+
this.name = "CircuitBreakerOpenError";
|
|
63
|
+
Object.setPrototypeOf(this, _CircuitBreakerOpenError.prototype);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/core/circuit-breaker.ts
|
|
68
|
+
var CircuitBreaker = class {
|
|
69
|
+
constructor(config = {}) {
|
|
70
|
+
this.state = "closed";
|
|
71
|
+
this.failures = 0;
|
|
72
|
+
this.successes = 0;
|
|
73
|
+
this.lastFailureTime = null;
|
|
74
|
+
this.failureThreshold = config.failureThreshold ?? 5;
|
|
75
|
+
this.resetTimeout = config.resetTimeout ?? 3e4;
|
|
76
|
+
this.successThreshold = config.successThreshold ?? 1;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if a request can proceed through the circuit breaker.
|
|
80
|
+
*/
|
|
81
|
+
canExecute() {
|
|
82
|
+
if (this.state === "closed") {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (this.state === "open") {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
if (this.lastFailureTime && now - this.lastFailureTime >= this.resetTimeout) {
|
|
88
|
+
this.state = "half-open";
|
|
89
|
+
this.successes = 0;
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Record a successful request.
|
|
98
|
+
*/
|
|
99
|
+
onSuccess() {
|
|
100
|
+
if (this.state === "half-open") {
|
|
101
|
+
this.successes++;
|
|
102
|
+
if (this.successes >= this.successThreshold) {
|
|
103
|
+
this.state = "closed";
|
|
104
|
+
this.failures = 0;
|
|
105
|
+
this.successes = 0;
|
|
106
|
+
this.lastFailureTime = null;
|
|
107
|
+
}
|
|
108
|
+
} else if (this.state === "closed") {
|
|
109
|
+
this.failures = 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Record a failed request.
|
|
114
|
+
*/
|
|
115
|
+
onFailure() {
|
|
116
|
+
this.failures++;
|
|
117
|
+
this.lastFailureTime = Date.now();
|
|
118
|
+
if (this.state === "half-open") {
|
|
119
|
+
this.state = "open";
|
|
120
|
+
this.successes = 0;
|
|
121
|
+
} else if (this.state === "closed" && this.failures >= this.failureThreshold) {
|
|
122
|
+
this.state = "open";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get current circuit breaker status.
|
|
127
|
+
*/
|
|
128
|
+
getStatus() {
|
|
129
|
+
return {
|
|
130
|
+
state: this.state,
|
|
131
|
+
failures: this.failures,
|
|
132
|
+
successes: this.successes,
|
|
133
|
+
lastFailureTime: this.lastFailureTime,
|
|
134
|
+
nextRetryTime: this.state === "open" && this.lastFailureTime ? this.lastFailureTime + this.resetTimeout : null
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Reset the circuit breaker to its initial closed state.
|
|
139
|
+
*/
|
|
140
|
+
reset() {
|
|
141
|
+
this.state = "closed";
|
|
142
|
+
this.failures = 0;
|
|
143
|
+
this.successes = 0;
|
|
144
|
+
this.lastFailureTime = null;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/core/rate-limiter.ts
|
|
149
|
+
var RateLimitTracker = class {
|
|
150
|
+
constructor() {
|
|
151
|
+
this.limit = null;
|
|
152
|
+
this.remaining = null;
|
|
153
|
+
this.reset = null;
|
|
154
|
+
this.retryAfter = null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Extract rate limit information from response headers.
|
|
158
|
+
*/
|
|
159
|
+
updateFromHeaders(headers) {
|
|
160
|
+
const limit = headers.get("x-ratelimit-limit");
|
|
161
|
+
const remaining = headers.get("x-ratelimit-remaining");
|
|
162
|
+
const reset = headers.get("x-ratelimit-reset");
|
|
163
|
+
const retryAfter = headers.get("retry-after");
|
|
164
|
+
if (limit !== null) this.limit = parseInt(limit, 10);
|
|
165
|
+
if (remaining !== null) this.remaining = parseInt(remaining, 10);
|
|
166
|
+
if (reset !== null) this.reset = parseInt(reset, 10);
|
|
167
|
+
if (retryAfter !== null) this.retryAfter = parseInt(retryAfter, 10);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Check if the rate limit has been exceeded based on tracked headers.
|
|
171
|
+
*/
|
|
172
|
+
isLimitExceeded() {
|
|
173
|
+
if (this.remaining !== null && this.remaining <= 0) {
|
|
174
|
+
if (this.reset !== null) {
|
|
175
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
176
|
+
if (now >= this.reset) {
|
|
177
|
+
this.remaining = null;
|
|
178
|
+
this.reset = null;
|
|
179
|
+
this.retryAfter = null;
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get current rate limit status.
|
|
189
|
+
*/
|
|
190
|
+
getStatus() {
|
|
191
|
+
return {
|
|
192
|
+
limit: this.limit,
|
|
193
|
+
remaining: this.remaining,
|
|
194
|
+
reset: this.reset,
|
|
195
|
+
retryAfter: this.retryAfter
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
};
|
|
59
199
|
|
|
60
200
|
// src/core/logger.ts
|
|
61
201
|
function createConsoleLogger() {
|
|
@@ -76,11 +216,25 @@ function createConsoleLogger() {
|
|
|
76
216
|
}
|
|
77
217
|
|
|
78
218
|
// src/core/version.ts
|
|
79
|
-
var SDK_VERSION = "1.
|
|
219
|
+
var SDK_VERSION = "1.3.0";
|
|
220
|
+
|
|
221
|
+
// src/shared/browser-utils.ts
|
|
222
|
+
function generateUUID() {
|
|
223
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
224
|
+
return crypto.randomUUID();
|
|
225
|
+
}
|
|
226
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
227
|
+
const r = Math.random() * 16 | 0;
|
|
228
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
229
|
+
return v.toString(16);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
80
232
|
|
|
81
233
|
// src/core/client.ts
|
|
82
234
|
var BaseClient = class {
|
|
83
235
|
constructor(config) {
|
|
236
|
+
this.circuitBreaker = null;
|
|
237
|
+
this.rateLimitTracker = null;
|
|
84
238
|
if (!config.baseURL?.trim()) {
|
|
85
239
|
throw new ValidationError("baseURL is required and must be a non-empty string", ["baseURL"]);
|
|
86
240
|
}
|
|
@@ -90,8 +244,7 @@ var BaseClient = class {
|
|
|
90
244
|
this.interceptors = config.interceptors || [];
|
|
91
245
|
this.logger = config.logger || createConsoleLogger();
|
|
92
246
|
this.config = {
|
|
93
|
-
|
|
94
|
-
tenantId: config.tenantId,
|
|
247
|
+
...config,
|
|
95
248
|
apiKey: config.apiKey || "",
|
|
96
249
|
headers: config.headers || {},
|
|
97
250
|
timeout: config.timeout || 1e4,
|
|
@@ -100,22 +253,49 @@ var BaseClient = class {
|
|
|
100
253
|
interceptors: this.interceptors,
|
|
101
254
|
logger: this.logger
|
|
102
255
|
};
|
|
256
|
+
if (config.circuitBreaker) {
|
|
257
|
+
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
258
|
+
}
|
|
259
|
+
if (config.enableRateLimitTracking) {
|
|
260
|
+
this.rateLimitTracker = new RateLimitTracker();
|
|
261
|
+
}
|
|
103
262
|
}
|
|
104
263
|
/**
|
|
105
264
|
* Make an HTTP request with timeout and error handling
|
|
106
265
|
*/
|
|
107
266
|
async request(endpoint, options = {}, serviceURL, requestOptions) {
|
|
108
|
-
const
|
|
267
|
+
const requestId = generateUUID();
|
|
268
|
+
if (this.circuitBreaker && !this.circuitBreaker.canExecute()) {
|
|
269
|
+
const error = new CircuitBreakerOpenError();
|
|
270
|
+
error.requestId = requestId;
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
if (this.rateLimitTracker && this.rateLimitTracker.isLimitExceeded()) {
|
|
274
|
+
const status = this.rateLimitTracker.getStatus();
|
|
275
|
+
const error = new RateLimitError(status.retryAfter ?? void 0);
|
|
276
|
+
error.requestId = requestId;
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
const baseURL = this.config.environment === "sandbox" && this.config.sandboxBaseURL ? this.config.sandboxBaseURL : serviceURL || this.config.baseURL;
|
|
280
|
+
const url = `${serviceURL || baseURL}${endpoint}`;
|
|
109
281
|
const headers = {
|
|
110
282
|
"Content-Type": "application/json",
|
|
111
283
|
"X-Tenant-ID": this.config.tenantId,
|
|
112
284
|
"X-SDK-Version": `vesant-sdk-ts/${SDK_VERSION}`,
|
|
285
|
+
"X-Request-ID": requestId,
|
|
113
286
|
...this.config.headers,
|
|
114
287
|
...options.headers || {}
|
|
115
288
|
};
|
|
116
289
|
if (this.config.apiKey) {
|
|
117
290
|
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
118
291
|
}
|
|
292
|
+
if (this.config.environment === "sandbox") {
|
|
293
|
+
headers["X-Sandbox"] = "true";
|
|
294
|
+
}
|
|
295
|
+
const method = (options.method || "GET").toUpperCase();
|
|
296
|
+
if (["POST", "PUT", "PATCH"].includes(method)) {
|
|
297
|
+
headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
|
|
298
|
+
}
|
|
119
299
|
const controller = new AbortController();
|
|
120
300
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
121
301
|
if (requestOptions?.signal) {
|
|
@@ -143,6 +323,9 @@ var BaseClient = class {
|
|
|
143
323
|
signal: controller.signal
|
|
144
324
|
});
|
|
145
325
|
clearTimeout(timeoutId);
|
|
326
|
+
if (this.rateLimitTracker) {
|
|
327
|
+
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
328
|
+
}
|
|
146
329
|
let data;
|
|
147
330
|
try {
|
|
148
331
|
data = await response.json();
|
|
@@ -151,13 +334,15 @@ var BaseClient = class {
|
|
|
151
334
|
this.handleErrorResponse(response.status, {
|
|
152
335
|
error: `HTTP ${response.status}`,
|
|
153
336
|
message: response.statusText
|
|
154
|
-
});
|
|
337
|
+
}, requestId);
|
|
155
338
|
}
|
|
339
|
+
this.circuitBreaker?.onSuccess();
|
|
156
340
|
return void 0;
|
|
157
341
|
}
|
|
158
342
|
if (!response.ok) {
|
|
159
|
-
this.handleErrorResponse(response.status, data || {});
|
|
343
|
+
this.handleErrorResponse(response.status, data || {}, requestId);
|
|
160
344
|
}
|
|
345
|
+
this.circuitBreaker?.onSuccess();
|
|
161
346
|
let result = data;
|
|
162
347
|
for (const interceptor of this.interceptors) {
|
|
163
348
|
if (interceptor.onResponse) {
|
|
@@ -170,6 +355,14 @@ var BaseClient = class {
|
|
|
170
355
|
return result;
|
|
171
356
|
} catch (error) {
|
|
172
357
|
clearTimeout(timeoutId);
|
|
358
|
+
if (error instanceof CGSError && error.statusCode && error.statusCode >= 500) {
|
|
359
|
+
this.circuitBreaker?.onFailure();
|
|
360
|
+
} else if (error instanceof NetworkError || error instanceof TimeoutError) {
|
|
361
|
+
this.circuitBreaker?.onFailure();
|
|
362
|
+
}
|
|
363
|
+
if (error instanceof CGSError && !error.requestId) {
|
|
364
|
+
error.requestId = requestId;
|
|
365
|
+
}
|
|
173
366
|
if (error instanceof Error) {
|
|
174
367
|
for (const interceptor of this.interceptors) {
|
|
175
368
|
if (interceptor.onError) {
|
|
@@ -180,15 +373,23 @@ var BaseClient = class {
|
|
|
180
373
|
if (error instanceof Error) {
|
|
181
374
|
if (error.name === "AbortError") {
|
|
182
375
|
if (requestOptions?.signal?.aborted) {
|
|
183
|
-
|
|
376
|
+
const abortError = new CGSError("Request aborted", "REQUEST_ABORTED");
|
|
377
|
+
abortError.requestId = requestId;
|
|
378
|
+
throw abortError;
|
|
184
379
|
}
|
|
185
|
-
|
|
380
|
+
this.circuitBreaker?.onFailure();
|
|
381
|
+
const timeoutError = new TimeoutError(this.config.timeout);
|
|
382
|
+
timeoutError.requestId = requestId;
|
|
383
|
+
throw timeoutError;
|
|
186
384
|
}
|
|
187
385
|
if (error instanceof CGSError) {
|
|
188
386
|
throw error;
|
|
189
387
|
}
|
|
190
388
|
}
|
|
191
|
-
|
|
389
|
+
const networkError = new NetworkError("Network request failed", error);
|
|
390
|
+
networkError.requestId = requestId;
|
|
391
|
+
this.circuitBreaker?.onFailure();
|
|
392
|
+
throw networkError;
|
|
192
393
|
}
|
|
193
394
|
}
|
|
194
395
|
/**
|
|
@@ -227,29 +428,36 @@ var BaseClient = class {
|
|
|
227
428
|
/**
|
|
228
429
|
* Handle error responses from API
|
|
229
430
|
*/
|
|
230
|
-
handleErrorResponse(status, data) {
|
|
431
|
+
handleErrorResponse(status, data, requestId) {
|
|
231
432
|
const message = data.error || data.message || `HTTP ${status}`;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
433
|
+
const createError = () => {
|
|
434
|
+
switch (status) {
|
|
435
|
+
case 400:
|
|
436
|
+
return new CGSError(message, "BAD_REQUEST", 400, data);
|
|
437
|
+
case 401:
|
|
438
|
+
return new AuthenticationError(message);
|
|
439
|
+
case 403:
|
|
440
|
+
return new CGSError(message, "FORBIDDEN", 403, data);
|
|
441
|
+
case 404:
|
|
442
|
+
return new CGSError(message, "NOT_FOUND", 404, data);
|
|
443
|
+
case 429: {
|
|
444
|
+
const retryAfter = data.retry_after || data.retryAfter;
|
|
445
|
+
return new RateLimitError(retryAfter);
|
|
446
|
+
}
|
|
447
|
+
case 500:
|
|
448
|
+
case 502:
|
|
449
|
+
case 503:
|
|
450
|
+
case 504:
|
|
451
|
+
return new ServiceUnavailableError(message);
|
|
452
|
+
default:
|
|
453
|
+
return new CGSError(message, "UNKNOWN_ERROR", status, data);
|
|
244
454
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
throw new ServiceUnavailableError(message);
|
|
250
|
-
default:
|
|
251
|
-
throw new CGSError(message, "UNKNOWN_ERROR", status, data);
|
|
455
|
+
};
|
|
456
|
+
const error = createError();
|
|
457
|
+
if (requestId) {
|
|
458
|
+
error.requestId = requestId;
|
|
252
459
|
}
|
|
460
|
+
throw error;
|
|
253
461
|
}
|
|
254
462
|
/**
|
|
255
463
|
* Build query string from parameters
|
|
@@ -293,6 +501,18 @@ var BaseClient = class {
|
|
|
293
501
|
getConfig() {
|
|
294
502
|
return { ...this.config };
|
|
295
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* Get rate limit status from tracked response headers.
|
|
506
|
+
*/
|
|
507
|
+
getRateLimitStatus() {
|
|
508
|
+
return this.rateLimitTracker?.getStatus() ?? null;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Get circuit breaker status.
|
|
512
|
+
*/
|
|
513
|
+
getCircuitBreakerStatus() {
|
|
514
|
+
return this.circuitBreaker?.getStatus() ?? null;
|
|
515
|
+
}
|
|
296
516
|
/**
|
|
297
517
|
* Health check endpoint
|
|
298
518
|
*/
|