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