@unboundcx/sdk 2.6.16 → 2.7.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/base.js +93 -57
- package/package.json +1 -1
package/base.js
CHANGED
|
@@ -101,6 +101,14 @@ export class BaseSDK {
|
|
|
101
101
|
removeTransport(name) {
|
|
102
102
|
this.transports.delete(name);
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
_getJsonSafely(str, defaultValue) {
|
|
106
|
+
try {
|
|
107
|
+
return JSON.parse(str);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
return defaultValue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
104
112
|
|
|
105
113
|
async _getAvailableTransport(forceFetch = false) {
|
|
106
114
|
if (forceFetch) {
|
|
@@ -174,9 +182,10 @@ export class BaseSDK {
|
|
|
174
182
|
|
|
175
183
|
// Try transport plugins first
|
|
176
184
|
const transport = await this._getAvailableTransport(forceFetch);
|
|
185
|
+
let response;
|
|
177
186
|
if (transport) {
|
|
178
187
|
try {
|
|
179
|
-
|
|
188
|
+
response = await transport.request(endpoint, method, params, {
|
|
180
189
|
namespace: this.namespace,
|
|
181
190
|
token: this.token,
|
|
182
191
|
callId: this.callId,
|
|
@@ -184,13 +193,7 @@ export class BaseSDK {
|
|
|
184
193
|
baseURL: this.baseURL || this.fullUrl,
|
|
185
194
|
});
|
|
186
195
|
|
|
187
|
-
// Debug logging for transport plugins
|
|
188
|
-
if (this.debugMode) {
|
|
189
|
-
const status = result?.status || 200;
|
|
190
|
-
console.log(`API :: ${transport.name} :: ${method.toUpperCase()} :: ${endpoint} :: ${status}`);
|
|
191
|
-
}
|
|
192
196
|
|
|
193
|
-
return result;
|
|
194
197
|
} catch (err) {
|
|
195
198
|
// IMPORTANT: This catch block should ONLY handle transport-level failures
|
|
196
199
|
// (e.g., WebSocket disconnected, plugin unavailable, network errors)
|
|
@@ -198,22 +201,22 @@ export class BaseSDK {
|
|
|
198
201
|
// Transport plugins should:
|
|
199
202
|
// - RETURN API error responses normally (400, 500, etc.) as response objects
|
|
200
203
|
// - ONLY THROW for transport mechanism failures
|
|
201
|
-
//
|
|
202
|
-
// This ensures API errors are passed through unchanged, just like built-in fetch
|
|
203
204
|
|
|
204
|
-
if (this.debugMode) {
|
|
205
|
-
console.log(`API :: Transport ${transport.name} failure :: ${method.toUpperCase()} :: ${endpoint} :: ${err.message}`);
|
|
206
|
-
}
|
|
207
205
|
console.warn(
|
|
208
206
|
`Transport ${transport.name} mechanism failed, falling back to HTTP:`,
|
|
209
207
|
err.message,
|
|
210
208
|
);
|
|
211
|
-
|
|
209
|
+
|
|
210
|
+
// Built-in HTTP transport (fallback)
|
|
211
|
+
return this._httpRequest(endpoint, method, params);
|
|
212
212
|
}
|
|
213
|
+
} else {
|
|
214
|
+
// No transport available, fallback to HTTP
|
|
215
|
+
return this._httpRequest(endpoint, method, params);
|
|
213
216
|
}
|
|
214
217
|
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
return this._processResponse(response, transport.name, method, endpoint);
|
|
219
|
+
|
|
217
220
|
}
|
|
218
221
|
|
|
219
222
|
_isMultipartBody(body) {
|
|
@@ -306,72 +309,105 @@ export class BaseSDK {
|
|
|
306
309
|
|
|
307
310
|
const response = await fetch(url, options);
|
|
308
311
|
|
|
312
|
+
return this._processResponse(response, 'https', method, endpoint);
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async _processResponse(response, transport, method, endpoint) {
|
|
309
317
|
// Check if the response indicates an HTTP error
|
|
310
318
|
// These are API/configuration errors, not transport failures
|
|
319
|
+
|
|
320
|
+
const responseHeaders = response.headers;
|
|
321
|
+
const responseRequestId =
|
|
322
|
+
responseHeaders?.get?.('x-request-id') ||
|
|
323
|
+
responseHeaders?.['x-request-id'] || '';
|
|
324
|
+
|
|
311
325
|
if (!response.ok) {
|
|
312
326
|
let errorBody;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
327
|
+
if (response?.body) {
|
|
328
|
+
errorBody = response.body;
|
|
329
|
+
} else if (response?.headers?.['content-type']) {
|
|
330
|
+
const contentType = response.headers['content-type'];
|
|
331
|
+
try {
|
|
332
|
+
if (typeof response?.json === 'function' || typeof response?.text === 'function') {
|
|
333
|
+
if (contentType.includes('application/json')) {
|
|
334
|
+
errorBody = await response.json();
|
|
335
|
+
} else if (contentType.includes('text/')) {
|
|
336
|
+
errorBody = await response.text();
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
if (contentType.includes('application/json')) {
|
|
340
|
+
errorBody = this._getJsonSafely(response?.body, response?.body || {});
|
|
341
|
+
} else if (contentType.includes('text/')) {
|
|
342
|
+
errorBody = response?.body || '';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (!errorBody) {
|
|
346
|
+
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
347
|
+
}
|
|
348
|
+
} catch (parseError) {
|
|
349
|
+
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
320
350
|
}
|
|
321
|
-
}
|
|
351
|
+
} else {
|
|
322
352
|
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
323
353
|
}
|
|
324
354
|
|
|
325
355
|
// Create a structured error for API/HTTP failures
|
|
326
|
-
const httpError = new Error(`API :: Error ::
|
|
356
|
+
const httpError = new Error(`API :: Error :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response.status} :: ${response.statusText}`);
|
|
327
357
|
httpError.status = response.status;
|
|
328
358
|
httpError.statusText = response.statusText;
|
|
329
|
-
httpError.method =
|
|
359
|
+
httpError.method = method;
|
|
330
360
|
httpError.endpoint = endpoint;
|
|
331
361
|
httpError.body = errorBody;
|
|
362
|
+
httpError.message = errorBody?.error || errorBody?.message || 'API Error';
|
|
332
363
|
|
|
364
|
+
// Debug logging for successful HTTP requests
|
|
365
|
+
if (this.debugMode) {
|
|
366
|
+
console.log(`API :: ERROR :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response?.status} :: ${responseRequestId}`, httpError);
|
|
367
|
+
}
|
|
368
|
+
|
|
333
369
|
throw httpError;
|
|
334
370
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
371
|
+
|
|
372
|
+
let responseBody;
|
|
373
|
+
if (response?.body) {
|
|
374
|
+
responseBody = response.body;
|
|
375
|
+
} else if (response?.headers?.['content-type']) {
|
|
376
|
+
const contentType = response.headers['content-type'];
|
|
377
|
+
try {
|
|
378
|
+
if (transport === 'https') {
|
|
379
|
+
if (contentType.includes('application/json')) {
|
|
380
|
+
responseBody = await response.json();
|
|
381
|
+
} else if (contentType.includes('text/')) {
|
|
382
|
+
responseBody = await response.text();
|
|
383
|
+
} else {
|
|
384
|
+
responseBody = await response.arrayBuffer();
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
if (contentType.includes('application/json')) {
|
|
388
|
+
responseBody = this._getJsonSafely(response.body, response.body);
|
|
389
|
+
} else if (contentType.includes('text/')) {
|
|
390
|
+
responseBody = response?.body || '';
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (!responseBody) {
|
|
394
|
+
responseBody = {};
|
|
395
|
+
}
|
|
396
|
+
} catch (parseError) {
|
|
397
|
+
responseBody = {};
|
|
398
|
+
}
|
|
344
399
|
} else {
|
|
345
|
-
|
|
346
|
-
bodyResponse = await response.arrayBuffer();
|
|
400
|
+
responseBody = {};
|
|
347
401
|
}
|
|
402
|
+
|
|
348
403
|
|
|
349
|
-
const responseHeaders = response.headers;
|
|
350
|
-
const responseRequestId =
|
|
351
|
-
responseHeaders?.get?.('x-request-id') ||
|
|
352
|
-
responseHeaders?.['x-request-id'];
|
|
353
404
|
|
|
354
|
-
if (!response.ok) {
|
|
355
|
-
// Debug logging for HTTP errors
|
|
356
|
-
if (this.debugMode) {
|
|
357
|
-
console.log(`API :: https :: ${method.toUpperCase()} :: ${endpoint} :: ${response?.status}`);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
throw {
|
|
361
|
-
name: `API :: Error :: https :: ${method} :: ${endpoint} :: ${responseRequestId} :: ${response?.status} :: ${response?.statusText}`,
|
|
362
|
-
message: bodyResponse?.message || `API Error occured.`,
|
|
363
|
-
method,
|
|
364
|
-
endpoint,
|
|
365
|
-
status: response?.status,
|
|
366
|
-
statusText: response?.statusText,
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
405
|
|
|
370
406
|
// Debug logging for successful HTTP requests
|
|
371
407
|
if (this.debugMode) {
|
|
372
|
-
console.log(`API ::
|
|
408
|
+
console.log(`API :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response?.status} :: ${responseRequestId}`);
|
|
373
409
|
}
|
|
374
410
|
|
|
375
|
-
return
|
|
411
|
+
return responseBody;
|
|
376
412
|
}
|
|
377
413
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundcx/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|