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