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.
Files changed (71) hide show
  1. package/dist/{client-BWp5FI3x.d.ts → client-B6fUFAUM.d.mts} +2 -1
  2. package/dist/{client-BIfLMfuC.d.mts → client-DoczGA6L.d.ts} +2 -1
  3. package/dist/client-DzElM7u-.d.mts +238 -0
  4. package/dist/client-DzElM7u-.d.ts +238 -0
  5. package/dist/compliance/index.d.mts +5 -4
  6. package/dist/compliance/index.d.ts +5 -4
  7. package/dist/compliance/index.js +306 -98
  8. package/dist/compliance/index.js.map +1 -1
  9. package/dist/compliance/index.mjs +306 -98
  10. package/dist/compliance/index.mjs.map +1 -1
  11. package/dist/decisions/index.d.mts +100 -0
  12. package/dist/decisions/index.d.ts +100 -0
  13. package/dist/decisions/index.js +607 -0
  14. package/dist/decisions/index.js.map +1 -0
  15. package/dist/decisions/index.mjs +605 -0
  16. package/dist/decisions/index.mjs.map +1 -0
  17. package/dist/geolocation/index.d.mts +4 -3
  18. package/dist/geolocation/index.d.ts +4 -3
  19. package/dist/geolocation/index.js +306 -98
  20. package/dist/geolocation/index.js.map +1 -1
  21. package/dist/geolocation/index.mjs +306 -98
  22. package/dist/geolocation/index.mjs.map +1 -1
  23. package/dist/index.d.mts +14 -6
  24. package/dist/index.d.ts +14 -6
  25. package/dist/index.js +641 -90
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +632 -91
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/kyc/core.d.mts +3 -2
  30. package/dist/kyc/core.d.ts +3 -2
  31. package/dist/kyc/core.js +249 -29
  32. package/dist/kyc/core.js.map +1 -1
  33. package/dist/kyc/core.mjs +249 -29
  34. package/dist/kyc/core.mjs.map +1 -1
  35. package/dist/kyc/index.d.mts +3 -2
  36. package/dist/kyc/index.d.ts +3 -2
  37. package/dist/kyc/index.js +249 -29
  38. package/dist/kyc/index.js.map +1 -1
  39. package/dist/kyc/index.mjs +249 -29
  40. package/dist/kyc/index.mjs.map +1 -1
  41. package/dist/react.d.mts +4 -3
  42. package/dist/react.d.ts +4 -3
  43. package/dist/react.js +1 -1
  44. package/dist/react.js.map +1 -1
  45. package/dist/react.mjs +1 -1
  46. package/dist/react.mjs.map +1 -1
  47. package/dist/risk-profile/index.d.mts +4 -4
  48. package/dist/risk-profile/index.d.ts +4 -4
  49. package/dist/risk-profile/index.js +249 -29
  50. package/dist/risk-profile/index.js.map +1 -1
  51. package/dist/risk-profile/index.mjs +249 -29
  52. package/dist/risk-profile/index.mjs.map +1 -1
  53. package/dist/scores/index.d.mts +96 -0
  54. package/dist/scores/index.d.ts +96 -0
  55. package/dist/scores/index.js +594 -0
  56. package/dist/scores/index.js.map +1 -0
  57. package/dist/scores/index.mjs +591 -0
  58. package/dist/scores/index.mjs.map +1 -0
  59. package/dist/{types-DfHLp_tz.d.ts → types-DLC7Sfy5.d.ts} +1 -1
  60. package/dist/types-DZHongaK.d.mts +61 -0
  61. package/dist/types-DZHongaK.d.ts +61 -0
  62. package/dist/{types-DKCQN4C5.d.mts → types-jaLuzruy.d.mts} +1 -1
  63. package/dist/webhooks/index.d.mts +176 -0
  64. package/dist/webhooks/index.d.ts +176 -0
  65. package/dist/webhooks/index.js +193 -0
  66. package/dist/webhooks/index.js.map +1 -0
  67. package/dist/webhooks/index.mjs +188 -0
  68. package/dist/webhooks/index.mjs.map +1 -0
  69. package/package.json +16 -1
  70. package/dist/types-BpKxSXGF.d.mts +0 -177
  71. package/dist/types-BpKxSXGF.d.ts +0 -177
package/dist/kyc/core.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.2.0";
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
- baseURL: config.baseURL,
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 url = `${serviceURL || this.config.baseURL}${endpoint}`;
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
- throw new CGSError("Request aborted", "REQUEST_ABORTED");
374
+ const abortError = new CGSError("Request aborted", "REQUEST_ABORTED");
375
+ abortError.requestId = requestId;
376
+ throw abortError;
182
377
  }
183
- throw new TimeoutError(this.config.timeout);
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
- throw new NetworkError("Network request failed", error);
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
- switch (status) {
231
- case 400:
232
- throw new CGSError(message, "BAD_REQUEST", 400, data);
233
- case 401:
234
- throw new AuthenticationError(message);
235
- case 403:
236
- throw new CGSError(message, "FORBIDDEN", 403, data);
237
- case 404:
238
- throw new CGSError(message, "NOT_FOUND", 404, data);
239
- case 429: {
240
- const retryAfter = data.retry_after || data.retryAfter;
241
- throw new RateLimitError(retryAfter);
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
- case 500:
244
- case 502:
245
- case 503:
246
- case 504:
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
  */