@unboundcx/sdk 2.6.16 → 2.7.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/base.js +87 -54
- 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,102 @@ 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
|
|
311
319
|
if (!response.ok) {
|
|
312
320
|
let errorBody;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
321
|
+
if (response?.body) {
|
|
322
|
+
errorBody = response.body;
|
|
323
|
+
} else if (response?.headers?.['content-type']) {
|
|
324
|
+
const contentType = response.headers['content-type'];
|
|
325
|
+
try {
|
|
326
|
+
if (typeof response?.json === 'function' || typeof response?.text === 'function') {
|
|
327
|
+
if (contentType.includes('application/json')) {
|
|
328
|
+
errorBody = await response.json();
|
|
329
|
+
} else if (contentType.includes('text/')) {
|
|
330
|
+
errorBody = await response.text();
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
if (contentType.includes('application/json')) {
|
|
334
|
+
errorBody = this._getJsonSafely(response?.body, response?.body || {});
|
|
335
|
+
} else if (contentType.includes('text/')) {
|
|
336
|
+
errorBody = response?.body || '';
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (!errorBody) {
|
|
340
|
+
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
341
|
+
}
|
|
342
|
+
} catch (parseError) {
|
|
343
|
+
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
320
344
|
}
|
|
321
|
-
}
|
|
345
|
+
} else {
|
|
322
346
|
errorBody = `HTTP ${response.status} ${response.statusText}`;
|
|
323
347
|
}
|
|
324
348
|
|
|
325
349
|
// Create a structured error for API/HTTP failures
|
|
326
|
-
const httpError = new Error(`API :: Error ::
|
|
350
|
+
const httpError = new Error(`API :: Error :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response.status} :: ${response.statusText}`);
|
|
327
351
|
httpError.status = response.status;
|
|
328
352
|
httpError.statusText = response.statusText;
|
|
329
|
-
httpError.method =
|
|
353
|
+
httpError.method = method;
|
|
330
354
|
httpError.endpoint = endpoint;
|
|
331
355
|
httpError.body = errorBody;
|
|
356
|
+
httpError.message = errorBody?.error || errorBody?.message || 'API Error';
|
|
332
357
|
|
|
358
|
+
// Debug logging for successful HTTP requests
|
|
359
|
+
if (this.debugMode) {
|
|
360
|
+
console.log(`API :: ERROR :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response?.status} :: ${responseRequestId}`, httpError);
|
|
361
|
+
}
|
|
362
|
+
|
|
333
363
|
throw httpError;
|
|
334
364
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
365
|
+
|
|
366
|
+
let responseBody;
|
|
367
|
+
if (response?.body) {
|
|
368
|
+
responseBody = response.body;
|
|
369
|
+
} else if (response?.headers?.['content-type']) {
|
|
370
|
+
const contentType = response.headers['content-type'];
|
|
371
|
+
try {
|
|
372
|
+
if (transport === 'https') {
|
|
373
|
+
if (contentType.includes('application/json')) {
|
|
374
|
+
responseBody = await response.json();
|
|
375
|
+
} else if (contentType.includes('text/')) {
|
|
376
|
+
responseBody = await response.text();
|
|
377
|
+
} else {
|
|
378
|
+
responseBody = await response.arrayBuffer();
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
if (contentType.includes('application/json')) {
|
|
382
|
+
responseBody = this._getJsonSafely(response.body, response.body);
|
|
383
|
+
} else if (contentType.includes('text/')) {
|
|
384
|
+
responseBody = response?.body || '';
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (!responseBody) {
|
|
388
|
+
responseBody = {};
|
|
389
|
+
}
|
|
390
|
+
} catch (parseError) {
|
|
391
|
+
responseBody = {};
|
|
392
|
+
}
|
|
344
393
|
} else {
|
|
345
|
-
|
|
346
|
-
bodyResponse = await response.arrayBuffer();
|
|
394
|
+
responseBody = {};
|
|
347
395
|
}
|
|
348
|
-
|
|
396
|
+
|
|
349
397
|
const responseHeaders = response.headers;
|
|
350
398
|
const responseRequestId =
|
|
351
399
|
responseHeaders?.get?.('x-request-id') ||
|
|
352
400
|
responseHeaders?.['x-request-id'];
|
|
353
401
|
|
|
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
402
|
|
|
370
403
|
// Debug logging for successful HTTP requests
|
|
371
404
|
if (this.debugMode) {
|
|
372
|
-
console.log(`API ::
|
|
405
|
+
console.log(`API :: ${transport} :: ${method.toUpperCase()} :: ${endpoint} :: ${response?.status} :: ${responseRequestId}`);
|
|
373
406
|
}
|
|
374
407
|
|
|
375
|
-
return
|
|
408
|
+
return responseBody;
|
|
376
409
|
}
|
|
377
410
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundcx/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
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",
|