@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
@@ -15,6 +15,78 @@ function coerceId(id) {
15
15
  }
16
16
  }
17
17
 
18
+ /**
19
+ Given the name of a relationship on a resource `type`, determines the
20
+ inverse relationship field (if any) using only the schema service.
21
+
22
+ Unlike `Model.inverseFor`, this does not require `type` to be backed by
23
+ a `Model` class, so it works for both `Model`-based and schema-only
24
+ (e.g. `withDefaults` migration-support) resources.
25
+
26
+ @private
27
+ */
28
+ function inverseForRelationship(store, type, name) {
29
+ const relationship = store.schema.fields({
30
+ type
31
+ }).get(name);
32
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
33
+ if (!test) {
34
+ throw new Error(`No relationship named '${name}' on '${type}' exists.`);
35
+ }
36
+ })(relationship) : {};
37
+ const {
38
+ options
39
+ } = relationship;
40
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
41
+ if (!test) {
42
+ throw new Error(`Expected the relationship ${name} on ${type} to define an inverse.`);
43
+ }
44
+ })(options.inverse === null || typeof options.inverse === 'string' && options.inverse.length > 0) : {};
45
+ if (options.inverse === null) {
46
+ return null;
47
+ }
48
+ const schemaExists = store.schema.hasResource(relationship);
49
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
50
+ if (!test) {
51
+ throw new Error(`No associated schema found for '${relationship.type}' while calculating the inverse of ${name} on ${type}`);
52
+ }
53
+ })(schemaExists) : {};
54
+ if (!schemaExists) {
55
+ return null;
56
+ }
57
+ const inverseField = store.schema.fields(relationship).get(options.inverse);
58
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
59
+ if (!test) {
60
+ throw new Error(`No inverse relationship found for '${name}' on '${type}'`);
61
+ }
62
+ })(inverseField && (inverseField.kind === 'belongsTo' || inverseField.kind === 'hasMany')) : {};
63
+ return inverseField ?? null;
64
+ }
65
+
66
+ /**
67
+ Given a relationship field on a resource `type`, determines the
68
+ cardinality of the relationship using only the schema service.
69
+
70
+ Unlike `Model.determineRelationshipType`, this does not require `type`
71
+ to be backed by a `Model` class, so it works for both `Model`-based and
72
+ schema-only (e.g. `withDefaults` migration-support) resources.
73
+
74
+ @private
75
+ */
76
+ function determineRelationshipType(store, type, knownSide) {
77
+ const knownKind = knownSide.kind;
78
+ const inverse = inverseForRelationship(store, type, knownSide.name);
79
+ if (!inverse) {
80
+ return knownKind === 'belongsTo' ? 'oneToNone' : 'manyToNone';
81
+ }
82
+ const otherKind = inverse.kind;
83
+ if (otherKind === 'belongsTo') {
84
+ return knownKind === 'belongsTo' ? 'oneToOne' : 'manyToOne';
85
+ } else {
86
+ return knownKind === 'belongsTo' ? 'oneToMany' : 'manyToMany';
87
+ }
88
+ }
89
+
18
90
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
19
91
  /* eslint-disable @typescript-eslint/no-unsafe-call */
20
92
  /* eslint-disable @typescript-eslint/no-unsafe-return */
@@ -744,9 +816,7 @@ const JSONSerializer = Serializer.extend({
744
816
  */
745
817
  shouldSerializeHasMany(snapshot, key, relationship) {
746
818
  // @ts-expect-error store is dynamically injected
747
- const schema = this.store.modelFor(snapshot.modelName);
748
- // @ts-expect-error store is dynamically injected
749
- const relationshipType = schema.determineRelationshipType(relationship, this.store);
819
+ const relationshipType = determineRelationshipType(this.store, snapshot.modelName, relationship);
750
820
  if (this._mustSerialize(key)) {
751
821
  return true;
752
822
  }
@@ -785,8 +855,15 @@ const JSONSerializer = Serializer.extend({
785
855
  `serialize` takes an options hash with a single option:
786
856
  `includeId`. If this option is `true`, `serialize` will,
787
857
  by default include the ID in the JSON object it builds.
788
- The adapter passes in `includeId: true` when serializing
789
- a record for `createRecord`, but not for `updateRecord`.
858
+ Whether `includeId` is `true` or `false` depends on the
859
+ adapter and the operation being performed, since it is the
860
+ adapter that invokes `serialize` and decides which options
861
+ to pass. For instance, `RESTAdapter` passes `includeId: true`
862
+ when serializing a record for `createRecord`, but not for
863
+ `updateRecord`, while `JSONAPIAdapter` passes `includeId: true`
864
+ for both `createRecord` and `updateRecord`. Refer to the
865
+ documentation for the adapter and serializer pairing you are
866
+ using for specifics.
790
867
  ## Customization
791
868
  Your server may expect a different JSON format than the
792
869
  built-in serialization format.
@@ -1256,4 +1333,4 @@ const JSONSerializer = Serializer.extend({
1256
1333
  return transform;
1257
1334
  }
1258
1335
  });
1259
- export { JSONSerializer as J, coerceId as c };
1336
+ 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-Cz5KrzBk.js";
1
+ export { E as Errors, L as LEGACY_SUPPORT, P as PromiseBelongsTo, a as PromiseManyArray, l as lookupLegacySupport } from "../errors-DZKA206g.js";
@@ -5,8 +5,8 @@ import { notifyInternalSignal } from '@warp-drive/core/signals/-leaked';
5
5
  import { assertPrivateStore } from '@warp-drive/core/store/-private';
6
6
  import { getOrSetGlobal } from '@warp-drive/core/types/-private';
7
7
  import { Type } from '@warp-drive/core/types/symbols';
8
- import { l as lookupLegacySupport, E as Errors } from "../errors-Cz5KrzBk.js";
9
- 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-DJCV_6AF.js";
8
+ import { l as lookupLegacySupport, E as Errors } from "../errors-DZKA206g.js";
9
+ 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-DtPOp0d7.js";
10
10
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
11
11
 
12
12
  /**
@@ -28,6 +28,11 @@ import { macroCondition, getGlobalConfig } from '@embroider/macros';
28
28
  *
29
29
  * @module
30
30
  */
31
+ /**
32
+ * Adds the `Model`-style `belongsTo`/`hasMany` reference methods to a
33
+ * {@link TypedRecordInstance}, for use when migrating a resource from
34
+ * `Model` to a schema-based record while preserving these APIs.
35
+ */
31
36
  // 'isDestroying', 'isDestroyed'
32
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'];
33
38
 
@@ -434,6 +439,9 @@ function registerDerivations(schema) {
434
439
  * @public
435
440
  */
436
441
 
442
+ /**
443
+ * See the {@link DelegatingSchemaService | class documentation above} for usage.
444
+ */
437
445
  class DelegatingSchemaService {
438
446
  /** @internal */
439
447
  _preferred;
@@ -443,6 +451,11 @@ class DelegatingSchemaService {
443
451
  this._preferred = schema;
444
452
  this._secondary = buildSchema(store);
445
453
  }
454
+
455
+ /**
456
+ * Whether the given resource's schema is being served by the fallback
457
+ * (legacy Model-derived) schema service rather than the primary one.
458
+ */
446
459
  isDelegated(resource) {
447
460
  return !this._preferred.hasResource(resource) && this._secondary.hasResource(resource);
448
461
  }
@@ -1,6 +1,11 @@
1
1
  import { tracked, cached } from '@glimmer/tracking';
2
2
  import { Context } from '@warp-drive/core/reactive/-private';
3
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
+ */
4
9
  class Fragment {
5
10
  static {
6
11
  decorateFieldV2(this.prototype, "isDestroying", [tracked], function () {
@@ -8,12 +13,21 @@ class Fragment {
8
13
  });
9
14
  }
10
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
+ */
11
19
  static {
12
20
  decorateFieldV2(this.prototype, "isDestroyed", [tracked], function () {
13
21
  return false;
14
22
  });
15
23
  }
16
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
+ */
17
31
  get hasDirtyAttributes() {
18
32
  const {
19
33
  path,
@@ -27,18 +41,30 @@ class Fragment {
27
41
  }
28
42
  return false;
29
43
  }
44
+
45
+ /**
46
+ * Always `true`. Used to distinguish fragments from other resources.
47
+ */
30
48
  static {
31
49
  decorateMethodV2(this.prototype, "hasDirtyAttributes", [cached]);
32
50
  }
33
51
  get isFragment() {
34
52
  return true;
35
53
  }
54
+
55
+ /**
56
+ * The resource type of this fragment, if known.
57
+ */
36
58
  get $type() {
37
59
  const {
38
60
  field
39
61
  } = this[Context];
40
62
  return field?.type;
41
63
  }
64
+
65
+ /**
66
+ * Reverts this fragment's attribute back to its last known remote value.
67
+ */
42
68
  rollbackAttributes() {
43
69
  const {
44
70
  path,
@@ -51,11 +77,21 @@ class Fragment {
51
77
  }
52
78
  }
53
79
  }
80
+
81
+ /**
82
+ * A schema extension that adds the {@link Fragment} API to migrated
83
+ * `ModelFragments` object resources.
84
+ */
54
85
  const FragmentExtension = {
55
86
  kind: 'object',
56
87
  name: 'fragment',
57
88
  features: Fragment
58
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
+ */
59
95
  class FragmentArray {
60
96
  static {
61
97
  decorateFieldV2(this.prototype, "isDestroying", [tracked], function () {
@@ -63,18 +99,29 @@ class FragmentArray {
63
99
  });
64
100
  }
65
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
+ */
66
105
  static {
67
106
  decorateFieldV2(this.prototype, "isDestroyed", [tracked], function () {
68
107
  return false;
69
108
  });
70
109
  }
71
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
+ */
72
117
  get hasDirtyAttributes() {
118
+ const array = this;
119
+ const context = array[Context];
73
120
  const {
74
121
  path,
75
122
  resourceKey,
76
123
  store
77
- } = this[Context];
124
+ } = context;
78
125
  const record = store.peekRecord(resourceKey);
79
126
  if (record.hasDirtyAttributes && path) {
80
127
  const root = path.at(0);
@@ -82,6 +129,10 @@ class FragmentArray {
82
129
  }
83
130
  return false;
84
131
  }
132
+
133
+ /**
134
+ * Adds an existing fragment to this array, if one was given.
135
+ */
85
136
  static {
86
137
  decorateMethodV2(this.prototype, "hasDirtyAttributes", [cached]);
87
138
  }
@@ -91,12 +142,20 @@ class FragmentArray {
91
142
  }
92
143
  return this.addObject(fragment);
93
144
  }
145
+
146
+ /**
147
+ * Appends a new fragment to the end of this array, if one was given.
148
+ */
94
149
  createFragment(fragment) {
95
150
  if (!fragment) {
96
151
  return;
97
152
  }
98
153
  return this.pushObject(fragment);
99
154
  }
155
+
156
+ /**
157
+ * Removes the given fragment from this array, if present.
158
+ */
100
159
  removeFragment(fragment) {
101
160
  if (!fragment) {
102
161
  return;
@@ -106,6 +165,10 @@ class FragmentArray {
106
165
  this.splice(index, 1);
107
166
  }
108
167
  }
168
+
169
+ /**
170
+ * Reverts each member fragment's attribute back to its last known remote value.
171
+ */
109
172
  rollbackAttributes() {
110
173
  for (const fragment of this) {
111
174
  // @ts-expect-error TODO: fix these types
@@ -113,6 +176,11 @@ class FragmentArray {
113
176
  }
114
177
  }
115
178
  }
179
+
180
+ /**
181
+ * A schema extension that adds the {@link FragmentArray} API to migrated
182
+ * `ModelFragments` array resources.
183
+ */
116
184
  const FragmentArrayExtension = {
117
185
  kind: 'array',
118
186
  name: 'fragment-array',
@@ -217,5 +285,13 @@ class ShimModelClass {
217
285
  function fragmentsModelFor(modelName) {
218
286
  return getShimClass(this, modelName);
219
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
+ */
220
296
  const modelFor = fragmentsModelFor;
221
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);
package/dist/model.js CHANGED
@@ -5,10 +5,10 @@ import { i as isElementDescriptor, n as normalizeModelName } from "./util-Dul6TZ
5
5
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
6
6
  import { warn, deprecate } from '@ember/debug';
7
7
  import { assertPrivateStore } from '@warp-drive/core/store/-private';
8
- import { l as lookupLegacySupport } from "./errors-Cz5KrzBk.js";
8
+ import { l as lookupLegacySupport } from "./errors-DZKA206g.js";
9
9
  import { singularize, dasherize } from '@warp-drive/utilities/string';
10
- export { M as Model, b as buildSchema, M as default, m as restoreDeprecatedModelRequestBehaviors } from "./schema-provider-DJCV_6AF.js";
11
- export { i as instantiateRecord, m as modelFor, t as teardownRecord } from "./hooks-D6diaM34.js";
10
+ export { M as Model, b as buildSchema, M as default, m as restoreDeprecatedModelRequestBehaviors } from "./schema-provider-DtPOp0d7.js";
11
+ export { i as instantiateRecord, m as modelFor, t as teardownRecord } from "./hooks-BvOqJBei.js";
12
12
  function _attr(type, options) {
13
13
  if (typeof type === 'object') {
14
14
  options = type;
@@ -21,6 +21,7 @@ function _attr(type, options) {
21
21
  kind: 'attribute',
22
22
  isAttribute: true,
23
23
  options: options,
24
+ sourceKey: options.sourceKey,
24
25
  key: null
25
26
  };
26
27
  return computed({
@@ -34,7 +35,7 @@ function _attr(type, options) {
34
35
  return;
35
36
  }
36
37
  const cache = this[RecordStore].cache;
37
- return cache.getAttr(recordIdentifierFor(this), key);
38
+ return cache.getAttr(recordIdentifierFor(this), meta.sourceKey ?? key);
38
39
  },
39
40
  set(key, value) {
40
41
  if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
@@ -49,9 +50,10 @@ function _attr(type, options) {
49
50
  }
50
51
  })(!this.currentState.isDeleted) : {};
51
52
  const cache = this[RecordStore].cache;
52
- const currentValue = cache.getAttr(identifier, key);
53
+ const cacheKey = meta.sourceKey ?? key;
54
+ const currentValue = cache.getAttr(identifier, cacheKey);
53
55
  if (currentValue !== value) {
54
- cache.setAttr(identifier, key, value);
56
+ cache.setAttr(identifier, cacheKey, value);
55
57
  if (!this.isValid) {
56
58
  const {
57
59
  errors
@@ -202,7 +204,8 @@ function _belongsTo(type, options) {
202
204
  type: normalizeModelName(type),
203
205
  options: options,
204
206
  kind: 'belongsTo',
205
- name: '<Unknown BelongsTo>'
207
+ name: '<Unknown BelongsTo>',
208
+ sourceKey: options.sourceKey
206
209
  };
207
210
  return computed({
208
211
  get(key) {
@@ -456,7 +459,8 @@ function _hasMany(type, options) {
456
459
  type: normalizeType(type),
457
460
  options,
458
461
  kind: 'hasMany',
459
- name: '<Unknown BelongsTo>'
462
+ name: '<Unknown BelongsTo>',
463
+ sourceKey: options.sourceKey
460
464
  };
461
465
  return computed({
462
466
  get(key) {
@@ -5,7 +5,7 @@ import { recordIdentifierFor, storeFor } from '@warp-drive/core';
5
5
  import { notifyInternalSignal, peekInternalSignal, withSignalStore, gate, memoized, defineSignal, entangleSignal, defineGate } from '@warp-drive/core/signals/-leaked';
6
6
  import { assertPrivateStore, recordIdentifierFor as recordIdentifierFor$1, coerceId } from '@warp-drive/core/store/-private';
7
7
  import { RecordStore } from '@warp-drive/core/types/symbols';
8
- import { l as lookupLegacySupport, L as LEGACY_SUPPORT, E as Errors } from "./errors-Cz5KrzBk.js";
8
+ import { l as lookupLegacySupport, L as LEGACY_SUPPORT, E as Errors } from "./errors-DZKA206g.js";
9
9
  import { u as upgradeStore, F as FetchManager } from "./-private-BG3bMiKp.js";
10
10
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
11
11
  import { cacheFor } from '@ember/object/internals';
@@ -44,11 +44,13 @@ function hasMany(prop) {
44
44
  }
45
45
  function reload(options = {}) {
46
46
  if (macroCondition(!getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_REQUEST_METHODS)) {
47
+ const message = `You cannot use reload() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`;
47
48
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
48
49
  {
49
- throw new Error(`You cannot use reload() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`);
50
+ throw new Error(message);
50
51
  }
51
52
  })() : {};
53
+ return Promise.reject(new Error(message));
52
54
  } else {
53
55
  deprecate(`record.reload is deprecated, please use store.request to initiate a request instead.`, false, {
54
56
  id: 'warp-drive:deprecate-legacy-request-methods',
@@ -102,11 +104,13 @@ function deleteRecord() {
102
104
  }
103
105
  function save(options) {
104
106
  if (macroCondition(!getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_REQUEST_METHODS)) {
107
+ const message = `You cannot use save() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`;
105
108
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
106
109
  {
107
- throw new Error(`You cannot use save() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`);
110
+ throw new Error(message);
108
111
  }
109
112
  })() : {};
113
+ return Promise.reject(new Error(message));
110
114
  } else {
111
115
  deprecate(`record.save is deprecated, please use store.request to initiate a request instead.`, false, {
112
116
  id: 'warp-drive:deprecate-legacy-request-methods',
@@ -133,11 +137,13 @@ function _save(options) {
133
137
  }
134
138
  function destroyRecord(options) {
135
139
  if (macroCondition(!getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_REQUEST_METHODS)) {
140
+ const message = `You cannot use destroyRecord() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`;
136
141
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
137
142
  {
138
- throw new Error(`You cannot use destroyRecord() on a record when ENABLE_LEGACY_REQUEST_METHODS is false.`);
143
+ throw new Error(message);
139
144
  }
140
145
  })() : {};
146
+ return Promise.reject(new Error(message));
141
147
  } else {
142
148
  deprecate(`record.destroyRecord is deprecated, please use store.request to initiate a request instead.`, false, {
143
149
  id: 'warp-drive:deprecate-legacy-request-methods',
@@ -977,6 +983,9 @@ class Model extends EmberObject {
977
983
  get isError() {
978
984
  return this.currentState.isError;
979
985
  }
986
+ /**
987
+ * `isError` is read-only and cannot be set directly.
988
+ */
980
989
  static {
981
990
  decorateMethodV2(this.prototype, "isError", [memoized]);
982
991
  }
@@ -1024,6 +1033,10 @@ class Model extends EmberObject {
1024
1033
  }
1025
1034
  return recordIdentifierFor(this).id;
1026
1035
  }
1036
+ /**
1037
+ * Assigns the resource's primary key. Typically only used internally
1038
+ * when a client-created record is assigned an id upon being saved.
1039
+ */
1027
1040
  static {
1028
1041
  decorateMethodV2(this.prototype, "id", [gate]);
1029
1042
  }
@@ -1063,6 +1076,9 @@ class Model extends EmberObject {
1063
1076
  }
1064
1077
  return this.___recordState;
1065
1078
  }
1079
+ /**
1080
+ * `currentState` is read-only and cannot be set directly.
1081
+ */
1066
1082
  static {
1067
1083
  decorateMethodV2(this.prototype, "currentState", [gate]);
1068
1084
  }
@@ -1136,6 +1152,9 @@ class Model extends EmberObject {
1136
1152
  get adapterError() {
1137
1153
  return this.currentState.adapterError;
1138
1154
  }
1155
+ /**
1156
+ * `adapterError` is read-only and cannot be set directly.
1157
+ */
1139
1158
  static {
1140
1159
  decorateMethodV2(this.prototype, "adapterError", [memoized]);
1141
1160
  }
@@ -1209,12 +1228,29 @@ class Model extends EmberObject {
1209
1228
  eachRelationship(callback, binding) {
1210
1229
  this.constructor.eachRelationship(callback, binding);
1211
1230
  }
1231
+
1232
+ /**
1233
+ * Returns the relationship schema for the given relationship name, if any.
1234
+ */
1212
1235
  relationshipFor(name) {
1213
1236
  return this.constructor.relationshipsByName.get(name);
1214
1237
  }
1238
+
1239
+ /**
1240
+ * Returns the inverse relationship schema for the given relationship
1241
+ * name, if one exists. See {@link Model.inverseFor | the static inverseFor}.
1242
+ */
1215
1243
  inverseFor(name) {
1216
1244
  return this.constructor.inverseFor(name, storeFor(this, false));
1217
1245
  }
1246
+
1247
+ /**
1248
+ * Iterates over the attributes defined on this record's class, calling
1249
+ * `callback` for each one. See {@link Model.eachAttribute | the static eachAttribute}.
1250
+ *
1251
+ * @param callback the callback to invoke
1252
+ * @param binding the value to which the callback's `this` should be bound
1253
+ */
1218
1254
  eachAttribute(callback, binding) {
1219
1255
  this.constructor.eachAttribute(callback, binding);
1220
1256
  }
@@ -1286,6 +1322,11 @@ class Model extends EmberObject {
1286
1322
  const relationship = this.relationshipsByName.get(name);
1287
1323
  return relationship && store.modelFor(relationship.type);
1288
1324
  }
1325
+
1326
+ /**
1327
+ * A cache of resolved inverse relationships by name, populated lazily by
1328
+ * {@link Model.inverseFor | inverseFor}.
1329
+ */
1289
1330
  static get inverseMap() {
1290
1331
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1291
1332
  if (!test) {
@@ -1338,6 +1379,9 @@ class Model extends EmberObject {
1338
1379
  }
1339
1380
  }
1340
1381
 
1382
+ /**
1383
+ * @private
1384
+ */
1341
1385
  //Calculate the inverse, ignoring the cache
1342
1386
  static _findInverseFor(name, store) {
1343
1387
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
@@ -1568,6 +1612,12 @@ class Model extends EmberObject {
1568
1612
  }
1569
1613
  return map;
1570
1614
  }
1615
+
1616
+ /**
1617
+ * A hash of the model's relationship schemas keyed by relationship name.
1618
+ * See also {@link Model.relationshipsByName | relationshipsByName}, which
1619
+ * provides the same information as a `Map`.
1620
+ */
1571
1621
  static {
1572
1622
  decorateMethodV2(this, "relationshipsByName", [computeOnce]);
1573
1623
  }
@@ -1954,6 +2004,13 @@ defineGate(Model.prototype, 'isReloading', {
1954
2004
  // @ts-expect-error specially handled prop
1955
2005
  isLocal: true
1956
2006
  });
2007
+
2008
+ /**
2009
+ * Restores the pre-`RequestManager` implementations of `save`,
2010
+ * `destroyRecord`, and `reload` onto the given `Model` subclass, for
2011
+ * apps that have not yet migrated off of the deprecated
2012
+ * `ENABLE_LEGACY_REQUEST_METHODS` behaviors.
2013
+ */
1957
2014
  function restoreDeprecatedModelRequestBehaviors(ModelKlass) {
1958
2015
  // @ts-expect-error TS doesn't know how to do `this` function overloads
1959
2016
  ModelKlass.prototype.save = _save;
@@ -2147,7 +2204,11 @@ class ModelSchemaProvider {
2147
2204
  }
2148
2205
  /** @internal */
2149
2206
  _loadModelSchema(type) {
2150
- const modelClass = this.store.modelFor(type);
2207
+ const factory = getModelFactory(this.store, type);
2208
+ if (!factory) {
2209
+ throw new Error(`No model was found for '${type}'`);
2210
+ }
2211
+ const modelClass = factory.class;
2151
2212
  const attributeMap = modelClass.attributes;
2152
2213
  const attributes = Object.create(null);
2153
2214
  attributeMap.forEach((meta, name) => attributes[name] = meta);
@@ -2168,11 +2229,22 @@ class ModelSchemaProvider {
2168
2229
  type,
2169
2230
  fields: Array.from(fields.values())
2170
2231
  };
2232
+ const cacheFields = new Map();
2233
+ for (const field of fields.values()) {
2234
+ const cacheKey = field.sourceKey ?? field.name;
2235
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2236
+ if (!test) {
2237
+ throw new Error(`The sourceKey '${field.sourceKey}' for the field '${field.name}' on '${type}' is invalid because it matches the name of an existing field`);
2238
+ }
2239
+ })(!field.sourceKey || field.sourceKey === field.name || !fields.has(field.sourceKey)) : {};
2240
+ cacheFields.set(cacheKey, field);
2241
+ }
2171
2242
  const internalSchema = {
2172
2243
  schema,
2173
2244
  attributes,
2174
2245
  relationships,
2175
- fields
2246
+ fields,
2247
+ cacheFields
2176
2248
  };
2177
2249
  this._schemas.set(type, internalSchema);
2178
2250
  return internalSchema;
@@ -2184,6 +2256,13 @@ class ModelSchemaProvider {
2184
2256
  }
2185
2257
  return this._schemas.get(type).fields;
2186
2258
  }
2259
+ cacheFields(resource) {
2260
+ const type = normalizeModelName(resource.type);
2261
+ if (!this._schemas.has(type)) {
2262
+ this._loadModelSchema(type);
2263
+ }
2264
+ return this._schemas.get(type).cacheFields;
2265
+ }
2187
2266
  hasResource(resource) {
2188
2267
  const type = normalizeModelName(resource.type);
2189
2268
  if (this._schemas.has(type)) {
@@ -2259,6 +2338,14 @@ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.ENABLE_LEGACY_SCHEMA
2259
2338
  return this._schemas.get(type).relationships;
2260
2339
  };
2261
2340
  }
2341
+
2342
+ /**
2343
+ * The `createSchemaService` implementation for use with `Model`. Pass
2344
+ * the result of this to your store's `createSchemaService` method when
2345
+ * configuring the store to use `Model` for schema information.
2346
+ *
2347
+ * @public
2348
+ */
2262
2349
  function buildSchema(store) {
2263
2350
  return new ModelSchemaProvider(store);
2264
2351
  }