@iblai/data-layer 1.4.4 → 1.5.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/dist/index.esm.js +89 -45
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +89 -45
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/features/utils.d.ts +22 -7
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -39164,44 +39164,71 @@ const getHeaders = async (service) => {
|
|
|
39164
39164
|
}
|
|
39165
39165
|
return token ? { Authorization: `${prefix} ${token}` } : undefined;
|
|
39166
39166
|
};
|
|
39167
|
+
/** Status codes that should not be retried for queryFn endpoints. */
|
|
39168
|
+
const QUERYFN_NON_RETRYABLE_STATUSES = [401, 403];
|
|
39169
|
+
/** Default max retries for queryFn endpoints. */
|
|
39170
|
+
const QUERYFN_MAX_RETRIES = 3;
|
|
39171
|
+
/** Base delay in ms for exponential backoff. */
|
|
39172
|
+
const QUERYFN_BASE_DELAY_MS = 1000;
|
|
39167
39173
|
/**
|
|
39168
39174
|
* Build a generic RTK Query endpoint from a service function.
|
|
39175
|
+
* Includes built-in retry with exponential backoff (since RTK Query
|
|
39176
|
+
* skips baseQuery retry for queryFn endpoints).
|
|
39169
39177
|
*/
|
|
39170
|
-
const buildEndpointFromService = (service, serviceFn) => {
|
|
39178
|
+
const buildEndpointFromService = (service, serviceFn, options) => {
|
|
39179
|
+
var _a;
|
|
39180
|
+
const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
|
|
39171
39181
|
return {
|
|
39172
39182
|
async queryFn(args) {
|
|
39173
|
-
|
|
39174
|
-
|
|
39175
|
-
|
|
39176
|
-
|
|
39177
|
-
|
|
39178
|
-
|
|
39179
|
-
|
|
39180
|
-
|
|
39181
|
-
}
|
|
39182
|
-
catch (err) {
|
|
39183
|
-
console.error('[data-layer] API error:', JSON.stringify(err, Object.getOwnPropertyNames(err)));
|
|
39184
|
-
if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
|
|
39185
|
-
Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({ ...((err === null || err === void 0 ? void 0 : err.data) || {}) });
|
|
39183
|
+
let lastError;
|
|
39184
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
39185
|
+
try {
|
|
39186
|
+
OpenAPI.BASE = getServiceUrl(service);
|
|
39187
|
+
OpenAPI.HEADERS = await getHeaders(service);
|
|
39188
|
+
OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
|
|
39189
|
+
const data = await serviceFn(args);
|
|
39190
|
+
return { data };
|
|
39186
39191
|
}
|
|
39187
|
-
|
|
39188
|
-
|
|
39189
|
-
|
|
39190
|
-
|
|
39191
|
-
|
|
39192
|
-
|
|
39192
|
+
catch (err) {
|
|
39193
|
+
lastError = err;
|
|
39194
|
+
const status = err === null || err === void 0 ? void 0 : err.status;
|
|
39195
|
+
// Don't retry auth errors
|
|
39196
|
+
if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
|
|
39197
|
+
break;
|
|
39198
|
+
}
|
|
39199
|
+
// If we have retries left, wait with exponential backoff
|
|
39200
|
+
if (attempt < maxRetries) {
|
|
39201
|
+
const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
39202
|
+
console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
|
|
39203
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
39204
|
+
continue;
|
|
39205
|
+
}
|
|
39206
|
+
}
|
|
39207
|
+
}
|
|
39208
|
+
// All retries exhausted or non-retryable error
|
|
39209
|
+
console.error('[data-layer] API error:', `service=${service}, fn=${serviceFn.name || 'anonymous'}`, JSON.stringify(lastError, Object.getOwnPropertyNames(lastError)));
|
|
39210
|
+
if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
|
|
39211
|
+
Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
|
|
39212
|
+
...((lastError === null || lastError === void 0 ? void 0 : lastError.data) || {}),
|
|
39213
|
+
});
|
|
39193
39214
|
}
|
|
39215
|
+
return {
|
|
39216
|
+
error: {
|
|
39217
|
+
status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
|
|
39218
|
+
data: (lastError === null || lastError === void 0 ? void 0 : lastError.body) || (lastError === null || lastError === void 0 ? void 0 : lastError.data) || (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'Unknown error',
|
|
39219
|
+
},
|
|
39220
|
+
};
|
|
39194
39221
|
},
|
|
39195
39222
|
};
|
|
39196
39223
|
};
|
|
39197
39224
|
/**
|
|
39198
39225
|
* Shortcut for building an endpoint using the DM service.
|
|
39199
39226
|
*/
|
|
39200
|
-
const buildEndpointFromDmService = (serviceFn) => buildEndpointFromService(SERVICES.DM, serviceFn);
|
|
39227
|
+
const buildEndpointFromDmService = (serviceFn, options) => buildEndpointFromService(SERVICES.DM, serviceFn);
|
|
39201
39228
|
/**
|
|
39202
39229
|
* Shortcut for building an endpoint using the AXD service.
|
|
39203
39230
|
*/
|
|
39204
|
-
const buildEndpointFromAxdService = (serviceFn) => buildEndpointFromService(SERVICES.AXD, serviceFn);
|
|
39231
|
+
const buildEndpointFromAxdService = (serviceFn, options) => buildEndpointFromService(SERVICES.AXD, serviceFn);
|
|
39205
39232
|
const isErrorObject = (data) => {
|
|
39206
39233
|
return (typeof data === 'object' &&
|
|
39207
39234
|
data !== null &&
|
|
@@ -39333,40 +39360,57 @@ const iblFetchBaseQuery = async (args, api, extraOptions) => {
|
|
|
39333
39360
|
}
|
|
39334
39361
|
};
|
|
39335
39362
|
/**
|
|
39336
|
-
* Build a generic RTK Query endpoint from a service function.
|
|
39363
|
+
* Build a generic RTK Query endpoint from a service function (legacy variant).
|
|
39364
|
+
* Includes built-in retry with exponential backoff.
|
|
39337
39365
|
*/
|
|
39338
|
-
const buildEndpointFromServiceLegacy = (service, serviceFn) => {
|
|
39366
|
+
const buildEndpointFromServiceLegacy = (service, serviceFn, options) => {
|
|
39367
|
+
var _a;
|
|
39368
|
+
const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
|
|
39339
39369
|
return {
|
|
39340
39370
|
async queryFn(args) {
|
|
39341
|
-
|
|
39342
|
-
|
|
39343
|
-
|
|
39344
|
-
|
|
39345
|
-
|
|
39346
|
-
|
|
39347
|
-
|
|
39348
|
-
|
|
39349
|
-
|
|
39350
|
-
|
|
39351
|
-
|
|
39352
|
-
|
|
39353
|
-
|
|
39354
|
-
|
|
39371
|
+
let lastError;
|
|
39372
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
39373
|
+
try {
|
|
39374
|
+
OpenAPI.BASE = getServiceUrl(service);
|
|
39375
|
+
OpenAPI.HEADERS = await getHeaders(service);
|
|
39376
|
+
OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
|
|
39377
|
+
const data = await serviceFn(...args);
|
|
39378
|
+
return { data };
|
|
39379
|
+
}
|
|
39380
|
+
catch (err) {
|
|
39381
|
+
lastError = err;
|
|
39382
|
+
const status = err === null || err === void 0 ? void 0 : err.status;
|
|
39383
|
+
if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
|
|
39384
|
+
break;
|
|
39385
|
+
}
|
|
39386
|
+
if (attempt < maxRetries) {
|
|
39387
|
+
const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
39388
|
+
console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
|
|
39389
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
39390
|
+
continue;
|
|
39391
|
+
}
|
|
39355
39392
|
}
|
|
39356
|
-
return {
|
|
39357
|
-
error: {
|
|
39358
|
-
status: (err === null || err === void 0 ? void 0 : err.status) || 500,
|
|
39359
|
-
data: (err === null || err === void 0 ? void 0 : err.body) || (err === null || err === void 0 ? void 0 : err.message) || 'Unknown error',
|
|
39360
|
-
},
|
|
39361
|
-
};
|
|
39362
39393
|
}
|
|
39394
|
+
if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
|
|
39395
|
+
Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
|
|
39396
|
+
status: lastError === null || lastError === void 0 ? void 0 : lastError.status,
|
|
39397
|
+
body: lastError === null || lastError === void 0 ? void 0 : lastError.body,
|
|
39398
|
+
message: lastError === null || lastError === void 0 ? void 0 : lastError.message,
|
|
39399
|
+
});
|
|
39400
|
+
}
|
|
39401
|
+
return {
|
|
39402
|
+
error: {
|
|
39403
|
+
status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
|
|
39404
|
+
data: (lastError === null || lastError === void 0 ? void 0 : lastError.body) || (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'Unknown error',
|
|
39405
|
+
},
|
|
39406
|
+
};
|
|
39363
39407
|
},
|
|
39364
39408
|
};
|
|
39365
39409
|
};
|
|
39366
39410
|
/**
|
|
39367
39411
|
* Shortcut for building an endpoint using the DM service.
|
|
39368
39412
|
*/
|
|
39369
|
-
const buildEndpointFromDmServiceLegacy = (serviceFn) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
|
|
39413
|
+
const buildEndpointFromDmServiceLegacy = (serviceFn, options) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
|
|
39370
39414
|
|
|
39371
39415
|
const apiKeysApiSlice = createApi({
|
|
39372
39416
|
reducerPath: 'apiKeysApiSlice',
|