@warp-drive/legacy 5.9.0-alpha.2 → 5.9.0-alpha.21

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 (162) hide show
  1. package/README.md +6 -0
  2. package/declarations/adapter/-private/build-url-mixin.d.ts +156 -0
  3. package/declarations/adapter/error.d.ts +385 -169
  4. package/declarations/adapter/json-api.d.ts +12 -1
  5. package/declarations/adapter/rest.d.ts +74 -0
  6. package/declarations/adapter.d.ts +6 -0
  7. package/declarations/compat/builders/find-all.d.ts +0 -1
  8. package/declarations/compat/extensions.d.ts +40 -0
  9. package/declarations/compat/legacy-network-handler/legacy-network-handler.d.ts +7 -0
  10. package/declarations/compat/legacy-network-handler/minimum-adapter-interface.d.ts +4 -0
  11. package/declarations/compat/legacy-network-handler/minimum-serializer-interface.d.ts +7 -0
  12. package/declarations/compat/utils.d.ts +11 -0
  13. package/declarations/compat.d.ts +32 -0
  14. package/declarations/index.d.ts +142 -0
  15. package/declarations/model/-private/attr.d.ts +21 -0
  16. package/declarations/model/-private/belongs-to.d.ts +21 -0
  17. package/declarations/model/-private/hooks.d.ts +26 -0
  18. package/declarations/model/-private/model.d.ts +55 -4
  19. package/declarations/model/-private/promise-many-array.d.ts +25 -1
  20. package/declarations/model/-private/schema-provider.d.ts +11 -1
  21. package/declarations/model/migration-support.d.ts +31 -5
  22. package/declarations/model-fragments/extensions/fragment-array.d.ts +38 -0
  23. package/declarations/model-fragments/extensions/fragment.d.ts +35 -0
  24. package/declarations/model-fragments/hooks/model-for.d.ts +7 -0
  25. package/declarations/model-fragments/index.d.ts +8 -0
  26. package/declarations/model-fragments/instance-initializers/fragment-extensions.d.ts +6 -0
  27. package/declarations/model-fragments/utilities/with-array-defaults.d.ts +30 -0
  28. package/declarations/model-fragments/utilities/with-fragment-array-defaults.d.ts +18 -0
  29. package/declarations/model-fragments/utilities/with-fragment-defaults.d.ts +15 -0
  30. package/declarations/model-fragments/utilities/with-legacy.d.ts +8 -0
  31. package/declarations/serializer/-private/transforms/boolean.d.ts +13 -0
  32. package/declarations/serializer/-private/transforms/date.d.ts +15 -1
  33. package/declarations/serializer/-private/transforms/number.d.ts +14 -1
  34. package/declarations/serializer/-private/transforms/string.d.ts +14 -1
  35. package/declarations/serializer/-private/utils.d.ts +24 -0
  36. package/declarations/serializer/json-api.d.ts +1 -1
  37. package/declarations/serializer.d.ts +4 -6
  38. package/declarations/store/-private.d.ts +2 -2
  39. package/declarations/store.d.ts +7 -0
  40. package/dist/adapter/error.js +386 -241
  41. package/dist/adapter/json-api.js +12 -0
  42. package/dist/adapter/rest.js +39 -3
  43. package/dist/adapter.js +23 -26
  44. package/dist/compat/builders.js +0 -1
  45. package/dist/compat/extensions.js +80 -3
  46. package/dist/compat/utils.js +14 -0
  47. package/dist/compat.js +17 -0
  48. package/dist/{errors-Cz5KrzBk.js → errors-DZKA206g.js} +24 -1
  49. package/dist/{hooks-D6diaM34.js → hooks-BvOqJBei.js} +33 -2
  50. package/dist/index.js +168 -13
  51. package/dist/{json-ChdEfB0X.js → json-DU8m1pGf.js} +83 -6
  52. package/dist/model/-private.js +1 -1
  53. package/dist/model/migration-support.js +15 -2
  54. package/dist/{unpkg/dev-deprecated/model-for-CqXsIKws.js → model-for-CXkJw59V.js} +77 -1
  55. package/dist/model-fragments.js +18 -2
  56. package/dist/model.js +12 -8
  57. package/dist/{schema-provider-DJCV_6AF.js → schema-provider-DtPOp0d7.js} +93 -6
  58. package/dist/serializer/json-api.js +8 -3
  59. package/dist/serializer/json.js +1 -1
  60. package/dist/serializer/rest.js +3 -4
  61. package/dist/serializer/transform.js +51 -3
  62. package/dist/serializer.js +4 -7
  63. package/dist/store.js +13 -7
  64. package/dist/unpkg/dev/adapter/error.js +386 -241
  65. package/dist/unpkg/dev/adapter/json-api.js +13 -1
  66. package/dist/unpkg/dev/adapter/rest.js +39 -3
  67. package/dist/unpkg/dev/adapter.js +23 -26
  68. package/dist/unpkg/dev/compat/builders.js +0 -1
  69. package/dist/unpkg/dev/compat/extensions.js +80 -3
  70. package/dist/unpkg/dev/compat/utils.js +14 -0
  71. package/dist/unpkg/dev/compat.js +34 -1
  72. package/dist/unpkg/dev/{errors-DmGGJr3T.js → errors-DngRU-If.js} +24 -1
  73. package/dist/unpkg/dev/{hooks-CkYiE6Ud.js → hooks-UuiLxWxS.js} +33 -2
  74. package/dist/unpkg/dev/index.js +171 -13
  75. package/dist/unpkg/dev/json-K2Y9z6MN.js +1333 -0
  76. package/dist/unpkg/dev/model/-private.js +1 -1
  77. package/dist/unpkg/dev/model/migration-support.js +16 -2
  78. package/dist/unpkg/{prod-deprecated/model-for-CqXsIKws.js → dev/model-for-CXkJw59V.js} +77 -1
  79. package/dist/unpkg/dev/model-fragments.js +18 -2
  80. package/dist/unpkg/dev/model.js +12 -8
  81. package/dist/unpkg/dev/{schema-provider-DDVYxmUV.js → schema-provider-0D7f-QOn.js} +92 -6
  82. package/dist/unpkg/dev/serializer/json-api.js +9 -4
  83. package/dist/unpkg/dev/serializer/json.js +1 -1
  84. package/dist/unpkg/dev/serializer/rest.js +3 -4
  85. package/dist/unpkg/dev/serializer/transform.js +51 -3
  86. package/dist/unpkg/dev/serializer.js +4 -7
  87. package/dist/unpkg/dev/store.js +21 -7
  88. package/dist/unpkg/dev-deprecated/adapter/error.js +386 -241
  89. package/dist/unpkg/dev-deprecated/adapter/json-api.js +13 -1
  90. package/dist/unpkg/dev-deprecated/adapter/rest.js +39 -3
  91. package/dist/unpkg/dev-deprecated/adapter.js +23 -26
  92. package/dist/unpkg/dev-deprecated/compat/builders.js +0 -1
  93. package/dist/unpkg/dev-deprecated/compat/extensions.js +80 -3
  94. package/dist/unpkg/dev-deprecated/compat/utils.js +14 -0
  95. package/dist/unpkg/dev-deprecated/compat.js +34 -1
  96. package/dist/unpkg/dev-deprecated/{errors-Spt6ubMd.js → errors-Bzidntpi.js} +24 -1
  97. package/dist/unpkg/dev-deprecated/{hooks-DOXegvhL.js → hooks-DVXhMW14.js} +33 -2
  98. package/dist/unpkg/dev-deprecated/index.js +171 -13
  99. package/dist/unpkg/{prod-deprecated/json-BWrZ5546.js → dev-deprecated/json-K2Y9z6MN.js} +96 -6
  100. package/dist/unpkg/dev-deprecated/model/-private.js +1 -1
  101. package/dist/unpkg/dev-deprecated/model/migration-support.js +16 -2
  102. package/dist/unpkg/{dev/model-for-CqXsIKws.js → dev-deprecated/model-for-CXkJw59V.js} +77 -1
  103. package/dist/unpkg/dev-deprecated/model-fragments.js +18 -2
  104. package/dist/unpkg/dev-deprecated/model.js +12 -8
  105. package/dist/unpkg/dev-deprecated/{schema-provider-BP6_8N-V.js → schema-provider-ZwO5_fZw.js} +84 -3
  106. package/dist/unpkg/dev-deprecated/serializer/json-api.js +9 -4
  107. package/dist/unpkg/dev-deprecated/serializer/json.js +1 -1
  108. package/dist/unpkg/dev-deprecated/serializer/rest.js +3 -4
  109. package/dist/unpkg/dev-deprecated/serializer/transform.js +51 -3
  110. package/dist/unpkg/dev-deprecated/serializer.js +4 -7
  111. package/dist/unpkg/dev-deprecated/store.js +21 -7
  112. package/dist/unpkg/prod/adapter/error.js +386 -241
  113. package/dist/unpkg/prod/adapter/json-api.js +13 -1
  114. package/dist/unpkg/prod/adapter/rest.js +39 -3
  115. package/dist/unpkg/prod/adapter.js +23 -26
  116. package/dist/unpkg/prod/compat/builders.js +0 -1
  117. package/dist/unpkg/prod/compat/extensions.js +70 -3
  118. package/dist/unpkg/prod/compat/utils.js +14 -0
  119. package/dist/unpkg/prod/compat.js +17 -0
  120. package/dist/unpkg/prod/{errors-BGVFCBmi.js → errors-B-PWeYlW.js} +24 -1
  121. package/dist/unpkg/prod/{hooks-BztVA_x0.js → hooks-Bx-zBziU.js} +32 -1
  122. package/dist/unpkg/prod/index.js +171 -5
  123. package/dist/unpkg/{dev/json-Cu1LNgmQ.js → prod/json-Qewu-UN9.js} +63 -19
  124. package/dist/unpkg/prod/model/-private.js +1 -1
  125. package/dist/unpkg/prod/model/migration-support.js +16 -2
  126. package/dist/unpkg/prod/model-for-CXkJw59V.js +297 -0
  127. package/dist/unpkg/prod/model-fragments.js +18 -2
  128. package/dist/unpkg/prod/model.js +12 -8
  129. package/dist/unpkg/prod/{schema-provider-DJtD_8jZ.js → schema-provider-BgRqk8i9.js} +96 -6
  130. package/dist/unpkg/prod/serializer/json-api.js +9 -4
  131. package/dist/unpkg/prod/serializer/json.js +1 -1
  132. package/dist/unpkg/prod/serializer/rest.js +3 -4
  133. package/dist/unpkg/prod/serializer/transform.js +51 -3
  134. package/dist/unpkg/prod/serializer.js +4 -7
  135. package/dist/unpkg/prod/store.js +21 -7
  136. package/dist/unpkg/prod-deprecated/adapter/error.js +386 -241
  137. package/dist/unpkg/prod-deprecated/adapter/json-api.js +13 -1
  138. package/dist/unpkg/prod-deprecated/adapter/rest.js +39 -3
  139. package/dist/unpkg/prod-deprecated/adapter.js +23 -26
  140. package/dist/unpkg/prod-deprecated/compat/builders.js +0 -1
  141. package/dist/unpkg/prod-deprecated/compat/extensions.js +70 -3
  142. package/dist/unpkg/prod-deprecated/compat/utils.js +14 -0
  143. package/dist/unpkg/prod-deprecated/compat.js +17 -0
  144. package/dist/unpkg/prod-deprecated/{errors-CdDaK81x.js → errors-Dl2J9d1D.js} +24 -1
  145. package/dist/unpkg/prod-deprecated/{hooks-yId87yyG.js → hooks-Cm60wWTf.js} +32 -1
  146. package/dist/unpkg/prod-deprecated/index.js +171 -5
  147. package/dist/unpkg/{dev-deprecated/json-Cu1LNgmQ.js → prod-deprecated/json-Qewu-UN9.js} +63 -19
  148. package/dist/unpkg/prod-deprecated/model/-private.js +1 -1
  149. package/dist/unpkg/prod-deprecated/model/migration-support.js +16 -2
  150. package/dist/{model-for-CqXsIKws.js → unpkg/prod-deprecated/model-for-CXkJw59V.js} +77 -1
  151. package/dist/unpkg/prod-deprecated/model-fragments.js +18 -2
  152. package/dist/unpkg/prod-deprecated/model.js +12 -8
  153. package/dist/unpkg/prod-deprecated/{schema-provider-CjX55uSY.js → schema-provider-Dh6tRqVI.js} +79 -3
  154. package/dist/unpkg/prod-deprecated/serializer/json-api.js +9 -4
  155. package/dist/unpkg/prod-deprecated/serializer/json.js +1 -1
  156. package/dist/unpkg/prod-deprecated/serializer/rest.js +3 -4
  157. package/dist/unpkg/prod-deprecated/serializer/transform.js +51 -3
  158. package/dist/unpkg/prod-deprecated/serializer.js +4 -7
  159. package/dist/unpkg/prod-deprecated/store.js +21 -7
  160. package/package.json +8 -8
  161. package/dist/unpkg/prod/json-BWrZ5546.js +0 -1243
  162. package/dist/unpkg/prod/model-for-CqXsIKws.js +0 -221
@@ -13,6 +13,58 @@ function coerceId(id) {
13
13
  }
14
14
  }
15
15
 
16
+ /**
17
+ Given the name of a relationship on a resource `type`, determines the
18
+ inverse relationship field (if any) using only the schema service.
19
+
20
+ Unlike `Model.inverseFor`, this does not require `type` to be backed by
21
+ a `Model` class, so it works for both `Model`-based and schema-only
22
+ (e.g. `withDefaults` migration-support) resources.
23
+
24
+ @private
25
+ */
26
+ function inverseForRelationship(store, type, name) {
27
+ const relationship = store.schema.fields({
28
+ type
29
+ }).get(name);
30
+ const {
31
+ options
32
+ } = relationship;
33
+ if (options.inverse === null) {
34
+ return null;
35
+ }
36
+ const schemaExists = store.schema.hasResource(relationship);
37
+ if (!schemaExists) {
38
+ return null;
39
+ }
40
+ const inverseField = store.schema.fields(relationship).get(options.inverse);
41
+ return inverseField ?? null;
42
+ }
43
+
44
+ /**
45
+ Given a relationship field on a resource `type`, determines the
46
+ cardinality of the relationship using only the schema service.
47
+
48
+ Unlike `Model.determineRelationshipType`, this does not require `type`
49
+ to be backed by a `Model` class, so it works for both `Model`-based and
50
+ schema-only (e.g. `withDefaults` migration-support) resources.
51
+
52
+ @private
53
+ */
54
+ function determineRelationshipType(store, type, knownSide) {
55
+ const knownKind = knownSide.kind;
56
+ const inverse = inverseForRelationship(store, type, knownSide.name);
57
+ if (!inverse) {
58
+ return knownKind === 'belongsTo' ? 'oneToNone' : 'manyToNone';
59
+ }
60
+ const otherKind = inverse.kind;
61
+ if (otherKind === 'belongsTo') {
62
+ return knownKind === 'belongsTo' ? 'oneToOne' : 'manyToOne';
63
+ } else {
64
+ return knownKind === 'belongsTo' ? 'oneToMany' : 'manyToMany';
65
+ }
66
+ }
67
+
16
68
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
17
69
  /* eslint-disable @typescript-eslint/no-unsafe-call */
18
70
  /* eslint-disable @typescript-eslint/no-unsafe-return */
@@ -381,11 +433,6 @@ const JSONSerializer = Serializer.extend({
381
433
  };
382
434
  const meta = this.extractMeta(store, primaryModelClass, payload);
383
435
  if (meta) {
384
- (test => {
385
- if (!test) {
386
- throw new Error('The `meta` returned from `extractMeta` has to be an object, not "' + typeof meta + '".');
387
- }
388
- })(typeof meta === 'object');
389
436
  // @ts-expect-error untyped
390
437
  documentHash.meta = meta;
391
438
  }
@@ -691,9 +738,6 @@ const JSONSerializer = Serializer.extend({
691
738
  @private
692
739
  */
693
740
  _getMappedKey(key, modelClass) {
694
- console.warn('There is no attribute or relationship with the name `' + key + '` on `' + modelClass.modelName + '`. Check your serializers attrs hash.', modelClass.attributes.has(key) || modelClass.relationshipsByName.has(key), {
695
- id: 'ds.serializer.no-mapped-attrs-key'
696
- }); // @ts-expect-error attrs is dynamically injected
697
741
  const attrs = this.attrs;
698
742
  let mappedKey;
699
743
  if (attrs && attrs[key]) {
@@ -741,9 +785,7 @@ const JSONSerializer = Serializer.extend({
741
785
  */
742
786
  shouldSerializeHasMany(snapshot, key, relationship) {
743
787
  // @ts-expect-error store is dynamically injected
744
- const schema = this.store.modelFor(snapshot.modelName);
745
- // @ts-expect-error store is dynamically injected
746
- const relationshipType = schema.determineRelationshipType(relationship, this.store);
788
+ const relationshipType = determineRelationshipType(this.store, snapshot.modelName, relationship);
747
789
  if (this._mustSerialize(key)) {
748
790
  return true;
749
791
  }
@@ -782,8 +824,15 @@ const JSONSerializer = Serializer.extend({
782
824
  `serialize` takes an options hash with a single option:
783
825
  `includeId`. If this option is `true`, `serialize` will,
784
826
  by default include the ID in the JSON object it builds.
785
- The adapter passes in `includeId: true` when serializing
786
- a record for `createRecord`, but not for `updateRecord`.
827
+ Whether `includeId` is `true` or `false` depends on the
828
+ adapter and the operation being performed, since it is the
829
+ adapter that invokes `serialize` and decides which options
830
+ to pass. For instance, `RESTAdapter` passes `includeId: true`
831
+ when serializing a record for `createRecord`, but not for
832
+ `updateRecord`, while `JSONAPIAdapter` passes `includeId: true`
833
+ for both `createRecord` and `updateRecord`. Refer to the
834
+ documentation for the adapter and serializer pairing you are
835
+ using for specifics.
787
836
  ## Customization
788
837
  Your server may expect a different JSON format than the
789
838
  built-in serialization format.
@@ -1245,12 +1294,7 @@ const JSONSerializer = Serializer.extend({
1245
1294
  */
1246
1295
  transformFor(attributeType, skipAssertion) {
1247
1296
  const transform = getOwner(this).lookup(`transform:${attributeType}`);
1248
- (test => {
1249
- if (!test) {
1250
- throw new Error(`Unable to find the transform for \`attr('${attributeType}')\``);
1251
- }
1252
- })(skipAssertion || !!transform);
1253
1297
  return transform;
1254
1298
  }
1255
1299
  });
1256
- export { JSONSerializer as J, coerceId as c };
1300
+ export { JSONSerializer as J, coerceId as c, inverseForRelationship as i };
@@ -1 +1 @@
1
- export { E as Errors, L as LEGACY_SUPPORT, P as PromiseBelongsTo, a as PromiseManyArray, l as lookupLegacySupport } from "../errors-BGVFCBmi.js";
1
+ export { E as Errors, L as LEGACY_SUPPORT, P as PromiseBelongsTo, a as PromiseManyArray, l as lookupLegacySupport } from "../errors-B-PWeYlW.js";
@@ -4,8 +4,8 @@ import { notifyInternalSignal } from '@warp-drive/core/signals/-leaked';
4
4
  import { assertPrivateStore } from '@warp-drive/core/store/-private';
5
5
  import { getOrSetGlobal } from '@warp-drive/core/types/-private';
6
6
  import { Type } from '@warp-drive/core/types/symbols';
7
- import { l as lookupLegacySupport, E as Errors } from "../errors-BGVFCBmi.js";
8
- import { b as buildSchema, u as unloadRecord, s as serialize, _ as _save, a as save, r as rollbackAttributes, c as _reload, d as reload, h as hasMany, e as _destroyRecord, f as destroyRecord, i as deleteRecord, R as RecordState, j as changedAttributes, k as belongsTo, l as createSnapshot } from "../schema-provider-DJtD_8jZ.js";
7
+ import { l as lookupLegacySupport, E as Errors } from "../errors-B-PWeYlW.js";
8
+ import { b as buildSchema, u as unloadRecord, s as serialize, _ as _save, a as save, r as rollbackAttributes, c as _reload, d as reload, h as hasMany, e as _destroyRecord, f as destroyRecord, i as deleteRecord, R as RecordState, j as changedAttributes, k as belongsTo, l as createSnapshot } from "../schema-provider-BgRqk8i9.js";
9
9
 
10
10
  /**
11
11
  * This module provides support for migrating away from @warp-drive/legacy/model
@@ -27,6 +27,12 @@ import { b as buildSchema, u as unloadRecord, s as serialize, _ as _save, a as s
27
27
  * @module
28
28
  */
29
29
 
30
+ /**
31
+ * Adds the `Model`-style `belongsTo`/`hasMany` reference methods to a
32
+ * {@link TypedRecordInstance}, for use when migrating a resource from
33
+ * `Model` to a schema-based record while preserving these APIs.
34
+ */
35
+
30
36
  // 'isDestroying', 'isDestroyed'
31
37
  const LegacyFields = ['_createSnapshot', 'adapterError', 'belongsTo', 'changedAttributes', 'constructor', 'currentState', 'deleteRecord', 'destroyRecord', 'dirtyType', 'errors', 'hasDirtyAttributes', 'hasMany', 'isDeleted', 'isEmpty', 'isError', 'isLoaded', 'isLoading', 'isNew', 'isSaving', 'isValid', 'reload', 'rollbackAttributes', 'save', 'serialize', 'unloadRecord'];
32
38
 
@@ -416,6 +422,9 @@ function registerDerivations(schema) {
416
422
  * @public
417
423
  */
418
424
 
425
+ /**
426
+ * See the {@link DelegatingSchemaService | class documentation above} for usage.
427
+ */
419
428
  class DelegatingSchemaService {
420
429
  /** @internal */
421
430
  _preferred;
@@ -425,6 +434,11 @@ class DelegatingSchemaService {
425
434
  this._preferred = schema;
426
435
  this._secondary = buildSchema(store);
427
436
  }
437
+
438
+ /**
439
+ * Whether the given resource's schema is being served by the fallback
440
+ * (legacy Model-derived) schema service rather than the primary one.
441
+ */
428
442
  isDelegated(resource) {
429
443
  return !this._preferred.hasResource(resource) && this._secondary.hasResource(resource);
430
444
  }
@@ -0,0 +1,297 @@
1
+ import { tracked, cached } from '@glimmer/tracking';
2
+ import { Context } from '@warp-drive/core/reactive/-private';
3
+ import { a as decorateFieldV2, i as initializeDeferredDecorator, d as decorateMethodV2 } from "./runtime-BPCpkOf1-BKOwiRJp.js";
4
+
5
+ /**
6
+ * The features added to an object resource by {@link FragmentExtension}, providing
7
+ * a subset of the legacy `ModelFragments` fragment API for migrated resources.
8
+ */
9
+ class Fragment {
10
+ static {
11
+ decorateFieldV2(this.prototype, "isDestroying", [tracked], function () {
12
+ return false;
13
+ });
14
+ }
15
+ #isDestroying = (initializeDeferredDecorator(this, "isDestroying"), void 0); // We might want to check the parent values once we move this code to warp-drive.
16
+ /**
17
+ * Whether this fragment is in the process of being destroyed.
18
+ */
19
+ static {
20
+ decorateFieldV2(this.prototype, "isDestroyed", [tracked], function () {
21
+ return false;
22
+ });
23
+ }
24
+ #isDestroyed = (initializeDeferredDecorator(this, "isDestroyed"), void 0);
25
+ /**
26
+ * Whether this fragment has been destroyed.
27
+ */
28
+ /**
29
+ * Whether this fragment (or the attribute it is rooted at) has uncommitted changes.
30
+ */
31
+ get hasDirtyAttributes() {
32
+ const {
33
+ path,
34
+ resourceKey,
35
+ store
36
+ } = this[Context];
37
+ const record = store.peekRecord(resourceKey);
38
+ if (record.hasDirtyAttributes && path) {
39
+ const root = path.at(0);
40
+ return root in record.changedAttributes();
41
+ }
42
+ return false;
43
+ }
44
+
45
+ /**
46
+ * Always `true`. Used to distinguish fragments from other resources.
47
+ */
48
+ static {
49
+ decorateMethodV2(this.prototype, "hasDirtyAttributes", [cached]);
50
+ }
51
+ get isFragment() {
52
+ return true;
53
+ }
54
+
55
+ /**
56
+ * The resource type of this fragment, if known.
57
+ */
58
+ get $type() {
59
+ const {
60
+ field
61
+ } = this[Context];
62
+ return field?.type;
63
+ }
64
+
65
+ /**
66
+ * Reverts this fragment's attribute back to its last known remote value.
67
+ */
68
+ rollbackAttributes() {
69
+ const {
70
+ path,
71
+ resourceKey,
72
+ store
73
+ } = this[Context];
74
+ if (path) {
75
+ const oldValue = store.cache.getRemoteAttr(resourceKey, path);
76
+ store.cache.setAttr(resourceKey, path, oldValue);
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * A schema extension that adds the {@link Fragment} API to migrated
83
+ * `ModelFragments` object resources.
84
+ */
85
+ const FragmentExtension = {
86
+ kind: 'object',
87
+ name: 'fragment',
88
+ features: Fragment
89
+ };
90
+
91
+ /**
92
+ * The features added to an array resource by {@link FragmentArrayExtension}, providing
93
+ * a subset of the legacy `ModelFragments` fragment-array API for migrated resources.
94
+ */
95
+ class FragmentArray {
96
+ static {
97
+ decorateFieldV2(this.prototype, "isDestroying", [tracked], function () {
98
+ return false;
99
+ });
100
+ }
101
+ #isDestroying = (initializeDeferredDecorator(this, "isDestroying"), void 0); // We might want to check the parent values once we move this code to warp-drive.
102
+ /**
103
+ * Whether this fragment array is in the process of being destroyed.
104
+ */
105
+ static {
106
+ decorateFieldV2(this.prototype, "isDestroyed", [tracked], function () {
107
+ return false;
108
+ });
109
+ }
110
+ #isDestroyed = (initializeDeferredDecorator(this, "isDestroyed"), void 0);
111
+ /**
112
+ * Whether this fragment array has been destroyed.
113
+ */
114
+ /**
115
+ * Whether this fragment array (or any of its members) has uncommitted changes.
116
+ */
117
+ get hasDirtyAttributes() {
118
+ const array = this;
119
+ const context = array[Context];
120
+ const {
121
+ path,
122
+ resourceKey,
123
+ store
124
+ } = context;
125
+ const record = store.peekRecord(resourceKey);
126
+ if (record.hasDirtyAttributes && path) {
127
+ const root = path.at(0);
128
+ return root in record.changedAttributes();
129
+ }
130
+ return false;
131
+ }
132
+
133
+ /**
134
+ * Adds an existing fragment to this array, if one was given.
135
+ */
136
+ static {
137
+ decorateMethodV2(this.prototype, "hasDirtyAttributes", [cached]);
138
+ }
139
+ addFragment(fragment) {
140
+ if (!fragment) {
141
+ return;
142
+ }
143
+ return this.addObject(fragment);
144
+ }
145
+
146
+ /**
147
+ * Appends a new fragment to the end of this array, if one was given.
148
+ */
149
+ createFragment(fragment) {
150
+ if (!fragment) {
151
+ return;
152
+ }
153
+ return this.pushObject(fragment);
154
+ }
155
+
156
+ /**
157
+ * Removes the given fragment from this array, if present.
158
+ */
159
+ removeFragment(fragment) {
160
+ if (!fragment) {
161
+ return;
162
+ }
163
+ const index = this.indexOf(fragment);
164
+ if (index !== -1) {
165
+ this.splice(index, 1);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Reverts each member fragment's attribute back to its last known remote value.
171
+ */
172
+ rollbackAttributes() {
173
+ for (const fragment of this) {
174
+ // @ts-expect-error TODO: fix these types
175
+ fragment?.rollbackAttributes?.();
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * A schema extension that adds the {@link FragmentArray} API to migrated
182
+ * `ModelFragments` array resources.
183
+ */
184
+ const FragmentArrayExtension = {
185
+ kind: 'array',
186
+ name: 'fragment-array',
187
+ features: FragmentArray
188
+ };
189
+
190
+ // if modelFor turns out to be a bottleneck we should replace with a Map
191
+ // and clear it during store teardown.
192
+ const AvailableShims = new WeakMap();
193
+ function getShimClass(store, modelName) {
194
+ let shims = AvailableShims.get(store);
195
+ if (!shims) {
196
+ shims = Object.create(null);
197
+ AvailableShims.set(store, shims);
198
+ }
199
+ let shim = shims[modelName];
200
+ if (shim === undefined) {
201
+ shim = shims[modelName] = new ShimModelClass(store, modelName);
202
+ }
203
+ return shim;
204
+ }
205
+ const AttributeKinds = ['field', 'attribute', 'object', 'array', 'schema-object', 'schema-array'];
206
+
207
+ // Mimics the static apis of @warp-drive/legacy/model
208
+ class ShimModelClass {
209
+ constructor(store, modelName) {
210
+ this.__store = store;
211
+ this.modelName = modelName;
212
+ }
213
+ get fields() {
214
+ const fields = new Map();
215
+ const fieldSchemas = this.__store.schema.fields({
216
+ type: this.modelName
217
+ });
218
+ fieldSchemas.forEach((schema, key) => {
219
+ // @ts-expect-error checking if a string is a valid string
220
+ if (AttributeKinds.includes(schema.kind)) {
221
+ fields.set(key, 'attribute');
222
+ } else if (schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
223
+ fields.set(key, schema.kind);
224
+ }
225
+ });
226
+ return fields;
227
+ }
228
+ get attributes() {
229
+ const attrs = new Map();
230
+ const fields = this.__store.schema.fields({
231
+ type: this.modelName
232
+ });
233
+ fields.forEach((schema, key) => {
234
+ if (schema.kind === 'attribute') {
235
+ attrs.set(key, schema);
236
+ // @ts-expect-error checking if a string is a valid string
237
+ } else if (AttributeKinds.includes(schema.kind)) {
238
+ attrs.set(key, {
239
+ kind: 'attribute',
240
+ name: key,
241
+ type: null,
242
+ options: schema.options ?? {}
243
+ });
244
+ }
245
+ });
246
+ return attrs;
247
+ }
248
+ get relationshipsByName() {
249
+ const rels = new Map();
250
+ const fields = this.__store.schema.fields({
251
+ type: this.modelName
252
+ });
253
+ fields.forEach((schema, key) => {
254
+ if (schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
255
+ rels.set(key, schema);
256
+ }
257
+ });
258
+ return rels;
259
+ }
260
+ eachAttribute(callback, binding) {
261
+ this.attributes.forEach((schema, key) => {
262
+ callback.call(binding, key, schema);
263
+ });
264
+ }
265
+ eachRelationship(callback, binding) {
266
+ this.__store.schema.fields({
267
+ type: this.modelName
268
+ }).forEach((schema, key) => {
269
+ if (schema.kind === 'belongsTo' || schema.kind === 'hasMany') {
270
+ callback.call(binding, key, schema);
271
+ }
272
+ });
273
+ }
274
+ eachTransformedAttribute(callback, binding) {
275
+ this.__store.schema.fields({
276
+ type: this.modelName
277
+ }).forEach((schema, key) => {
278
+ if (schema.kind === 'attribute') {
279
+ const type = schema.type;
280
+ if (type) callback.call(binding, key, type);
281
+ }
282
+ });
283
+ }
284
+ }
285
+ function fragmentsModelFor(modelName) {
286
+ return getShimClass(this, modelName);
287
+ }
288
+
289
+ /**
290
+ * The `modelFor` fallback used to construct a `ShimModelClass` schema for a
291
+ * type when ModelFragments support is enabled and no real `Model` subclass
292
+ * is registered for that type.
293
+ *
294
+ * @public
295
+ */
296
+ const modelFor = fragmentsModelFor;
297
+ export { FragmentExtension as F, FragmentArrayExtension as a, FragmentArray as b, Fragment as c, fragmentsModelFor as f, modelFor as m };
@@ -1,7 +1,7 @@
1
1
  import { pluralize, singularize } from '@warp-drive/utilities/string';
2
2
  import { withDefaults } from './model/migration-support.js';
3
- import { F as FragmentExtension, a as FragmentArrayExtension } from "./model-for-CqXsIKws.js";
4
- export { c as Fragment, b as FragmentArray, m as modelFor } from "./model-for-CqXsIKws.js";
3
+ import { F as FragmentExtension, a as FragmentArrayExtension } from "./model-for-CXkJw59V.js";
4
+ export { c as Fragment, b as FragmentArray, m as modelFor } from "./model-for-CXkJw59V.js";
5
5
 
6
6
  /**
7
7
  * Used as a helper to setup the relevant parts of an array
@@ -62,6 +62,15 @@ function withFragmentArrayDefaults(fragmentArrayType, fragmentArrayName) {
62
62
  }
63
63
  };
64
64
  }
65
+
66
+ /**
67
+ * Used as a helper to setup the relevant parts of a legacy resource schema
68
+ * migrated from `Model`, applying the `ember-object` and `fragment` object
69
+ * extensions and a default `@id` identity field.
70
+ *
71
+ * @param schema the partial legacy resource schema to complete
72
+ * @returns the completed resource schema
73
+ */
65
74
  function withLegacy(schema) {
66
75
  return withDefaults({
67
76
  ...schema,
@@ -72,6 +81,13 @@ function withLegacy(schema) {
72
81
  objectExtensions: ['ember-object', 'fragment']
73
82
  });
74
83
  }
84
+
85
+ /**
86
+ * Registers the {@link FragmentExtension}/{@link FragmentArrayExtension} schema
87
+ * extensions on the given `SchemaService`, enabling ModelFragments migration support.
88
+ *
89
+ * @public
90
+ */
75
91
  function registerFragmentExtensions(schema) {
76
92
  schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentExtension);
77
93
  schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentArrayExtension);
@@ -3,10 +3,10 @@ import { recordIdentifierFor } from '@warp-drive/core';
3
3
  import { RecordStore } from '@warp-drive/core/types/symbols';
4
4
  import { i as isElementDescriptor, n as normalizeModelName } from "./util-DvanW33H.js";
5
5
  import { assertPrivateStore } from '@warp-drive/core/store/-private';
6
- import { l as lookupLegacySupport } from "./errors-BGVFCBmi.js";
6
+ import { l as lookupLegacySupport } from "./errors-B-PWeYlW.js";
7
7
  import '@warp-drive/utilities/string';
8
- export { M as Model, b as buildSchema, M as default, m as restoreDeprecatedModelRequestBehaviors } from "./schema-provider-DJtD_8jZ.js";
9
- export { i as instantiateRecord, m as modelFor, t as teardownRecord } from "./hooks-BztVA_x0.js";
8
+ export { M as Model, b as buildSchema, M as default, m as restoreDeprecatedModelRequestBehaviors } from "./schema-provider-BgRqk8i9.js";
9
+ export { i as instantiateRecord, m as modelFor, t as teardownRecord } from "./hooks-Bx-zBziU.js";
10
10
 
11
11
  /**
12
12
  * Options provided to the attr decorator are
@@ -44,6 +44,7 @@ function _attr(type, options) {
44
44
  kind: 'attribute',
45
45
  isAttribute: true,
46
46
  options: options,
47
+ sourceKey: options.sourceKey,
47
48
  key: null
48
49
  };
49
50
  return computed({
@@ -52,14 +53,15 @@ function _attr(type, options) {
52
53
  return;
53
54
  }
54
55
  const cache = this[RecordStore].cache;
55
- return cache.getAttr(recordIdentifierFor(this), key);
56
+ return cache.getAttr(recordIdentifierFor(this), meta.sourceKey ?? key);
56
57
  },
57
58
  set(key, value) {
58
59
  const identifier = recordIdentifierFor(this);
59
60
  const cache = this[RecordStore].cache;
60
- const currentValue = cache.getAttr(identifier, key);
61
+ const cacheKey = meta.sourceKey ?? key;
62
+ const currentValue = cache.getAttr(identifier, cacheKey);
61
63
  if (currentValue !== value) {
62
- cache.setAttr(identifier, key, value);
64
+ cache.setAttr(identifier, cacheKey, value);
63
65
  if (!this.isValid) {
64
66
  const {
65
67
  errors
@@ -201,7 +203,8 @@ function _belongsTo(type, options) {
201
203
  type: normalizeModelName(type),
202
204
  options: options,
203
205
  kind: 'belongsTo',
204
- name: '<Unknown BelongsTo>'
206
+ name: '<Unknown BelongsTo>',
207
+ sourceKey: options.sourceKey
205
208
  };
206
209
  return computed({
207
210
  get(key) {
@@ -404,7 +407,8 @@ function _hasMany(type, options) {
404
407
  type: normalizeType(type),
405
408
  options,
406
409
  kind: 'hasMany',
407
- name: '<Unknown BelongsTo>'
410
+ name: '<Unknown BelongsTo>',
411
+ sourceKey: options.sourceKey
408
412
  };
409
413
  return computed({
410
414
  get(key) {