@fjell/client-api 4.4.44 → 4.4.45
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/MIGRATION_v3.md +231 -0
- package/README.md +169 -0
- package/dist/AItemAPI.d.ts +2 -2
- package/dist/CItemAPI.d.ts +5 -12
- package/dist/ClientApi.d.ts +13 -14
- package/dist/Instance.d.ts +2 -1
- package/dist/PItemAPI.d.ts +1 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.js +164 -158
- package/dist/index.js.map +4 -4
- package/dist/ops/action.d.ts +2 -2
- package/dist/ops/all.d.ts +2 -2
- package/dist/ops/allAction.d.ts +2 -2
- package/dist/ops/allFacet.d.ts +2 -2
- package/dist/ops/create.d.ts +2 -2
- package/dist/ops/errorHandling.d.ts +1 -0
- package/dist/ops/facet.d.ts +2 -2
- package/dist/ops/find.d.ts +2 -2
- package/dist/ops/findOne.d.ts +2 -2
- package/dist/ops/get.d.ts +2 -2
- package/dist/ops/one.d.ts +2 -2
- package/dist/ops/remove.d.ts +2 -2
- package/dist/ops/update.d.ts +2 -2
- package/dist/ops/upsert.d.ts +5 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -17,12 +17,12 @@ var getAllOperation = (api, apiOptions, utilities) => {
|
|
|
17
17
|
const params = queryToParams(query);
|
|
18
18
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.allAuthenticated, params });
|
|
19
19
|
logger.default("all", { query, locations, requestOptions });
|
|
20
|
-
return
|
|
20
|
+
return await utilities.processArray(
|
|
21
21
|
api.httpGet(
|
|
22
22
|
utilities.getPath(loc),
|
|
23
23
|
requestOptions
|
|
24
24
|
)
|
|
25
|
-
)
|
|
25
|
+
);
|
|
26
26
|
};
|
|
27
27
|
return all;
|
|
28
28
|
};
|
|
@@ -30,17 +30,17 @@ var getAllOperation = (api, apiOptions, utilities) => {
|
|
|
30
30
|
// src/ops/action.ts
|
|
31
31
|
var logger2 = logger_default.get("client-api", "ops", "action");
|
|
32
32
|
var getActionOperation = (api, apiOptions, utilities) => {
|
|
33
|
-
const action = async (ik, action2,
|
|
33
|
+
const action = async (ik, action2, params) => {
|
|
34
34
|
const requestOptions = Object.assign({}, apiOptions.postOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
35
|
-
logger2.default("action", { ik, action: action2,
|
|
35
|
+
logger2.default("action", { ik, action: action2, params, requestOptions });
|
|
36
36
|
const response = await api.httpPost(
|
|
37
37
|
`${utilities.getPath(ik)}/${action2}`,
|
|
38
|
-
|
|
38
|
+
params || {},
|
|
39
39
|
requestOptions
|
|
40
40
|
);
|
|
41
41
|
const [item, affectedItems] = response;
|
|
42
42
|
return [
|
|
43
|
-
|
|
43
|
+
await utilities.processOne(Promise.resolve(item)),
|
|
44
44
|
affectedItems
|
|
45
45
|
];
|
|
46
46
|
};
|
|
@@ -50,24 +50,23 @@ var getActionOperation = (api, apiOptions, utilities) => {
|
|
|
50
50
|
// src/ops/allAction.ts
|
|
51
51
|
var logger3 = logger_default.get("client-api", "ops", "allAction");
|
|
52
52
|
var getAllActionOperation = (api, apiOptions, utilities) => {
|
|
53
|
-
const allAction = async (action,
|
|
53
|
+
const allAction = async (action, params, locations) => {
|
|
54
54
|
const requestOptions = Object.assign({}, apiOptions.postOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const loc = locations || [];
|
|
56
|
+
logger3.default("allAction", { action, params, locations: loc, requestOptions });
|
|
57
|
+
utilities.verifyLocations(loc);
|
|
58
58
|
const response = await api.httpPost(
|
|
59
59
|
`${utilities.getPath(loc)}/${action}`,
|
|
60
|
-
|
|
60
|
+
params || {},
|
|
61
61
|
requestOptions
|
|
62
62
|
);
|
|
63
63
|
let items = [];
|
|
64
64
|
let affectedItems = [];
|
|
65
65
|
if (Array.isArray(response)) {
|
|
66
|
-
if (response
|
|
66
|
+
if (response.length === 2 && Array.isArray(response[0])) {
|
|
67
67
|
[items, affectedItems] = response;
|
|
68
|
-
} else
|
|
69
|
-
|
|
70
|
-
affectedItems = [];
|
|
68
|
+
} else {
|
|
69
|
+
return response;
|
|
71
70
|
}
|
|
72
71
|
} else if (response && typeof response === "object" && Object.keys(response).length === 0) {
|
|
73
72
|
items = [];
|
|
@@ -76,10 +75,12 @@ var getAllActionOperation = (api, apiOptions, utilities) => {
|
|
|
76
75
|
items = [];
|
|
77
76
|
affectedItems = [];
|
|
78
77
|
}
|
|
78
|
+
const processedItems = await utilities.processArray(Promise.resolve(items));
|
|
79
|
+
if (Array.isArray(processedItems)) {
|
|
80
|
+
processedItems.forEach((item) => utilities.validatePK(item));
|
|
81
|
+
}
|
|
79
82
|
return [
|
|
80
|
-
|
|
81
|
-
await utilities.processArray(Promise.resolve(items))
|
|
82
|
-
),
|
|
83
|
+
processedItems,
|
|
83
84
|
affectedItems
|
|
84
85
|
];
|
|
85
86
|
};
|
|
@@ -99,12 +100,12 @@ var getOneOperation = (api, apiOptions, utilities) => {
|
|
|
99
100
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.readAuthenticated, params });
|
|
100
101
|
logger4.default("one", { query, locations, requestOptions });
|
|
101
102
|
let item = null;
|
|
102
|
-
const items =
|
|
103
|
+
const items = await utilities.processArray(
|
|
103
104
|
api.httpGet(
|
|
104
105
|
utilities.getPath(loc),
|
|
105
106
|
requestOptions
|
|
106
107
|
)
|
|
107
|
-
)
|
|
108
|
+
);
|
|
108
109
|
if (items.length > 0) {
|
|
109
110
|
item = items[0];
|
|
110
111
|
}
|
|
@@ -114,7 +115,11 @@ var getOneOperation = (api, apiOptions, utilities) => {
|
|
|
114
115
|
};
|
|
115
116
|
|
|
116
117
|
// src/ops/errorHandling.ts
|
|
118
|
+
import { isFjellHttpError } from "@fjell/http-api";
|
|
117
119
|
function shouldRetryError(error) {
|
|
120
|
+
if (isFjellHttpError(error)) {
|
|
121
|
+
return error.isRetryable();
|
|
122
|
+
}
|
|
118
123
|
if (error.code === "ECONNREFUSED" || error.code === "ENOTFOUND" || error.code === "ENETUNREACH" || error.message?.includes("timeout") || error.message?.includes("network")) {
|
|
119
124
|
return true;
|
|
120
125
|
}
|
|
@@ -134,6 +139,9 @@ function calculateRetryDelay(attempt, config) {
|
|
|
134
139
|
}
|
|
135
140
|
function enhanceError(error, context) {
|
|
136
141
|
if (!error) return new Error("Unknown error occurred");
|
|
142
|
+
if (isFjellHttpError(error)) {
|
|
143
|
+
return error;
|
|
144
|
+
}
|
|
137
145
|
if (error.context) return error;
|
|
138
146
|
const enhancedError = new Error(error.message || "HTTP operation failed");
|
|
139
147
|
Object.assign(enhancedError, {
|
|
@@ -153,27 +161,27 @@ function getRetryConfig(apiOptions) {
|
|
|
153
161
|
...apiOptions.retryConfig
|
|
154
162
|
};
|
|
155
163
|
}
|
|
156
|
-
function executeErrorHandler(errorHandler, error, context,
|
|
164
|
+
function executeErrorHandler(errorHandler, error, context, logger22) {
|
|
157
165
|
if (!errorHandler) return;
|
|
158
166
|
try {
|
|
159
167
|
errorHandler(error, context);
|
|
160
168
|
} catch (handlerError) {
|
|
161
|
-
|
|
169
|
+
logger22.error("Custom error handler failed", {
|
|
162
170
|
originalError: error.message,
|
|
163
171
|
handlerError: handlerError?.message || String(handlerError)
|
|
164
172
|
});
|
|
165
173
|
}
|
|
166
174
|
}
|
|
167
|
-
async function executeWithRetry(operation, operationName, operationContext, apiOptions,
|
|
175
|
+
async function executeWithRetry(operation, operationName, operationContext, apiOptions, logger22, specialErrorHandling) {
|
|
168
176
|
const retryConfig = getRetryConfig(apiOptions);
|
|
169
177
|
let lastError = null;
|
|
170
178
|
const startTime = Date.now();
|
|
171
179
|
for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
|
|
172
180
|
try {
|
|
173
|
-
|
|
181
|
+
logger22.debug(`Executing ${operationName} (attempt ${attempt + 1})`, operationContext);
|
|
174
182
|
const result = await operation();
|
|
175
183
|
if (attempt > 0) {
|
|
176
|
-
|
|
184
|
+
logger22.info(`${operationName} operation succeeded after ${attempt} retries`, {
|
|
177
185
|
...operationContext,
|
|
178
186
|
totalAttempts: attempt + 1,
|
|
179
187
|
duration: Date.now() - startTime
|
|
@@ -193,7 +201,7 @@ async function executeWithRetry(operation, operationName, operationContext, apiO
|
|
|
193
201
|
}
|
|
194
202
|
const isRetryable = shouldRetryError(error);
|
|
195
203
|
if (!isRetryable) {
|
|
196
|
-
|
|
204
|
+
logger22.debug(`Not retrying ${operationName} operation due to non-retryable error`, {
|
|
197
205
|
...operationContext,
|
|
198
206
|
errorMessage: error.message,
|
|
199
207
|
errorCode: error.code || error.status,
|
|
@@ -202,7 +210,7 @@ async function executeWithRetry(operation, operationName, operationContext, apiO
|
|
|
202
210
|
break;
|
|
203
211
|
}
|
|
204
212
|
const delay = calculateRetryDelay(attempt, retryConfig);
|
|
205
|
-
|
|
213
|
+
logger22.warning(`Retrying ${operationName} operation (attempt ${attempt + 2}) after ${delay}ms`, {
|
|
206
214
|
...operationContext,
|
|
207
215
|
errorMessage: error.message,
|
|
208
216
|
errorCode: error.code || error.status,
|
|
@@ -213,8 +221,8 @@ async function executeWithRetry(operation, operationName, operationContext, apiO
|
|
|
213
221
|
}
|
|
214
222
|
}
|
|
215
223
|
const finalError = enhanceError(lastError, operationContext);
|
|
216
|
-
executeErrorHandler(apiOptions.errorHandler, finalError, operationContext,
|
|
217
|
-
|
|
224
|
+
executeErrorHandler(apiOptions.errorHandler, finalError, operationContext, logger22);
|
|
225
|
+
logger22.error(`${operationName} operation failed after ${retryConfig.maxRetries + 1} attempts`, {
|
|
218
226
|
...operationContext,
|
|
219
227
|
errorMessage: finalError.message,
|
|
220
228
|
errorCode: finalError.code || finalError.status,
|
|
@@ -227,10 +235,15 @@ async function executeWithRetry(operation, operationName, operationContext, apiO
|
|
|
227
235
|
// src/ops/create.ts
|
|
228
236
|
var logger5 = logger_default.get("client-api", "ops", "create");
|
|
229
237
|
var getCreateOperation = (api, apiOptions, utilities) => {
|
|
230
|
-
const create = async (item,
|
|
238
|
+
const create = async (item, options) => {
|
|
239
|
+
const locations = options?.locations || [];
|
|
231
240
|
const requestOptions = Object.assign({}, apiOptions.postOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
232
|
-
logger5.default("create", { item, locations, requestOptions });
|
|
241
|
+
logger5.default("create", { item, options, locations, requestOptions });
|
|
233
242
|
utilities.verifyLocations(locations);
|
|
243
|
+
let itemToCreate = item;
|
|
244
|
+
if (options?.key) {
|
|
245
|
+
itemToCreate = { ...item, ...options.key };
|
|
246
|
+
}
|
|
234
247
|
const loc = locations;
|
|
235
248
|
const operationContext = {
|
|
236
249
|
operation: "create",
|
|
@@ -252,10 +265,10 @@ var getCreateOperation = (api, apiOptions, utilities) => {
|
|
|
252
265
|
logger5.debug(`Creating item (attempt ${attempt + 1})`, operationContext);
|
|
253
266
|
const result = await utilities.processOne(api.httpPost(
|
|
254
267
|
utilities.getPath(loc),
|
|
255
|
-
|
|
268
|
+
itemToCreate,
|
|
256
269
|
requestOptions
|
|
257
270
|
));
|
|
258
|
-
|
|
271
|
+
utilities.validatePK(result);
|
|
259
272
|
if (attempt > 0) {
|
|
260
273
|
logger5.info(`Create operation succeeded after ${attempt} retries`, {
|
|
261
274
|
...operationContext,
|
|
@@ -263,7 +276,7 @@ var getCreateOperation = (api, apiOptions, utilities) => {
|
|
|
263
276
|
duration: Date.now() - startTime
|
|
264
277
|
});
|
|
265
278
|
}
|
|
266
|
-
return
|
|
279
|
+
return result;
|
|
267
280
|
} catch (error) {
|
|
268
281
|
lastError = error;
|
|
269
282
|
if (attempt === retryConfig.maxRetries) {
|
|
@@ -319,23 +332,42 @@ var getUpdateOperation = (api, apiOptions, utilities) => {
|
|
|
319
332
|
const update = async (ik, item) => {
|
|
320
333
|
const requestOptions = Object.assign({}, apiOptions.putOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
321
334
|
logger6.default("update", { ik, item, requestOptions });
|
|
322
|
-
return
|
|
335
|
+
return await utilities.processOne(
|
|
323
336
|
api.httpPut(
|
|
324
337
|
utilities.getPath(ik),
|
|
325
338
|
item,
|
|
326
339
|
requestOptions
|
|
327
340
|
)
|
|
328
|
-
)
|
|
341
|
+
);
|
|
329
342
|
};
|
|
330
343
|
return update;
|
|
331
344
|
};
|
|
332
345
|
|
|
346
|
+
// src/ops/upsert.ts
|
|
347
|
+
var logger7 = logger_default.get("client-api", "ops", "upsert");
|
|
348
|
+
var getUpsertOperation = (api, apiOptions, utilities) => {
|
|
349
|
+
const upsert = async (key, item, locations) => {
|
|
350
|
+
const requestOptions = Object.assign({}, apiOptions.putOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
351
|
+
logger7.default("upsert", { key, item, locations, requestOptions });
|
|
352
|
+
const path = utilities.getPath(key);
|
|
353
|
+
const url = locations && locations.length > 0 ? `${path}?locations=${encodeURIComponent(JSON.stringify(locations))}` : path;
|
|
354
|
+
return await utilities.processOne(
|
|
355
|
+
api.httpPut(
|
|
356
|
+
url,
|
|
357
|
+
{ ...item, upsert: true },
|
|
358
|
+
requestOptions
|
|
359
|
+
)
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
return upsert;
|
|
363
|
+
};
|
|
364
|
+
|
|
333
365
|
// src/ops/get.ts
|
|
334
|
-
var
|
|
366
|
+
var logger8 = logger_default.get("client-api", "ops", "get");
|
|
335
367
|
var getGetOperation = (api, apiOptions, utilities) => {
|
|
336
368
|
const get = async (ik) => {
|
|
337
369
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.readAuthenticated });
|
|
338
|
-
|
|
370
|
+
logger8.default("get", { ik, requestOptions });
|
|
339
371
|
const operationContext = {
|
|
340
372
|
operation: "get",
|
|
341
373
|
path: utilities.getPath(ik),
|
|
@@ -352,26 +384,26 @@ var getGetOperation = (api, apiOptions, utilities) => {
|
|
|
352
384
|
const startTime = Date.now();
|
|
353
385
|
for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
|
|
354
386
|
try {
|
|
355
|
-
|
|
387
|
+
logger8.debug(`Getting item (attempt ${attempt + 1})`, operationContext);
|
|
356
388
|
const result = await utilities.processOne(
|
|
357
389
|
api.httpGet(
|
|
358
390
|
utilities.getPath(ik),
|
|
359
391
|
requestOptions
|
|
360
392
|
)
|
|
361
393
|
);
|
|
362
|
-
|
|
394
|
+
utilities.validatePK(result);
|
|
363
395
|
if (attempt > 0) {
|
|
364
|
-
|
|
396
|
+
logger8.info(`Get operation succeeded after ${attempt} retries`, {
|
|
365
397
|
...operationContext,
|
|
366
398
|
totalAttempts: attempt + 1,
|
|
367
399
|
duration: Date.now() - startTime
|
|
368
400
|
});
|
|
369
401
|
}
|
|
370
|
-
return
|
|
402
|
+
return result;
|
|
371
403
|
} catch (error) {
|
|
372
404
|
lastError = error;
|
|
373
405
|
if (error.status === 404) {
|
|
374
|
-
|
|
406
|
+
logger8.debug("Item not found (404)", operationContext);
|
|
375
407
|
return null;
|
|
376
408
|
}
|
|
377
409
|
if (attempt === retryConfig.maxRetries) {
|
|
@@ -379,7 +411,7 @@ var getGetOperation = (api, apiOptions, utilities) => {
|
|
|
379
411
|
}
|
|
380
412
|
const isRetryable = shouldRetryError(error);
|
|
381
413
|
if (!isRetryable) {
|
|
382
|
-
|
|
414
|
+
logger8.debug("Not retrying get operation due to non-retryable error", {
|
|
383
415
|
...operationContext,
|
|
384
416
|
errorMessage: error.message,
|
|
385
417
|
errorCode: error.code || error.status,
|
|
@@ -388,7 +420,7 @@ var getGetOperation = (api, apiOptions, utilities) => {
|
|
|
388
420
|
break;
|
|
389
421
|
}
|
|
390
422
|
const delay = calculateRetryDelay(attempt, retryConfig);
|
|
391
|
-
|
|
423
|
+
logger8.warning(`Retrying get operation (attempt ${attempt + 2}) after ${delay}ms`, {
|
|
392
424
|
...operationContext,
|
|
393
425
|
errorMessage: error.message,
|
|
394
426
|
errorCode: error.code || error.status,
|
|
@@ -403,13 +435,13 @@ var getGetOperation = (api, apiOptions, utilities) => {
|
|
|
403
435
|
try {
|
|
404
436
|
apiOptions.errorHandler(finalError, operationContext);
|
|
405
437
|
} catch (handlerError) {
|
|
406
|
-
|
|
438
|
+
logger8.error("Custom error handler failed", {
|
|
407
439
|
originalError: finalError.message,
|
|
408
440
|
handlerError: handlerError?.message || String(handlerError)
|
|
409
441
|
});
|
|
410
442
|
}
|
|
411
443
|
}
|
|
412
|
-
|
|
444
|
+
logger8.error(`Get operation failed after ${retryConfig.maxRetries + 1} attempts`, {
|
|
413
445
|
...operationContext,
|
|
414
446
|
errorMessage: finalError.message,
|
|
415
447
|
errorCode: finalError.code || finalError.status,
|
|
@@ -422,37 +454,41 @@ var getGetOperation = (api, apiOptions, utilities) => {
|
|
|
422
454
|
};
|
|
423
455
|
|
|
424
456
|
// src/ops/remove.ts
|
|
425
|
-
var
|
|
457
|
+
var logger9 = logger_default.get("client-api", "ops", "remove");
|
|
426
458
|
var getRemoveOperation = (api, apiOptions, utilities) => {
|
|
427
459
|
const remove = async (ik) => {
|
|
428
460
|
const requestOptions = Object.assign({}, apiOptions.deleteOptions, { isAuthenticated: apiOptions.writeAuthenticated });
|
|
429
|
-
|
|
430
|
-
|
|
461
|
+
logger9.default("remove", { ik, requestOptions });
|
|
462
|
+
const result = await api.httpDelete(utilities.getPath(ik), requestOptions);
|
|
463
|
+
if (typeof result === "boolean") {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
return result;
|
|
431
467
|
};
|
|
432
468
|
return remove;
|
|
433
469
|
};
|
|
434
470
|
|
|
435
471
|
// src/ops/find.ts
|
|
436
|
-
var
|
|
472
|
+
var logger10 = logger_default.get("client-api", "ops", "find");
|
|
437
473
|
var getFindOperation = (api, apiOptions, utilities) => {
|
|
438
474
|
const find = async (finder, finderParams = {}, locations = []) => {
|
|
439
475
|
utilities.verifyLocations(locations);
|
|
440
476
|
const loc = locations;
|
|
441
477
|
const mergedParams = finderToParams(finder, finderParams);
|
|
442
478
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.allAuthenticated, params: mergedParams });
|
|
443
|
-
|
|
444
|
-
return
|
|
479
|
+
logger10.default("find", { finder, finderParams, locations, requestOptions });
|
|
480
|
+
return await utilities.processArray(
|
|
445
481
|
api.httpGet(
|
|
446
482
|
utilities.getPath(loc),
|
|
447
483
|
requestOptions
|
|
448
484
|
)
|
|
449
|
-
)
|
|
485
|
+
);
|
|
450
486
|
};
|
|
451
487
|
return find;
|
|
452
488
|
};
|
|
453
489
|
|
|
454
490
|
// src/ops/findOne.ts
|
|
455
|
-
var
|
|
491
|
+
var logger11 = logger_default.get("client-api", "ops", "find");
|
|
456
492
|
var getFindOneOperation = (api, apiOptions, utilities) => {
|
|
457
493
|
const findOne = async (finder, finderParams = {}, locations = []) => {
|
|
458
494
|
utilities.verifyLocations(locations);
|
|
@@ -460,23 +496,28 @@ var getFindOneOperation = (api, apiOptions, utilities) => {
|
|
|
460
496
|
const params = finderToParams(finder, finderParams);
|
|
461
497
|
params.one = true;
|
|
462
498
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.allAuthenticated, params });
|
|
463
|
-
|
|
464
|
-
|
|
499
|
+
logger11.default("findOne", { finder, finderParams, locations, requestOptions });
|
|
500
|
+
const results = await utilities.processArray(
|
|
465
501
|
api.httpGet(
|
|
466
502
|
utilities.getPath(loc),
|
|
467
503
|
requestOptions
|
|
468
504
|
)
|
|
469
|
-
)
|
|
505
|
+
);
|
|
506
|
+
const result = results[0];
|
|
507
|
+
if (result) {
|
|
508
|
+
utilities.validatePK(result);
|
|
509
|
+
}
|
|
510
|
+
return result;
|
|
470
511
|
};
|
|
471
512
|
return findOne;
|
|
472
513
|
};
|
|
473
514
|
|
|
474
515
|
// src/ops/facet.ts
|
|
475
|
-
var
|
|
516
|
+
var logger12 = logger_default.get("client-api", "ops", "facet");
|
|
476
517
|
var getFacetOperation = (api, apiOptions, utilities) => {
|
|
477
518
|
const facet = async (ik, facet2, params = {}) => {
|
|
478
519
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.writeAuthenticated, params });
|
|
479
|
-
|
|
520
|
+
logger12.default("facet", { ik, facet: facet2, requestOptions });
|
|
480
521
|
return api.httpGet(
|
|
481
522
|
`${utilities.getPath(ik)}/${facet2}`,
|
|
482
523
|
requestOptions
|
|
@@ -486,11 +527,11 @@ var getFacetOperation = (api, apiOptions, utilities) => {
|
|
|
486
527
|
};
|
|
487
528
|
|
|
488
529
|
// src/ops/allFacet.ts
|
|
489
|
-
var
|
|
530
|
+
var logger13 = logger_default.get("client-api", "ops", "allFacet");
|
|
490
531
|
var getAllFacetOperation = (api, apiOptions, utilities) => {
|
|
491
532
|
const allFacet = async (facet, params = {}, locations = []) => {
|
|
492
533
|
const requestOptions = Object.assign({}, apiOptions.getOptions, { isAuthenticated: apiOptions.writeAuthenticated, params });
|
|
493
|
-
|
|
534
|
+
logger13.default("allFacet", { facet, locations, requestOptions });
|
|
494
535
|
utilities.verifyLocations(locations);
|
|
495
536
|
const loc = locations;
|
|
496
537
|
return api.httpGet(
|
|
@@ -563,6 +604,11 @@ var getOperations = (api, apiOptions, utilities) => {
|
|
|
563
604
|
api,
|
|
564
605
|
apiOptions,
|
|
565
606
|
utilities
|
|
607
|
+
),
|
|
608
|
+
upsert: getUpsertOperation(
|
|
609
|
+
api,
|
|
610
|
+
apiOptions,
|
|
611
|
+
utilities
|
|
566
612
|
)
|
|
567
613
|
};
|
|
568
614
|
};
|
|
@@ -574,9 +620,9 @@ import {
|
|
|
574
620
|
isPriKey
|
|
575
621
|
} from "@fjell/core";
|
|
576
622
|
import deepmerge from "deepmerge";
|
|
577
|
-
var
|
|
623
|
+
var logger14 = logger_default.get("client-api", "Utility");
|
|
578
624
|
var createUtilities = (pkType, pathNames) => {
|
|
579
|
-
|
|
625
|
+
logger14.default("createUtilities", { pkType, pathNames });
|
|
580
626
|
const verifyLocations = (locations) => {
|
|
581
627
|
if (locations && locations.length < pathNames.length - 1) {
|
|
582
628
|
throw new Error("Not enough locations for pathNames: locations:" + locations.length + " pathNames:" + pathNames.length);
|
|
@@ -584,18 +630,18 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
584
630
|
return true;
|
|
585
631
|
};
|
|
586
632
|
const processOne = async (apiCall) => {
|
|
587
|
-
|
|
633
|
+
logger14.default("processOne", { apiCall });
|
|
588
634
|
const response = await apiCall;
|
|
589
|
-
|
|
635
|
+
logger14.default("processOne response", {
|
|
590
636
|
responseType: typeof response,
|
|
591
637
|
hasData: !!response
|
|
592
638
|
});
|
|
593
639
|
return convertDoc(response);
|
|
594
640
|
};
|
|
595
641
|
const processArray = async (api) => {
|
|
596
|
-
|
|
642
|
+
logger14.default("processArray", { api });
|
|
597
643
|
const response = await api;
|
|
598
|
-
|
|
644
|
+
logger14.default("processArray response", {
|
|
599
645
|
responseType: typeof response,
|
|
600
646
|
isArray: Array.isArray(response),
|
|
601
647
|
length: Array.isArray(response) ? response.length : 0
|
|
@@ -605,12 +651,12 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
605
651
|
(subjectChat) => convertDoc(subjectChat)
|
|
606
652
|
);
|
|
607
653
|
} else {
|
|
608
|
-
|
|
654
|
+
logger14.error("Response was not an array", { response });
|
|
609
655
|
throw new Error("Response was not an array");
|
|
610
656
|
}
|
|
611
657
|
};
|
|
612
658
|
const convertDoc = (doc) => {
|
|
613
|
-
|
|
659
|
+
logger14.default("convertDoc", { doc });
|
|
614
660
|
if (doc && doc.events) {
|
|
615
661
|
const events = doc.events;
|
|
616
662
|
for (const key in events) {
|
|
@@ -621,65 +667,16 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
621
667
|
return doc;
|
|
622
668
|
}
|
|
623
669
|
};
|
|
624
|
-
const validateLocationKeyOrder = (keys) => {
|
|
625
|
-
const locKeys = keys.filter((k) => !isPriKey(k));
|
|
626
|
-
if (locKeys.length <= 1) {
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
const pathNameOrder = /* @__PURE__ */ new Map();
|
|
630
|
-
pathNames.forEach((pathName, index) => {
|
|
631
|
-
const pathParts = pathName.split("/");
|
|
632
|
-
const lastPart = pathParts[pathParts.length - 1];
|
|
633
|
-
pathNameOrder.set(pathName, index);
|
|
634
|
-
pathNameOrder.set(pathName.toLowerCase(), index);
|
|
635
|
-
pathNameOrder.set(lastPart, index);
|
|
636
|
-
pathNameOrder.set(lastPart.toLowerCase(), index);
|
|
637
|
-
const singular = lastPart.endsWith("s") ? lastPart.slice(0, -1) : lastPart;
|
|
638
|
-
const plural = lastPart + "s";
|
|
639
|
-
const pluralEs = lastPart + "es";
|
|
640
|
-
pathNameOrder.set(singular, index);
|
|
641
|
-
pathNameOrder.set(plural, index);
|
|
642
|
-
pathNameOrder.set(pluralEs, index);
|
|
643
|
-
pathNameOrder.set(singular.toLowerCase(), index);
|
|
644
|
-
pathNameOrder.set(plural.toLowerCase(), index);
|
|
645
|
-
});
|
|
646
|
-
let lastIndex = Infinity;
|
|
647
|
-
const keyDetails = [];
|
|
648
|
-
for (const locKey of locKeys) {
|
|
649
|
-
const keyType = locKey.kt;
|
|
650
|
-
const currentIndex = pathNameOrder.get(keyType);
|
|
651
|
-
keyDetails.push({ kt: keyType, pathNameIndex: currentIndex });
|
|
652
|
-
if (typeof currentIndex !== "undefined") {
|
|
653
|
-
if (currentIndex >= lastIndex) {
|
|
654
|
-
logger13.error("Location keys are not in the correct hierarchical order", {
|
|
655
|
-
keys: locKeys.map((k) => ({ kt: k.kt, lk: k.lk })),
|
|
656
|
-
pathNames,
|
|
657
|
-
keyDetails,
|
|
658
|
-
issue: `Key type "${keyType}" (index ${currentIndex}) should come after the previous key (index ${lastIndex})`
|
|
659
|
-
});
|
|
660
|
-
throw new Error(
|
|
661
|
-
`Location keys must be ordered from child to parent according to the entity hierarchy. Expected order based on pathNames: [${pathNames.join(", ")}]. Received key types in order: [${locKeys.map((k) => k.kt).join(", ")}]. Key "${keyType}" is out of order - it should appear later in the hierarchy.`
|
|
662
|
-
);
|
|
663
|
-
}
|
|
664
|
-
lastIndex = currentIndex;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
logger13.default("Location key order validation passed", {
|
|
668
|
-
locKeys: locKeys.map((k) => ({ kt: k.kt, lk: k.lk })),
|
|
669
|
-
keyDetails
|
|
670
|
-
});
|
|
671
|
-
};
|
|
672
670
|
const getPath = (key) => {
|
|
673
671
|
const localPathNames = [...pathNames];
|
|
674
|
-
|
|
672
|
+
logger14.default("getPath", { key, pathNames: localPathNames });
|
|
675
673
|
const keys = generateKeyArray(key);
|
|
676
|
-
validateLocationKeyOrder(keys);
|
|
677
674
|
if (keys.length > 1) {
|
|
678
675
|
const priKeys = keys.filter((k) => isPriKey(k));
|
|
679
676
|
const locKeys = keys.filter((k) => !isPriKey(k));
|
|
680
677
|
const reversedLocKeys = [...locKeys].reverse();
|
|
681
678
|
const reorderedKeys = [...reversedLocKeys, ...priKeys];
|
|
682
|
-
|
|
679
|
+
logger14.default("Reordered keys for contained item", {
|
|
683
680
|
original: keys,
|
|
684
681
|
locKeys,
|
|
685
682
|
reversedLocKeys,
|
|
@@ -690,7 +687,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
690
687
|
if (localPathNames.length === 1) {
|
|
691
688
|
path = `${path}/${localPathNames[0]}`;
|
|
692
689
|
}
|
|
693
|
-
|
|
690
|
+
logger14.default("getPath created", { key, path });
|
|
694
691
|
return path;
|
|
695
692
|
} else {
|
|
696
693
|
const priKeys = keys.filter((k) => isPriKey(k));
|
|
@@ -701,27 +698,27 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
701
698
|
if (localPathNames.length === 1) {
|
|
702
699
|
path = `${path}/${localPathNames[0]}`;
|
|
703
700
|
}
|
|
704
|
-
|
|
701
|
+
logger14.default("getPath created", { key, path });
|
|
705
702
|
return path;
|
|
706
703
|
}
|
|
707
704
|
};
|
|
708
705
|
const addPath = (base, keys, localPathNames) => {
|
|
709
|
-
|
|
706
|
+
logger14.default("addPath", { base, keys, pathNames: localPathNames });
|
|
710
707
|
if (keys.length < localPathNames.length - 1) {
|
|
711
|
-
|
|
708
|
+
logger14.error(
|
|
712
709
|
"addPath should never have keys with a length less than the length of pathNames - 1",
|
|
713
710
|
{ keys, localPathNames }
|
|
714
711
|
);
|
|
715
712
|
throw new Error("addPath should never have keys with a length less than the length of pathNames - 1: " + keys.length + " " + localPathNames.length + " " + JSON.stringify(keys, localPathNames));
|
|
716
713
|
} else if (keys.length > localPathNames.length) {
|
|
717
|
-
|
|
714
|
+
logger14.error(
|
|
718
715
|
"addPath should never have keys with a length greater than the length of pathNames",
|
|
719
716
|
{ keys, pathNames }
|
|
720
717
|
);
|
|
721
718
|
throw new Error("addPath should never have keys with a length greater than the length of pathNames: " + keys.length + " " + localPathNames.length + " " + JSON.stringify(keys, localPathNames));
|
|
722
719
|
}
|
|
723
720
|
if (keys.length === 0) {
|
|
724
|
-
|
|
721
|
+
logger14.default("addPath returning base", { base });
|
|
725
722
|
return base;
|
|
726
723
|
} else {
|
|
727
724
|
const currentKey = keys[0];
|
|
@@ -740,7 +737,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
740
737
|
const key = keys.shift();
|
|
741
738
|
const id = isPriKey(key) ? key.pk : key.lk;
|
|
742
739
|
const nextBase = `${base}/${pathName}/${id}`;
|
|
743
|
-
|
|
740
|
+
logger14.default("Adding Path (matched)", {
|
|
744
741
|
pathName,
|
|
745
742
|
keyType,
|
|
746
743
|
isPriKey: isPriKey(key),
|
|
@@ -753,7 +750,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
753
750
|
const key = keys.shift();
|
|
754
751
|
const id = isPriKey(key) ? key.pk : key.lk;
|
|
755
752
|
const nextBase = `${base}/${pathName}/${id}`;
|
|
756
|
-
|
|
753
|
+
logger14.default("Adding Path (no match, using first)", {
|
|
757
754
|
pathName,
|
|
758
755
|
keyType,
|
|
759
756
|
isPriKey: isPriKey(key),
|
|
@@ -778,7 +775,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
778
775
|
};
|
|
779
776
|
|
|
780
777
|
// src/AItemAPI.ts
|
|
781
|
-
var
|
|
778
|
+
var logger15 = logger_default.get("AItemAPI");
|
|
782
779
|
var finderToParams = (finder, finderParams) => {
|
|
783
780
|
return {
|
|
784
781
|
finder,
|
|
@@ -786,7 +783,7 @@ var finderToParams = (finder, finderParams) => {
|
|
|
786
783
|
};
|
|
787
784
|
};
|
|
788
785
|
var createAItemAPI = (api, pkType, pathNames, options) => {
|
|
789
|
-
|
|
786
|
+
logger15.default("createAItemAPI", { pkType, pathNames, options });
|
|
790
787
|
let mergedOptions;
|
|
791
788
|
const defaultOptions = {
|
|
792
789
|
readAuthenticated: true,
|
|
@@ -816,14 +813,15 @@ var createAItemAPI = (api, pkType, pathNames, options) => {
|
|
|
816
813
|
get: operations.get,
|
|
817
814
|
one: operations.one,
|
|
818
815
|
remove: operations.remove,
|
|
819
|
-
update: operations.update
|
|
816
|
+
update: operations.update,
|
|
817
|
+
upsert: operations.upsert
|
|
820
818
|
};
|
|
821
819
|
};
|
|
822
820
|
|
|
823
821
|
// src/CItemAPI.ts
|
|
824
|
-
var
|
|
822
|
+
var logger16 = logger_default.get("CItemAPI");
|
|
825
823
|
var createCItemApi = (api, type, pathNames, options) => {
|
|
826
|
-
|
|
824
|
+
logger16.default("createCItemApi", { api, type, pathNames, options });
|
|
827
825
|
const aItemAPI = createAItemAPI(api, type, pathNames, options);
|
|
828
826
|
return {
|
|
829
827
|
action: aItemAPI.action,
|
|
@@ -835,6 +833,7 @@ var createCItemApi = (api, type, pathNames, options) => {
|
|
|
835
833
|
create: aItemAPI.create,
|
|
836
834
|
remove: aItemAPI.remove,
|
|
837
835
|
update: aItemAPI.update,
|
|
836
|
+
upsert: aItemAPI.upsert,
|
|
838
837
|
facet: aItemAPI.facet,
|
|
839
838
|
find: aItemAPI.find,
|
|
840
839
|
findOne: aItemAPI.findOne
|
|
@@ -842,24 +841,24 @@ var createCItemApi = (api, type, pathNames, options) => {
|
|
|
842
841
|
};
|
|
843
842
|
|
|
844
843
|
// src/PItemAPI.ts
|
|
845
|
-
var
|
|
844
|
+
var logger17 = logger_default.get("PItemAPI");
|
|
846
845
|
var createPItemApi = (api, type, pathName, options) => {
|
|
847
|
-
|
|
846
|
+
logger17.default("createPItemApi", { type, pathName, options });
|
|
848
847
|
const aItemAPI = createAItemAPI(api, type, [pathName], options);
|
|
849
|
-
const action = async (ik, action2,
|
|
850
|
-
const all = async (query
|
|
851
|
-
const allAction = async (action2,
|
|
852
|
-
const allFacet = async (facet2, params
|
|
853
|
-
const one = async (query
|
|
848
|
+
const action = async (ik, action2, params) => await aItemAPI.action(ik, action2, params);
|
|
849
|
+
const all = async (query) => await aItemAPI.all(query || {}, []);
|
|
850
|
+
const allAction = async (action2, params) => await aItemAPI.allAction(action2, params, []);
|
|
851
|
+
const allFacet = async (facet2, params) => await aItemAPI.allFacet(facet2, params);
|
|
852
|
+
const one = async (query) => await aItemAPI.one(query || {}, []);
|
|
854
853
|
const get = async (ik) => await aItemAPI.get(ik);
|
|
855
|
-
const create = async (item) => await aItemAPI.create(item,
|
|
854
|
+
const create = async (item, options2) => await aItemAPI.create(item, options2);
|
|
856
855
|
const remove = async (ik) => await aItemAPI.remove(ik);
|
|
857
856
|
const update = async (ik, item) => await aItemAPI.update(ik, item);
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
const
|
|
857
|
+
const upsert = async (ik, item, locations) => await aItemAPI.upsert(ik, item, locations);
|
|
858
|
+
const facet = async (ik, facet2, params) => await aItemAPI.facet(ik, facet2, params);
|
|
859
|
+
const find = async (finder, finderParams) => await aItemAPI.find(finder, finderParams);
|
|
860
|
+
const findOne = async (finder, finderParams) => await aItemAPI.findOne(finder, finderParams);
|
|
861
861
|
return {
|
|
862
|
-
...aItemAPI,
|
|
863
862
|
action,
|
|
864
863
|
all,
|
|
865
864
|
allAction,
|
|
@@ -869,6 +868,7 @@ var createPItemApi = (api, type, pathName, options) => {
|
|
|
869
868
|
create,
|
|
870
869
|
remove,
|
|
871
870
|
update,
|
|
871
|
+
upsert,
|
|
872
872
|
facet,
|
|
873
873
|
find,
|
|
874
874
|
findOne
|
|
@@ -877,18 +877,18 @@ var createPItemApi = (api, type, pathName, options) => {
|
|
|
877
877
|
|
|
878
878
|
// src/Instance.ts
|
|
879
879
|
import { createInstance as createBaseInstance } from "@fjell/registry";
|
|
880
|
-
var
|
|
880
|
+
var logger18 = logger_default.get("Instance");
|
|
881
881
|
var createInstance = (registry, coordinate, clientApi) => {
|
|
882
|
-
|
|
882
|
+
logger18.debug("createInstance", { coordinate, clientApi, registry });
|
|
883
883
|
const baseInstance = createBaseInstance(registry, coordinate);
|
|
884
884
|
return { ...baseInstance, clientApi };
|
|
885
885
|
};
|
|
886
886
|
|
|
887
887
|
// src/InstanceFactory.ts
|
|
888
|
-
var
|
|
888
|
+
var logger19 = logger_default.get("InstanceFactory");
|
|
889
889
|
var createInstanceFactory = (clientApi) => {
|
|
890
890
|
return (coordinate, context) => {
|
|
891
|
-
|
|
891
|
+
logger19.debug("Creating client-api instance", { coordinate, registry: context.registry, clientApi });
|
|
892
892
|
return createInstance(context.registry, coordinate, clientApi);
|
|
893
893
|
};
|
|
894
894
|
};
|
|
@@ -897,13 +897,13 @@ var createInstanceFactory = (clientApi) => {
|
|
|
897
897
|
import {
|
|
898
898
|
createRegistry as createBaseRegistry
|
|
899
899
|
} from "@fjell/registry";
|
|
900
|
-
var
|
|
900
|
+
var logger20 = logger_default.get("Registry");
|
|
901
901
|
var createRegistryFactory = () => {
|
|
902
902
|
return (type, registryHub) => {
|
|
903
903
|
if (type !== "client-api") {
|
|
904
904
|
throw new Error(`Client API registry factory can only create 'client-api' type registries, got: ${type}`);
|
|
905
905
|
}
|
|
906
|
-
|
|
906
|
+
logger20.debug("Creating client-api registry", { type, registryHub });
|
|
907
907
|
const baseRegistry = createBaseRegistry(type, registryHub);
|
|
908
908
|
return baseRegistry;
|
|
909
909
|
};
|
|
@@ -1102,8 +1102,11 @@ function isClientApiError(error) {
|
|
|
1102
1102
|
return error instanceof ClientApiError;
|
|
1103
1103
|
}
|
|
1104
1104
|
|
|
1105
|
+
// src/index.ts
|
|
1106
|
+
import { FjellHttpError, isFjellHttpError as isFjellHttpError2, extractErrorInfo } from "@fjell/http-api";
|
|
1107
|
+
|
|
1105
1108
|
// src/http/HttpWrapper.ts
|
|
1106
|
-
var
|
|
1109
|
+
var logger21 = {
|
|
1107
1110
|
debug: (message, context) => console.debug(message, context),
|
|
1108
1111
|
info: (message, context) => console.info(message, context),
|
|
1109
1112
|
warning: (message, context) => console.warn(message, context),
|
|
@@ -1121,7 +1124,7 @@ var DEFAULT_RETRY_CONFIG = {
|
|
|
1121
1124
|
return false;
|
|
1122
1125
|
},
|
|
1123
1126
|
onRetry: (error, attemptNumber, delay) => {
|
|
1124
|
-
|
|
1127
|
+
logger21.warning(`Retrying HTTP request (attempt ${attemptNumber + 1}) after ${delay}ms`, {
|
|
1125
1128
|
errorCode: error.code,
|
|
1126
1129
|
errorMessage: error.message,
|
|
1127
1130
|
delay,
|
|
@@ -1154,14 +1157,14 @@ var HttpWrapper = class {
|
|
|
1154
1157
|
const startTime = Date.now();
|
|
1155
1158
|
for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
|
|
1156
1159
|
try {
|
|
1157
|
-
|
|
1160
|
+
logger21.debug(`Executing ${operationName}`, {
|
|
1158
1161
|
attempt: attempt + 1,
|
|
1159
1162
|
maxRetries: this.retryConfig.maxRetries + 1,
|
|
1160
1163
|
...context
|
|
1161
1164
|
});
|
|
1162
1165
|
const result = await operation();
|
|
1163
1166
|
if (attempt > 0) {
|
|
1164
|
-
|
|
1167
|
+
logger21.info(`${operationName} succeeded after ${attempt} retries`, {
|
|
1165
1168
|
totalAttempts: attempt + 1,
|
|
1166
1169
|
duration: Date.now() - startTime,
|
|
1167
1170
|
...context
|
|
@@ -1174,7 +1177,7 @@ var HttpWrapper = class {
|
|
|
1174
1177
|
break;
|
|
1175
1178
|
}
|
|
1176
1179
|
if (!this.retryConfig.shouldRetry(lastError, attempt)) {
|
|
1177
|
-
|
|
1180
|
+
logger21.debug(`Not retrying ${operationName} due to non-retryable error`, {
|
|
1178
1181
|
errorCode: lastError.code,
|
|
1179
1182
|
errorMessage: lastError.message,
|
|
1180
1183
|
attempt: attempt + 1,
|
|
@@ -1190,7 +1193,7 @@ var HttpWrapper = class {
|
|
|
1190
1193
|
await sleep(delay);
|
|
1191
1194
|
}
|
|
1192
1195
|
}
|
|
1193
|
-
|
|
1196
|
+
logger21.error(`${operationName} failed after ${this.retryConfig.maxRetries + 1} attempts`, {
|
|
1194
1197
|
errorCode: lastError?.code,
|
|
1195
1198
|
errorMessage: lastError?.message,
|
|
1196
1199
|
duration: Date.now() - startTime,
|
|
@@ -1282,6 +1285,7 @@ export {
|
|
|
1282
1285
|
ClientApiError,
|
|
1283
1286
|
ConfigurationError,
|
|
1284
1287
|
ConflictError,
|
|
1288
|
+
FjellHttpError,
|
|
1285
1289
|
HttpError,
|
|
1286
1290
|
HttpWrapper,
|
|
1287
1291
|
NetworkError,
|
|
@@ -1304,8 +1308,10 @@ export {
|
|
|
1304
1308
|
enhanceError,
|
|
1305
1309
|
executeErrorHandler,
|
|
1306
1310
|
executeWithRetry,
|
|
1311
|
+
extractErrorInfo,
|
|
1307
1312
|
getRetryConfig,
|
|
1308
1313
|
isClientApiError,
|
|
1314
|
+
isFjellHttpError2 as isFjellHttpError,
|
|
1309
1315
|
isRetryableError,
|
|
1310
1316
|
shouldRetryError
|
|
1311
1317
|
};
|