@fjell/client-api 4.4.43 → 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 +174 -162
- 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,101 +667,58 @@ 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 = -1;
|
|
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 before the previous key (index ${lastIndex})`
|
|
659
|
-
});
|
|
660
|
-
throw new Error(
|
|
661
|
-
`Location keys must be ordered from parent to child 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 earlier 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
|
-
const
|
|
681
|
-
|
|
677
|
+
const reversedLocKeys = [...locKeys].reverse();
|
|
678
|
+
const reorderedKeys = [...reversedLocKeys, ...priKeys];
|
|
679
|
+
logger14.default("Reordered keys for contained item", {
|
|
682
680
|
original: keys,
|
|
681
|
+
locKeys,
|
|
682
|
+
reversedLocKeys,
|
|
683
683
|
reordered: reorderedKeys,
|
|
684
|
-
priKeys
|
|
685
|
-
locKeys
|
|
684
|
+
priKeys
|
|
686
685
|
});
|
|
687
686
|
let path = addPath("", reorderedKeys, localPathNames);
|
|
688
687
|
if (localPathNames.length === 1) {
|
|
689
688
|
path = `${path}/${localPathNames[0]}`;
|
|
690
689
|
}
|
|
691
|
-
|
|
690
|
+
logger14.default("getPath created", { key, path });
|
|
692
691
|
return path;
|
|
693
692
|
} else {
|
|
694
|
-
|
|
693
|
+
const priKeys = keys.filter((k) => isPriKey(k));
|
|
694
|
+
const locKeys = keys.filter((k) => !isPriKey(k));
|
|
695
|
+
const reversedLocKeys = locKeys.length > 0 ? [...locKeys].reverse() : [];
|
|
696
|
+
const orderedKeys = [...reversedLocKeys, ...priKeys];
|
|
697
|
+
let path = addPath("", orderedKeys, localPathNames);
|
|
695
698
|
if (localPathNames.length === 1) {
|
|
696
699
|
path = `${path}/${localPathNames[0]}`;
|
|
697
700
|
}
|
|
698
|
-
|
|
701
|
+
logger14.default("getPath created", { key, path });
|
|
699
702
|
return path;
|
|
700
703
|
}
|
|
701
704
|
};
|
|
702
705
|
const addPath = (base, keys, localPathNames) => {
|
|
703
|
-
|
|
706
|
+
logger14.default("addPath", { base, keys, pathNames: localPathNames });
|
|
704
707
|
if (keys.length < localPathNames.length - 1) {
|
|
705
|
-
|
|
708
|
+
logger14.error(
|
|
706
709
|
"addPath should never have keys with a length less than the length of pathNames - 1",
|
|
707
710
|
{ keys, localPathNames }
|
|
708
711
|
);
|
|
709
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));
|
|
710
713
|
} else if (keys.length > localPathNames.length) {
|
|
711
|
-
|
|
714
|
+
logger14.error(
|
|
712
715
|
"addPath should never have keys with a length greater than the length of pathNames",
|
|
713
716
|
{ keys, pathNames }
|
|
714
717
|
);
|
|
715
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));
|
|
716
719
|
}
|
|
717
720
|
if (keys.length === 0) {
|
|
718
|
-
|
|
721
|
+
logger14.default("addPath returning base", { base });
|
|
719
722
|
return base;
|
|
720
723
|
} else {
|
|
721
724
|
const currentKey = keys[0];
|
|
@@ -734,7 +737,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
734
737
|
const key = keys.shift();
|
|
735
738
|
const id = isPriKey(key) ? key.pk : key.lk;
|
|
736
739
|
const nextBase = `${base}/${pathName}/${id}`;
|
|
737
|
-
|
|
740
|
+
logger14.default("Adding Path (matched)", {
|
|
738
741
|
pathName,
|
|
739
742
|
keyType,
|
|
740
743
|
isPriKey: isPriKey(key),
|
|
@@ -747,7 +750,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
747
750
|
const key = keys.shift();
|
|
748
751
|
const id = isPriKey(key) ? key.pk : key.lk;
|
|
749
752
|
const nextBase = `${base}/${pathName}/${id}`;
|
|
750
|
-
|
|
753
|
+
logger14.default("Adding Path (no match, using first)", {
|
|
751
754
|
pathName,
|
|
752
755
|
keyType,
|
|
753
756
|
isPriKey: isPriKey(key),
|
|
@@ -772,7 +775,7 @@ var createUtilities = (pkType, pathNames) => {
|
|
|
772
775
|
};
|
|
773
776
|
|
|
774
777
|
// src/AItemAPI.ts
|
|
775
|
-
var
|
|
778
|
+
var logger15 = logger_default.get("AItemAPI");
|
|
776
779
|
var finderToParams = (finder, finderParams) => {
|
|
777
780
|
return {
|
|
778
781
|
finder,
|
|
@@ -780,7 +783,7 @@ var finderToParams = (finder, finderParams) => {
|
|
|
780
783
|
};
|
|
781
784
|
};
|
|
782
785
|
var createAItemAPI = (api, pkType, pathNames, options) => {
|
|
783
|
-
|
|
786
|
+
logger15.default("createAItemAPI", { pkType, pathNames, options });
|
|
784
787
|
let mergedOptions;
|
|
785
788
|
const defaultOptions = {
|
|
786
789
|
readAuthenticated: true,
|
|
@@ -810,14 +813,15 @@ var createAItemAPI = (api, pkType, pathNames, options) => {
|
|
|
810
813
|
get: operations.get,
|
|
811
814
|
one: operations.one,
|
|
812
815
|
remove: operations.remove,
|
|
813
|
-
update: operations.update
|
|
816
|
+
update: operations.update,
|
|
817
|
+
upsert: operations.upsert
|
|
814
818
|
};
|
|
815
819
|
};
|
|
816
820
|
|
|
817
821
|
// src/CItemAPI.ts
|
|
818
|
-
var
|
|
822
|
+
var logger16 = logger_default.get("CItemAPI");
|
|
819
823
|
var createCItemApi = (api, type, pathNames, options) => {
|
|
820
|
-
|
|
824
|
+
logger16.default("createCItemApi", { api, type, pathNames, options });
|
|
821
825
|
const aItemAPI = createAItemAPI(api, type, pathNames, options);
|
|
822
826
|
return {
|
|
823
827
|
action: aItemAPI.action,
|
|
@@ -829,6 +833,7 @@ var createCItemApi = (api, type, pathNames, options) => {
|
|
|
829
833
|
create: aItemAPI.create,
|
|
830
834
|
remove: aItemAPI.remove,
|
|
831
835
|
update: aItemAPI.update,
|
|
836
|
+
upsert: aItemAPI.upsert,
|
|
832
837
|
facet: aItemAPI.facet,
|
|
833
838
|
find: aItemAPI.find,
|
|
834
839
|
findOne: aItemAPI.findOne
|
|
@@ -836,24 +841,24 @@ var createCItemApi = (api, type, pathNames, options) => {
|
|
|
836
841
|
};
|
|
837
842
|
|
|
838
843
|
// src/PItemAPI.ts
|
|
839
|
-
var
|
|
844
|
+
var logger17 = logger_default.get("PItemAPI");
|
|
840
845
|
var createPItemApi = (api, type, pathName, options) => {
|
|
841
|
-
|
|
846
|
+
logger17.default("createPItemApi", { type, pathName, options });
|
|
842
847
|
const aItemAPI = createAItemAPI(api, type, [pathName], options);
|
|
843
|
-
const action = async (ik, action2,
|
|
844
|
-
const all = async (query
|
|
845
|
-
const allAction = async (action2,
|
|
846
|
-
const allFacet = async (facet2, params
|
|
847
|
-
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 || {}, []);
|
|
848
853
|
const get = async (ik) => await aItemAPI.get(ik);
|
|
849
|
-
const create = async (item) => await aItemAPI.create(item,
|
|
854
|
+
const create = async (item, options2) => await aItemAPI.create(item, options2);
|
|
850
855
|
const remove = async (ik) => await aItemAPI.remove(ik);
|
|
851
856
|
const update = async (ik, item) => await aItemAPI.update(ik, item);
|
|
852
|
-
const
|
|
853
|
-
const
|
|
854
|
-
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);
|
|
855
861
|
return {
|
|
856
|
-
...aItemAPI,
|
|
857
862
|
action,
|
|
858
863
|
all,
|
|
859
864
|
allAction,
|
|
@@ -863,6 +868,7 @@ var createPItemApi = (api, type, pathName, options) => {
|
|
|
863
868
|
create,
|
|
864
869
|
remove,
|
|
865
870
|
update,
|
|
871
|
+
upsert,
|
|
866
872
|
facet,
|
|
867
873
|
find,
|
|
868
874
|
findOne
|
|
@@ -871,18 +877,18 @@ var createPItemApi = (api, type, pathName, options) => {
|
|
|
871
877
|
|
|
872
878
|
// src/Instance.ts
|
|
873
879
|
import { createInstance as createBaseInstance } from "@fjell/registry";
|
|
874
|
-
var
|
|
880
|
+
var logger18 = logger_default.get("Instance");
|
|
875
881
|
var createInstance = (registry, coordinate, clientApi) => {
|
|
876
|
-
|
|
882
|
+
logger18.debug("createInstance", { coordinate, clientApi, registry });
|
|
877
883
|
const baseInstance = createBaseInstance(registry, coordinate);
|
|
878
884
|
return { ...baseInstance, clientApi };
|
|
879
885
|
};
|
|
880
886
|
|
|
881
887
|
// src/InstanceFactory.ts
|
|
882
|
-
var
|
|
888
|
+
var logger19 = logger_default.get("InstanceFactory");
|
|
883
889
|
var createInstanceFactory = (clientApi) => {
|
|
884
890
|
return (coordinate, context) => {
|
|
885
|
-
|
|
891
|
+
logger19.debug("Creating client-api instance", { coordinate, registry: context.registry, clientApi });
|
|
886
892
|
return createInstance(context.registry, coordinate, clientApi);
|
|
887
893
|
};
|
|
888
894
|
};
|
|
@@ -891,13 +897,13 @@ var createInstanceFactory = (clientApi) => {
|
|
|
891
897
|
import {
|
|
892
898
|
createRegistry as createBaseRegistry
|
|
893
899
|
} from "@fjell/registry";
|
|
894
|
-
var
|
|
900
|
+
var logger20 = logger_default.get("Registry");
|
|
895
901
|
var createRegistryFactory = () => {
|
|
896
902
|
return (type, registryHub) => {
|
|
897
903
|
if (type !== "client-api") {
|
|
898
904
|
throw new Error(`Client API registry factory can only create 'client-api' type registries, got: ${type}`);
|
|
899
905
|
}
|
|
900
|
-
|
|
906
|
+
logger20.debug("Creating client-api registry", { type, registryHub });
|
|
901
907
|
const baseRegistry = createBaseRegistry(type, registryHub);
|
|
902
908
|
return baseRegistry;
|
|
903
909
|
};
|
|
@@ -1096,8 +1102,11 @@ function isClientApiError(error) {
|
|
|
1096
1102
|
return error instanceof ClientApiError;
|
|
1097
1103
|
}
|
|
1098
1104
|
|
|
1105
|
+
// src/index.ts
|
|
1106
|
+
import { FjellHttpError, isFjellHttpError as isFjellHttpError2, extractErrorInfo } from "@fjell/http-api";
|
|
1107
|
+
|
|
1099
1108
|
// src/http/HttpWrapper.ts
|
|
1100
|
-
var
|
|
1109
|
+
var logger21 = {
|
|
1101
1110
|
debug: (message, context) => console.debug(message, context),
|
|
1102
1111
|
info: (message, context) => console.info(message, context),
|
|
1103
1112
|
warning: (message, context) => console.warn(message, context),
|
|
@@ -1115,7 +1124,7 @@ var DEFAULT_RETRY_CONFIG = {
|
|
|
1115
1124
|
return false;
|
|
1116
1125
|
},
|
|
1117
1126
|
onRetry: (error, attemptNumber, delay) => {
|
|
1118
|
-
|
|
1127
|
+
logger21.warning(`Retrying HTTP request (attempt ${attemptNumber + 1}) after ${delay}ms`, {
|
|
1119
1128
|
errorCode: error.code,
|
|
1120
1129
|
errorMessage: error.message,
|
|
1121
1130
|
delay,
|
|
@@ -1148,14 +1157,14 @@ var HttpWrapper = class {
|
|
|
1148
1157
|
const startTime = Date.now();
|
|
1149
1158
|
for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
|
|
1150
1159
|
try {
|
|
1151
|
-
|
|
1160
|
+
logger21.debug(`Executing ${operationName}`, {
|
|
1152
1161
|
attempt: attempt + 1,
|
|
1153
1162
|
maxRetries: this.retryConfig.maxRetries + 1,
|
|
1154
1163
|
...context
|
|
1155
1164
|
});
|
|
1156
1165
|
const result = await operation();
|
|
1157
1166
|
if (attempt > 0) {
|
|
1158
|
-
|
|
1167
|
+
logger21.info(`${operationName} succeeded after ${attempt} retries`, {
|
|
1159
1168
|
totalAttempts: attempt + 1,
|
|
1160
1169
|
duration: Date.now() - startTime,
|
|
1161
1170
|
...context
|
|
@@ -1168,7 +1177,7 @@ var HttpWrapper = class {
|
|
|
1168
1177
|
break;
|
|
1169
1178
|
}
|
|
1170
1179
|
if (!this.retryConfig.shouldRetry(lastError, attempt)) {
|
|
1171
|
-
|
|
1180
|
+
logger21.debug(`Not retrying ${operationName} due to non-retryable error`, {
|
|
1172
1181
|
errorCode: lastError.code,
|
|
1173
1182
|
errorMessage: lastError.message,
|
|
1174
1183
|
attempt: attempt + 1,
|
|
@@ -1184,7 +1193,7 @@ var HttpWrapper = class {
|
|
|
1184
1193
|
await sleep(delay);
|
|
1185
1194
|
}
|
|
1186
1195
|
}
|
|
1187
|
-
|
|
1196
|
+
logger21.error(`${operationName} failed after ${this.retryConfig.maxRetries + 1} attempts`, {
|
|
1188
1197
|
errorCode: lastError?.code,
|
|
1189
1198
|
errorMessage: lastError?.message,
|
|
1190
1199
|
duration: Date.now() - startTime,
|
|
@@ -1276,6 +1285,7 @@ export {
|
|
|
1276
1285
|
ClientApiError,
|
|
1277
1286
|
ConfigurationError,
|
|
1278
1287
|
ConflictError,
|
|
1288
|
+
FjellHttpError,
|
|
1279
1289
|
HttpError,
|
|
1280
1290
|
HttpWrapper,
|
|
1281
1291
|
NetworkError,
|
|
@@ -1298,8 +1308,10 @@ export {
|
|
|
1298
1308
|
enhanceError,
|
|
1299
1309
|
executeErrorHandler,
|
|
1300
1310
|
executeWithRetry,
|
|
1311
|
+
extractErrorInfo,
|
|
1301
1312
|
getRetryConfig,
|
|
1302
1313
|
isClientApiError,
|
|
1314
|
+
isFjellHttpError2 as isFjellHttpError,
|
|
1303
1315
|
isRetryableError,
|
|
1304
1316
|
shouldRetryError
|
|
1305
1317
|
};
|