@warp-drive-mirror/schema-record 4.13.0-alpha.3 → 4.13.0-alpha.5
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/LICENSE.md +19 -8
- package/README.md +211 -123
- package/dist/-private.js +1 -0
- package/dist/-private.js.map +1 -0
- package/dist/{record.js → index.js} +531 -68
- package/dist/index.js.map +1 -0
- package/dist/symbols-DqoS4ybV.js.map +1 -1
- package/logos/NCC-1701-a-gold.svg +4 -0
- package/logos/NCC-1701-a-gold_100.svg +1 -0
- package/logos/NCC-1701-a-gold_base-64.txt +1 -0
- package/logos/README.md +4 -0
- package/logos/docs-badge.svg +2 -0
- package/logos/ember-data-logo-dark.svg +12 -0
- package/logos/ember-data-logo-light.svg +12 -0
- package/logos/github-header.svg +444 -0
- package/logos/social1.png +0 -0
- package/logos/social2.png +0 -0
- package/logos/warp-drive-logo-dark.svg +4 -0
- package/logos/warp-drive-logo-gold.svg +4 -0
- package/package.json +38 -55
- package/unstable-preview-types/-private/{compute.d.ts → fields/compute.d.ts} +17 -15
- package/unstable-preview-types/-private/fields/compute.d.ts.map +1 -0
- package/unstable-preview-types/-private/{managed-array.d.ts → fields/managed-array.d.ts} +4 -4
- package/unstable-preview-types/-private/fields/managed-array.d.ts.map +1 -0
- package/unstable-preview-types/-private/{managed-object.d.ts → fields/managed-object.d.ts} +4 -4
- package/unstable-preview-types/-private/fields/managed-object.d.ts.map +1 -0
- package/unstable-preview-types/-private/fields/many-array-manager.d.ts +23 -0
- package/unstable-preview-types/-private/fields/many-array-manager.d.ts.map +1 -0
- package/unstable-preview-types/{hooks.d.ts → -private/hooks.d.ts} +3 -3
- package/unstable-preview-types/-private/hooks.d.ts.map +1 -0
- package/unstable-preview-types/{record.d.ts → -private/record.d.ts} +3 -3
- package/unstable-preview-types/-private/record.d.ts.map +1 -0
- package/unstable-preview-types/{schema.d.ts → -private/schema.d.ts} +2 -2
- package/unstable-preview-types/-private/schema.d.ts.map +1 -0
- package/unstable-preview-types/{symbols.d.ts → -private/symbols.d.ts} +1 -1
- package/unstable-preview-types/-private/symbols.d.ts.map +1 -0
- package/unstable-preview-types/-private.d.ts +4 -0
- package/unstable-preview-types/-private.d.ts.map +1 -0
- package/unstable-preview-types/index.d.ts +16 -7
- package/unstable-preview-types/index.d.ts.map +1 -0
- package/dist/hooks.js +0 -19
- package/dist/hooks.js.map +0 -1
- package/dist/record.js.map +0 -1
- package/dist/schema.js +0 -278
- package/dist/schema.js.map +0 -1
- package/unstable-preview-types/-private/compute.d.ts.map +0 -1
- package/unstable-preview-types/-private/managed-array.d.ts.map +0 -1
- package/unstable-preview-types/-private/managed-object.d.ts.map +0 -1
- package/unstable-preview-types/hooks.d.ts.map +0 -1
- package/unstable-preview-types/record.d.ts.map +0 -1
- package/unstable-preview-types/schema.d.ts.map +0 -1
- package/unstable-preview-types/symbols.d.ts.map +0 -1
- /package/{NCC-1701-a-blue.svg → logos/NCC-1701-a-blue.svg} +0 -0
- /package/{NCC-1701-a.svg → logos/NCC-1701-a.svg} +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
2
|
-
import { setRecordIdentifier, recordIdentifierFor } from '@ember-data-mirror/store/-private';
|
|
3
|
-
import { createSignal, subscribe, defineSignal, peekSignal, getSignal, Signals,
|
|
4
|
-
import { STRUCTURED } from '@warp-drive-mirror/core-types/request';
|
|
5
|
-
import { RecordStore } from '@warp-drive-mirror/core-types/symbols';
|
|
2
|
+
import { SOURCE as SOURCE$1, fastPush, RelatedCollection, setRecordIdentifier, recordIdentifierFor } from '@ember-data-mirror/store/-private';
|
|
3
|
+
import { createSignal, subscribe, defineSignal, peekSignal, getSignal, Signals, addToTransaction, entangleSignal } from '@ember-data-mirror/tracking/-private';
|
|
4
|
+
import { EnableHydration, STRUCTURED } from '@warp-drive-mirror/core-types/request';
|
|
5
|
+
import { RecordStore, Type } from '@warp-drive-mirror/core-types/symbols';
|
|
6
6
|
import { getOrSetGlobal } from '@warp-drive-mirror/core-types/-private';
|
|
7
7
|
import { S as SOURCE, A as ARRAY_SIGNAL, E as Editable, L as Legacy, I as Identifier, P as Parent, O as OBJECT_SIGNAL, a as EmbeddedPath, D as Destroy, C as Checkout, b as EmbeddedType } from "./symbols-DqoS4ybV.js";
|
|
8
|
+
import { deprecate } from '@ember/debug';
|
|
9
|
+
import { recordIdentifierFor as recordIdentifierFor$1 } from '@ember-data-mirror/store';
|
|
10
|
+
import { createCache, getValue } from '@ember-data-mirror/tracking';
|
|
8
11
|
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']);
|
|
9
12
|
// const ARRAY_SETTER_METHODS = new Set<KeyType>(['push', 'pop', 'unshift', 'shift', 'splice', 'sort']);
|
|
10
13
|
const SYNC_PROPS = new Set(['[]', 'length']);
|
|
@@ -32,7 +35,7 @@ function safeForEach(instance, arr, store, callback, target) {
|
|
|
32
35
|
}
|
|
33
36
|
// clone to prevent mutation
|
|
34
37
|
arr = arr.slice();
|
|
35
|
-
macroCondition(getGlobalConfig().
|
|
38
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
36
39
|
if (!test) {
|
|
37
40
|
throw new Error('`forEach` expects a function as first argument.');
|
|
38
41
|
}
|
|
@@ -112,7 +115,7 @@ class ManagedArray {
|
|
|
112
115
|
// the given field does not exist OR
|
|
113
116
|
// the field is anything other than a GenericField or LegacyAttributeField.
|
|
114
117
|
if (mode !== '@identity' && mode !== '@index') {
|
|
115
|
-
macroCondition(getGlobalConfig().
|
|
118
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
116
119
|
if (!test) {
|
|
117
120
|
throw new Error('mode must be a string');
|
|
118
121
|
}
|
|
@@ -120,12 +123,12 @@ class ManagedArray {
|
|
|
120
123
|
const modeField = schema.resource({
|
|
121
124
|
type: field.type
|
|
122
125
|
}).fields.find(f => f.name === mode);
|
|
123
|
-
macroCondition(getGlobalConfig().
|
|
126
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
124
127
|
if (!test) {
|
|
125
128
|
throw new Error('field must exist in schema');
|
|
126
129
|
}
|
|
127
130
|
})(modeField) : {};
|
|
128
|
-
macroCondition(getGlobalConfig().
|
|
131
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
129
132
|
if (!test) {
|
|
130
133
|
throw new Error('field must be a GenericField or LegacyAttributeField');
|
|
131
134
|
}
|
|
@@ -257,6 +260,12 @@ class ManagedArray {
|
|
|
257
260
|
_SIGNAL.shouldReset = true;
|
|
258
261
|
}
|
|
259
262
|
return reflect;
|
|
263
|
+
},
|
|
264
|
+
has(target, prop) {
|
|
265
|
+
if (prop === 'identifier' || prop === 'owner' || prop === ARRAY_SIGNAL) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
return Reflect.has(target, prop);
|
|
260
269
|
}
|
|
261
270
|
});
|
|
262
271
|
return proxy;
|
|
@@ -337,7 +346,7 @@ class ManagedObject {
|
|
|
337
346
|
return Reflect.get(target, prop, receiver);
|
|
338
347
|
},
|
|
339
348
|
set(target, prop, value, receiver) {
|
|
340
|
-
macroCondition(getGlobalConfig().
|
|
349
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
341
350
|
if (!test) {
|
|
342
351
|
throw new Error(`Cannot set read-only property '${String(prop)}' on ManagedObject`);
|
|
343
352
|
}
|
|
@@ -360,6 +369,75 @@ class ManagedObject {
|
|
|
360
369
|
return proxy;
|
|
361
370
|
}
|
|
362
371
|
}
|
|
372
|
+
class ManyArrayManager {
|
|
373
|
+
constructor(record) {
|
|
374
|
+
this.record = record;
|
|
375
|
+
this.store = record[RecordStore];
|
|
376
|
+
this.identifier = record[Identifier];
|
|
377
|
+
}
|
|
378
|
+
_syncArray(array) {
|
|
379
|
+
const rawValue = this.store.cache.getRelationship(this.identifier, array.key);
|
|
380
|
+
if (rawValue.meta) {
|
|
381
|
+
array.meta = rawValue.meta;
|
|
382
|
+
}
|
|
383
|
+
if (rawValue.links) {
|
|
384
|
+
array.links = rawValue.links;
|
|
385
|
+
}
|
|
386
|
+
const currentState = array[SOURCE$1];
|
|
387
|
+
currentState.length = 0;
|
|
388
|
+
fastPush(currentState, rawValue.data);
|
|
389
|
+
}
|
|
390
|
+
reloadHasMany(key, options) {
|
|
391
|
+
const field = this.store.schema.fields(this.identifier).get(key);
|
|
392
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
393
|
+
if (!test) {
|
|
394
|
+
throw new Error(`Expected a hasMany field for ${key}`);
|
|
395
|
+
}
|
|
396
|
+
})(field?.kind === 'hasMany') : {};
|
|
397
|
+
const cacheOptions = options ? extractCacheOptions(options) : {
|
|
398
|
+
reload: true
|
|
399
|
+
};
|
|
400
|
+
cacheOptions.types = [field.type];
|
|
401
|
+
const rawValue = this.store.cache.getRelationship(this.identifier, key);
|
|
402
|
+
const req = {
|
|
403
|
+
url: getRelatedLink(rawValue),
|
|
404
|
+
op: 'findHasMany',
|
|
405
|
+
method: 'GET',
|
|
406
|
+
records: rawValue.data,
|
|
407
|
+
cacheOptions,
|
|
408
|
+
options: {
|
|
409
|
+
field,
|
|
410
|
+
identifier: this.identifier,
|
|
411
|
+
links: rawValue.links,
|
|
412
|
+
meta: rawValue.meta
|
|
413
|
+
},
|
|
414
|
+
[EnableHydration]: false
|
|
415
|
+
};
|
|
416
|
+
return this.store.request(req);
|
|
417
|
+
}
|
|
418
|
+
mutate(mutation) {
|
|
419
|
+
this.cache.mutate(mutation);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function getRelatedLink(resource) {
|
|
423
|
+
const related = resource.links?.related;
|
|
424
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
425
|
+
if (!test) {
|
|
426
|
+
throw new Error(`Expected a related link`);
|
|
427
|
+
}
|
|
428
|
+
})(related) : {};
|
|
429
|
+
return typeof related === 'object' ? related.href : related;
|
|
430
|
+
}
|
|
431
|
+
function extractCacheOptions(options) {
|
|
432
|
+
const cacheOptions = {};
|
|
433
|
+
if ('reload' in options) {
|
|
434
|
+
cacheOptions.reload = options.reload;
|
|
435
|
+
}
|
|
436
|
+
if ('backgroundReload' in options) {
|
|
437
|
+
cacheOptions.backgroundReload = options.backgroundReload;
|
|
438
|
+
}
|
|
439
|
+
return cacheOptions;
|
|
440
|
+
}
|
|
363
441
|
const ManagedArrayMap = getOrSetGlobal('ManagedArrayMap', new Map());
|
|
364
442
|
const ManagedObjectMap = getOrSetGlobal('ManagedObjectMap', new Map());
|
|
365
443
|
function computeLocal(record, field, prop) {
|
|
@@ -373,24 +451,25 @@ function computeLocal(record, field, prop) {
|
|
|
373
451
|
function peekManagedArray(record, field) {
|
|
374
452
|
const managedArrayMapForRecord = ManagedArrayMap.get(record);
|
|
375
453
|
if (managedArrayMapForRecord) {
|
|
376
|
-
return managedArrayMapForRecord.get(field);
|
|
454
|
+
return managedArrayMapForRecord.get(field.name);
|
|
377
455
|
}
|
|
378
456
|
}
|
|
379
457
|
function peekManagedObject(record, field) {
|
|
380
458
|
const managedObjectMapForRecord = ManagedObjectMap.get(record);
|
|
381
459
|
if (managedObjectMapForRecord) {
|
|
382
|
-
return managedObjectMapForRecord.get(field);
|
|
460
|
+
return managedObjectMapForRecord.get(field.name);
|
|
383
461
|
}
|
|
384
462
|
}
|
|
385
|
-
function computeField(schema, cache, record, identifier, field, prop) {
|
|
386
|
-
const rawValue = cache.getAttr(identifier, prop);
|
|
463
|
+
function computeField(schema, cache, record, identifier, field, prop, editable) {
|
|
464
|
+
const rawValue = editable ? cache.getAttr(identifier, prop) : cache.getRemoteAttr(identifier, prop);
|
|
387
465
|
if (!field.type) {
|
|
388
466
|
return rawValue;
|
|
389
467
|
}
|
|
390
468
|
const transform = schema.transformation(field);
|
|
391
469
|
return transform.hydrate(rawValue, field.options ?? null, record);
|
|
392
470
|
}
|
|
393
|
-
function computeArray(store, schema, cache, record, identifier, field, path,
|
|
471
|
+
function computeArray(store, schema, cache, record, identifier, field, path, editable, legacy) {
|
|
472
|
+
const isSchemaArray = field.kind === 'schema-array';
|
|
394
473
|
// the thing we hand out needs to know its owner and path in a private manner
|
|
395
474
|
// its "address" is the parent identifier (identifier) + field name (field.name)
|
|
396
475
|
// in the nested object case field name here is the full dot path from root resource to this value
|
|
@@ -400,20 +479,20 @@ function computeArray(store, schema, cache, record, identifier, field, path, isS
|
|
|
400
479
|
const managedArrayMapForRecord = ManagedArrayMap.get(record);
|
|
401
480
|
let managedArray;
|
|
402
481
|
if (managedArrayMapForRecord) {
|
|
403
|
-
managedArray = managedArrayMapForRecord.get(field);
|
|
482
|
+
managedArray = managedArrayMapForRecord.get(field.name);
|
|
404
483
|
}
|
|
405
484
|
if (managedArray) {
|
|
406
485
|
return managedArray;
|
|
407
486
|
} else {
|
|
408
|
-
const rawValue = cache.getAttr(identifier, path);
|
|
487
|
+
const rawValue = editable ? cache.getAttr(identifier, path) : cache.getRemoteAttr(identifier, path);
|
|
409
488
|
if (!rawValue) {
|
|
410
489
|
return null;
|
|
411
490
|
}
|
|
412
491
|
managedArray = new ManagedArray(store, schema, cache, field, rawValue, identifier, path, record, isSchemaArray, editable, legacy);
|
|
413
492
|
if (!managedArrayMapForRecord) {
|
|
414
|
-
ManagedArrayMap.set(record, new Map([[field, managedArray]]));
|
|
493
|
+
ManagedArrayMap.set(record, new Map([[field.name, managedArray]]));
|
|
415
494
|
} else {
|
|
416
|
-
managedArrayMapForRecord.set(field, managedArray);
|
|
495
|
+
managedArrayMapForRecord.set(field.name, managedArray);
|
|
417
496
|
}
|
|
418
497
|
}
|
|
419
498
|
return managedArray;
|
|
@@ -422,12 +501,12 @@ function computeObject(schema, cache, record, identifier, field, path, editable,
|
|
|
422
501
|
const managedObjectMapForRecord = ManagedObjectMap.get(record);
|
|
423
502
|
let managedObject;
|
|
424
503
|
if (managedObjectMapForRecord) {
|
|
425
|
-
managedObject = managedObjectMapForRecord.get(field);
|
|
504
|
+
managedObject = managedObjectMapForRecord.get(field.name);
|
|
426
505
|
}
|
|
427
506
|
if (managedObject) {
|
|
428
507
|
return managedObject;
|
|
429
508
|
} else {
|
|
430
|
-
let rawValue = cache.getAttr(identifier, path);
|
|
509
|
+
let rawValue = editable ? cache.getAttr(identifier, path) : cache.getRemoteAttr(identifier, path);
|
|
431
510
|
if (!rawValue) {
|
|
432
511
|
return null;
|
|
433
512
|
}
|
|
@@ -437,9 +516,9 @@ function computeObject(schema, cache, record, identifier, field, path, editable,
|
|
|
437
516
|
}
|
|
438
517
|
managedObject = new ManagedObject(schema, cache, field, rawValue, identifier, path, record, editable, legacy);
|
|
439
518
|
if (!managedObjectMapForRecord) {
|
|
440
|
-
ManagedObjectMap.set(record, new Map([[field, managedObject]]));
|
|
519
|
+
ManagedObjectMap.set(record, new Map([[field.name, managedObject]]));
|
|
441
520
|
} else {
|
|
442
|
-
managedObjectMapForRecord.set(field, managedObject);
|
|
521
|
+
managedObjectMapForRecord.set(field.name, managedObject);
|
|
443
522
|
}
|
|
444
523
|
}
|
|
445
524
|
return managedObject;
|
|
@@ -448,12 +527,12 @@ function computeSchemaObject(store, cache, record, identifier, field, path, lega
|
|
|
448
527
|
const schemaObjectMapForRecord = ManagedObjectMap.get(record);
|
|
449
528
|
let schemaObject;
|
|
450
529
|
if (schemaObjectMapForRecord) {
|
|
451
|
-
schemaObject = schemaObjectMapForRecord.get(field);
|
|
530
|
+
schemaObject = schemaObjectMapForRecord.get(field.name);
|
|
452
531
|
}
|
|
453
532
|
if (schemaObject) {
|
|
454
533
|
return schemaObject;
|
|
455
534
|
} else {
|
|
456
|
-
const rawValue = cache.getAttr(identifier, path);
|
|
535
|
+
const rawValue = editable ? cache.getAttr(identifier, path) : cache.getRemoteAttr(identifier, path);
|
|
457
536
|
if (!rawValue) {
|
|
458
537
|
return null;
|
|
459
538
|
}
|
|
@@ -464,14 +543,14 @@ function computeSchemaObject(store, cache, record, identifier, field, path, lega
|
|
|
464
543
|
}, true, field.type, embeddedPath);
|
|
465
544
|
}
|
|
466
545
|
if (!schemaObjectMapForRecord) {
|
|
467
|
-
ManagedObjectMap.set(record, new Map([[field, schemaObject]]));
|
|
546
|
+
ManagedObjectMap.set(record, new Map([[field.name, schemaObject]]));
|
|
468
547
|
} else {
|
|
469
|
-
schemaObjectMapForRecord.set(field, schemaObject);
|
|
548
|
+
schemaObjectMapForRecord.set(field.name, schemaObject);
|
|
470
549
|
}
|
|
471
550
|
return schemaObject;
|
|
472
551
|
}
|
|
473
|
-
function computeAttribute(cache, identifier, prop) {
|
|
474
|
-
return cache.getAttr(identifier, prop);
|
|
552
|
+
function computeAttribute(cache, identifier, prop, editable) {
|
|
553
|
+
return editable ? cache.getAttr(identifier, prop) : cache.getRemoteAttr(identifier, prop);
|
|
475
554
|
}
|
|
476
555
|
function computeDerivation(schema, record, identifier, field, prop) {
|
|
477
556
|
return schema.derivation(field)(record, field.options ?? null, prop);
|
|
@@ -480,8 +559,8 @@ function computeDerivation(schema, record, identifier, field, prop) {
|
|
|
480
559
|
// TODO probably this should just be a Document
|
|
481
560
|
// but its separate until we work out the lid situation
|
|
482
561
|
class ResourceRelationship {
|
|
483
|
-
constructor(store, cache, parent, identifier, field, name) {
|
|
484
|
-
const rawValue = cache.getRelationship(identifier, name);
|
|
562
|
+
constructor(store, cache, parent, identifier, field, name, editable) {
|
|
563
|
+
const rawValue = editable ? cache.getRelationship(identifier, name) : cache.getRemoteRelationship(identifier, name);
|
|
485
564
|
|
|
486
565
|
// TODO setup true lids for relationship documents
|
|
487
566
|
// @ts-expect-error we need to give relationship documents a lid
|
|
@@ -489,7 +568,7 @@ class ResourceRelationship {
|
|
|
489
568
|
this.lid = rawValue.lid ?? rawValue.links?.self ?? `relationship:${identifier.lid}.${name}`;
|
|
490
569
|
this.data = rawValue.data ? store.peekRecord(rawValue.data) : null;
|
|
491
570
|
this.name = name;
|
|
492
|
-
if (macroCondition(getGlobalConfig().
|
|
571
|
+
if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
493
572
|
this.links = Object.freeze(Object.assign({}, rawValue.links));
|
|
494
573
|
this.meta = Object.freeze(Object.assign({}, rawValue.meta));
|
|
495
574
|
} else {
|
|
@@ -523,11 +602,56 @@ function getHref(link) {
|
|
|
523
602
|
}
|
|
524
603
|
return link.href;
|
|
525
604
|
}
|
|
526
|
-
function computeResource(store, cache, parent, identifier, field, prop) {
|
|
605
|
+
function computeResource(store, cache, parent, identifier, field, prop, editable) {
|
|
527
606
|
if (field.kind !== 'resource') {
|
|
528
607
|
throw new Error(`The schema for ${identifier.type}.${String(prop)} is not a resource relationship`);
|
|
529
608
|
}
|
|
530
|
-
return new ResourceRelationship(store, cache, parent, identifier, field, prop);
|
|
609
|
+
return new ResourceRelationship(store, cache, parent, identifier, field, prop, editable);
|
|
610
|
+
}
|
|
611
|
+
function computeHasMany(store, schema, cache, record, identifier, field, path, editable, legacy) {
|
|
612
|
+
// the thing we hand out needs to know its owner and path in a private manner
|
|
613
|
+
// its "address" is the parent identifier (identifier) + field name (field.name)
|
|
614
|
+
// in the nested object case field name here is the full dot path from root resource to this value
|
|
615
|
+
// its "key" is the field on the parent record
|
|
616
|
+
// its "owner" is the parent record
|
|
617
|
+
|
|
618
|
+
const managedArrayMapForRecord = ManagedArrayMap.get(record);
|
|
619
|
+
let managedArray;
|
|
620
|
+
if (managedArrayMapForRecord) {
|
|
621
|
+
managedArray = managedArrayMapForRecord.get(field.name);
|
|
622
|
+
}
|
|
623
|
+
if (managedArray) {
|
|
624
|
+
return managedArray;
|
|
625
|
+
} else {
|
|
626
|
+
const rawValue = cache.getRelationship(identifier, field.name);
|
|
627
|
+
if (!rawValue) {
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
managedArray = new RelatedCollection({
|
|
631
|
+
store,
|
|
632
|
+
type: field.type,
|
|
633
|
+
identifier,
|
|
634
|
+
cache,
|
|
635
|
+
identifiers: rawValue.data,
|
|
636
|
+
key: field.name,
|
|
637
|
+
meta: rawValue.meta || null,
|
|
638
|
+
links: rawValue.links || null,
|
|
639
|
+
isPolymorphic: field.options.polymorphic ?? false,
|
|
640
|
+
isAsync: field.options.async ?? false,
|
|
641
|
+
// TODO: Grab the proper value
|
|
642
|
+
_inverseIsAsync: false,
|
|
643
|
+
// @ts-expect-error Typescript doesn't have a way for us to thread the generic backwards so it infers unknown instead of T
|
|
644
|
+
manager: new ManyArrayManager(record),
|
|
645
|
+
isLoaded: true,
|
|
646
|
+
allowMutation: editable
|
|
647
|
+
});
|
|
648
|
+
if (!managedArrayMapForRecord) {
|
|
649
|
+
ManagedArrayMap.set(record, new Map([[field.name, managedArray]]));
|
|
650
|
+
} else {
|
|
651
|
+
managedArrayMapForRecord.set(field.name, managedArray);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return managedArray;
|
|
531
655
|
}
|
|
532
656
|
const HAS_MODEL_PACKAGE = dependencySatisfies('@ember-data-mirror/model', '*');
|
|
533
657
|
const getLegacySupport = macroCondition(dependencySatisfies('@ember-data-mirror/model', '*')) ? importSync('@ember-data-mirror/model/-private').lookupLegacySupport : null;
|
|
@@ -570,6 +694,9 @@ class SchemaRecord {
|
|
|
570
694
|
return Array.from(fields.keys());
|
|
571
695
|
},
|
|
572
696
|
has(target, prop) {
|
|
697
|
+
if (prop === Destroy || prop === Checkout) {
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
573
700
|
return fields.has(prop);
|
|
574
701
|
},
|
|
575
702
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -652,7 +779,7 @@ class SchemaRecord {
|
|
|
652
779
|
throw new Error(`No field named ${String(prop)} on ${type}`);
|
|
653
780
|
}
|
|
654
781
|
const field = maybeField.kind === 'alias' ? maybeField.options : maybeField;
|
|
655
|
-
macroCondition(getGlobalConfig().
|
|
782
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
656
783
|
if (!test) {
|
|
657
784
|
throw new Error(`Alias fields cannot alias '@id' '@local' '@hash' or 'derived' fields`);
|
|
658
785
|
}
|
|
@@ -677,39 +804,37 @@ class SchemaRecord {
|
|
|
677
804
|
return lastValue;
|
|
678
805
|
}
|
|
679
806
|
case 'field':
|
|
680
|
-
macroCondition(getGlobalConfig().
|
|
807
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
681
808
|
if (!test) {
|
|
682
809
|
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
683
810
|
}
|
|
684
811
|
})(!target[Legacy]) : {};
|
|
685
812
|
entangleSignal(signals, receiver, field.name);
|
|
686
|
-
return computeField(schema, cache, target, identifier, field, propArray);
|
|
813
|
+
return computeField(schema, cache, target, identifier, field, propArray, IS_EDITABLE);
|
|
687
814
|
case 'attribute':
|
|
688
815
|
entangleSignal(signals, receiver, field.name);
|
|
689
|
-
return computeAttribute(cache, identifier, prop);
|
|
816
|
+
return computeAttribute(cache, identifier, prop, IS_EDITABLE);
|
|
690
817
|
case 'resource':
|
|
691
|
-
macroCondition(getGlobalConfig().
|
|
818
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
692
819
|
if (!test) {
|
|
693
820
|
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
694
821
|
}
|
|
695
822
|
})(!target[Legacy]) : {};
|
|
696
823
|
entangleSignal(signals, receiver, field.name);
|
|
697
|
-
return computeResource(store, cache, target, identifier, field, prop);
|
|
824
|
+
return computeResource(store, cache, target, identifier, field, prop, IS_EDITABLE);
|
|
698
825
|
case 'derived':
|
|
699
826
|
return computeDerivation(schema, receiver, identifier, field, prop);
|
|
700
827
|
case 'schema-array':
|
|
701
|
-
entangleSignal(signals, receiver, field.name);
|
|
702
|
-
return computeArray(store, schema, cache, target, identifier, field, propArray, true, Mode[Editable], Mode[Legacy]);
|
|
703
828
|
case 'array':
|
|
704
|
-
macroCondition(getGlobalConfig().
|
|
829
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
705
830
|
if (!test) {
|
|
706
831
|
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
707
832
|
}
|
|
708
833
|
})(!target[Legacy]) : {};
|
|
709
834
|
entangleSignal(signals, receiver, field.name);
|
|
710
|
-
return computeArray(store, schema, cache, target, identifier, field, propArray,
|
|
835
|
+
return computeArray(store, schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
|
|
711
836
|
case 'object':
|
|
712
|
-
macroCondition(getGlobalConfig().
|
|
837
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
713
838
|
if (!test) {
|
|
714
839
|
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
715
840
|
}
|
|
@@ -717,7 +842,7 @@ class SchemaRecord {
|
|
|
717
842
|
entangleSignal(signals, receiver, field.name);
|
|
718
843
|
return computeObject(schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
|
|
719
844
|
case 'schema-object':
|
|
720
|
-
macroCondition(getGlobalConfig().
|
|
845
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
721
846
|
if (!test) {
|
|
722
847
|
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
723
848
|
}
|
|
@@ -726,19 +851,26 @@ class SchemaRecord {
|
|
|
726
851
|
// run transform, then use that value as the object to manage
|
|
727
852
|
return computeSchemaObject(store, cache, target, identifier, field, propArray, Mode[Legacy], Mode[Editable]);
|
|
728
853
|
case 'belongsTo':
|
|
854
|
+
if (field.options.linksMode) {
|
|
855
|
+
entangleSignal(signals, receiver, field.name);
|
|
856
|
+
const rawValue = IS_EDITABLE ? cache.getRelationship(identifier, field.name) : cache.getRemoteRelationship(identifier, field.name);
|
|
857
|
+
|
|
858
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
859
|
+
return rawValue.data ? store.peekRecord(rawValue.data) : null;
|
|
860
|
+
}
|
|
729
861
|
if (!HAS_MODEL_PACKAGE) {
|
|
730
|
-
macroCondition(getGlobalConfig().
|
|
862
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
731
863
|
{
|
|
732
864
|
throw new Error(`Cannot use belongsTo fields in your schema unless @ember-data-mirror/model is installed to provide legacy model support. ${field.name} should likely be migrated to be a resource field.`);
|
|
733
865
|
}
|
|
734
866
|
})() : {};
|
|
735
867
|
}
|
|
736
|
-
macroCondition(getGlobalConfig().
|
|
868
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
737
869
|
if (!test) {
|
|
738
870
|
throw new Error(`Expected to have a getLegacySupport function`);
|
|
739
871
|
}
|
|
740
872
|
})(getLegacySupport) : {};
|
|
741
|
-
macroCondition(getGlobalConfig().
|
|
873
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
742
874
|
if (!test) {
|
|
743
875
|
throw new Error(`Can only use belongsTo fields when the resource is in legacy mode`);
|
|
744
876
|
}
|
|
@@ -746,19 +878,23 @@ class SchemaRecord {
|
|
|
746
878
|
entangleSignal(signals, receiver, field.name);
|
|
747
879
|
return getLegacySupport(receiver).getBelongsTo(field.name);
|
|
748
880
|
case 'hasMany':
|
|
881
|
+
if (field.options.linksMode) {
|
|
882
|
+
entangleSignal(signals, receiver, field.name);
|
|
883
|
+
return computeHasMany(store, schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
|
|
884
|
+
}
|
|
749
885
|
if (!HAS_MODEL_PACKAGE) {
|
|
750
|
-
macroCondition(getGlobalConfig().
|
|
886
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
751
887
|
{
|
|
752
888
|
throw new Error(`Cannot use hasMany fields in your schema unless @ember-data-mirror/model is installed to provide legacy model support. ${field.name} should likely be migrated to be a collection field.`);
|
|
753
889
|
}
|
|
754
890
|
})() : {};
|
|
755
891
|
}
|
|
756
|
-
macroCondition(getGlobalConfig().
|
|
892
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
757
893
|
if (!test) {
|
|
758
894
|
throw new Error(`Expected to have a getLegacySupport function`);
|
|
759
895
|
}
|
|
760
896
|
})(getLegacySupport) : {};
|
|
761
|
-
macroCondition(getGlobalConfig().
|
|
897
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
762
898
|
if (!test) {
|
|
763
899
|
throw new Error(`Can only use hasMany fields when the resource is in legacy mode`);
|
|
764
900
|
}
|
|
@@ -780,7 +916,7 @@ class SchemaRecord {
|
|
|
780
916
|
throw new Error(`There is no field named ${String(prop)} on ${type}`);
|
|
781
917
|
}
|
|
782
918
|
const field = maybeField.kind === 'alias' ? maybeField.options : maybeField;
|
|
783
|
-
macroCondition(getGlobalConfig().
|
|
919
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
784
920
|
if (!test) {
|
|
785
921
|
throw new Error(`Alias fields cannot alias '@id' '@local' '@hash' or 'derived' fields`);
|
|
786
922
|
}
|
|
@@ -794,14 +930,14 @@ class SchemaRecord {
|
|
|
794
930
|
switch (field.kind) {
|
|
795
931
|
case '@id':
|
|
796
932
|
{
|
|
797
|
-
macroCondition(getGlobalConfig().
|
|
933
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
798
934
|
if (!test) {
|
|
799
935
|
throw new Error(`Expected to receive a string id`);
|
|
800
936
|
}
|
|
801
937
|
})(typeof value === 'string' && value.length) : {};
|
|
802
938
|
const normalizedId = String(value);
|
|
803
939
|
const didChange = normalizedId !== identifier.id;
|
|
804
|
-
macroCondition(getGlobalConfig().
|
|
940
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
805
941
|
if (!test) {
|
|
806
942
|
throw new Error(`Cannot set ${identifier.type} record's id to ${normalizedId}, because id is already ${identifier.id}`);
|
|
807
943
|
}
|
|
@@ -843,6 +979,11 @@ class SchemaRecord {
|
|
|
843
979
|
cache.setAttr(identifier, propArray, value?.slice());
|
|
844
980
|
const peeked = peekManagedArray(self, field);
|
|
845
981
|
if (peeked) {
|
|
982
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
983
|
+
if (!test) {
|
|
984
|
+
throw new Error(`Expected the peekManagedArray for ${field.kind} to return a ManagedArray`);
|
|
985
|
+
}
|
|
986
|
+
})(ARRAY_SIGNAL in peeked) : {};
|
|
846
987
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
847
988
|
arrSignal.shouldReset = true;
|
|
848
989
|
}
|
|
@@ -856,6 +997,11 @@ class SchemaRecord {
|
|
|
856
997
|
cache.setAttr(identifier, propArray, rawValue);
|
|
857
998
|
const peeked = peekManagedArray(self, field);
|
|
858
999
|
if (peeked) {
|
|
1000
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1001
|
+
if (!test) {
|
|
1002
|
+
throw new Error(`Expected the peekManagedArray for ${field.kind} to return a ManagedArray`);
|
|
1003
|
+
}
|
|
1004
|
+
})(ARRAY_SIGNAL in peeked) : {};
|
|
859
1005
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
860
1006
|
arrSignal.shouldReset = true;
|
|
861
1007
|
}
|
|
@@ -870,6 +1016,11 @@ class SchemaRecord {
|
|
|
870
1016
|
cache.setAttr(identifier, propArray, arrayValue);
|
|
871
1017
|
const peeked = peekManagedArray(self, field);
|
|
872
1018
|
if (peeked) {
|
|
1019
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1020
|
+
if (!test) {
|
|
1021
|
+
throw new Error(`Expected the peekManagedArray for ${field.kind} to return a ManagedArray`);
|
|
1022
|
+
}
|
|
1023
|
+
})(ARRAY_SIGNAL in peeked) : {};
|
|
873
1024
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
874
1025
|
arrSignal.shouldReset = true;
|
|
875
1026
|
}
|
|
@@ -913,7 +1064,7 @@ class SchemaRecord {
|
|
|
913
1064
|
{
|
|
914
1065
|
let newValue = value;
|
|
915
1066
|
if (value !== null) {
|
|
916
|
-
macroCondition(getGlobalConfig().
|
|
1067
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
917
1068
|
if (!test) {
|
|
918
1069
|
throw new Error(`Expected value to be an object`);
|
|
919
1070
|
}
|
|
@@ -946,18 +1097,18 @@ class SchemaRecord {
|
|
|
946
1097
|
}
|
|
947
1098
|
case 'belongsTo':
|
|
948
1099
|
if (!HAS_MODEL_PACKAGE) {
|
|
949
|
-
macroCondition(getGlobalConfig().
|
|
1100
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
950
1101
|
{
|
|
951
1102
|
throw new Error(`Cannot use belongsTo fields in your schema unless @ember-data-mirror/model is installed to provide legacy model support. ${field.name} should likely be migrated to be a resource field.`);
|
|
952
1103
|
}
|
|
953
1104
|
})() : {};
|
|
954
1105
|
}
|
|
955
|
-
macroCondition(getGlobalConfig().
|
|
1106
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
956
1107
|
if (!test) {
|
|
957
1108
|
throw new Error(`Expected to have a getLegacySupport function`);
|
|
958
1109
|
}
|
|
959
1110
|
})(getLegacySupport) : {};
|
|
960
|
-
macroCondition(getGlobalConfig().
|
|
1111
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
961
1112
|
if (!test) {
|
|
962
1113
|
throw new Error(`Can only use belongsTo fields when the resource is in legacy mode`);
|
|
963
1114
|
}
|
|
@@ -968,23 +1119,23 @@ class SchemaRecord {
|
|
|
968
1119
|
return true;
|
|
969
1120
|
case 'hasMany':
|
|
970
1121
|
if (!HAS_MODEL_PACKAGE) {
|
|
971
|
-
macroCondition(getGlobalConfig().
|
|
1122
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
972
1123
|
{
|
|
973
1124
|
throw new Error(`Cannot use hasMany fields in your schema unless @ember-data-mirror/model is installed to provide legacy model support. ${field.name} should likely be migrated to be a collection field.`);
|
|
974
1125
|
}
|
|
975
1126
|
})() : {};
|
|
976
1127
|
}
|
|
977
|
-
macroCondition(getGlobalConfig().
|
|
1128
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
978
1129
|
if (!test) {
|
|
979
1130
|
throw new Error(`Expected to have a getLegacySupport function`);
|
|
980
1131
|
}
|
|
981
1132
|
})(getLegacySupport) : {};
|
|
982
|
-
macroCondition(getGlobalConfig().
|
|
1133
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
983
1134
|
if (!test) {
|
|
984
1135
|
throw new Error(`Can only use hasMany fields when the resource is in legacy mode`);
|
|
985
1136
|
}
|
|
986
1137
|
})(Mode[Legacy]) : {};
|
|
987
|
-
macroCondition(getGlobalConfig().
|
|
1138
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
988
1139
|
if (!test) {
|
|
989
1140
|
throw new Error(`You must pass an array of records to set a hasMany relationship`);
|
|
990
1141
|
}
|
|
@@ -1047,6 +1198,11 @@ class SchemaRecord {
|
|
|
1047
1198
|
if (field?.kind === 'array' || field?.kind === 'schema-array') {
|
|
1048
1199
|
const peeked = peekManagedArray(self, field);
|
|
1049
1200
|
if (peeked) {
|
|
1201
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1202
|
+
if (!test) {
|
|
1203
|
+
throw new Error(`Expected the peekManagedArray for ${field.kind} to return a ManagedArray`);
|
|
1204
|
+
}
|
|
1205
|
+
})(ARRAY_SIGNAL in peeked) : {};
|
|
1050
1206
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
1051
1207
|
arrSignal.shouldReset = true;
|
|
1052
1208
|
addToTransaction(arrSignal);
|
|
@@ -1069,7 +1225,7 @@ class SchemaRecord {
|
|
|
1069
1225
|
if (isEmbedded) return; // base paths never apply to embedded records
|
|
1070
1226
|
|
|
1071
1227
|
const field = fields.get(key);
|
|
1072
|
-
macroCondition(getGlobalConfig().
|
|
1228
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1073
1229
|
if (!test) {
|
|
1074
1230
|
throw new Error(`Expected relationshp ${key} to be the name of a field`);
|
|
1075
1231
|
}
|
|
@@ -1083,12 +1239,22 @@ class SchemaRecord {
|
|
|
1083
1239
|
}
|
|
1084
1240
|
// FIXME
|
|
1085
1241
|
} else if (field.kind === 'resource') ;else if (field.kind === 'hasMany') {
|
|
1086
|
-
|
|
1242
|
+
if (field.options.linksMode) {
|
|
1243
|
+
const peeked = peekManagedArray(self, field);
|
|
1244
|
+
if (peeked) {
|
|
1245
|
+
// const arrSignal = peeked[ARRAY_SIGNAL];
|
|
1246
|
+
// arrSignal.shouldReset = true;
|
|
1247
|
+
// addToTransaction(arrSignal);
|
|
1248
|
+
peeked.notify();
|
|
1249
|
+
}
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1087
1253
|
if (!test) {
|
|
1088
1254
|
throw new Error(`Expected to have a getLegacySupport function`);
|
|
1089
1255
|
}
|
|
1090
1256
|
})(getLegacySupport) : {};
|
|
1091
|
-
macroCondition(getGlobalConfig().
|
|
1257
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1092
1258
|
if (!test) {
|
|
1093
1259
|
throw new Error(`Can only use hasMany fields when the resource is in legacy mode`);
|
|
1094
1260
|
}
|
|
@@ -1103,12 +1269,12 @@ class SchemaRecord {
|
|
|
1103
1269
|
}
|
|
1104
1270
|
if (manyArray) {
|
|
1105
1271
|
manyArray.notify();
|
|
1106
|
-
macroCondition(getGlobalConfig().
|
|
1272
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1107
1273
|
if (!test) {
|
|
1108
1274
|
throw new Error(`Expected options to exist on relationship meta`);
|
|
1109
1275
|
}
|
|
1110
1276
|
})(field.options) : {};
|
|
1111
|
-
macroCondition(getGlobalConfig().
|
|
1277
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1112
1278
|
if (!test) {
|
|
1113
1279
|
throw new Error(`Expected async to exist on relationship meta options`);
|
|
1114
1280
|
}
|
|
@@ -1138,6 +1304,10 @@ class SchemaRecord {
|
|
|
1138
1304
|
this[RecordStore].notifications.unsubscribe(this.___notifications);
|
|
1139
1305
|
}
|
|
1140
1306
|
[Checkout]() {
|
|
1307
|
+
// IF we are already the editable record, throw an error
|
|
1308
|
+
if (this[Editable]) {
|
|
1309
|
+
throw new Error(`Cannot checkout an already editable record`);
|
|
1310
|
+
}
|
|
1141
1311
|
const editable = Editables.get(this);
|
|
1142
1312
|
if (editable) {
|
|
1143
1313
|
return Promise.resolve(editable);
|
|
@@ -1156,4 +1326,297 @@ class SchemaRecord {
|
|
|
1156
1326
|
return Promise.resolve(editableRecord);
|
|
1157
1327
|
}
|
|
1158
1328
|
}
|
|
1159
|
-
|
|
1329
|
+
function instantiateRecord(store, identifier, createArgs) {
|
|
1330
|
+
const schema = store.schema;
|
|
1331
|
+
const isLegacy = schema.resource(identifier)?.legacy ?? false;
|
|
1332
|
+
const isEditable = isLegacy || store.cache.isNew(identifier);
|
|
1333
|
+
const record = new SchemaRecord(store, identifier, {
|
|
1334
|
+
[Editable]: isEditable,
|
|
1335
|
+
[Legacy]: isLegacy
|
|
1336
|
+
});
|
|
1337
|
+
if (createArgs) {
|
|
1338
|
+
Object.assign(record, createArgs);
|
|
1339
|
+
}
|
|
1340
|
+
return record;
|
|
1341
|
+
}
|
|
1342
|
+
function assertSchemaRecord(record) {
|
|
1343
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1344
|
+
if (!test) {
|
|
1345
|
+
throw new Error('Expected a SchemaRecord');
|
|
1346
|
+
}
|
|
1347
|
+
})(record && typeof record === 'object' && Destroy in record) : {};
|
|
1348
|
+
}
|
|
1349
|
+
function teardownRecord(record) {
|
|
1350
|
+
assertSchemaRecord(record);
|
|
1351
|
+
record[Destroy]();
|
|
1352
|
+
}
|
|
1353
|
+
const Support = getOrSetGlobal('Support', new WeakMap());
|
|
1354
|
+
const SchemaRecordFields = [{
|
|
1355
|
+
type: '@constructor',
|
|
1356
|
+
name: 'constructor',
|
|
1357
|
+
kind: 'derived'
|
|
1358
|
+
}, {
|
|
1359
|
+
type: '@identity',
|
|
1360
|
+
name: '$type',
|
|
1361
|
+
kind: 'derived',
|
|
1362
|
+
options: {
|
|
1363
|
+
key: 'type'
|
|
1364
|
+
}
|
|
1365
|
+
}];
|
|
1366
|
+
function _constructor(record) {
|
|
1367
|
+
let state = Support.get(record);
|
|
1368
|
+
if (!state) {
|
|
1369
|
+
state = {};
|
|
1370
|
+
Support.set(record, state);
|
|
1371
|
+
}
|
|
1372
|
+
return state._constructor = state._constructor || {
|
|
1373
|
+
name: `SchemaRecord<${recordIdentifierFor$1(record).type}>`,
|
|
1374
|
+
get modelName() {
|
|
1375
|
+
throw new Error('Cannot access record.constructor.modelName on non-Legacy Schema Records.');
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
_constructor[Type] = '@constructor';
|
|
1380
|
+
function withDefaults(schema) {
|
|
1381
|
+
schema.identity = schema.identity || {
|
|
1382
|
+
name: 'id',
|
|
1383
|
+
kind: '@id'
|
|
1384
|
+
};
|
|
1385
|
+
schema.fields.push(...SchemaRecordFields);
|
|
1386
|
+
return schema;
|
|
1387
|
+
}
|
|
1388
|
+
function fromIdentity(record, options, key) {
|
|
1389
|
+
const identifier = record[Identifier];
|
|
1390
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1391
|
+
if (!test) {
|
|
1392
|
+
throw new Error(`Cannot compute @identity for a record without an identifier`);
|
|
1393
|
+
}
|
|
1394
|
+
})(identifier) : {};
|
|
1395
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1396
|
+
if (!test) {
|
|
1397
|
+
throw new Error(`Expected to receive a key to compute @identity, but got ${String(options)}`);
|
|
1398
|
+
}
|
|
1399
|
+
})(options?.key && ['lid', 'id', 'type', '^'].includes(options.key)) : {};
|
|
1400
|
+
return options.key === '^' ? identifier : identifier[options.key];
|
|
1401
|
+
}
|
|
1402
|
+
fromIdentity[Type] = '@identity';
|
|
1403
|
+
function registerDerivations(schema) {
|
|
1404
|
+
schema.registerDerivation(fromIdentity);
|
|
1405
|
+
schema.registerDerivation(_constructor);
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Wraps a derivation in a new function with Derivation signature but that looks
|
|
1409
|
+
* up the value in the cache before recomputing.
|
|
1410
|
+
*
|
|
1411
|
+
* @param record
|
|
1412
|
+
* @param options
|
|
1413
|
+
* @param prop
|
|
1414
|
+
*/
|
|
1415
|
+
function makeCachedDerivation(derivation) {
|
|
1416
|
+
const memoizedDerivation = (record, options, prop) => {
|
|
1417
|
+
const signals = record[Signals];
|
|
1418
|
+
let signal = signals.get(prop);
|
|
1419
|
+
if (!signal) {
|
|
1420
|
+
signal = createCache(() => {
|
|
1421
|
+
return derivation(record, options, prop);
|
|
1422
|
+
}); // a total lie, for convenience of reusing the storage
|
|
1423
|
+
signals.set(prop, signal);
|
|
1424
|
+
}
|
|
1425
|
+
return getValue(signal);
|
|
1426
|
+
};
|
|
1427
|
+
memoizedDerivation[Type] = derivation[Type];
|
|
1428
|
+
return memoizedDerivation;
|
|
1429
|
+
}
|
|
1430
|
+
class SchemaService {
|
|
1431
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1432
|
+
|
|
1433
|
+
constructor() {
|
|
1434
|
+
this._schemas = new Map();
|
|
1435
|
+
this._transforms = new Map();
|
|
1436
|
+
this._hashFns = new Map();
|
|
1437
|
+
this._derivations = new Map();
|
|
1438
|
+
}
|
|
1439
|
+
hasTrait(type) {
|
|
1440
|
+
return this._traits.has(type);
|
|
1441
|
+
}
|
|
1442
|
+
resourceHasTrait(resource, trait) {
|
|
1443
|
+
return this._schemas.get(resource.type).traits.has(trait);
|
|
1444
|
+
}
|
|
1445
|
+
transformation(field) {
|
|
1446
|
+
const kind = 'kind' in field ? field.kind : '<unknown kind>';
|
|
1447
|
+
const name = 'name' in field ? field.name : '<unknown name>';
|
|
1448
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1449
|
+
if (!test) {
|
|
1450
|
+
throw new Error(`'${kind}' fields cannot be transformed. Only fields of kind 'field' 'object' or 'array' can specify a transformation. Attempted to find '${field.type ?? '<unknown type>'}' on field '${name}'.`);
|
|
1451
|
+
}
|
|
1452
|
+
})(!('kind' in field) || ['field', 'object', 'array'].includes(kind)) : {};
|
|
1453
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1454
|
+
if (!test) {
|
|
1455
|
+
throw new Error(`Expected the '${kind}' field '${name}' to specify a transformation via 'field.type', but none was present`);
|
|
1456
|
+
}
|
|
1457
|
+
})(field.type) : {};
|
|
1458
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1459
|
+
if (!test) {
|
|
1460
|
+
throw new Error(`No transformation registered with name '${field.type}' for '${kind}' field '${name}'`);
|
|
1461
|
+
}
|
|
1462
|
+
})(this._transforms.has(field.type)) : {};
|
|
1463
|
+
return this._transforms.get(field.type);
|
|
1464
|
+
}
|
|
1465
|
+
derivation(field) {
|
|
1466
|
+
const kind = 'kind' in field ? field.kind : '<unknown kind>';
|
|
1467
|
+
const name = 'name' in field ? field.name : '<unknown name>';
|
|
1468
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1469
|
+
if (!test) {
|
|
1470
|
+
throw new Error(`The '${kind}' field '${name}' is not derived and so cannot be used to lookup a derivation`);
|
|
1471
|
+
}
|
|
1472
|
+
})(!('kind' in field) || kind === 'derived') : {};
|
|
1473
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1474
|
+
if (!test) {
|
|
1475
|
+
throw new Error(`Expected the '${kind}' field '${name}' to specify a derivation via 'field.type', but no value was present`);
|
|
1476
|
+
}
|
|
1477
|
+
})(field.type) : {};
|
|
1478
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1479
|
+
if (!test) {
|
|
1480
|
+
throw new Error(`No '${field.type}' derivation registered for use by the '${kind}' field '${name}'`);
|
|
1481
|
+
}
|
|
1482
|
+
})(this._derivations.has(field.type)) : {};
|
|
1483
|
+
return this._derivations.get(field.type);
|
|
1484
|
+
}
|
|
1485
|
+
hashFn(field) {
|
|
1486
|
+
const kind = 'kind' in field ? field.kind : '<unknown kind>';
|
|
1487
|
+
const name = 'name' in field ? field.name : '<unknown name>';
|
|
1488
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1489
|
+
if (!test) {
|
|
1490
|
+
throw new Error(`The '${kind}' field '${name}' is not a HashField and so cannot be used to lookup a hash function`);
|
|
1491
|
+
}
|
|
1492
|
+
})(!('kind' in field) || kind === '@hash') : {};
|
|
1493
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1494
|
+
if (!test) {
|
|
1495
|
+
throw new Error(`Expected the '${kind}' field '${name}' to specify a hash function via 'field.type', but no value was present`);
|
|
1496
|
+
}
|
|
1497
|
+
})(field.type) : {};
|
|
1498
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1499
|
+
if (!test) {
|
|
1500
|
+
throw new Error(`No '${field.type}' hash function is registered for use by the '${kind}' field '${name}'`);
|
|
1501
|
+
}
|
|
1502
|
+
})(this._hashFns.has(field.type)) : {};
|
|
1503
|
+
return this._hashFns.get(field.type);
|
|
1504
|
+
}
|
|
1505
|
+
resource(resource) {
|
|
1506
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1507
|
+
if (!test) {
|
|
1508
|
+
throw new Error(`No resource registered with name '${resource.type}'`);
|
|
1509
|
+
}
|
|
1510
|
+
})(this._schemas.has(resource.type)) : {};
|
|
1511
|
+
return this._schemas.get(resource.type).original;
|
|
1512
|
+
}
|
|
1513
|
+
registerResources(schemas) {
|
|
1514
|
+
schemas.forEach(schema => {
|
|
1515
|
+
this.registerResource(schema);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
registerResource(schema) {
|
|
1519
|
+
const fields = new Map();
|
|
1520
|
+
const relationships = {};
|
|
1521
|
+
const attributes = {};
|
|
1522
|
+
schema.fields.forEach(field => {
|
|
1523
|
+
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
1524
|
+
if (!test) {
|
|
1525
|
+
throw new Error(`${field.kind} is not valid inside a ResourceSchema's fields.`);
|
|
1526
|
+
}
|
|
1527
|
+
})(
|
|
1528
|
+
// @ts-expect-error we are checking for mistakes at runtime
|
|
1529
|
+
field.kind !== '@id' && field.kind !== '@hash') : {};
|
|
1530
|
+
fields.set(field.name, field);
|
|
1531
|
+
if (field.kind === 'attribute') {
|
|
1532
|
+
attributes[field.name] = field;
|
|
1533
|
+
} else if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
1534
|
+
relationships[field.name] = field;
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
const traits = new Set(schema.traits);
|
|
1538
|
+
traits.forEach(trait => {
|
|
1539
|
+
this._traits.add(trait);
|
|
1540
|
+
});
|
|
1541
|
+
const internalSchema = {
|
|
1542
|
+
original: schema,
|
|
1543
|
+
fields,
|
|
1544
|
+
relationships,
|
|
1545
|
+
attributes,
|
|
1546
|
+
traits
|
|
1547
|
+
};
|
|
1548
|
+
this._schemas.set(schema.type, internalSchema);
|
|
1549
|
+
}
|
|
1550
|
+
registerTransformation(transformation) {
|
|
1551
|
+
this._transforms.set(transformation[Type], transformation);
|
|
1552
|
+
}
|
|
1553
|
+
registerDerivation(derivation) {
|
|
1554
|
+
this._derivations.set(derivation[Type], makeCachedDerivation(derivation));
|
|
1555
|
+
}
|
|
1556
|
+
registerHashFn(hashFn) {
|
|
1557
|
+
this._hashFns.set(hashFn[Type], hashFn);
|
|
1558
|
+
}
|
|
1559
|
+
fields({
|
|
1560
|
+
type
|
|
1561
|
+
}) {
|
|
1562
|
+
const schema = this._schemas.get(type);
|
|
1563
|
+
if (!schema) {
|
|
1564
|
+
throw new Error(`No schema defined for ${type}`);
|
|
1565
|
+
}
|
|
1566
|
+
return schema.fields;
|
|
1567
|
+
}
|
|
1568
|
+
hasResource(resource) {
|
|
1569
|
+
return this._schemas.has(resource.type);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
if (macroCondition(getGlobalConfig().WarpDriveMirror.deprecations.ENABLE_LEGACY_SCHEMA_SERVICE)) {
|
|
1573
|
+
SchemaService.prototype.attributesDefinitionFor = function ({
|
|
1574
|
+
type
|
|
1575
|
+
}) {
|
|
1576
|
+
deprecate(`Use \`schema.fields({ type })\` instead of \`schema.attributesDefinitionFor({ type })\``, false, {
|
|
1577
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
1578
|
+
until: '6.0',
|
|
1579
|
+
for: 'ember-data-mirror',
|
|
1580
|
+
since: {
|
|
1581
|
+
available: '4.13',
|
|
1582
|
+
enabled: '5.4'
|
|
1583
|
+
}
|
|
1584
|
+
});
|
|
1585
|
+
const schema = this._schemas.get(type);
|
|
1586
|
+
if (!schema) {
|
|
1587
|
+
throw new Error(`No schema defined for ${type}`);
|
|
1588
|
+
}
|
|
1589
|
+
return schema.attributes;
|
|
1590
|
+
};
|
|
1591
|
+
SchemaService.prototype.relationshipsDefinitionFor = function ({
|
|
1592
|
+
type
|
|
1593
|
+
}) {
|
|
1594
|
+
deprecate(`Use \`schema.fields({ type })\` instead of \`schema.relationshipsDefinitionFor({ type })\``, false, {
|
|
1595
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
1596
|
+
until: '6.0',
|
|
1597
|
+
for: 'ember-data-mirror',
|
|
1598
|
+
since: {
|
|
1599
|
+
available: '4.13',
|
|
1600
|
+
enabled: '5.4'
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
const schema = this._schemas.get(type);
|
|
1604
|
+
if (!schema) {
|
|
1605
|
+
throw new Error(`No schema defined for ${type}`);
|
|
1606
|
+
}
|
|
1607
|
+
return schema.relationships;
|
|
1608
|
+
};
|
|
1609
|
+
SchemaService.prototype.doesTypeExist = function (type) {
|
|
1610
|
+
deprecate(`Use \`schema.hasResource({ type })\` instead of \`schema.doesTypeExist(type)\``, false, {
|
|
1611
|
+
id: 'ember-data-mirror:schema-service-updates',
|
|
1612
|
+
until: '6.0',
|
|
1613
|
+
for: 'ember-data-mirror',
|
|
1614
|
+
since: {
|
|
1615
|
+
available: '4.13',
|
|
1616
|
+
enabled: '5.4'
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
return this._schemas.has(type);
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
export { Checkout, SchemaService, fromIdentity, instantiateRecord, registerDerivations, teardownRecord, withDefaults };
|