@warp-drive/schema-record 5.4.0-alpha.138 → 5.4.0-alpha.140

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.
Files changed (39) hide show
  1. package/README.md +209 -121
  2. package/dist/-private.js +1 -0
  3. package/dist/-private.js.map +1 -0
  4. package/dist/{record.js → index.js} +490 -34
  5. package/dist/index.js.map +1 -0
  6. package/dist/symbols-DqoS4ybV.js.map +1 -1
  7. package/package.json +18 -15
  8. package/unstable-preview-types/-private/{compute.d.ts → fields/compute.d.ts} +17 -15
  9. package/unstable-preview-types/-private/fields/compute.d.ts.map +1 -0
  10. package/unstable-preview-types/-private/{managed-array.d.ts → fields/managed-array.d.ts} +4 -4
  11. package/unstable-preview-types/-private/fields/managed-array.d.ts.map +1 -0
  12. package/unstable-preview-types/-private/{managed-object.d.ts → fields/managed-object.d.ts} +4 -4
  13. package/unstable-preview-types/-private/fields/managed-object.d.ts.map +1 -0
  14. package/unstable-preview-types/-private/fields/many-array-manager.d.ts +23 -0
  15. package/unstable-preview-types/-private/fields/many-array-manager.d.ts.map +1 -0
  16. package/unstable-preview-types/{hooks.d.ts → -private/hooks.d.ts} +3 -3
  17. package/unstable-preview-types/-private/hooks.d.ts.map +1 -0
  18. package/unstable-preview-types/{record.d.ts → -private/record.d.ts} +3 -3
  19. package/unstable-preview-types/-private/record.d.ts.map +1 -0
  20. package/unstable-preview-types/{schema.d.ts → -private/schema.d.ts} +2 -2
  21. package/unstable-preview-types/-private/schema.d.ts.map +1 -0
  22. package/unstable-preview-types/{symbols.d.ts → -private/symbols.d.ts} +1 -1
  23. package/unstable-preview-types/-private/symbols.d.ts.map +1 -0
  24. package/unstable-preview-types/-private.d.ts +4 -0
  25. package/unstable-preview-types/-private.d.ts.map +1 -0
  26. package/unstable-preview-types/index.d.ts +16 -7
  27. package/unstable-preview-types/index.d.ts.map +1 -0
  28. package/dist/hooks.js +0 -19
  29. package/dist/hooks.js.map +0 -1
  30. package/dist/record.js.map +0 -1
  31. package/dist/schema.js +0 -278
  32. package/dist/schema.js.map +0 -1
  33. package/unstable-preview-types/-private/compute.d.ts.map +0 -1
  34. package/unstable-preview-types/-private/managed-array.d.ts.map +0 -1
  35. package/unstable-preview-types/-private/managed-object.d.ts.map +0 -1
  36. package/unstable-preview-types/hooks.d.ts.map +0 -1
  37. package/unstable-preview-types/record.d.ts.map +0 -1
  38. package/unstable-preview-types/schema.d.ts.map +0 -1
  39. package/unstable-preview-types/symbols.d.ts.map +0 -1
@@ -1,10 +1,13 @@
1
1
  import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
2
- import { setRecordIdentifier, recordIdentifierFor } from '@ember-data/store/-private';
2
+ import { SOURCE as SOURCE$1, fastPush, RelatedCollection, setRecordIdentifier, recordIdentifierFor } from '@ember-data/store/-private';
3
3
  import { createSignal, subscribe, defineSignal, peekSignal, getSignal, Signals, entangleSignal, addToTransaction } from '@ember-data/tracking/-private';
4
- import { STRUCTURED } from '@warp-drive/core-types/request';
5
- import { RecordStore } from '@warp-drive/core-types/symbols';
4
+ import { EnableHydration, STRUCTURED } from '@warp-drive/core-types/request';
5
+ import { RecordStore, Type } from '@warp-drive/core-types/symbols';
6
6
  import { getOrSetGlobal } from '@warp-drive/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/store';
10
+ import { createCache, getValue } from '@ember-data/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']);
@@ -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;
@@ -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().WarpDrive.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().WarpDrive.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, isSchemaArray, editable, legacy) {
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
@@ -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/model', '*');
533
657
  const getLegacySupport = macroCondition(dependencySatisfies('@ember-data/model', '*')) ? importSync('@ember-data/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) {
@@ -683,10 +810,10 @@ class SchemaRecord {
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
818
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
692
819
  if (!test) {
@@ -694,12 +821,10 @@ class SchemaRecord {
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
829
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
705
830
  if (!test) {
@@ -707,7 +832,7 @@ class SchemaRecord {
707
832
  }
708
833
  })(!target[Legacy]) : {};
709
834
  entangleSignal(signals, receiver, field.name);
710
- return computeArray(store, schema, cache, target, identifier, field, propArray, false, Mode[Editable], Mode[Legacy]);
835
+ return computeArray(store, schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
711
836
  case 'object':
712
837
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
713
838
  if (!test) {
@@ -728,7 +853,7 @@ class SchemaRecord {
728
853
  case 'belongsTo':
729
854
  if (field.options.linksMode) {
730
855
  entangleSignal(signals, receiver, field.name);
731
- const rawValue = cache.getRelationship(identifier, field.name);
856
+ const rawValue = IS_EDITABLE ? cache.getRelationship(identifier, field.name) : cache.getRemoteRelationship(identifier, field.name);
732
857
 
733
858
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
734
859
  return rawValue.data ? store.peekRecord(rawValue.data) : null;
@@ -753,6 +878,10 @@ class SchemaRecord {
753
878
  entangleSignal(signals, receiver, field.name);
754
879
  return getLegacySupport(receiver).getBelongsTo(field.name);
755
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
+ }
756
885
  if (!HAS_MODEL_PACKAGE) {
757
886
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
758
887
  {
@@ -850,6 +979,11 @@ class SchemaRecord {
850
979
  cache.setAttr(identifier, propArray, value?.slice());
851
980
  const peeked = peekManagedArray(self, field);
852
981
  if (peeked) {
982
+ macroCondition(getGlobalConfig().WarpDrive.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) : {};
853
987
  const arrSignal = peeked[ARRAY_SIGNAL];
854
988
  arrSignal.shouldReset = true;
855
989
  }
@@ -863,6 +997,11 @@ class SchemaRecord {
863
997
  cache.setAttr(identifier, propArray, rawValue);
864
998
  const peeked = peekManagedArray(self, field);
865
999
  if (peeked) {
1000
+ macroCondition(getGlobalConfig().WarpDrive.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) : {};
866
1005
  const arrSignal = peeked[ARRAY_SIGNAL];
867
1006
  arrSignal.shouldReset = true;
868
1007
  }
@@ -877,6 +1016,11 @@ class SchemaRecord {
877
1016
  cache.setAttr(identifier, propArray, arrayValue);
878
1017
  const peeked = peekManagedArray(self, field);
879
1018
  if (peeked) {
1019
+ macroCondition(getGlobalConfig().WarpDrive.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) : {};
880
1024
  const arrSignal = peeked[ARRAY_SIGNAL];
881
1025
  arrSignal.shouldReset = true;
882
1026
  }
@@ -1054,6 +1198,11 @@ class SchemaRecord {
1054
1198
  if (field?.kind === 'array' || field?.kind === 'schema-array') {
1055
1199
  const peeked = peekManagedArray(self, field);
1056
1200
  if (peeked) {
1201
+ macroCondition(getGlobalConfig().WarpDrive.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) : {};
1057
1206
  const arrSignal = peeked[ARRAY_SIGNAL];
1058
1207
  arrSignal.shouldReset = true;
1059
1208
  addToTransaction(arrSignal);
@@ -1090,6 +1239,16 @@ class SchemaRecord {
1090
1239
  }
1091
1240
  // FIXME
1092
1241
  } else if (field.kind === 'resource') ;else if (field.kind === 'hasMany') {
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
+ }
1093
1252
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1094
1253
  if (!test) {
1095
1254
  throw new Error(`Expected to have a getLegacySupport function`);
@@ -1145,6 +1304,10 @@ class SchemaRecord {
1145
1304
  this[RecordStore].notifications.unsubscribe(this.___notifications);
1146
1305
  }
1147
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
+ }
1148
1311
  const editable = Editables.get(this);
1149
1312
  if (editable) {
1150
1313
  return Promise.resolve(editable);
@@ -1163,4 +1326,297 @@ class SchemaRecord {
1163
1326
  return Promise.resolve(editableRecord);
1164
1327
  }
1165
1328
  }
1166
- export { Checkout, Editable, Legacy, SchemaRecord };
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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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().WarpDrive.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:schema-service-updates',
1578
+ until: '6.0',
1579
+ for: 'ember-data',
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:schema-service-updates',
1596
+ until: '6.0',
1597
+ for: 'ember-data',
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:schema-service-updates',
1612
+ until: '6.0',
1613
+ for: 'ember-data',
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 };