vesant-sdk 1.2.0 → 1.3.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/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 +15 -7
- package/dist/index.d.ts +15 -7
- package/dist/index.js +676 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +667 -91
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +4 -3
- package/dist/kyc/core.d.ts +4 -3
- package/dist/kyc/core.js +284 -29
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +284 -29
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +46 -3
- package/dist/kyc/index.d.ts +46 -3
- package/dist/kyc/index.js +284 -29
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +284 -29
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +9 -5
- package/dist/react.d.ts +9 -5
- package/dist/react.js +422 -99
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +322 -4
- 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 +25 -2
- package/dist/types-BpKxSXGF.d.mts +0 -177
- package/dist/types-BpKxSXGF.d.ts +0 -177
|
@@ -62,6 +62,146 @@ var ComplianceError = class _ComplianceError extends CGSError {
|
|
|
62
62
|
Object.setPrototypeOf(this, _ComplianceError.prototype);
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
+
var CircuitBreakerOpenError = class _CircuitBreakerOpenError extends CGSError {
|
|
66
|
+
constructor() {
|
|
67
|
+
super("Circuit breaker is open \u2014 requests are temporarily blocked", "CIRCUIT_BREAKER_OPEN", 503);
|
|
68
|
+
this.name = "CircuitBreakerOpenError";
|
|
69
|
+
Object.setPrototypeOf(this, _CircuitBreakerOpenError.prototype);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/core/circuit-breaker.ts
|
|
74
|
+
var CircuitBreaker = class {
|
|
75
|
+
constructor(config = {}) {
|
|
76
|
+
this.state = "closed";
|
|
77
|
+
this.failures = 0;
|
|
78
|
+
this.successes = 0;
|
|
79
|
+
this.lastFailureTime = null;
|
|
80
|
+
this.failureThreshold = config.failureThreshold ?? 5;
|
|
81
|
+
this.resetTimeout = config.resetTimeout ?? 3e4;
|
|
82
|
+
this.successThreshold = config.successThreshold ?? 1;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if a request can proceed through the circuit breaker.
|
|
86
|
+
*/
|
|
87
|
+
canExecute() {
|
|
88
|
+
if (this.state === "closed") {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
if (this.state === "open") {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
if (this.lastFailureTime && now - this.lastFailureTime >= this.resetTimeout) {
|
|
94
|
+
this.state = "half-open";
|
|
95
|
+
this.successes = 0;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Record a successful request.
|
|
104
|
+
*/
|
|
105
|
+
onSuccess() {
|
|
106
|
+
if (this.state === "half-open") {
|
|
107
|
+
this.successes++;
|
|
108
|
+
if (this.successes >= this.successThreshold) {
|
|
109
|
+
this.state = "closed";
|
|
110
|
+
this.failures = 0;
|
|
111
|
+
this.successes = 0;
|
|
112
|
+
this.lastFailureTime = null;
|
|
113
|
+
}
|
|
114
|
+
} else if (this.state === "closed") {
|
|
115
|
+
this.failures = 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Record a failed request.
|
|
120
|
+
*/
|
|
121
|
+
onFailure() {
|
|
122
|
+
this.failures++;
|
|
123
|
+
this.lastFailureTime = Date.now();
|
|
124
|
+
if (this.state === "half-open") {
|
|
125
|
+
this.state = "open";
|
|
126
|
+
this.successes = 0;
|
|
127
|
+
} else if (this.state === "closed" && this.failures >= this.failureThreshold) {
|
|
128
|
+
this.state = "open";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get current circuit breaker status.
|
|
133
|
+
*/
|
|
134
|
+
getStatus() {
|
|
135
|
+
return {
|
|
136
|
+
state: this.state,
|
|
137
|
+
failures: this.failures,
|
|
138
|
+
successes: this.successes,
|
|
139
|
+
lastFailureTime: this.lastFailureTime,
|
|
140
|
+
nextRetryTime: this.state === "open" && this.lastFailureTime ? this.lastFailureTime + this.resetTimeout : null
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reset the circuit breaker to its initial closed state.
|
|
145
|
+
*/
|
|
146
|
+
reset() {
|
|
147
|
+
this.state = "closed";
|
|
148
|
+
this.failures = 0;
|
|
149
|
+
this.successes = 0;
|
|
150
|
+
this.lastFailureTime = null;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/core/rate-limiter.ts
|
|
155
|
+
var RateLimitTracker = class {
|
|
156
|
+
constructor() {
|
|
157
|
+
this.limit = null;
|
|
158
|
+
this.remaining = null;
|
|
159
|
+
this.reset = null;
|
|
160
|
+
this.retryAfter = null;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extract rate limit information from response headers.
|
|
164
|
+
*/
|
|
165
|
+
updateFromHeaders(headers) {
|
|
166
|
+
const limit = headers.get("x-ratelimit-limit");
|
|
167
|
+
const remaining = headers.get("x-ratelimit-remaining");
|
|
168
|
+
const reset = headers.get("x-ratelimit-reset");
|
|
169
|
+
const retryAfter = headers.get("retry-after");
|
|
170
|
+
if (limit !== null) this.limit = parseInt(limit, 10);
|
|
171
|
+
if (remaining !== null) this.remaining = parseInt(remaining, 10);
|
|
172
|
+
if (reset !== null) this.reset = parseInt(reset, 10);
|
|
173
|
+
if (retryAfter !== null) this.retryAfter = parseInt(retryAfter, 10);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Check if the rate limit has been exceeded based on tracked headers.
|
|
177
|
+
*/
|
|
178
|
+
isLimitExceeded() {
|
|
179
|
+
if (this.remaining !== null && this.remaining <= 0) {
|
|
180
|
+
if (this.reset !== null) {
|
|
181
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
182
|
+
if (now >= this.reset) {
|
|
183
|
+
this.remaining = null;
|
|
184
|
+
this.reset = null;
|
|
185
|
+
this.retryAfter = null;
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get current rate limit status.
|
|
195
|
+
*/
|
|
196
|
+
getStatus() {
|
|
197
|
+
return {
|
|
198
|
+
limit: this.limit,
|
|
199
|
+
remaining: this.remaining,
|
|
200
|
+
reset: this.reset,
|
|
201
|
+
retryAfter: this.retryAfter
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
};
|
|
65
205
|
|
|
66
206
|
// src/core/logger.ts
|
|
67
207
|
function createConsoleLogger() {
|
|
@@ -82,11 +222,82 @@ function createConsoleLogger() {
|
|
|
82
222
|
}
|
|
83
223
|
|
|
84
224
|
// src/core/version.ts
|
|
85
|
-
var SDK_VERSION = "1.
|
|
225
|
+
var SDK_VERSION = "1.3.0";
|
|
226
|
+
|
|
227
|
+
// src/shared/browser-utils.ts
|
|
228
|
+
function generateUUID() {
|
|
229
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
230
|
+
return crypto.randomUUID();
|
|
231
|
+
}
|
|
232
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
233
|
+
const r = Math.random() * 16 | 0;
|
|
234
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
235
|
+
return v.toString(16);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function generateDeviceId() {
|
|
239
|
+
if (typeof window === "undefined" || typeof localStorage === "undefined") {
|
|
240
|
+
return generateUUID();
|
|
241
|
+
}
|
|
242
|
+
const storageKey = "cgs_device_id";
|
|
243
|
+
let deviceId = localStorage.getItem(storageKey);
|
|
244
|
+
if (!deviceId) {
|
|
245
|
+
deviceId = generateUUID();
|
|
246
|
+
localStorage.setItem(storageKey, deviceId);
|
|
247
|
+
}
|
|
248
|
+
return deviceId;
|
|
249
|
+
}
|
|
250
|
+
function getBrowserInfo() {
|
|
251
|
+
if (typeof navigator === "undefined") {
|
|
252
|
+
return { browser: "unknown", browser_version: "", os: "unknown", os_version: "" };
|
|
253
|
+
}
|
|
254
|
+
const ua = navigator.userAgent;
|
|
255
|
+
let browser = "unknown";
|
|
256
|
+
let browserVersion = "";
|
|
257
|
+
let os = "unknown";
|
|
258
|
+
let osVersion = "";
|
|
259
|
+
if (ua.includes("Firefox/")) {
|
|
260
|
+
browser = "Firefox";
|
|
261
|
+
browserVersion = ua.match(/Firefox\/([\d.]+)/)?.[1] || "";
|
|
262
|
+
} else if (ua.includes("Edg/")) {
|
|
263
|
+
browser = "Edge";
|
|
264
|
+
browserVersion = ua.match(/Edg\/([\d.]+)/)?.[1] || "";
|
|
265
|
+
} else if (ua.includes("Chrome/")) {
|
|
266
|
+
browser = "Chrome";
|
|
267
|
+
browserVersion = ua.match(/Chrome\/([\d.]+)/)?.[1] || "";
|
|
268
|
+
} else if (ua.includes("Safari/") && !ua.includes("Chrome")) {
|
|
269
|
+
browser = "Safari";
|
|
270
|
+
browserVersion = ua.match(/Version\/([\d.]+)/)?.[1] || "";
|
|
271
|
+
} else if (ua.includes("Opera") || ua.includes("OPR/")) {
|
|
272
|
+
browser = "Opera";
|
|
273
|
+
browserVersion = ua.match(/(?:Opera|OPR)\/([\d.]+)/)?.[1] || "";
|
|
274
|
+
}
|
|
275
|
+
if (ua.includes("Windows")) {
|
|
276
|
+
os = "Windows";
|
|
277
|
+
if (ua.includes("Windows NT 10.0")) osVersion = "10";
|
|
278
|
+
else if (ua.includes("Windows NT 6.3")) osVersion = "8.1";
|
|
279
|
+
else if (ua.includes("Windows NT 6.2")) osVersion = "8";
|
|
280
|
+
else if (ua.includes("Windows NT 6.1")) osVersion = "7";
|
|
281
|
+
} else if (ua.includes("Mac OS X")) {
|
|
282
|
+
os = "macOS";
|
|
283
|
+
osVersion = ua.match(/Mac OS X ([\d_]+)/)?.[1]?.replace(/_/g, ".") || "";
|
|
284
|
+
} else if (ua.includes("Linux")) {
|
|
285
|
+
os = "Linux";
|
|
286
|
+
} else if (ua.includes("Android")) {
|
|
287
|
+
os = "Android";
|
|
288
|
+
osVersion = ua.match(/Android ([\d.]+)/)?.[1] || "";
|
|
289
|
+
} else if (ua.includes("iOS") || ua.includes("iPhone") || ua.includes("iPad")) {
|
|
290
|
+
os = "iOS";
|
|
291
|
+
osVersion = ua.match(/OS ([\d_]+)/)?.[1]?.replace(/_/g, ".") || "";
|
|
292
|
+
}
|
|
293
|
+
return { browser, browser_version: browserVersion, os, os_version: osVersion };
|
|
294
|
+
}
|
|
86
295
|
|
|
87
296
|
// src/core/client.ts
|
|
88
297
|
var BaseClient = class {
|
|
89
298
|
constructor(config) {
|
|
299
|
+
this.circuitBreaker = null;
|
|
300
|
+
this.rateLimitTracker = null;
|
|
90
301
|
if (!config.baseURL?.trim()) {
|
|
91
302
|
throw new ValidationError("baseURL is required and must be a non-empty string", ["baseURL"]);
|
|
92
303
|
}
|
|
@@ -96,8 +307,7 @@ var BaseClient = class {
|
|
|
96
307
|
this.interceptors = config.interceptors || [];
|
|
97
308
|
this.logger = config.logger || createConsoleLogger();
|
|
98
309
|
this.config = {
|
|
99
|
-
|
|
100
|
-
tenantId: config.tenantId,
|
|
310
|
+
...config,
|
|
101
311
|
apiKey: config.apiKey || "",
|
|
102
312
|
headers: config.headers || {},
|
|
103
313
|
timeout: config.timeout || 1e4,
|
|
@@ -106,22 +316,49 @@ var BaseClient = class {
|
|
|
106
316
|
interceptors: this.interceptors,
|
|
107
317
|
logger: this.logger
|
|
108
318
|
};
|
|
319
|
+
if (config.circuitBreaker) {
|
|
320
|
+
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
321
|
+
}
|
|
322
|
+
if (config.enableRateLimitTracking) {
|
|
323
|
+
this.rateLimitTracker = new RateLimitTracker();
|
|
324
|
+
}
|
|
109
325
|
}
|
|
110
326
|
/**
|
|
111
327
|
* Make an HTTP request with timeout and error handling
|
|
112
328
|
*/
|
|
113
329
|
async request(endpoint, options = {}, serviceURL, requestOptions) {
|
|
114
|
-
const
|
|
330
|
+
const requestId = generateUUID();
|
|
331
|
+
if (this.circuitBreaker && !this.circuitBreaker.canExecute()) {
|
|
332
|
+
const error = new CircuitBreakerOpenError();
|
|
333
|
+
error.requestId = requestId;
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
if (this.rateLimitTracker && this.rateLimitTracker.isLimitExceeded()) {
|
|
337
|
+
const status = this.rateLimitTracker.getStatus();
|
|
338
|
+
const error = new RateLimitError(status.retryAfter ?? void 0);
|
|
339
|
+
error.requestId = requestId;
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
const baseURL = this.config.environment === "sandbox" && this.config.sandboxBaseURL ? this.config.sandboxBaseURL : serviceURL || this.config.baseURL;
|
|
343
|
+
const url = `${serviceURL || baseURL}${endpoint}`;
|
|
115
344
|
const headers = {
|
|
116
345
|
"Content-Type": "application/json",
|
|
117
346
|
"X-Tenant-ID": this.config.tenantId,
|
|
118
347
|
"X-SDK-Version": `vesant-sdk-ts/${SDK_VERSION}`,
|
|
348
|
+
"X-Request-ID": requestId,
|
|
119
349
|
...this.config.headers,
|
|
120
350
|
...options.headers || {}
|
|
121
351
|
};
|
|
122
352
|
if (this.config.apiKey) {
|
|
123
353
|
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
124
354
|
}
|
|
355
|
+
if (this.config.environment === "sandbox") {
|
|
356
|
+
headers["X-Sandbox"] = "true";
|
|
357
|
+
}
|
|
358
|
+
const method = (options.method || "GET").toUpperCase();
|
|
359
|
+
if (["POST", "PUT", "PATCH"].includes(method)) {
|
|
360
|
+
headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
|
|
361
|
+
}
|
|
125
362
|
const controller = new AbortController();
|
|
126
363
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
127
364
|
if (requestOptions?.signal) {
|
|
@@ -149,6 +386,9 @@ var BaseClient = class {
|
|
|
149
386
|
signal: controller.signal
|
|
150
387
|
});
|
|
151
388
|
clearTimeout(timeoutId);
|
|
389
|
+
if (this.rateLimitTracker) {
|
|
390
|
+
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
391
|
+
}
|
|
152
392
|
let data;
|
|
153
393
|
try {
|
|
154
394
|
data = await response.json();
|
|
@@ -157,13 +397,15 @@ var BaseClient = class {
|
|
|
157
397
|
this.handleErrorResponse(response.status, {
|
|
158
398
|
error: `HTTP ${response.status}`,
|
|
159
399
|
message: response.statusText
|
|
160
|
-
});
|
|
400
|
+
}, requestId);
|
|
161
401
|
}
|
|
402
|
+
this.circuitBreaker?.onSuccess();
|
|
162
403
|
return void 0;
|
|
163
404
|
}
|
|
164
405
|
if (!response.ok) {
|
|
165
|
-
this.handleErrorResponse(response.status, data || {});
|
|
406
|
+
this.handleErrorResponse(response.status, data || {}, requestId);
|
|
166
407
|
}
|
|
408
|
+
this.circuitBreaker?.onSuccess();
|
|
167
409
|
let result = data;
|
|
168
410
|
for (const interceptor of this.interceptors) {
|
|
169
411
|
if (interceptor.onResponse) {
|
|
@@ -176,6 +418,14 @@ var BaseClient = class {
|
|
|
176
418
|
return result;
|
|
177
419
|
} catch (error) {
|
|
178
420
|
clearTimeout(timeoutId);
|
|
421
|
+
if (error instanceof CGSError && error.statusCode && error.statusCode >= 500) {
|
|
422
|
+
this.circuitBreaker?.onFailure();
|
|
423
|
+
} else if (error instanceof NetworkError || error instanceof TimeoutError) {
|
|
424
|
+
this.circuitBreaker?.onFailure();
|
|
425
|
+
}
|
|
426
|
+
if (error instanceof CGSError && !error.requestId) {
|
|
427
|
+
error.requestId = requestId;
|
|
428
|
+
}
|
|
179
429
|
if (error instanceof Error) {
|
|
180
430
|
for (const interceptor of this.interceptors) {
|
|
181
431
|
if (interceptor.onError) {
|
|
@@ -186,15 +436,23 @@ var BaseClient = class {
|
|
|
186
436
|
if (error instanceof Error) {
|
|
187
437
|
if (error.name === "AbortError") {
|
|
188
438
|
if (requestOptions?.signal?.aborted) {
|
|
189
|
-
|
|
439
|
+
const abortError = new CGSError("Request aborted", "REQUEST_ABORTED");
|
|
440
|
+
abortError.requestId = requestId;
|
|
441
|
+
throw abortError;
|
|
190
442
|
}
|
|
191
|
-
|
|
443
|
+
this.circuitBreaker?.onFailure();
|
|
444
|
+
const timeoutError = new TimeoutError(this.config.timeout);
|
|
445
|
+
timeoutError.requestId = requestId;
|
|
446
|
+
throw timeoutError;
|
|
192
447
|
}
|
|
193
448
|
if (error instanceof CGSError) {
|
|
194
449
|
throw error;
|
|
195
450
|
}
|
|
196
451
|
}
|
|
197
|
-
|
|
452
|
+
const networkError = new NetworkError("Network request failed", error);
|
|
453
|
+
networkError.requestId = requestId;
|
|
454
|
+
this.circuitBreaker?.onFailure();
|
|
455
|
+
throw networkError;
|
|
198
456
|
}
|
|
199
457
|
}
|
|
200
458
|
/**
|
|
@@ -233,29 +491,36 @@ var BaseClient = class {
|
|
|
233
491
|
/**
|
|
234
492
|
* Handle error responses from API
|
|
235
493
|
*/
|
|
236
|
-
handleErrorResponse(status, data) {
|
|
494
|
+
handleErrorResponse(status, data, requestId) {
|
|
237
495
|
const message = data.error || data.message || `HTTP ${status}`;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
496
|
+
const createError = () => {
|
|
497
|
+
switch (status) {
|
|
498
|
+
case 400:
|
|
499
|
+
return new CGSError(message, "BAD_REQUEST", 400, data);
|
|
500
|
+
case 401:
|
|
501
|
+
return new AuthenticationError(message);
|
|
502
|
+
case 403:
|
|
503
|
+
return new CGSError(message, "FORBIDDEN", 403, data);
|
|
504
|
+
case 404:
|
|
505
|
+
return new CGSError(message, "NOT_FOUND", 404, data);
|
|
506
|
+
case 429: {
|
|
507
|
+
const retryAfter = data.retry_after || data.retryAfter;
|
|
508
|
+
return new RateLimitError(retryAfter);
|
|
509
|
+
}
|
|
510
|
+
case 500:
|
|
511
|
+
case 502:
|
|
512
|
+
case 503:
|
|
513
|
+
case 504:
|
|
514
|
+
return new ServiceUnavailableError(message);
|
|
515
|
+
default:
|
|
516
|
+
return new CGSError(message, "UNKNOWN_ERROR", status, data);
|
|
250
517
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
throw new ServiceUnavailableError(message);
|
|
256
|
-
default:
|
|
257
|
-
throw new CGSError(message, "UNKNOWN_ERROR", status, data);
|
|
518
|
+
};
|
|
519
|
+
const error = createError();
|
|
520
|
+
if (requestId) {
|
|
521
|
+
error.requestId = requestId;
|
|
258
522
|
}
|
|
523
|
+
throw error;
|
|
259
524
|
}
|
|
260
525
|
/**
|
|
261
526
|
* Build query string from parameters
|
|
@@ -299,6 +564,18 @@ var BaseClient = class {
|
|
|
299
564
|
getConfig() {
|
|
300
565
|
return { ...this.config };
|
|
301
566
|
}
|
|
567
|
+
/**
|
|
568
|
+
* Get rate limit status from tracked response headers.
|
|
569
|
+
*/
|
|
570
|
+
getRateLimitStatus() {
|
|
571
|
+
return this.rateLimitTracker?.getStatus() ?? null;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Get circuit breaker status.
|
|
575
|
+
*/
|
|
576
|
+
getCircuitBreakerStatus() {
|
|
577
|
+
return this.circuitBreaker?.getStatus() ?? null;
|
|
578
|
+
}
|
|
302
579
|
/**
|
|
303
580
|
* Health check endpoint
|
|
304
581
|
*/
|
|
@@ -307,75 +584,6 @@ var BaseClient = class {
|
|
|
307
584
|
}
|
|
308
585
|
};
|
|
309
586
|
|
|
310
|
-
// src/shared/browser-utils.ts
|
|
311
|
-
function generateUUID() {
|
|
312
|
-
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
313
|
-
return crypto.randomUUID();
|
|
314
|
-
}
|
|
315
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
316
|
-
const r = Math.random() * 16 | 0;
|
|
317
|
-
const v = c === "x" ? r : r & 3 | 8;
|
|
318
|
-
return v.toString(16);
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
function generateDeviceId() {
|
|
322
|
-
if (typeof window === "undefined" || typeof localStorage === "undefined") {
|
|
323
|
-
return generateUUID();
|
|
324
|
-
}
|
|
325
|
-
const storageKey = "cgs_device_id";
|
|
326
|
-
let deviceId = localStorage.getItem(storageKey);
|
|
327
|
-
if (!deviceId) {
|
|
328
|
-
deviceId = generateUUID();
|
|
329
|
-
localStorage.setItem(storageKey, deviceId);
|
|
330
|
-
}
|
|
331
|
-
return deviceId;
|
|
332
|
-
}
|
|
333
|
-
function getBrowserInfo() {
|
|
334
|
-
if (typeof navigator === "undefined") {
|
|
335
|
-
return { browser: "unknown", browser_version: "", os: "unknown", os_version: "" };
|
|
336
|
-
}
|
|
337
|
-
const ua = navigator.userAgent;
|
|
338
|
-
let browser = "unknown";
|
|
339
|
-
let browserVersion = "";
|
|
340
|
-
let os = "unknown";
|
|
341
|
-
let osVersion = "";
|
|
342
|
-
if (ua.includes("Firefox/")) {
|
|
343
|
-
browser = "Firefox";
|
|
344
|
-
browserVersion = ua.match(/Firefox\/([\d.]+)/)?.[1] || "";
|
|
345
|
-
} else if (ua.includes("Edg/")) {
|
|
346
|
-
browser = "Edge";
|
|
347
|
-
browserVersion = ua.match(/Edg\/([\d.]+)/)?.[1] || "";
|
|
348
|
-
} else if (ua.includes("Chrome/")) {
|
|
349
|
-
browser = "Chrome";
|
|
350
|
-
browserVersion = ua.match(/Chrome\/([\d.]+)/)?.[1] || "";
|
|
351
|
-
} else if (ua.includes("Safari/") && !ua.includes("Chrome")) {
|
|
352
|
-
browser = "Safari";
|
|
353
|
-
browserVersion = ua.match(/Version\/([\d.]+)/)?.[1] || "";
|
|
354
|
-
} else if (ua.includes("Opera") || ua.includes("OPR/")) {
|
|
355
|
-
browser = "Opera";
|
|
356
|
-
browserVersion = ua.match(/(?:Opera|OPR)\/([\d.]+)/)?.[1] || "";
|
|
357
|
-
}
|
|
358
|
-
if (ua.includes("Windows")) {
|
|
359
|
-
os = "Windows";
|
|
360
|
-
if (ua.includes("Windows NT 10.0")) osVersion = "10";
|
|
361
|
-
else if (ua.includes("Windows NT 6.3")) osVersion = "8.1";
|
|
362
|
-
else if (ua.includes("Windows NT 6.2")) osVersion = "8";
|
|
363
|
-
else if (ua.includes("Windows NT 6.1")) osVersion = "7";
|
|
364
|
-
} else if (ua.includes("Mac OS X")) {
|
|
365
|
-
os = "macOS";
|
|
366
|
-
osVersion = ua.match(/Mac OS X ([\d_]+)/)?.[1]?.replace(/_/g, ".") || "";
|
|
367
|
-
} else if (ua.includes("Linux")) {
|
|
368
|
-
os = "Linux";
|
|
369
|
-
} else if (ua.includes("Android")) {
|
|
370
|
-
os = "Android";
|
|
371
|
-
osVersion = ua.match(/Android ([\d.]+)/)?.[1] || "";
|
|
372
|
-
} else if (ua.includes("iOS") || ua.includes("iPhone") || ua.includes("iPad")) {
|
|
373
|
-
os = "iOS";
|
|
374
|
-
osVersion = ua.match(/OS ([\d_]+)/)?.[1]?.replace(/_/g, ".") || "";
|
|
375
|
-
}
|
|
376
|
-
return { browser, browser_version: browserVersion, os, os_version: osVersion };
|
|
377
|
-
}
|
|
378
|
-
|
|
379
587
|
// src/geolocation/ciphertext.ts
|
|
380
588
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
381
589
|
async function computeHMAC(key, message) {
|