@ember-data-mirror/store 5.4.0-alpha.63 → 5.4.0-alpha.70
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/addon-main.cjs +5 -0
- package/dist/-private.js +1 -0
- package/{addon/cache-handler-Cm55UqNi.js → dist/cache-handler-BCWOzbbB.js} +956 -598
- package/dist/cache-handler-BCWOzbbB.js.map +1 -0
- package/dist/index.js +4 -0
- package/{addon → dist}/index.js.map +1 -1
- package/dist/types.js +0 -0
- package/dist/types.js.map +1 -0
- package/package.json +31 -43
- package/unstable-preview-types/-private/cache-handler.d.ts +7 -4
- package/unstable-preview-types/-private/cache-handler.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/cache-utils.d.ts +3 -3
- package/unstable-preview-types/-private/caches/cache-utils.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/identifier-cache.d.ts +1 -2
- package/unstable-preview-types/-private/caches/identifier-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/instance-cache.d.ts +3 -5
- package/unstable-preview-types/-private/caches/instance-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/document.d.ts +7 -7
- package/unstable-preview-types/-private/document.d.ts.map +1 -1
- package/unstable-preview-types/-private/legacy-model-support/record-reference.d.ts +2 -2
- package/unstable-preview-types/-private/legacy-model-support/record-reference.d.ts.map +1 -1
- package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts +6 -6
- package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts +5 -3
- package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/cache-manager.d.ts +2 -3
- package/unstable-preview-types/-private/managers/cache-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/notification-manager.d.ts +2 -4
- package/unstable-preview-types/-private/managers/notification-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/record-array-manager.d.ts +5 -5
- package/unstable-preview-types/-private/managers/record-array-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/network/request-cache.d.ts +4 -4
- package/unstable-preview-types/-private/network/request-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts +22 -17
- package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts.map +1 -1
- package/unstable-preview-types/-private/store-service.d.ts +160 -195
- package/unstable-preview-types/-private/store-service.d.ts.map +1 -1
- package/unstable-preview-types/-private/utils/coerce-id.d.ts +2 -2
- package/unstable-preview-types/-private/utils/coerce-id.d.ts.map +1 -1
- package/unstable-preview-types/-private/utils/construct-resource.d.ts +6 -7
- package/unstable-preview-types/-private/utils/construct-resource.d.ts.map +1 -1
- package/unstable-preview-types/-private/utils/is-non-empty-string.d.ts +1 -1
- package/unstable-preview-types/-private/utils/is-non-empty-string.d.ts.map +1 -1
- package/unstable-preview-types/-private/utils/normalize-model-name.d.ts +1 -1
- package/unstable-preview-types/-private/utils/normalize-model-name.d.ts.map +1 -1
- package/unstable-preview-types/-private.d.ts +12 -8
- package/unstable-preview-types/-private.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/{cache-store-wrapper.d.ts → cache-capabilities-manager.d.ts} +8 -6
- package/unstable-preview-types/-types/q/cache-capabilities-manager.d.ts.map +1 -0
- package/unstable-preview-types/-types/q/ds-model.d.ts +15 -5
- package/unstable-preview-types/-types/q/ds-model.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/identifier.d.ts +0 -2
- package/unstable-preview-types/-types/q/identifier.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/record-data-json-api.d.ts +1 -1
- package/unstable-preview-types/-types/q/record-data-json-api.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/schema-service.d.ts +164 -29
- package/unstable-preview-types/-types/q/schema-service.d.ts.map +1 -1
- package/unstable-preview-types/index.d.ts +26 -27
- package/unstable-preview-types/index.d.ts.map +1 -1
- package/unstable-preview-types/types.d.ts +7 -0
- package/unstable-preview-types/types.d.ts.map +1 -0
- package/addon/-private.js +0 -1
- package/addon/cache-handler-Cm55UqNi.js.map +0 -1
- package/addon/index.js +0 -1
- package/addon-main.js +0 -94
- package/unstable-preview-types/-private/utils/identifier-debug-consts.d.ts +0 -7
- package/unstable-preview-types/-private/utils/identifier-debug-consts.d.ts.map +0 -1
- package/unstable-preview-types/-types/q/cache-store-wrapper.d.ts.map +0 -1
- package/unstable-preview-types/-types/q/cache.d.ts +0 -47
- package/unstable-preview-types/-types/q/cache.d.ts.map +0 -1
- /package/{addon → dist}/-private.js.map +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { deprecate,
|
|
2
|
-
import
|
|
1
|
+
import { deprecate, warn } from '@ember/debug';
|
|
2
|
+
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
3
3
|
import { SkipCache, EnableHydration } from '@warp-drive-mirror/core-types/request';
|
|
4
|
-
import {
|
|
4
|
+
import { getOrSetGlobal, setTransient, peekTransient } from '@warp-drive-mirror/core-types/-private';
|
|
5
5
|
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '@warp-drive-mirror/core-types/identifier';
|
|
6
6
|
import { dasherize } from '@ember/string';
|
|
7
|
-
import { defineSignal,
|
|
7
|
+
import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data-mirror/tracking/-private';
|
|
8
8
|
import { _backburner } from '@ember/runloop';
|
|
9
9
|
import { compat } from '@ember-data-mirror/tracking';
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ import { compat } from '@ember-data-mirror/tracking';
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
function coerceId(id) {
|
|
16
|
-
if (macroCondition(
|
|
16
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_NON_STRICT_ID)) {
|
|
17
17
|
let normalized;
|
|
18
18
|
if (id === null || id === undefined || id === '') {
|
|
19
19
|
normalized = null;
|
|
@@ -31,7 +31,11 @@ function coerceId(id) {
|
|
|
31
31
|
});
|
|
32
32
|
return normalized;
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
35
|
+
if (!test) {
|
|
36
|
+
throw new Error(`Resource IDs must be a non-empty string or null. Received '${String(id)}'.`);
|
|
37
|
+
}
|
|
38
|
+
})(id === null || typeof id === 'string' && id.length > 0) : {};
|
|
35
39
|
return id;
|
|
36
40
|
}
|
|
37
41
|
function ensureStringId(id) {
|
|
@@ -41,11 +45,15 @@ function ensureStringId(id) {
|
|
|
41
45
|
} else if (typeof id === 'number' && !isNaN(id)) {
|
|
42
46
|
normalized = String(id);
|
|
43
47
|
}
|
|
44
|
-
|
|
48
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
49
|
+
if (!test) {
|
|
50
|
+
throw new Error(`Expected id to be a string or number, received ${String(id)}`);
|
|
51
|
+
}
|
|
52
|
+
})(normalized !== null) : {};
|
|
45
53
|
return normalized;
|
|
46
54
|
}
|
|
47
55
|
function normalizeModelName(type) {
|
|
48
|
-
if (macroCondition(
|
|
56
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_NON_STRICT_TYPES)) {
|
|
49
57
|
const result = dasherize(type);
|
|
50
58
|
deprecate(`The resource type '${type}' is not normalized. Update your application code to use '${result}' instead of '${type}'.`, result === type, {
|
|
51
59
|
id: 'ember-data-mirror:deprecate-non-strict-types',
|
|
@@ -121,8 +129,8 @@ function hasType(resource) {
|
|
|
121
129
|
/**
|
|
122
130
|
@module @ember-data-mirror/store
|
|
123
131
|
*/
|
|
124
|
-
const IDENTIFIERS = new Set();
|
|
125
|
-
const DOCUMENTS = new Set();
|
|
132
|
+
const IDENTIFIERS = getOrSetGlobal('IDENTIFIERS', new Set());
|
|
133
|
+
const DOCUMENTS = getOrSetGlobal('DOCUMENTS', new Set());
|
|
126
134
|
function isStableIdentifier(identifier) {
|
|
127
135
|
return identifier[CACHE_OWNER] !== undefined || IDENTIFIERS.has(identifier);
|
|
128
136
|
}
|
|
@@ -131,11 +139,15 @@ function isDocumentIdentifier(identifier) {
|
|
|
131
139
|
}
|
|
132
140
|
const isFastBoot = typeof FastBoot !== 'undefined';
|
|
133
141
|
const _crypto = isFastBoot ? FastBoot.require('crypto') : window.crypto;
|
|
134
|
-
if (macroCondition(
|
|
142
|
+
if (macroCondition(getGlobalConfig().WarpDrive.polyfillUUID)) {
|
|
135
143
|
installPolyfill();
|
|
136
144
|
}
|
|
137
145
|
function uuidv4() {
|
|
138
|
-
|
|
146
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
147
|
+
if (!test) {
|
|
148
|
+
throw new Error('crypto.randomUUID needs to be avaliable. Some browsers incorrectly disallow it in insecure contexts. You maybe want to enable the polyfill: https://github.com/emberjs/data#randomuuid-polyfill');
|
|
149
|
+
}
|
|
150
|
+
})(typeof _crypto.randomUUID === 'function') : {};
|
|
139
151
|
return _crypto.randomUUID();
|
|
140
152
|
}
|
|
141
153
|
function freeze(obj) {
|
|
@@ -148,30 +160,27 @@ function freeze(obj) {
|
|
|
148
160
|
// type IdentifierTypeLookup = { all: Set<StableRecordIdentifier>; id: Map<string, StableRecordIdentifier> };
|
|
149
161
|
// type IdentifiersByType = Map<string, IdentifierTypeLookup>;
|
|
150
162
|
|
|
151
|
-
let configuredForgetMethod;
|
|
152
|
-
let configuredGenerationMethod;
|
|
153
|
-
let configuredResetMethod;
|
|
154
|
-
let configuredUpdateMethod;
|
|
155
|
-
let configuredKeyInfoMethod;
|
|
156
163
|
function setIdentifierGenerationMethod(method) {
|
|
157
|
-
configuredGenerationMethod
|
|
164
|
+
setTransient('configuredGenerationMethod', method);
|
|
158
165
|
}
|
|
159
166
|
function setIdentifierUpdateMethod(method) {
|
|
160
|
-
configuredUpdateMethod
|
|
167
|
+
setTransient('configuredUpdateMethod', method);
|
|
161
168
|
}
|
|
162
169
|
function setIdentifierForgetMethod(method) {
|
|
163
|
-
configuredForgetMethod
|
|
170
|
+
setTransient('configuredForgetMethod', method);
|
|
164
171
|
}
|
|
165
172
|
function setIdentifierResetMethod(method) {
|
|
166
|
-
configuredResetMethod
|
|
173
|
+
setTransient('configuredResetMethod', method);
|
|
167
174
|
}
|
|
168
175
|
function setKeyInfoForResource(method) {
|
|
169
|
-
configuredKeyInfoMethod
|
|
176
|
+
setTransient('configuredKeyInfoMethod', method);
|
|
170
177
|
}
|
|
171
178
|
|
|
172
179
|
// Map<type, Map<id, lid>>
|
|
173
180
|
|
|
181
|
+
// TODO can we just delete this?
|
|
174
182
|
const NEW_IDENTIFIERS = new Map();
|
|
183
|
+
// TODO @runspired maybe needs peekTransient ?
|
|
175
184
|
let IDENTIFIER_CACHE_ID = 0;
|
|
176
185
|
function updateTypeIdMapping(typeMap, identifier, id) {
|
|
177
186
|
let idMap = typeMap.get(identifier.type);
|
|
@@ -183,7 +192,11 @@ function updateTypeIdMapping(typeMap, identifier, id) {
|
|
|
183
192
|
}
|
|
184
193
|
function defaultUpdateMethod(identifier, data, bucket) {
|
|
185
194
|
if (bucket === 'record') {
|
|
186
|
-
|
|
195
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
196
|
+
if (!test) {
|
|
197
|
+
throw new Error(`Expected identifier to be a StableRecordIdentifier`);
|
|
198
|
+
}
|
|
199
|
+
})(isStableIdentifier(identifier)) : {};
|
|
187
200
|
if (!identifier.id && hasId(data)) {
|
|
188
201
|
updateTypeIdMapping(NEW_IDENTIFIERS, identifier, data.id);
|
|
189
202
|
}
|
|
@@ -193,7 +206,11 @@ function defaultKeyInfoMethod(resource, known) {
|
|
|
193
206
|
// TODO RFC something to make this configurable
|
|
194
207
|
const id = hasId(resource) ? coerceId(resource.id) : null;
|
|
195
208
|
const type = hasType(resource) ? normalizeModelName(resource.type) : known ? known.type : null;
|
|
196
|
-
|
|
209
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
210
|
+
if (!test) {
|
|
211
|
+
throw new Error(`Expected keyInfoForResource to provide a type for the resource`);
|
|
212
|
+
}
|
|
213
|
+
})(type) : {};
|
|
197
214
|
return {
|
|
198
215
|
type,
|
|
199
216
|
id
|
|
@@ -204,7 +221,11 @@ function defaultGenerationMethod(data, bucket) {
|
|
|
204
221
|
if (hasLid(data)) {
|
|
205
222
|
return data.lid;
|
|
206
223
|
}
|
|
207
|
-
|
|
224
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
225
|
+
if (!test) {
|
|
226
|
+
throw new Error(`Cannot generate an identifier for a resource without a type`);
|
|
227
|
+
}
|
|
228
|
+
})(hasType(data)) : {};
|
|
208
229
|
if (hasId(data)) {
|
|
209
230
|
const type = normalizeModelName(data.type);
|
|
210
231
|
const lid = NEW_IDENTIFIERS.get(type)?.get(data.id);
|
|
@@ -220,15 +241,19 @@ function defaultGenerationMethod(data, bucket) {
|
|
|
220
241
|
}
|
|
221
242
|
return null;
|
|
222
243
|
}
|
|
223
|
-
|
|
244
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
245
|
+
{
|
|
246
|
+
throw new Error(`Unknown bucket ${bucket}`);
|
|
247
|
+
}
|
|
248
|
+
})() : {};
|
|
224
249
|
}
|
|
225
250
|
function defaultEmptyCallback(...args) {}
|
|
226
251
|
function defaultMergeMethod(a, _b, _c) {
|
|
227
252
|
return a;
|
|
228
253
|
}
|
|
229
254
|
let DEBUG_MAP;
|
|
230
|
-
if (macroCondition(
|
|
231
|
-
DEBUG_MAP = new WeakMap();
|
|
255
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
256
|
+
DEBUG_MAP = getOrSetGlobal('DEBUG_MAP', new WeakMap());
|
|
232
257
|
}
|
|
233
258
|
|
|
234
259
|
/**
|
|
@@ -248,13 +273,12 @@ class IdentifierCache {
|
|
|
248
273
|
constructor() {
|
|
249
274
|
// we cache the user configuredGenerationMethod at init because it must
|
|
250
275
|
// be configured prior and is not allowed to be changed
|
|
251
|
-
this._generate = configuredGenerationMethod || defaultGenerationMethod;
|
|
252
|
-
this._update = configuredUpdateMethod || defaultUpdateMethod;
|
|
253
|
-
this._forget = configuredForgetMethod || defaultEmptyCallback;
|
|
254
|
-
this._reset = configuredResetMethod || defaultEmptyCallback;
|
|
276
|
+
this._generate = peekTransient('configuredGenerationMethod') || defaultGenerationMethod;
|
|
277
|
+
this._update = peekTransient('configuredUpdateMethod') || defaultUpdateMethod;
|
|
278
|
+
this._forget = peekTransient('configuredForgetMethod') || defaultEmptyCallback;
|
|
279
|
+
this._reset = peekTransient('configuredResetMethod') || defaultEmptyCallback;
|
|
255
280
|
this._merge = defaultMergeMethod;
|
|
256
|
-
this._keyInfoForResource = configuredKeyInfoMethod || defaultKeyInfoMethod;
|
|
257
|
-
this._isDefaultConfig = !configuredGenerationMethod;
|
|
281
|
+
this._keyInfoForResource = peekTransient('configuredKeyInfoMethod') || defaultKeyInfoMethod;
|
|
258
282
|
this._id = IDENTIFIER_CACHE_ID++;
|
|
259
283
|
this._cache = {
|
|
260
284
|
resources: new Map(),
|
|
@@ -286,19 +310,19 @@ class IdentifierCache {
|
|
|
286
310
|
*/
|
|
287
311
|
|
|
288
312
|
_getRecordIdentifier(resource, shouldGenerate) {
|
|
289
|
-
if (macroCondition(
|
|
313
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
290
314
|
// eslint-disable-next-line no-console
|
|
291
315
|
console.groupCollapsed(`Identifiers: ${shouldGenerate ? 'Generating' : 'Peeking'} Identifier`, resource);
|
|
292
316
|
}
|
|
293
317
|
// short circuit if we're already the stable version
|
|
294
318
|
if (isStableIdentifier(resource)) {
|
|
295
|
-
if (macroCondition(
|
|
319
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
296
320
|
// TODO should we instead just treat this case as a new generation skipping the short circuit?
|
|
297
321
|
if (!this._cache.resources.has(resource.lid) || this._cache.resources.get(resource.lid) !== resource) {
|
|
298
322
|
throw new Error(`The supplied identifier ${JSON.stringify(resource)} does not belong to this store instance`);
|
|
299
323
|
}
|
|
300
324
|
}
|
|
301
|
-
if (macroCondition(
|
|
325
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
302
326
|
// eslint-disable-next-line no-console
|
|
303
327
|
console.log(`Identifiers: cache HIT - Stable ${resource.lid}`);
|
|
304
328
|
// eslint-disable-next-line no-console
|
|
@@ -309,20 +333,20 @@ class IdentifierCache {
|
|
|
309
333
|
|
|
310
334
|
// the resource is unknown, ask the application to identify this data for us
|
|
311
335
|
const lid = this._generate(resource, 'record');
|
|
312
|
-
if (macroCondition(
|
|
336
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
313
337
|
// eslint-disable-next-line no-console
|
|
314
338
|
console.log(`Identifiers: ${lid ? 'no ' : ''}lid ${lid ? lid + ' ' : ''}determined for resource`, resource);
|
|
315
339
|
}
|
|
316
340
|
let identifier = /*#__NOINLINE__*/getIdentifierFromLid(this._cache, lid, resource);
|
|
317
341
|
if (identifier !== null) {
|
|
318
|
-
if (macroCondition(
|
|
342
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
319
343
|
// eslint-disable-next-line no-console
|
|
320
344
|
console.groupEnd();
|
|
321
345
|
}
|
|
322
346
|
return identifier;
|
|
323
347
|
}
|
|
324
348
|
if (shouldGenerate === 0) {
|
|
325
|
-
if (macroCondition(
|
|
349
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
326
350
|
// eslint-disable-next-line no-console
|
|
327
351
|
console.groupEnd();
|
|
328
352
|
}
|
|
@@ -342,7 +366,7 @@ class IdentifierCache {
|
|
|
342
366
|
identifier = /*#__NOINLINE__*/makeStableRecordIdentifier(keyInfo, 'record', false);
|
|
343
367
|
}
|
|
344
368
|
addResourceToCache(this._cache, identifier);
|
|
345
|
-
if (macroCondition(
|
|
369
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
346
370
|
// eslint-disable-next-line no-console
|
|
347
371
|
console.groupEnd();
|
|
348
372
|
}
|
|
@@ -384,7 +408,7 @@ class IdentifierCache {
|
|
|
384
408
|
identifier = {
|
|
385
409
|
lid: cacheKey
|
|
386
410
|
};
|
|
387
|
-
if (macroCondition(
|
|
411
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
388
412
|
Object.freeze(identifier);
|
|
389
413
|
}
|
|
390
414
|
DOCUMENTS.add(identifier);
|
|
@@ -430,7 +454,7 @@ class IdentifierCache {
|
|
|
430
454
|
}, 'record', true);
|
|
431
455
|
|
|
432
456
|
// populate our unique table
|
|
433
|
-
if (macroCondition(
|
|
457
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
434
458
|
if (this._cache.resources.has(identifier.lid)) {
|
|
435
459
|
throw new Error(`The lid generated for the new record is not unique as it matches an existing identifier`);
|
|
436
460
|
}
|
|
@@ -438,7 +462,7 @@ class IdentifierCache {
|
|
|
438
462
|
|
|
439
463
|
/*#__NOINLINE__*/
|
|
440
464
|
addResourceToCache(this._cache, identifier);
|
|
441
|
-
if (macroCondition(
|
|
465
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
442
466
|
// eslint-disable-next-line no-console
|
|
443
467
|
console.log(`Identifiers: created identifier ${String(identifier)} for newly generated resource`, data);
|
|
444
468
|
}
|
|
@@ -487,7 +511,7 @@ class IdentifierCache {
|
|
|
487
511
|
if (hadLid) {
|
|
488
512
|
data.lid = identifier.lid;
|
|
489
513
|
}
|
|
490
|
-
if (macroCondition(
|
|
514
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
491
515
|
// eslint-disable-next-line no-console
|
|
492
516
|
console.log(`Identifiers: merged identifiers ${generatedIdentifier.lid} and ${existingIdentifier.lid} for resource into ${identifier.lid}`, data);
|
|
493
517
|
}
|
|
@@ -499,17 +523,21 @@ class IdentifierCache {
|
|
|
499
523
|
|
|
500
524
|
// add to our own secondary lookup table
|
|
501
525
|
if (id !== newId && newId !== null) {
|
|
502
|
-
if (macroCondition(
|
|
526
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
503
527
|
// eslint-disable-next-line no-console
|
|
504
528
|
console.log(`Identifiers: updated id for identifier ${identifier.lid} from '${String(id)}' to '${String(newId)}' for resource`, data);
|
|
505
529
|
}
|
|
506
530
|
const typeSet = this._cache.resourcesByType[identifier.type];
|
|
507
|
-
|
|
531
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
532
|
+
if (!test) {
|
|
533
|
+
throw new Error(`Expected to find a typeSet for ${identifier.type}`);
|
|
534
|
+
}
|
|
535
|
+
})(typeSet) : {};
|
|
508
536
|
typeSet.id.set(newId, identifier);
|
|
509
537
|
if (id !== null) {
|
|
510
538
|
typeSet.id.delete(id);
|
|
511
539
|
}
|
|
512
|
-
} else if (macroCondition(
|
|
540
|
+
} else if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
513
541
|
// eslint-disable-next-line no-console
|
|
514
542
|
console.log(`Identifiers: updated identifier ${identifier.lid} resource`, data);
|
|
515
543
|
}
|
|
@@ -521,7 +549,11 @@ class IdentifierCache {
|
|
|
521
549
|
* @private
|
|
522
550
|
*/
|
|
523
551
|
_mergeRecordIdentifiers(keyInfo, identifier, existingIdentifier, data) {
|
|
524
|
-
|
|
552
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
553
|
+
if (!test) {
|
|
554
|
+
throw new Error(`Expected keyInfo to contain an id`);
|
|
555
|
+
}
|
|
556
|
+
})(hasId(keyInfo)) : {};
|
|
525
557
|
// delegate determining which identifier to keep to the configured MergeMethod
|
|
526
558
|
const kept = this._merge(identifier, existingIdentifier, data);
|
|
527
559
|
const abandoned = kept === identifier ? existingIdentifier : identifier;
|
|
@@ -568,7 +600,11 @@ class IdentifierCache {
|
|
|
568
600
|
forgetRecordIdentifier(identifierObject) {
|
|
569
601
|
const identifier = this.getOrCreateRecordIdentifier(identifierObject);
|
|
570
602
|
const typeSet = this._cache.resourcesByType[identifier.type];
|
|
571
|
-
|
|
603
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
604
|
+
if (!test) {
|
|
605
|
+
throw new Error(`Expected to find a typeSet for ${identifier.type}`);
|
|
606
|
+
}
|
|
607
|
+
})(typeSet) : {};
|
|
572
608
|
if (identifier.id !== null) {
|
|
573
609
|
typeSet.id.delete(identifier.id);
|
|
574
610
|
}
|
|
@@ -581,13 +617,13 @@ class IdentifierCache {
|
|
|
581
617
|
});
|
|
582
618
|
this._cache.polymorphicLidBackMap.delete(identifier.lid);
|
|
583
619
|
}
|
|
584
|
-
if (macroCondition(
|
|
620
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
585
621
|
identifier[DEBUG_STALE_CACHE_OWNER] = identifier[CACHE_OWNER];
|
|
586
622
|
}
|
|
587
623
|
identifier[CACHE_OWNER] = undefined;
|
|
588
624
|
IDENTIFIERS.delete(identifier);
|
|
589
625
|
this._forget(identifier, 'record');
|
|
590
|
-
if (macroCondition(
|
|
626
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
591
627
|
// eslint-disable-next-line no-console
|
|
592
628
|
console.log(`Identifiers: released identifier ${identifierObject.lid}`);
|
|
593
629
|
}
|
|
@@ -602,7 +638,7 @@ class IdentifierCache {
|
|
|
602
638
|
}
|
|
603
639
|
function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated) {
|
|
604
640
|
IDENTIFIERS.add(recordIdentifier);
|
|
605
|
-
if (macroCondition(
|
|
641
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
606
642
|
// we enforce immutability in dev
|
|
607
643
|
// but preserve our ability to do controlled updates to the reference
|
|
608
644
|
let wrapper = {
|
|
@@ -664,7 +700,7 @@ function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated)
|
|
|
664
700
|
return recordIdentifier;
|
|
665
701
|
}
|
|
666
702
|
function performRecordIdentifierUpdate(identifier, keyInfo, data, updateFn) {
|
|
667
|
-
if (macroCondition(
|
|
703
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
668
704
|
const {
|
|
669
705
|
id,
|
|
670
706
|
type
|
|
@@ -739,7 +775,7 @@ function detectMerge(cache, keyInfo, identifier, data) {
|
|
|
739
775
|
}
|
|
740
776
|
function getIdentifierFromLid(cache, lid, resource) {
|
|
741
777
|
const identifier = cache.resources.get(lid);
|
|
742
|
-
if (macroCondition(
|
|
778
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS)) {
|
|
743
779
|
// eslint-disable-next-line no-console
|
|
744
780
|
console.log(`Identifiers: cache ${identifier ? 'HIT' : 'MISS'} - Non-Stable ${lid}`, resource);
|
|
745
781
|
}
|
|
@@ -765,10 +801,6 @@ function addResourceToCache(cache, identifier) {
|
|
|
765
801
|
@module @ember-data-mirror/store
|
|
766
802
|
*/
|
|
767
803
|
|
|
768
|
-
/**
|
|
769
|
-
@module @ember-data-mirror/store
|
|
770
|
-
*/
|
|
771
|
-
|
|
772
804
|
/**
|
|
773
805
|
A `RecordReference` is a low-level API that allows users and
|
|
774
806
|
addon authors to perform meta-operations on a record.
|
|
@@ -777,10 +809,10 @@ function addResourceToCache(cache, identifier) {
|
|
|
777
809
|
@public
|
|
778
810
|
*/
|
|
779
811
|
class RecordReference {
|
|
812
|
+
// unsubscribe token given to us by the notification manager
|
|
813
|
+
___token;
|
|
814
|
+
___identifier;
|
|
780
815
|
constructor(store, identifier) {
|
|
781
|
-
// unsubscribe token given to us by the notification manager
|
|
782
|
-
this.___token = void 0;
|
|
783
|
-
this.___identifier = void 0;
|
|
784
816
|
this.store = store;
|
|
785
817
|
this.___identifier = identifier;
|
|
786
818
|
this.___token = store.notifications.subscribe(identifier, (_, bucket, notifiedKey) => {
|
|
@@ -923,7 +955,11 @@ class RecordReference {
|
|
|
923
955
|
if (id !== null) {
|
|
924
956
|
return this.store.findRecord(this.type, id);
|
|
925
957
|
}
|
|
926
|
-
|
|
958
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
959
|
+
{
|
|
960
|
+
throw new Error(`Unable to fetch record of type ${this.type} without an id`);
|
|
961
|
+
}
|
|
962
|
+
})() : {};
|
|
927
963
|
}
|
|
928
964
|
|
|
929
965
|
/**
|
|
@@ -946,7 +982,11 @@ class RecordReference {
|
|
|
946
982
|
reload: true
|
|
947
983
|
});
|
|
948
984
|
}
|
|
949
|
-
|
|
985
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
986
|
+
{
|
|
987
|
+
throw new Error(`Unable to fetch record of type ${this.type} without an id`);
|
|
988
|
+
}
|
|
989
|
+
})() : {};
|
|
950
990
|
}
|
|
951
991
|
}
|
|
952
992
|
defineSignal(RecordReference.prototype, '_ref');
|
|
@@ -954,7 +994,6 @@ defineSignal(RecordReference.prototype, '_ref');
|
|
|
954
994
|
/**
|
|
955
995
|
@module @ember-data-mirror/store
|
|
956
996
|
*/
|
|
957
|
-
|
|
958
997
|
class CacheCapabilitiesManager {
|
|
959
998
|
constructor(_store) {
|
|
960
999
|
this._store = _store;
|
|
@@ -999,7 +1038,11 @@ class CacheCapabilitiesManager {
|
|
|
999
1038
|
});
|
|
1000
1039
|
}
|
|
1001
1040
|
notifyChange(identifier, namespace, key) {
|
|
1002
|
-
|
|
1041
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1042
|
+
if (!test) {
|
|
1043
|
+
throw new Error(`Expected a stable identifier`);
|
|
1044
|
+
}
|
|
1045
|
+
})(isStableIdentifier(identifier) || isDocumentIdentifier(identifier)) : {};
|
|
1003
1046
|
|
|
1004
1047
|
// TODO do we still get value from this?
|
|
1005
1048
|
if (namespace === 'relationships' && key) {
|
|
@@ -1010,34 +1053,49 @@ class CacheCapabilitiesManager {
|
|
|
1010
1053
|
// @ts-expect-error
|
|
1011
1054
|
this._store.notifications.notify(identifier, namespace, key);
|
|
1012
1055
|
}
|
|
1013
|
-
getSchemaDefinitionService() {
|
|
1014
|
-
return this._store.getSchemaDefinitionService();
|
|
1015
|
-
}
|
|
1016
1056
|
get schema() {
|
|
1017
1057
|
return this._store.schema;
|
|
1018
1058
|
}
|
|
1019
1059
|
setRecordId(identifier, id) {
|
|
1020
|
-
|
|
1060
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1061
|
+
if (!test) {
|
|
1062
|
+
throw new Error(`Expected a stable identifier`);
|
|
1063
|
+
}
|
|
1064
|
+
})(isStableIdentifier(identifier)) : {};
|
|
1021
1065
|
this._store._instanceCache.setRecordId(identifier, id);
|
|
1022
1066
|
}
|
|
1023
1067
|
hasRecord(identifier) {
|
|
1024
1068
|
return Boolean(this._store._instanceCache.peek(identifier));
|
|
1025
1069
|
}
|
|
1026
1070
|
disconnectRecord(identifier) {
|
|
1027
|
-
|
|
1071
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1072
|
+
if (!test) {
|
|
1073
|
+
throw new Error(`Expected a stable identifier`);
|
|
1074
|
+
}
|
|
1075
|
+
})(isStableIdentifier(identifier)) : {};
|
|
1028
1076
|
this._store._instanceCache.disconnect(identifier);
|
|
1029
1077
|
this._pendingNotifies.delete(identifier);
|
|
1030
1078
|
}
|
|
1031
1079
|
}
|
|
1080
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_SCHEMA_SERVICE)) {
|
|
1081
|
+
CacheCapabilitiesManager.prototype.getSchemaDefinitionService = function () {
|
|
1082
|
+
// FIXME add deprecation for this
|
|
1083
|
+
return this._store.schema;
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1032
1086
|
|
|
1033
1087
|
/*
|
|
1034
1088
|
* Returns the Cache instance associated with a given
|
|
1035
1089
|
* Model or Identifier
|
|
1036
1090
|
*/
|
|
1037
1091
|
|
|
1038
|
-
const CacheForIdentifierCache = new Map();
|
|
1092
|
+
const CacheForIdentifierCache = getOrSetGlobal('CacheForIdentifierCache', new Map());
|
|
1039
1093
|
function setCacheFor(identifier, cache) {
|
|
1040
|
-
|
|
1094
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1095
|
+
if (!test) {
|
|
1096
|
+
throw new Error(`Illegal set of identifier`);
|
|
1097
|
+
}
|
|
1098
|
+
})(!CacheForIdentifierCache.has(identifier) || CacheForIdentifierCache.get(identifier) === cache) : {};
|
|
1041
1099
|
CacheForIdentifierCache.set(identifier, cache);
|
|
1042
1100
|
}
|
|
1043
1101
|
function removeRecordDataFor(identifier) {
|
|
@@ -1057,7 +1115,7 @@ function isDestroyable(record) {
|
|
|
1057
1115
|
@module @ember-data-mirror/store
|
|
1058
1116
|
*/
|
|
1059
1117
|
|
|
1060
|
-
const RecordCache = new Map();
|
|
1118
|
+
const RecordCache = getOrSetGlobal('RecordCache', new Map());
|
|
1061
1119
|
function peekRecordIdentifier(record) {
|
|
1062
1120
|
return RecordCache.get(record);
|
|
1063
1121
|
}
|
|
@@ -1083,11 +1141,15 @@ function peekRecordIdentifier(record) {
|
|
|
1083
1141
|
*/
|
|
1084
1142
|
|
|
1085
1143
|
function recordIdentifierFor(record) {
|
|
1086
|
-
|
|
1144
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1145
|
+
if (!test) {
|
|
1146
|
+
throw new Error(`${String(record)} is not a record instantiated by @ember-data-mirror/store`);
|
|
1147
|
+
}
|
|
1148
|
+
})(RecordCache.has(record)) : {};
|
|
1087
1149
|
return RecordCache.get(record);
|
|
1088
1150
|
}
|
|
1089
1151
|
function setRecordIdentifier(record, identifier) {
|
|
1090
|
-
if (macroCondition(
|
|
1152
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
1091
1153
|
if (RecordCache.has(record) && RecordCache.get(record) !== identifier) {
|
|
1092
1154
|
throw new Error(`${String(record)} was already assigned an identifier`);
|
|
1093
1155
|
}
|
|
@@ -1103,18 +1165,22 @@ function setRecordIdentifier(record, identifier) {
|
|
|
1103
1165
|
|
|
1104
1166
|
RecordCache.set(record, identifier);
|
|
1105
1167
|
}
|
|
1106
|
-
const StoreMap = new Map();
|
|
1168
|
+
const StoreMap = getOrSetGlobal('StoreMap', new Map());
|
|
1107
1169
|
function storeFor(record) {
|
|
1108
1170
|
const store = StoreMap.get(record);
|
|
1109
|
-
|
|
1171
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1172
|
+
if (!test) {
|
|
1173
|
+
throw new Error(`A record in a disconnected state cannot utilize the store. This typically means the record has been destroyed, most commonly by unloading it.`);
|
|
1174
|
+
}
|
|
1175
|
+
})(store) : {};
|
|
1110
1176
|
return store;
|
|
1111
1177
|
}
|
|
1112
1178
|
class InstanceCache {
|
|
1179
|
+
__instances = {
|
|
1180
|
+
record: new Map(),
|
|
1181
|
+
reference: new WeakMap()
|
|
1182
|
+
};
|
|
1113
1183
|
constructor(store) {
|
|
1114
|
-
this.__instances = {
|
|
1115
|
-
record: new Map(),
|
|
1116
|
-
reference: new WeakMap()
|
|
1117
|
-
};
|
|
1118
1184
|
this.store = store;
|
|
1119
1185
|
this._storeWrapper = new CacheCapabilitiesManager(this.store);
|
|
1120
1186
|
store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
|
|
@@ -1144,7 +1210,11 @@ class InstanceCache {
|
|
|
1144
1210
|
if ('id' in resourceData) {
|
|
1145
1211
|
throw new Error(`Failed to update the 'id' for the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to '${String(resourceData.id)}', because that id is already in use by '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${matchedIdentifier.lid})'`);
|
|
1146
1212
|
}
|
|
1147
|
-
|
|
1213
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1214
|
+
{
|
|
1215
|
+
throw new Error(`Failed to update the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to merge with the detected duplicate identifier '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${String(matchedIdentifier.lid)})'`);
|
|
1216
|
+
}
|
|
1217
|
+
})() : {};
|
|
1148
1218
|
}
|
|
1149
1219
|
this.store.cache.patch({
|
|
1150
1220
|
op: 'mergeIdentifiers',
|
|
@@ -1169,7 +1239,11 @@ class InstanceCache {
|
|
|
1169
1239
|
getRecord(identifier, properties) {
|
|
1170
1240
|
let record = this.__instances.record.get(identifier);
|
|
1171
1241
|
if (!record) {
|
|
1172
|
-
|
|
1242
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1243
|
+
if (!test) {
|
|
1244
|
+
throw new Error(`Cannot create a new record instance while the store is being destroyed`);
|
|
1245
|
+
}
|
|
1246
|
+
})(!this.store.isDestroying && !this.store.isDestroyed) : {};
|
|
1173
1247
|
const cache = this.store.cache;
|
|
1174
1248
|
setCacheFor(identifier, cache);
|
|
1175
1249
|
record = this.store.instantiateRecord(identifier, properties || {});
|
|
@@ -1177,7 +1251,7 @@ class InstanceCache {
|
|
|
1177
1251
|
setCacheFor(record, cache);
|
|
1178
1252
|
StoreMap.set(record, this.store);
|
|
1179
1253
|
this.__instances.record.set(identifier, record);
|
|
1180
|
-
if (macroCondition(
|
|
1254
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1181
1255
|
// eslint-disable-next-line no-console
|
|
1182
1256
|
console.log(`InstanceCache: created Record for ${String(identifier)}`, properties);
|
|
1183
1257
|
}
|
|
@@ -1216,26 +1290,34 @@ class InstanceCache {
|
|
|
1216
1290
|
}
|
|
1217
1291
|
disconnect(identifier) {
|
|
1218
1292
|
const record = this.__instances.record.get(identifier);
|
|
1219
|
-
|
|
1293
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1294
|
+
if (!test) {
|
|
1295
|
+
throw new Error('Cannot destroy record while it is still materialized');
|
|
1296
|
+
}
|
|
1297
|
+
})(!isDestroyable(record) || record.isDestroyed || record.isDestroying) : {};
|
|
1220
1298
|
this.store._graph?.remove(identifier);
|
|
1221
1299
|
this.store.identifierCache.forgetRecordIdentifier(identifier);
|
|
1222
1300
|
removeRecordDataFor(identifier);
|
|
1223
1301
|
this.store._requestCache._clearEntries(identifier);
|
|
1224
|
-
if (macroCondition(
|
|
1302
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1225
1303
|
// eslint-disable-next-line no-console
|
|
1226
1304
|
console.log(`InstanceCache: disconnected ${String(identifier)}`);
|
|
1227
1305
|
}
|
|
1228
1306
|
}
|
|
1229
1307
|
unloadRecord(identifier) {
|
|
1230
|
-
if (macroCondition(
|
|
1308
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
1231
1309
|
const requests = this.store.getRequestStateService().getPendingRequestsForRecord(identifier);
|
|
1232
1310
|
if (requests.some(req => {
|
|
1233
1311
|
return req.type === 'mutation';
|
|
1234
1312
|
})) {
|
|
1235
|
-
|
|
1313
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1314
|
+
{
|
|
1315
|
+
throw new Error(`You can only unload a record which is not inFlight. '${String(identifier)}'`);
|
|
1316
|
+
}
|
|
1317
|
+
})() : {};
|
|
1236
1318
|
}
|
|
1237
1319
|
}
|
|
1238
|
-
if (macroCondition(
|
|
1320
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1239
1321
|
// eslint-disable-next-line no-console
|
|
1240
1322
|
console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
|
|
1241
1323
|
}
|
|
@@ -1250,7 +1332,7 @@ class InstanceCache {
|
|
|
1250
1332
|
StoreMap.delete(record);
|
|
1251
1333
|
RecordCache.delete(record);
|
|
1252
1334
|
removeRecordDataFor(record);
|
|
1253
|
-
if (macroCondition(
|
|
1335
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1254
1336
|
// eslint-disable-next-line no-console
|
|
1255
1337
|
console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
|
|
1256
1338
|
}
|
|
@@ -1258,7 +1340,7 @@ class InstanceCache {
|
|
|
1258
1340
|
if (cache) {
|
|
1259
1341
|
cache.unloadRecord(identifier);
|
|
1260
1342
|
removeRecordDataFor(identifier);
|
|
1261
|
-
if (macroCondition(
|
|
1343
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1262
1344
|
// eslint-disable-next-line no-console
|
|
1263
1345
|
console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
|
|
1264
1346
|
}
|
|
@@ -1266,7 +1348,7 @@ class InstanceCache {
|
|
|
1266
1348
|
this.disconnect(identifier);
|
|
1267
1349
|
}
|
|
1268
1350
|
this.store._requestCache._clearEntries(identifier);
|
|
1269
|
-
if (macroCondition(
|
|
1351
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1270
1352
|
// eslint-disable-next-line no-console
|
|
1271
1353
|
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
1272
1354
|
// eslint-disable-next-line no-console
|
|
@@ -1305,11 +1387,19 @@ class InstanceCache {
|
|
|
1305
1387
|
const oldId = identifier.id;
|
|
1306
1388
|
|
|
1307
1389
|
// ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record)
|
|
1308
|
-
|
|
1390
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1391
|
+
if (!test) {
|
|
1392
|
+
throw new Error(`'${type}' was saved to the server, but the response does not have an id and your record does not either.`);
|
|
1393
|
+
}
|
|
1394
|
+
})(!(id === null && oldId === null)) : {};
|
|
1309
1395
|
|
|
1310
1396
|
// ID absolutely can't be different than oldID if oldID is not null
|
|
1311
1397
|
// TODO this assertion and restriction may not strictly be needed in the identifiers world
|
|
1312
|
-
|
|
1398
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1399
|
+
if (!test) {
|
|
1400
|
+
throw new Error(`Cannot update the id for '${type}:${lid}' from '${String(oldId)}' to '${id}'.`);
|
|
1401
|
+
}
|
|
1402
|
+
})(!(oldId !== null && id !== oldId)) : {};
|
|
1313
1403
|
|
|
1314
1404
|
// ID can be null if oldID is not null (altered ID in response for a record)
|
|
1315
1405
|
// however, this is more than likely a developer error.
|
|
@@ -1317,7 +1407,7 @@ class InstanceCache {
|
|
|
1317
1407
|
warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
|
|
1318
1408
|
return;
|
|
1319
1409
|
}
|
|
1320
|
-
if (macroCondition(
|
|
1410
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
|
|
1321
1411
|
// eslint-disable-next-line no-console
|
|
1322
1412
|
console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
|
|
1323
1413
|
}
|
|
@@ -1325,7 +1415,11 @@ class InstanceCache {
|
|
|
1325
1415
|
type,
|
|
1326
1416
|
id
|
|
1327
1417
|
});
|
|
1328
|
-
|
|
1418
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1419
|
+
if (!test) {
|
|
1420
|
+
throw new Error(`'${type}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`);
|
|
1421
|
+
}
|
|
1422
|
+
})(!existingIdentifier || existingIdentifier === identifier) : {};
|
|
1329
1423
|
if (identifier.id === null) {
|
|
1330
1424
|
// TODO potentially this needs to handle merged result
|
|
1331
1425
|
this.store.identifierCache.updateRecordIdentifier(identifier, {
|
|
@@ -1362,16 +1456,16 @@ function resourceIsFullyDeleted(instanceCache, identifier) {
|
|
|
1362
1456
|
function preloadData(store, identifier, preload) {
|
|
1363
1457
|
const jsonPayload = {};
|
|
1364
1458
|
//TODO(Igor) consider the polymorphic case
|
|
1365
|
-
const schemas = store.
|
|
1366
|
-
const
|
|
1459
|
+
const schemas = store.schema;
|
|
1460
|
+
const fields = schemas.fields(identifier);
|
|
1367
1461
|
Object.keys(preload).forEach(key => {
|
|
1368
1462
|
const preloadValue = preload[key];
|
|
1369
|
-
const
|
|
1370
|
-
if (
|
|
1463
|
+
const field = fields.get(key);
|
|
1464
|
+
if (field && (field.kind === 'hasMany' || field.kind === 'belongsTo')) {
|
|
1371
1465
|
if (!jsonPayload.relationships) {
|
|
1372
1466
|
jsonPayload.relationships = {};
|
|
1373
1467
|
}
|
|
1374
|
-
jsonPayload.relationships[key] = preloadRelationship(
|
|
1468
|
+
jsonPayload.relationships[key] = preloadRelationship(field, preloadValue);
|
|
1375
1469
|
} else {
|
|
1376
1470
|
if (!jsonPayload.attributes) {
|
|
1377
1471
|
jsonPayload.attributes = {};
|
|
@@ -1386,12 +1480,20 @@ function preloadData(store, identifier, preload) {
|
|
|
1386
1480
|
function preloadRelationship(schema, preloadValue) {
|
|
1387
1481
|
const relatedType = schema.type;
|
|
1388
1482
|
if (schema.kind === 'hasMany') {
|
|
1389
|
-
|
|
1483
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1484
|
+
if (!test) {
|
|
1485
|
+
throw new Error('You need to pass in an array to set a hasMany property on a record');
|
|
1486
|
+
}
|
|
1487
|
+
})(Array.isArray(preloadValue)) : {};
|
|
1390
1488
|
return {
|
|
1391
1489
|
data: preloadValue.map(value => _convertPreloadRelationshipToJSON(value, relatedType))
|
|
1392
1490
|
};
|
|
1393
1491
|
}
|
|
1394
|
-
|
|
1492
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1493
|
+
if (!test) {
|
|
1494
|
+
throw new Error('You should not pass in an array to set a belongsTo property on a record');
|
|
1495
|
+
}
|
|
1496
|
+
})(!Array.isArray(preloadValue)) : {};
|
|
1395
1497
|
return {
|
|
1396
1498
|
data: preloadValue ? _convertPreloadRelationshipToJSON(preloadValue, relatedType) : null
|
|
1397
1499
|
};
|
|
@@ -1420,7 +1522,7 @@ function _clearCaches() {
|
|
|
1420
1522
|
|
|
1421
1523
|
// if modelFor turns out to be a bottleneck we should replace with a Map
|
|
1422
1524
|
// and clear it during store teardown.
|
|
1423
|
-
const AvailableShims = new WeakMap();
|
|
1525
|
+
const AvailableShims = getOrSetGlobal('AvailableShims', new WeakMap());
|
|
1424
1526
|
function getShimClass(store, modelName) {
|
|
1425
1527
|
let shims = AvailableShims.get(store);
|
|
1426
1528
|
if (!shims) {
|
|
@@ -1433,15 +1535,6 @@ function getShimClass(store, modelName) {
|
|
|
1433
1535
|
}
|
|
1434
1536
|
return shim;
|
|
1435
1537
|
}
|
|
1436
|
-
function mapFromHash(hash) {
|
|
1437
|
-
const map = new Map();
|
|
1438
|
-
for (const i in hash) {
|
|
1439
|
-
if (Object.prototype.hasOwnProperty.call(hash, i)) {
|
|
1440
|
-
map.set(i, hash[i]);
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
return map;
|
|
1444
|
-
}
|
|
1445
1538
|
|
|
1446
1539
|
// Mimics the static apis of @ember-data-mirror/model
|
|
1447
1540
|
class ShimModelClass {
|
|
@@ -1450,67 +1543,71 @@ class ShimModelClass {
|
|
|
1450
1543
|
this.modelName = modelName;
|
|
1451
1544
|
}
|
|
1452
1545
|
get fields() {
|
|
1453
|
-
const
|
|
1546
|
+
const fields = new Map();
|
|
1547
|
+
const fieldSchemas = this.__store.schema.fields({
|
|
1454
1548
|
type: this.modelName
|
|
1455
1549
|
});
|
|
1456
|
-
|
|
1457
|
-
|
|
1550
|
+
fieldSchemas.forEach((schema, key) => {
|
|
1551
|
+
if (schema.kind === 'attribute' || schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
|
|
1552
|
+
fields.set(key, schema.kind);
|
|
1553
|
+
}
|
|
1458
1554
|
});
|
|
1459
|
-
const fields = new Map();
|
|
1460
|
-
Object.keys(attrs).forEach(key => fields.set(key, 'attribute'));
|
|
1461
|
-
Object.keys(relationships).forEach(key => fields.set(key, relationships[key].kind));
|
|
1462
1555
|
return fields;
|
|
1463
1556
|
}
|
|
1464
1557
|
get attributes() {
|
|
1465
|
-
const attrs =
|
|
1558
|
+
const attrs = new Map();
|
|
1559
|
+
const fields = this.__store.schema.fields({
|
|
1466
1560
|
type: this.modelName
|
|
1467
1561
|
});
|
|
1468
|
-
|
|
1562
|
+
fields.forEach((schema, key) => {
|
|
1563
|
+
if (schema.kind === 'attribute') {
|
|
1564
|
+
attrs.set(key, schema);
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
return attrs;
|
|
1469
1568
|
}
|
|
1470
1569
|
get relationshipsByName() {
|
|
1471
|
-
const
|
|
1570
|
+
const rels = new Map();
|
|
1571
|
+
const fields = this.__store.schema.fields({
|
|
1472
1572
|
type: this.modelName
|
|
1473
1573
|
});
|
|
1474
|
-
|
|
1574
|
+
fields.forEach((schema, key) => {
|
|
1575
|
+
if (schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
|
|
1576
|
+
rels.set(key, schema);
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1579
|
+
return rels;
|
|
1475
1580
|
}
|
|
1476
1581
|
eachAttribute(callback, binding) {
|
|
1477
|
-
|
|
1582
|
+
this.__store.schema.fields({
|
|
1478
1583
|
type: this.modelName
|
|
1479
|
-
})
|
|
1480
|
-
|
|
1481
|
-
|
|
1584
|
+
}).forEach((schema, key) => {
|
|
1585
|
+
if (schema.kind === 'attribute') {
|
|
1586
|
+
callback.call(binding, key, schema);
|
|
1587
|
+
}
|
|
1482
1588
|
});
|
|
1483
1589
|
}
|
|
1484
1590
|
eachRelationship(callback, binding) {
|
|
1485
|
-
|
|
1591
|
+
this.__store.schema.fields({
|
|
1486
1592
|
type: this.modelName
|
|
1487
|
-
})
|
|
1488
|
-
|
|
1489
|
-
|
|
1593
|
+
}).forEach((schema, key) => {
|
|
1594
|
+
if (schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
|
|
1595
|
+
callback.call(binding, key, schema);
|
|
1596
|
+
}
|
|
1490
1597
|
});
|
|
1491
1598
|
}
|
|
1492
1599
|
eachTransformedAttribute(callback, binding) {
|
|
1493
|
-
|
|
1600
|
+
this.__store.schema.fields({
|
|
1494
1601
|
type: this.modelName
|
|
1495
|
-
})
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
callback.call(binding, key,
|
|
1602
|
+
}).forEach((schema, key) => {
|
|
1603
|
+
if (schema.kind === 'attribute') {
|
|
1604
|
+
const type = schema.type;
|
|
1605
|
+
if (type) callback.call(binding, key, type);
|
|
1499
1606
|
}
|
|
1500
1607
|
});
|
|
1501
1608
|
}
|
|
1502
1609
|
}
|
|
1503
|
-
|
|
1504
|
-
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
|
|
1505
|
-
throw new TypeError("attempted to use private field on non-instance");
|
|
1506
|
-
}
|
|
1507
|
-
return receiver;
|
|
1508
|
-
}
|
|
1509
|
-
var id = 0;
|
|
1510
|
-
function _classPrivateFieldKey(name) {
|
|
1511
|
-
return "__private_" + id++ + "_" + name;
|
|
1512
|
-
}
|
|
1513
|
-
var _cache = /*#__PURE__*/_classPrivateFieldKey("cache");
|
|
1610
|
+
|
|
1514
1611
|
/**
|
|
1515
1612
|
* The CacheManager wraps a Cache enforcing that only
|
|
1516
1613
|
* the public API surface area is exposed.
|
|
@@ -1530,13 +1627,10 @@ var _cache = /*#__PURE__*/_classPrivateFieldKey("cache");
|
|
|
1530
1627
|
* @public
|
|
1531
1628
|
*/
|
|
1532
1629
|
class CacheManager {
|
|
1630
|
+
version = '2';
|
|
1631
|
+
#cache;
|
|
1533
1632
|
constructor(cache) {
|
|
1534
|
-
this
|
|
1535
|
-
Object.defineProperty(this, _cache, {
|
|
1536
|
-
writable: true,
|
|
1537
|
-
value: void 0
|
|
1538
|
-
});
|
|
1539
|
-
_classPrivateFieldBase(this, _cache)[_cache] = cache;
|
|
1633
|
+
this.#cache = cache;
|
|
1540
1634
|
}
|
|
1541
1635
|
|
|
1542
1636
|
// Cache Management
|
|
@@ -1566,7 +1660,7 @@ class CacheManager {
|
|
|
1566
1660
|
* @public
|
|
1567
1661
|
*/
|
|
1568
1662
|
put(doc) {
|
|
1569
|
-
return
|
|
1663
|
+
return this.#cache.put(doc);
|
|
1570
1664
|
}
|
|
1571
1665
|
|
|
1572
1666
|
/**
|
|
@@ -1581,7 +1675,7 @@ class CacheManager {
|
|
|
1581
1675
|
* @return {void}
|
|
1582
1676
|
*/
|
|
1583
1677
|
patch(op) {
|
|
1584
|
-
|
|
1678
|
+
this.#cache.patch(op);
|
|
1585
1679
|
}
|
|
1586
1680
|
|
|
1587
1681
|
/**
|
|
@@ -1593,7 +1687,7 @@ class CacheManager {
|
|
|
1593
1687
|
* @param mutation
|
|
1594
1688
|
*/
|
|
1595
1689
|
mutate(mutation) {
|
|
1596
|
-
|
|
1690
|
+
this.#cache.mutate(mutation);
|
|
1597
1691
|
}
|
|
1598
1692
|
|
|
1599
1693
|
/**
|
|
@@ -1630,7 +1724,7 @@ class CacheManager {
|
|
|
1630
1724
|
*/
|
|
1631
1725
|
|
|
1632
1726
|
peek(identifier) {
|
|
1633
|
-
return
|
|
1727
|
+
return this.#cache.peek(identifier);
|
|
1634
1728
|
}
|
|
1635
1729
|
|
|
1636
1730
|
/**
|
|
@@ -1643,7 +1737,7 @@ class CacheManager {
|
|
|
1643
1737
|
* @public
|
|
1644
1738
|
*/
|
|
1645
1739
|
peekRequest(identifier) {
|
|
1646
|
-
return
|
|
1740
|
+
return this.#cache.peekRequest(identifier);
|
|
1647
1741
|
}
|
|
1648
1742
|
|
|
1649
1743
|
/**
|
|
@@ -1657,7 +1751,7 @@ class CacheManager {
|
|
|
1657
1751
|
* @return {void | string[]} if `hasRecord` is true then calculated key changes should be returned
|
|
1658
1752
|
*/
|
|
1659
1753
|
upsert(identifier, data, hasRecord) {
|
|
1660
|
-
return
|
|
1754
|
+
return this.#cache.upsert(identifier, data, hasRecord);
|
|
1661
1755
|
}
|
|
1662
1756
|
|
|
1663
1757
|
// Cache Forking Support
|
|
@@ -1675,7 +1769,7 @@ class CacheManager {
|
|
|
1675
1769
|
* @return Promise<Cache>
|
|
1676
1770
|
*/
|
|
1677
1771
|
fork() {
|
|
1678
|
-
return
|
|
1772
|
+
return this.#cache.fork();
|
|
1679
1773
|
}
|
|
1680
1774
|
|
|
1681
1775
|
/**
|
|
@@ -1691,7 +1785,7 @@ class CacheManager {
|
|
|
1691
1785
|
* @return Promise<void>
|
|
1692
1786
|
*/
|
|
1693
1787
|
merge(cache) {
|
|
1694
|
-
return
|
|
1788
|
+
return this.#cache.merge(cache);
|
|
1695
1789
|
}
|
|
1696
1790
|
|
|
1697
1791
|
/**
|
|
@@ -1728,7 +1822,7 @@ class CacheManager {
|
|
|
1728
1822
|
* @public
|
|
1729
1823
|
*/
|
|
1730
1824
|
diff() {
|
|
1731
|
-
return
|
|
1825
|
+
return this.#cache.diff();
|
|
1732
1826
|
}
|
|
1733
1827
|
|
|
1734
1828
|
// SSR Support
|
|
@@ -1744,7 +1838,7 @@ class CacheManager {
|
|
|
1744
1838
|
* @public
|
|
1745
1839
|
*/
|
|
1746
1840
|
dump() {
|
|
1747
|
-
return
|
|
1841
|
+
return this.#cache.dump();
|
|
1748
1842
|
}
|
|
1749
1843
|
|
|
1750
1844
|
/**
|
|
@@ -1765,7 +1859,7 @@ class CacheManager {
|
|
|
1765
1859
|
* @public
|
|
1766
1860
|
*/
|
|
1767
1861
|
hydrate(stream) {
|
|
1768
|
-
return
|
|
1862
|
+
return this.#cache.hydrate(stream);
|
|
1769
1863
|
}
|
|
1770
1864
|
|
|
1771
1865
|
// Cache
|
|
@@ -1786,7 +1880,7 @@ class CacheManager {
|
|
|
1786
1880
|
* @param options
|
|
1787
1881
|
*/
|
|
1788
1882
|
clientDidCreate(identifier, options) {
|
|
1789
|
-
return
|
|
1883
|
+
return this.#cache.clientDidCreate(identifier, options);
|
|
1790
1884
|
}
|
|
1791
1885
|
|
|
1792
1886
|
/**
|
|
@@ -1798,7 +1892,7 @@ class CacheManager {
|
|
|
1798
1892
|
* @param identifier
|
|
1799
1893
|
*/
|
|
1800
1894
|
willCommit(identifier, context) {
|
|
1801
|
-
|
|
1895
|
+
this.#cache.willCommit(identifier, context);
|
|
1802
1896
|
}
|
|
1803
1897
|
|
|
1804
1898
|
/**
|
|
@@ -1811,7 +1905,7 @@ class CacheManager {
|
|
|
1811
1905
|
* @param data
|
|
1812
1906
|
*/
|
|
1813
1907
|
didCommit(identifier, result) {
|
|
1814
|
-
return
|
|
1908
|
+
return this.#cache.didCommit(identifier, result);
|
|
1815
1909
|
}
|
|
1816
1910
|
|
|
1817
1911
|
/**
|
|
@@ -1824,7 +1918,7 @@ class CacheManager {
|
|
|
1824
1918
|
* @param errors
|
|
1825
1919
|
*/
|
|
1826
1920
|
commitWasRejected(identifier, errors) {
|
|
1827
|
-
|
|
1921
|
+
this.#cache.commitWasRejected(identifier, errors);
|
|
1828
1922
|
}
|
|
1829
1923
|
|
|
1830
1924
|
/**
|
|
@@ -1836,7 +1930,7 @@ class CacheManager {
|
|
|
1836
1930
|
* @param identifier
|
|
1837
1931
|
*/
|
|
1838
1932
|
unloadRecord(identifier) {
|
|
1839
|
-
|
|
1933
|
+
this.#cache.unloadRecord(identifier);
|
|
1840
1934
|
}
|
|
1841
1935
|
|
|
1842
1936
|
// Granular Resource Data APIs
|
|
@@ -1852,7 +1946,7 @@ class CacheManager {
|
|
|
1852
1946
|
* @return {unknown}
|
|
1853
1947
|
*/
|
|
1854
1948
|
getAttr(identifier, propertyName) {
|
|
1855
|
-
return
|
|
1949
|
+
return this.#cache.getAttr(identifier, propertyName);
|
|
1856
1950
|
}
|
|
1857
1951
|
|
|
1858
1952
|
/**
|
|
@@ -1865,7 +1959,7 @@ class CacheManager {
|
|
|
1865
1959
|
* @param value
|
|
1866
1960
|
*/
|
|
1867
1961
|
setAttr(identifier, propertyName, value) {
|
|
1868
|
-
|
|
1962
|
+
this.#cache.setAttr(identifier, propertyName, value);
|
|
1869
1963
|
}
|
|
1870
1964
|
|
|
1871
1965
|
/**
|
|
@@ -1877,7 +1971,7 @@ class CacheManager {
|
|
|
1877
1971
|
* @return
|
|
1878
1972
|
*/
|
|
1879
1973
|
changedAttrs(identifier) {
|
|
1880
|
-
return
|
|
1974
|
+
return this.#cache.changedAttrs(identifier);
|
|
1881
1975
|
}
|
|
1882
1976
|
|
|
1883
1977
|
/**
|
|
@@ -1889,7 +1983,7 @@ class CacheManager {
|
|
|
1889
1983
|
* @return {boolean}
|
|
1890
1984
|
*/
|
|
1891
1985
|
hasChangedAttrs(identifier) {
|
|
1892
|
-
return
|
|
1986
|
+
return this.#cache.hasChangedAttrs(identifier);
|
|
1893
1987
|
}
|
|
1894
1988
|
|
|
1895
1989
|
/**
|
|
@@ -1901,7 +1995,7 @@ class CacheManager {
|
|
|
1901
1995
|
* @return the names of attributes that were restored
|
|
1902
1996
|
*/
|
|
1903
1997
|
rollbackAttrs(identifier) {
|
|
1904
|
-
return
|
|
1998
|
+
return this.#cache.rollbackAttrs(identifier);
|
|
1905
1999
|
}
|
|
1906
2000
|
|
|
1907
2001
|
// Relationships
|
|
@@ -1935,7 +2029,7 @@ class CacheManager {
|
|
|
1935
2029
|
* @return {Map<string, RelationshipDiff>}
|
|
1936
2030
|
*/
|
|
1937
2031
|
changedRelationships(identifier) {
|
|
1938
|
-
return
|
|
2032
|
+
return this.#cache.changedRelationships(identifier);
|
|
1939
2033
|
}
|
|
1940
2034
|
|
|
1941
2035
|
/**
|
|
@@ -1947,7 +2041,7 @@ class CacheManager {
|
|
|
1947
2041
|
* @return {boolean}
|
|
1948
2042
|
*/
|
|
1949
2043
|
hasChangedRelationships(identifier) {
|
|
1950
|
-
return
|
|
2044
|
+
return this.#cache.hasChangedRelationships(identifier);
|
|
1951
2045
|
}
|
|
1952
2046
|
|
|
1953
2047
|
/**
|
|
@@ -1963,7 +2057,7 @@ class CacheManager {
|
|
|
1963
2057
|
* @return {string[]} the names of relationships that were restored
|
|
1964
2058
|
*/
|
|
1965
2059
|
rollbackRelationships(identifier) {
|
|
1966
|
-
return
|
|
2060
|
+
return this.#cache.rollbackRelationships(identifier);
|
|
1967
2061
|
}
|
|
1968
2062
|
|
|
1969
2063
|
/**
|
|
@@ -1976,7 +2070,7 @@ class CacheManager {
|
|
|
1976
2070
|
* @return resource relationship object
|
|
1977
2071
|
*/
|
|
1978
2072
|
getRelationship(identifier, propertyName) {
|
|
1979
|
-
return
|
|
2073
|
+
return this.#cache.getRelationship(identifier, propertyName);
|
|
1980
2074
|
}
|
|
1981
2075
|
|
|
1982
2076
|
// Resource State
|
|
@@ -1992,7 +2086,7 @@ class CacheManager {
|
|
|
1992
2086
|
* @param isDeleted
|
|
1993
2087
|
*/
|
|
1994
2088
|
setIsDeleted(identifier, isDeleted) {
|
|
1995
|
-
|
|
2089
|
+
this.#cache.setIsDeleted(identifier, isDeleted);
|
|
1996
2090
|
}
|
|
1997
2091
|
|
|
1998
2092
|
/**
|
|
@@ -2004,7 +2098,7 @@ class CacheManager {
|
|
|
2004
2098
|
* @return
|
|
2005
2099
|
*/
|
|
2006
2100
|
getErrors(identifier) {
|
|
2007
|
-
return
|
|
2101
|
+
return this.#cache.getErrors(identifier);
|
|
2008
2102
|
}
|
|
2009
2103
|
|
|
2010
2104
|
/**
|
|
@@ -2016,7 +2110,7 @@ class CacheManager {
|
|
|
2016
2110
|
* @return {boolean}
|
|
2017
2111
|
*/
|
|
2018
2112
|
isEmpty(identifier) {
|
|
2019
|
-
return
|
|
2113
|
+
return this.#cache.isEmpty(identifier);
|
|
2020
2114
|
}
|
|
2021
2115
|
|
|
2022
2116
|
/**
|
|
@@ -2029,7 +2123,7 @@ class CacheManager {
|
|
|
2029
2123
|
* @return {boolean}
|
|
2030
2124
|
*/
|
|
2031
2125
|
isNew(identifier) {
|
|
2032
|
-
return
|
|
2126
|
+
return this.#cache.isNew(identifier);
|
|
2033
2127
|
}
|
|
2034
2128
|
|
|
2035
2129
|
/**
|
|
@@ -2042,7 +2136,7 @@ class CacheManager {
|
|
|
2042
2136
|
* @return {boolean}
|
|
2043
2137
|
*/
|
|
2044
2138
|
isDeleted(identifier) {
|
|
2045
|
-
return
|
|
2139
|
+
return this.#cache.isDeleted(identifier);
|
|
2046
2140
|
}
|
|
2047
2141
|
|
|
2048
2142
|
/**
|
|
@@ -2055,13 +2149,14 @@ class CacheManager {
|
|
|
2055
2149
|
* @return {boolean}
|
|
2056
2150
|
*/
|
|
2057
2151
|
isDeletionCommitted(identifier) {
|
|
2058
|
-
return
|
|
2152
|
+
return this.#cache.isDeletionCommitted(identifier);
|
|
2059
2153
|
}
|
|
2060
2154
|
}
|
|
2061
2155
|
|
|
2062
2156
|
/**
|
|
2063
2157
|
* @module @ember-data-mirror/store
|
|
2064
2158
|
*/
|
|
2159
|
+
// eslint-disable-next-line no-restricted-imports
|
|
2065
2160
|
let tokenId = 0;
|
|
2066
2161
|
const CacheOperations = new Set(['added', 'removed', 'state', 'updated']);
|
|
2067
2162
|
function isCacheOperationValue(value) {
|
|
@@ -2073,7 +2168,7 @@ function runLoopIsFlushing() {
|
|
|
2073
2168
|
}
|
|
2074
2169
|
function _unsubscribe(tokens, token, cache) {
|
|
2075
2170
|
const identifier = tokens.get(token);
|
|
2076
|
-
if (macroCondition(
|
|
2171
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
|
|
2077
2172
|
if (!identifier) {
|
|
2078
2173
|
// eslint-disable-next-line no-console
|
|
2079
2174
|
console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
|
|
@@ -2135,13 +2230,17 @@ class NotificationManager {
|
|
|
2135
2230
|
*/
|
|
2136
2231
|
|
|
2137
2232
|
subscribe(identifier, callback) {
|
|
2138
|
-
|
|
2233
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2234
|
+
if (!test) {
|
|
2235
|
+
throw new Error(`Expected to receive a stable Identifier to subscribe to`);
|
|
2236
|
+
}
|
|
2237
|
+
})(identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier) || isDocumentIdentifier(identifier)) : {};
|
|
2139
2238
|
let map = this._cache.get(identifier);
|
|
2140
2239
|
if (!map) {
|
|
2141
2240
|
map = new Map();
|
|
2142
2241
|
this._cache.set(identifier, map);
|
|
2143
2242
|
}
|
|
2144
|
-
const unsubToken = macroCondition(
|
|
2243
|
+
const unsubToken = macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? {
|
|
2145
2244
|
_tokenRef: tokenId++
|
|
2146
2245
|
} : {};
|
|
2147
2246
|
map.set(unsubToken, callback);
|
|
@@ -2174,15 +2273,19 @@ class NotificationManager {
|
|
|
2174
2273
|
*/
|
|
2175
2274
|
|
|
2176
2275
|
notify(identifier, value, key) {
|
|
2177
|
-
|
|
2276
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2277
|
+
if (!test) {
|
|
2278
|
+
throw new Error(`Notify does not accept a key argument for the namespace '${value}'. Received key '${key || ''}'.`);
|
|
2279
|
+
}
|
|
2280
|
+
})(!key || value === 'attributes' || value === 'relationships') : {};
|
|
2178
2281
|
if (!isStableIdentifier(identifier) && !isDocumentIdentifier(identifier)) {
|
|
2179
|
-
if (macroCondition(
|
|
2282
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
|
|
2180
2283
|
// eslint-disable-next-line no-console
|
|
2181
2284
|
console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
|
|
2182
2285
|
}
|
|
2183
2286
|
return false;
|
|
2184
2287
|
}
|
|
2185
|
-
if (macroCondition(
|
|
2288
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
|
|
2186
2289
|
// eslint-disable-next-line no-console
|
|
2187
2290
|
console.log(`Buffering Notify: ${String(identifier.lid)}\t${value}\t${key || ''}`);
|
|
2188
2291
|
}
|
|
@@ -2229,7 +2332,7 @@ class NotificationManager {
|
|
|
2229
2332
|
this._onFlushCB = undefined;
|
|
2230
2333
|
}
|
|
2231
2334
|
_flushNotification(identifier, value, key) {
|
|
2232
|
-
if (macroCondition(
|
|
2335
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
|
|
2233
2336
|
// eslint-disable-next-line no-console
|
|
2234
2337
|
console.log(`Notifying: ${String(identifier)}\t${value}\t${key || ''}`);
|
|
2235
2338
|
}
|
|
@@ -2259,29 +2362,6 @@ class NotificationManager {
|
|
|
2259
2362
|
this._cache.clear();
|
|
2260
2363
|
}
|
|
2261
2364
|
}
|
|
2262
|
-
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
2263
|
-
var desc = {};
|
|
2264
|
-
Object.keys(descriptor).forEach(function (key) {
|
|
2265
|
-
desc[key] = descriptor[key];
|
|
2266
|
-
});
|
|
2267
|
-
desc.enumerable = !!desc.enumerable;
|
|
2268
|
-
desc.configurable = !!desc.configurable;
|
|
2269
|
-
if ('value' in desc || desc.initializer) {
|
|
2270
|
-
desc.writable = true;
|
|
2271
|
-
}
|
|
2272
|
-
desc = decorators.slice().reverse().reduce(function (desc, decorator) {
|
|
2273
|
-
return decorator(target, property, desc) || desc;
|
|
2274
|
-
}, desc);
|
|
2275
|
-
if (context && desc.initializer !== void 0) {
|
|
2276
|
-
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
2277
|
-
desc.initializer = undefined;
|
|
2278
|
-
}
|
|
2279
|
-
if (desc.initializer === void 0) {
|
|
2280
|
-
Object.defineProperty(target, property, desc);
|
|
2281
|
-
desc = null;
|
|
2282
|
-
}
|
|
2283
|
-
return desc;
|
|
2284
|
-
}
|
|
2285
2365
|
|
|
2286
2366
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2287
2367
|
/*
|
|
@@ -2292,7 +2372,129 @@ function _applyDecoratedDescriptor(target, property, decorators, descriptor, con
|
|
|
2292
2372
|
*/
|
|
2293
2373
|
|
|
2294
2374
|
const NativeProxy = Proxy;
|
|
2295
|
-
var
|
|
2375
|
+
var __defProp = Object.defineProperty;
|
|
2376
|
+
var __export = (target, all) => {
|
|
2377
|
+
for (var name in all) __defProp(target, name, {
|
|
2378
|
+
get: all[name],
|
|
2379
|
+
enumerable: true
|
|
2380
|
+
});
|
|
2381
|
+
};
|
|
2382
|
+
|
|
2383
|
+
// src/runtime.ts
|
|
2384
|
+
var runtime_exports = {};
|
|
2385
|
+
__export(runtime_exports, {
|
|
2386
|
+
c: () => decorateClass,
|
|
2387
|
+
f: () => decorateFieldV1,
|
|
2388
|
+
g: () => decorateFieldV2,
|
|
2389
|
+
i: () => initializeDeferredDecorator,
|
|
2390
|
+
m: () => decorateMethodV1,
|
|
2391
|
+
n: () => decorateMethodV2,
|
|
2392
|
+
p: () => decoratePOJO
|
|
2393
|
+
});
|
|
2394
|
+
var deferred = /* @__PURE__ */new WeakMap();
|
|
2395
|
+
function deferDecorator(proto, prop, desc) {
|
|
2396
|
+
let map = deferred.get(proto);
|
|
2397
|
+
if (!map) {
|
|
2398
|
+
map = /* @__PURE__ */new Map();
|
|
2399
|
+
deferred.set(proto, map);
|
|
2400
|
+
}
|
|
2401
|
+
map.set(prop, desc);
|
|
2402
|
+
}
|
|
2403
|
+
function findDeferredDecorator(target, prop) {
|
|
2404
|
+
let cursor = target.prototype;
|
|
2405
|
+
while (cursor) {
|
|
2406
|
+
let desc = deferred.get(cursor)?.get(prop);
|
|
2407
|
+
if (desc) {
|
|
2408
|
+
return desc;
|
|
2409
|
+
}
|
|
2410
|
+
cursor = cursor.prototype;
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
function decorateFieldV1(target, prop, decorators, initializer) {
|
|
2414
|
+
return decorateFieldV2(target.prototype, prop, decorators, initializer);
|
|
2415
|
+
}
|
|
2416
|
+
function decorateFieldV2(prototype, prop, decorators, initializer) {
|
|
2417
|
+
let desc = {
|
|
2418
|
+
configurable: true,
|
|
2419
|
+
enumerable: true,
|
|
2420
|
+
writable: true,
|
|
2421
|
+
initializer: null
|
|
2422
|
+
};
|
|
2423
|
+
if (initializer) {
|
|
2424
|
+
desc.initializer = initializer;
|
|
2425
|
+
}
|
|
2426
|
+
for (let decorator of decorators) {
|
|
2427
|
+
desc = decorator(prototype, prop, desc) || desc;
|
|
2428
|
+
}
|
|
2429
|
+
if (desc.initializer === void 0) {
|
|
2430
|
+
Object.defineProperty(prototype, prop, desc);
|
|
2431
|
+
} else {
|
|
2432
|
+
deferDecorator(prototype, prop, desc);
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
function decorateMethodV1({
|
|
2436
|
+
prototype
|
|
2437
|
+
}, prop, decorators) {
|
|
2438
|
+
return decorateMethodV2(prototype, prop, decorators);
|
|
2439
|
+
}
|
|
2440
|
+
function decorateMethodV2(prototype, prop, decorators) {
|
|
2441
|
+
const origDesc = Object.getOwnPropertyDescriptor(prototype, prop);
|
|
2442
|
+
let desc = {
|
|
2443
|
+
...origDesc
|
|
2444
|
+
};
|
|
2445
|
+
for (let decorator of decorators) {
|
|
2446
|
+
desc = decorator(prototype, prop, desc) || desc;
|
|
2447
|
+
}
|
|
2448
|
+
if (desc.initializer !== void 0) {
|
|
2449
|
+
desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
|
|
2450
|
+
desc.initializer = void 0;
|
|
2451
|
+
}
|
|
2452
|
+
Object.defineProperty(prototype, prop, desc);
|
|
2453
|
+
}
|
|
2454
|
+
function initializeDeferredDecorator(target, prop) {
|
|
2455
|
+
let desc = findDeferredDecorator(target.constructor, prop);
|
|
2456
|
+
if (desc) {
|
|
2457
|
+
Object.defineProperty(target, prop, {
|
|
2458
|
+
enumerable: desc.enumerable,
|
|
2459
|
+
configurable: desc.configurable,
|
|
2460
|
+
writable: desc.writable,
|
|
2461
|
+
value: desc.initializer ? desc.initializer.call(target) : void 0
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
function decorateClass(target, decorators) {
|
|
2466
|
+
return decorators.reduce((accum, decorator) => decorator(accum) || accum, target);
|
|
2467
|
+
}
|
|
2468
|
+
function decoratePOJO(pojo, decorated) {
|
|
2469
|
+
for (let [type, prop, decorators] of decorated) {
|
|
2470
|
+
if (type === "field") {
|
|
2471
|
+
decoratePojoField(pojo, prop, decorators);
|
|
2472
|
+
} else {
|
|
2473
|
+
decorateMethodV2(pojo, prop, decorators);
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
return pojo;
|
|
2477
|
+
}
|
|
2478
|
+
function decoratePojoField(pojo, prop, decorators) {
|
|
2479
|
+
let desc = {
|
|
2480
|
+
configurable: true,
|
|
2481
|
+
enumerable: true,
|
|
2482
|
+
writable: true,
|
|
2483
|
+
initializer: () => Object.getOwnPropertyDescriptor(pojo, prop)?.value
|
|
2484
|
+
};
|
|
2485
|
+
for (let decorator of decorators) {
|
|
2486
|
+
desc = decorator(pojo, prop, desc) || desc;
|
|
2487
|
+
}
|
|
2488
|
+
if (desc.initializer) {
|
|
2489
|
+
desc.value = desc.initializer.call(pojo);
|
|
2490
|
+
delete desc.initializer;
|
|
2491
|
+
}
|
|
2492
|
+
Object.defineProperty(pojo, prop, desc);
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
/**
|
|
2496
|
+
@module @ember-data-mirror/store
|
|
2497
|
+
*/
|
|
2296
2498
|
const ARRAY_GETTER_METHODS = new Set([Symbol.iterator, 'concat', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'flat', 'flatMap', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'map', 'reduce', 'reduceRight', 'slice', 'some', 'values']);
|
|
2297
2499
|
const ARRAY_SETTER_METHODS = new Set(['push', 'pop', 'unshift', 'shift', 'splice', 'sort']);
|
|
2298
2500
|
const SYNC_PROPS = new Set(['[]', 'length', 'links', 'meta']);
|
|
@@ -2305,11 +2507,11 @@ function isArraySetter(prop) {
|
|
|
2305
2507
|
function isSelfProp(self, prop) {
|
|
2306
2508
|
return prop in self;
|
|
2307
2509
|
}
|
|
2308
|
-
const ARRAY_SIGNAL = Symbol('#signal');
|
|
2309
|
-
const SOURCE = Symbol('#source');
|
|
2310
|
-
const MUTATE = Symbol('#update');
|
|
2311
|
-
const NOTIFY = Symbol('#notify');
|
|
2312
|
-
const IS_COLLECTION = Symbol.for('Collection');
|
|
2510
|
+
const ARRAY_SIGNAL = getOrSetGlobal('#signal', Symbol('#signal'));
|
|
2511
|
+
const SOURCE = getOrSetGlobal('#source', Symbol('#source'));
|
|
2512
|
+
const MUTATE = getOrSetGlobal('#update', Symbol('#update'));
|
|
2513
|
+
const NOTIFY = getOrSetGlobal('#notify', Symbol('#notify'));
|
|
2514
|
+
const IS_COLLECTION = getOrSetGlobal('IS_COLLECTION', Symbol.for('Collection'));
|
|
2313
2515
|
function notifyArray(arr) {
|
|
2314
2516
|
addToTransaction(arr[ARRAY_SIGNAL]);
|
|
2315
2517
|
}
|
|
@@ -2325,7 +2527,11 @@ function safeForEach(instance, arr, store, callback, target) {
|
|
|
2325
2527
|
}
|
|
2326
2528
|
// clone to prevent mutation
|
|
2327
2529
|
arr = arr.slice();
|
|
2328
|
-
|
|
2530
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2531
|
+
if (!test) {
|
|
2532
|
+
throw new Error('`forEach` expects a function as first argument.');
|
|
2533
|
+
}
|
|
2534
|
+
})(typeof callback === 'function') : {};
|
|
2329
2535
|
|
|
2330
2536
|
// because we retrieveLatest above we need not worry if array is mutated during iteration
|
|
2331
2537
|
// by unloadRecord/rollbackAttributes
|
|
@@ -2351,7 +2557,28 @@ function safeForEach(instance, arr, store, callback, target) {
|
|
|
2351
2557
|
@class RecordArray
|
|
2352
2558
|
@public
|
|
2353
2559
|
*/
|
|
2354
|
-
|
|
2560
|
+
|
|
2561
|
+
class IdentifierArray {
|
|
2562
|
+
/**
|
|
2563
|
+
The flag to signal a `RecordArray` is currently loading data.
|
|
2564
|
+
Example
|
|
2565
|
+
```javascript
|
|
2566
|
+
let people = store.peekAll('person');
|
|
2567
|
+
people.isUpdating; // false
|
|
2568
|
+
people.update();
|
|
2569
|
+
people.isUpdating; // true
|
|
2570
|
+
```
|
|
2571
|
+
@property isUpdating
|
|
2572
|
+
@public
|
|
2573
|
+
@type Boolean
|
|
2574
|
+
*/
|
|
2575
|
+
|
|
2576
|
+
isLoaded = true;
|
|
2577
|
+
isDestroying = false;
|
|
2578
|
+
isDestroyed = false;
|
|
2579
|
+
_updatingPromise = null;
|
|
2580
|
+
[IS_COLLECTION] = true;
|
|
2581
|
+
[SOURCE];
|
|
2355
2582
|
[NOTIFY]() {
|
|
2356
2583
|
notifyArray(this);
|
|
2357
2584
|
}
|
|
@@ -2376,29 +2603,13 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2376
2603
|
get length() {
|
|
2377
2604
|
return this[SOURCE].length;
|
|
2378
2605
|
}
|
|
2606
|
+
static {
|
|
2607
|
+
decorateMethodV2(this.prototype, "length", [compat]);
|
|
2608
|
+
}
|
|
2379
2609
|
set length(value) {
|
|
2380
2610
|
this[SOURCE].length = value;
|
|
2381
2611
|
}
|
|
2382
2612
|
constructor(options) {
|
|
2383
|
-
/**
|
|
2384
|
-
The flag to signal a `RecordArray` is currently loading data.
|
|
2385
|
-
Example
|
|
2386
|
-
```javascript
|
|
2387
|
-
let people = store.peekAll('person');
|
|
2388
|
-
people.isUpdating; // false
|
|
2389
|
-
people.update();
|
|
2390
|
-
people.isUpdating; // true
|
|
2391
|
-
```
|
|
2392
|
-
@property isUpdating
|
|
2393
|
-
@public
|
|
2394
|
-
@type Boolean
|
|
2395
|
-
*/
|
|
2396
|
-
this.isLoaded = true;
|
|
2397
|
-
this.isDestroying = false;
|
|
2398
|
-
this.isDestroyed = false;
|
|
2399
|
-
this._updatingPromise = null;
|
|
2400
|
-
this[IS_COLLECTION] = true;
|
|
2401
|
-
this[SOURCE] = void 0;
|
|
2402
2613
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
2403
2614
|
const self = this;
|
|
2404
2615
|
this.modelName = options.type;
|
|
@@ -2470,11 +2681,19 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2470
2681
|
// array functions must run through Reflect to work properly
|
|
2471
2682
|
// binding via other means will not work.
|
|
2472
2683
|
if (!options.allowMutation) {
|
|
2473
|
-
|
|
2684
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2685
|
+
if (!test) {
|
|
2686
|
+
throw new Error(`Mutating this array of records via ${String(prop)} is not allowed.`);
|
|
2687
|
+
}
|
|
2688
|
+
})(options.allowMutation) : {};
|
|
2474
2689
|
return;
|
|
2475
2690
|
}
|
|
2476
2691
|
const args = Array.prototype.slice.call(arguments);
|
|
2477
|
-
|
|
2692
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2693
|
+
if (!test) {
|
|
2694
|
+
throw new Error(`Cannot start a new array transaction while a previous transaction is underway`);
|
|
2695
|
+
}
|
|
2696
|
+
})(!transaction) : {};
|
|
2478
2697
|
transaction = true;
|
|
2479
2698
|
const result = self[MUTATE](target, receiver, prop, args, _SIGNAL);
|
|
2480
2699
|
transaction = false;
|
|
@@ -2516,7 +2735,11 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2516
2735
|
} else if (transaction) {
|
|
2517
2736
|
return Reflect.set(target, prop, value);
|
|
2518
2737
|
} else {
|
|
2519
|
-
|
|
2738
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2739
|
+
{
|
|
2740
|
+
throw new Error(`unexpected length set`);
|
|
2741
|
+
}
|
|
2742
|
+
})() : {};
|
|
2520
2743
|
}
|
|
2521
2744
|
}
|
|
2522
2745
|
if (prop === 'links') {
|
|
@@ -2539,7 +2762,11 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2539
2762
|
if (index === null || index > target.length) {
|
|
2540
2763
|
if (index !== null && transaction) {
|
|
2541
2764
|
const identifier = recordIdentifierFor(value);
|
|
2542
|
-
|
|
2765
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2766
|
+
if (!test) {
|
|
2767
|
+
throw new Error(`Cannot set index ${index} past the end of the array.`);
|
|
2768
|
+
}
|
|
2769
|
+
})(isStableIdentifier(identifier)) : {};
|
|
2543
2770
|
target[index] = identifier;
|
|
2544
2771
|
return true;
|
|
2545
2772
|
} else if (isSelfProp(self, prop)) {
|
|
@@ -2550,13 +2777,21 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2550
2777
|
return false;
|
|
2551
2778
|
}
|
|
2552
2779
|
if (!options.allowMutation) {
|
|
2553
|
-
|
|
2780
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2781
|
+
if (!test) {
|
|
2782
|
+
throw new Error(`Mutating ${String(prop)} on this Array is not allowed.`);
|
|
2783
|
+
}
|
|
2784
|
+
})(options.allowMutation) : {};
|
|
2554
2785
|
return false;
|
|
2555
2786
|
}
|
|
2556
2787
|
const original = target[index];
|
|
2557
2788
|
const newIdentifier = extractIdentifierFromRecord$1(value);
|
|
2558
2789
|
target[index] = newIdentifier;
|
|
2559
|
-
|
|
2790
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2791
|
+
if (!test) {
|
|
2792
|
+
throw new Error(`Expected a record`);
|
|
2793
|
+
}
|
|
2794
|
+
})(isStableIdentifier(newIdentifier)) : {};
|
|
2560
2795
|
// We generate "transactions" whenever a setter method on the array
|
|
2561
2796
|
// is called and might bulk update multiple array cells. Fundamentally,
|
|
2562
2797
|
// all array operations decompose into individual cell replacements.
|
|
@@ -2581,7 +2816,11 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2581
2816
|
return true;
|
|
2582
2817
|
},
|
|
2583
2818
|
deleteProperty(target, prop) {
|
|
2584
|
-
|
|
2819
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2820
|
+
if (!test) {
|
|
2821
|
+
throw new Error(`Deleting keys on managed arrays is disallowed`);
|
|
2822
|
+
}
|
|
2823
|
+
})(transaction) : {};
|
|
2585
2824
|
if (!transaction) {
|
|
2586
2825
|
return false;
|
|
2587
2826
|
}
|
|
@@ -2629,11 +2868,15 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2629
2868
|
}
|
|
2630
2869
|
|
|
2631
2870
|
/*
|
|
2632
|
-
Update this
|
|
2871
|
+
Update this Array and return a promise which resolves once the update
|
|
2633
2872
|
is finished.
|
|
2634
2873
|
*/
|
|
2635
2874
|
_update() {
|
|
2636
|
-
|
|
2875
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2876
|
+
if (!test) {
|
|
2877
|
+
throw new Error(`_update cannot be used with this array`);
|
|
2878
|
+
}
|
|
2879
|
+
})(this.modelName) : {};
|
|
2637
2880
|
// @ts-expect-error typescript is unable to handle the complexity of
|
|
2638
2881
|
// T = unknown, modelName = string
|
|
2639
2882
|
// T extends TypedRecordInstance, modelName = TypeFromInstance<T>
|
|
@@ -2662,7 +2905,9 @@ let IdentifierArray = (_class = class IdentifierArray {
|
|
|
2662
2905
|
const promise = Promise.all(this.map(record => this.store.saveRecord(record))).then(() => this);
|
|
2663
2906
|
return promise;
|
|
2664
2907
|
}
|
|
2665
|
-
}
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
// this will error if someone tries to call
|
|
2666
2911
|
// A(identifierArray) since it is not configurable
|
|
2667
2912
|
// which is preferable to the `meta` override we used
|
|
2668
2913
|
// before which required importing all of Ember
|
|
@@ -2677,9 +2922,9 @@ compat(desc);
|
|
|
2677
2922
|
Object.defineProperty(IdentifierArray.prototype, '[]', desc);
|
|
2678
2923
|
defineSignal(IdentifierArray.prototype, 'isUpdating', false);
|
|
2679
2924
|
class Collection extends IdentifierArray {
|
|
2925
|
+
query = null;
|
|
2680
2926
|
constructor(options) {
|
|
2681
2927
|
super(options);
|
|
2682
|
-
this.query = null;
|
|
2683
2928
|
this.query = options.query || null;
|
|
2684
2929
|
this.isLoaded = options.isLoaded || false;
|
|
2685
2930
|
}
|
|
@@ -2690,8 +2935,16 @@ class Collection extends IdentifierArray {
|
|
|
2690
2935
|
} = this;
|
|
2691
2936
|
|
|
2692
2937
|
// TODO save options from initial request?
|
|
2693
|
-
|
|
2694
|
-
|
|
2938
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2939
|
+
if (!test) {
|
|
2940
|
+
throw new Error(`update cannot be used with this array`);
|
|
2941
|
+
}
|
|
2942
|
+
})(this.modelName) : {};
|
|
2943
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2944
|
+
if (!test) {
|
|
2945
|
+
throw new Error(`update cannot be used with no query`);
|
|
2946
|
+
}
|
|
2947
|
+
})(query) : {};
|
|
2695
2948
|
// @ts-expect-error typescript is unable to handle the complexity of
|
|
2696
2949
|
// T = unknown, modelName = string
|
|
2697
2950
|
// T extends TypedRecordInstance, modelName = TypeFromInstance<T>
|
|
@@ -2714,14 +2967,18 @@ Collection.prototype.query = null;
|
|
|
2714
2967
|
// Object.setPrototypeOf(IdentifierArray.prototype, Array.prototype);
|
|
2715
2968
|
|
|
2716
2969
|
function assertRecordPassedToHasMany(record) {
|
|
2717
|
-
|
|
2970
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2971
|
+
if (!test) {
|
|
2972
|
+
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`);
|
|
2973
|
+
}
|
|
2974
|
+
})(function () {
|
|
2718
2975
|
try {
|
|
2719
2976
|
recordIdentifierFor(record);
|
|
2720
2977
|
return true;
|
|
2721
2978
|
} catch {
|
|
2722
2979
|
return false;
|
|
2723
2980
|
}
|
|
2724
|
-
}());
|
|
2981
|
+
}()) : {};
|
|
2725
2982
|
}
|
|
2726
2983
|
function extractIdentifierFromRecord$1(record) {
|
|
2727
2984
|
if (!record) {
|
|
@@ -2734,7 +2991,7 @@ function extractIdentifierFromRecord$1(record) {
|
|
|
2734
2991
|
/**
|
|
2735
2992
|
@module @ember-data-mirror/store
|
|
2736
2993
|
*/
|
|
2737
|
-
const FAKE_ARR = {};
|
|
2994
|
+
const FAKE_ARR = getOrSetGlobal('FAKE_ARR', {});
|
|
2738
2995
|
const SLICE_BATCH_SIZE = 1200;
|
|
2739
2996
|
/**
|
|
2740
2997
|
* This is a clever optimization.
|
|
@@ -3082,9 +3339,10 @@ function sync(array, changes, arraySet) {
|
|
|
3082
3339
|
/**
|
|
3083
3340
|
* @module @ember-data-mirror/store
|
|
3084
3341
|
*/
|
|
3085
|
-
|
|
3086
|
-
const
|
|
3087
|
-
const
|
|
3342
|
+
|
|
3343
|
+
const Touching = getOrSetGlobal('Touching', Symbol('touching'));
|
|
3344
|
+
const RequestPromise = getOrSetGlobal('RequestPromise', Symbol('promise'));
|
|
3345
|
+
const EMPTY_ARR = macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? Object.freeze([]) : [];
|
|
3088
3346
|
function hasRecordIdentifier(op) {
|
|
3089
3347
|
return 'recordIdentifier' in op;
|
|
3090
3348
|
}
|
|
@@ -3097,12 +3355,12 @@ function hasRecordIdentifier(op) {
|
|
|
3097
3355
|
* @public
|
|
3098
3356
|
*/
|
|
3099
3357
|
class RequestStateService {
|
|
3358
|
+
_pending = new Map();
|
|
3359
|
+
_done = new Map();
|
|
3360
|
+
_subscriptions = new Map();
|
|
3361
|
+
_toFlush = [];
|
|
3362
|
+
_store;
|
|
3100
3363
|
constructor(store) {
|
|
3101
|
-
this._pending = new Map();
|
|
3102
|
-
this._done = new Map();
|
|
3103
|
-
this._subscriptions = new Map();
|
|
3104
|
-
this._toFlush = [];
|
|
3105
|
-
this._store = void 0;
|
|
3106
3364
|
this._store = store;
|
|
3107
3365
|
}
|
|
3108
3366
|
_clearEntries(identifier) {
|
|
@@ -3155,7 +3413,11 @@ class RequestStateService {
|
|
|
3155
3413
|
throw error;
|
|
3156
3414
|
});
|
|
3157
3415
|
}
|
|
3158
|
-
|
|
3416
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3417
|
+
{
|
|
3418
|
+
throw new Error(`Expected a well formed query`);
|
|
3419
|
+
}
|
|
3420
|
+
})() : {};
|
|
3159
3421
|
}
|
|
3160
3422
|
_triggerSubscriptions(req) {
|
|
3161
3423
|
if (req.state === 'pending') {
|
|
@@ -3288,8 +3550,16 @@ function constructResource(type, id, lid) {
|
|
|
3288
3550
|
if ('id' in resource) {
|
|
3289
3551
|
resource.id = coerceId(resource.id);
|
|
3290
3552
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3553
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3554
|
+
if (!test) {
|
|
3555
|
+
throw new Error('Expected either id or lid to be a valid string');
|
|
3556
|
+
}
|
|
3557
|
+
})('id' in resource && isNonEmptyString(resource.id) || isNonEmptyString(resource.lid)) : {};
|
|
3558
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3559
|
+
if (!test) {
|
|
3560
|
+
throw new Error('if id is present, the type must be a string');
|
|
3561
|
+
}
|
|
3562
|
+
})(!('id' in resource) || typeof resource.type === 'string') : {};
|
|
3293
3563
|
return resource;
|
|
3294
3564
|
} else {
|
|
3295
3565
|
const trueId = coerceId(id);
|
|
@@ -3301,7 +3571,11 @@ function constructResource(type, id, lid) {
|
|
|
3301
3571
|
}
|
|
3302
3572
|
throw new Error('Expected either id or lid to be a valid string');
|
|
3303
3573
|
}
|
|
3304
|
-
|
|
3574
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3575
|
+
if (!test) {
|
|
3576
|
+
throw new Error('type must be a string');
|
|
3577
|
+
}
|
|
3578
|
+
})(typeof type === 'string') : {};
|
|
3305
3579
|
if (isNonEmptyString(lid)) {
|
|
3306
3580
|
return {
|
|
3307
3581
|
type,
|
|
@@ -3321,6 +3595,8 @@ function constructResource(type, id, lid) {
|
|
|
3321
3595
|
*/
|
|
3322
3596
|
// this import location is deprecated but breaks in 4.8 and older
|
|
3323
3597
|
|
|
3598
|
+
// `AwaitedKeys` is needed here to resolve any promise types like `PromiseBelongsTo`.
|
|
3599
|
+
|
|
3324
3600
|
/**
|
|
3325
3601
|
* Currently only records that extend object can be created via
|
|
3326
3602
|
* store.createRecord. This is a limitation of the current API,
|
|
@@ -3350,18 +3626,47 @@ function constructResource(type, id, lid) {
|
|
|
3350
3626
|
* export default class extends Store {}
|
|
3351
3627
|
* ```
|
|
3352
3628
|
*
|
|
3353
|
-
* Most
|
|
3629
|
+
* Most Applications will only have a single `Store` configured as a Service
|
|
3354
3630
|
* in this manner. However, setting up multiple stores is possible, including using
|
|
3355
|
-
* each as a unique service.
|
|
3631
|
+
* each as a unique service or within a specific context.
|
|
3356
3632
|
*
|
|
3357
3633
|
|
|
3358
3634
|
@class Store
|
|
3359
3635
|
@public
|
|
3360
3636
|
*/
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3637
|
+
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
3638
|
+
const EmptyClass = class {
|
|
3639
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
3640
|
+
constructor(args) {}
|
|
3641
|
+
};
|
|
3642
|
+
const BaseClass = macroCondition(dependencySatisfies('ember-source', '*')) ? macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_STORE_EXTENDS_EMBER_OBJECT) ? importSync('@ember/object') : EmptyClass : EmptyClass;
|
|
3643
|
+
if (BaseClass !== EmptyClass) {
|
|
3644
|
+
deprecate(`The Store class extending from EmberObject is deprecated.
|
|
3645
|
+
Please remove usage of EmberObject APIs and mark your class as not requiring it.
|
|
3646
|
+
|
|
3647
|
+
To mark the class as no longer extending from EmberObject, in ember-cli-build.js
|
|
3648
|
+
set the following config:
|
|
3649
|
+
|
|
3650
|
+
\`\`\`js
|
|
3651
|
+
const app = new EmberApp(defaults, {
|
|
3652
|
+
emberData: {
|
|
3653
|
+
deprecations: {
|
|
3654
|
+
DEPRECATE_STORE_EXTENDS_EMBER_OBJECT: false
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
});
|
|
3658
|
+
\`\`\`
|
|
3659
|
+
`, false, {
|
|
3660
|
+
id: 'ember-data-mirror:deprecate-store-extends-ember-object',
|
|
3661
|
+
until: '6.0',
|
|
3662
|
+
for: 'ember-data-mirror',
|
|
3663
|
+
since: {
|
|
3664
|
+
available: '5.4',
|
|
3665
|
+
enabled: '5.4'
|
|
3666
|
+
}
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3669
|
+
class Store extends BaseClass {
|
|
3365
3670
|
/**
|
|
3366
3671
|
* Provides access to the NotificationManager associated
|
|
3367
3672
|
* with this Store instance.
|
|
@@ -3384,7 +3689,10 @@ class Store extends EmberObject {
|
|
|
3384
3689
|
* @public
|
|
3385
3690
|
*/
|
|
3386
3691
|
get schema() {
|
|
3387
|
-
|
|
3692
|
+
if (!this._schema) {
|
|
3693
|
+
this._schema = this.createSchemaService();
|
|
3694
|
+
}
|
|
3695
|
+
return this._schema;
|
|
3388
3696
|
}
|
|
3389
3697
|
|
|
3390
3698
|
/**
|
|
@@ -3410,7 +3718,7 @@ class Store extends EmberObject {
|
|
|
3410
3718
|
* ```ts
|
|
3411
3719
|
* import Store, { CacheHandler } from '@ember-data-mirror/store';
|
|
3412
3720
|
* import RequestManager from '@ember-data-mirror/request';
|
|
3413
|
-
* import Fetch from '@ember
|
|
3721
|
+
* import Fetch from '@ember-data-mirror/request/fetch';
|
|
3414
3722
|
*
|
|
3415
3723
|
* class extends Store {
|
|
3416
3724
|
* constructor() {
|
|
@@ -3427,7 +3735,7 @@ class Store extends EmberObject {
|
|
|
3427
3735
|
*/
|
|
3428
3736
|
|
|
3429
3737
|
/**
|
|
3430
|
-
* A Property which an App may set to provide a
|
|
3738
|
+
* A Property which an App may set to provide a CachePolicy
|
|
3431
3739
|
* to control when a cached request becomes stale.
|
|
3432
3740
|
*
|
|
3433
3741
|
* Note, when defined, these methods will only be invoked if a
|
|
@@ -3453,7 +3761,7 @@ class Store extends EmberObject {
|
|
|
3453
3761
|
* ```
|
|
3454
3762
|
*
|
|
3455
3763
|
* @public
|
|
3456
|
-
* @property {
|
|
3764
|
+
* @property {CachePolicy|undefined} lifetimes
|
|
3457
3765
|
*/
|
|
3458
3766
|
|
|
3459
3767
|
// Private
|
|
@@ -3478,7 +3786,6 @@ class Store extends EmberObject {
|
|
|
3478
3786
|
@private
|
|
3479
3787
|
*/
|
|
3480
3788
|
constructor(createArgs) {
|
|
3481
|
-
// @ts-expect-error ember-source types improperly expect createArgs to be `Owner`
|
|
3482
3789
|
super(createArgs);
|
|
3483
3790
|
Object.assign(this, createArgs);
|
|
3484
3791
|
this.identifierCache = new IdentifierCache();
|
|
@@ -3497,9 +3804,13 @@ class Store extends EmberObject {
|
|
|
3497
3804
|
this.isDestroyed = false;
|
|
3498
3805
|
}
|
|
3499
3806
|
_run(cb) {
|
|
3500
|
-
|
|
3807
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3808
|
+
if (!test) {
|
|
3809
|
+
throw new Error(`EmberData should never encounter a nested run`);
|
|
3810
|
+
}
|
|
3811
|
+
})(!this._cbs) : {};
|
|
3501
3812
|
const _cbs = this._cbs = {};
|
|
3502
|
-
if (macroCondition(
|
|
3813
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3503
3814
|
try {
|
|
3504
3815
|
cb();
|
|
3505
3816
|
if (_cbs.coalesce) {
|
|
@@ -3536,8 +3847,16 @@ class Store extends EmberObject {
|
|
|
3536
3847
|
}
|
|
3537
3848
|
}
|
|
3538
3849
|
_schedule(name, cb) {
|
|
3539
|
-
|
|
3540
|
-
|
|
3850
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3851
|
+
if (!test) {
|
|
3852
|
+
throw new Error(`EmberData expects to schedule only when there is an active run`);
|
|
3853
|
+
}
|
|
3854
|
+
})(!!this._cbs) : {};
|
|
3855
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3856
|
+
if (!test) {
|
|
3857
|
+
throw new Error(`EmberData expects only one flush per queue name, cannot schedule ${name}`);
|
|
3858
|
+
}
|
|
3859
|
+
})(!this._cbs[name]) : {};
|
|
3541
3860
|
this._cbs[name] = cb;
|
|
3542
3861
|
}
|
|
3543
3862
|
|
|
@@ -3556,7 +3875,7 @@ class Store extends EmberObject {
|
|
|
3556
3875
|
return this._requestCache;
|
|
3557
3876
|
}
|
|
3558
3877
|
_getAllPending() {
|
|
3559
|
-
if (macroCondition(
|
|
3878
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
3560
3879
|
const all = [];
|
|
3561
3880
|
const pending = this._requestCache._pending;
|
|
3562
3881
|
pending.forEach(requests => {
|
|
@@ -3599,7 +3918,7 @@ class Store extends EmberObject {
|
|
|
3599
3918
|
* When a cache-key is determined, the request may fulfill
|
|
3600
3919
|
* from cache provided the cache is not stale.
|
|
3601
3920
|
*
|
|
3602
|
-
* Cache staleness is determined by the configured
|
|
3921
|
+
* Cache staleness is determined by the configured CachePolicy
|
|
3603
3922
|
* with priority given to the `cacheOptions.reload` and
|
|
3604
3923
|
* `cacheOptions.backgroundReload` on the request if present.
|
|
3605
3924
|
*
|
|
@@ -3634,12 +3953,12 @@ class Store extends EmberObject {
|
|
|
3634
3953
|
const identifierCache = this.identifierCache;
|
|
3635
3954
|
opts.records = requestConfig.records.map(r => identifierCache.getOrCreateRecordIdentifier(r));
|
|
3636
3955
|
}
|
|
3637
|
-
if (macroCondition(
|
|
3956
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
3638
3957
|
if (this.DISABLE_WAITER) {
|
|
3639
3958
|
opts.disableTestWaiter = typeof requestConfig.disableTestWaiter === 'boolean' ? requestConfig.disableTestWaiter : true;
|
|
3640
3959
|
}
|
|
3641
3960
|
}
|
|
3642
|
-
if (macroCondition(
|
|
3961
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
|
|
3643
3962
|
let options;
|
|
3644
3963
|
try {
|
|
3645
3964
|
options = JSON.parse(JSON.stringify(requestConfig));
|
|
@@ -3649,9 +3968,10 @@ class Store extends EmberObject {
|
|
|
3649
3968
|
// eslint-disable-next-line no-console
|
|
3650
3969
|
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3651
3970
|
}
|
|
3652
|
-
const
|
|
3971
|
+
const request = Object.assign({}, requestConfig, opts);
|
|
3972
|
+
const future = this.requestManager.request(request);
|
|
3653
3973
|
future.onFinalize(() => {
|
|
3654
|
-
if (macroCondition(
|
|
3974
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
|
|
3655
3975
|
// eslint-disable-next-line no-console
|
|
3656
3976
|
console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
|
|
3657
3977
|
}
|
|
@@ -3693,133 +4013,6 @@ class Store extends EmberObject {
|
|
|
3693
4013
|
* @param record
|
|
3694
4014
|
*/
|
|
3695
4015
|
|
|
3696
|
-
/**
|
|
3697
|
-
* Provides access to the SchemaDefinitionService instance
|
|
3698
|
-
* for this Store instance.
|
|
3699
|
-
*
|
|
3700
|
-
* The SchemaDefinitionService can be used to query for
|
|
3701
|
-
* information about the schema of a resource.
|
|
3702
|
-
*
|
|
3703
|
-
* @method getSchemaDefinitionService
|
|
3704
|
-
* @public
|
|
3705
|
-
*/
|
|
3706
|
-
getSchemaDefinitionService() {
|
|
3707
|
-
assert(`You must registerSchemaDefinitionService with the store to use custom model classes`, this._schema);
|
|
3708
|
-
return this._schema;
|
|
3709
|
-
}
|
|
3710
|
-
|
|
3711
|
-
/**
|
|
3712
|
-
* DEPRECATED - Use `registerSchema` instead.
|
|
3713
|
-
*
|
|
3714
|
-
* Allows an app to register a custom SchemaService
|
|
3715
|
-
* for use when information about a resource's schema needs
|
|
3716
|
-
* to be queried.
|
|
3717
|
-
*
|
|
3718
|
-
* This method can only be called more than once, but only one schema
|
|
3719
|
-
* definition service may exist. Therefore if you wish to chain services
|
|
3720
|
-
* you must lookup the existing service and close over it with the new
|
|
3721
|
-
* service by accessing `store.schema` prior to registration.
|
|
3722
|
-
*
|
|
3723
|
-
* For Example:
|
|
3724
|
-
*
|
|
3725
|
-
* ```ts
|
|
3726
|
-
* import Store from '@ember-data-mirror/store';
|
|
3727
|
-
*
|
|
3728
|
-
* class SchemaDelegator {
|
|
3729
|
-
* constructor(schema) {
|
|
3730
|
-
* this._schema = schema;
|
|
3731
|
-
* }
|
|
3732
|
-
*
|
|
3733
|
-
* doesTypeExist(type: string): boolean {
|
|
3734
|
-
* if (AbstractSchemas.has(type)) {
|
|
3735
|
-
* return true;
|
|
3736
|
-
* }
|
|
3737
|
-
* return this._schema.doesTypeExist(type);
|
|
3738
|
-
* }
|
|
3739
|
-
*
|
|
3740
|
-
* attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
|
|
3741
|
-
* return this._schema.attributesDefinitionFor(identifier);
|
|
3742
|
-
* }
|
|
3743
|
-
*
|
|
3744
|
-
* relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
|
|
3745
|
-
* const schema = AbstractSchemas.get(identifier.type);
|
|
3746
|
-
* return schema || this._schema.relationshipsDefinitionFor(identifier);
|
|
3747
|
-
* }
|
|
3748
|
-
* }
|
|
3749
|
-
*
|
|
3750
|
-
* export default class extends Store {
|
|
3751
|
-
* constructor(...args) {
|
|
3752
|
-
* super(...args);
|
|
3753
|
-
*
|
|
3754
|
-
* const schema = this.schema;
|
|
3755
|
-
* this.registerSchemaDefinitionService(new SchemaDelegator(schema));
|
|
3756
|
-
* }
|
|
3757
|
-
* }
|
|
3758
|
-
* ```
|
|
3759
|
-
*
|
|
3760
|
-
* @method registerSchemaDefinitionService
|
|
3761
|
-
* @param {SchemaService} schema
|
|
3762
|
-
* @deprecated
|
|
3763
|
-
* @public
|
|
3764
|
-
*/
|
|
3765
|
-
registerSchemaDefinitionService(schema) {
|
|
3766
|
-
this._schema = schema;
|
|
3767
|
-
}
|
|
3768
|
-
/**
|
|
3769
|
-
* Allows an app to register a custom SchemaService
|
|
3770
|
-
* for use when information about a resource's schema needs
|
|
3771
|
-
* to be queried.
|
|
3772
|
-
*
|
|
3773
|
-
* This method can only be called more than once, but only one schema
|
|
3774
|
-
* definition service may exist. Therefore if you wish to chain services
|
|
3775
|
-
* you must lookup the existing service and close over it with the new
|
|
3776
|
-
* service by accessing `store.schema` prior to registration.
|
|
3777
|
-
*
|
|
3778
|
-
* For Example:
|
|
3779
|
-
*
|
|
3780
|
-
* ```ts
|
|
3781
|
-
* import Store from '@ember-data-mirror/store';
|
|
3782
|
-
*
|
|
3783
|
-
* class SchemaDelegator {
|
|
3784
|
-
* constructor(schema) {
|
|
3785
|
-
* this._schema = schema;
|
|
3786
|
-
* }
|
|
3787
|
-
*
|
|
3788
|
-
* doesTypeExist(type: string): boolean {
|
|
3789
|
-
* if (AbstractSchemas.has(type)) {
|
|
3790
|
-
* return true;
|
|
3791
|
-
* }
|
|
3792
|
-
* return this._schema.doesTypeExist(type);
|
|
3793
|
-
* }
|
|
3794
|
-
*
|
|
3795
|
-
* attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
|
|
3796
|
-
* return this._schema.attributesDefinitionFor(identifier);
|
|
3797
|
-
* }
|
|
3798
|
-
*
|
|
3799
|
-
* relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
|
|
3800
|
-
* const schema = AbstractSchemas.get(identifier.type);
|
|
3801
|
-
* return schema || this._schema.relationshipsDefinitionFor(identifier);
|
|
3802
|
-
* }
|
|
3803
|
-
* }
|
|
3804
|
-
*
|
|
3805
|
-
* export default class extends Store {
|
|
3806
|
-
* constructor(...args) {
|
|
3807
|
-
* super(...args);
|
|
3808
|
-
*
|
|
3809
|
-
* const schema = this.schema;
|
|
3810
|
-
* this.registerSchema(new SchemaDelegator(schema));
|
|
3811
|
-
* }
|
|
3812
|
-
* }
|
|
3813
|
-
* ```
|
|
3814
|
-
*
|
|
3815
|
-
* @method registerSchema
|
|
3816
|
-
* @param {SchemaService} schema
|
|
3817
|
-
* @public
|
|
3818
|
-
*/
|
|
3819
|
-
registerSchema(schema) {
|
|
3820
|
-
this._schema = schema;
|
|
3821
|
-
}
|
|
3822
|
-
|
|
3823
4016
|
/**
|
|
3824
4017
|
Returns the schema for a particular resource type (modelName).
|
|
3825
4018
|
When used with Model from @ember-data-mirror/model the return is the model class,
|
|
@@ -3835,17 +4028,29 @@ class Store extends EmberObject {
|
|
|
3835
4028
|
for example.
|
|
3836
4029
|
@method modelFor
|
|
3837
4030
|
@public
|
|
4031
|
+
@deprecated
|
|
3838
4032
|
@param {string} type
|
|
3839
4033
|
@return {ModelSchema}
|
|
3840
4034
|
*/
|
|
3841
|
-
// TODO @deprecate in favor of schema APIs, requires adapter/serializer overhaul or replacement
|
|
3842
4035
|
|
|
3843
4036
|
modelFor(type) {
|
|
3844
|
-
|
|
4037
|
+
// FIXME add deprecation and deprecation stripping
|
|
4038
|
+
// FIXME/TODO update RFC to remove this method
|
|
4039
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3845
4040
|
assertDestroyedStoreOnly(this, 'modelFor');
|
|
3846
4041
|
}
|
|
3847
|
-
|
|
3848
|
-
|
|
4042
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4043
|
+
if (!test) {
|
|
4044
|
+
throw new Error(`You need to pass <type> to the store's modelFor method`);
|
|
4045
|
+
}
|
|
4046
|
+
})(typeof type === 'string' && type.length) : {};
|
|
4047
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4048
|
+
if (!test) {
|
|
4049
|
+
throw new Error(`No model was found for '${type}' and no schema handles the type`);
|
|
4050
|
+
}
|
|
4051
|
+
})(this.schema.hasResource({
|
|
4052
|
+
type
|
|
4053
|
+
})) : {};
|
|
3849
4054
|
return getShimClass(this, type);
|
|
3850
4055
|
}
|
|
3851
4056
|
|
|
@@ -3875,11 +4080,19 @@ class Store extends EmberObject {
|
|
|
3875
4080
|
*/
|
|
3876
4081
|
|
|
3877
4082
|
createRecord(type, inputProperties) {
|
|
3878
|
-
if (macroCondition(
|
|
4083
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3879
4084
|
assertDestroyingStore(this, 'createRecord');
|
|
3880
4085
|
}
|
|
3881
|
-
|
|
3882
|
-
|
|
4086
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4087
|
+
if (!test) {
|
|
4088
|
+
throw new Error(`You need to pass a model name to the store's createRecord method`);
|
|
4089
|
+
}
|
|
4090
|
+
})(type) : {};
|
|
4091
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4092
|
+
if (!test) {
|
|
4093
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${type}`);
|
|
4094
|
+
}
|
|
4095
|
+
})(typeof type === 'string') : {};
|
|
3883
4096
|
|
|
3884
4097
|
// This is wrapped in a `run.join` so that in test environments users do not need to manually wrap
|
|
3885
4098
|
// calls to `createRecord`. The run loop usage here is because we batch the joining and updating
|
|
@@ -3914,7 +4127,11 @@ class Store extends EmberObject {
|
|
|
3914
4127
|
};
|
|
3915
4128
|
if (resource.id) {
|
|
3916
4129
|
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
3917
|
-
|
|
4130
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4131
|
+
if (!test) {
|
|
4132
|
+
throw new Error(`The id ${String(properties.id)} has already been used with another '${normalizedModelName}' record.`);
|
|
4133
|
+
}
|
|
4134
|
+
})(!identifier) : {};
|
|
3918
4135
|
}
|
|
3919
4136
|
const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
|
|
3920
4137
|
const cache = this.cache;
|
|
@@ -3939,12 +4156,16 @@ class Store extends EmberObject {
|
|
|
3939
4156
|
@param {unknown} record
|
|
3940
4157
|
*/
|
|
3941
4158
|
deleteRecord(record) {
|
|
3942
|
-
if (macroCondition(
|
|
4159
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3943
4160
|
assertDestroyingStore(this, 'deleteRecord');
|
|
3944
4161
|
}
|
|
3945
4162
|
const identifier = peekRecordIdentifier(record);
|
|
3946
4163
|
const cache = this.cache;
|
|
3947
|
-
|
|
4164
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4165
|
+
if (!test) {
|
|
4166
|
+
throw new Error(`expected the record to be connected to a cache`);
|
|
4167
|
+
}
|
|
4168
|
+
})(identifier) : {};
|
|
3948
4169
|
this._join(() => {
|
|
3949
4170
|
cache.setIsDeleted(identifier, true);
|
|
3950
4171
|
if (cache.isNew(identifier)) {
|
|
@@ -3967,7 +4188,7 @@ class Store extends EmberObject {
|
|
|
3967
4188
|
@param {Model} record
|
|
3968
4189
|
*/
|
|
3969
4190
|
unloadRecord(record) {
|
|
3970
|
-
if (macroCondition(
|
|
4191
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3971
4192
|
assertDestroyingStore(this, 'unloadRecord');
|
|
3972
4193
|
}
|
|
3973
4194
|
const identifier = peekRecordIdentifier(record);
|
|
@@ -3984,8 +4205,7 @@ class Store extends EmberObject {
|
|
|
3984
4205
|
resolved with the record.
|
|
3985
4206
|
**Example 1**
|
|
3986
4207
|
```app/routes/post.js
|
|
3987
|
-
|
|
3988
|
-
export default class PostRoute extends Route {
|
|
4208
|
+
export default class PostRoute extends Route {
|
|
3989
4209
|
model({ post_id }) {
|
|
3990
4210
|
return this.store.findRecord('post', post_id);
|
|
3991
4211
|
}
|
|
@@ -3996,8 +4216,7 @@ class Store extends EmberObject {
|
|
|
3996
4216
|
of `type` (modelName) and `id` as separate arguments. You may recognize this combo as
|
|
3997
4217
|
the typical pairing from [JSON:API](https://jsonapi.org/format/#document-resource-object-identification)
|
|
3998
4218
|
```app/routes/post.js
|
|
3999
|
-
|
|
4000
|
-
export default class PostRoute extends Route {
|
|
4219
|
+
export default class PostRoute extends Route {
|
|
4001
4220
|
model({ post_id: id }) {
|
|
4002
4221
|
return this.store.findRecord({ type: 'post', id });
|
|
4003
4222
|
}
|
|
@@ -4020,8 +4239,7 @@ class Store extends EmberObject {
|
|
|
4020
4239
|
for the comment also looks like `/posts/1/comments/2` if you want to fetch the comment
|
|
4021
4240
|
without also fetching the post you can pass in the post to the `findRecord` call:
|
|
4022
4241
|
```app/routes/post-comments.js
|
|
4023
|
-
|
|
4024
|
-
export default class PostRoute extends Route {
|
|
4242
|
+
export default class PostRoute extends Route {
|
|
4025
4243
|
model({ post_id, comment_id: id }) {
|
|
4026
4244
|
return this.store.findRecord({ type: 'comment', id, { preload: { post: post_id }} });
|
|
4027
4245
|
}
|
|
@@ -4047,8 +4265,7 @@ class Store extends EmberObject {
|
|
|
4047
4265
|
This could also be achieved by supplying the post id to the adapter via the adapterOptions
|
|
4048
4266
|
property on the options hash.
|
|
4049
4267
|
```app/routes/post-comments.js
|
|
4050
|
-
|
|
4051
|
-
export default class PostRoute extends Route {
|
|
4268
|
+
export default class PostRoute extends Route {
|
|
4052
4269
|
model({ post_id, comment_id: id }) {
|
|
4053
4270
|
return this.store.findRecord({ type: 'comment', id, { adapterOptions: { post: post_id }} });
|
|
4054
4271
|
}
|
|
@@ -4142,8 +4359,7 @@ class Store extends EmberObject {
|
|
|
4142
4359
|
boolean value for `backgroundReload` in the options object for
|
|
4143
4360
|
`findRecord`.
|
|
4144
4361
|
```app/routes/post/edit.js
|
|
4145
|
-
|
|
4146
|
-
export default class PostEditRoute extends Route {
|
|
4362
|
+
export default class PostEditRoute extends Route {
|
|
4147
4363
|
model(params) {
|
|
4148
4364
|
return this.store.findRecord('post', params.post_id, { backgroundReload: false });
|
|
4149
4365
|
}
|
|
@@ -4152,8 +4368,7 @@ class Store extends EmberObject {
|
|
|
4152
4368
|
If you pass an object on the `adapterOptions` property of the options
|
|
4153
4369
|
argument it will be passed to your adapter via the snapshot
|
|
4154
4370
|
```app/routes/post/edit.js
|
|
4155
|
-
|
|
4156
|
-
export default class PostEditRoute extends Route {
|
|
4371
|
+
export default class PostEditRoute extends Route {
|
|
4157
4372
|
model(params) {
|
|
4158
4373
|
return this.store.findRecord('post', params.post_id, {
|
|
4159
4374
|
adapterOptions: { subscribe: false }
|
|
@@ -4185,8 +4400,7 @@ class Store extends EmberObject {
|
|
|
4185
4400
|
model, when we retrieve a specific post we can have the server also return that post's
|
|
4186
4401
|
comments in the same request:
|
|
4187
4402
|
```app/routes/post.js
|
|
4188
|
-
|
|
4189
|
-
export default class PostRoute extends Route {
|
|
4403
|
+
export default class PostRoute extends Route {
|
|
4190
4404
|
model(params) {
|
|
4191
4405
|
return this.store.findRecord('post', params.post_id, { include: 'comments' });
|
|
4192
4406
|
}
|
|
@@ -4214,8 +4428,7 @@ class Store extends EmberObject {
|
|
|
4214
4428
|
using a dot-separated sequence of relationship names. So to request both the post's
|
|
4215
4429
|
comments and the authors of those comments the request would look like this:
|
|
4216
4430
|
```app/routes/post.js
|
|
4217
|
-
|
|
4218
|
-
export default class PostRoute extends Route {
|
|
4431
|
+
export default class PostRoute extends Route {
|
|
4219
4432
|
model(params) {
|
|
4220
4433
|
return this.store.findRecord('post', params.post_id, { include: 'comments,comments.author' });
|
|
4221
4434
|
}
|
|
@@ -4238,22 +4451,20 @@ class Store extends EmberObject {
|
|
|
4238
4451
|
2. Then pass through the applicable fields to your `findRecord` request.
|
|
4239
4452
|
Given a `post` model with attributes body, title, publishDate and meta, you can retrieve a filtered list of attributes.
|
|
4240
4453
|
```app/routes/post.js
|
|
4241
|
-
|
|
4242
|
-
export default Route.extend({
|
|
4454
|
+
export default class extends Route {
|
|
4243
4455
|
model(params) {
|
|
4244
4456
|
return this.store.findRecord('post', params.post_id, { adapterOptions: { fields: { post: 'body,title' } });
|
|
4245
4457
|
}
|
|
4246
|
-
}
|
|
4458
|
+
}
|
|
4247
4459
|
```
|
|
4248
4460
|
Moreover, you can filter attributes on related models as well. If a `post` has a `belongsTo` relationship to a user,
|
|
4249
4461
|
just include the relationship key and attributes.
|
|
4250
4462
|
```app/routes/post.js
|
|
4251
|
-
|
|
4252
|
-
export default Route.extend({
|
|
4463
|
+
export default class extends Route {
|
|
4253
4464
|
model(params) {
|
|
4254
4465
|
return this.store.findRecord('post', params.post_id, { adapterOptions: { fields: { post: 'body,title', user: 'name,email' } });
|
|
4255
4466
|
}
|
|
4256
|
-
}
|
|
4467
|
+
}
|
|
4257
4468
|
```
|
|
4258
4469
|
@since 1.13.0
|
|
4259
4470
|
@method findRecord
|
|
@@ -4265,14 +4476,22 @@ class Store extends EmberObject {
|
|
|
4265
4476
|
*/
|
|
4266
4477
|
|
|
4267
4478
|
findRecord(resource, id, options) {
|
|
4268
|
-
if (macroCondition(
|
|
4479
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4269
4480
|
assertDestroyingStore(this, 'findRecord');
|
|
4270
4481
|
}
|
|
4271
|
-
|
|
4482
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4483
|
+
if (!test) {
|
|
4484
|
+
throw new Error(`You need to pass a modelName or resource identifier as the first argument to the store's findRecord method`);
|
|
4485
|
+
}
|
|
4486
|
+
})(resource) : {};
|
|
4272
4487
|
if (isMaybeIdentifier(resource)) {
|
|
4273
4488
|
options = id;
|
|
4274
4489
|
} else {
|
|
4275
|
-
|
|
4490
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4491
|
+
if (!test) {
|
|
4492
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${resource}`);
|
|
4493
|
+
}
|
|
4494
|
+
})(typeof resource === 'string') : {};
|
|
4276
4495
|
const type = normalizeModelName(resource);
|
|
4277
4496
|
const normalizedId = ensureStringId(id);
|
|
4278
4497
|
resource = constructResource(type, normalizedId);
|
|
@@ -4336,7 +4555,7 @@ class Store extends EmberObject {
|
|
|
4336
4555
|
*/
|
|
4337
4556
|
// TODO @deprecate getReference (and references generally)
|
|
4338
4557
|
getReference(resource, id) {
|
|
4339
|
-
if (macroCondition(
|
|
4558
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4340
4559
|
assertDestroyingStore(this, 'getReference');
|
|
4341
4560
|
}
|
|
4342
4561
|
let resourceIdentifier;
|
|
@@ -4347,7 +4566,11 @@ class Store extends EmberObject {
|
|
|
4347
4566
|
const normalizedId = ensureStringId(id);
|
|
4348
4567
|
resourceIdentifier = constructResource(type, normalizedId);
|
|
4349
4568
|
}
|
|
4350
|
-
|
|
4569
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4570
|
+
if (!test) {
|
|
4571
|
+
throw new Error('getReference expected to receive either a resource identifier or type and id as arguments');
|
|
4572
|
+
}
|
|
4573
|
+
})(isMaybeIdentifier(resourceIdentifier)) : {};
|
|
4351
4574
|
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
4352
4575
|
return this._instanceCache.getReference(identifier);
|
|
4353
4576
|
}
|
|
@@ -4395,11 +4618,19 @@ class Store extends EmberObject {
|
|
|
4395
4618
|
// this is basically an "are we not empty" query.
|
|
4396
4619
|
return isLoaded ? this._instanceCache.getRecord(stableIdentifier) : null;
|
|
4397
4620
|
}
|
|
4398
|
-
if (macroCondition(
|
|
4621
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4399
4622
|
assertDestroyingStore(this, 'peekRecord');
|
|
4400
4623
|
}
|
|
4401
|
-
|
|
4402
|
-
|
|
4624
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4625
|
+
if (!test) {
|
|
4626
|
+
throw new Error(`You need to pass a model name to the store's peekRecord method`);
|
|
4627
|
+
}
|
|
4628
|
+
})(identifier) : {};
|
|
4629
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4630
|
+
if (!test) {
|
|
4631
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${String(identifier)}`);
|
|
4632
|
+
}
|
|
4633
|
+
})(typeof identifier === 'string') : {};
|
|
4403
4634
|
const type = normalizeModelName(identifier);
|
|
4404
4635
|
const normalizedId = ensureStringId(id);
|
|
4405
4636
|
const resource = {
|
|
@@ -4450,12 +4681,24 @@ class Store extends EmberObject {
|
|
|
4450
4681
|
*/
|
|
4451
4682
|
|
|
4452
4683
|
query(type, query, options = {}) {
|
|
4453
|
-
if (macroCondition(
|
|
4684
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4454
4685
|
assertDestroyingStore(this, 'query');
|
|
4455
4686
|
}
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4687
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4688
|
+
if (!test) {
|
|
4689
|
+
throw new Error(`You need to pass a model name to the store's query method`);
|
|
4690
|
+
}
|
|
4691
|
+
})(type) : {};
|
|
4692
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4693
|
+
if (!test) {
|
|
4694
|
+
throw new Error(`You need to pass a query hash to the store's query method`);
|
|
4695
|
+
}
|
|
4696
|
+
})(query) : {};
|
|
4697
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4698
|
+
if (!test) {
|
|
4699
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${type}`);
|
|
4700
|
+
}
|
|
4701
|
+
})(typeof type === 'string') : {};
|
|
4459
4702
|
const promise = this.request({
|
|
4460
4703
|
op: 'query',
|
|
4461
4704
|
data: {
|
|
@@ -4553,12 +4796,24 @@ class Store extends EmberObject {
|
|
|
4553
4796
|
*/
|
|
4554
4797
|
|
|
4555
4798
|
queryRecord(type, query, options) {
|
|
4556
|
-
if (macroCondition(
|
|
4799
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4557
4800
|
assertDestroyingStore(this, 'queryRecord');
|
|
4558
4801
|
}
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4802
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4803
|
+
if (!test) {
|
|
4804
|
+
throw new Error(`You need to pass a model name to the store's queryRecord method`);
|
|
4805
|
+
}
|
|
4806
|
+
})(type) : {};
|
|
4807
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4808
|
+
if (!test) {
|
|
4809
|
+
throw new Error(`You need to pass a query hash to the store's queryRecord method`);
|
|
4810
|
+
}
|
|
4811
|
+
})(query) : {};
|
|
4812
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4813
|
+
if (!test) {
|
|
4814
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${type}`);
|
|
4815
|
+
}
|
|
4816
|
+
})(typeof type === 'string') : {};
|
|
4562
4817
|
const promise = this.request({
|
|
4563
4818
|
op: 'queryRecord',
|
|
4564
4819
|
data: {
|
|
@@ -4579,8 +4834,7 @@ class Store extends EmberObject {
|
|
|
4579
4834
|
this type present in the store, even if the adapter only returns a subset
|
|
4580
4835
|
of them.
|
|
4581
4836
|
```app/routes/authors.js
|
|
4582
|
-
|
|
4583
|
-
export default class AuthorsRoute extends Route {
|
|
4837
|
+
export default class AuthorsRoute extends Route {
|
|
4584
4838
|
model(params) {
|
|
4585
4839
|
return this.store.findAll('author');
|
|
4586
4840
|
}
|
|
@@ -4653,8 +4907,7 @@ class Store extends EmberObject {
|
|
|
4653
4907
|
boolean value for `backgroundReload` in the options object for
|
|
4654
4908
|
`findAll`.
|
|
4655
4909
|
```app/routes/post/edit.js
|
|
4656
|
-
|
|
4657
|
-
export default class PostEditRoute extends Route {
|
|
4910
|
+
export default class PostEditRoute extends Route {
|
|
4658
4911
|
model() {
|
|
4659
4912
|
return this.store.findAll('post', { backgroundReload: false });
|
|
4660
4913
|
}
|
|
@@ -4663,8 +4916,7 @@ class Store extends EmberObject {
|
|
|
4663
4916
|
If you pass an object on the `adapterOptions` property of the options
|
|
4664
4917
|
argument it will be passed to you adapter via the `snapshotRecordArray`
|
|
4665
4918
|
```app/routes/posts.js
|
|
4666
|
-
|
|
4667
|
-
export default class PostsRoute extends Route {
|
|
4919
|
+
export default class PostsRoute extends Route {
|
|
4668
4920
|
model(params) {
|
|
4669
4921
|
return this.store.findAll('post', {
|
|
4670
4922
|
adapterOptions: { subscribe: false }
|
|
@@ -4697,8 +4949,7 @@ class Store extends EmberObject {
|
|
|
4697
4949
|
model, when we retrieve all of the post records we can have the server also return
|
|
4698
4950
|
all of the posts' comments in the same request:
|
|
4699
4951
|
```app/routes/posts.js
|
|
4700
|
-
|
|
4701
|
-
export default class PostsRoute extends Route {
|
|
4952
|
+
export default class PostsRoute extends Route {
|
|
4702
4953
|
model() {
|
|
4703
4954
|
return this.store.findAll('post', { include: 'comments' });
|
|
4704
4955
|
}
|
|
@@ -4709,8 +4960,7 @@ class Store extends EmberObject {
|
|
|
4709
4960
|
using a dot-separated sequence of relationship names. So to request both the posts'
|
|
4710
4961
|
comments and the authors of those comments the request would look like this:
|
|
4711
4962
|
```app/routes/posts.js
|
|
4712
|
-
|
|
4713
|
-
export default class PostsRoute extends Route {
|
|
4963
|
+
export default class PostsRoute extends Route {
|
|
4714
4964
|
model() {
|
|
4715
4965
|
return this.store.findAll('post', { include: 'comments,comments.author' });
|
|
4716
4966
|
}
|
|
@@ -4726,11 +4976,19 @@ class Store extends EmberObject {
|
|
|
4726
4976
|
*/
|
|
4727
4977
|
|
|
4728
4978
|
findAll(type, options = {}) {
|
|
4729
|
-
if (macroCondition(
|
|
4979
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4730
4980
|
assertDestroyingStore(this, 'findAll');
|
|
4731
4981
|
}
|
|
4732
|
-
|
|
4733
|
-
|
|
4982
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4983
|
+
if (!test) {
|
|
4984
|
+
throw new Error(`You need to pass a model name to the store's findAll method`);
|
|
4985
|
+
}
|
|
4986
|
+
})(type) : {};
|
|
4987
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
4988
|
+
if (!test) {
|
|
4989
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${type}`);
|
|
4990
|
+
}
|
|
4991
|
+
})(typeof type === 'string') : {};
|
|
4734
4992
|
const promise = this.request({
|
|
4735
4993
|
op: 'findAll',
|
|
4736
4994
|
data: {
|
|
@@ -4766,11 +5024,19 @@ class Store extends EmberObject {
|
|
|
4766
5024
|
*/
|
|
4767
5025
|
|
|
4768
5026
|
peekAll(type) {
|
|
4769
|
-
if (macroCondition(
|
|
5027
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4770
5028
|
assertDestroyingStore(this, 'peekAll');
|
|
4771
5029
|
}
|
|
4772
|
-
|
|
4773
|
-
|
|
5030
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5031
|
+
if (!test) {
|
|
5032
|
+
throw new Error(`You need to pass a model name to the store's peekAll method`);
|
|
5033
|
+
}
|
|
5034
|
+
})(type) : {};
|
|
5035
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5036
|
+
if (!test) {
|
|
5037
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${type}`);
|
|
5038
|
+
}
|
|
5039
|
+
})(typeof type === 'string') : {};
|
|
4774
5040
|
return this.recordArrayManager.liveArrayFor(normalizeModelName(type));
|
|
4775
5041
|
}
|
|
4776
5042
|
|
|
@@ -4788,10 +5054,14 @@ class Store extends EmberObject {
|
|
|
4788
5054
|
*/
|
|
4789
5055
|
|
|
4790
5056
|
unloadAll(type) {
|
|
4791
|
-
if (macroCondition(
|
|
5057
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4792
5058
|
assertDestroyedStoreOnly(this, 'unloadAll');
|
|
4793
5059
|
}
|
|
4794
|
-
|
|
5060
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5061
|
+
if (!test) {
|
|
5062
|
+
throw new Error(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${String(type)}`);
|
|
5063
|
+
}
|
|
5064
|
+
})(!type || typeof type === 'string') : {};
|
|
4795
5065
|
this._join(() => {
|
|
4796
5066
|
if (type === undefined) {
|
|
4797
5067
|
// destroy the graph before unloadAll
|
|
@@ -4938,7 +5208,7 @@ class Store extends EmberObject {
|
|
|
4938
5208
|
*/
|
|
4939
5209
|
|
|
4940
5210
|
push(data) {
|
|
4941
|
-
if (macroCondition(
|
|
5211
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4942
5212
|
assertDestroyingStore(this, 'push');
|
|
4943
5213
|
}
|
|
4944
5214
|
const pushed = this._push(data, false);
|
|
@@ -4960,10 +5230,10 @@ class Store extends EmberObject {
|
|
|
4960
5230
|
@return {StableRecordIdentifier|Array<StableRecordIdentifier>|null} identifiers for the primary records that had data loaded
|
|
4961
5231
|
*/
|
|
4962
5232
|
_push(jsonApiDoc, asyncFlush) {
|
|
4963
|
-
if (macroCondition(
|
|
5233
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4964
5234
|
assertDestroyingStore(this, '_push');
|
|
4965
5235
|
}
|
|
4966
|
-
if (macroCondition(
|
|
5236
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS)) {
|
|
4967
5237
|
try {
|
|
4968
5238
|
const data = JSON.parse(JSON.stringify(jsonApiDoc));
|
|
4969
5239
|
// eslint-disable-next-line no-console
|
|
@@ -4998,10 +5268,14 @@ class Store extends EmberObject {
|
|
|
4998
5268
|
* @return {Promise<record>}
|
|
4999
5269
|
*/
|
|
5000
5270
|
saveRecord(record, options = {}) {
|
|
5001
|
-
if (macroCondition(
|
|
5271
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5002
5272
|
assertDestroyingStore(this, 'saveRecord');
|
|
5003
5273
|
}
|
|
5004
|
-
|
|
5274
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5275
|
+
if (!test) {
|
|
5276
|
+
throw new Error(`Unable to initiate save for a record in a disconnected state`);
|
|
5277
|
+
}
|
|
5278
|
+
})(storeFor(record)) : {};
|
|
5005
5279
|
const identifier = recordIdentifierFor(record);
|
|
5006
5280
|
const cache = this.cache;
|
|
5007
5281
|
if (!identifier) {
|
|
@@ -5009,7 +5283,11 @@ class Store extends EmberObject {
|
|
|
5009
5283
|
// but just in case we reject here to prevent bad things.
|
|
5010
5284
|
return Promise.reject(new Error(`Record Is Disconnected`));
|
|
5011
5285
|
}
|
|
5012
|
-
|
|
5286
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5287
|
+
if (!test) {
|
|
5288
|
+
throw new Error(`Cannot initiate a save request for an unloaded record: ${identifier.lid}`);
|
|
5289
|
+
}
|
|
5290
|
+
})(this._instanceCache.recordIsLoaded(identifier)) : {};
|
|
5013
5291
|
if (resourceIsFullyDeleted(this._instanceCache, identifier)) {
|
|
5014
5292
|
return Promise.resolve(record);
|
|
5015
5293
|
}
|
|
@@ -5062,14 +5340,12 @@ class Store extends EmberObject {
|
|
|
5062
5340
|
} = this._instanceCache;
|
|
5063
5341
|
if (!cache) {
|
|
5064
5342
|
cache = this._instanceCache.cache = this.createCache(this._instanceCache._storeWrapper);
|
|
5065
|
-
if (macroCondition(
|
|
5343
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5066
5344
|
cache = new CacheManager(cache);
|
|
5067
5345
|
}
|
|
5068
5346
|
}
|
|
5069
5347
|
return cache;
|
|
5070
5348
|
}
|
|
5071
|
-
|
|
5072
|
-
// @ts-expect-error
|
|
5073
5349
|
destroy() {
|
|
5074
5350
|
if (this.isDestroyed) {
|
|
5075
5351
|
// @ember/test-helpers will call destroy multiple times
|
|
@@ -5088,16 +5364,67 @@ class Store extends EmberObject {
|
|
|
5088
5364
|
return new this(args);
|
|
5089
5365
|
}
|
|
5090
5366
|
}
|
|
5367
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_SCHEMA_SERVICE)) {
|
|
5368
|
+
Store.prototype.getSchemaDefinitionService = function () {
|
|
5369
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5370
|
+
if (!test) {
|
|
5371
|
+
throw new Error(`You must registerSchemaDefinitionService with the store to use custom model classes`);
|
|
5372
|
+
}
|
|
5373
|
+
})(this._schema) : {};
|
|
5374
|
+
deprecate(`Use \`store.schema\` instead of \`store.getSchemaDefinitionService()\``, false, {
|
|
5375
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
5376
|
+
until: '5.0',
|
|
5377
|
+
for: 'ember-data-mirror',
|
|
5378
|
+
since: {
|
|
5379
|
+
available: '5.4',
|
|
5380
|
+
enabled: '5.4'
|
|
5381
|
+
}
|
|
5382
|
+
});
|
|
5383
|
+
return this._schema;
|
|
5384
|
+
};
|
|
5385
|
+
Store.prototype.registerSchemaDefinitionService = function (schema) {
|
|
5386
|
+
deprecate(`Use \`store.createSchemaService\` instead of \`store.registerSchemaDefinitionService()\``, false, {
|
|
5387
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
5388
|
+
until: '5.0',
|
|
5389
|
+
for: 'ember-data-mirror',
|
|
5390
|
+
since: {
|
|
5391
|
+
available: '5.4',
|
|
5392
|
+
enabled: '5.4'
|
|
5393
|
+
}
|
|
5394
|
+
});
|
|
5395
|
+
this._schema = schema;
|
|
5396
|
+
};
|
|
5397
|
+
Store.prototype.registerSchema = function (schema) {
|
|
5398
|
+
deprecate(`Use \`store.createSchemaService\` instead of \`store.registerSchema()\``, false, {
|
|
5399
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
5400
|
+
until: '5.0',
|
|
5401
|
+
for: 'ember-data-mirror',
|
|
5402
|
+
since: {
|
|
5403
|
+
available: '5.4',
|
|
5404
|
+
enabled: '5.4'
|
|
5405
|
+
}
|
|
5406
|
+
});
|
|
5407
|
+
this._schema = schema;
|
|
5408
|
+
};
|
|
5409
|
+
}
|
|
5091
5410
|
let assertDestroyingStore;
|
|
5092
5411
|
let assertDestroyedStoreOnly;
|
|
5093
|
-
if (macroCondition(
|
|
5412
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5094
5413
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5095
5414
|
assertDestroyingStore = function assertDestroyingStore(store, method) {
|
|
5096
|
-
|
|
5415
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5416
|
+
if (!test) {
|
|
5417
|
+
throw new Error(`Attempted to call store.${method}(), but the store instance has already been destroyed.`);
|
|
5418
|
+
}
|
|
5419
|
+
})(!(store.isDestroying || store.isDestroyed)) : {};
|
|
5097
5420
|
};
|
|
5098
5421
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5099
5422
|
assertDestroyedStoreOnly = function assertDestroyedStoreOnly(store, method) {
|
|
5100
|
-
|
|
5423
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5424
|
+
if (!test) {
|
|
5425
|
+
throw new Error(`Attempted to call store.${method}(), but the store instance has already been destroyed.`);
|
|
5426
|
+
}
|
|
5427
|
+
})(!store.isDestroyed) : {};
|
|
5101
5428
|
};
|
|
5102
5429
|
}
|
|
5103
5430
|
function isMaybeIdentifier(maybeIdentifier) {
|
|
@@ -5107,33 +5434,38 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5107
5434
|
// assert here
|
|
5108
5435
|
if (properties !== undefined) {
|
|
5109
5436
|
if ('id' in properties) {
|
|
5110
|
-
|
|
5437
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5438
|
+
if (!test) {
|
|
5439
|
+
throw new Error(`expected id to be a string or null`);
|
|
5440
|
+
}
|
|
5441
|
+
})(properties.id !== undefined) : {};
|
|
5111
5442
|
}
|
|
5112
|
-
|
|
5443
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5444
|
+
if (!test) {
|
|
5445
|
+
throw new Error(`You passed '${typeof properties}' as properties for record creation instead of an object.`);
|
|
5446
|
+
}
|
|
5447
|
+
})(typeof properties === 'object' && properties !== null) : {};
|
|
5113
5448
|
const {
|
|
5114
5449
|
type
|
|
5115
5450
|
} = identifier;
|
|
5116
5451
|
|
|
5117
5452
|
// convert relationship Records to RecordDatas before passing to RecordData
|
|
5118
|
-
const defs = store.
|
|
5453
|
+
const defs = store.schema.fields({
|
|
5119
5454
|
type
|
|
5120
5455
|
});
|
|
5121
|
-
if (defs
|
|
5456
|
+
if (defs.size) {
|
|
5122
5457
|
const keys = Object.keys(properties);
|
|
5123
|
-
let relationshipValue;
|
|
5124
5458
|
for (let i = 0; i < keys.length; i++) {
|
|
5125
5459
|
const prop = keys[i];
|
|
5126
|
-
const
|
|
5127
|
-
if (
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
}
|
|
5132
|
-
relationshipValue = extractIdentifiersFromRecords(properties[prop]);
|
|
5133
|
-
} else {
|
|
5134
|
-
relationshipValue = extractIdentifierFromRecord(properties[prop]);
|
|
5460
|
+
const field = defs.get(prop);
|
|
5461
|
+
if (!field) continue;
|
|
5462
|
+
if (field.kind === 'hasMany') {
|
|
5463
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5464
|
+
assertRecordsPassedToHasMany(properties[prop]);
|
|
5135
5465
|
}
|
|
5136
|
-
properties[prop] =
|
|
5466
|
+
properties[prop] = extractIdentifiersFromRecords(properties[prop]);
|
|
5467
|
+
} else if (field.kind === 'belongsTo') {
|
|
5468
|
+
properties[prop] = extractIdentifierFromRecord(properties[prop]);
|
|
5137
5469
|
}
|
|
5138
5470
|
}
|
|
5139
5471
|
}
|
|
@@ -5141,8 +5473,16 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5141
5473
|
return properties;
|
|
5142
5474
|
}
|
|
5143
5475
|
function assertRecordsPassedToHasMany(records) {
|
|
5144
|
-
|
|
5145
|
-
|
|
5476
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5477
|
+
if (!test) {
|
|
5478
|
+
throw new Error(`You must pass an array of records to set a hasMany relationship`);
|
|
5479
|
+
}
|
|
5480
|
+
})(Array.isArray(records)) : {};
|
|
5481
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5482
|
+
if (!test) {
|
|
5483
|
+
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed ${records.map(r => `${typeof r}`).join(', ')}`);
|
|
5484
|
+
}
|
|
5485
|
+
})(function () {
|
|
5146
5486
|
return records.every(record => {
|
|
5147
5487
|
try {
|
|
5148
5488
|
recordIdentifierFor(record);
|
|
@@ -5151,7 +5491,7 @@ function assertRecordsPassedToHasMany(records) {
|
|
|
5151
5491
|
return false;
|
|
5152
5492
|
}
|
|
5153
5493
|
});
|
|
5154
|
-
}());
|
|
5494
|
+
}()) : {};
|
|
5155
5495
|
}
|
|
5156
5496
|
function extractIdentifiersFromRecords(records) {
|
|
5157
5497
|
return records.map(record => extractIdentifierFromRecord(record));
|
|
@@ -5163,6 +5503,10 @@ function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
|
5163
5503
|
const extract = recordIdentifierFor;
|
|
5164
5504
|
return extract(recordOrPromiseRecord);
|
|
5165
5505
|
}
|
|
5506
|
+
|
|
5507
|
+
/**
|
|
5508
|
+
* @module @ember-data-mirror/store
|
|
5509
|
+
*/
|
|
5166
5510
|
function urlFromLink(link) {
|
|
5167
5511
|
if (typeof link === 'string') return link;
|
|
5168
5512
|
return link.href;
|
|
@@ -5180,69 +5524,79 @@ function urlFromLink(link) {
|
|
|
5180
5524
|
* @public
|
|
5181
5525
|
* @class Document
|
|
5182
5526
|
*/
|
|
5183
|
-
var _store = /*#__PURE__*/_classPrivateFieldKey("store");
|
|
5184
|
-
var _request = /*#__PURE__*/_classPrivateFieldKey("request");
|
|
5185
5527
|
class Document {
|
|
5528
|
+
/**
|
|
5529
|
+
* The links object for this document, if any
|
|
5530
|
+
*
|
|
5531
|
+
* e.g.
|
|
5532
|
+
*
|
|
5533
|
+
* ```
|
|
5534
|
+
* {
|
|
5535
|
+
* self: '/articles?page[number]=3',
|
|
5536
|
+
* }
|
|
5537
|
+
* ```
|
|
5538
|
+
*
|
|
5539
|
+
* @property links
|
|
5540
|
+
* @type {object|undefined} - a links object
|
|
5541
|
+
* @public
|
|
5542
|
+
*/
|
|
5543
|
+
|
|
5544
|
+
/**
|
|
5545
|
+
* The primary data for this document, if any.
|
|
5546
|
+
*
|
|
5547
|
+
* If this document has no primary data (e.g. because it is an error document)
|
|
5548
|
+
* this property will be `undefined`.
|
|
5549
|
+
*
|
|
5550
|
+
* For collections this will be an array of record instances,
|
|
5551
|
+
* for single resource requests it will be a single record instance or null.
|
|
5552
|
+
*
|
|
5553
|
+
* @property data
|
|
5554
|
+
* @public
|
|
5555
|
+
* @type {object|Array<object>|null|undefined} - a data object
|
|
5556
|
+
*/
|
|
5557
|
+
|
|
5558
|
+
/**
|
|
5559
|
+
* The errors returned by the API for this request, if any
|
|
5560
|
+
*
|
|
5561
|
+
* @property errors
|
|
5562
|
+
* @public
|
|
5563
|
+
* @type {object|undefined} - an errors object
|
|
5564
|
+
*/
|
|
5565
|
+
|
|
5566
|
+
/**
|
|
5567
|
+
* The meta object for this document, if any
|
|
5568
|
+
*
|
|
5569
|
+
* @property meta
|
|
5570
|
+
* @public
|
|
5571
|
+
* @type {object|undefined} - a meta object
|
|
5572
|
+
*/
|
|
5573
|
+
|
|
5574
|
+
/**
|
|
5575
|
+
* The identifier associated with this document, if any
|
|
5576
|
+
*
|
|
5577
|
+
* @property identifier
|
|
5578
|
+
* @public
|
|
5579
|
+
* @type {StableDocumentIdentifier|null}
|
|
5580
|
+
*/
|
|
5581
|
+
|
|
5582
|
+
#store;
|
|
5186
5583
|
constructor(store, identifier) {
|
|
5187
|
-
|
|
5188
|
-
value: _request2
|
|
5189
|
-
});
|
|
5190
|
-
/**
|
|
5191
|
-
* The links object for this document, if any
|
|
5192
|
-
*
|
|
5193
|
-
* e.g.
|
|
5194
|
-
*
|
|
5195
|
-
* ```
|
|
5196
|
-
* {
|
|
5197
|
-
* self: '/articles?page[number]=3',
|
|
5198
|
-
* }
|
|
5199
|
-
* ```
|
|
5200
|
-
*
|
|
5201
|
-
* @property links
|
|
5202
|
-
* @type {object|undefined} - a links object
|
|
5203
|
-
* @public
|
|
5204
|
-
*/
|
|
5205
|
-
/**
|
|
5206
|
-
* The primary data for this document, if any.
|
|
5207
|
-
*
|
|
5208
|
-
* If this document has no primary data (e.g. because it is an error document)
|
|
5209
|
-
* this property will be `undefined`.
|
|
5210
|
-
*
|
|
5211
|
-
* For collections this will be an array of record instances,
|
|
5212
|
-
* for single resource requests it will be a single record instance or null.
|
|
5213
|
-
*
|
|
5214
|
-
* @property data
|
|
5215
|
-
* @public
|
|
5216
|
-
* @type {object|Array<object>|null|undefined} - a data object
|
|
5217
|
-
*/
|
|
5218
|
-
/**
|
|
5219
|
-
* The errors returned by the API for this request, if any
|
|
5220
|
-
*
|
|
5221
|
-
* @property errors
|
|
5222
|
-
* @public
|
|
5223
|
-
* @type {object|undefined} - an errors object
|
|
5224
|
-
*/
|
|
5225
|
-
/**
|
|
5226
|
-
* The meta object for this document, if any
|
|
5227
|
-
*
|
|
5228
|
-
* @property meta
|
|
5229
|
-
* @public
|
|
5230
|
-
* @type {object|undefined} - a meta object
|
|
5231
|
-
*/
|
|
5232
|
-
/**
|
|
5233
|
-
* The identifier associated with this document, if any
|
|
5234
|
-
*
|
|
5235
|
-
* @property identifier
|
|
5236
|
-
* @public
|
|
5237
|
-
* @type {StableDocumentIdentifier|null}
|
|
5238
|
-
*/
|
|
5239
|
-
Object.defineProperty(this, _store, {
|
|
5240
|
-
writable: true,
|
|
5241
|
-
value: void 0
|
|
5242
|
-
});
|
|
5243
|
-
_classPrivateFieldBase(this, _store)[_store] = store;
|
|
5584
|
+
this.#store = store;
|
|
5244
5585
|
this.identifier = identifier;
|
|
5245
5586
|
}
|
|
5587
|
+
async #request(link, options) {
|
|
5588
|
+
const href = this.links?.[link];
|
|
5589
|
+
if (!href) {
|
|
5590
|
+
return null;
|
|
5591
|
+
}
|
|
5592
|
+
options.method = options.method || 'GET';
|
|
5593
|
+
Object.assign(options, {
|
|
5594
|
+
url: urlFromLink(href)
|
|
5595
|
+
});
|
|
5596
|
+
const response = await this.#store.request(options);
|
|
5597
|
+
return response.content;
|
|
5598
|
+
}
|
|
5599
|
+
|
|
5246
5600
|
/**
|
|
5247
5601
|
* Fetches the related link for this document, returning a promise that resolves
|
|
5248
5602
|
* with the document when the request completes. If no related link is present,
|
|
@@ -5254,10 +5608,14 @@ class Document {
|
|
|
5254
5608
|
* @return Promise<Document>
|
|
5255
5609
|
*/
|
|
5256
5610
|
fetch(options = {}) {
|
|
5257
|
-
|
|
5611
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5612
|
+
if (!test) {
|
|
5613
|
+
throw new Error(`No self or related link`);
|
|
5614
|
+
}
|
|
5615
|
+
})(this.links?.related || this.links?.self) : {};
|
|
5258
5616
|
options.cacheOptions = options.cacheOptions || {};
|
|
5259
5617
|
options.cacheOptions.key = this.identifier?.lid;
|
|
5260
|
-
return
|
|
5618
|
+
return this.#request(this.links.related ? 'related' : 'self', options);
|
|
5261
5619
|
}
|
|
5262
5620
|
|
|
5263
5621
|
/**
|
|
@@ -5271,7 +5629,7 @@ class Document {
|
|
|
5271
5629
|
* @return Promise<Document | null>
|
|
5272
5630
|
*/
|
|
5273
5631
|
next(options = {}) {
|
|
5274
|
-
return
|
|
5632
|
+
return this.#request('next', options);
|
|
5275
5633
|
}
|
|
5276
5634
|
|
|
5277
5635
|
/**
|
|
@@ -5285,7 +5643,7 @@ class Document {
|
|
|
5285
5643
|
* @return Promise<Document | null>
|
|
5286
5644
|
*/
|
|
5287
5645
|
prev(options = {}) {
|
|
5288
|
-
return
|
|
5646
|
+
return this.#request('prev', options);
|
|
5289
5647
|
}
|
|
5290
5648
|
|
|
5291
5649
|
/**
|
|
@@ -5299,7 +5657,7 @@ class Document {
|
|
|
5299
5657
|
* @return Promise<Document | null>
|
|
5300
5658
|
*/
|
|
5301
5659
|
first(options = {}) {
|
|
5302
|
-
return
|
|
5660
|
+
return this.#request('first', options);
|
|
5303
5661
|
}
|
|
5304
5662
|
|
|
5305
5663
|
/**
|
|
@@ -5313,7 +5671,7 @@ class Document {
|
|
|
5313
5671
|
* @return Promise<Document | null>
|
|
5314
5672
|
*/
|
|
5315
5673
|
last(options = {}) {
|
|
5316
|
-
return
|
|
5674
|
+
return this.#request('last', options);
|
|
5317
5675
|
}
|
|
5318
5676
|
|
|
5319
5677
|
/**
|
|
@@ -5347,17 +5705,6 @@ class Document {
|
|
|
5347
5705
|
return data;
|
|
5348
5706
|
}
|
|
5349
5707
|
}
|
|
5350
|
-
async function _request2(link, options) {
|
|
5351
|
-
const href = this.links?.[link];
|
|
5352
|
-
if (!href) {
|
|
5353
|
-
return null;
|
|
5354
|
-
}
|
|
5355
|
-
options.method = options.method || 'GET';
|
|
5356
|
-
const response = await _classPrivateFieldBase(this, _store)[_store].request(Object.assign(options, {
|
|
5357
|
-
url: urlFromLink(href)
|
|
5358
|
-
}));
|
|
5359
|
-
return response.content;
|
|
5360
|
-
}
|
|
5361
5708
|
defineSignal(Document.prototype, 'data');
|
|
5362
5709
|
defineSignal(Document.prototype, 'links');
|
|
5363
5710
|
defineSignal(Document.prototype, 'errors');
|
|
@@ -5378,10 +5725,9 @@ defineSignal(Document.prototype, 'meta');
|
|
|
5378
5725
|
* Implementing this service allows you to programatically define
|
|
5379
5726
|
* when a request should be considered expired.
|
|
5380
5727
|
*
|
|
5381
|
-
* @class <Interface>
|
|
5728
|
+
* @class <Interface> CachePolicy
|
|
5382
5729
|
* @public
|
|
5383
5730
|
*/
|
|
5384
|
-
|
|
5385
5731
|
const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
|
|
5386
5732
|
function isErrorDocument(document) {
|
|
5387
5733
|
return 'errors' in document;
|
|
@@ -5391,7 +5737,11 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
|
|
|
5391
5737
|
identifier
|
|
5392
5738
|
} = options;
|
|
5393
5739
|
if (!document) {
|
|
5394
|
-
|
|
5740
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5741
|
+
if (!test) {
|
|
5742
|
+
throw new Error(`The CacheHandler expected response content but none was found`);
|
|
5743
|
+
}
|
|
5744
|
+
})(!options.shouldHydrate) : {};
|
|
5395
5745
|
return document;
|
|
5396
5746
|
}
|
|
5397
5747
|
if (isErrorDocument(document)) {
|
|
@@ -5491,7 +5841,7 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
|
|
|
5491
5841
|
const {
|
|
5492
5842
|
cacheOptions
|
|
5493
5843
|
} = request;
|
|
5494
|
-
return
|
|
5844
|
+
return cacheOptions?.backgroundReload || (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier, store) : false);
|
|
5495
5845
|
}
|
|
5496
5846
|
function isMutation(request) {
|
|
5497
5847
|
return Boolean(request.op && MUTATION_OPS.has(request.op));
|
|
@@ -5506,7 +5856,11 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
|
|
|
5506
5856
|
isMut = true;
|
|
5507
5857
|
// TODO should we handle multiple records in request.records by iteratively calling willCommit for each
|
|
5508
5858
|
const record = context.request.data?.record || context.request.records?.[0];
|
|
5509
|
-
|
|
5859
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5860
|
+
if (!test) {
|
|
5861
|
+
throw new Error(`Expected to receive a list of records included in the ${context.request.op} request`);
|
|
5862
|
+
}
|
|
5863
|
+
})(record || !shouldHydrate) : {};
|
|
5510
5864
|
if (record) {
|
|
5511
5865
|
store.cache.willCommit(record, context);
|
|
5512
5866
|
}
|
|
@@ -5591,7 +5945,11 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
|
|
|
5591
5945
|
if (!isMut) {
|
|
5592
5946
|
return promise;
|
|
5593
5947
|
}
|
|
5594
|
-
|
|
5948
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5949
|
+
if (!test) {
|
|
5950
|
+
throw new Error(`Expected a mutation`);
|
|
5951
|
+
}
|
|
5952
|
+
})(isMutation(context.request)) : {};
|
|
5595
5953
|
|
|
5596
5954
|
// for mutations we need to enqueue the promise with the requestStateService
|
|
5597
5955
|
// TODO should we enque a request per record in records?
|
|
@@ -5723,4 +6081,4 @@ function isCacheAffecting(document) {
|
|
|
5723
6081
|
}
|
|
5724
6082
|
return document.response?.status !== 204;
|
|
5725
6083
|
}
|
|
5726
|
-
export { ARRAY_SIGNAL as A, CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _,
|
|
6084
|
+
export { ARRAY_SIGNAL as A, CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _, setIdentifierGenerationMethod as a, setIdentifierUpdateMethod as b, setIdentifierForgetMethod as c, setIdentifierResetMethod as d, setKeyInfoForResource as e, constructResource as f, coerceId as g, ensureStringId as h, isStableIdentifier as i, Collection as j, SOURCE as k, fastPush as l, removeRecordDataFor as m, notifyArray as n, setRecordIdentifier as o, peekCache as p, StoreMap as q, recordIdentifierFor as r, storeFor as s, setCacheFor as t, normalizeModelName as u };
|