@web-ts-toolkit/access-router-client 0.32.0 → 0.34.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/README.md +258 -14
- package/index.d.mts +453 -85
- package/index.d.ts +453 -85
- package/index.js +1133 -368
- package/index.mjs +1133 -368
- package/llms.txt +39 -5
- package/package.json +11 -4
package/index.mjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
// src/adapter.ts
|
|
2
|
-
import
|
|
3
|
-
import { castArray, isEmpty } from "@web-ts-toolkit/utils";
|
|
2
|
+
import axios2, { mergeConfig as mergeConfig5 } from "axios";
|
|
4
3
|
|
|
5
4
|
// src/services/model-service.ts
|
|
6
5
|
import { mergeConfig as mergeConfig3 } from "axios";
|
|
7
|
-
import { set as set3 } from "@web-ts-toolkit/utils";
|
|
8
6
|
|
|
9
7
|
// src/model.ts
|
|
10
8
|
import {
|
|
@@ -12,42 +10,162 @@ import {
|
|
|
12
10
|
cloneDeep,
|
|
13
11
|
get as getValue,
|
|
14
12
|
hasOwn,
|
|
13
|
+
isEqual,
|
|
15
14
|
omit,
|
|
16
15
|
pick,
|
|
17
16
|
set as setValue
|
|
18
17
|
} from "@web-ts-toolkit/utils";
|
|
18
|
+
var MissingPersistenceIdentityError = class extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "MissingPersistenceIdentityError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
19
24
|
var Model = class _Model {
|
|
20
|
-
constructor(data, adapter) {
|
|
25
|
+
constructor(data, adapter, persistenceId, fromExisting) {
|
|
21
26
|
this.modifiedPaths = /* @__PURE__ */ new Set();
|
|
27
|
+
this._persistenceId = persistenceId;
|
|
28
|
+
this._fromExisting = fromExisting ?? false;
|
|
22
29
|
this._snapshot = cloneDeep(data);
|
|
23
30
|
this.defineHiddenDataProp(cloneDeep(data));
|
|
24
31
|
this.defineHiddenAdapterProp(adapter);
|
|
25
32
|
this.definePublicDataProps();
|
|
26
33
|
this.initializeDirtyState();
|
|
27
34
|
}
|
|
28
|
-
static create(data, adapter) {
|
|
29
|
-
return new _Model(data, adapter);
|
|
30
|
-
}
|
|
35
|
+
static create(data, adapter, persistenceId, fromExisting) {
|
|
36
|
+
return new _Model(data, adapter, persistenceId, fromExisting);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Persists the currently dirty paths to the server, then merges the
|
|
40
|
+
* server's response back into local state.
|
|
41
|
+
*
|
|
42
|
+
* Concurrency contract:
|
|
43
|
+
*
|
|
44
|
+
* 1. Submitted paths and their values are snapshotted before the request
|
|
45
|
+
* starts, so an in-flight response cannot wipe edits that were made
|
|
46
|
+
* while the request was pending.
|
|
47
|
+
* 2. On success, a submitted path is cleared from `modifiedPaths` only if
|
|
48
|
+
* its current local value still equals the submitted value — i.e. the
|
|
49
|
+
* user has not concurrently re-edited it to a different value.
|
|
50
|
+
* 3. Server-returned values overwrite local values for paths the user did
|
|
51
|
+
* NOT concurrently re-modify during the in-flight save; for paths the
|
|
52
|
+
* user did concurrently re-modify, the local value is preserved and
|
|
53
|
+
* the dirty flag is retained so the concurrent edit is resubmitted on
|
|
54
|
+
* the next `save()`. (Deterministic conflict rule: the newer local
|
|
55
|
+
* edit wins for the same path; the server value becomes its reset
|
|
56
|
+
* baseline without replacing the newer local value.)
|
|
57
|
+
* 4. On failure, no dirty state is cleared and no local value is
|
|
58
|
+
* overwritten; the caller can retry `save()` with the same set.
|
|
59
|
+
* 5. The return value echoes `{ ...result, data }` where `data` is a
|
|
60
|
+
* refreshed `Model` snapshot of the post-save local state (or `null`
|
|
61
|
+
* on failure), matching `ModelResponse<T, TData>`.
|
|
62
|
+
*
|
|
63
|
+
* Persistence identity (ARC-21): create-vs-update is resolved from a
|
|
64
|
+
* captured persistence identity rather than from the projected `_data`
|
|
65
|
+
* payload alone, so a read that strips `_id` (e.g. `select: { name: 1,
|
|
66
|
+
* _id: 0 }`) cannot turn a subsequent `save()` into a silent create of
|
|
67
|
+
* a duplicate. When `_data._id` is present it takes precedence so callers
|
|
68
|
+
* can still deliberately aim `_id` at a bogus id to observe a failing
|
|
69
|
+
* save. When neither `_data._id` nor a captured persistence identity is
|
|
70
|
+
* available (e.g. `readAdvancedFilter` with an `_id`-excluding
|
|
71
|
+
* projection), `save()` throws `MissingPersistenceIdentityError` instead
|
|
72
|
+
* of POSTing a new document.
|
|
73
|
+
*/
|
|
31
74
|
async save(reqConfig) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
75
|
+
const submittedPaths = new Set(this.modifiedPaths);
|
|
76
|
+
const submittedValues = {};
|
|
77
|
+
for (const path of submittedPaths) {
|
|
78
|
+
submittedValues[path] = cloneDeep(getValue(this._data, path));
|
|
79
|
+
}
|
|
80
|
+
const submittedData = this.prepareData();
|
|
81
|
+
const persistenceId = this._data._id ?? this._persistenceId;
|
|
82
|
+
if (persistenceId == null && this._fromExisting) {
|
|
83
|
+
throw new MissingPersistenceIdentityError(
|
|
84
|
+
"Model.save() cannot determine create-vs-update without a persistence identity. A read of an existing document produced a Model whose projection strips `_id` and no identity was captured at read time. Use `read(id)` / `readAdvanced(id, ...)` (which capture the identifier as a persistence identity), or include `_id` in the projection."
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
const isCreate = persistenceId == null;
|
|
88
|
+
const result = isCreate ? await this._service.create(submittedData, null, reqConfig) : await this._service.update(String(persistenceId), submittedData, { returningAll: false }, reqConfig);
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
return { ...result, data: null };
|
|
91
|
+
}
|
|
92
|
+
const isConcurrentEdit = (path) => {
|
|
93
|
+
if (!submittedPaths.has(path)) {
|
|
94
|
+
return this.modifiedPaths.has(path);
|
|
95
|
+
}
|
|
96
|
+
const current = getValue(this._data, path);
|
|
97
|
+
const submitted = submittedValues[path];
|
|
98
|
+
return !isEqual(current, submitted);
|
|
99
|
+
};
|
|
100
|
+
const serverData = result.raw ?? {};
|
|
101
|
+
for (const key of Object.keys(serverData)) {
|
|
102
|
+
const normKey = this.normalizePath(key);
|
|
103
|
+
if (normKey === "_id") continue;
|
|
104
|
+
if (isConcurrentEdit(normKey)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const serverValue = serverData[key];
|
|
108
|
+
const before = getValue(this._data, normKey);
|
|
109
|
+
if (!isEqual(before, serverValue)) {
|
|
110
|
+
this._data[normKey] = serverValue;
|
|
111
|
+
}
|
|
112
|
+
this.modifiedPaths.delete(normKey);
|
|
113
|
+
}
|
|
114
|
+
for (const path of submittedPaths) {
|
|
115
|
+
if (!isConcurrentEdit(path)) {
|
|
116
|
+
this.modifiedPaths.delete(path);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (isCreate && serverData._id != null) {
|
|
120
|
+
this._data._id = String(serverData._id);
|
|
121
|
+
this.modifiedPaths.delete("_id");
|
|
37
122
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.
|
|
41
|
-
this.modifiedPaths.clear();
|
|
123
|
+
const latestId = this._data._id ?? (serverData._id != null ? String(serverData._id) : void 0);
|
|
124
|
+
if (latestId != null) {
|
|
125
|
+
this._persistenceId = latestId;
|
|
42
126
|
}
|
|
127
|
+
const nextSnapshot = Array.isArray(this._snapshot) ? [] : {};
|
|
128
|
+
const dataRecord = this._data;
|
|
129
|
+
for (const key of Object.keys(dataRecord)) {
|
|
130
|
+
const normKey = this.normalizePath(key);
|
|
131
|
+
if (this.modifiedPaths.has(normKey)) {
|
|
132
|
+
if (submittedPaths.has(normKey)) {
|
|
133
|
+
nextSnapshot[key] = cloneDeep(hasOwn(serverData, key) ? serverData[key] : submittedValues[normKey]);
|
|
134
|
+
} else {
|
|
135
|
+
nextSnapshot[key] = cloneDeep(this._snapshot[key]);
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
nextSnapshot[key] = cloneDeep(dataRecord[key]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
this._snapshot = nextSnapshot;
|
|
142
|
+
this.definePublicDataProps();
|
|
43
143
|
return {
|
|
44
144
|
...result,
|
|
45
|
-
|
|
145
|
+
// The post-save snapshot is always an existing document, so propagate
|
|
146
|
+
// `_fromExisting=true` plus the refreshed persistence identity so the
|
|
147
|
+
// returned wrapper cannot later silently create a duplicate. (If the
|
|
148
|
+
// caller intends a fresh draft, they construct `new Model({...}, s)`
|
|
149
|
+
// directly — `${_fromExisting}` defaults to `false` there.)
|
|
150
|
+
data: _Model.create(this._data, this._service, this._persistenceId, true)
|
|
46
151
|
};
|
|
47
152
|
}
|
|
48
153
|
isDirty(path) {
|
|
49
154
|
return path ? this.modifiedPaths.has(this.normalizePath(String(path))) : this.modifiedPaths.size > 0;
|
|
50
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Marks a path dirty and skips snapshot reconciliation. This is the
|
|
158
|
+
* explicit "include this path on the next save()" escape hatch: even when
|
|
159
|
+
* the effective value still equals the snapshot, the path stays dirty so
|
|
160
|
+
* callers can force a field to be re-sent to the server (e.g., to retrigger
|
|
161
|
+
* server-side defaults or to re-submit a value that another client may
|
|
162
|
+
* have reverted).
|
|
163
|
+
*
|
|
164
|
+
* For implicit writes that reconcile against the snapshot automatically
|
|
165
|
+
* (reverting a field to its baseline clears the dirty flag), use `set()`,
|
|
166
|
+
* `assign(...)`, or direct property assignment — those entry points all
|
|
167
|
+
* run `reconcilePath` after the write.
|
|
168
|
+
*/
|
|
51
169
|
markModified(path) {
|
|
52
170
|
this.trackModified(String(path));
|
|
53
171
|
return this;
|
|
@@ -63,6 +181,7 @@ var Model = class _Model {
|
|
|
63
181
|
setValue(this._data, path, value);
|
|
64
182
|
this.trackModified(path);
|
|
65
183
|
this.definePublicDataProps();
|
|
184
|
+
this.reconcilePath(this.normalizePath(path));
|
|
66
185
|
return this;
|
|
67
186
|
}
|
|
68
187
|
assign(partial) {
|
|
@@ -75,6 +194,9 @@ var Model = class _Model {
|
|
|
75
194
|
}
|
|
76
195
|
}
|
|
77
196
|
this.definePublicDataProps();
|
|
197
|
+
for (let x = 0; x < keys.length; x++) {
|
|
198
|
+
this.reconcilePath(this.normalizePath(String(keys[x])));
|
|
199
|
+
}
|
|
78
200
|
return this;
|
|
79
201
|
}
|
|
80
202
|
reset() {
|
|
@@ -88,10 +210,6 @@ var Model = class _Model {
|
|
|
88
210
|
toJSON() {
|
|
89
211
|
return this.toObject();
|
|
90
212
|
}
|
|
91
|
-
updateModel(data) {
|
|
92
|
-
assignObject(this._data, data);
|
|
93
|
-
this.definePublicDataProps();
|
|
94
|
-
}
|
|
95
213
|
replaceData(data) {
|
|
96
214
|
const nextData = cloneDeep(data);
|
|
97
215
|
const currentKeys = Object.keys(this._data);
|
|
@@ -105,7 +223,7 @@ var Model = class _Model {
|
|
|
105
223
|
this.definePublicDataProps();
|
|
106
224
|
}
|
|
107
225
|
initializeDirtyState() {
|
|
108
|
-
if (this._data._id) {
|
|
226
|
+
if (this._fromExisting || this._data._id) {
|
|
109
227
|
return;
|
|
110
228
|
}
|
|
111
229
|
const keys = Object.keys(this._data);
|
|
@@ -129,6 +247,7 @@ var Model = class _Model {
|
|
|
129
247
|
}
|
|
130
248
|
this.trackModified(keystr);
|
|
131
249
|
target[key] = value;
|
|
250
|
+
this.reconcilePath(this.normalizePath(keystr));
|
|
132
251
|
return true;
|
|
133
252
|
}
|
|
134
253
|
}),
|
|
@@ -164,24 +283,42 @@ var Model = class _Model {
|
|
|
164
283
|
normalizePath(path) {
|
|
165
284
|
return path.split(".")[0];
|
|
166
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Removes `path` from the dirty set when its current top-level value deeply
|
|
288
|
+
* equals the snapshot baseline. Used uniformly by `set()`, `assign()`,
|
|
289
|
+
* public property setters (via the proxy), and `markModified()` so all
|
|
290
|
+
* entry points share the same tracking rule.
|
|
291
|
+
*
|
|
292
|
+
* Note: `_id` is intentionally never reconciled away here — it is excluded
|
|
293
|
+
* from `initializeDirtyState` and managed explicitly during `save()`
|
|
294
|
+
* reconciliation.
|
|
295
|
+
*/
|
|
296
|
+
reconcilePath(path) {
|
|
297
|
+
if (path === "_id") return;
|
|
298
|
+
if (!this.modifiedPaths.has(path)) return;
|
|
299
|
+
const current = this._data[path];
|
|
300
|
+
const base = this._snapshot[path];
|
|
301
|
+
if (isEqual(current, base)) {
|
|
302
|
+
this.modifiedPaths.delete(path);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
167
305
|
};
|
|
168
306
|
|
|
169
307
|
// src/services/service.ts
|
|
170
|
-
import { AxiosHeaders } from "axios";
|
|
308
|
+
import { AxiosHeaders as AxiosHeaders2 } from "axios";
|
|
171
309
|
|
|
172
310
|
// src/constants.ts
|
|
173
311
|
var CACHE_HEADER = "x-axios-cache";
|
|
174
312
|
|
|
175
313
|
// src/services/wrap.ts
|
|
176
|
-
import { mergeConfig } from "axios";
|
|
177
|
-
import { set } from "@web-ts-toolkit/utils";
|
|
314
|
+
import { AxiosHeaders, mergeConfig } from "axios";
|
|
178
315
|
|
|
179
316
|
// src/helpers.ts
|
|
180
317
|
import { isPlainObject, mapValues } from "@web-ts-toolkit/utils";
|
|
181
318
|
function replaceSubQuery(filter) {
|
|
182
319
|
if (!isPlainObject(filter)) return filter;
|
|
183
320
|
const ret = mapValues(filter, (val) => {
|
|
184
|
-
if (val && val.__op && val.__query) {
|
|
321
|
+
if (isPlainObject(val) && "__op" in val && val.__op && "__query" in val && val.__query) {
|
|
185
322
|
return {
|
|
186
323
|
$$sq: val.__query
|
|
187
324
|
};
|
|
@@ -196,16 +333,20 @@ function replaceSubQuery(filter) {
|
|
|
196
333
|
});
|
|
197
334
|
return ret;
|
|
198
335
|
}
|
|
336
|
+
function encodePathSegment(value) {
|
|
337
|
+
if (value === void 0 || value === null) return "";
|
|
338
|
+
return encodeURIComponent(String(value));
|
|
339
|
+
}
|
|
199
340
|
function template(templateString, data) {
|
|
200
341
|
return templateString.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
201
|
-
return data[key] !== void 0 ? data[key] : match;
|
|
342
|
+
return data[key] !== void 0 ? encodePathSegment(data[key]) : match;
|
|
202
343
|
});
|
|
203
344
|
}
|
|
204
345
|
function getWrapContext(url, options, config) {
|
|
205
346
|
const { queryParams, pathParams } = options ?? {};
|
|
206
347
|
const finalUrl = pathParams ? template(url, pathParams) : url;
|
|
207
|
-
|
|
208
|
-
return { finalUrl, finalConfig
|
|
348
|
+
const finalConfig = queryParams && config ? { ...config, params: queryParams } : queryParams && !config ? { params: queryParams } : config;
|
|
349
|
+
return { finalUrl, finalConfig };
|
|
209
350
|
}
|
|
210
351
|
|
|
211
352
|
// src/services/wrap.ts
|
|
@@ -215,10 +356,12 @@ function resolveUrl(basePath, url) {
|
|
|
215
356
|
return basePath ? `${removeTrailingSlash(basePath)}/${removeLeadingSlash(url)}` : url;
|
|
216
357
|
}
|
|
217
358
|
function prepareConfig(defaultConfig, cacheValue, requestConfig) {
|
|
218
|
-
|
|
219
|
-
|
|
359
|
+
const headerClone = new AxiosHeaders(defaultConfig.headers);
|
|
360
|
+
headerClone.set(CACHE_HEADER, cacheValue);
|
|
361
|
+
const defaulted = { ...defaultConfig, headers: headerClone };
|
|
362
|
+
return mergeConfig(defaulted, requestConfig);
|
|
220
363
|
}
|
|
221
|
-
function createWrapHelper(
|
|
364
|
+
function createWrapHelper(axios3, basePath) {
|
|
222
365
|
return {
|
|
223
366
|
wrapGet: (url, defaultConfig = {}) => {
|
|
224
367
|
const _url = resolveUrl(basePath, url);
|
|
@@ -228,7 +371,7 @@ function createWrapHelper(axios2, basePath) {
|
|
|
228
371
|
options,
|
|
229
372
|
prepareConfig(defaultConfig, "true", requestConfig)
|
|
230
373
|
);
|
|
231
|
-
return
|
|
374
|
+
return axios3.get(finalUrl, finalConfig);
|
|
232
375
|
};
|
|
233
376
|
},
|
|
234
377
|
wrapPost: (url, defaultConfig = {}) => {
|
|
@@ -239,7 +382,7 @@ function createWrapHelper(axios2, basePath) {
|
|
|
239
382
|
options,
|
|
240
383
|
prepareConfig(defaultConfig, "false", requestConfig)
|
|
241
384
|
);
|
|
242
|
-
return
|
|
385
|
+
return axios3.post(finalUrl, data, finalConfig);
|
|
243
386
|
};
|
|
244
387
|
},
|
|
245
388
|
wrapPut: (url, defaultConfig = {}) => {
|
|
@@ -250,7 +393,7 @@ function createWrapHelper(axios2, basePath) {
|
|
|
250
393
|
options,
|
|
251
394
|
prepareConfig(defaultConfig, "false", requestConfig)
|
|
252
395
|
);
|
|
253
|
-
return
|
|
396
|
+
return axios3.put(finalUrl, data, finalConfig);
|
|
254
397
|
};
|
|
255
398
|
},
|
|
256
399
|
wrapPatch: (url, defaultConfig = {}) => {
|
|
@@ -261,7 +404,7 @@ function createWrapHelper(axios2, basePath) {
|
|
|
261
404
|
options,
|
|
262
405
|
prepareConfig(defaultConfig, "false", requestConfig)
|
|
263
406
|
);
|
|
264
|
-
return
|
|
407
|
+
return axios3.patch(finalUrl, data, finalConfig);
|
|
265
408
|
};
|
|
266
409
|
},
|
|
267
410
|
wrapDelete: (url, defaultConfig = {}) => {
|
|
@@ -272,7 +415,7 @@ function createWrapHelper(axios2, basePath) {
|
|
|
272
415
|
options,
|
|
273
416
|
prepareConfig(defaultConfig, "false", requestConfig)
|
|
274
417
|
);
|
|
275
|
-
return
|
|
418
|
+
return axios3.delete(finalUrl, finalConfig);
|
|
276
419
|
};
|
|
277
420
|
}
|
|
278
421
|
};
|
|
@@ -322,38 +465,77 @@ var stringifyErrorPayload = (value) => {
|
|
|
322
465
|
return String(value);
|
|
323
466
|
}
|
|
324
467
|
};
|
|
468
|
+
function finalizeOperationResult({
|
|
469
|
+
success,
|
|
470
|
+
raw,
|
|
471
|
+
status,
|
|
472
|
+
headers = {},
|
|
473
|
+
message,
|
|
474
|
+
totalCount
|
|
475
|
+
}) {
|
|
476
|
+
if (success) {
|
|
477
|
+
return {
|
|
478
|
+
success: true,
|
|
479
|
+
raw,
|
|
480
|
+
data: raw,
|
|
481
|
+
message: "",
|
|
482
|
+
status,
|
|
483
|
+
headers,
|
|
484
|
+
...totalCount == null ? {} : { totalCount }
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
success: false,
|
|
489
|
+
raw,
|
|
490
|
+
data: null,
|
|
491
|
+
message: message ?? stringifyErrorPayload(raw),
|
|
492
|
+
status,
|
|
493
|
+
headers,
|
|
494
|
+
...totalCount == null ? {} : { totalCount }
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
var normalizeTransportFailure = (error) => {
|
|
498
|
+
const transportError = error && typeof error === "object" ? error : {};
|
|
499
|
+
let raw = null;
|
|
500
|
+
let status = 0;
|
|
501
|
+
let headers = {};
|
|
502
|
+
let message;
|
|
503
|
+
if (transportError.response) {
|
|
504
|
+
status = transportError.response.status;
|
|
505
|
+
headers = transportError.response.headers;
|
|
506
|
+
raw = transportError.response.data;
|
|
507
|
+
} else if (transportError.request) {
|
|
508
|
+
message = "The server is not responding";
|
|
509
|
+
} else {
|
|
510
|
+
message = transportError.message;
|
|
511
|
+
}
|
|
512
|
+
return finalizeOperationResult({ success: false, raw, status, headers, message });
|
|
513
|
+
};
|
|
325
514
|
var Service = class {
|
|
326
|
-
constructor(
|
|
327
|
-
this._axios =
|
|
515
|
+
constructor(axios3, basePath, throwOnError = false) {
|
|
516
|
+
this._axios = axios3;
|
|
328
517
|
this._basePath = basePath;
|
|
329
|
-
this._wrap = createWrapHelper(
|
|
518
|
+
this._wrap = createWrapHelper(axios3, basePath);
|
|
519
|
+
this._throwOnError = throwOnError;
|
|
330
520
|
}
|
|
331
521
|
handleSuccess(res, extra = {}) {
|
|
332
|
-
return {
|
|
522
|
+
return {
|
|
523
|
+
...finalizeOperationResult({
|
|
524
|
+
success: true,
|
|
525
|
+
raw: res.data,
|
|
526
|
+
status: res.status,
|
|
527
|
+
headers: res.headers
|
|
528
|
+
}),
|
|
529
|
+
...extra
|
|
530
|
+
};
|
|
333
531
|
}
|
|
334
532
|
// See https://axios-http.com/docs/handling-errors
|
|
335
533
|
handleError(error) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
status: 0,
|
|
342
|
-
headers: {}
|
|
343
|
-
};
|
|
344
|
-
if (error.response) {
|
|
345
|
-
result.status = error.response.status;
|
|
346
|
-
result.headers = error.response.headers;
|
|
347
|
-
const responseData = error.response.data;
|
|
348
|
-
result.raw = responseData;
|
|
349
|
-
result.data = responseData;
|
|
350
|
-
result.message = stringifyErrorPayload(responseData);
|
|
351
|
-
} else if (error.request) {
|
|
352
|
-
result.message = "The server is not responding";
|
|
353
|
-
} else {
|
|
354
|
-
result.message = error.message;
|
|
355
|
-
}
|
|
356
|
-
return result;
|
|
534
|
+
return normalizeTransportFailure(error);
|
|
535
|
+
}
|
|
536
|
+
/** Resolves per-call policy against the already-resolved service/adapter default. */
|
|
537
|
+
resolveThrowOnError(override) {
|
|
538
|
+
return override ?? this._throwOnError;
|
|
357
539
|
}
|
|
358
540
|
wrapGet(url, defaultAxiosRequestConfig = {}) {
|
|
359
541
|
return this._wrap.wrapGet(url, defaultAxiosRequestConfig);
|
|
@@ -370,15 +552,40 @@ var Service = class {
|
|
|
370
552
|
wrapDelete(url, defaultAxiosRequestConfig = {}) {
|
|
371
553
|
return this._wrap.wrapDelete(url, defaultAxiosRequestConfig);
|
|
372
554
|
}
|
|
555
|
+
/**
|
|
556
|
+
* Public bridge to the per-service success/failure callback pipeline and
|
|
557
|
+
* `throwOnError` policy. Adapter-internal grouping machinery calls this so
|
|
558
|
+
* that grouped entries go through the same finalization the direct path
|
|
559
|
+
* uses (`createResponseHandler`). Returns `res` unchanged on success and
|
|
560
|
+
* throws `ServiceError` when both `res.success === false` and the
|
|
561
|
+
* `throwOnError` override (or the service-level default) are enabled.
|
|
562
|
+
*/
|
|
563
|
+
applyResponseCallbacks(res, throwOnErrorOverride) {
|
|
564
|
+
const handler = this._handleCallbacks;
|
|
565
|
+
return handler ? handler(res, throwOnErrorOverride) : res;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Returns a fresh headers object that includes the package-owned
|
|
569
|
+
* `CACHE_HEADER` set to `"true"` (cache eligible) or `"false"` (bypass)
|
|
570
|
+
* according to the `ignoreCache` option. The caller's `CACHE_HEADER`
|
|
571
|
+
* value, if any, wins over the `ignoreCache` default.
|
|
572
|
+
*
|
|
573
|
+
* The input `headers` object is **never mutated**: an `AxiosHeaders`
|
|
574
|
+
* instance is cloned via `.toJSON()` before any value is set, and a
|
|
575
|
+
* plain-object headers input is shallow-copied. Reusing the same
|
|
576
|
+
* caller-owned headers across multiple requests therefore has no
|
|
577
|
+
* hidden side effects, and the order of invocations is irrelevant.
|
|
578
|
+
*/
|
|
373
579
|
updateHeaders(headers, { ignoreCache }) {
|
|
374
580
|
const cacheValue = ignoreCache ? "false" : "true";
|
|
375
581
|
if (!headers) {
|
|
376
582
|
return { [CACHE_HEADER]: cacheValue };
|
|
377
583
|
}
|
|
378
|
-
if (headers instanceof
|
|
584
|
+
if (headers instanceof AxiosHeaders2) {
|
|
379
585
|
if (headers.has(CACHE_HEADER)) return headers;
|
|
380
|
-
headers.
|
|
381
|
-
|
|
586
|
+
const cloned = new AxiosHeaders2(headers.toJSON());
|
|
587
|
+
cloned.set(CACHE_HEADER, cacheValue);
|
|
588
|
+
return cloned;
|
|
382
589
|
}
|
|
383
590
|
if (CACHE_HEADER in headers) return headers;
|
|
384
591
|
return {
|
|
@@ -391,16 +598,399 @@ var ServiceError = class extends Error {
|
|
|
391
598
|
constructor(result) {
|
|
392
599
|
super(result.message);
|
|
393
600
|
this.name = "ServiceError";
|
|
394
|
-
this.success =
|
|
601
|
+
this.success = false;
|
|
395
602
|
this.raw = result.raw;
|
|
396
|
-
this.data =
|
|
603
|
+
this.data = null;
|
|
397
604
|
this.status = result.status;
|
|
398
605
|
this.headers = result.headers;
|
|
399
606
|
}
|
|
400
607
|
};
|
|
401
608
|
|
|
609
|
+
// src/services/interceptors.ts
|
|
610
|
+
import axios, { AxiosHeaders as AxiosHeaders4 } from "axios";
|
|
611
|
+
|
|
612
|
+
// src/services/cache-utils.ts
|
|
613
|
+
import { AxiosHeaders as AxiosHeaders3 } from "axios";
|
|
614
|
+
import { omitBy } from "@web-ts-toolkit/utils";
|
|
615
|
+
var normalizeConfigValue = (value) => {
|
|
616
|
+
if (value == null) return value;
|
|
617
|
+
if (value instanceof AxiosHeaders3) {
|
|
618
|
+
return normalizeConfigValue(value.toJSON());
|
|
619
|
+
}
|
|
620
|
+
if (Array.isArray(value)) {
|
|
621
|
+
return value.map((item) => normalizeConfigValue(item));
|
|
622
|
+
}
|
|
623
|
+
if (typeof value === "object") {
|
|
624
|
+
return Object.entries(omitBy(value, (item) => item === void 0)).sort(([left], [right]) => left.localeCompare(right)).reduce((acc, [key, item]) => {
|
|
625
|
+
acc[key] = normalizeConfigValue(item);
|
|
626
|
+
return acc;
|
|
627
|
+
}, {});
|
|
628
|
+
}
|
|
629
|
+
return value;
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// src/services/interceptors.ts
|
|
633
|
+
var DEFAULT_CACHE_CAPACITY = 100;
|
|
634
|
+
var CACHEABLE_METHODS = /* @__PURE__ */ new Set(["get"]);
|
|
635
|
+
var MUTATION_METHODS = /* @__PURE__ */ new Set(["post", "put", "patch", "delete"]);
|
|
636
|
+
var CACHEABLE_RESPONSE_TYPES = /* @__PURE__ */ new Set(["", "json", "text"]);
|
|
637
|
+
var SENSITIVE_CACHE_HEADERS = /* @__PURE__ */ new Set([
|
|
638
|
+
"authorization",
|
|
639
|
+
"cookie",
|
|
640
|
+
"set-cookie",
|
|
641
|
+
"proxy-authorization",
|
|
642
|
+
"www-authenticate"
|
|
643
|
+
]);
|
|
644
|
+
var cloneConfigWithCacheBypass = (config) => {
|
|
645
|
+
const baseConfig = config ?? {};
|
|
646
|
+
const next = { ...baseConfig };
|
|
647
|
+
const sourceHeaders = config?.headers;
|
|
648
|
+
if (sourceHeaders instanceof AxiosHeaders4) {
|
|
649
|
+
next.headers = sourceHeaders.toJSON();
|
|
650
|
+
} else if (sourceHeaders && typeof sourceHeaders === "object") {
|
|
651
|
+
next.headers = { ...sourceHeaders };
|
|
652
|
+
} else {
|
|
653
|
+
next.headers = {};
|
|
654
|
+
}
|
|
655
|
+
next.headers[CACHE_HEADER] = "false";
|
|
656
|
+
return next;
|
|
657
|
+
};
|
|
658
|
+
var SimpleCache = class {
|
|
659
|
+
constructor(opts = {}) {
|
|
660
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
661
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
662
|
+
this.capacity = opts.capacity !== void 0 && Number.isFinite(opts.capacity) && opts.capacity > 0 ? Math.floor(opts.capacity) : DEFAULT_CACHE_CAPACITY;
|
|
663
|
+
this.clone = opts.clone ?? defaultClone;
|
|
664
|
+
}
|
|
665
|
+
set(key, value, ttl) {
|
|
666
|
+
if (this.cache.size >= this.capacity && !this.cache.has(key)) {
|
|
667
|
+
const oldestKey = this.cache.keys().next().value;
|
|
668
|
+
if (oldestKey !== void 0) {
|
|
669
|
+
this.delete(oldestKey);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
this.cache.delete(key);
|
|
673
|
+
this.cache.set(key, value);
|
|
674
|
+
if (ttl && ttl > 0) {
|
|
675
|
+
const existing = this.timers.get(key);
|
|
676
|
+
if (existing) clearTimeout(existing);
|
|
677
|
+
const timer = setTimeout(() => {
|
|
678
|
+
this.cache.delete(key);
|
|
679
|
+
this.timers.delete(key);
|
|
680
|
+
}, ttl);
|
|
681
|
+
if (typeof timer === "object" && timer && "unref" in timer && typeof timer.unref === "function") {
|
|
682
|
+
timer.unref();
|
|
683
|
+
}
|
|
684
|
+
this.timers.set(key, timer);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
get(key) {
|
|
688
|
+
const value = this.cache.get(key);
|
|
689
|
+
if (value === void 0) {
|
|
690
|
+
return void 0;
|
|
691
|
+
}
|
|
692
|
+
this.cache.delete(key);
|
|
693
|
+
this.cache.set(key, value);
|
|
694
|
+
return this.clone(value);
|
|
695
|
+
}
|
|
696
|
+
has(key) {
|
|
697
|
+
return this.cache.has(key);
|
|
698
|
+
}
|
|
699
|
+
delete(key) {
|
|
700
|
+
const timer = this.timers.get(key);
|
|
701
|
+
if (timer) {
|
|
702
|
+
clearTimeout(timer);
|
|
703
|
+
this.timers.delete(key);
|
|
704
|
+
}
|
|
705
|
+
return this.cache.delete(key);
|
|
706
|
+
}
|
|
707
|
+
clear() {
|
|
708
|
+
for (const timer of this.timers.values()) {
|
|
709
|
+
clearTimeout(timer);
|
|
710
|
+
}
|
|
711
|
+
this.timers.clear();
|
|
712
|
+
this.cache.clear();
|
|
713
|
+
}
|
|
714
|
+
dispose() {
|
|
715
|
+
this.clear();
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
var defaultClone = (value) => {
|
|
719
|
+
if (value == null) return value;
|
|
720
|
+
try {
|
|
721
|
+
return JSON.parse(JSON.stringify(value));
|
|
722
|
+
} catch {
|
|
723
|
+
return value;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
var CACHE_REQUEST_STATE = /* @__PURE__ */ Symbol("access-router-client.cache-request-state");
|
|
727
|
+
var CACHE_DISPOSED_ERROR = "Access router client cache was disposed while the request was in flight";
|
|
728
|
+
var setCacheRequestState = (config, state) => {
|
|
729
|
+
Object.defineProperty(config, CACHE_REQUEST_STATE, {
|
|
730
|
+
configurable: false,
|
|
731
|
+
enumerable: false,
|
|
732
|
+
writable: false,
|
|
733
|
+
value: Object.freeze(state)
|
|
734
|
+
});
|
|
735
|
+
};
|
|
736
|
+
var isUnsupportedResponseBody = (response) => {
|
|
737
|
+
const responseType = response.config?.responseType;
|
|
738
|
+
if (responseType === "stream" || responseType === "arraybuffer" || responseType === "blob" || responseType === "document") {
|
|
739
|
+
return true;
|
|
740
|
+
}
|
|
741
|
+
const data = response.data;
|
|
742
|
+
if (data == null) return false;
|
|
743
|
+
if (typeof data === "string") return false;
|
|
744
|
+
if (typeof data !== "object") return false;
|
|
745
|
+
if (Array.isArray(data)) return false;
|
|
746
|
+
try {
|
|
747
|
+
JSON.stringify(data);
|
|
748
|
+
return false;
|
|
749
|
+
} catch {
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
var snapshotResponse = (response) => {
|
|
754
|
+
const headers = response.headers instanceof AxiosHeaders4 ? response.headers.toJSON() : { ...response.headers ?? {} };
|
|
755
|
+
return {
|
|
756
|
+
data: defaultClone(response.data),
|
|
757
|
+
status: response.status,
|
|
758
|
+
statusText: response.statusText,
|
|
759
|
+
headers: defaultClone(headers)
|
|
760
|
+
};
|
|
761
|
+
};
|
|
762
|
+
var serializeHeaders = (headers) => {
|
|
763
|
+
const resolvedHeaders = headers instanceof AxiosHeaders4 ? headers.toJSON() : headers;
|
|
764
|
+
const normalizedHeaders = Object.entries(resolvedHeaders ?? {}).filter(([key, value]) => {
|
|
765
|
+
const normalizedKey = key.toLowerCase();
|
|
766
|
+
return normalizedKey !== CACHE_HEADER.toLowerCase() && !SENSITIVE_CACHE_HEADERS.has(normalizedKey) && value !== void 0;
|
|
767
|
+
}).reduce((acc, [key, value]) => {
|
|
768
|
+
acc[key.toLowerCase()] = value;
|
|
769
|
+
return acc;
|
|
770
|
+
}, {});
|
|
771
|
+
return JSON.stringify(normalizeConfigValue(normalizedHeaders));
|
|
772
|
+
};
|
|
773
|
+
var hasStableCacheValue = (value, seen = /* @__PURE__ */ new Set()) => {
|
|
774
|
+
if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
775
|
+
return true;
|
|
776
|
+
if (typeof value !== "object") return false;
|
|
777
|
+
if (seen.has(value)) return false;
|
|
778
|
+
if (value instanceof AxiosHeaders4) {
|
|
779
|
+
return hasStableCacheValue(value.toJSON(), seen);
|
|
780
|
+
}
|
|
781
|
+
const prototype = Object.getPrototypeOf(value);
|
|
782
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) return false;
|
|
783
|
+
seen.add(value);
|
|
784
|
+
const stable = Object.values(value).every((item) => hasStableCacheValue(item, seen));
|
|
785
|
+
seen.delete(value);
|
|
786
|
+
return stable;
|
|
787
|
+
};
|
|
788
|
+
var sameTransform = (configured, defaultValue) => {
|
|
789
|
+
const configuredList = Array.isArray(configured) ? configured : [configured];
|
|
790
|
+
const defaultList = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
791
|
+
return configuredList.length === defaultList.length && configuredList.every((item, index) => item === defaultList[index]);
|
|
792
|
+
};
|
|
793
|
+
var sameConfigIdentity = (configured, defaultValue) => {
|
|
794
|
+
if (Array.isArray(configured) && Array.isArray(defaultValue)) {
|
|
795
|
+
return configured.length === defaultValue.length && configured.every((item, index) => item === defaultValue[index]);
|
|
796
|
+
}
|
|
797
|
+
return configured === defaultValue;
|
|
798
|
+
};
|
|
799
|
+
var isCacheEligible = (config, instance) => {
|
|
800
|
+
const method = (config.method ?? "get").toLowerCase();
|
|
801
|
+
const responseType = config.responseType ?? "";
|
|
802
|
+
return CACHEABLE_METHODS.has(method) && CACHEABLE_RESPONSE_TYPES.has(responseType) && config.paramsSerializer === void 0 && config.auth === void 0 && config.signal === void 0 && config.cancelToken === void 0 && config.onDownloadProgress === void 0 && config.onUploadProgress === void 0 && sameConfigIdentity(config.adapter, instance.defaults.adapter) && sameTransform(config.transformRequest, instance.defaults.transformRequest) && sameTransform(config.transformResponse, instance.defaults.transformResponse) && hasStableCacheValue(config.params) && hasStableCacheValue(config.data) && hasStableCacheValue(config.headers);
|
|
803
|
+
};
|
|
804
|
+
function generateCacheKey(config, partition) {
|
|
805
|
+
const responseSemantics = JSON.stringify({
|
|
806
|
+
responseType: config.responseType ?? "",
|
|
807
|
+
responseEncoding: config.responseEncoding ?? "",
|
|
808
|
+
decompress: config.decompress ?? true,
|
|
809
|
+
timeout: config.timeout ?? 0,
|
|
810
|
+
maxContentLength: config.maxContentLength ?? -1,
|
|
811
|
+
maxBodyLength: config.maxBodyLength ?? -1,
|
|
812
|
+
withCredentials: Boolean(config.withCredentials),
|
|
813
|
+
transitional: normalizeConfigValue(config.transitional)
|
|
814
|
+
});
|
|
815
|
+
const key = `${config.baseURL}/${config.url}_${config.method}_${generateParamKey(config.params)}_${generateDataKey(
|
|
816
|
+
config.data
|
|
817
|
+
)}_${partition ?? ""}_${serializeHeaders(config.headers)}_${responseSemantics}`;
|
|
818
|
+
return encodeURI(key);
|
|
819
|
+
}
|
|
820
|
+
function generateParamKey(params) {
|
|
821
|
+
if (!params) return "";
|
|
822
|
+
return JSON.stringify(normalizeConfigValue(params));
|
|
823
|
+
}
|
|
824
|
+
function generateDataKey(data) {
|
|
825
|
+
if (!data) return "";
|
|
826
|
+
return typeof data === "string" ? data : JSON.stringify(normalizeConfigValue(data));
|
|
827
|
+
}
|
|
828
|
+
var resolveWithCredentials = (config, withCredentialsDefault) => {
|
|
829
|
+
if (config.withCredentials !== void 0) {
|
|
830
|
+
return Boolean(config.withCredentials);
|
|
831
|
+
}
|
|
832
|
+
return withCredentialsDefault;
|
|
833
|
+
};
|
|
834
|
+
function useCacheInterceptors(instance, policyOrTtl) {
|
|
835
|
+
const policy = typeof policyOrTtl === "number" ? { ttl: policyOrTtl } : policyOrTtl;
|
|
836
|
+
const store = new SimpleCache({ capacity: policy.capacity, clone: policy.clone });
|
|
837
|
+
const withCredentialsDefault = policy.withCredentialsDefault ?? Boolean(instance.defaults.withCredentials);
|
|
838
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
839
|
+
let generation = 0;
|
|
840
|
+
let disposed = false;
|
|
841
|
+
const finalizeInflight = (slot) => {
|
|
842
|
+
if (inflight.get(slot.key) === slot) {
|
|
843
|
+
inflight.delete(slot.key);
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
const resolveInflight = (slot, response) => {
|
|
847
|
+
if (slot.settled) return;
|
|
848
|
+
slot.settled = true;
|
|
849
|
+
slot.resolve(response);
|
|
850
|
+
finalizeInflight(slot);
|
|
851
|
+
};
|
|
852
|
+
const rejectInflight = (slot, error) => {
|
|
853
|
+
if (slot.settled) return;
|
|
854
|
+
slot.settled = true;
|
|
855
|
+
slot.reject(error);
|
|
856
|
+
finalizeInflight(slot);
|
|
857
|
+
};
|
|
858
|
+
const invalidate = () => {
|
|
859
|
+
generation += 1;
|
|
860
|
+
store.clear();
|
|
861
|
+
inflight.clear();
|
|
862
|
+
};
|
|
863
|
+
instance.interceptors.request.use(
|
|
864
|
+
async (config) => {
|
|
865
|
+
if (disposed || config.headers[CACHE_HEADER] === "false" || !isCacheEligible(config, instance)) return config;
|
|
866
|
+
const isCredentialed = resolveWithCredentials(config, withCredentialsDefault);
|
|
867
|
+
const partitionKey = policy.partitionForRequest?.(config);
|
|
868
|
+
if (isCredentialed && !partitionKey) {
|
|
869
|
+
return config;
|
|
870
|
+
}
|
|
871
|
+
const key = generateCacheKey(config, partitionKey);
|
|
872
|
+
policy.onCacheKey?.(key);
|
|
873
|
+
const snapshot = store.get(key);
|
|
874
|
+
if (snapshot) {
|
|
875
|
+
setCacheRequestState(config, Object.freeze({ key, generation, role: "hit" }));
|
|
876
|
+
config.adapter = async (_config) => {
|
|
877
|
+
return {
|
|
878
|
+
data: snapshot.data,
|
|
879
|
+
status: snapshot.status,
|
|
880
|
+
statusText: snapshot.statusText,
|
|
881
|
+
headers: { ...snapshot.headers, [CACHE_HEADER]: "true" },
|
|
882
|
+
config: _config
|
|
883
|
+
};
|
|
884
|
+
};
|
|
885
|
+
return config;
|
|
886
|
+
}
|
|
887
|
+
const existing = inflight.get(key);
|
|
888
|
+
if (existing) {
|
|
889
|
+
config.adapter = async (_config) => {
|
|
890
|
+
const response = await existing.promise;
|
|
891
|
+
const shared = response;
|
|
892
|
+
return {
|
|
893
|
+
data: defaultClone(shared.data),
|
|
894
|
+
status: shared.status,
|
|
895
|
+
statusText: shared.statusText,
|
|
896
|
+
headers: { ...shared.headers, [CACHE_HEADER]: "true" },
|
|
897
|
+
config: _config
|
|
898
|
+
};
|
|
899
|
+
};
|
|
900
|
+
setCacheRequestState(config, Object.freeze({ key, generation, role: "tail", slot: existing }));
|
|
901
|
+
return config;
|
|
902
|
+
}
|
|
903
|
+
let resolvePromise;
|
|
904
|
+
let rejectPromise;
|
|
905
|
+
const inflightPromise = new Promise((resolve, reject) => {
|
|
906
|
+
resolvePromise = resolve;
|
|
907
|
+
rejectPromise = reject;
|
|
908
|
+
});
|
|
909
|
+
inflightPromise.catch(() => {
|
|
910
|
+
});
|
|
911
|
+
const slot = {
|
|
912
|
+
key,
|
|
913
|
+
generation,
|
|
914
|
+
promise: inflightPromise,
|
|
915
|
+
resolve: resolvePromise,
|
|
916
|
+
reject: rejectPromise,
|
|
917
|
+
settled: false
|
|
918
|
+
};
|
|
919
|
+
inflight.set(key, slot);
|
|
920
|
+
const nextConfig = { ...config };
|
|
921
|
+
setCacheRequestState(nextConfig, Object.freeze({ key, generation, role: "source", slot }));
|
|
922
|
+
let realAdapter = config.adapter;
|
|
923
|
+
if (realAdapter === void 0 || realAdapter === null) {
|
|
924
|
+
realAdapter = instance.defaults.adapter;
|
|
925
|
+
}
|
|
926
|
+
const dispatch = typeof realAdapter === "function" ? realAdapter : typeof axios.getAdapter === "function" ? axios.getAdapter(
|
|
927
|
+
realAdapter,
|
|
928
|
+
instance.defaults
|
|
929
|
+
) : void 0;
|
|
930
|
+
nextConfig.adapter = async (adapterConfig) => {
|
|
931
|
+
if (!dispatch) {
|
|
932
|
+
const response = await adapterConfig.adapter;
|
|
933
|
+
return response;
|
|
934
|
+
}
|
|
935
|
+
try {
|
|
936
|
+
const response = await dispatch(adapterConfig);
|
|
937
|
+
return response;
|
|
938
|
+
} catch (error) {
|
|
939
|
+
rejectInflight(slot, error);
|
|
940
|
+
throw error;
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
return nextConfig;
|
|
944
|
+
},
|
|
945
|
+
(error) => Promise.reject(error)
|
|
946
|
+
);
|
|
947
|
+
instance.interceptors.response.use(
|
|
948
|
+
(response) => {
|
|
949
|
+
const method = (response.config.method ?? "get").toLowerCase();
|
|
950
|
+
if (response.config.headers[CACHE_HEADER] === "false" || MUTATION_METHODS.has(method)) {
|
|
951
|
+
if (response.status >= 200 && response.status < 300) {
|
|
952
|
+
invalidate();
|
|
953
|
+
}
|
|
954
|
+
return response;
|
|
955
|
+
}
|
|
956
|
+
const state = response.config[CACHE_REQUEST_STATE];
|
|
957
|
+
if (!state || state.role !== "source" || !state.slot) {
|
|
958
|
+
return response;
|
|
959
|
+
}
|
|
960
|
+
if (response.status >= 200 && response.status < 300) {
|
|
961
|
+
if (!disposed && state.generation === generation && !isUnsupportedResponseBody(response)) {
|
|
962
|
+
store.set(state.key, snapshotResponse(response), policy.ttl);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
resolveInflight(state.slot, response);
|
|
966
|
+
return response;
|
|
967
|
+
},
|
|
968
|
+
(error) => {
|
|
969
|
+
const state = (error?.config ?? {})[CACHE_REQUEST_STATE];
|
|
970
|
+
if (state?.role === "source" && state.slot) {
|
|
971
|
+
rejectInflight(state.slot, error);
|
|
972
|
+
}
|
|
973
|
+
return Promise.reject(error);
|
|
974
|
+
}
|
|
975
|
+
);
|
|
976
|
+
return {
|
|
977
|
+
clear: invalidate,
|
|
978
|
+
dispose: () => {
|
|
979
|
+
if (disposed) return;
|
|
980
|
+
disposed = true;
|
|
981
|
+
generation += 1;
|
|
982
|
+
store.dispose();
|
|
983
|
+
const error = new Error(CACHE_DISPOSED_ERROR);
|
|
984
|
+
for (const slot of inflight.values()) {
|
|
985
|
+
rejectInflight(slot, error);
|
|
986
|
+
}
|
|
987
|
+
inflight.clear();
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
|
|
402
992
|
// src/services/shared.ts
|
|
403
|
-
import { get, noop, set
|
|
993
|
+
import { castArray, get, noop, set } from "@web-ts-toolkit/utils";
|
|
404
994
|
|
|
405
995
|
// src/enums.ts
|
|
406
996
|
var CustomHeaders = /* @__PURE__ */ ((CustomHeaders2) => {
|
|
@@ -415,10 +1005,118 @@ var CustomHeaders = /* @__PURE__ */ ((CustomHeaders2) => {
|
|
|
415
1005
|
})(CustomHeaders || {});
|
|
416
1006
|
|
|
417
1007
|
// src/services/shared.ts
|
|
1008
|
+
var getSubdocumentResultShape = (query) => {
|
|
1009
|
+
if (query.target !== "model") return void 0;
|
|
1010
|
+
switch (query.op) {
|
|
1011
|
+
case "subList":
|
|
1012
|
+
case "subCreate":
|
|
1013
|
+
case "subBulkUpdate":
|
|
1014
|
+
return "list";
|
|
1015
|
+
case "subRead":
|
|
1016
|
+
case "subUpdate":
|
|
1017
|
+
return "single";
|
|
1018
|
+
case "subDelete":
|
|
1019
|
+
return "scalar";
|
|
1020
|
+
default:
|
|
1021
|
+
return void 0;
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
function finalizeRootEntry(query, entry, responseHeaders, service) {
|
|
1025
|
+
const { result, message: entryMessage, statusCode, op } = entry;
|
|
1026
|
+
const success = result.success;
|
|
1027
|
+
const baseResult = finalizeOperationResult({
|
|
1028
|
+
success,
|
|
1029
|
+
raw: success ? result.data : result,
|
|
1030
|
+
status: statusCode,
|
|
1031
|
+
headers: responseHeaders,
|
|
1032
|
+
message: success ? void 0 : entryMessage
|
|
1033
|
+
});
|
|
1034
|
+
let _raw = baseResult.raw;
|
|
1035
|
+
let _data = baseResult.data;
|
|
1036
|
+
const subdocumentResultShape = getSubdocumentResultShape(query);
|
|
1037
|
+
if (!success) {
|
|
1038
|
+
_data = null;
|
|
1039
|
+
} else if (subdocumentResultShape) {
|
|
1040
|
+
if (subdocumentResultShape === "list") {
|
|
1041
|
+
const rows = result.data == null ? [] : castArray(result.data);
|
|
1042
|
+
_raw = rows;
|
|
1043
|
+
_data = rows;
|
|
1044
|
+
}
|
|
1045
|
+
} else if (query.target === "model") {
|
|
1046
|
+
const modelService = service;
|
|
1047
|
+
if (result.kind === "list" && Array.isArray(result.data)) {
|
|
1048
|
+
if (op === "create" && !Array.isArray(query.data) && result.data.length === 1) {
|
|
1049
|
+
_raw = result.data[0];
|
|
1050
|
+
if (modelService) {
|
|
1051
|
+
_data = Model.create(result.data[0], modelService, void 0, true);
|
|
1052
|
+
}
|
|
1053
|
+
} else if (op !== "distinct") {
|
|
1054
|
+
const rows = castArray(result.data);
|
|
1055
|
+
if (modelService) {
|
|
1056
|
+
_data = rows.map((item) => Model.create(item, modelService, void 0, true));
|
|
1057
|
+
} else {
|
|
1058
|
+
_data = rows;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
} else if (result.kind === "single" && (op === "new" || op === "read" || op === "update" || op === "upsert")) {
|
|
1062
|
+
if (op === "new" && result.data && typeof result.data === "object") {
|
|
1063
|
+
const { _id: _generatedId, ...draft } = result.data;
|
|
1064
|
+
void _generatedId;
|
|
1065
|
+
_raw = draft;
|
|
1066
|
+
_data = draft;
|
|
1067
|
+
}
|
|
1068
|
+
if (modelService) {
|
|
1069
|
+
const fromExisting = op !== "new";
|
|
1070
|
+
const persistenceId = op === "read" && query.target === "model" && "id" in query ? query.id : void 0;
|
|
1071
|
+
_data = Model.create(_data, modelService, persistenceId, fromExisting);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const isSubdocumentList = subdocumentResultShape === "list";
|
|
1076
|
+
const isModelOrDataList = !subdocumentResultShape && query.op === "list";
|
|
1077
|
+
const returnedCount = Array.isArray(_data) ? _data.length : 0;
|
|
1078
|
+
const totalCount = success && query.options?.includeCount === true ? result.totalCount ?? result.count ?? returnedCount : 0;
|
|
1079
|
+
return {
|
|
1080
|
+
success,
|
|
1081
|
+
raw: _raw,
|
|
1082
|
+
data: _data,
|
|
1083
|
+
message: baseResult.message,
|
|
1084
|
+
status: statusCode,
|
|
1085
|
+
...isSubdocumentList ? { count: success ? returnedCount : 0 } : {},
|
|
1086
|
+
...isModelOrDataList ? { totalCount } : {},
|
|
1087
|
+
headers: responseHeaders
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
function finalizeRootTransportFailure(query, error) {
|
|
1091
|
+
const failure = normalizeTransportFailure(error);
|
|
1092
|
+
const subdocumentResultShape = getSubdocumentResultShape(query);
|
|
1093
|
+
return {
|
|
1094
|
+
...failure,
|
|
1095
|
+
...subdocumentResultShape === "list" ? { count: 0 } : {},
|
|
1096
|
+
...!subdocumentResultShape && query.op === "list" ? { totalCount: 0 } : {}
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
function applyGroupCallbacks(entries, services, groupThrowOnError) {
|
|
1100
|
+
let callbackError;
|
|
1101
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1102
|
+
const svc = services[i];
|
|
1103
|
+
try {
|
|
1104
|
+
entries[i] = svc?.applyResponseCallbacks ? svc.applyResponseCallbacks(entries[i], false) : entries[i];
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
callbackError ??= error;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (callbackError) throw callbackError;
|
|
1110
|
+
if (groupThrowOnError) {
|
|
1111
|
+
const failure = entries.find((entry) => !entry.success);
|
|
1112
|
+
if (failure) throw new ServiceError(toResultError(failure));
|
|
1113
|
+
}
|
|
1114
|
+
return entries;
|
|
1115
|
+
}
|
|
418
1116
|
var toResultError = (result) => ({
|
|
419
1117
|
success: false,
|
|
420
1118
|
raw: result.raw ?? null,
|
|
421
|
-
data:
|
|
1119
|
+
data: null,
|
|
422
1120
|
message: result.message ?? "",
|
|
423
1121
|
status: result.status ?? 0,
|
|
424
1122
|
headers: result.headers ?? {}
|
|
@@ -431,9 +1129,13 @@ var isLegacyListPayload = (value) => {
|
|
|
431
1129
|
};
|
|
432
1130
|
var setDefaultObjectProp = (obj, key, value) => {
|
|
433
1131
|
if (!get(obj, key)) {
|
|
434
|
-
|
|
1132
|
+
set(obj, key, value);
|
|
435
1133
|
}
|
|
436
1134
|
};
|
|
1135
|
+
var ensureListResultCount = (result) => {
|
|
1136
|
+
result.totalCount ??= 0;
|
|
1137
|
+
return result;
|
|
1138
|
+
};
|
|
437
1139
|
var createResponseHandler = (onSuccess, onFailure, throwOnError) => {
|
|
438
1140
|
const successHandler = onSuccess ?? noop;
|
|
439
1141
|
const failureHandler = onFailure ?? noop;
|
|
@@ -450,6 +1152,7 @@ var createResponseHandler = (onSuccess, onFailure, throwOnError) => {
|
|
|
450
1152
|
};
|
|
451
1153
|
};
|
|
452
1154
|
function processListResult(result, { includeCount, includeExtraHeaders }, wrapItem) {
|
|
1155
|
+
ensureListResultCount(result);
|
|
453
1156
|
const wrappedRows = get(result, "raw.data");
|
|
454
1157
|
const wrappedTotalCount = get(result, "raw.meta.totalCount");
|
|
455
1158
|
if (Array.isArray(wrappedRows)) {
|
|
@@ -482,11 +1185,40 @@ function processListResult(result, { includeCount, includeExtraHeaders }, wrapIt
|
|
|
482
1185
|
}
|
|
483
1186
|
|
|
484
1187
|
// src/lazy-promise.ts
|
|
1188
|
+
var STARTED_KEY = /* @__PURE__ */ Symbol("started");
|
|
1189
|
+
var executionClaims = /* @__PURE__ */ new WeakMap();
|
|
1190
|
+
var claimLazyRequest = (request, mode, owner) => {
|
|
1191
|
+
const claim = executionClaims.get(request);
|
|
1192
|
+
if (!claim) {
|
|
1193
|
+
executionClaims.set(request, { mode, owner });
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
if (mode === "grouped") {
|
|
1197
|
+
if (claim.mode === "direct") {
|
|
1198
|
+
throw new Error(
|
|
1199
|
+
"Cannot group a request that has already started execution; group() must be called before await/then/catch/finally/exec on each input"
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
throw new Error("Cannot group a request already claimed for grouped execution");
|
|
1203
|
+
}
|
|
1204
|
+
throw new Error("Cannot execute a request already claimed for grouped execution");
|
|
1205
|
+
};
|
|
1206
|
+
var releaseLazyRequestClaim = (request, owner) => {
|
|
1207
|
+
const claim = executionClaims.get(request);
|
|
1208
|
+
if (claim?.mode === "grouped" && claim.owner === owner) {
|
|
1209
|
+
executionClaims.delete(request);
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
485
1212
|
var wrapLazyPromise = (promiseFn, meta) => {
|
|
486
1213
|
let promise;
|
|
487
1214
|
const exec = () => {
|
|
488
1215
|
if (!promise) {
|
|
489
|
-
|
|
1216
|
+
try {
|
|
1217
|
+
claimLazyRequest(prom, "direct");
|
|
1218
|
+
promise = Promise.resolve().then(promiseFn);
|
|
1219
|
+
} catch (error) {
|
|
1220
|
+
promise = Promise.reject(error);
|
|
1221
|
+
}
|
|
490
1222
|
}
|
|
491
1223
|
return promise;
|
|
492
1224
|
};
|
|
@@ -509,32 +1241,62 @@ var wrapLazyPromise = (promiseFn, meta) => {
|
|
|
509
1241
|
value: "Promise",
|
|
510
1242
|
writable: false,
|
|
511
1243
|
enumerable: false,
|
|
512
|
-
configurable:
|
|
1244
|
+
configurable: false
|
|
1245
|
+
});
|
|
1246
|
+
Object.defineProperty(prom, STARTED_KEY, {
|
|
1247
|
+
get: () => executionClaims.has(prom),
|
|
1248
|
+
enumerable: false,
|
|
1249
|
+
configurable: false
|
|
513
1250
|
});
|
|
514
|
-
|
|
1251
|
+
if (meta != null) {
|
|
1252
|
+
const metaKeys = Object.keys(meta);
|
|
1253
|
+
for (let i = 0; i < metaKeys.length; i++) {
|
|
1254
|
+
const key = metaKeys[i];
|
|
1255
|
+
Object.defineProperty(prom, key, {
|
|
1256
|
+
value: meta[key],
|
|
1257
|
+
enumerable: false,
|
|
1258
|
+
writable: false,
|
|
1259
|
+
configurable: false
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
515
1263
|
return prom;
|
|
516
1264
|
};
|
|
517
1265
|
|
|
518
1266
|
// src/services/request.ts
|
|
519
1267
|
function makeRequest(execute, meta) {
|
|
520
|
-
|
|
1268
|
+
const effectiveMeta = {
|
|
1269
|
+
...meta,
|
|
1270
|
+
__throwOnError: meta.__service?.resolveThrowOnError(meta.__throwOnError) ?? Boolean(meta.__throwOnError)
|
|
1271
|
+
};
|
|
1272
|
+
return wrapLazyPromise(execute, effectiveMeta);
|
|
521
1273
|
}
|
|
522
1274
|
|
|
523
1275
|
// src/services/sub-ops.ts
|
|
524
1276
|
import { mergeConfig as mergeConfig2 } from "axios";
|
|
1277
|
+
var toArray = (value) => Array.isArray(value) ? value : value == null ? [] : [value];
|
|
1278
|
+
var ensureSubdocumentListCount = (result) => {
|
|
1279
|
+
result.count ??= 0;
|
|
1280
|
+
return result;
|
|
1281
|
+
};
|
|
525
1282
|
function buildSubDocumentOps(ctx, id, sub) {
|
|
526
|
-
const { axios:
|
|
527
|
-
const asS = parentService;
|
|
1283
|
+
const { axios: axios3, basePath, modelName, queryPath, handleSuccess, handleError, _handleCallbacks, parentService } = ctx;
|
|
528
1284
|
return {
|
|
529
1285
|
list: (axiosRequestConfig) => {
|
|
530
1286
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
531
1287
|
return makeRequest(
|
|
532
|
-
() =>
|
|
533
|
-
|
|
534
|
-
|
|
1288
|
+
() => axios3.get(
|
|
1289
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}`,
|
|
1290
|
+
mergeConfig2(reqConfig, { params: {} })
|
|
1291
|
+
).then(handleSuccess).then((result) => {
|
|
1292
|
+
const rawArray = toArray(result.raw);
|
|
1293
|
+
result.raw = rawArray;
|
|
1294
|
+
result.count = rawArray.length;
|
|
1295
|
+
result.data = rawArray;
|
|
535
1296
|
return result;
|
|
536
|
-
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
1297
|
+
}).catch(handleError).then(ensureSubdocumentListCount).then((res) => _handleCallbacks(res, throwOnError)),
|
|
537
1298
|
{
|
|
1299
|
+
__throwOnError: throwOnError,
|
|
538
1300
|
__op: "listSub",
|
|
539
1301
|
__query: {
|
|
540
1302
|
target: "model",
|
|
@@ -556,14 +1318,21 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
556
1318
|
const select = args?.select;
|
|
557
1319
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
558
1320
|
return makeRequest(
|
|
559
|
-
() =>
|
|
560
|
-
|
|
561
|
-
|
|
1321
|
+
() => axios3.post(
|
|
1322
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}/${queryPath}`,
|
|
1323
|
+
{ filter, select },
|
|
1324
|
+
reqConfig
|
|
1325
|
+
).then(handleSuccess).then((result) => {
|
|
1326
|
+
const rawArray = toArray(result.raw);
|
|
1327
|
+
result.raw = rawArray;
|
|
1328
|
+
result.count = rawArray.length;
|
|
1329
|
+
result.data = rawArray;
|
|
562
1330
|
return result;
|
|
563
|
-
}).catch(handleError).then(
|
|
1331
|
+
}).catch(handleError).then(ensureSubdocumentListCount).then(
|
|
564
1332
|
(res) => _handleCallbacks(res, throwOnError)
|
|
565
1333
|
),
|
|
566
1334
|
{
|
|
1335
|
+
__throwOnError: throwOnError,
|
|
567
1336
|
__op: "listAdvancedSub",
|
|
568
1337
|
__query: {
|
|
569
1338
|
target: "model",
|
|
@@ -584,11 +1353,15 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
584
1353
|
read: (subId, axiosRequestConfig) => {
|
|
585
1354
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
586
1355
|
return makeRequest(
|
|
587
|
-
() =>
|
|
588
|
-
|
|
1356
|
+
() => axios3.get(
|
|
1357
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}/${encodePathSegment(subId)}`,
|
|
1358
|
+
mergeConfig2(reqConfig, { params: {} })
|
|
1359
|
+
).then(handleSuccess).then((result) => {
|
|
1360
|
+
result.data = result.success ? result.raw : null;
|
|
589
1361
|
return result;
|
|
590
1362
|
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
591
1363
|
{
|
|
1364
|
+
__throwOnError: throwOnError,
|
|
592
1365
|
__op: "readSub",
|
|
593
1366
|
__query: {
|
|
594
1367
|
target: "model",
|
|
@@ -610,13 +1383,18 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
610
1383
|
const { select, populate } = args ?? {};
|
|
611
1384
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
612
1385
|
return makeRequest(
|
|
613
|
-
() =>
|
|
614
|
-
|
|
1386
|
+
() => axios3.post(
|
|
1387
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}/${encodePathSegment(subId)}/${queryPath}`,
|
|
1388
|
+
{ select, populate },
|
|
1389
|
+
reqConfig
|
|
1390
|
+
).then(handleSuccess).then((result) => {
|
|
1391
|
+
result.data = result.success ? result.raw : null;
|
|
615
1392
|
return result;
|
|
616
1393
|
}).catch(handleError).then(
|
|
617
1394
|
(res) => _handleCallbacks(res, throwOnError)
|
|
618
1395
|
),
|
|
619
1396
|
{
|
|
1397
|
+
__throwOnError: throwOnError,
|
|
620
1398
|
__op: "readAdvancedSub",
|
|
621
1399
|
__query: {
|
|
622
1400
|
target: "model",
|
|
@@ -635,13 +1413,18 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
635
1413
|
);
|
|
636
1414
|
},
|
|
637
1415
|
update: (subId, data, axiosRequestConfig) => {
|
|
638
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1416
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
639
1417
|
return makeRequest(
|
|
640
|
-
() =>
|
|
641
|
-
|
|
1418
|
+
() => axios3.patch(
|
|
1419
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}/${encodePathSegment(subId)}`,
|
|
1420
|
+
data,
|
|
1421
|
+
mergeConfig2(reqConfig, { params: {} })
|
|
1422
|
+
).then(handleSuccess).then((result) => {
|
|
1423
|
+
result.data = result.success ? result.raw : null;
|
|
642
1424
|
return result;
|
|
643
1425
|
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
644
1426
|
{
|
|
1427
|
+
__throwOnError: throwOnError,
|
|
645
1428
|
__op: "updateSub",
|
|
646
1429
|
__query: {
|
|
647
1430
|
target: "model",
|
|
@@ -660,13 +1443,21 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
660
1443
|
);
|
|
661
1444
|
},
|
|
662
1445
|
bulkUpdate: (data, axiosRequestConfig) => {
|
|
663
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1446
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
664
1447
|
return makeRequest(
|
|
665
|
-
() =>
|
|
666
|
-
|
|
1448
|
+
() => axios3.patch(
|
|
1449
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}`,
|
|
1450
|
+
data,
|
|
1451
|
+
mergeConfig2(reqConfig, { params: {} })
|
|
1452
|
+
).then(handleSuccess).then((result) => {
|
|
1453
|
+
const rawArray = toArray(result.raw);
|
|
1454
|
+
result.raw = rawArray;
|
|
1455
|
+
result.count = rawArray.length;
|
|
1456
|
+
result.data = rawArray;
|
|
667
1457
|
return result;
|
|
668
|
-
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
1458
|
+
}).catch(handleError).then(ensureSubdocumentListCount).then((res) => _handleCallbacks(res, throwOnError)),
|
|
669
1459
|
{
|
|
1460
|
+
__throwOnError: throwOnError,
|
|
670
1461
|
__op: "bulkUpdateSub",
|
|
671
1462
|
__query: {
|
|
672
1463
|
target: "model",
|
|
@@ -684,30 +1475,42 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
684
1475
|
);
|
|
685
1476
|
},
|
|
686
1477
|
create: (data, axiosRequestConfig) => {
|
|
687
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1478
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
688
1479
|
return makeRequest(
|
|
689
|
-
() =>
|
|
690
|
-
|
|
1480
|
+
() => axios3.post(
|
|
1481
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}`,
|
|
1482
|
+
data,
|
|
1483
|
+
mergeConfig2(reqConfig, { params: {} })
|
|
1484
|
+
).then(handleSuccess).then((result) => {
|
|
1485
|
+
const rawArray = toArray(result.raw);
|
|
1486
|
+
result.raw = rawArray;
|
|
1487
|
+
result.count = rawArray.length;
|
|
1488
|
+
result.data = rawArray;
|
|
691
1489
|
return result;
|
|
692
|
-
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
1490
|
+
}).catch(handleError).then(ensureSubdocumentListCount).then((res) => _handleCallbacks(res, throwOnError)),
|
|
693
1491
|
{
|
|
1492
|
+
__throwOnError: throwOnError,
|
|
694
1493
|
__op: "createSub",
|
|
695
|
-
__query: { target: "model", name: modelName,
|
|
1494
|
+
__query: { target: "model", name: modelName, op: "subCreate", id, sub, data, options: {} },
|
|
696
1495
|
__requestConfig: reqConfig,
|
|
697
1496
|
__service: parentService
|
|
698
1497
|
}
|
|
699
1498
|
);
|
|
700
1499
|
},
|
|
701
1500
|
delete: (subId, axiosRequestConfig) => {
|
|
702
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1501
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
703
1502
|
return makeRequest(
|
|
704
|
-
() =>
|
|
705
|
-
|
|
1503
|
+
() => axios3.delete(
|
|
1504
|
+
`${basePath}/${encodePathSegment(id)}/${encodePathSegment(sub)}/${encodePathSegment(subId)}`,
|
|
1505
|
+
reqConfig
|
|
1506
|
+
).then(handleSuccess).then((result) => {
|
|
1507
|
+
if (result.success) result.data = result.raw;
|
|
706
1508
|
return result;
|
|
707
1509
|
}).catch(handleError).then((res) => _handleCallbacks(res, throwOnError)),
|
|
708
1510
|
{
|
|
1511
|
+
__throwOnError: throwOnError,
|
|
709
1512
|
__op: "deleteSub",
|
|
710
|
-
__query: { target: "model", name: modelName,
|
|
1513
|
+
__query: { target: "model", name: modelName, op: "subDelete", id, sub, subId },
|
|
711
1514
|
__requestConfig: reqConfig,
|
|
712
1515
|
__service: parentService
|
|
713
1516
|
}
|
|
@@ -718,8 +1521,8 @@ function buildSubDocumentOps(ctx, id, sub) {
|
|
|
718
1521
|
|
|
719
1522
|
// src/services/model-service.ts
|
|
720
1523
|
var ModelService = class extends Service {
|
|
721
|
-
constructor({ axios:
|
|
722
|
-
super(
|
|
1524
|
+
constructor({ axios: axios3, modelName, basePath, queryPath, mutationPath, onSuccess, onFailure, throwOnError }, defaults) {
|
|
1525
|
+
super(axios3, basePath, throwOnError);
|
|
723
1526
|
this._modelName = modelName;
|
|
724
1527
|
this._queryPath = queryPath;
|
|
725
1528
|
this._mutationPath = mutationPath;
|
|
@@ -783,10 +1586,15 @@ var ModelService = class extends Service {
|
|
|
783
1586
|
return processListResult(
|
|
784
1587
|
result,
|
|
785
1588
|
{ includeCount, includeExtraHeaders },
|
|
786
|
-
|
|
1589
|
+
// ARC-21: list items come from existing documents, so mark
|
|
1590
|
+
// them as `_fromExisting=true` even if the server response
|
|
1591
|
+
// (or a custom adapter) strips `_id` — a save on such an item
|
|
1592
|
+
// must throw rather than silently re-create.
|
|
1593
|
+
(item) => Model.create(item, this, void 0, true)
|
|
787
1594
|
);
|
|
788
|
-
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1595
|
+
}).catch(this.handleError).then(ensureListResultCount).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
789
1596
|
{
|
|
1597
|
+
__throwOnError: throwOnError,
|
|
790
1598
|
__op: "list",
|
|
791
1599
|
__query: {
|
|
792
1600
|
target: "model",
|
|
@@ -795,7 +1603,7 @@ var ModelService = class extends Service {
|
|
|
795
1603
|
op: "list",
|
|
796
1604
|
filter: {},
|
|
797
1605
|
args: { skip, limit, page, pageSize },
|
|
798
|
-
options: { skim, includePermissions, includeCount
|
|
1606
|
+
options: { skim, includePermissions, includeCount },
|
|
799
1607
|
sqOptions: sq
|
|
800
1608
|
},
|
|
801
1609
|
__requestConfig: reqConfig,
|
|
@@ -848,12 +1656,18 @@ var ModelService = class extends Service {
|
|
|
848
1656
|
return processListResult(
|
|
849
1657
|
result,
|
|
850
1658
|
{ includeCount, includeExtraHeaders },
|
|
851
|
-
(item) =>
|
|
1659
|
+
(item) => (
|
|
1660
|
+
// ARC-21: listAdvanced items come from existing documents;
|
|
1661
|
+
// mark `_fromExisting=true` so a save cannot silently re-create
|
|
1662
|
+
// when a server response shape drops `_id`.
|
|
1663
|
+
Model.create(item, this, void 0, true)
|
|
1664
|
+
)
|
|
852
1665
|
);
|
|
853
|
-
}).catch(this.handleError).then(
|
|
1666
|
+
}).catch(this.handleError).then(ensureListResultCount).then(
|
|
854
1667
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
855
1668
|
),
|
|
856
1669
|
{
|
|
1670
|
+
__throwOnError: throwOnError,
|
|
857
1671
|
__op: "listAdvanced",
|
|
858
1672
|
__query: {
|
|
859
1673
|
target: "model",
|
|
@@ -862,7 +1676,7 @@ var ModelService = class extends Service {
|
|
|
862
1676
|
op: "list",
|
|
863
1677
|
filter: _filter,
|
|
864
1678
|
args: { select, sort, populate, include, skip, limit, page, pageSize, tasks },
|
|
865
|
-
options: { skim, includePermissions, includeCount,
|
|
1679
|
+
options: { skim, includePermissions, includeCount, populateAccess },
|
|
866
1680
|
sqOptions: sq
|
|
867
1681
|
},
|
|
868
1682
|
__requestConfig: reqConfig,
|
|
@@ -872,14 +1686,25 @@ var ModelService = class extends Service {
|
|
|
872
1686
|
}
|
|
873
1687
|
create(data, options, axiosRequestConfig) {
|
|
874
1688
|
const { includePermissions = this._defaults.createOptions.includePermissions ?? true } = options ?? {};
|
|
875
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
876
|
-
|
|
1689
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1690
|
+
const bulk = Array.isArray(data);
|
|
877
1691
|
return makeRequest(
|
|
878
1692
|
() => this._axios.post(this._basePath, data, mergeConfig3(reqConfig, { params: { include_permissions: includePermissions } })).then(this.handleSuccess).then((result) => {
|
|
879
|
-
|
|
1693
|
+
if (result.success) {
|
|
1694
|
+
if (bulk) {
|
|
1695
|
+
const rows = Array.isArray(result.raw) ? result.raw : [result.raw];
|
|
1696
|
+
result.raw = rows;
|
|
1697
|
+
result.data = rows.map((row) => Model.create(row, this, void 0, true));
|
|
1698
|
+
} else {
|
|
1699
|
+
result.data = Model.create(result.raw, this, void 0, true);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
880
1702
|
return result;
|
|
881
|
-
}).catch(this.handleError).then(
|
|
1703
|
+
}).catch(this.handleError).then(
|
|
1704
|
+
(res) => this._handleCallbacks(res, throwOnError)
|
|
1705
|
+
),
|
|
882
1706
|
{
|
|
1707
|
+
__throwOnError: throwOnError,
|
|
883
1708
|
__op: "create",
|
|
884
1709
|
__query: {
|
|
885
1710
|
target: "model",
|
|
@@ -901,20 +1726,27 @@ var ModelService = class extends Service {
|
|
|
901
1726
|
includePermissions = this._defaults.createAdvancedOptions.includePermissions ?? true,
|
|
902
1727
|
populateAccess = this._defaults.createAdvancedOptions.populateAccess
|
|
903
1728
|
} = options ?? {};
|
|
904
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
905
|
-
|
|
1729
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1730
|
+
const bulk = Array.isArray(data);
|
|
906
1731
|
return makeRequest(
|
|
907
1732
|
() => this._axios.post(
|
|
908
1733
|
`${this._basePath}/${this._mutationPath}`,
|
|
909
1734
|
{ data, select, populate, tasks, options: { includePermissions, populateAccess } },
|
|
910
1735
|
reqConfig
|
|
911
1736
|
).then(this.handleSuccess).then((result) => {
|
|
912
|
-
|
|
1737
|
+
if (result.success) {
|
|
1738
|
+
if (bulk) {
|
|
1739
|
+
const rows = Array.isArray(result.raw) ? result.raw : [result.raw];
|
|
1740
|
+
result.raw = rows;
|
|
1741
|
+
result.data = rows.map((row) => Model.create(row, this, void 0, true));
|
|
1742
|
+
} else {
|
|
1743
|
+
result.data = Model.create(result.raw, this, void 0, true);
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
913
1746
|
return result;
|
|
914
|
-
}).catch(this.handleError).then(
|
|
915
|
-
(res) => this._handleCallbacks(res, throwOnError)
|
|
916
|
-
),
|
|
1747
|
+
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
917
1748
|
{
|
|
1749
|
+
__throwOnError: throwOnError,
|
|
918
1750
|
__op: "createAdvanced",
|
|
919
1751
|
__query: {
|
|
920
1752
|
target: "model",
|
|
@@ -931,15 +1763,24 @@ var ModelService = class extends Service {
|
|
|
931
1763
|
);
|
|
932
1764
|
}
|
|
933
1765
|
upsert(data, options, axiosRequestConfig) {
|
|
934
|
-
const {
|
|
935
|
-
|
|
936
|
-
|
|
1766
|
+
const {
|
|
1767
|
+
returningAll = this._defaults.upsertOptions.returningAll ?? true,
|
|
1768
|
+
includePermissions = this._defaults.upsertOptions.includePermissions ?? true
|
|
1769
|
+
} = options ?? {};
|
|
1770
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
937
1771
|
return makeRequest(
|
|
938
|
-
() => this._axios.put(
|
|
939
|
-
|
|
1772
|
+
() => this._axios.put(
|
|
1773
|
+
this._basePath,
|
|
1774
|
+
data,
|
|
1775
|
+
mergeConfig3(reqConfig, {
|
|
1776
|
+
params: { returning_all: returningAll, include_permissions: includePermissions }
|
|
1777
|
+
})
|
|
1778
|
+
).then(this.handleSuccess).then((result) => {
|
|
1779
|
+
result.data = result.success ? Model.create(result.raw, this, void 0, true) : null;
|
|
940
1780
|
return result;
|
|
941
1781
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
942
1782
|
{
|
|
1783
|
+
__throwOnError: throwOnError,
|
|
943
1784
|
__op: "upsert",
|
|
944
1785
|
__query: {
|
|
945
1786
|
target: "model",
|
|
@@ -947,7 +1788,7 @@ var ModelService = class extends Service {
|
|
|
947
1788
|
model: this._modelName,
|
|
948
1789
|
op: "upsert",
|
|
949
1790
|
data,
|
|
950
|
-
options: { returningAll }
|
|
1791
|
+
options: { returningAll, includePermissions }
|
|
951
1792
|
},
|
|
952
1793
|
__requestConfig: reqConfig,
|
|
953
1794
|
__service: this
|
|
@@ -962,8 +1803,7 @@ var ModelService = class extends Service {
|
|
|
962
1803
|
includePermissions = this._defaults.upsertAdvancedOptions.includePermissions ?? true,
|
|
963
1804
|
populateAccess = this._defaults.upsertAdvancedOptions.populateAccess
|
|
964
1805
|
} = options ?? {};
|
|
965
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
966
|
-
set3(reqConfig, `headers.${CACHE_HEADER}`, "false");
|
|
1806
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
967
1807
|
return makeRequest(
|
|
968
1808
|
() => this._axios.put(
|
|
969
1809
|
`${this._basePath}/${this._mutationPath}`,
|
|
@@ -976,12 +1816,13 @@ var ModelService = class extends Service {
|
|
|
976
1816
|
},
|
|
977
1817
|
reqConfig
|
|
978
1818
|
).then(this.handleSuccess).then((result) => {
|
|
979
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
1819
|
+
result.data = result.success ? Model.create(result.raw, this, void 0, true) : null;
|
|
980
1820
|
return result;
|
|
981
1821
|
}).catch(this.handleError).then(
|
|
982
1822
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
983
1823
|
),
|
|
984
1824
|
{
|
|
1825
|
+
__throwOnError: throwOnError,
|
|
985
1826
|
__op: "upsertAdvanced",
|
|
986
1827
|
__query: {
|
|
987
1828
|
target: "model",
|
|
@@ -998,14 +1839,14 @@ var ModelService = class extends Service {
|
|
|
998
1839
|
);
|
|
999
1840
|
}
|
|
1000
1841
|
delete(identifier, axiosRequestConfig) {
|
|
1001
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1002
|
-
set3(reqConfig, `headers.${CACHE_HEADER}`, "false");
|
|
1842
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1003
1843
|
return makeRequest(
|
|
1004
|
-
() => this._axios.delete(`${this._basePath}/${identifier}`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1005
|
-
result.data = result.raw;
|
|
1844
|
+
() => this._axios.delete(`${this._basePath}/${encodePathSegment(identifier)}`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1845
|
+
if (result.success) result.data = result.raw;
|
|
1006
1846
|
return result;
|
|
1007
1847
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1008
1848
|
{
|
|
1849
|
+
__throwOnError: throwOnError,
|
|
1009
1850
|
__op: "delete",
|
|
1010
1851
|
__query: {
|
|
1011
1852
|
target: "model",
|
|
@@ -1020,15 +1861,17 @@ var ModelService = class extends Service {
|
|
|
1020
1861
|
);
|
|
1021
1862
|
}
|
|
1022
1863
|
new(axiosRequestConfig) {
|
|
1023
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1024
|
-
set3(reqConfig, `headers.${CACHE_HEADER}`, "false");
|
|
1864
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1025
1865
|
return makeRequest(
|
|
1026
1866
|
() => this._axios.get(`${this._basePath}/new`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1027
|
-
|
|
1028
|
-
|
|
1867
|
+
if (result.success) {
|
|
1868
|
+
delete result.raw._id;
|
|
1869
|
+
result.data = Model.create(result.raw, this);
|
|
1870
|
+
}
|
|
1029
1871
|
return result;
|
|
1030
1872
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1031
1873
|
{
|
|
1874
|
+
__throwOnError: throwOnError,
|
|
1032
1875
|
__op: "new",
|
|
1033
1876
|
__query: {
|
|
1034
1877
|
target: "model",
|
|
@@ -1044,11 +1887,12 @@ var ModelService = class extends Service {
|
|
|
1044
1887
|
distinct(field, axiosRequestConfig) {
|
|
1045
1888
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1046
1889
|
return makeRequest(
|
|
1047
|
-
() => this._axios.get(`${this._basePath}/distinct/${field}`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1048
|
-
result.data = result.raw;
|
|
1890
|
+
() => this._axios.get(`${this._basePath}/distinct/${encodePathSegment(field)}`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1891
|
+
if (result.success) result.data = result.raw;
|
|
1049
1892
|
return result;
|
|
1050
1893
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1051
1894
|
{
|
|
1895
|
+
__throwOnError: throwOnError,
|
|
1052
1896
|
__op: "distinct",
|
|
1053
1897
|
__query: {
|
|
1054
1898
|
target: "model",
|
|
@@ -1065,11 +1909,12 @@ var ModelService = class extends Service {
|
|
|
1065
1909
|
distinctAdvanced(field, conditions, axiosRequestConfig) {
|
|
1066
1910
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1067
1911
|
return makeRequest(
|
|
1068
|
-
() => this._axios.post(`${this._basePath}/distinct/${field}`, conditions, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1069
|
-
result.data = result.raw;
|
|
1912
|
+
() => this._axios.post(`${this._basePath}/distinct/${encodePathSegment(field)}`, { filter: conditions }, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1913
|
+
if (result.success) result.data = result.raw;
|
|
1070
1914
|
return result;
|
|
1071
1915
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1072
1916
|
{
|
|
1917
|
+
__throwOnError: throwOnError,
|
|
1073
1918
|
__op: "distinctAdvanced",
|
|
1074
1919
|
__query: {
|
|
1075
1920
|
target: "model",
|
|
@@ -1088,10 +1933,11 @@ var ModelService = class extends Service {
|
|
|
1088
1933
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1089
1934
|
return makeRequest(
|
|
1090
1935
|
() => this._axios.get(`${this._basePath}/count`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1091
|
-
result.data = result.raw;
|
|
1936
|
+
if (result.success) result.data = result.raw;
|
|
1092
1937
|
return result;
|
|
1093
1938
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1094
1939
|
{
|
|
1940
|
+
__throwOnError: throwOnError,
|
|
1095
1941
|
__op: "count",
|
|
1096
1942
|
__query: {
|
|
1097
1943
|
target: "model",
|
|
@@ -1104,23 +1950,22 @@ var ModelService = class extends Service {
|
|
|
1104
1950
|
}
|
|
1105
1951
|
);
|
|
1106
1952
|
}
|
|
1107
|
-
countAdvanced(filter,
|
|
1108
|
-
const { access } = args ?? {};
|
|
1953
|
+
countAdvanced(filter, axiosRequestConfig) {
|
|
1109
1954
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1110
1955
|
return makeRequest(
|
|
1111
|
-
() => this._axios.post(`${this._basePath}/count`, { filter
|
|
1112
|
-
result.data = result.raw;
|
|
1956
|
+
() => this._axios.post(`${this._basePath}/count`, { filter }, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1957
|
+
if (result.success) result.data = result.raw;
|
|
1113
1958
|
return result;
|
|
1114
1959
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1115
1960
|
{
|
|
1961
|
+
__throwOnError: throwOnError,
|
|
1116
1962
|
__op: "countAdvanced",
|
|
1117
1963
|
__query: {
|
|
1118
1964
|
target: "model",
|
|
1119
1965
|
name: this._modelName,
|
|
1120
1966
|
model: this._modelName,
|
|
1121
1967
|
op: "count",
|
|
1122
|
-
filter
|
|
1123
|
-
options: { access }
|
|
1968
|
+
filter
|
|
1124
1969
|
},
|
|
1125
1970
|
__requestConfig: reqConfig,
|
|
1126
1971
|
__service: this
|
|
@@ -1141,15 +1986,16 @@ var ModelService = class extends Service {
|
|
|
1141
1986
|
reqConfig.headers = this.updateHeaders(reqConfig.headers, { ignoreCache });
|
|
1142
1987
|
return makeRequest(
|
|
1143
1988
|
() => this._axios.get(
|
|
1144
|
-
`${this._basePath}/${identifier}`,
|
|
1989
|
+
`${this._basePath}/${encodePathSegment(identifier)}`,
|
|
1145
1990
|
mergeConfig3(reqConfig, {
|
|
1146
1991
|
params: { include_permissions: includePermissions, try_list: tryList }
|
|
1147
1992
|
})
|
|
1148
1993
|
).then(this.handleSuccess).then((result) => {
|
|
1149
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
1994
|
+
result.data = result.success ? Model.create(result.raw, this, identifier, true) : null;
|
|
1150
1995
|
return result;
|
|
1151
1996
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1152
1997
|
{
|
|
1998
|
+
__throwOnError: throwOnError,
|
|
1153
1999
|
__op: "read",
|
|
1154
2000
|
__query: {
|
|
1155
2001
|
target: "model",
|
|
@@ -1185,7 +2031,7 @@ var ModelService = class extends Service {
|
|
|
1185
2031
|
reqConfig.headers = this.updateHeaders(reqConfig.headers, { ignoreCache });
|
|
1186
2032
|
return makeRequest(
|
|
1187
2033
|
() => this._axios.post(
|
|
1188
|
-
`${this._basePath}/${this._queryPath}/${identifier}`,
|
|
2034
|
+
`${this._basePath}/${this._queryPath}/${encodePathSegment(identifier)}`,
|
|
1189
2035
|
{
|
|
1190
2036
|
select,
|
|
1191
2037
|
populate,
|
|
@@ -1195,12 +2041,13 @@ var ModelService = class extends Service {
|
|
|
1195
2041
|
},
|
|
1196
2042
|
reqConfig
|
|
1197
2043
|
).then(this.handleSuccess).then((result) => {
|
|
1198
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
2044
|
+
result.data = result.success ? Model.create(result.raw, this, identifier, true) : null;
|
|
1199
2045
|
return result;
|
|
1200
2046
|
}).catch(this.handleError).then(
|
|
1201
2047
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1202
2048
|
),
|
|
1203
2049
|
{
|
|
2050
|
+
__throwOnError: throwOnError,
|
|
1204
2051
|
__op: "readAdvanced",
|
|
1205
2052
|
__query: {
|
|
1206
2053
|
target: "model",
|
|
@@ -1250,12 +2097,13 @@ var ModelService = class extends Service {
|
|
|
1250
2097
|
},
|
|
1251
2098
|
reqConfig
|
|
1252
2099
|
).then(this.handleSuccess).then((result) => {
|
|
1253
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
2100
|
+
result.data = result.success ? Model.create(result.raw, this, void 0, true) : null;
|
|
1254
2101
|
return result;
|
|
1255
2102
|
}).catch(this.handleError).then(
|
|
1256
2103
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1257
2104
|
),
|
|
1258
2105
|
{
|
|
2106
|
+
__throwOnError: throwOnError,
|
|
1259
2107
|
__op: "readAdvancedFilter",
|
|
1260
2108
|
__query: {
|
|
1261
2109
|
target: "model",
|
|
@@ -1273,19 +2121,24 @@ var ModelService = class extends Service {
|
|
|
1273
2121
|
);
|
|
1274
2122
|
}
|
|
1275
2123
|
update(identifier, data, options, axiosRequestConfig) {
|
|
1276
|
-
const {
|
|
1277
|
-
|
|
1278
|
-
|
|
2124
|
+
const {
|
|
2125
|
+
returningAll = this._defaults.updateOptions.returningAll ?? true,
|
|
2126
|
+
includePermissions = this._defaults.updateOptions.includePermissions ?? true
|
|
2127
|
+
} = options ?? {};
|
|
2128
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1279
2129
|
return makeRequest(
|
|
1280
2130
|
() => this._axios.patch(
|
|
1281
|
-
`${this._basePath}/${identifier}`,
|
|
2131
|
+
`${this._basePath}/${encodePathSegment(identifier)}`,
|
|
1282
2132
|
data,
|
|
1283
|
-
mergeConfig3(reqConfig, {
|
|
2133
|
+
mergeConfig3(reqConfig, {
|
|
2134
|
+
params: { returning_all: returningAll, include_permissions: includePermissions }
|
|
2135
|
+
})
|
|
1284
2136
|
).then(this.handleSuccess).then((result) => {
|
|
1285
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
2137
|
+
result.data = result.success ? Model.create(result.raw, this, void 0, true) : null;
|
|
1286
2138
|
return result;
|
|
1287
2139
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1288
2140
|
{
|
|
2141
|
+
__throwOnError: throwOnError,
|
|
1289
2142
|
__op: "update",
|
|
1290
2143
|
__query: {
|
|
1291
2144
|
target: "model",
|
|
@@ -1294,7 +2147,7 @@ var ModelService = class extends Service {
|
|
|
1294
2147
|
op: "update",
|
|
1295
2148
|
id: identifier,
|
|
1296
2149
|
data,
|
|
1297
|
-
options: { returningAll }
|
|
2150
|
+
options: { returningAll, includePermissions }
|
|
1298
2151
|
},
|
|
1299
2152
|
__requestConfig: reqConfig,
|
|
1300
2153
|
__service: this
|
|
@@ -1309,11 +2162,10 @@ var ModelService = class extends Service {
|
|
|
1309
2162
|
includePermissions = this._defaults.updateAdvancedOptions.includePermissions ?? true,
|
|
1310
2163
|
populateAccess = this._defaults.updateAdvancedOptions.populateAccess
|
|
1311
2164
|
} = options ?? {};
|
|
1312
|
-
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1313
|
-
set3(reqConfig, `headers.${CACHE_HEADER}`, "false");
|
|
2165
|
+
const { throwOnError, ...reqConfig } = cloneConfigWithCacheBypass(axiosRequestConfig ?? {});
|
|
1314
2166
|
return makeRequest(
|
|
1315
2167
|
() => this._axios.patch(
|
|
1316
|
-
`${this._basePath}/${this._mutationPath}/${identifier}`,
|
|
2168
|
+
`${this._basePath}/${this._mutationPath}/${encodePathSegment(identifier)}`,
|
|
1317
2169
|
{
|
|
1318
2170
|
data,
|
|
1319
2171
|
select,
|
|
@@ -1323,12 +2175,13 @@ var ModelService = class extends Service {
|
|
|
1323
2175
|
},
|
|
1324
2176
|
reqConfig
|
|
1325
2177
|
).then(this.handleSuccess).then((result) => {
|
|
1326
|
-
result.data = result.success ? Model.create(result.raw, this) : null;
|
|
2178
|
+
result.data = result.success ? Model.create(result.raw, this, void 0, true) : null;
|
|
1327
2179
|
return result;
|
|
1328
2180
|
}).catch(this.handleError).then(
|
|
1329
2181
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1330
2182
|
),
|
|
1331
2183
|
{
|
|
2184
|
+
__throwOnError: throwOnError,
|
|
1332
2185
|
__op: "updateAdvanced",
|
|
1333
2186
|
__query: {
|
|
1334
2187
|
target: "model",
|
|
@@ -1377,8 +2230,8 @@ var ModelService = class extends Service {
|
|
|
1377
2230
|
// src/services/data-service.ts
|
|
1378
2231
|
import { mergeConfig as mergeConfig4 } from "axios";
|
|
1379
2232
|
var DataService = class extends Service {
|
|
1380
|
-
constructor({ axios:
|
|
1381
|
-
super(
|
|
2233
|
+
constructor({ axios: axios3, dataName, basePath, queryPath, onSuccess, onFailure, throwOnError }, defaults) {
|
|
2234
|
+
super(axios3, basePath, throwOnError);
|
|
1382
2235
|
this._dataName = dataName;
|
|
1383
2236
|
this._queryPath = queryPath;
|
|
1384
2237
|
this._defaults = defaults ?? {};
|
|
@@ -1404,7 +2257,6 @@ var DataService = class extends Service {
|
|
|
1404
2257
|
pageSize = this._defaults.listArgs.pageSize
|
|
1405
2258
|
} = args ?? {};
|
|
1406
2259
|
const {
|
|
1407
|
-
includePermissions = this._defaults.listOptions.includePermissions ?? false,
|
|
1408
2260
|
includeCount = this._defaults.listOptions.includeCount ?? false,
|
|
1409
2261
|
includeExtraHeaders = this._defaults.listOptions.includeExtraHeaders ?? false,
|
|
1410
2262
|
ignoreCache = this._defaults.listOptions.ignoreCache ?? false
|
|
@@ -1420,15 +2272,15 @@ var DataService = class extends Service {
|
|
|
1420
2272
|
limit,
|
|
1421
2273
|
page,
|
|
1422
2274
|
page_size: pageSize,
|
|
1423
|
-
include_permissions: includePermissions,
|
|
1424
2275
|
include_count: includeCount,
|
|
1425
2276
|
include_extra_headers: includeExtraHeaders
|
|
1426
2277
|
}
|
|
1427
2278
|
})
|
|
1428
2279
|
).then(this.handleSuccess).then((result) => {
|
|
1429
2280
|
return processListResult(result, { includeCount, includeExtraHeaders });
|
|
1430
|
-
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
2281
|
+
}).catch(this.handleError).then(ensureListResultCount).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1431
2282
|
{
|
|
2283
|
+
__throwOnError: throwOnError,
|
|
1432
2284
|
__op: "list",
|
|
1433
2285
|
__query: {
|
|
1434
2286
|
target: "data",
|
|
@@ -1436,7 +2288,7 @@ var DataService = class extends Service {
|
|
|
1436
2288
|
op: "list",
|
|
1437
2289
|
filter: {},
|
|
1438
2290
|
args: { skip, limit, page, pageSize },
|
|
1439
|
-
options: {
|
|
2291
|
+
options: { includeCount }
|
|
1440
2292
|
},
|
|
1441
2293
|
__requestConfig: reqConfig,
|
|
1442
2294
|
__service: this
|
|
@@ -1453,7 +2305,6 @@ var DataService = class extends Service {
|
|
|
1453
2305
|
} = args ?? {};
|
|
1454
2306
|
const select = args?.select ?? this._defaults.listAdvancedArgs.select;
|
|
1455
2307
|
const {
|
|
1456
|
-
includePermissions = this._defaults.listAdvancedOptions.includePermissions ?? false,
|
|
1457
2308
|
includeCount = this._defaults.listAdvancedOptions.includeCount ?? false,
|
|
1458
2309
|
includeExtraHeaders = this._defaults.listAdvancedOptions.includeExtraHeaders ?? false,
|
|
1459
2310
|
ignoreCache = this._defaults.listAdvancedOptions.ignoreCache ?? false
|
|
@@ -1472,7 +2323,7 @@ var DataService = class extends Service {
|
|
|
1472
2323
|
limit,
|
|
1473
2324
|
page,
|
|
1474
2325
|
pageSize,
|
|
1475
|
-
options: {
|
|
2326
|
+
options: { includeCount, includeExtraHeaders }
|
|
1476
2327
|
},
|
|
1477
2328
|
reqConfig
|
|
1478
2329
|
).then(this.handleSuccess).then((result) => {
|
|
@@ -1480,10 +2331,11 @@ var DataService = class extends Service {
|
|
|
1480
2331
|
includeCount,
|
|
1481
2332
|
includeExtraHeaders
|
|
1482
2333
|
});
|
|
1483
|
-
}).catch(this.handleError).then(
|
|
2334
|
+
}).catch(this.handleError).then(ensureListResultCount).then(
|
|
1484
2335
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1485
2336
|
),
|
|
1486
2337
|
{
|
|
2338
|
+
__throwOnError: throwOnError,
|
|
1487
2339
|
__op: "listAdvanced",
|
|
1488
2340
|
__query: {
|
|
1489
2341
|
target: "data",
|
|
@@ -1491,7 +2343,7 @@ var DataService = class extends Service {
|
|
|
1491
2343
|
op: "list",
|
|
1492
2344
|
filter: _filter,
|
|
1493
2345
|
args: { select, sort, skip, limit, page, pageSize },
|
|
1494
|
-
options: {
|
|
2346
|
+
options: { includeCount }
|
|
1495
2347
|
},
|
|
1496
2348
|
__requestConfig: reqConfig,
|
|
1497
2349
|
__service: this
|
|
@@ -1502,23 +2354,16 @@ var DataService = class extends Service {
|
|
|
1502
2354
|
// Document operations
|
|
1503
2355
|
// ---------------------------------------------------------------------------
|
|
1504
2356
|
read(identifier, options, axiosRequestConfig) {
|
|
1505
|
-
const {
|
|
1506
|
-
includePermissions = this._defaults.readOptions.includePermissions ?? true,
|
|
1507
|
-
ignoreCache = this._defaults.readOptions.ignoreCache ?? false
|
|
1508
|
-
} = options ?? {};
|
|
2357
|
+
const { ignoreCache = this._defaults.readOptions.ignoreCache ?? false } = options ?? {};
|
|
1509
2358
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1510
2359
|
reqConfig.headers = this.updateHeaders(reqConfig.headers, { ignoreCache });
|
|
1511
2360
|
return makeRequest(
|
|
1512
|
-
() => this._axios.get(
|
|
1513
|
-
|
|
1514
|
-
mergeConfig4(reqConfig, {
|
|
1515
|
-
params: { include_permissions: includePermissions }
|
|
1516
|
-
})
|
|
1517
|
-
).then(this.handleSuccess).then((result) => {
|
|
1518
|
-
result.data = result.raw;
|
|
2361
|
+
() => this._axios.get(`${this._basePath}/${encodePathSegment(identifier)}`, reqConfig).then(this.handleSuccess).then((result) => {
|
|
2362
|
+
if (result.success) result.data = result.raw;
|
|
1519
2363
|
return result;
|
|
1520
2364
|
}).catch(this.handleError).then((res) => this._handleCallbacks(res, throwOnError)),
|
|
1521
2365
|
{
|
|
2366
|
+
__throwOnError: throwOnError,
|
|
1522
2367
|
__op: "read",
|
|
1523
2368
|
__query: {
|
|
1524
2369
|
target: "data",
|
|
@@ -1526,7 +2371,7 @@ var DataService = class extends Service {
|
|
|
1526
2371
|
op: "read",
|
|
1527
2372
|
id: identifier,
|
|
1528
2373
|
args: {},
|
|
1529
|
-
options: {
|
|
2374
|
+
options: {}
|
|
1530
2375
|
},
|
|
1531
2376
|
__requestConfig: reqConfig,
|
|
1532
2377
|
__service: this
|
|
@@ -1534,19 +2379,19 @@ var DataService = class extends Service {
|
|
|
1534
2379
|
);
|
|
1535
2380
|
}
|
|
1536
2381
|
readAdvanced(identifier, args, options, axiosRequestConfig) {
|
|
1537
|
-
const { ignoreCache = this._defaults.readAdvancedArgs.ignoreCache ?? false } = args ?? {};
|
|
1538
2382
|
const select = args?.select ?? this._defaults.readAdvancedArgs.select;
|
|
1539
|
-
const {
|
|
2383
|
+
const { ignoreCache = this._defaults.readAdvancedOptions.ignoreCache ?? false } = options ?? {};
|
|
1540
2384
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1541
2385
|
reqConfig.headers = this.updateHeaders(reqConfig.headers, { ignoreCache });
|
|
1542
2386
|
return makeRequest(
|
|
1543
|
-
() => this._axios.post(`${this._basePath}/${this._queryPath}/${identifier}`, { select }, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1544
|
-
result.data = result.raw;
|
|
2387
|
+
() => this._axios.post(`${this._basePath}/${this._queryPath}/${encodePathSegment(identifier)}`, { select }, reqConfig).then(this.handleSuccess).then((result) => {
|
|
2388
|
+
if (result.success) result.data = result.raw;
|
|
1545
2389
|
return result;
|
|
1546
2390
|
}).catch(this.handleError).then(
|
|
1547
2391
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1548
2392
|
),
|
|
1549
2393
|
{
|
|
2394
|
+
__throwOnError: throwOnError,
|
|
1550
2395
|
__op: "readAdvanced",
|
|
1551
2396
|
__query: {
|
|
1552
2397
|
target: "data",
|
|
@@ -1554,7 +2399,7 @@ var DataService = class extends Service {
|
|
|
1554
2399
|
op: "read",
|
|
1555
2400
|
id: identifier,
|
|
1556
2401
|
args: { select },
|
|
1557
|
-
options: {
|
|
2402
|
+
options: {}
|
|
1558
2403
|
},
|
|
1559
2404
|
__requestConfig: reqConfig,
|
|
1560
2405
|
__service: this
|
|
@@ -1563,19 +2408,19 @@ var DataService = class extends Service {
|
|
|
1563
2408
|
}
|
|
1564
2409
|
readAdvancedFilter(filter, args, options, axiosRequestConfig) {
|
|
1565
2410
|
const select = args?.select ?? this._defaults.readAdvancedArgs.select;
|
|
1566
|
-
const { ignoreCache = this._defaults.
|
|
1567
|
-
const { includePermissions = this._defaults.readAdvancedOptions.includePermissions ?? true } = options ?? {};
|
|
2411
|
+
const { ignoreCache = this._defaults.readAdvancedOptions.ignoreCache ?? false } = options ?? {};
|
|
1568
2412
|
const { throwOnError, ...reqConfig } = axiosRequestConfig ?? {};
|
|
1569
2413
|
reqConfig.headers = this.updateHeaders(reqConfig.headers, { ignoreCache });
|
|
1570
2414
|
const _filter = replaceSubQuery(filter);
|
|
1571
2415
|
return makeRequest(
|
|
1572
2416
|
() => this._axios.post(`${this._basePath}/${this._queryPath}/__filter`, { filter: _filter, select }, reqConfig).then(this.handleSuccess).then((result) => {
|
|
1573
|
-
result.data = result.raw;
|
|
2417
|
+
if (result.success) result.data = result.raw;
|
|
1574
2418
|
return result;
|
|
1575
2419
|
}).catch(this.handleError).then(
|
|
1576
2420
|
(res) => this._handleCallbacks(res, throwOnError)
|
|
1577
2421
|
),
|
|
1578
2422
|
{
|
|
2423
|
+
__throwOnError: throwOnError,
|
|
1579
2424
|
__op: "readAdvancedFilter",
|
|
1580
2425
|
__query: {
|
|
1581
2426
|
target: "data",
|
|
@@ -1583,7 +2428,7 @@ var DataService = class extends Service {
|
|
|
1583
2428
|
op: "read",
|
|
1584
2429
|
filter: _filter,
|
|
1585
2430
|
args: { select },
|
|
1586
|
-
options: {
|
|
2431
|
+
options: {}
|
|
1587
2432
|
},
|
|
1588
2433
|
__requestConfig: reqConfig,
|
|
1589
2434
|
__service: this
|
|
@@ -1592,132 +2437,8 @@ var DataService = class extends Service {
|
|
|
1592
2437
|
}
|
|
1593
2438
|
};
|
|
1594
2439
|
|
|
1595
|
-
// src/services/
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
// src/services/cache-utils.ts
|
|
1599
|
-
import { AxiosHeaders as AxiosHeaders2 } from "axios";
|
|
1600
|
-
import { omitBy } from "@web-ts-toolkit/utils";
|
|
1601
|
-
var normalizeConfigValue = (value) => {
|
|
1602
|
-
if (value == null) return value;
|
|
1603
|
-
if (value instanceof AxiosHeaders2) {
|
|
1604
|
-
return normalizeConfigValue(value.toJSON());
|
|
1605
|
-
}
|
|
1606
|
-
if (Array.isArray(value)) {
|
|
1607
|
-
return value.map((item) => normalizeConfigValue(item));
|
|
1608
|
-
}
|
|
1609
|
-
if (typeof value === "object") {
|
|
1610
|
-
return Object.entries(omitBy(value, (item) => item === void 0)).sort(([left], [right]) => left.localeCompare(right)).reduce((acc, [key, item]) => {
|
|
1611
|
-
acc[key] = normalizeConfigValue(item);
|
|
1612
|
-
return acc;
|
|
1613
|
-
}, {});
|
|
1614
|
-
}
|
|
1615
|
-
return value;
|
|
1616
|
-
};
|
|
1617
|
-
|
|
1618
|
-
// src/services/interceptors.ts
|
|
1619
|
-
var SimpleCache = class {
|
|
1620
|
-
constructor() {
|
|
1621
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
1622
|
-
this.timers = /* @__PURE__ */ new Map();
|
|
1623
|
-
}
|
|
1624
|
-
set(key, value, ttl) {
|
|
1625
|
-
this.cache.set(key, value);
|
|
1626
|
-
if (ttl && ttl > 0) {
|
|
1627
|
-
const existing = this.timers.get(key);
|
|
1628
|
-
if (existing) clearTimeout(existing);
|
|
1629
|
-
this.timers.set(
|
|
1630
|
-
key,
|
|
1631
|
-
setTimeout(() => {
|
|
1632
|
-
this.cache.delete(key);
|
|
1633
|
-
this.timers.delete(key);
|
|
1634
|
-
}, ttl)
|
|
1635
|
-
);
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
get(key) {
|
|
1639
|
-
return this.cache.get(key);
|
|
1640
|
-
}
|
|
1641
|
-
has(key) {
|
|
1642
|
-
return this.cache.has(key);
|
|
1643
|
-
}
|
|
1644
|
-
delete(key) {
|
|
1645
|
-
const timer = this.timers.get(key);
|
|
1646
|
-
if (timer) {
|
|
1647
|
-
clearTimeout(timer);
|
|
1648
|
-
this.timers.delete(key);
|
|
1649
|
-
}
|
|
1650
|
-
return this.cache.delete(key);
|
|
1651
|
-
}
|
|
1652
|
-
};
|
|
1653
|
-
var IGNORED_CACHE_HEADERS = /* @__PURE__ */ new Set([
|
|
1654
|
-
"accept",
|
|
1655
|
-
"accept-encoding",
|
|
1656
|
-
"cache-control",
|
|
1657
|
-
"connection",
|
|
1658
|
-
"content-length",
|
|
1659
|
-
"content-type",
|
|
1660
|
-
"expires",
|
|
1661
|
-
"host",
|
|
1662
|
-
"pragma",
|
|
1663
|
-
"user-agent"
|
|
1664
|
-
]);
|
|
1665
|
-
var serializeHeaders = (headers) => {
|
|
1666
|
-
const resolvedHeaders = headers instanceof AxiosHeaders3 ? headers.toJSON() : headers;
|
|
1667
|
-
const normalizedHeaders = Object.entries(resolvedHeaders ?? {}).filter(([key, value]) => {
|
|
1668
|
-
const normalizedKey = key.toLowerCase();
|
|
1669
|
-
return normalizedKey !== CACHE_HEADER.toLowerCase() && !IGNORED_CACHE_HEADERS.has(normalizedKey) && value !== void 0;
|
|
1670
|
-
}).reduce((acc, [key, value]) => {
|
|
1671
|
-
acc[key.toLowerCase()] = value;
|
|
1672
|
-
return acc;
|
|
1673
|
-
}, {});
|
|
1674
|
-
return JSON.stringify(normalizeConfigValue(normalizedHeaders));
|
|
1675
|
-
};
|
|
1676
|
-
function generateCacheKey(config) {
|
|
1677
|
-
const key = `${config.baseURL}/${config.url}_${config.method}_${generateParamKey(config.params)}_${generateDataKey(
|
|
1678
|
-
config.data
|
|
1679
|
-
)}_${serializeHeaders(config.headers)}`;
|
|
1680
|
-
return encodeURI(key);
|
|
1681
|
-
}
|
|
1682
|
-
function generateParamKey(params) {
|
|
1683
|
-
if (!params) return "";
|
|
1684
|
-
return JSON.stringify(normalizeConfigValue(params));
|
|
1685
|
-
}
|
|
1686
|
-
function generateDataKey(data) {
|
|
1687
|
-
if (!data) return "";
|
|
1688
|
-
return typeof data === "string" ? data : JSON.stringify(normalizeConfigValue(data));
|
|
1689
|
-
}
|
|
1690
|
-
function useCacheInterceptors(instance, cacheTTL) {
|
|
1691
|
-
const store = new SimpleCache();
|
|
1692
|
-
instance.interceptors.request.use(
|
|
1693
|
-
async (config) => {
|
|
1694
|
-
if (config.headers[CACHE_HEADER] === "false") return config;
|
|
1695
|
-
const key = generateCacheKey(config);
|
|
1696
|
-
const cachedResponse = store.get(key);
|
|
1697
|
-
if (!cachedResponse) {
|
|
1698
|
-
return config;
|
|
1699
|
-
}
|
|
1700
|
-
config.adapter = async (_config) => {
|
|
1701
|
-
return {
|
|
1702
|
-
...cachedResponse,
|
|
1703
|
-
config: _config,
|
|
1704
|
-
headers: { ...cachedResponse.headers, [CACHE_HEADER]: "true" }
|
|
1705
|
-
};
|
|
1706
|
-
};
|
|
1707
|
-
return config;
|
|
1708
|
-
},
|
|
1709
|
-
(error) => Promise.reject(error)
|
|
1710
|
-
);
|
|
1711
|
-
instance.interceptors.response.use(
|
|
1712
|
-
(response) => {
|
|
1713
|
-
if (response.config.headers[CACHE_HEADER] === "false") return response;
|
|
1714
|
-
const key = generateCacheKey(response.config);
|
|
1715
|
-
store.set(key, response, cacheTTL);
|
|
1716
|
-
return response;
|
|
1717
|
-
},
|
|
1718
|
-
(error) => Promise.reject(error)
|
|
1719
|
-
);
|
|
1720
|
-
}
|
|
2440
|
+
// src/services/symbols.ts
|
|
2441
|
+
var ADAPTER_ID_KEY = /* @__PURE__ */ Symbol("adapterId");
|
|
1721
2442
|
|
|
1722
2443
|
// src/adapter.ts
|
|
1723
2444
|
var defaultAxiosConfig = Object.freeze({
|
|
@@ -1730,7 +2451,12 @@ var defaultAxiosConfig = Object.freeze({
|
|
|
1730
2451
|
Expires: "0"
|
|
1731
2452
|
}
|
|
1732
2453
|
});
|
|
1733
|
-
var
|
|
2454
|
+
var noopCacheController = {
|
|
2455
|
+
clear: () => {
|
|
2456
|
+
},
|
|
2457
|
+
dispose: () => {
|
|
2458
|
+
}
|
|
2459
|
+
};
|
|
1734
2460
|
var serializeRequestConfig = (config) => JSON.stringify(normalizeConfigValue(config ?? {}));
|
|
1735
2461
|
var isObjectRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
1736
2462
|
var mergeServiceDefaults = (adapterDefaults, serviceDefaults) => {
|
|
@@ -1755,20 +2481,39 @@ var mergeServiceDefaults = (adapterDefaults, serviceDefaults) => {
|
|
|
1755
2481
|
};
|
|
1756
2482
|
function createAdapter(axiosConfig, adapterOptions) {
|
|
1757
2483
|
const merged = mergeConfig5(defaultAxiosConfig, axiosConfig ?? {});
|
|
1758
|
-
const instance =
|
|
2484
|
+
const instance = axios2.create(merged);
|
|
1759
2485
|
const {
|
|
1760
2486
|
rootRouterPath = "root",
|
|
1761
2487
|
onSuccess: onSuccessRoot,
|
|
1762
2488
|
onFailure: onFailureRoot,
|
|
1763
2489
|
throwOnError: throwOnErrorRoot,
|
|
1764
2490
|
cacheTTL = 0,
|
|
2491
|
+
cachePartition,
|
|
2492
|
+
cacheCapacity,
|
|
1765
2493
|
modelDefaults: adapterModelDefaults,
|
|
1766
2494
|
dataDefaults: adapterDataDefaults
|
|
1767
2495
|
} = adapterOptions ?? {};
|
|
1768
|
-
|
|
2496
|
+
const cacheController = cacheTTL > 0 ? useCacheInterceptors(instance, {
|
|
2497
|
+
ttl: cacheTTL,
|
|
2498
|
+
capacity: cacheCapacity,
|
|
2499
|
+
withCredentialsDefault: Boolean(instance.defaults.withCredentials),
|
|
2500
|
+
partitionForRequest: cachePartition
|
|
2501
|
+
}) : noopCacheController;
|
|
1769
2502
|
const wraps = createWrapHelper(instance);
|
|
2503
|
+
const adapterId = /* @__PURE__ */ Symbol("adapter");
|
|
2504
|
+
const stampAdapterId = (service) => {
|
|
2505
|
+
Object.defineProperty(service, ADAPTER_ID_KEY, {
|
|
2506
|
+
value: adapterId,
|
|
2507
|
+
enumerable: false,
|
|
2508
|
+
writable: false,
|
|
2509
|
+
configurable: false
|
|
2510
|
+
});
|
|
2511
|
+
return service;
|
|
2512
|
+
};
|
|
1770
2513
|
return Object.freeze({
|
|
1771
2514
|
axios: instance,
|
|
2515
|
+
clearCache: cacheController.clear,
|
|
2516
|
+
disposeCache: cacheController.dispose,
|
|
1772
2517
|
createModelService: ({
|
|
1773
2518
|
modelName,
|
|
1774
2519
|
basePath,
|
|
@@ -1778,7 +2523,7 @@ function createAdapter(axiosConfig, adapterOptions) {
|
|
|
1778
2523
|
onFailure,
|
|
1779
2524
|
throwOnError
|
|
1780
2525
|
}, defaults) => {
|
|
1781
|
-
|
|
2526
|
+
const service = new ModelService(
|
|
1782
2527
|
{
|
|
1783
2528
|
axios: instance,
|
|
1784
2529
|
modelName,
|
|
@@ -1791,9 +2536,10 @@ function createAdapter(axiosConfig, adapterOptions) {
|
|
|
1791
2536
|
},
|
|
1792
2537
|
mergeServiceDefaults(adapterModelDefaults, defaults)
|
|
1793
2538
|
);
|
|
2539
|
+
return stampAdapterId(service);
|
|
1794
2540
|
},
|
|
1795
2541
|
createDataService: ({ dataName, basePath, queryPath = "__query", onSuccess, onFailure, throwOnError }, defaults) => {
|
|
1796
|
-
|
|
2542
|
+
const service = new DataService(
|
|
1797
2543
|
{
|
|
1798
2544
|
axios: instance,
|
|
1799
2545
|
dataName,
|
|
@@ -1805,6 +2551,7 @@ function createAdapter(axiosConfig, adapterOptions) {
|
|
|
1805
2551
|
},
|
|
1806
2552
|
mergeServiceDefaults(adapterDataDefaults, defaults)
|
|
1807
2553
|
);
|
|
2554
|
+
return stampAdapterId(service);
|
|
1808
2555
|
},
|
|
1809
2556
|
wrapGet: wraps.wrapGet,
|
|
1810
2557
|
wrapPost: wraps.wrapPost,
|
|
@@ -1814,55 +2561,72 @@ function createAdapter(axiosConfig, adapterOptions) {
|
|
|
1814
2561
|
group: async (...proms) => {
|
|
1815
2562
|
let sharedConfig;
|
|
1816
2563
|
let sharedConfigKey;
|
|
2564
|
+
let groupThrowOnError;
|
|
1817
2565
|
const defs = proms.map((prom, index) => {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
2566
|
+
const service = prom.__service;
|
|
2567
|
+
if (!service || service[ADAPTER_ID_KEY] !== adapterId) {
|
|
2568
|
+
throw new Error(
|
|
2569
|
+
"Cannot group a request owned by a different adapter; create the request from this adapter's services"
|
|
2570
|
+
);
|
|
2571
|
+
}
|
|
2572
|
+
if (groupThrowOnError != null && groupThrowOnError !== prom.__throwOnError) {
|
|
2573
|
+
throw new Error("Grouped requests must share the same effective throwOnError policy");
|
|
2574
|
+
}
|
|
2575
|
+
groupThrowOnError = prom.__throwOnError;
|
|
2576
|
+
const configKey = serializeRequestConfig(prom.__requestConfig);
|
|
2577
|
+
if (sharedConfigKey != null && sharedConfigKey !== configKey) {
|
|
2578
|
+
throw new Error("Grouped requests must share the same axios request config");
|
|
1825
2579
|
}
|
|
2580
|
+
sharedConfig = prom.__requestConfig ?? {};
|
|
2581
|
+
sharedConfigKey = configKey;
|
|
1826
2582
|
const query = { ...prom.__query };
|
|
2583
|
+
if (query.target === "model") {
|
|
2584
|
+
delete query.model;
|
|
2585
|
+
}
|
|
1827
2586
|
if (prom.__query.order == null) {
|
|
1828
2587
|
query.order = index;
|
|
1829
2588
|
}
|
|
1830
2589
|
return query;
|
|
1831
2590
|
});
|
|
1832
|
-
const
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
_data = castArray(result2.data).map((item) => Model.create(item, modelService));
|
|
1850
|
-
}
|
|
1851
|
-
} else if (result2.kind === "single" && ["new", "read", "update", "upsert"].includes(op)) {
|
|
1852
|
-
_data = Model.create(result2.data, modelService);
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
return {
|
|
1856
|
-
success,
|
|
1857
|
-
raw: _raw,
|
|
1858
|
-
data: _data,
|
|
2591
|
+
const groupOwner = /* @__PURE__ */ Symbol("group");
|
|
2592
|
+
const claimed = [];
|
|
2593
|
+
try {
|
|
2594
|
+
for (const prom of proms) {
|
|
2595
|
+
claimLazyRequest(prom, "grouped", groupOwner);
|
|
2596
|
+
claimed.push(prom);
|
|
2597
|
+
}
|
|
2598
|
+
} catch (error) {
|
|
2599
|
+
for (const prom of claimed) {
|
|
2600
|
+
releaseLazyRequestClaim(prom, groupOwner);
|
|
2601
|
+
}
|
|
2602
|
+
throw error;
|
|
2603
|
+
}
|
|
2604
|
+
const result = await instance.post(rootRouterPath, defs, sharedConfig ?? {}).then(
|
|
2605
|
+
(res) => {
|
|
2606
|
+
const rawEntries = res.data.map(({ result: result2, message, statusCode, op }) => ({
|
|
2607
|
+
result: result2,
|
|
1859
2608
|
message,
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
2609
|
+
statusCode,
|
|
2610
|
+
op
|
|
2611
|
+
}));
|
|
2612
|
+
const finalized = rawEntries.map(
|
|
2613
|
+
(rawEntry, index) => finalizeRootEntry(proms[index].__query, rawEntry, {}, proms[index].__service)
|
|
2614
|
+
);
|
|
2615
|
+
return applyGroupCallbacks(
|
|
2616
|
+
finalized,
|
|
2617
|
+
proms.map((p) => p.__service),
|
|
2618
|
+
groupThrowOnError ?? false
|
|
2619
|
+
);
|
|
2620
|
+
},
|
|
2621
|
+
(error) => {
|
|
2622
|
+
const failures = proms.map((prom) => finalizeRootTransportFailure(prom.__query, error));
|
|
2623
|
+
return applyGroupCallbacks(
|
|
2624
|
+
failures,
|
|
2625
|
+
proms.map((p) => p.__service),
|
|
2626
|
+
groupThrowOnError ?? false
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
);
|
|
1866
2630
|
return result;
|
|
1867
2631
|
}
|
|
1868
2632
|
});
|
|
@@ -1886,6 +2650,7 @@ function removeItemById(items, targetItem) {
|
|
|
1886
2650
|
export {
|
|
1887
2651
|
CustomHeaders,
|
|
1888
2652
|
DataService,
|
|
2653
|
+
MissingPersistenceIdentityError,
|
|
1889
2654
|
Model,
|
|
1890
2655
|
ModelService,
|
|
1891
2656
|
Service,
|