@ember-data/store 5.4.0-alpha.64 → 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-Dl0DS1Iq.js → dist/cache-handler-BCWOzbbB.js} +954 -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 +158 -196
- 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-Dl0DS1Iq.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/core-types/request';
|
|
4
|
-
import {
|
|
4
|
+
import { getOrSetGlobal, setTransient, peekTransient } from '@warp-drive/core-types/-private';
|
|
5
5
|
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '@warp-drive/core-types/identifier';
|
|
6
6
|
import { dasherize } from '@ember/string';
|
|
7
|
-
import { defineSignal,
|
|
7
|
+
import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
8
8
|
import { _backburner } from '@ember/runloop';
|
|
9
9
|
import { compat } from '@ember-data/tracking';
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ import { compat } from '@ember-data/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:deprecate-non-strict-types',
|
|
@@ -121,8 +129,8 @@ function hasType(resource) {
|
|
|
121
129
|
/**
|
|
122
130
|
@module @ember-data/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/store
|
|
766
802
|
*/
|
|
767
803
|
|
|
768
|
-
/**
|
|
769
|
-
@module @ember-data/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/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/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/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/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/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/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/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/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,
|
|
@@ -3352,18 +3626,47 @@ function constructResource(type, id, lid) {
|
|
|
3352
3626
|
* export default class extends Store {}
|
|
3353
3627
|
* ```
|
|
3354
3628
|
*
|
|
3355
|
-
* Most
|
|
3629
|
+
* Most Applications will only have a single `Store` configured as a Service
|
|
3356
3630
|
* in this manner. However, setting up multiple stores is possible, including using
|
|
3357
|
-
* each as a unique service.
|
|
3631
|
+
* each as a unique service or within a specific context.
|
|
3358
3632
|
*
|
|
3359
3633
|
|
|
3360
3634
|
@class Store
|
|
3361
3635
|
@public
|
|
3362
3636
|
*/
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
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:deprecate-store-extends-ember-object',
|
|
3661
|
+
until: '6.0',
|
|
3662
|
+
for: 'ember-data',
|
|
3663
|
+
since: {
|
|
3664
|
+
available: '5.4',
|
|
3665
|
+
enabled: '5.4'
|
|
3666
|
+
}
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3669
|
+
class Store extends BaseClass {
|
|
3367
3670
|
/**
|
|
3368
3671
|
* Provides access to the NotificationManager associated
|
|
3369
3672
|
* with this Store instance.
|
|
@@ -3386,7 +3689,10 @@ class Store extends EmberObject {
|
|
|
3386
3689
|
* @public
|
|
3387
3690
|
*/
|
|
3388
3691
|
get schema() {
|
|
3389
|
-
|
|
3692
|
+
if (!this._schema) {
|
|
3693
|
+
this._schema = this.createSchemaService();
|
|
3694
|
+
}
|
|
3695
|
+
return this._schema;
|
|
3390
3696
|
}
|
|
3391
3697
|
|
|
3392
3698
|
/**
|
|
@@ -3412,7 +3718,7 @@ class Store extends EmberObject {
|
|
|
3412
3718
|
* ```ts
|
|
3413
3719
|
* import Store, { CacheHandler } from '@ember-data/store';
|
|
3414
3720
|
* import RequestManager from '@ember-data/request';
|
|
3415
|
-
* import Fetch from '@ember
|
|
3721
|
+
* import Fetch from '@ember-data/request/fetch';
|
|
3416
3722
|
*
|
|
3417
3723
|
* class extends Store {
|
|
3418
3724
|
* constructor() {
|
|
@@ -3429,7 +3735,7 @@ class Store extends EmberObject {
|
|
|
3429
3735
|
*/
|
|
3430
3736
|
|
|
3431
3737
|
/**
|
|
3432
|
-
* A Property which an App may set to provide a
|
|
3738
|
+
* A Property which an App may set to provide a CachePolicy
|
|
3433
3739
|
* to control when a cached request becomes stale.
|
|
3434
3740
|
*
|
|
3435
3741
|
* Note, when defined, these methods will only be invoked if a
|
|
@@ -3455,7 +3761,7 @@ class Store extends EmberObject {
|
|
|
3455
3761
|
* ```
|
|
3456
3762
|
*
|
|
3457
3763
|
* @public
|
|
3458
|
-
* @property {
|
|
3764
|
+
* @property {CachePolicy|undefined} lifetimes
|
|
3459
3765
|
*/
|
|
3460
3766
|
|
|
3461
3767
|
// Private
|
|
@@ -3480,7 +3786,6 @@ class Store extends EmberObject {
|
|
|
3480
3786
|
@private
|
|
3481
3787
|
*/
|
|
3482
3788
|
constructor(createArgs) {
|
|
3483
|
-
// @ts-expect-error ember-source types improperly expect createArgs to be `Owner`
|
|
3484
3789
|
super(createArgs);
|
|
3485
3790
|
Object.assign(this, createArgs);
|
|
3486
3791
|
this.identifierCache = new IdentifierCache();
|
|
@@ -3499,9 +3804,13 @@ class Store extends EmberObject {
|
|
|
3499
3804
|
this.isDestroyed = false;
|
|
3500
3805
|
}
|
|
3501
3806
|
_run(cb) {
|
|
3502
|
-
|
|
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) : {};
|
|
3503
3812
|
const _cbs = this._cbs = {};
|
|
3504
|
-
if (macroCondition(
|
|
3813
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3505
3814
|
try {
|
|
3506
3815
|
cb();
|
|
3507
3816
|
if (_cbs.coalesce) {
|
|
@@ -3538,8 +3847,16 @@ class Store extends EmberObject {
|
|
|
3538
3847
|
}
|
|
3539
3848
|
}
|
|
3540
3849
|
_schedule(name, cb) {
|
|
3541
|
-
|
|
3542
|
-
|
|
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]) : {};
|
|
3543
3860
|
this._cbs[name] = cb;
|
|
3544
3861
|
}
|
|
3545
3862
|
|
|
@@ -3558,7 +3875,7 @@ class Store extends EmberObject {
|
|
|
3558
3875
|
return this._requestCache;
|
|
3559
3876
|
}
|
|
3560
3877
|
_getAllPending() {
|
|
3561
|
-
if (macroCondition(
|
|
3878
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
3562
3879
|
const all = [];
|
|
3563
3880
|
const pending = this._requestCache._pending;
|
|
3564
3881
|
pending.forEach(requests => {
|
|
@@ -3601,7 +3918,7 @@ class Store extends EmberObject {
|
|
|
3601
3918
|
* When a cache-key is determined, the request may fulfill
|
|
3602
3919
|
* from cache provided the cache is not stale.
|
|
3603
3920
|
*
|
|
3604
|
-
* Cache staleness is determined by the configured
|
|
3921
|
+
* Cache staleness is determined by the configured CachePolicy
|
|
3605
3922
|
* with priority given to the `cacheOptions.reload` and
|
|
3606
3923
|
* `cacheOptions.backgroundReload` on the request if present.
|
|
3607
3924
|
*
|
|
@@ -3636,12 +3953,12 @@ class Store extends EmberObject {
|
|
|
3636
3953
|
const identifierCache = this.identifierCache;
|
|
3637
3954
|
opts.records = requestConfig.records.map(r => identifierCache.getOrCreateRecordIdentifier(r));
|
|
3638
3955
|
}
|
|
3639
|
-
if (macroCondition(
|
|
3956
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
3640
3957
|
if (this.DISABLE_WAITER) {
|
|
3641
3958
|
opts.disableTestWaiter = typeof requestConfig.disableTestWaiter === 'boolean' ? requestConfig.disableTestWaiter : true;
|
|
3642
3959
|
}
|
|
3643
3960
|
}
|
|
3644
|
-
if (macroCondition(
|
|
3961
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
|
|
3645
3962
|
let options;
|
|
3646
3963
|
try {
|
|
3647
3964
|
options = JSON.parse(JSON.stringify(requestConfig));
|
|
@@ -3651,9 +3968,10 @@ class Store extends EmberObject {
|
|
|
3651
3968
|
// eslint-disable-next-line no-console
|
|
3652
3969
|
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3653
3970
|
}
|
|
3654
|
-
const
|
|
3971
|
+
const request = Object.assign({}, requestConfig, opts);
|
|
3972
|
+
const future = this.requestManager.request(request);
|
|
3655
3973
|
future.onFinalize(() => {
|
|
3656
|
-
if (macroCondition(
|
|
3974
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
|
|
3657
3975
|
// eslint-disable-next-line no-console
|
|
3658
3976
|
console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
|
|
3659
3977
|
}
|
|
@@ -3695,133 +4013,6 @@ class Store extends EmberObject {
|
|
|
3695
4013
|
* @param record
|
|
3696
4014
|
*/
|
|
3697
4015
|
|
|
3698
|
-
/**
|
|
3699
|
-
* Provides access to the SchemaDefinitionService instance
|
|
3700
|
-
* for this Store instance.
|
|
3701
|
-
*
|
|
3702
|
-
* The SchemaDefinitionService can be used to query for
|
|
3703
|
-
* information about the schema of a resource.
|
|
3704
|
-
*
|
|
3705
|
-
* @method getSchemaDefinitionService
|
|
3706
|
-
* @public
|
|
3707
|
-
*/
|
|
3708
|
-
getSchemaDefinitionService() {
|
|
3709
|
-
assert(`You must registerSchemaDefinitionService with the store to use custom model classes`, this._schema);
|
|
3710
|
-
return this._schema;
|
|
3711
|
-
}
|
|
3712
|
-
|
|
3713
|
-
/**
|
|
3714
|
-
* DEPRECATED - Use `registerSchema` instead.
|
|
3715
|
-
*
|
|
3716
|
-
* Allows an app to register a custom SchemaService
|
|
3717
|
-
* for use when information about a resource's schema needs
|
|
3718
|
-
* to be queried.
|
|
3719
|
-
*
|
|
3720
|
-
* This method can only be called more than once, but only one schema
|
|
3721
|
-
* definition service may exist. Therefore if you wish to chain services
|
|
3722
|
-
* you must lookup the existing service and close over it with the new
|
|
3723
|
-
* service by accessing `store.schema` prior to registration.
|
|
3724
|
-
*
|
|
3725
|
-
* For Example:
|
|
3726
|
-
*
|
|
3727
|
-
* ```ts
|
|
3728
|
-
* import Store from '@ember-data/store';
|
|
3729
|
-
*
|
|
3730
|
-
* class SchemaDelegator {
|
|
3731
|
-
* constructor(schema) {
|
|
3732
|
-
* this._schema = schema;
|
|
3733
|
-
* }
|
|
3734
|
-
*
|
|
3735
|
-
* doesTypeExist(type: string): boolean {
|
|
3736
|
-
* if (AbstractSchemas.has(type)) {
|
|
3737
|
-
* return true;
|
|
3738
|
-
* }
|
|
3739
|
-
* return this._schema.doesTypeExist(type);
|
|
3740
|
-
* }
|
|
3741
|
-
*
|
|
3742
|
-
* attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
|
|
3743
|
-
* return this._schema.attributesDefinitionFor(identifier);
|
|
3744
|
-
* }
|
|
3745
|
-
*
|
|
3746
|
-
* relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
|
|
3747
|
-
* const schema = AbstractSchemas.get(identifier.type);
|
|
3748
|
-
* return schema || this._schema.relationshipsDefinitionFor(identifier);
|
|
3749
|
-
* }
|
|
3750
|
-
* }
|
|
3751
|
-
*
|
|
3752
|
-
* export default class extends Store {
|
|
3753
|
-
* constructor(...args) {
|
|
3754
|
-
* super(...args);
|
|
3755
|
-
*
|
|
3756
|
-
* const schema = this.schema;
|
|
3757
|
-
* this.registerSchemaDefinitionService(new SchemaDelegator(schema));
|
|
3758
|
-
* }
|
|
3759
|
-
* }
|
|
3760
|
-
* ```
|
|
3761
|
-
*
|
|
3762
|
-
* @method registerSchemaDefinitionService
|
|
3763
|
-
* @param {SchemaService} schema
|
|
3764
|
-
* @deprecated
|
|
3765
|
-
* @public
|
|
3766
|
-
*/
|
|
3767
|
-
registerSchemaDefinitionService(schema) {
|
|
3768
|
-
this._schema = schema;
|
|
3769
|
-
}
|
|
3770
|
-
/**
|
|
3771
|
-
* Allows an app to register a custom SchemaService
|
|
3772
|
-
* for use when information about a resource's schema needs
|
|
3773
|
-
* to be queried.
|
|
3774
|
-
*
|
|
3775
|
-
* This method can only be called more than once, but only one schema
|
|
3776
|
-
* definition service may exist. Therefore if you wish to chain services
|
|
3777
|
-
* you must lookup the existing service and close over it with the new
|
|
3778
|
-
* service by accessing `store.schema` prior to registration.
|
|
3779
|
-
*
|
|
3780
|
-
* For Example:
|
|
3781
|
-
*
|
|
3782
|
-
* ```ts
|
|
3783
|
-
* import Store from '@ember-data/store';
|
|
3784
|
-
*
|
|
3785
|
-
* class SchemaDelegator {
|
|
3786
|
-
* constructor(schema) {
|
|
3787
|
-
* this._schema = schema;
|
|
3788
|
-
* }
|
|
3789
|
-
*
|
|
3790
|
-
* doesTypeExist(type: string): boolean {
|
|
3791
|
-
* if (AbstractSchemas.has(type)) {
|
|
3792
|
-
* return true;
|
|
3793
|
-
* }
|
|
3794
|
-
* return this._schema.doesTypeExist(type);
|
|
3795
|
-
* }
|
|
3796
|
-
*
|
|
3797
|
-
* attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
|
|
3798
|
-
* return this._schema.attributesDefinitionFor(identifier);
|
|
3799
|
-
* }
|
|
3800
|
-
*
|
|
3801
|
-
* relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
|
|
3802
|
-
* const schema = AbstractSchemas.get(identifier.type);
|
|
3803
|
-
* return schema || this._schema.relationshipsDefinitionFor(identifier);
|
|
3804
|
-
* }
|
|
3805
|
-
* }
|
|
3806
|
-
*
|
|
3807
|
-
* export default class extends Store {
|
|
3808
|
-
* constructor(...args) {
|
|
3809
|
-
* super(...args);
|
|
3810
|
-
*
|
|
3811
|
-
* const schema = this.schema;
|
|
3812
|
-
* this.registerSchema(new SchemaDelegator(schema));
|
|
3813
|
-
* }
|
|
3814
|
-
* }
|
|
3815
|
-
* ```
|
|
3816
|
-
*
|
|
3817
|
-
* @method registerSchema
|
|
3818
|
-
* @param {SchemaService} schema
|
|
3819
|
-
* @public
|
|
3820
|
-
*/
|
|
3821
|
-
registerSchema(schema) {
|
|
3822
|
-
this._schema = schema;
|
|
3823
|
-
}
|
|
3824
|
-
|
|
3825
4016
|
/**
|
|
3826
4017
|
Returns the schema for a particular resource type (modelName).
|
|
3827
4018
|
When used with Model from @ember-data/model the return is the model class,
|
|
@@ -3837,17 +4028,29 @@ class Store extends EmberObject {
|
|
|
3837
4028
|
for example.
|
|
3838
4029
|
@method modelFor
|
|
3839
4030
|
@public
|
|
4031
|
+
@deprecated
|
|
3840
4032
|
@param {string} type
|
|
3841
4033
|
@return {ModelSchema}
|
|
3842
4034
|
*/
|
|
3843
|
-
// TODO @deprecate in favor of schema APIs, requires adapter/serializer overhaul or replacement
|
|
3844
4035
|
|
|
3845
4036
|
modelFor(type) {
|
|
3846
|
-
|
|
4037
|
+
// FIXME add deprecation and deprecation stripping
|
|
4038
|
+
// FIXME/TODO update RFC to remove this method
|
|
4039
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3847
4040
|
assertDestroyedStoreOnly(this, 'modelFor');
|
|
3848
4041
|
}
|
|
3849
|
-
|
|
3850
|
-
|
|
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
|
+
})) : {};
|
|
3851
4054
|
return getShimClass(this, type);
|
|
3852
4055
|
}
|
|
3853
4056
|
|
|
@@ -3877,11 +4080,19 @@ class Store extends EmberObject {
|
|
|
3877
4080
|
*/
|
|
3878
4081
|
|
|
3879
4082
|
createRecord(type, inputProperties) {
|
|
3880
|
-
if (macroCondition(
|
|
4083
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3881
4084
|
assertDestroyingStore(this, 'createRecord');
|
|
3882
4085
|
}
|
|
3883
|
-
|
|
3884
|
-
|
|
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') : {};
|
|
3885
4096
|
|
|
3886
4097
|
// This is wrapped in a `run.join` so that in test environments users do not need to manually wrap
|
|
3887
4098
|
// calls to `createRecord`. The run loop usage here is because we batch the joining and updating
|
|
@@ -3916,7 +4127,11 @@ class Store extends EmberObject {
|
|
|
3916
4127
|
};
|
|
3917
4128
|
if (resource.id) {
|
|
3918
4129
|
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
3919
|
-
|
|
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) : {};
|
|
3920
4135
|
}
|
|
3921
4136
|
const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
|
|
3922
4137
|
const cache = this.cache;
|
|
@@ -3941,12 +4156,16 @@ class Store extends EmberObject {
|
|
|
3941
4156
|
@param {unknown} record
|
|
3942
4157
|
*/
|
|
3943
4158
|
deleteRecord(record) {
|
|
3944
|
-
if (macroCondition(
|
|
4159
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3945
4160
|
assertDestroyingStore(this, 'deleteRecord');
|
|
3946
4161
|
}
|
|
3947
4162
|
const identifier = peekRecordIdentifier(record);
|
|
3948
4163
|
const cache = this.cache;
|
|
3949
|
-
|
|
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) : {};
|
|
3950
4169
|
this._join(() => {
|
|
3951
4170
|
cache.setIsDeleted(identifier, true);
|
|
3952
4171
|
if (cache.isNew(identifier)) {
|
|
@@ -3969,7 +4188,7 @@ class Store extends EmberObject {
|
|
|
3969
4188
|
@param {Model} record
|
|
3970
4189
|
*/
|
|
3971
4190
|
unloadRecord(record) {
|
|
3972
|
-
if (macroCondition(
|
|
4191
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3973
4192
|
assertDestroyingStore(this, 'unloadRecord');
|
|
3974
4193
|
}
|
|
3975
4194
|
const identifier = peekRecordIdentifier(record);
|
|
@@ -3986,8 +4205,7 @@ class Store extends EmberObject {
|
|
|
3986
4205
|
resolved with the record.
|
|
3987
4206
|
**Example 1**
|
|
3988
4207
|
```app/routes/post.js
|
|
3989
|
-
|
|
3990
|
-
export default class PostRoute extends Route {
|
|
4208
|
+
export default class PostRoute extends Route {
|
|
3991
4209
|
model({ post_id }) {
|
|
3992
4210
|
return this.store.findRecord('post', post_id);
|
|
3993
4211
|
}
|
|
@@ -3998,8 +4216,7 @@ class Store extends EmberObject {
|
|
|
3998
4216
|
of `type` (modelName) and `id` as separate arguments. You may recognize this combo as
|
|
3999
4217
|
the typical pairing from [JSON:API](https://jsonapi.org/format/#document-resource-object-identification)
|
|
4000
4218
|
```app/routes/post.js
|
|
4001
|
-
|
|
4002
|
-
export default class PostRoute extends Route {
|
|
4219
|
+
export default class PostRoute extends Route {
|
|
4003
4220
|
model({ post_id: id }) {
|
|
4004
4221
|
return this.store.findRecord({ type: 'post', id });
|
|
4005
4222
|
}
|
|
@@ -4022,8 +4239,7 @@ class Store extends EmberObject {
|
|
|
4022
4239
|
for the comment also looks like `/posts/1/comments/2` if you want to fetch the comment
|
|
4023
4240
|
without also fetching the post you can pass in the post to the `findRecord` call:
|
|
4024
4241
|
```app/routes/post-comments.js
|
|
4025
|
-
|
|
4026
|
-
export default class PostRoute extends Route {
|
|
4242
|
+
export default class PostRoute extends Route {
|
|
4027
4243
|
model({ post_id, comment_id: id }) {
|
|
4028
4244
|
return this.store.findRecord({ type: 'comment', id, { preload: { post: post_id }} });
|
|
4029
4245
|
}
|
|
@@ -4049,8 +4265,7 @@ class Store extends EmberObject {
|
|
|
4049
4265
|
This could also be achieved by supplying the post id to the adapter via the adapterOptions
|
|
4050
4266
|
property on the options hash.
|
|
4051
4267
|
```app/routes/post-comments.js
|
|
4052
|
-
|
|
4053
|
-
export default class PostRoute extends Route {
|
|
4268
|
+
export default class PostRoute extends Route {
|
|
4054
4269
|
model({ post_id, comment_id: id }) {
|
|
4055
4270
|
return this.store.findRecord({ type: 'comment', id, { adapterOptions: { post: post_id }} });
|
|
4056
4271
|
}
|
|
@@ -4144,8 +4359,7 @@ class Store extends EmberObject {
|
|
|
4144
4359
|
boolean value for `backgroundReload` in the options object for
|
|
4145
4360
|
`findRecord`.
|
|
4146
4361
|
```app/routes/post/edit.js
|
|
4147
|
-
|
|
4148
|
-
export default class PostEditRoute extends Route {
|
|
4362
|
+
export default class PostEditRoute extends Route {
|
|
4149
4363
|
model(params) {
|
|
4150
4364
|
return this.store.findRecord('post', params.post_id, { backgroundReload: false });
|
|
4151
4365
|
}
|
|
@@ -4154,8 +4368,7 @@ class Store extends EmberObject {
|
|
|
4154
4368
|
If you pass an object on the `adapterOptions` property of the options
|
|
4155
4369
|
argument it will be passed to your adapter via the snapshot
|
|
4156
4370
|
```app/routes/post/edit.js
|
|
4157
|
-
|
|
4158
|
-
export default class PostEditRoute extends Route {
|
|
4371
|
+
export default class PostEditRoute extends Route {
|
|
4159
4372
|
model(params) {
|
|
4160
4373
|
return this.store.findRecord('post', params.post_id, {
|
|
4161
4374
|
adapterOptions: { subscribe: false }
|
|
@@ -4187,8 +4400,7 @@ class Store extends EmberObject {
|
|
|
4187
4400
|
model, when we retrieve a specific post we can have the server also return that post's
|
|
4188
4401
|
comments in the same request:
|
|
4189
4402
|
```app/routes/post.js
|
|
4190
|
-
|
|
4191
|
-
export default class PostRoute extends Route {
|
|
4403
|
+
export default class PostRoute extends Route {
|
|
4192
4404
|
model(params) {
|
|
4193
4405
|
return this.store.findRecord('post', params.post_id, { include: 'comments' });
|
|
4194
4406
|
}
|
|
@@ -4216,8 +4428,7 @@ class Store extends EmberObject {
|
|
|
4216
4428
|
using a dot-separated sequence of relationship names. So to request both the post's
|
|
4217
4429
|
comments and the authors of those comments the request would look like this:
|
|
4218
4430
|
```app/routes/post.js
|
|
4219
|
-
|
|
4220
|
-
export default class PostRoute extends Route {
|
|
4431
|
+
export default class PostRoute extends Route {
|
|
4221
4432
|
model(params) {
|
|
4222
4433
|
return this.store.findRecord('post', params.post_id, { include: 'comments,comments.author' });
|
|
4223
4434
|
}
|
|
@@ -4240,22 +4451,20 @@ class Store extends EmberObject {
|
|
|
4240
4451
|
2. Then pass through the applicable fields to your `findRecord` request.
|
|
4241
4452
|
Given a `post` model with attributes body, title, publishDate and meta, you can retrieve a filtered list of attributes.
|
|
4242
4453
|
```app/routes/post.js
|
|
4243
|
-
|
|
4244
|
-
export default Route.extend({
|
|
4454
|
+
export default class extends Route {
|
|
4245
4455
|
model(params) {
|
|
4246
4456
|
return this.store.findRecord('post', params.post_id, { adapterOptions: { fields: { post: 'body,title' } });
|
|
4247
4457
|
}
|
|
4248
|
-
}
|
|
4458
|
+
}
|
|
4249
4459
|
```
|
|
4250
4460
|
Moreover, you can filter attributes on related models as well. If a `post` has a `belongsTo` relationship to a user,
|
|
4251
4461
|
just include the relationship key and attributes.
|
|
4252
4462
|
```app/routes/post.js
|
|
4253
|
-
|
|
4254
|
-
export default Route.extend({
|
|
4463
|
+
export default class extends Route {
|
|
4255
4464
|
model(params) {
|
|
4256
4465
|
return this.store.findRecord('post', params.post_id, { adapterOptions: { fields: { post: 'body,title', user: 'name,email' } });
|
|
4257
4466
|
}
|
|
4258
|
-
}
|
|
4467
|
+
}
|
|
4259
4468
|
```
|
|
4260
4469
|
@since 1.13.0
|
|
4261
4470
|
@method findRecord
|
|
@@ -4267,14 +4476,22 @@ class Store extends EmberObject {
|
|
|
4267
4476
|
*/
|
|
4268
4477
|
|
|
4269
4478
|
findRecord(resource, id, options) {
|
|
4270
|
-
if (macroCondition(
|
|
4479
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4271
4480
|
assertDestroyingStore(this, 'findRecord');
|
|
4272
4481
|
}
|
|
4273
|
-
|
|
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) : {};
|
|
4274
4487
|
if (isMaybeIdentifier(resource)) {
|
|
4275
4488
|
options = id;
|
|
4276
4489
|
} else {
|
|
4277
|
-
|
|
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') : {};
|
|
4278
4495
|
const type = normalizeModelName(resource);
|
|
4279
4496
|
const normalizedId = ensureStringId(id);
|
|
4280
4497
|
resource = constructResource(type, normalizedId);
|
|
@@ -4338,7 +4555,7 @@ class Store extends EmberObject {
|
|
|
4338
4555
|
*/
|
|
4339
4556
|
// TODO @deprecate getReference (and references generally)
|
|
4340
4557
|
getReference(resource, id) {
|
|
4341
|
-
if (macroCondition(
|
|
4558
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4342
4559
|
assertDestroyingStore(this, 'getReference');
|
|
4343
4560
|
}
|
|
4344
4561
|
let resourceIdentifier;
|
|
@@ -4349,7 +4566,11 @@ class Store extends EmberObject {
|
|
|
4349
4566
|
const normalizedId = ensureStringId(id);
|
|
4350
4567
|
resourceIdentifier = constructResource(type, normalizedId);
|
|
4351
4568
|
}
|
|
4352
|
-
|
|
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)) : {};
|
|
4353
4574
|
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
4354
4575
|
return this._instanceCache.getReference(identifier);
|
|
4355
4576
|
}
|
|
@@ -4397,11 +4618,19 @@ class Store extends EmberObject {
|
|
|
4397
4618
|
// this is basically an "are we not empty" query.
|
|
4398
4619
|
return isLoaded ? this._instanceCache.getRecord(stableIdentifier) : null;
|
|
4399
4620
|
}
|
|
4400
|
-
if (macroCondition(
|
|
4621
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4401
4622
|
assertDestroyingStore(this, 'peekRecord');
|
|
4402
4623
|
}
|
|
4403
|
-
|
|
4404
|
-
|
|
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') : {};
|
|
4405
4634
|
const type = normalizeModelName(identifier);
|
|
4406
4635
|
const normalizedId = ensureStringId(id);
|
|
4407
4636
|
const resource = {
|
|
@@ -4452,12 +4681,24 @@ class Store extends EmberObject {
|
|
|
4452
4681
|
*/
|
|
4453
4682
|
|
|
4454
4683
|
query(type, query, options = {}) {
|
|
4455
|
-
if (macroCondition(
|
|
4684
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4456
4685
|
assertDestroyingStore(this, 'query');
|
|
4457
4686
|
}
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
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') : {};
|
|
4461
4702
|
const promise = this.request({
|
|
4462
4703
|
op: 'query',
|
|
4463
4704
|
data: {
|
|
@@ -4555,12 +4796,24 @@ class Store extends EmberObject {
|
|
|
4555
4796
|
*/
|
|
4556
4797
|
|
|
4557
4798
|
queryRecord(type, query, options) {
|
|
4558
|
-
if (macroCondition(
|
|
4799
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4559
4800
|
assertDestroyingStore(this, 'queryRecord');
|
|
4560
4801
|
}
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
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') : {};
|
|
4564
4817
|
const promise = this.request({
|
|
4565
4818
|
op: 'queryRecord',
|
|
4566
4819
|
data: {
|
|
@@ -4581,8 +4834,7 @@ class Store extends EmberObject {
|
|
|
4581
4834
|
this type present in the store, even if the adapter only returns a subset
|
|
4582
4835
|
of them.
|
|
4583
4836
|
```app/routes/authors.js
|
|
4584
|
-
|
|
4585
|
-
export default class AuthorsRoute extends Route {
|
|
4837
|
+
export default class AuthorsRoute extends Route {
|
|
4586
4838
|
model(params) {
|
|
4587
4839
|
return this.store.findAll('author');
|
|
4588
4840
|
}
|
|
@@ -4655,8 +4907,7 @@ class Store extends EmberObject {
|
|
|
4655
4907
|
boolean value for `backgroundReload` in the options object for
|
|
4656
4908
|
`findAll`.
|
|
4657
4909
|
```app/routes/post/edit.js
|
|
4658
|
-
|
|
4659
|
-
export default class PostEditRoute extends Route {
|
|
4910
|
+
export default class PostEditRoute extends Route {
|
|
4660
4911
|
model() {
|
|
4661
4912
|
return this.store.findAll('post', { backgroundReload: false });
|
|
4662
4913
|
}
|
|
@@ -4665,8 +4916,7 @@ class Store extends EmberObject {
|
|
|
4665
4916
|
If you pass an object on the `adapterOptions` property of the options
|
|
4666
4917
|
argument it will be passed to you adapter via the `snapshotRecordArray`
|
|
4667
4918
|
```app/routes/posts.js
|
|
4668
|
-
|
|
4669
|
-
export default class PostsRoute extends Route {
|
|
4919
|
+
export default class PostsRoute extends Route {
|
|
4670
4920
|
model(params) {
|
|
4671
4921
|
return this.store.findAll('post', {
|
|
4672
4922
|
adapterOptions: { subscribe: false }
|
|
@@ -4699,8 +4949,7 @@ class Store extends EmberObject {
|
|
|
4699
4949
|
model, when we retrieve all of the post records we can have the server also return
|
|
4700
4950
|
all of the posts' comments in the same request:
|
|
4701
4951
|
```app/routes/posts.js
|
|
4702
|
-
|
|
4703
|
-
export default class PostsRoute extends Route {
|
|
4952
|
+
export default class PostsRoute extends Route {
|
|
4704
4953
|
model() {
|
|
4705
4954
|
return this.store.findAll('post', { include: 'comments' });
|
|
4706
4955
|
}
|
|
@@ -4711,8 +4960,7 @@ class Store extends EmberObject {
|
|
|
4711
4960
|
using a dot-separated sequence of relationship names. So to request both the posts'
|
|
4712
4961
|
comments and the authors of those comments the request would look like this:
|
|
4713
4962
|
```app/routes/posts.js
|
|
4714
|
-
|
|
4715
|
-
export default class PostsRoute extends Route {
|
|
4963
|
+
export default class PostsRoute extends Route {
|
|
4716
4964
|
model() {
|
|
4717
4965
|
return this.store.findAll('post', { include: 'comments,comments.author' });
|
|
4718
4966
|
}
|
|
@@ -4728,11 +4976,19 @@ class Store extends EmberObject {
|
|
|
4728
4976
|
*/
|
|
4729
4977
|
|
|
4730
4978
|
findAll(type, options = {}) {
|
|
4731
|
-
if (macroCondition(
|
|
4979
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4732
4980
|
assertDestroyingStore(this, 'findAll');
|
|
4733
4981
|
}
|
|
4734
|
-
|
|
4735
|
-
|
|
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') : {};
|
|
4736
4992
|
const promise = this.request({
|
|
4737
4993
|
op: 'findAll',
|
|
4738
4994
|
data: {
|
|
@@ -4768,11 +5024,19 @@ class Store extends EmberObject {
|
|
|
4768
5024
|
*/
|
|
4769
5025
|
|
|
4770
5026
|
peekAll(type) {
|
|
4771
|
-
if (macroCondition(
|
|
5027
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4772
5028
|
assertDestroyingStore(this, 'peekAll');
|
|
4773
5029
|
}
|
|
4774
|
-
|
|
4775
|
-
|
|
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') : {};
|
|
4776
5040
|
return this.recordArrayManager.liveArrayFor(normalizeModelName(type));
|
|
4777
5041
|
}
|
|
4778
5042
|
|
|
@@ -4790,10 +5054,14 @@ class Store extends EmberObject {
|
|
|
4790
5054
|
*/
|
|
4791
5055
|
|
|
4792
5056
|
unloadAll(type) {
|
|
4793
|
-
if (macroCondition(
|
|
5057
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4794
5058
|
assertDestroyedStoreOnly(this, 'unloadAll');
|
|
4795
5059
|
}
|
|
4796
|
-
|
|
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') : {};
|
|
4797
5065
|
this._join(() => {
|
|
4798
5066
|
if (type === undefined) {
|
|
4799
5067
|
// destroy the graph before unloadAll
|
|
@@ -4940,7 +5208,7 @@ class Store extends EmberObject {
|
|
|
4940
5208
|
*/
|
|
4941
5209
|
|
|
4942
5210
|
push(data) {
|
|
4943
|
-
if (macroCondition(
|
|
5211
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4944
5212
|
assertDestroyingStore(this, 'push');
|
|
4945
5213
|
}
|
|
4946
5214
|
const pushed = this._push(data, false);
|
|
@@ -4962,10 +5230,10 @@ class Store extends EmberObject {
|
|
|
4962
5230
|
@return {StableRecordIdentifier|Array<StableRecordIdentifier>|null} identifiers for the primary records that had data loaded
|
|
4963
5231
|
*/
|
|
4964
5232
|
_push(jsonApiDoc, asyncFlush) {
|
|
4965
|
-
if (macroCondition(
|
|
5233
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
4966
5234
|
assertDestroyingStore(this, '_push');
|
|
4967
5235
|
}
|
|
4968
|
-
if (macroCondition(
|
|
5236
|
+
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS)) {
|
|
4969
5237
|
try {
|
|
4970
5238
|
const data = JSON.parse(JSON.stringify(jsonApiDoc));
|
|
4971
5239
|
// eslint-disable-next-line no-console
|
|
@@ -5000,10 +5268,14 @@ class Store extends EmberObject {
|
|
|
5000
5268
|
* @return {Promise<record>}
|
|
5001
5269
|
*/
|
|
5002
5270
|
saveRecord(record, options = {}) {
|
|
5003
|
-
if (macroCondition(
|
|
5271
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5004
5272
|
assertDestroyingStore(this, 'saveRecord');
|
|
5005
5273
|
}
|
|
5006
|
-
|
|
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)) : {};
|
|
5007
5279
|
const identifier = recordIdentifierFor(record);
|
|
5008
5280
|
const cache = this.cache;
|
|
5009
5281
|
if (!identifier) {
|
|
@@ -5011,7 +5283,11 @@ class Store extends EmberObject {
|
|
|
5011
5283
|
// but just in case we reject here to prevent bad things.
|
|
5012
5284
|
return Promise.reject(new Error(`Record Is Disconnected`));
|
|
5013
5285
|
}
|
|
5014
|
-
|
|
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)) : {};
|
|
5015
5291
|
if (resourceIsFullyDeleted(this._instanceCache, identifier)) {
|
|
5016
5292
|
return Promise.resolve(record);
|
|
5017
5293
|
}
|
|
@@ -5064,14 +5340,12 @@ class Store extends EmberObject {
|
|
|
5064
5340
|
} = this._instanceCache;
|
|
5065
5341
|
if (!cache) {
|
|
5066
5342
|
cache = this._instanceCache.cache = this.createCache(this._instanceCache._storeWrapper);
|
|
5067
|
-
if (macroCondition(
|
|
5343
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5068
5344
|
cache = new CacheManager(cache);
|
|
5069
5345
|
}
|
|
5070
5346
|
}
|
|
5071
5347
|
return cache;
|
|
5072
5348
|
}
|
|
5073
|
-
|
|
5074
|
-
// @ts-expect-error
|
|
5075
5349
|
destroy() {
|
|
5076
5350
|
if (this.isDestroyed) {
|
|
5077
5351
|
// @ember/test-helpers will call destroy multiple times
|
|
@@ -5090,16 +5364,67 @@ class Store extends EmberObject {
|
|
|
5090
5364
|
return new this(args);
|
|
5091
5365
|
}
|
|
5092
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:schema-service-updates',
|
|
5376
|
+
until: '5.0',
|
|
5377
|
+
for: 'ember-data',
|
|
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:schema-service-updates',
|
|
5388
|
+
until: '5.0',
|
|
5389
|
+
for: 'ember-data',
|
|
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:schema-service-updates',
|
|
5400
|
+
until: '5.0',
|
|
5401
|
+
for: 'ember-data',
|
|
5402
|
+
since: {
|
|
5403
|
+
available: '5.4',
|
|
5404
|
+
enabled: '5.4'
|
|
5405
|
+
}
|
|
5406
|
+
});
|
|
5407
|
+
this._schema = schema;
|
|
5408
|
+
};
|
|
5409
|
+
}
|
|
5093
5410
|
let assertDestroyingStore;
|
|
5094
5411
|
let assertDestroyedStoreOnly;
|
|
5095
|
-
if (macroCondition(
|
|
5412
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5096
5413
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5097
5414
|
assertDestroyingStore = function assertDestroyingStore(store, method) {
|
|
5098
|
-
|
|
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)) : {};
|
|
5099
5420
|
};
|
|
5100
5421
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5101
5422
|
assertDestroyedStoreOnly = function assertDestroyedStoreOnly(store, method) {
|
|
5102
|
-
|
|
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) : {};
|
|
5103
5428
|
};
|
|
5104
5429
|
}
|
|
5105
5430
|
function isMaybeIdentifier(maybeIdentifier) {
|
|
@@ -5109,33 +5434,38 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5109
5434
|
// assert here
|
|
5110
5435
|
if (properties !== undefined) {
|
|
5111
5436
|
if ('id' in properties) {
|
|
5112
|
-
|
|
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) : {};
|
|
5113
5442
|
}
|
|
5114
|
-
|
|
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) : {};
|
|
5115
5448
|
const {
|
|
5116
5449
|
type
|
|
5117
5450
|
} = identifier;
|
|
5118
5451
|
|
|
5119
5452
|
// convert relationship Records to RecordDatas before passing to RecordData
|
|
5120
|
-
const defs = store.
|
|
5453
|
+
const defs = store.schema.fields({
|
|
5121
5454
|
type
|
|
5122
5455
|
});
|
|
5123
|
-
if (defs
|
|
5456
|
+
if (defs.size) {
|
|
5124
5457
|
const keys = Object.keys(properties);
|
|
5125
|
-
let relationshipValue;
|
|
5126
5458
|
for (let i = 0; i < keys.length; i++) {
|
|
5127
5459
|
const prop = keys[i];
|
|
5128
|
-
const
|
|
5129
|
-
if (
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
}
|
|
5134
|
-
relationshipValue = extractIdentifiersFromRecords(properties[prop]);
|
|
5135
|
-
} else {
|
|
5136
|
-
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]);
|
|
5137
5465
|
}
|
|
5138
|
-
properties[prop] =
|
|
5466
|
+
properties[prop] = extractIdentifiersFromRecords(properties[prop]);
|
|
5467
|
+
} else if (field.kind === 'belongsTo') {
|
|
5468
|
+
properties[prop] = extractIdentifierFromRecord(properties[prop]);
|
|
5139
5469
|
}
|
|
5140
5470
|
}
|
|
5141
5471
|
}
|
|
@@ -5143,8 +5473,16 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5143
5473
|
return properties;
|
|
5144
5474
|
}
|
|
5145
5475
|
function assertRecordsPassedToHasMany(records) {
|
|
5146
|
-
|
|
5147
|
-
|
|
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 () {
|
|
5148
5486
|
return records.every(record => {
|
|
5149
5487
|
try {
|
|
5150
5488
|
recordIdentifierFor(record);
|
|
@@ -5153,7 +5491,7 @@ function assertRecordsPassedToHasMany(records) {
|
|
|
5153
5491
|
return false;
|
|
5154
5492
|
}
|
|
5155
5493
|
});
|
|
5156
|
-
}());
|
|
5494
|
+
}()) : {};
|
|
5157
5495
|
}
|
|
5158
5496
|
function extractIdentifiersFromRecords(records) {
|
|
5159
5497
|
return records.map(record => extractIdentifierFromRecord(record));
|
|
@@ -5165,6 +5503,10 @@ function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
|
5165
5503
|
const extract = recordIdentifierFor;
|
|
5166
5504
|
return extract(recordOrPromiseRecord);
|
|
5167
5505
|
}
|
|
5506
|
+
|
|
5507
|
+
/**
|
|
5508
|
+
* @module @ember-data/store
|
|
5509
|
+
*/
|
|
5168
5510
|
function urlFromLink(link) {
|
|
5169
5511
|
if (typeof link === 'string') return link;
|
|
5170
5512
|
return link.href;
|
|
@@ -5182,69 +5524,79 @@ function urlFromLink(link) {
|
|
|
5182
5524
|
* @public
|
|
5183
5525
|
* @class Document
|
|
5184
5526
|
*/
|
|
5185
|
-
var _store = /*#__PURE__*/_classPrivateFieldKey("store");
|
|
5186
|
-
var _request = /*#__PURE__*/_classPrivateFieldKey("request");
|
|
5187
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;
|
|
5188
5583
|
constructor(store, identifier) {
|
|
5189
|
-
|
|
5190
|
-
value: _request2
|
|
5191
|
-
});
|
|
5192
|
-
/**
|
|
5193
|
-
* The links object for this document, if any
|
|
5194
|
-
*
|
|
5195
|
-
* e.g.
|
|
5196
|
-
*
|
|
5197
|
-
* ```
|
|
5198
|
-
* {
|
|
5199
|
-
* self: '/articles?page[number]=3',
|
|
5200
|
-
* }
|
|
5201
|
-
* ```
|
|
5202
|
-
*
|
|
5203
|
-
* @property links
|
|
5204
|
-
* @type {object|undefined} - a links object
|
|
5205
|
-
* @public
|
|
5206
|
-
*/
|
|
5207
|
-
/**
|
|
5208
|
-
* The primary data for this document, if any.
|
|
5209
|
-
*
|
|
5210
|
-
* If this document has no primary data (e.g. because it is an error document)
|
|
5211
|
-
* this property will be `undefined`.
|
|
5212
|
-
*
|
|
5213
|
-
* For collections this will be an array of record instances,
|
|
5214
|
-
* for single resource requests it will be a single record instance or null.
|
|
5215
|
-
*
|
|
5216
|
-
* @property data
|
|
5217
|
-
* @public
|
|
5218
|
-
* @type {object|Array<object>|null|undefined} - a data object
|
|
5219
|
-
*/
|
|
5220
|
-
/**
|
|
5221
|
-
* The errors returned by the API for this request, if any
|
|
5222
|
-
*
|
|
5223
|
-
* @property errors
|
|
5224
|
-
* @public
|
|
5225
|
-
* @type {object|undefined} - an errors object
|
|
5226
|
-
*/
|
|
5227
|
-
/**
|
|
5228
|
-
* The meta object for this document, if any
|
|
5229
|
-
*
|
|
5230
|
-
* @property meta
|
|
5231
|
-
* @public
|
|
5232
|
-
* @type {object|undefined} - a meta object
|
|
5233
|
-
*/
|
|
5234
|
-
/**
|
|
5235
|
-
* The identifier associated with this document, if any
|
|
5236
|
-
*
|
|
5237
|
-
* @property identifier
|
|
5238
|
-
* @public
|
|
5239
|
-
* @type {StableDocumentIdentifier|null}
|
|
5240
|
-
*/
|
|
5241
|
-
Object.defineProperty(this, _store, {
|
|
5242
|
-
writable: true,
|
|
5243
|
-
value: void 0
|
|
5244
|
-
});
|
|
5245
|
-
_classPrivateFieldBase(this, _store)[_store] = store;
|
|
5584
|
+
this.#store = store;
|
|
5246
5585
|
this.identifier = identifier;
|
|
5247
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
|
+
|
|
5248
5600
|
/**
|
|
5249
5601
|
* Fetches the related link for this document, returning a promise that resolves
|
|
5250
5602
|
* with the document when the request completes. If no related link is present,
|
|
@@ -5256,10 +5608,14 @@ class Document {
|
|
|
5256
5608
|
* @return Promise<Document>
|
|
5257
5609
|
*/
|
|
5258
5610
|
fetch(options = {}) {
|
|
5259
|
-
|
|
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) : {};
|
|
5260
5616
|
options.cacheOptions = options.cacheOptions || {};
|
|
5261
5617
|
options.cacheOptions.key = this.identifier?.lid;
|
|
5262
|
-
return
|
|
5618
|
+
return this.#request(this.links.related ? 'related' : 'self', options);
|
|
5263
5619
|
}
|
|
5264
5620
|
|
|
5265
5621
|
/**
|
|
@@ -5273,7 +5629,7 @@ class Document {
|
|
|
5273
5629
|
* @return Promise<Document | null>
|
|
5274
5630
|
*/
|
|
5275
5631
|
next(options = {}) {
|
|
5276
|
-
return
|
|
5632
|
+
return this.#request('next', options);
|
|
5277
5633
|
}
|
|
5278
5634
|
|
|
5279
5635
|
/**
|
|
@@ -5287,7 +5643,7 @@ class Document {
|
|
|
5287
5643
|
* @return Promise<Document | null>
|
|
5288
5644
|
*/
|
|
5289
5645
|
prev(options = {}) {
|
|
5290
|
-
return
|
|
5646
|
+
return this.#request('prev', options);
|
|
5291
5647
|
}
|
|
5292
5648
|
|
|
5293
5649
|
/**
|
|
@@ -5301,7 +5657,7 @@ class Document {
|
|
|
5301
5657
|
* @return Promise<Document | null>
|
|
5302
5658
|
*/
|
|
5303
5659
|
first(options = {}) {
|
|
5304
|
-
return
|
|
5660
|
+
return this.#request('first', options);
|
|
5305
5661
|
}
|
|
5306
5662
|
|
|
5307
5663
|
/**
|
|
@@ -5315,7 +5671,7 @@ class Document {
|
|
|
5315
5671
|
* @return Promise<Document | null>
|
|
5316
5672
|
*/
|
|
5317
5673
|
last(options = {}) {
|
|
5318
|
-
return
|
|
5674
|
+
return this.#request('last', options);
|
|
5319
5675
|
}
|
|
5320
5676
|
|
|
5321
5677
|
/**
|
|
@@ -5349,17 +5705,6 @@ class Document {
|
|
|
5349
5705
|
return data;
|
|
5350
5706
|
}
|
|
5351
5707
|
}
|
|
5352
|
-
async function _request2(link, options) {
|
|
5353
|
-
const href = this.links?.[link];
|
|
5354
|
-
if (!href) {
|
|
5355
|
-
return null;
|
|
5356
|
-
}
|
|
5357
|
-
options.method = options.method || 'GET';
|
|
5358
|
-
const response = await _classPrivateFieldBase(this, _store)[_store].request(Object.assign(options, {
|
|
5359
|
-
url: urlFromLink(href)
|
|
5360
|
-
}));
|
|
5361
|
-
return response.content;
|
|
5362
|
-
}
|
|
5363
5708
|
defineSignal(Document.prototype, 'data');
|
|
5364
5709
|
defineSignal(Document.prototype, 'links');
|
|
5365
5710
|
defineSignal(Document.prototype, 'errors');
|
|
@@ -5380,10 +5725,9 @@ defineSignal(Document.prototype, 'meta');
|
|
|
5380
5725
|
* Implementing this service allows you to programatically define
|
|
5381
5726
|
* when a request should be considered expired.
|
|
5382
5727
|
*
|
|
5383
|
-
* @class <Interface>
|
|
5728
|
+
* @class <Interface> CachePolicy
|
|
5384
5729
|
* @public
|
|
5385
5730
|
*/
|
|
5386
|
-
|
|
5387
5731
|
const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
|
|
5388
5732
|
function isErrorDocument(document) {
|
|
5389
5733
|
return 'errors' in document;
|
|
@@ -5393,7 +5737,11 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
|
|
|
5393
5737
|
identifier
|
|
5394
5738
|
} = options;
|
|
5395
5739
|
if (!document) {
|
|
5396
|
-
|
|
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) : {};
|
|
5397
5745
|
return document;
|
|
5398
5746
|
}
|
|
5399
5747
|
if (isErrorDocument(document)) {
|
|
@@ -5493,7 +5841,7 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
|
|
|
5493
5841
|
const {
|
|
5494
5842
|
cacheOptions
|
|
5495
5843
|
} = request;
|
|
5496
|
-
return
|
|
5844
|
+
return cacheOptions?.backgroundReload || (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier, store) : false);
|
|
5497
5845
|
}
|
|
5498
5846
|
function isMutation(request) {
|
|
5499
5847
|
return Boolean(request.op && MUTATION_OPS.has(request.op));
|
|
@@ -5508,7 +5856,11 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
|
|
|
5508
5856
|
isMut = true;
|
|
5509
5857
|
// TODO should we handle multiple records in request.records by iteratively calling willCommit for each
|
|
5510
5858
|
const record = context.request.data?.record || context.request.records?.[0];
|
|
5511
|
-
|
|
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) : {};
|
|
5512
5864
|
if (record) {
|
|
5513
5865
|
store.cache.willCommit(record, context);
|
|
5514
5866
|
}
|
|
@@ -5593,7 +5945,11 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
|
|
|
5593
5945
|
if (!isMut) {
|
|
5594
5946
|
return promise;
|
|
5595
5947
|
}
|
|
5596
|
-
|
|
5948
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5949
|
+
if (!test) {
|
|
5950
|
+
throw new Error(`Expected a mutation`);
|
|
5951
|
+
}
|
|
5952
|
+
})(isMutation(context.request)) : {};
|
|
5597
5953
|
|
|
5598
5954
|
// for mutations we need to enqueue the promise with the requestStateService
|
|
5599
5955
|
// TODO should we enque a request per record in records?
|
|
@@ -5725,4 +6081,4 @@ function isCacheAffecting(document) {
|
|
|
5725
6081
|
}
|
|
5726
6082
|
return document.response?.status !== 204;
|
|
5727
6083
|
}
|
|
5728
|
-
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 };
|