@ember-data/model 5.6.0-alpha.2 → 5.6.0-alpha.4

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 (45) hide show
  1. package/dist/-private.js +1 -2
  2. package/dist/-private.js.map +1 -1
  3. package/dist/{model-Dkk-TZlL.js → errors-DsUSZ9m8.js} +41 -2335
  4. package/dist/errors-DsUSZ9m8.js.map +1 -0
  5. package/dist/{hooks-o1U_cEA3.js → hooks-rXIjX2-H.js} +1 -2
  6. package/dist/{hooks-o1U_cEA3.js.map → hooks-rXIjX2-H.js.map} +1 -1
  7. package/dist/hooks.js +2 -2
  8. package/dist/index.js +667 -5
  9. package/dist/index.js.map +1 -1
  10. package/dist/migration-support.js +7 -14
  11. package/dist/migration-support.js.map +1 -1
  12. package/dist/schema-provider-B6-5uzxP.js +2229 -0
  13. package/dist/schema-provider-B6-5uzxP.js.map +1 -0
  14. package/package.json +16 -19
  15. package/unstable-preview-types/-private/attr.d.ts +4 -12
  16. package/unstable-preview-types/-private/attr.d.ts.map +1 -1
  17. package/unstable-preview-types/-private/belongs-to.d.ts +0 -6
  18. package/unstable-preview-types/-private/belongs-to.d.ts.map +1 -1
  19. package/unstable-preview-types/-private/errors.d.ts +4 -15
  20. package/unstable-preview-types/-private/errors.d.ts.map +1 -1
  21. package/unstable-preview-types/-private/has-many.d.ts +0 -3
  22. package/unstable-preview-types/-private/has-many.d.ts.map +1 -1
  23. package/unstable-preview-types/-private/model.d.ts +531 -562
  24. package/unstable-preview-types/-private/model.d.ts.map +1 -1
  25. package/unstable-preview-types/-private/promise-belongs-to.d.ts +0 -4
  26. package/unstable-preview-types/-private/promise-belongs-to.d.ts.map +1 -1
  27. package/unstable-preview-types/-private/promise-many-array.d.ts +3 -11
  28. package/unstable-preview-types/-private/promise-many-array.d.ts.map +1 -1
  29. package/unstable-preview-types/-private/references/belongs-to.d.ts +3 -12
  30. package/unstable-preview-types/-private/references/belongs-to.d.ts.map +1 -1
  31. package/unstable-preview-types/-private/references/has-many.d.ts +7 -19
  32. package/unstable-preview-types/-private/references/has-many.d.ts.map +1 -1
  33. package/unstable-preview-types/-private/type-utils.d.ts +0 -5
  34. package/unstable-preview-types/-private/type-utils.d.ts.map +1 -1
  35. package/unstable-preview-types/-private.d.ts +0 -4
  36. package/unstable-preview-types/-private.d.ts.map +1 -1
  37. package/unstable-preview-types/index.d.ts +23 -20
  38. package/unstable-preview-types/index.d.ts.map +1 -1
  39. package/unstable-preview-types/migration-support.d.ts +4 -10
  40. package/unstable-preview-types/migration-support.d.ts.map +1 -1
  41. package/dist/has-many-BXU96bZ9.js +0 -682
  42. package/dist/has-many-BXU96bZ9.js.map +0 -1
  43. package/dist/model-Dkk-TZlL.js.map +0 -1
  44. package/dist/schema-provider-DyG6fJXt.js +0 -259
  45. package/dist/schema-provider-DyG6fJXt.js.map +0 -1
@@ -1,50 +1,14 @@
1
- import { deprecate } from '@ember/debug';
2
- import { dasherize } from '@ember-data/request-utils/string';
3
1
  import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
4
- import EmberObject, { computed, get } from '@ember/object';
5
- import { recordIdentifierFor as recordIdentifierFor$1, storeFor as storeFor$1 } from '@ember-data/store';
6
- import { memoized, defineSignal, defineNonEnumerableSignal, isStableIdentifier, recordIdentifierFor, storeFor, peekCache, SOURCE, fastPush, RelatedCollection, notifyInternalSignal, ARRAY_SIGNAL, peekInternalSignal, withSignalStore, gate, coerceId, entangleSignal } from '@ember-data/store/-private';
7
- import { RecordStore } from '@warp-drive/core-types/symbols';
8
- import { A } from '@ember/array';
9
- import ArrayProxy from '@ember/array/proxy';
10
- import { mapBy, not } from '@ember/object/computed';
11
2
  import { upgradeStore } from '@ember-data/legacy-compat/-private';
3
+ import { memoized, defineSignal, defineNonEnumerableSignal, isStableIdentifier, recordIdentifierFor, storeFor, peekCache, SOURCE, fastPush, RelatedCollection, notifyInternalSignal, ARRAY_SIGNAL } from '@ember-data/store/-private';
12
4
  import { getOrSetGlobal } from '@warp-drive/core-types/-private';
13
5
  import { EnableHydration } from '@warp-drive/core-types/request';
6
+ import { computed, get } from '@ember/object';
14
7
  import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
15
8
  import ObjectProxy from '@ember/object/proxy';
16
- import { cacheFor } from '@ember/object/internals';
17
- function isElementDescriptor(args) {
18
- const [maybeTarget, maybeKey, maybeDesc] = args;
19
- return (
20
- // Ensure we have the right number of args
21
- args.length === 3 && (
22
- // Make sure the target is a class or object (prototype)
23
- typeof maybeTarget === 'function' || typeof maybeTarget === 'object' && maybeTarget !== null) &&
24
- // Make sure the key is a string
25
- typeof maybeKey === 'string' && (
26
- // Make sure the descriptor is the right shape
27
- typeof maybeDesc === 'object' && maybeDesc !== null && 'enumerable' in maybeDesc && 'configurable' in maybeDesc ||
28
- // TS compatibility
29
- maybeDesc === undefined)
30
- );
31
- }
32
- function normalizeModelName(type) {
33
- if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_NON_STRICT_TYPES)) {
34
- const result = dasherize(type);
35
- deprecate(`The resource type '${type}' is not normalized. Update your application code to use '${result}' instead of '${type}'.`, result === type, {
36
- id: 'ember-data:deprecate-non-strict-types',
37
- until: '6.0',
38
- for: 'ember-data',
39
- since: {
40
- available: '4.13',
41
- enabled: '5.3'
42
- }
43
- });
44
- return result;
45
- }
46
- return type;
47
- }
9
+ import { A } from '@ember/array';
10
+ import ArrayProxy from '@ember/array/proxy';
11
+ import { mapBy, not } from '@ember/object/computed';
48
12
  const PromiseObject = ObjectProxy.extend(PromiseProxyMixin);
49
13
  const deferred = /* @__PURE__ */new WeakMap();
50
14
  function deferDecorator(proto, prop, desc) {
@@ -116,17 +80,12 @@ const LegacyPromiseProxy = Symbol.for('LegacyPromiseProxy');
116
80
 
117
81
  const Extended = PromiseObject;
118
82
 
119
- /**
120
- @module @ember-data/model
121
- */
122
-
123
83
  /**
124
84
  A PromiseBelongsTo is a PromiseObject that also proxies certain method calls
125
85
  to the underlying belongsTo model.
126
86
  Right now we proxy:
127
87
  * `reload()`
128
88
  @class PromiseBelongsTo
129
- @extends PromiseObject
130
89
  @private
131
90
  */
132
91
  class PromiseBelongsTo extends Extended {
@@ -175,9 +134,6 @@ class PromiseBelongsTo extends Extended {
175
134
  [LegacyPromiseProxy] = true;
176
135
  }
177
136
 
178
- /**
179
- @module @ember-data/model
180
- */
181
137
  /**
182
138
  This class is returned as the result of accessing an async hasMany relationship
183
139
  on an instance of a Model extending from `@ember-data/model`.
@@ -235,7 +191,6 @@ class PromiseManyArray {
235
191
  * We do not guarantee that forEach will always be available. This
236
192
  * may eventually be made to use Symbol.Iterator once glimmer supports it.
237
193
  *
238
- * @method forEach
239
194
  * @param cb
240
195
  * @return
241
196
  * @private
@@ -251,7 +206,6 @@ class PromiseManyArray {
251
206
 
252
207
  /**
253
208
  * Reload the relationship
254
- * @method reload
255
209
  * @public
256
210
  * @param options
257
211
  * @return
@@ -303,11 +257,10 @@ class PromiseManyArray {
303
257
  /**
304
258
  * chain this promise
305
259
  *
306
- * @method then
307
260
  * @public
308
261
  * @param success
309
262
  * @param fail
310
- * @return Promise
263
+ * @return {Promise}
311
264
  */
312
265
  then(s, f) {
313
266
  return this.promise.then(s, f);
@@ -315,10 +268,9 @@ class PromiseManyArray {
315
268
 
316
269
  /**
317
270
  * catch errors thrown by this promise
318
- * @method catch
319
271
  * @public
320
272
  * @param callback
321
- * @return Promise
273
+ * @return {Promise}
322
274
  */
323
275
  catch(cb) {
324
276
  return this.promise.catch(cb);
@@ -327,10 +279,9 @@ class PromiseManyArray {
327
279
  /**
328
280
  * run cleanup after this promise completes
329
281
  *
330
- * @method finally
331
282
  * @public
332
283
  * @param callback
333
- * @return Promise
284
+ * @return {Promise}
334
285
  */
335
286
  finally(cb) {
336
287
  return this.promise.finally(cb);
@@ -577,7 +528,7 @@ class HasManyReference {
577
528
  looked up when it is loaded. If the relationship has a link it will
578
529
  use the "link" otherwise it defaults to "id".
579
530
  Example
580
- ```app/models/post.js
531
+ ```js [app/models/post.js]
581
532
  import Model, { hasMany } from '@ember-data/model';
582
533
  export default class PostModel extends Model {
583
534
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -603,8 +554,7 @@ class HasManyReference {
603
554
  let link = commentsRef.link();
604
555
  }
605
556
  ```
606
- @method remoteType
607
- @public
557
+ @public
608
558
  @return {String} The name of the remote type. This should either be `link` or `ids`
609
559
  */
610
560
  remoteType() {
@@ -618,7 +568,7 @@ class HasManyReference {
618
568
  /**
619
569
  `ids()` returns an array of the record IDs in this relationship.
620
570
  Example
621
- ```app/models/post.js
571
+ ```js [app/models/post.js]
622
572
  import Model, { hasMany } from '@ember-data/model';
623
573
  export default class PostModel extends Model {
624
574
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -639,8 +589,7 @@ class HasManyReference {
639
589
  let commentsRef = post.hasMany('comments');
640
590
  commentsRef.ids(); // ['1']
641
591
  ```
642
- @method ids
643
- @public
592
+ @public
644
593
  @return {Array} The ids in this has-many relationship
645
594
  */
646
595
  ids() {
@@ -676,8 +625,7 @@ class HasManyReference {
676
625
  let link = userRef.link();
677
626
  }
678
627
  ```
679
- @method link
680
- @public
628
+ @public
681
629
  @return {String} The link Ember Data will use to fetch or reload this belongs-to relationship.
682
630
  */
683
631
  link() {
@@ -694,7 +642,6 @@ class HasManyReference {
694
642
  /**
695
643
  * any links that have been received for this relationship
696
644
  *
697
- * @method links
698
645
  * @public
699
646
  * @return
700
647
  */
@@ -733,8 +680,7 @@ class HasManyReference {
733
680
  let usersRef = blog.hasMany('user');
734
681
  usersRef.meta() // { lastUpdated: 1458014400000 }
735
682
  ```
736
- @method meta
737
- @public
683
+ @public
738
684
  @return {Object|null} The meta information for the belongs-to relationship.
739
685
  */
740
686
  meta() {
@@ -752,7 +698,7 @@ class HasManyReference {
752
698
  the backend. An empty array will signify the canonical value should be
753
699
  empty.
754
700
  Example model
755
- ```app/models/post.js
701
+ ```js [app/models/post.js]
756
702
  import Model, { hasMany } from '@ember-data/model';
757
703
  export default class PostModel extends Model {
758
704
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -820,8 +766,7 @@ class HasManyReference {
820
766
  and instead the promise will resolve with void without attempting to fetch. This is
821
767
  particularly useful if you want to update the state of the relationship without
822
768
  forcing the load of all of the associated records.
823
- @method push
824
- @public
769
+ @public
825
770
  @param {Array|Object} doc a JSONAPI document object describing the new value of this relationship.
826
771
  @param {Boolean} [skipFetch] if `true`, do not attempt to fetch unloaded records
827
772
  @return {Promise<ManyArray | void>}
@@ -890,7 +835,7 @@ class HasManyReference {
890
835
  relationship is not yet loaded. If the relationship is not loaded
891
836
  it will always return `null`.
892
837
  Example
893
- ```app/models/post.js
838
+ ```js [app/models/post.js]
894
839
  import Model, { hasMany } from '@ember-data/model';
895
840
  export default class PostModel extends Model {
896
841
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -913,8 +858,7 @@ class HasManyReference {
913
858
  commentsRef.value() === comments
914
859
  })
915
860
  ```
916
- @method value
917
- @public
861
+ @public
918
862
  @return {ManyArray}
919
863
  */
920
864
  value() {
@@ -933,7 +877,7 @@ class HasManyReference {
933
877
  load. This causes a request to the specified
934
878
  relationship link or reloads all items currently in the relationship.
935
879
  Example
936
- ```app/models/post.js
880
+ ```js [app/models/post.js]
937
881
  import Model, { hasMany } from '@ember-data/model';
938
882
  export default class PostModel extends Model {
939
883
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -966,7 +910,7 @@ class HasManyReference {
966
910
  //...
967
911
  });
968
912
  ```
969
- ```app/adapters/comment.js
913
+ ```js [app/adapters/comment.js]
970
914
  export default ApplicationAdapter.extend({
971
915
  findMany(store, type, id, snapshots) {
972
916
  // In the adapter you will have access to adapterOptions.
@@ -974,8 +918,7 @@ class HasManyReference {
974
918
  }
975
919
  });
976
920
  ```
977
- @method load
978
- @public
921
+ @public
979
922
  @param {Object} options the options to pass in.
980
923
  @return {Promise} a promise that resolves with the ManyArray in
981
924
  this has-many relationship.
@@ -993,7 +936,7 @@ class HasManyReference {
993
936
  Reloads this has-many relationship. This causes a request to the specified
994
937
  relationship link or reloads all items currently in the relationship.
995
938
  Example
996
- ```app/models/post.js
939
+ ```js [app/models/post.js]
997
940
  import Model, { hasMany } from '@ember-data/model';
998
941
  export default class PostModel extends Model {
999
942
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -1024,8 +967,7 @@ class HasManyReference {
1024
967
  ```javascript
1025
968
  commentsRef.reload({ adapterOptions: { isPrivate: true } })
1026
969
  ```
1027
- @method reload
1028
- @public
970
+ @public
1029
971
  @param {Object} options the options to pass in.
1030
972
  @return {Promise} a promise that resolves with the ManyArray in this has-many relationship.
1031
973
  */
@@ -1193,8 +1135,7 @@ class BelongsToReference {
1193
1135
  let id = userRef.id();
1194
1136
  }
1195
1137
  ```
1196
- @method id
1197
- @public
1138
+ @public
1198
1139
  @return {String} The id of the record in this belongsTo relationship.
1199
1140
  */
1200
1141
  static {
@@ -1233,8 +1174,7 @@ class BelongsToReference {
1233
1174
  let link = userRef.link();
1234
1175
  }
1235
1176
  ```
1236
- @method link
1237
- @public
1177
+ @public
1238
1178
  @return {String} The link Ember Data will use to fetch or reload this belongs-to relationship.
1239
1179
  */
1240
1180
  link() {
@@ -1251,7 +1191,6 @@ class BelongsToReference {
1251
1191
  /**
1252
1192
  * any links that have been received for this relationship
1253
1193
  *
1254
- * @method links
1255
1194
  * @public
1256
1195
  * @return
1257
1196
  */
@@ -1290,8 +1229,7 @@ class BelongsToReference {
1290
1229
  let userRef = blog.belongsTo('user');
1291
1230
  userRef.meta() // { lastUpdated: 1458014400000 }
1292
1231
  ```
1293
- @method meta
1294
- @public
1232
+ @public
1295
1233
  @return {Object} The meta information for the belongs-to relationship.
1296
1234
  */
1297
1235
  meta() {
@@ -1314,7 +1252,7 @@ class BelongsToReference {
1314
1252
  looked up when it is loaded. If the relationship has a link it will
1315
1253
  use the "link" otherwise it defaults to "id".
1316
1254
  Example
1317
- ```app/models/post.js
1255
+ ```js [app/models/post.js]
1318
1256
  import Model, { hasMany } from '@ember-data/model';
1319
1257
  export default class PostModel extends Model {
1320
1258
  @hasMany('comment', { async: true, inverse: null }) comments;
@@ -1340,8 +1278,7 @@ class BelongsToReference {
1340
1278
  let link = commentsRef.link();
1341
1279
  }
1342
1280
  ```
1343
- @method remoteType
1344
- @public
1281
+ @public
1345
1282
  @return {String} The name of the remote type. This should either be `link` or `id`
1346
1283
  */
1347
1284
  remoteType() {
@@ -1358,7 +1295,7 @@ class BelongsToReference {
1358
1295
  the backend. A value of `null` (e.g. `{ data: null }`) can be passed to
1359
1296
  clear the relationship.
1360
1297
  Example model
1361
- ```app/models/blog.js
1298
+ ```js [app/models/blog.js]
1362
1299
  import Model, { belongsTo } from '@ember-data/model';
1363
1300
  export default class BlogModel extends Model {
1364
1301
  @belongsTo('user', { async: true, inverse: null }) user;
@@ -1424,8 +1361,7 @@ class BelongsToReference {
1424
1361
  and instead the promise will resolve with void without attempting to fetch. This is
1425
1362
  particularly useful if you want to update the state of the relationship without
1426
1363
  forcing the load of all of the associated record.
1427
- @method push
1428
- @public
1364
+ @public
1429
1365
  @param {Object} doc a JSONAPI document object describing the new value of this relationship.
1430
1366
  @param {Boolean} [skipFetch] if `true`, do not attempt to fetch unloaded records
1431
1367
  @return {Promise<OpaqueRecordInstance | null | void>}
@@ -1506,8 +1442,7 @@ class BelongsToReference {
1506
1442
  userRef.value(); // user
1507
1443
  });
1508
1444
  ```
1509
- @method value
1510
- @public
1445
+ @public
1511
1446
  @return {Model} the record in this relationship
1512
1447
  */
1513
1448
  value() {
@@ -1552,7 +1487,7 @@ class BelongsToReference {
1552
1487
  userRef.value() === user;
1553
1488
  });
1554
1489
  ```
1555
- ```app/adapters/user.js
1490
+ ```js [app/adapters/user.js]
1556
1491
  import Adapter from '@ember-data/adapter';
1557
1492
  export default class UserAdapter extends Adapter {
1558
1493
  findRecord(store, type, id, snapshot) {
@@ -1561,8 +1496,7 @@ class BelongsToReference {
1561
1496
  }
1562
1497
  });
1563
1498
  ```
1564
- @method load
1565
- @public
1499
+ @public
1566
1500
  @param {Object} options the options to pass in.
1567
1501
  @return {Promise} a promise that resolves with the record in this belongs-to relationship.
1568
1502
  */
@@ -1611,8 +1545,7 @@ class BelongsToReference {
1611
1545
  ```javascript
1612
1546
  userRef.reload({ adapterOptions: { isPrivate: true } })
1613
1547
  ```
1614
- @method reload
1615
- @public
1548
+ @public
1616
1549
  @param {Object} options the options to pass in.
1617
1550
  @return {Promise} a promise that resolves with the record in this belongs-to relationship after the reload has completed.
1618
1551
  */
@@ -2329,7 +2262,7 @@ const ArrayProxyWithCustomOverrides = ArrayProxy;
2329
2262
 
2330
2263
  For Example, if you had a `User` model that looked like this:
2331
2264
 
2332
- ```app/models/user.js
2265
+ ```js [app/models/user.js]
2333
2266
  import Model, { attr } from '@ember-data/model';
2334
2267
 
2335
2268
  export default class UserModel extends Model {
@@ -2391,7 +2324,6 @@ const ArrayProxyWithCustomOverrides = ArrayProxy;
2391
2324
 
2392
2325
  @class Errors
2393
2326
  @public
2394
- @extends Ember.ArrayProxy
2395
2327
  */
2396
2328
  class Errors extends ArrayProxyWithCustomOverrides {
2397
2329
  /**
@@ -2415,8 +2347,7 @@ class Errors extends ArrayProxyWithCustomOverrides {
2415
2347
  // [{attribute: "email", message: "Doesn't look like a valid email."}]
2416
2348
  });
2417
2349
  ```
2418
- @method errorsFor
2419
- @public
2350
+ @public
2420
2351
  @param {String} attribute
2421
2352
  @return {Array}
2422
2353
  */
@@ -2467,7 +2398,6 @@ class Errors extends ArrayProxyWithCustomOverrides {
2467
2398
  }
2468
2399
 
2469
2400
  /**
2470
- @method unknownProperty
2471
2401
  @private
2472
2402
  */
2473
2403
  static {
@@ -2486,7 +2416,7 @@ class Errors extends ArrayProxyWithCustomOverrides {
2486
2416
  @property length
2487
2417
  @type {Number}
2488
2418
  @public
2489
- @readOnly
2419
+ @readonly
2490
2420
  */
2491
2421
 
2492
2422
  /**
@@ -2494,7 +2424,7 @@ class Errors extends ArrayProxyWithCustomOverrides {
2494
2424
  @property isEmpty
2495
2425
  @type {Boolean}
2496
2426
  @public
2497
- @readOnly
2427
+ @readonly
2498
2428
  */
2499
2429
  static {
2500
2430
  decorateFieldV2(this.prototype, "isEmpty", [not('length')]);
@@ -2527,7 +2457,6 @@ class Errors extends ArrayProxyWithCustomOverrides {
2527
2457
  // { attribute: 'username', message: 'This field is required' },
2528
2458
  // ]
2529
2459
  ```
2530
- @method add
2531
2460
  @public
2532
2461
  @param {String} attribute - the property name of an attribute or relationship
2533
2462
  @param {string[]|string} messages - an error message or array of error messages for the attribute
@@ -2541,7 +2470,6 @@ class Errors extends ArrayProxyWithCustomOverrides {
2541
2470
  }
2542
2471
 
2543
2472
  /**
2544
- @method _findOrCreateMessages
2545
2473
  @private
2546
2474
  */
2547
2475
  _findOrCreateMessages(attribute, messages) {
@@ -2581,7 +2509,6 @@ class Errors extends ArrayProxyWithCustomOverrides {
2581
2509
  errors.errorsFor('phone');
2582
2510
  // => undefined
2583
2511
  ```
2584
- @method remove
2585
2512
  @public
2586
2513
  @param {String} member - the property name of an attribute or relationship
2587
2514
  */
@@ -2635,7 +2562,6 @@ class Errors extends ArrayProxyWithCustomOverrides {
2635
2562
  errors.messages
2636
2563
  // => []
2637
2564
  ```
2638
- @method clear
2639
2565
  @public
2640
2566
  */
2641
2567
  clear() {
@@ -2657,7 +2583,7 @@ class Errors extends ArrayProxyWithCustomOverrides {
2657
2583
 
2658
2584
  /**
2659
2585
  Checks if there are error messages for the given attribute.
2660
- ```app/controllers/user/edit.js
2586
+ ```js [app/controllers/user/edit.js]
2661
2587
  export default class UserEditController extends Controller {
2662
2588
  @action
2663
2589
  save(user) {
@@ -2668,8 +2594,7 @@ class Errors extends ArrayProxyWithCustomOverrides {
2668
2594
  }
2669
2595
  }
2670
2596
  ```
2671
- @method has
2672
- @public
2597
+ @public
2673
2598
  @param {String} attribute
2674
2599
  @return {Boolean} true if there some errors on given attribute
2675
2600
  */
@@ -2677,2223 +2602,4 @@ class Errors extends ArrayProxyWithCustomOverrides {
2677
2602
  return this.errorsFor(attribute).length > 0;
2678
2603
  }
2679
2604
  }
2680
- function rollbackAttributes() {
2681
- const {
2682
- currentState
2683
- } = this;
2684
- const {
2685
- isNew
2686
- } = currentState;
2687
- this[RecordStore]._join(() => {
2688
- peekCache(this).rollbackAttrs(recordIdentifierFor$1(this));
2689
- this.errors.clear();
2690
- currentState.cleanErrorRequests();
2691
- if (isNew) {
2692
- this.unloadRecord();
2693
- }
2694
- });
2695
- }
2696
- function unloadRecord() {
2697
- if (this.currentState.isNew && (this.isDestroyed || this.isDestroying)) {
2698
- return;
2699
- }
2700
- this[RecordStore].unloadRecord(this);
2701
- }
2702
- function belongsTo(prop) {
2703
- return lookupLegacySupport(this).referenceFor('belongsTo', prop);
2704
- }
2705
- function hasMany(prop) {
2706
- return lookupLegacySupport(this).referenceFor('hasMany', prop);
2707
- }
2708
- function reload(options = {}) {
2709
- options.isReloading = true;
2710
- options.reload = true;
2711
- const identifier = recordIdentifierFor$1(this);
2712
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2713
- if (!test) {
2714
- throw new Error(`You cannot reload a record without an ID`);
2715
- }
2716
- })(identifier.id) : {};
2717
- this.isReloading = true;
2718
- const promise = this[RecordStore].request({
2719
- op: 'findRecord',
2720
- data: {
2721
- options,
2722
- record: identifier
2723
- },
2724
- cacheOptions: {
2725
- [Symbol.for('wd:skip-cache')]: true
2726
- }
2727
- }).then(() => this).finally(() => {
2728
- this.isReloading = false;
2729
- });
2730
- return promise;
2731
- }
2732
- function changedAttributes() {
2733
- return peekCache(this).changedAttrs(recordIdentifierFor$1(this));
2734
- }
2735
- function serialize(options) {
2736
- upgradeStore(this[RecordStore]);
2737
- return this[RecordStore].serializeRecord(this, options);
2738
- }
2739
- function deleteRecord() {
2740
- // ensure we've populated currentState prior to deleting a new record
2741
- if (this.currentState) {
2742
- this[RecordStore].deleteRecord(this);
2743
- }
2744
- }
2745
- function save(options) {
2746
- let promise;
2747
- if (this.currentState.isNew && this.currentState.isDeleted) {
2748
- promise = Promise.resolve(this);
2749
- } else {
2750
- this.errors.clear();
2751
- promise = this[RecordStore].saveRecord(this, options);
2752
- }
2753
- return promise;
2754
- }
2755
- function destroyRecord(options) {
2756
- const {
2757
- isNew
2758
- } = this.currentState;
2759
- this.deleteRecord();
2760
- if (isNew) {
2761
- return Promise.resolve(this);
2762
- }
2763
- return this.save(options).then(_ => {
2764
- this.unloadRecord();
2765
- return this;
2766
- });
2767
- }
2768
- function createSnapshot() {
2769
- const store = this[RecordStore];
2770
- upgradeStore(store);
2771
- if (!store._fetchManager) {
2772
- const FetchManager = importSync('@ember-data/legacy-compat/-private').FetchManager;
2773
- store._fetchManager = new FetchManager(store);
2774
- }
2775
-
2776
- // @ts-expect-error Typescript isn't able to curry narrowed args that are divorced from each other.
2777
- return store._fetchManager.createSnapshot(recordIdentifierFor$1(this));
2778
- }
2779
- function notifyChanges(identifier, value, key, record, store) {
2780
- switch (value) {
2781
- case 'added':
2782
- case 'attributes':
2783
- if (key) {
2784
- notifyAttribute(store, identifier, key, record);
2785
- } else {
2786
- record.eachAttribute(name => {
2787
- notifyAttribute(store, identifier, name, record);
2788
- });
2789
- }
2790
- break;
2791
- case 'relationships':
2792
- if (key) {
2793
- const meta = record.constructor.relationshipsByName.get(key);
2794
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2795
- if (!test) {
2796
- throw new Error(`Expected to find a relationship for ${key} on ${identifier.type}`);
2797
- }
2798
- })(meta) : {};
2799
- notifyRelationship(identifier, key, record, meta);
2800
- } else {
2801
- record.eachRelationship((name, meta) => {
2802
- notifyRelationship(identifier, name, record, meta);
2803
- });
2804
- }
2805
- break;
2806
- case 'identity':
2807
- notifyInternalSignal(peekInternalSignal(withSignalStore(record), 'id'));
2808
- break;
2809
- }
2810
- }
2811
- function notifyRelationship(identifier, key, record, meta) {
2812
- if (meta.kind === 'belongsTo') {
2813
- record.notifyPropertyChange(key);
2814
- } else if (meta.kind === 'hasMany') {
2815
- const support = LEGACY_SUPPORT.get(identifier);
2816
- const manyArray = support && support._manyArrayCache[key];
2817
- const hasPromise = support && support._relationshipPromisesCache[key];
2818
- if (manyArray && hasPromise) {
2819
- // do nothing, we will notify the ManyArray directly
2820
- // once the fetch has completed.
2821
- return;
2822
- }
2823
- if (manyArray) {
2824
- notifyInternalSignal(manyArray[ARRAY_SIGNAL]);
2825
-
2826
- //We need to notifyPropertyChange in the adding case because we need to make sure
2827
- //we fetch the newly added record in case it is unloaded
2828
- //TODO(Igor): Consider whether we could do this only if the record state is unloaded
2829
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2830
- if (!test) {
2831
- throw new Error(`Expected options to exist on relationship meta`);
2832
- }
2833
- })(meta.options) : {};
2834
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2835
- if (!test) {
2836
- throw new Error(`Expected async to exist on relationship meta options`);
2837
- }
2838
- })('async' in meta.options) : {};
2839
- if (meta.options.async) {
2840
- record.notifyPropertyChange(key);
2841
- }
2842
- }
2843
- }
2844
- }
2845
- function notifyAttribute(store, identifier, key, record) {
2846
- const currentValue = cacheFor(record, key);
2847
- const cache = store.cache;
2848
- if (currentValue !== cache.getAttr(identifier, key)) {
2849
- record.notifyPropertyChange(key);
2850
- }
2851
- }
2852
- const SOURCE_POINTER_REGEXP = /^\/?data\/(attributes|relationships)\/(.*)/;
2853
- const SOURCE_POINTER_PRIMARY_REGEXP = /^\/?data/;
2854
- const PRIMARY_ATTRIBUTE_KEY = 'base';
2855
- function isInvalidError(error) {
2856
- return !!error && error instanceof Error && 'isAdapterError' in error && error.isAdapterError === true && 'code' in error && error.code === 'InvalidError';
2857
- }
2858
-
2859
- /**
2860
- Historically EmberData managed a state machine
2861
- for each record, the localState for which
2862
- was reflected onto Model.
2863
-
2864
- This implements the flags and stateName for backwards compat
2865
- with the state tree that used to be possible (listed below).
2866
-
2867
- stateName and dirtyType are candidates for deprecation.
2868
-
2869
- root
2870
- empty
2871
- deleted // hidden from stateName
2872
- preloaded // hidden from stateName
2873
-
2874
- loading
2875
- empty // hidden from stateName
2876
- preloaded // hidden from stateName
2877
-
2878
- loaded
2879
- saved
2880
- updated
2881
- uncommitted
2882
- invalid
2883
- inFlight
2884
- created
2885
- uncommitted
2886
- invalid
2887
- inFlight
2888
-
2889
- deleted
2890
- saved
2891
- new // hidden from stateName
2892
- uncommitted
2893
- invalid
2894
- inFlight
2895
-
2896
- @internal
2897
- */
2898
- class RecordState {
2899
- constructor(record) {
2900
- const store = storeFor$1(record);
2901
- const identity = recordIdentifierFor(record);
2902
- this.identifier = identity;
2903
- this.record = record;
2904
- this.cache = store.cache;
2905
- this.pendingCount = 0;
2906
- this.fulfilledCount = 0;
2907
- this.rejectedCount = 0;
2908
- this._errorRequests = [];
2909
- this._lastError = null;
2910
- const requests = store.getRequestStateService();
2911
- const notifications = store.notifications;
2912
- const handleRequest = req => {
2913
- if (req.type === 'mutation') {
2914
- switch (req.state) {
2915
- case 'pending':
2916
- this.isSaving = true;
2917
- break;
2918
- case 'rejected':
2919
- this.isSaving = false;
2920
- this._lastError = req;
2921
- if (!(req.response && isInvalidError(req.response.data))) {
2922
- this._errorRequests.push(req);
2923
- }
2924
- notifyErrorsStateChanged(this);
2925
- break;
2926
- case 'fulfilled':
2927
- this._errorRequests = [];
2928
- this._lastError = null;
2929
- this.isSaving = false;
2930
- this.notify('isDirty');
2931
- notifyErrorsStateChanged(this);
2932
- break;
2933
- }
2934
- } else {
2935
- switch (req.state) {
2936
- case 'pending':
2937
- this.pendingCount++;
2938
- this.notify('isLoading');
2939
- break;
2940
- case 'rejected':
2941
- this.pendingCount--;
2942
- this._lastError = req;
2943
- if (!(req.response && isInvalidError(req.response.data))) {
2944
- this._errorRequests.push(req);
2945
- }
2946
- this.notify('isLoading');
2947
- notifyErrorsStateChanged(this);
2948
- break;
2949
- case 'fulfilled':
2950
- this.pendingCount--;
2951
- this.fulfilledCount++;
2952
- this.notify('isLoading');
2953
- this.notify('isDirty');
2954
- notifyErrorsStateChanged(this);
2955
- this._errorRequests = [];
2956
- this._lastError = null;
2957
- break;
2958
- }
2959
- }
2960
- };
2961
- requests.subscribeForRecord(identity, handleRequest);
2962
-
2963
- // we instantiate lazily
2964
- // so we grab anything we don't have yet
2965
- const lastRequest = requests.getLastRequestForRecord(identity);
2966
- if (lastRequest) {
2967
- handleRequest(lastRequest);
2968
- }
2969
- this.handler = notifications.subscribe(identity, (identifier, type, key) => {
2970
- switch (type) {
2971
- case 'state':
2972
- this.notify('isSaved');
2973
- this.notify('isNew');
2974
- this.notify('isDeleted');
2975
- this.notify('isDirty');
2976
- break;
2977
- case 'attributes':
2978
- this.notify('isEmpty');
2979
- this.notify('isDirty');
2980
- break;
2981
- case 'errors':
2982
- this.updateInvalidErrors(this.record.errors);
2983
- this.notify('isValid');
2984
- break;
2985
- }
2986
- });
2987
- }
2988
- destroy() {
2989
- storeFor$1(this.record).notifications.unsubscribe(this.handler);
2990
- }
2991
- notify(key) {
2992
- const signals = withSignalStore(this);
2993
- const signal = peekInternalSignal(signals, key);
2994
- if (signal) {
2995
- notifyInternalSignal(signal);
2996
- }
2997
- }
2998
- updateInvalidErrors(errors) {
2999
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3000
- if (!test) {
3001
- throw new Error(`Expected the Cache instance for ${this.identifier.lid} to implement getErrors(identifier)`);
3002
- }
3003
- })(typeof this.cache.getErrors === 'function') : {};
3004
- const jsonApiErrors = this.cache.getErrors(this.identifier);
3005
- errors.clear();
3006
- for (let i = 0; i < jsonApiErrors.length; i++) {
3007
- const error = jsonApiErrors[i];
3008
- if (error.source && error.source.pointer) {
3009
- const keyMatch = error.source.pointer.match(SOURCE_POINTER_REGEXP);
3010
- let key;
3011
- if (keyMatch) {
3012
- key = keyMatch[2];
3013
- } else if (error.source.pointer.search(SOURCE_POINTER_PRIMARY_REGEXP) !== -1) {
3014
- key = PRIMARY_ATTRIBUTE_KEY;
3015
- }
3016
- if (key) {
3017
- const errMsg = error.detail || error.title;
3018
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3019
- if (!test) {
3020
- throw new Error(`Expected field error to have a detail or title to use as the message`);
3021
- }
3022
- })(errMsg) : {};
3023
- errors.add(key, errMsg);
3024
- }
3025
- }
3026
- }
3027
- }
3028
- cleanErrorRequests() {
3029
- this.notify('isValid');
3030
- this.notify('isError');
3031
- this.notify('adapterError');
3032
- this._errorRequests = [];
3033
- this._lastError = null;
3034
- }
3035
- get isLoading() {
3036
- return !this.isLoaded && this.pendingCount > 0 && this.fulfilledCount === 0;
3037
- }
3038
- static {
3039
- decorateMethodV2(this.prototype, "isLoading", [gate]);
3040
- }
3041
- get isLoaded() {
3042
- if (this.isNew) {
3043
- return true;
3044
- }
3045
- return this.fulfilledCount > 0 || !this.isEmpty;
3046
- }
3047
- static {
3048
- decorateMethodV2(this.prototype, "isLoaded", [gate]);
3049
- }
3050
- get isSaved() {
3051
- const rd = this.cache;
3052
- if (this.isDeleted) {
3053
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3054
- if (!test) {
3055
- throw new Error(`Expected Cache to implement isDeletionCommitted()`);
3056
- }
3057
- })(typeof rd.isDeletionCommitted === 'function') : {};
3058
- return rd.isDeletionCommitted(this.identifier);
3059
- }
3060
- if (this.isNew || this.isEmpty || !this.isValid || this.isDirty || this.isLoading) {
3061
- return false;
3062
- }
3063
- return true;
3064
- }
3065
- static {
3066
- decorateMethodV2(this.prototype, "isSaved", [gate]);
3067
- }
3068
- get isEmpty() {
3069
- const rd = this.cache;
3070
- // TODO this is not actually an RFC'd concept. Determine the
3071
- // correct heuristic to replace this with.
3072
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3073
- if (!test) {
3074
- throw new Error(`Expected Cache to implement isEmpty()`);
3075
- }
3076
- })(typeof rd.isEmpty === 'function') : {};
3077
- return !this.isNew && rd.isEmpty(this.identifier);
3078
- }
3079
- static {
3080
- decorateMethodV2(this.prototype, "isEmpty", [gate]);
3081
- }
3082
- get isNew() {
3083
- const rd = this.cache;
3084
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3085
- if (!test) {
3086
- throw new Error(`Expected Cache to implement isNew()`);
3087
- }
3088
- })(typeof rd.isNew === 'function') : {};
3089
- return rd.isNew(this.identifier);
3090
- }
3091
- static {
3092
- decorateMethodV2(this.prototype, "isNew", [gate]);
3093
- }
3094
- get isDeleted() {
3095
- const rd = this.cache;
3096
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3097
- if (!test) {
3098
- throw new Error(`Expected Cache to implement isDeleted()`);
3099
- }
3100
- })(typeof rd.isDeleted === 'function') : {};
3101
- return rd.isDeleted(this.identifier);
3102
- }
3103
- static {
3104
- decorateMethodV2(this.prototype, "isDeleted", [gate]);
3105
- }
3106
- get isValid() {
3107
- return this.record.errors.length === 0;
3108
- }
3109
- static {
3110
- decorateMethodV2(this.prototype, "isValid", [gate]);
3111
- }
3112
- get isDirty() {
3113
- const rd = this.cache;
3114
- if (this.isEmpty || rd.isDeletionCommitted(this.identifier) || this.isDeleted && this.isNew) {
3115
- return false;
3116
- }
3117
- return this.isDeleted || this.isNew || rd.hasChangedAttrs(this.identifier);
3118
- }
3119
- static {
3120
- decorateMethodV2(this.prototype, "isDirty", [gate]);
3121
- }
3122
- get isError() {
3123
- const errorReq = this._errorRequests[this._errorRequests.length - 1];
3124
- if (!errorReq) {
3125
- return false;
3126
- } else {
3127
- return true;
3128
- }
3129
- }
3130
- static {
3131
- decorateMethodV2(this.prototype, "isError", [gate]);
3132
- }
3133
- get adapterError() {
3134
- const request = this._lastError;
3135
- if (!request) {
3136
- return null;
3137
- }
3138
- return request.state === 'rejected' && request.response.data;
3139
- }
3140
- static {
3141
- decorateMethodV2(this.prototype, "adapterError", [gate]);
3142
- }
3143
- get isPreloaded() {
3144
- return !this.isEmpty && this.isLoading;
3145
- }
3146
- static {
3147
- decorateMethodV2(this.prototype, "isPreloaded", [memoized]);
3148
- }
3149
- get stateName() {
3150
- // we might be empty while loading so check this first
3151
- if (this.isLoading) {
3152
- return 'root.loading';
3153
-
3154
- // got nothing yet or were unloaded
3155
- } else if (this.isEmpty) {
3156
- return 'root.empty';
3157
-
3158
- // deleted substates
3159
- } else if (this.isDeleted) {
3160
- if (this.isSaving) {
3161
- return 'root.deleted.inFlight';
3162
- } else if (this.isSaved) {
3163
- // TODO ensure isSaved isn't true from previous requests
3164
- return 'root.deleted.saved';
3165
- } else if (!this.isValid) {
3166
- return 'root.deleted.invalid';
3167
- } else {
3168
- return 'root.deleted.uncommitted';
3169
- }
3170
-
3171
- // loaded.created substates
3172
- } else if (this.isNew) {
3173
- if (this.isSaving) {
3174
- return 'root.loaded.created.inFlight';
3175
- } else if (!this.isValid) {
3176
- return 'root.loaded.created.invalid';
3177
- }
3178
- return 'root.loaded.created.uncommitted';
3179
-
3180
- // loaded.updated substates
3181
- } else if (this.isSaving) {
3182
- return 'root.loaded.updated.inFlight';
3183
- } else if (!this.isValid) {
3184
- return 'root.loaded.updated.invalid';
3185
- } else if (this.isDirty) {
3186
- return 'root.loaded.updated.uncommitted';
3187
-
3188
- // if nothing remains, we are loaded saved!
3189
- } else {
3190
- return 'root.loaded.saved';
3191
- }
3192
- }
3193
- static {
3194
- decorateMethodV2(this.prototype, "stateName", [memoized]);
3195
- }
3196
- get dirtyType() {
3197
- // we might be empty while loading so check this first
3198
- if (this.isLoading || this.isEmpty) {
3199
- return '';
3200
-
3201
- // deleted substates
3202
- } else if (this.isDirty && this.isDeleted) {
3203
- return 'deleted';
3204
-
3205
- // loaded.created substates
3206
- } else if (this.isNew) {
3207
- return 'created';
3208
-
3209
- // loaded.updated substates
3210
- } else if (this.isSaving || !this.isValid || this.isDirty) {
3211
- return 'updated';
3212
-
3213
- // if nothing remains, we are loaded saved!
3214
- } else {
3215
- return '';
3216
- }
3217
- }
3218
- static {
3219
- decorateMethodV2(this.prototype, "dirtyType", [memoized]);
3220
- }
3221
- }
3222
- defineSignal(RecordState.prototype, 'isSaving', false);
3223
- function notifyErrorsStateChanged(state) {
3224
- state.notify('isValid');
3225
- state.notify('isError');
3226
- state.notify('adapterError');
3227
- }
3228
-
3229
- /**
3230
- @module @ember-data/model
3231
- */
3232
-
3233
- /*
3234
- * This decorator allows us to lazily compute
3235
- * an expensive getter on first-access and thereafter
3236
- * never recompute it.
3237
- */
3238
- function computeOnce(target, propertyName, desc) {
3239
- const cache = new WeakMap();
3240
- // eslint-disable-next-line @typescript-eslint/unbound-method
3241
- const getter = desc.get;
3242
- desc.get = function () {
3243
- let meta = cache.get(this);
3244
- if (!meta) {
3245
- meta = {
3246
- hasComputed: false,
3247
- value: undefined
3248
- };
3249
- cache.set(this, meta);
3250
- }
3251
- if (!meta.hasComputed) {
3252
- meta.value = getter.call(this);
3253
- meta.hasComputed = true;
3254
- }
3255
- return meta.value;
3256
- };
3257
- return desc;
3258
- }
3259
-
3260
- /**
3261
- Base class from which Models can be defined.
3262
-
3263
- ```js
3264
- import Model, { attr } from '@ember-data/model';
3265
-
3266
- export default class User extends Model {
3267
- @attr name;
3268
- }
3269
- ```
3270
-
3271
- Models are used both to define the static schema for a
3272
- particular resource type as well as the class to instantiate
3273
- to present that data from cache.
3274
-
3275
- @class Model
3276
- @public
3277
- @extends Ember.EmberObject
3278
- */
3279
-
3280
- class Model extends EmberObject {
3281
- // set during create by the store
3282
-
3283
- init(options) {
3284
- if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
3285
- if (!options?._secretInit && !options?._createProps) {
3286
- throw new Error('You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.');
3287
- }
3288
- }
3289
- const createProps = options._createProps;
3290
- const _secretInit = options._secretInit;
3291
- options._createProps = null;
3292
- options._secretInit = null;
3293
- const store = this.store = _secretInit.store;
3294
- super.init(options);
3295
- this[RecordStore] = store;
3296
- const identity = _secretInit.identifier;
3297
- _secretInit.cb(this, _secretInit.cache, identity, _secretInit.store);
3298
- this.___recordState = macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? new RecordState(this) : null;
3299
- this.setProperties(createProps);
3300
- const notifications = store.notifications;
3301
- this.___private_notifications = notifications.subscribe(identity, (identifier, type, field) => {
3302
- notifyChanges(identifier, type, field, this, store);
3303
- });
3304
- }
3305
-
3306
- // @ts-expect-error destroy should not return a value, but ember's types force it to
3307
- destroy() {
3308
- const identifier = recordIdentifierFor$1(this);
3309
- this.___recordState?.destroy();
3310
- const store = storeFor$1(this);
3311
- store.notifications.unsubscribe(this.___private_notifications);
3312
- LEGACY_SUPPORT.get(this)?.destroy();
3313
- LEGACY_SUPPORT.delete(this);
3314
- LEGACY_SUPPORT.delete(identifier);
3315
- super.destroy();
3316
- }
3317
-
3318
- /**
3319
- If this property is `true` the record is in the `empty`
3320
- state. Empty is the first state all records enter after they have
3321
- been created. Most records created by the store will quickly
3322
- transition to the `loading` state if data needs to be fetched from
3323
- the server or the `created` state if the record is created on the
3324
- client. A record can also enter the empty state if the adapter is
3325
- unable to locate the record.
3326
- @property isEmpty
3327
- @public
3328
- @type {Boolean}
3329
- @readOnly
3330
- */
3331
- get isEmpty() {
3332
- return this.currentState.isEmpty;
3333
- }
3334
-
3335
- /**
3336
- If this property is `true` the record is in the `loading` state. A
3337
- record enters this state when the store asks the adapter for its
3338
- data. It remains in this state until the adapter provides the
3339
- requested data.
3340
- @property isLoading
3341
- @public
3342
- @type {Boolean}
3343
- @readOnly
3344
- */
3345
- static {
3346
- decorateMethodV2(this.prototype, "isEmpty", [memoized]);
3347
- }
3348
- get isLoading() {
3349
- return this.currentState.isLoading;
3350
- }
3351
-
3352
- /**
3353
- If this property is `true` the record is in the `loaded` state. A
3354
- record enters this state when its data is populated. Most of a
3355
- record's lifecycle is spent inside substates of the `loaded`
3356
- state.
3357
- Example
3358
- ```javascript
3359
- let record = store.createRecord('model');
3360
- record.isLoaded; // true
3361
- const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
3362
- model.isLoaded;
3363
- ```
3364
- @property isLoaded
3365
- @public
3366
- @type {Boolean}
3367
- @readOnly
3368
- */
3369
- static {
3370
- decorateMethodV2(this.prototype, "isLoading", [memoized]);
3371
- }
3372
- get isLoaded() {
3373
- return this.currentState.isLoaded;
3374
- }
3375
-
3376
- /**
3377
- If this property is `true` the record is in the `dirty` state. The
3378
- record has local changes that have not yet been saved by the
3379
- adapter. This includes records that have been created (but not yet
3380
- saved) or deleted.
3381
- Example
3382
- ```javascript
3383
- let record = store.createRecord('model');
3384
- record.hasDirtyAttributes; // true
3385
- const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
3386
- model.hasDirtyAttributes; // false
3387
- model.foo = 'some value';
3388
- model.hasDirtyAttributes; // true
3389
- ```
3390
- @since 1.13.0
3391
- @property hasDirtyAttributes
3392
- @public
3393
- @type {Boolean}
3394
- @readOnly
3395
- */
3396
- static {
3397
- decorateMethodV2(this.prototype, "isLoaded", [memoized]);
3398
- }
3399
- get hasDirtyAttributes() {
3400
- return this.currentState.isDirty;
3401
- }
3402
-
3403
- /**
3404
- If this property is `true` the record is in the `saving` state. A
3405
- record enters the saving state when `save` is called, but the
3406
- adapter has not yet acknowledged that the changes have been
3407
- persisted to the backend.
3408
- Example
3409
- ```javascript
3410
- let record = store.createRecord('model');
3411
- record.isSaving; // false
3412
- let promise = record.save();
3413
- record.isSaving; // true
3414
- promise.then(function() {
3415
- record.isSaving; // false
3416
- });
3417
- ```
3418
- @property isSaving
3419
- @public
3420
- @type {Boolean}
3421
- @readOnly
3422
- */
3423
- static {
3424
- decorateMethodV2(this.prototype, "hasDirtyAttributes", [memoized]);
3425
- }
3426
- get isSaving() {
3427
- return this.currentState.isSaving;
3428
- }
3429
-
3430
- /**
3431
- If this property is `true` the record is in the `deleted` state
3432
- and has been marked for deletion. When `isDeleted` is true and
3433
- `hasDirtyAttributes` is true, the record is deleted locally but the deletion
3434
- was not yet persisted. When `isSaving` is true, the change is
3435
- in-flight. When both `hasDirtyAttributes` and `isSaving` are false, the
3436
- change has persisted.
3437
- Example
3438
- ```javascript
3439
- let record = store.createRecord('model');
3440
- record.isDeleted; // false
3441
- record.deleteRecord();
3442
- // Locally deleted
3443
- record.isDeleted; // true
3444
- record.hasDirtyAttributes; // true
3445
- record.isSaving; // false
3446
- // Persisting the deletion
3447
- let promise = record.save();
3448
- record.isDeleted; // true
3449
- record.isSaving; // true
3450
- // Deletion Persisted
3451
- promise.then(function() {
3452
- record.isDeleted; // true
3453
- record.isSaving; // false
3454
- record.hasDirtyAttributes; // false
3455
- });
3456
- ```
3457
- @property isDeleted
3458
- @public
3459
- @type {Boolean}
3460
- @readOnly
3461
- */
3462
- static {
3463
- decorateMethodV2(this.prototype, "isSaving", [memoized]);
3464
- }
3465
- get isDeleted() {
3466
- return this.currentState.isDeleted;
3467
- }
3468
-
3469
- /**
3470
- If this property is `true` the record is in the `new` state. A
3471
- record will be in the `new` state when it has been created on the
3472
- client and the adapter has not yet report that it was successfully
3473
- saved.
3474
- Example
3475
- ```javascript
3476
- let record = store.createRecord('model');
3477
- record.isNew; // true
3478
- record.save().then(function(model) {
3479
- model.isNew; // false
3480
- });
3481
- ```
3482
- @property isNew
3483
- @public
3484
- @type {Boolean}
3485
- @readOnly
3486
- */
3487
- static {
3488
- decorateMethodV2(this.prototype, "isDeleted", [memoized]);
3489
- }
3490
- get isNew() {
3491
- return this.currentState.isNew;
3492
- }
3493
-
3494
- /**
3495
- If this property is `true` the record is in the `valid` state.
3496
- A record will be in the `valid` state when the adapter did not report any
3497
- server-side validation failures.
3498
- @property isValid
3499
- @public
3500
- @type {Boolean}
3501
- @readOnly
3502
- */
3503
- static {
3504
- decorateMethodV2(this.prototype, "isNew", [memoized]);
3505
- }
3506
- get isValid() {
3507
- return this.currentState.isValid;
3508
- }
3509
-
3510
- /**
3511
- If the record is in the dirty state this property will report what
3512
- kind of change has caused it to move into the dirty
3513
- state. Possible values are:
3514
- - `created` The record has been created by the client and not yet saved to the adapter.
3515
- - `updated` The record has been updated by the client and not yet saved to the adapter.
3516
- - `deleted` The record has been deleted by the client and not yet saved to the adapter.
3517
- Example
3518
- ```javascript
3519
- let record = store.createRecord('model');
3520
- record.dirtyType; // 'created'
3521
- ```
3522
- @property dirtyType
3523
- @public
3524
- @type {String}
3525
- @readOnly
3526
- */
3527
- static {
3528
- decorateMethodV2(this.prototype, "isValid", [memoized]);
3529
- }
3530
- get dirtyType() {
3531
- return this.currentState.dirtyType;
3532
- }
3533
-
3534
- /**
3535
- If `true` the adapter reported that it was unable to save local
3536
- changes to the backend for any reason other than a server-side
3537
- validation error.
3538
- Example
3539
- ```javascript
3540
- record.isError; // false
3541
- record.set('foo', 'valid value');
3542
- record.save().then(null, function() {
3543
- record.isError; // true
3544
- });
3545
- ```
3546
- @property isError
3547
- @public
3548
- @type {Boolean}
3549
- @readOnly
3550
- */
3551
- static {
3552
- decorateMethodV2(this.prototype, "dirtyType", [memoized]);
3553
- }
3554
- get isError() {
3555
- return this.currentState.isError;
3556
- }
3557
- static {
3558
- decorateMethodV2(this.prototype, "isError", [memoized]);
3559
- }
3560
- set isError(v) {
3561
- if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
3562
- throw new Error(`isError is not directly settable`);
3563
- }
3564
- }
3565
-
3566
- /**
3567
- If `true` the store is attempting to reload the record from the adapter.
3568
- Example
3569
- ```javascript
3570
- record.isReloading; // false
3571
- record.reload();
3572
- record.isReloading; // true
3573
- ```
3574
- @property isReloading
3575
- @public
3576
- @type {Boolean}
3577
- @readOnly
3578
- */
3579
-
3580
- /**
3581
- All ember models have an id property. This is an identifier
3582
- managed by an external source. These are always coerced to be
3583
- strings before being used internally. Note when declaring the
3584
- attributes for a model it is an error to declare an id
3585
- attribute.
3586
- ```javascript
3587
- let record = store.createRecord('model');
3588
- record.id; // null
3589
- const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
3590
- model.id; // '1'
3591
- ```
3592
- @property id
3593
- @public
3594
- @type {String}
3595
- */
3596
- get id() {
3597
- // this guard exists, because some dev-only deprecation code
3598
- // (addListener via validatePropertyInjections) invokes toString before the
3599
- // object is real.
3600
- if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
3601
- try {
3602
- return recordIdentifierFor$1(this).id;
3603
- } catch {
3604
- return null;
3605
- }
3606
- }
3607
- return recordIdentifierFor$1(this).id;
3608
- }
3609
- static {
3610
- decorateMethodV2(this.prototype, "id", [gate]);
3611
- }
3612
- set id(id) {
3613
- const normalizedId = coerceId(id);
3614
- const identifier = recordIdentifierFor$1(this);
3615
- const didChange = normalizedId !== identifier.id;
3616
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3617
- if (!test) {
3618
- throw new Error(`Cannot set ${identifier.type} record's id to ${id}, because id is already ${identifier.id}`);
3619
- }
3620
- })(!didChange || identifier.id === null) : {};
3621
- if (normalizedId !== null && didChange) {
3622
- this.store._instanceCache.setRecordId(identifier, normalizedId);
3623
- this.store.notifications.notify(identifier, 'identity');
3624
- }
3625
- }
3626
- toString() {
3627
- return `<model::${this.constructor.modelName}:${this.id}>`;
3628
- }
3629
-
3630
- /**
3631
- @property currentState
3632
- @private
3633
- @type {Object}
3634
- */
3635
- // TODO we can probably make this a computeOnce
3636
- // we likely do not need to notify the currentState root anymore
3637
- get currentState() {
3638
- // descriptors are called with the wrong `this` context during mergeMixins
3639
- // when using legacy/classic ember classes. Basically: lazy in prod and eager in dev.
3640
- // so we do this to try to steer folks to the nicer "dont user currentState"
3641
- // error.
3642
- if (macroCondition(!getGlobalConfig().WarpDrive.env.DEBUG)) {
3643
- if (!this.___recordState) {
3644
- this.___recordState = new RecordState(this);
3645
- }
3646
- }
3647
- return this.___recordState;
3648
- }
3649
- static {
3650
- decorateMethodV2(this.prototype, "currentState", [gate]);
3651
- }
3652
- set currentState(_v) {
3653
- throw new Error('cannot set currentState');
3654
- }
3655
-
3656
- /**
3657
- The store service instance which created this record instance
3658
- @property store
3659
- @public
3660
- */
3661
-
3662
- /**
3663
- When the record is in the `invalid` state this object will contain
3664
- any errors returned by the adapter. When present the errors hash
3665
- contains keys corresponding to the invalid property names
3666
- and values which are arrays of Javascript objects with two keys:
3667
- - `message` A string containing the error message from the backend
3668
- - `attribute` The name of the property associated with this error message
3669
- ```javascript
3670
- record.errors.length; // 0
3671
- record.set('foo', 'invalid value');
3672
- record.save().catch(function() {
3673
- record.errors.foo;
3674
- // [{message: 'foo should be a number.', attribute: 'foo'}]
3675
- });
3676
- ```
3677
- The `errors` property is useful for displaying error messages to
3678
- the user.
3679
- ```handlebars
3680
- <label>Username: <Input @value={{@model.username}} /> </label>
3681
- {{#each @model.errors.username as |error|}}
3682
- <div class="error">
3683
- {{error.message}}
3684
- </div>
3685
- {{/each}}
3686
- <label>Email: <Input @value={{@model.email}} /> </label>
3687
- {{#each @model.errors.email as |error|}}
3688
- <div class="error">
3689
- {{error.message}}
3690
- </div>
3691
- {{/each}}
3692
- ```
3693
- You can also access the special `messages` property on the error
3694
- object to get an array of all the error strings.
3695
- ```handlebars
3696
- {{#each @model.errors.messages as |message|}}
3697
- <div class="error">
3698
- {{message}}
3699
- </div>
3700
- {{/each}}
3701
- ```
3702
- @property errors
3703
- @public
3704
- @type {Errors}
3705
- */
3706
- get errors() {
3707
- const errors = Errors.create({
3708
- __record: this
3709
- });
3710
- this.currentState.updateInvalidErrors(errors);
3711
- return errors;
3712
- }
3713
-
3714
- /**
3715
- This property holds the `AdapterError` object with which
3716
- last adapter operation was rejected.
3717
- @property adapterError
3718
- @public
3719
- @type {AdapterError}
3720
- */
3721
- static {
3722
- decorateMethodV2(this.prototype, "errors", [computeOnce]);
3723
- }
3724
- get adapterError() {
3725
- return this.currentState.adapterError;
3726
- }
3727
- static {
3728
- decorateMethodV2(this.prototype, "adapterError", [memoized]);
3729
- }
3730
- set adapterError(v) {
3731
- throw new Error(`adapterError is not directly settable`);
3732
- }
3733
-
3734
- /**
3735
- Create a JSON representation of the record, using the serialization
3736
- strategy of the store's adapter.
3737
- `serialize` takes an optional hash as a parameter, currently
3738
- supported options are:
3739
- - `includeId`: `true` if the record's ID should be included in the
3740
- JSON representation.
3741
- @method serialize
3742
- @public
3743
- @param {Object} options
3744
- @return {Object} an object whose values are primitive JSON values only
3745
- */
3746
- /*
3747
- We hook the default implementation to ensure
3748
- our tagged properties are properly notified
3749
- as well. We still super for everything because
3750
- sync observers require a direct call occuring
3751
- to trigger their flush. We wouldn't need to
3752
- super in 4.0+ where sync observers are removed.
3753
- */
3754
- // @ts-expect-error no return is necessary, but Ember's types are forcing it
3755
- notifyPropertyChange(prop) {
3756
- const signals = withSignalStore(this);
3757
- entangleSignal(signals, this, prop, undefined);
3758
- super.notifyPropertyChange(prop);
3759
- }
3760
-
3761
- /**
3762
- Marks the record as deleted but does not save it. You must call
3763
- `save` afterwards if you want to persist it. You might use this
3764
- method if you want to allow the user to still `rollbackAttributes()`
3765
- after a delete was made.
3766
- Example
3767
- ```js
3768
- import Component from '@glimmer/component';
3769
- export default class extends Component {
3770
- softDelete = () => {
3771
- this.args.model.deleteRecord();
3772
- }
3773
- confirm = () => {
3774
- this.args.model.save();
3775
- }
3776
- undo = () => {
3777
- this.args.model.rollbackAttributes();
3778
- }
3779
- }
3780
- ```
3781
- @method deleteRecord
3782
- @public
3783
- */
3784
-
3785
- /**
3786
- Same as `deleteRecord`, but saves the record immediately.
3787
- Example
3788
- ```js
3789
- import Component from '@glimmer/component';
3790
- export default class extends Component {
3791
- delete = () => {
3792
- this.args.model.destroyRecord().then(function() {
3793
- this.transitionToRoute('model.index');
3794
- });
3795
- }
3796
- }
3797
- ```
3798
- If you pass an object on the `adapterOptions` property of the options
3799
- argument it will be passed to your adapter via the snapshot
3800
- ```js
3801
- record.destroyRecord({ adapterOptions: { subscribe: false } });
3802
- ```
3803
- ```app/adapters/post.js
3804
- import MyCustomAdapter from './custom-adapter';
3805
- export default class PostAdapter extends MyCustomAdapter {
3806
- deleteRecord(store, type, snapshot) {
3807
- if (snapshot.adapterOptions.subscribe) {
3808
- // ...
3809
- }
3810
- // ...
3811
- }
3812
- }
3813
- ```
3814
- @method destroyRecord
3815
- @public
3816
- @param {Object} options
3817
- @return {Promise} a promise that will be resolved when the adapter returns
3818
- successfully or rejected if the adapter returns with an error.
3819
- */
3820
-
3821
- /**
3822
- Unloads the record from the store. This will not send a delete request
3823
- to your server, it just unloads the record from memory.
3824
- @method unloadRecord
3825
- @public
3826
- */
3827
-
3828
- /**
3829
- Returns an object, whose keys are changed properties, and value is
3830
- an [oldProp, newProp] array.
3831
- The array represents the diff of the canonical state with the local state
3832
- of the model. Note: if the model is created locally, the canonical state is
3833
- empty since the adapter hasn't acknowledged the attributes yet:
3834
- Example
3835
- ```app/models/mascot.js
3836
- import Model, { attr } from '@ember-data/model';
3837
- export default class MascotModel extends Model {
3838
- @attr('string') name;
3839
- @attr('boolean', {
3840
- defaultValue: false
3841
- })
3842
- isAdmin;
3843
- }
3844
- ```
3845
- ```javascript
3846
- let mascot = store.createRecord('mascot');
3847
- mascot.changedAttributes(); // {}
3848
- mascot.set('name', 'Tomster');
3849
- mascot.changedAttributes(); // { name: [undefined, 'Tomster'] }
3850
- mascot.set('isAdmin', true);
3851
- mascot.changedAttributes(); // { isAdmin: [undefined, true], name: [undefined, 'Tomster'] }
3852
- mascot.save().then(function() {
3853
- mascot.changedAttributes(); // {}
3854
- mascot.set('isAdmin', false);
3855
- mascot.changedAttributes(); // { isAdmin: [true, false] }
3856
- });
3857
- ```
3858
- @method changedAttributes
3859
- @public
3860
- @return {Object} an object, whose keys are changed properties,
3861
- and value is an [oldProp, newProp] array.
3862
- */
3863
-
3864
- /**
3865
- If the model `hasDirtyAttributes` this function will discard any unsaved
3866
- changes. If the model `isNew` it will be removed from the store.
3867
- Example
3868
- ```javascript
3869
- record.name; // 'Untitled Document'
3870
- record.set('name', 'Doc 1');
3871
- record.name; // 'Doc 1'
3872
- record.rollbackAttributes();
3873
- record.name; // 'Untitled Document'
3874
- ```
3875
- @since 1.13.0
3876
- @method rollbackAttributes
3877
- @public
3878
- */
3879
-
3880
- /**
3881
- @method _createSnapshot
3882
- @private
3883
- */
3884
- // TODO @deprecate in favor of a public API or examples of how to test successfully
3885
-
3886
- /**
3887
- Save the record and persist any changes to the record to an
3888
- external source via the adapter.
3889
- Example
3890
- ```javascript
3891
- record.set('name', 'Tomster');
3892
- record.save().then(function() {
3893
- // Success callback
3894
- }, function() {
3895
- // Error callback
3896
- });
3897
- ```
3898
- If you pass an object using the `adapterOptions` property of the options
3899
- argument it will be passed to your adapter via the snapshot.
3900
- ```js
3901
- record.save({ adapterOptions: { subscribe: false } });
3902
- ```
3903
- ```app/adapters/post.js
3904
- import MyCustomAdapter from './custom-adapter';
3905
- export default class PostAdapter extends MyCustomAdapter {
3906
- updateRecord(store, type, snapshot) {
3907
- if (snapshot.adapterOptions.subscribe) {
3908
- // ...
3909
- }
3910
- // ...
3911
- }
3912
- }
3913
- ```
3914
- @method save
3915
- @public
3916
- @param {Object} options
3917
- @return {Promise} a promise that will be resolved when the adapter returns
3918
- successfully or rejected if the adapter returns with an error.
3919
- */
3920
-
3921
- /**
3922
- Reload the record from the adapter.
3923
- This will only work if the record has already finished loading.
3924
- Example
3925
- ```js
3926
- import Component from '@glimmer/component';
3927
- export default class extends Component {
3928
- async reload = () => {
3929
- await this.args.model.reload();
3930
- // do something with the reloaded model
3931
- }
3932
- }
3933
- ```
3934
- @method reload
3935
- @public
3936
- @param {Object} options optional, may include `adapterOptions` hash which will be passed to adapter request
3937
- @return {Promise} a promise that will be resolved with the record when the
3938
- adapter returns successfully or rejected if the adapter returns
3939
- with an error.
3940
- */
3941
-
3942
- attr() {
3943
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3944
- {
3945
- throw new Error('The `attr` method is not available on Model, a Snapshot was probably expected. Are you passing a Model instead of a Snapshot to your serializer?');
3946
- }
3947
- })() : {};
3948
- }
3949
-
3950
- /**
3951
- Get the reference for the specified belongsTo relationship.
3952
- For instance, given the following model
3953
- ```app/models/blog-post.js
3954
- import Model, { belongsTo } from '@ember-data/model';
3955
- export default class BlogPost extends Model {
3956
- @belongsTo('user', { async: true, inverse: null }) author;
3957
- }
3958
- ```
3959
- Then the reference for the author relationship would be
3960
- retrieved from a record instance like so:
3961
- ```js
3962
- blogPost.belongsTo('author');
3963
- ```
3964
- A `BelongsToReference` is a low-level API that allows access
3965
- and manipulation of a belongsTo relationship.
3966
- It is especially useful when you're dealing with `async` relationships
3967
- as it allows synchronous access to the relationship data if loaded, as
3968
- well as APIs for loading, reloading the data or accessing available
3969
- information without triggering a load.
3970
- It may also be useful when using `sync` relationships that need to be
3971
- loaded/reloaded with more precise timing than marking the
3972
- relationship as `async` and relying on autofetch would have allowed.
3973
- However,keep in mind that marking a relationship as `async: false` will introduce
3974
- bugs into your application if the data is not always guaranteed to be available
3975
- by the time the relationship is accessed. Ergo, it is recommended when using this
3976
- approach to utilize `links` for unloaded relationship state instead of identifiers.
3977
- Reference APIs are entangled with the relationship's underlying state,
3978
- thus any getters or cached properties that utilize these will properly
3979
- invalidate if the relationship state changes.
3980
- References are "stable", meaning that multiple calls to retrieve the reference
3981
- for a given relationship will always return the same HasManyReference.
3982
- @method belongsTo
3983
- @public
3984
- @param {String} name of the relationship
3985
- @since 2.5.0
3986
- @return {BelongsToReference} reference for this relationship
3987
- */
3988
-
3989
- /**
3990
- Get the reference for the specified hasMany relationship.
3991
- For instance, given the following model
3992
- ```app/models/blog-post.js
3993
- import Model, { hasMany } from '@ember-data/model';
3994
- export default class BlogPost extends Model {
3995
- @hasMany('comment', { async: true, inverse: null }) comments;
3996
- }
3997
- ```
3998
- Then the reference for the comments relationship would be
3999
- retrieved from a record instance like so:
4000
- ```js
4001
- blogPost.hasMany('comments');
4002
- ```
4003
- A `HasManyReference` is a low-level API that allows access
4004
- and manipulation of a hasMany relationship.
4005
- It is especially useful when you are dealing with `async` relationships
4006
- as it allows synchronous access to the relationship data if loaded, as
4007
- well as APIs for loading, reloading the data or accessing available
4008
- information without triggering a load.
4009
- It may also be useful when using `sync` relationships with `@ember-data/model`
4010
- that need to be loaded/reloaded with more precise timing than marking the
4011
- relationship as `async` and relying on autofetch would have allowed.
4012
- However,keep in mind that marking a relationship as `async: false` will introduce
4013
- bugs into your application if the data is not always guaranteed to be available
4014
- by the time the relationship is accessed. Ergo, it is recommended when using this
4015
- approach to utilize `links` for unloaded relationship state instead of identifiers.
4016
- Reference APIs are entangled with the relationship's underlying state,
4017
- thus any getters or cached properties that utilize these will properly
4018
- invalidate if the relationship state changes.
4019
- References are "stable", meaning that multiple calls to retrieve the reference
4020
- for a given relationship will always return the same HasManyReference.
4021
- @method hasMany
4022
- @public
4023
- @param {String} name of the relationship
4024
- @since 2.5.0
4025
- @return {HasManyReference} reference for this relationship
4026
- */
4027
-
4028
- /**
4029
- Given a callback, iterates over each of the relationships in the model,
4030
- invoking the callback with the name of each relationship and its relationship
4031
- descriptor.
4032
- The callback method you provide should have the following signature (all
4033
- parameters are optional):
4034
- ```javascript
4035
- function(name, descriptor);
4036
- ```
4037
- - `name` the name of the current property in the iteration
4038
- - `descriptor` the meta object that describes this relationship
4039
- The relationship descriptor argument is an object with the following properties.
4040
- - **name** <span class="type">String</span> the name of this relationship on the Model
4041
- - **kind** <span class="type">String</span> "hasMany" or "belongsTo"
4042
- - **options** <span class="type">Object</span> the original options hash passed when the relationship was declared
4043
- - **parentType** <span class="type">Model</span> the type of the Model that owns this relationship
4044
- - **type** <span class="type">String</span> the type name of the related Model
4045
- Note that in addition to a callback, you can also pass an optional target
4046
- object that will be set as `this` on the context.
4047
- Example
4048
- ```app/serializers/application.js
4049
- import JSONSerializer from '@ember-data/serializer/json';
4050
- export default class ApplicationSerializer extends JSONSerializer {
4051
- serialize(record, options) {
4052
- let json = {};
4053
- record.eachRelationship(function(name, descriptor) {
4054
- if (descriptor.kind === 'hasMany') {
4055
- let serializedHasManyName = name.toUpperCase() + '_IDS';
4056
- json[serializedHasManyName] = record.get(name).map(r => r.id);
4057
- }
4058
- });
4059
- return json;
4060
- }
4061
- }
4062
- ```
4063
- @method eachRelationship
4064
- @public
4065
- @param {Function} callback the callback to invoke
4066
- @param {any} binding the value to which the callback's `this` should be bound
4067
- */
4068
- eachRelationship(callback, binding) {
4069
- this.constructor.eachRelationship(callback, binding);
4070
- }
4071
- relationshipFor(name) {
4072
- return this.constructor.relationshipsByName.get(name);
4073
- }
4074
- inverseFor(name) {
4075
- return this.constructor.inverseFor(name, storeFor$1(this));
4076
- }
4077
- eachAttribute(callback, binding) {
4078
- this.constructor.eachAttribute(callback, binding);
4079
- }
4080
- static isModel = true;
4081
-
4082
- /**
4083
- Create should only ever be called by the store. To create an instance of a
4084
- `Model` in a dirty state use `store.createRecord`.
4085
- To create instances of `Model` in a clean state, use `store.push`
4086
- @method create
4087
- @private
4088
- @static
4089
- */
4090
-
4091
- /**
4092
- Represents the model's class name as a string. This can be used to look up the model's class name through
4093
- `Store`'s modelFor method.
4094
- `modelName` is generated for you by EmberData. It will be a lowercased, dasherized string.
4095
- For example:
4096
- ```javascript
4097
- store.modelFor('post').modelName; // 'post'
4098
- store.modelFor('blog-post').modelName; // 'blog-post'
4099
- ```
4100
- The most common place you'll want to access `modelName` is in your serializer's `payloadKeyFromModelName` method. For example, to change payload
4101
- keys to underscore (instead of dasherized), you might use the following code:
4102
- ```javascript
4103
- import RESTSerializer from '@ember-data/serializer/rest';
4104
- import { underscore } from '<app-name>/utils/string-utils';
4105
- export default const PostSerializer = RESTSerializer.extend({
4106
- payloadKeyFromModelName(modelName) {
4107
- return underscore(modelName);
4108
- }
4109
- });
4110
- ```
4111
- @property modelName
4112
- @public
4113
- @type String
4114
- @readonly
4115
- @static
4116
- */
4117
- static modelName = null;
4118
-
4119
- /*
4120
- These class methods below provide relationship
4121
- introspection abilities about relationships.
4122
- A note about the computed properties contained here:
4123
- **These properties are effectively sealed once called for the first time.**
4124
- To avoid repeatedly doing expensive iteration over a model's fields, these
4125
- values are computed once and then cached for the remainder of the runtime of
4126
- your application.
4127
- If your application needs to modify a class after its initial definition
4128
- (for example, using `reopen()` to add additional attributes), make sure you
4129
- do it before using your model with the store, which uses these properties
4130
- extensively.
4131
- */
4132
-
4133
- /**
4134
- For a given relationship name, returns the model type of the relationship.
4135
- For example, if you define a model like this:
4136
- ```app/models/post.js
4137
- import Model, { hasMany } from '@ember-data/model';
4138
- export default class PostModel extends Model {
4139
- @hasMany('comment') comments;
4140
- }
4141
- ```
4142
- Calling `store.modelFor('post').typeForRelationship('comments', store)` will return `Comment`.
4143
- @method typeForRelationship
4144
- @public
4145
- @static
4146
- @param {String} name the name of the relationship
4147
- @param {store} store an instance of Store
4148
- @return {Model} the type of the relationship, or undefined
4149
- */
4150
- static typeForRelationship(name, store) {
4151
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4152
- if (!test) {
4153
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4154
- }
4155
- })(this.modelName) : {};
4156
- const relationship = this.relationshipsByName.get(name);
4157
- return relationship && store.modelFor(relationship.type);
4158
- }
4159
- static get inverseMap() {
4160
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4161
- if (!test) {
4162
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4163
- }
4164
- })(this.modelName) : {};
4165
- return Object.create(null);
4166
- }
4167
-
4168
- /**
4169
- Find the relationship which is the inverse of the one asked for.
4170
- For example, if you define models like this:
4171
- ```app/models/post.js
4172
- import Model, { hasMany } from '@ember-data/model';
4173
- export default class PostModel extends Model {
4174
- @hasMany('message') comments;
4175
- }
4176
- ```
4177
- ```app/models/message.js
4178
- import Model, { belongsTo } from '@ember-data/model';
4179
- export default class MessageModel extends Model {
4180
- @belongsTo('post') owner;
4181
- }
4182
- ```
4183
- ``` js
4184
- store.modelFor('post').inverseFor('comments', store) // { type: 'message', name: 'owner', kind: 'belongsTo' }
4185
- store.modelFor('message').inverseFor('owner', store) // { type: 'post', name: 'comments', kind: 'hasMany' }
4186
- ```
4187
- @method inverseFor
4188
- @public
4189
- @static
4190
- @param {String} name the name of the relationship
4191
- @param {Store} store
4192
- @return {Object} the inverse relationship, or null
4193
- */
4194
- static {
4195
- decorateMethodV2(this, "inverseMap", [computeOnce]);
4196
- }
4197
- static inverseFor(name, store) {
4198
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4199
- if (!test) {
4200
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4201
- }
4202
- })(this.modelName) : {};
4203
- const inverseMap = this.inverseMap;
4204
- if (inverseMap[name]) {
4205
- return inverseMap[name];
4206
- } else {
4207
- const inverse = this._findInverseFor(name, store);
4208
- inverseMap[name] = inverse;
4209
- return inverse;
4210
- }
4211
- }
4212
-
4213
- //Calculate the inverse, ignoring the cache
4214
- static _findInverseFor(name, store) {
4215
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4216
- if (!test) {
4217
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4218
- }
4219
- })(this.modelName) : {};
4220
- const relationship = this.relationshipsByName.get(name);
4221
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4222
- if (!test) {
4223
- throw new Error(`No relationship named '${name}' on '${this.modelName}' exists.`);
4224
- }
4225
- })(relationship) : {};
4226
- if (!relationship) {
4227
- return null;
4228
- }
4229
- const {
4230
- options
4231
- } = relationship;
4232
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4233
- if (!test) {
4234
- throw new Error(`Expected the relationship ${name} on ${this.modelName} to define an inverse.`);
4235
- }
4236
- })(options.inverse === null || typeof options.inverse === 'string' && options.inverse.length > 0) : {};
4237
- if (options.inverse === null) {
4238
- return null;
4239
- }
4240
- const schemaExists = store.schema.hasResource(relationship);
4241
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4242
- if (!test) {
4243
- throw new Error(`No associated schema found for '${relationship.type}' while calculating the inverse of ${name} on ${this.modelName}`);
4244
- }
4245
- })(schemaExists) : {};
4246
- if (!schemaExists) {
4247
- return null;
4248
- }
4249
- const inverseField = store.schema.fields(relationship).get(options.inverse);
4250
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4251
- if (!test) {
4252
- throw new Error(`No inverse relationship found for '${name}' on '${this.modelName}'`);
4253
- }
4254
- })(inverseField && (inverseField.kind === 'belongsTo' || inverseField.kind === 'hasMany')) : {};
4255
- return inverseField || null;
4256
- }
4257
-
4258
- /**
4259
- The model's relationships as a map, keyed on the type of the
4260
- relationship. The value of each entry is an array containing a descriptor
4261
- for each relationship with that type, describing the name of the relationship
4262
- as well as the type.
4263
- For example, given the following model definition:
4264
- ```app/models/blog.js
4265
- import Model, { belongsTo, hasMany } from '@ember-data/model';
4266
- export default class BlogModel extends Model {
4267
- @hasMany('user') users;
4268
- @belongsTo('user') owner;
4269
- @hasMany('post') posts;
4270
- }
4271
- ```
4272
- This computed property would return a map describing these
4273
- relationships, like this:
4274
- ```javascript
4275
- import Blog from 'app/models/blog';
4276
- import User from 'app/models/user';
4277
- import Post from 'app/models/post';
4278
- let relationships = Blog.relationships;
4279
- relationships.user;
4280
- //=> [ { name: 'users', kind: 'hasMany' },
4281
- // { name: 'owner', kind: 'belongsTo' } ]
4282
- relationships.post;
4283
- //=> [ { name: 'posts', kind: 'hasMany' } ]
4284
- ```
4285
- @property relationships
4286
- @public
4287
- @static
4288
- @type Map
4289
- @readOnly
4290
- */
4291
-
4292
- static get relationships() {
4293
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4294
- if (!test) {
4295
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4296
- }
4297
- })(this.modelName) : {};
4298
- const map = new Map();
4299
- const relationshipsByName = this.relationshipsByName;
4300
-
4301
- // Loop through each computed property on the class
4302
- relationshipsByName.forEach(desc => {
4303
- const {
4304
- type
4305
- } = desc;
4306
- if (!map.has(type)) {
4307
- map.set(type, []);
4308
- }
4309
- map.get(type).push(desc);
4310
- });
4311
- return map;
4312
- }
4313
-
4314
- /**
4315
- A hash containing lists of the model's relationships, grouped
4316
- by the relationship kind. For example, given a model with this
4317
- definition:
4318
- ```app/models/blog.js
4319
- import Model, { belongsTo, hasMany } from '@ember-data/model';
4320
- export default class BlogModel extends Model {
4321
- @hasMany('user') users;
4322
- @belongsTo('user') owner;
4323
- @hasMany('post') posts;
4324
- }
4325
- ```
4326
- This property would contain the following:
4327
- ```javascript
4328
- import Blog from 'app/models/blog';
4329
- let relationshipNames = Blog.relationshipNames;
4330
- relationshipNames.hasMany;
4331
- //=> ['users', 'posts']
4332
- relationshipNames.belongsTo;
4333
- //=> ['owner']
4334
- ```
4335
- @property relationshipNames
4336
- @public
4337
- @static
4338
- @type Object
4339
- @readOnly
4340
- */
4341
- static {
4342
- decorateMethodV2(this, "relationships", [computeOnce]);
4343
- }
4344
- static get relationshipNames() {
4345
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4346
- if (!test) {
4347
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4348
- }
4349
- })(this.modelName) : {};
4350
- const names = {
4351
- hasMany: [],
4352
- belongsTo: []
4353
- };
4354
- this.eachComputedProperty((name, meta) => {
4355
- if (isRelationshipSchema(meta)) {
4356
- names[meta.kind].push(name);
4357
- }
4358
- });
4359
- return names;
4360
- }
4361
-
4362
- /**
4363
- An array of types directly related to a model. Each type will be
4364
- included once, regardless of the number of relationships it has with
4365
- the model.
4366
- For example, given a model with this definition:
4367
- ```app/models/blog.js
4368
- import Model, { belongsTo, hasMany } from '@ember-data/model';
4369
- export default class BlogModel extends Model {
4370
- @hasMany('user') users;
4371
- @belongsTo('user') owner;
4372
- @hasMany('post') posts;
4373
- }
4374
- ```
4375
- This property would contain the following:
4376
- ```javascript
4377
- import Blog from 'app/models/blog';
4378
- let relatedTypes = Blog.relatedTypes');
4379
- //=> ['user', 'post']
4380
- ```
4381
- @property relatedTypes
4382
- @public
4383
- @static
4384
- @type Array
4385
- @readOnly
4386
- */
4387
- static {
4388
- decorateMethodV2(this, "relationshipNames", [computeOnce]);
4389
- }
4390
- static get relatedTypes() {
4391
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4392
- if (!test) {
4393
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4394
- }
4395
- })(this.modelName) : {};
4396
- const types = [];
4397
- const rels = this.relationshipsObject;
4398
- const relationships = Object.keys(rels);
4399
-
4400
- // create an array of the unique types involved
4401
- // in relationships
4402
- for (let i = 0; i < relationships.length; i++) {
4403
- const name = relationships[i];
4404
- const meta = rels[name];
4405
- const modelName = meta.type;
4406
- if (!types.includes(modelName)) {
4407
- types.push(modelName);
4408
- }
4409
- }
4410
- return types;
4411
- }
4412
-
4413
- /**
4414
- A map whose keys are the relationships of a model and whose values are
4415
- relationship descriptors.
4416
- For example, given a model with this
4417
- definition:
4418
- ```app/models/blog.js
4419
- import Model, { belongsTo, hasMany } from '@ember-data/model';
4420
- export default class BlogModel extends Model {
4421
- @hasMany('user') users;
4422
- @belongsTo('user') owner;
4423
- @hasMany('post') posts;
4424
- }
4425
- ```
4426
- This property would contain the following:
4427
- ```javascript
4428
- import Blog from 'app/models/blog';
4429
- let relationshipsByName = Blog.relationshipsByName;
4430
- relationshipsByName.users;
4431
- //=> { name: 'users', kind: 'hasMany', type: 'user', options: Object }
4432
- relationshipsByName.owner;
4433
- //=> { name: 'owner', kind: 'belongsTo', type: 'user', options: Object }
4434
- ```
4435
- @property relationshipsByName
4436
- @public
4437
- @static
4438
- @type Map
4439
- @readOnly
4440
- */
4441
- static {
4442
- decorateMethodV2(this, "relatedTypes", [computeOnce]);
4443
- }
4444
- static get relationshipsByName() {
4445
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4446
- if (!test) {
4447
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4448
- }
4449
- })(this.modelName) : {};
4450
- const map = new Map();
4451
- const rels = this.relationshipsObject;
4452
- const relationships = Object.keys(rels);
4453
- for (let i = 0; i < relationships.length; i++) {
4454
- const name = relationships[i];
4455
- const value = rels[name];
4456
- map.set(value.name, value);
4457
- }
4458
- return map;
4459
- }
4460
- static {
4461
- decorateMethodV2(this, "relationshipsByName", [computeOnce]);
4462
- }
4463
- static get relationshipsObject() {
4464
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4465
- if (!test) {
4466
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4467
- }
4468
- })(this.modelName) : {};
4469
- const relationships = Object.create(null);
4470
- const modelName = this.modelName;
4471
- this.eachComputedProperty((name, meta) => {
4472
- if (!isRelationshipSchema(meta)) {
4473
- return;
4474
- }
4475
- // TODO deprecate key being here
4476
- meta.key = name;
4477
- meta.name = name;
4478
- relationships[name] = meta;
4479
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4480
- if (!test) {
4481
- throw new Error(`Expected options in meta`);
4482
- }
4483
- })(meta.options && typeof meta.options === 'object') : {};
4484
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4485
- if (!test) {
4486
- throw new Error(`You should not specify both options.as and options.inverse as null on ${modelName}.${meta.name}, as if there is no inverse field there is no abstract type to conform to. You may have intended for this relationship to be polymorphic, or you may have mistakenly set inverse to null.`);
4487
- }
4488
- })(!(meta.options.inverse === null && meta.options.as?.length)) : {};
4489
- });
4490
- return relationships;
4491
- }
4492
-
4493
- /**
4494
- A map whose keys are the fields of the model and whose values are strings
4495
- describing the kind of the field. A model's fields are the union of all of its
4496
- attributes and relationships.
4497
- For example:
4498
- ```app/models/blog.js
4499
- import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
4500
- export default class BlogModel extends Model {
4501
- @hasMany('user') users;
4502
- @belongsTo('user') owner;
4503
- @hasMany('post') posts;
4504
- @attr('string') title;
4505
- }
4506
- ```
4507
- ```js
4508
- import Blog from 'app/models/blog'
4509
- let fields = Blog.fields;
4510
- fields.forEach(function(kind, field) {
4511
- // do thing
4512
- });
4513
- // prints:
4514
- // users, hasMany
4515
- // owner, belongsTo
4516
- // posts, hasMany
4517
- // title, attribute
4518
- ```
4519
- @property fields
4520
- @public
4521
- @static
4522
- @type Map
4523
- @readOnly
4524
- */
4525
- static {
4526
- decorateMethodV2(this, "relationshipsObject", [computeOnce]);
4527
- }
4528
- static get fields() {
4529
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4530
- if (!test) {
4531
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4532
- }
4533
- })(this.modelName) : {};
4534
- const map = new Map();
4535
- this.eachComputedProperty((name, meta) => {
4536
- if (isRelationshipSchema(meta)) {
4537
- map.set(name, meta.kind);
4538
- } else if (isAttributeSchema(meta)) {
4539
- map.set(name, 'attribute');
4540
- }
4541
- });
4542
- return map;
4543
- }
4544
-
4545
- /**
4546
- Given a callback, iterates over each of the relationships in the model,
4547
- invoking the callback with the name of each relationship and its relationship
4548
- descriptor.
4549
- @method eachRelationship
4550
- @public
4551
- @static
4552
- @param {Function} callback the callback to invoke
4553
- @param {any} binding the value to which the callback's `this` should be bound
4554
- */
4555
- static {
4556
- decorateMethodV2(this, "fields", [computeOnce]);
4557
- }
4558
- static eachRelationship(callback, binding) {
4559
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4560
- if (!test) {
4561
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4562
- }
4563
- })(this.modelName) : {};
4564
- this.relationshipsByName.forEach((relationship, name) => {
4565
- callback.call(binding, name, relationship);
4566
- });
4567
- }
4568
-
4569
- /**
4570
- Given a callback, iterates over each of the types related to a model,
4571
- invoking the callback with the related type's class. Each type will be
4572
- returned just once, regardless of how many different relationships it has
4573
- with a model.
4574
- @method eachRelatedType
4575
- @public
4576
- @static
4577
- @param {Function} callback the callback to invoke
4578
- @param {any} binding the value to which the callback's `this` should be bound
4579
- */
4580
- static eachRelatedType(callback, binding) {
4581
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4582
- if (!test) {
4583
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4584
- }
4585
- })(this.modelName) : {};
4586
- const relationshipTypes = this.relatedTypes;
4587
- for (let i = 0; i < relationshipTypes.length; i++) {
4588
- const type = relationshipTypes[i];
4589
- callback.call(binding, type);
4590
- }
4591
- }
4592
-
4593
- /**
4594
- *
4595
- * @method determineRelationshipType
4596
- * @private
4597
- * @deprecated
4598
- */
4599
- static determineRelationshipType(knownSide, store) {
4600
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4601
- if (!test) {
4602
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4603
- }
4604
- })(this.modelName) : {};
4605
- const knownKey = knownSide.name;
4606
- const knownKind = knownSide.kind;
4607
- const inverse = this.inverseFor(knownKey, store);
4608
- // let key;
4609
-
4610
- if (!inverse) {
4611
- return knownKind === 'belongsTo' ? 'oneToNone' : 'manyToNone';
4612
- }
4613
-
4614
- // key = inverse.name;
4615
- const otherKind = inverse.kind;
4616
- if (otherKind === 'belongsTo') {
4617
- return knownKind === 'belongsTo' ? 'oneToOne' : 'manyToOne';
4618
- } else {
4619
- return knownKind === 'belongsTo' ? 'oneToMany' : 'manyToMany';
4620
- }
4621
- }
4622
-
4623
- /**
4624
- A map whose keys are the attributes of the model (properties
4625
- described by attr) and whose values are the meta object for the
4626
- property.
4627
- Example
4628
- ```app/models/person.js
4629
- import Model, { attr } from '@ember-data/model';
4630
- export default class PersonModel extends Model {
4631
- @attr('string') firstName;
4632
- @attr('string') lastName;
4633
- @attr('date') birthday;
4634
- }
4635
- ```
4636
- ```javascript
4637
- import Person from 'app/models/person'
4638
- let attributes = Person.attributes
4639
- attributes.forEach(function(meta, name) {
4640
- // do thing
4641
- });
4642
- // prints:
4643
- // firstName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "firstName"}
4644
- // lastName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "lastName"}
4645
- // birthday {type: "date", kind: 'attribute', options: Object, parentType: function, name: "birthday"}
4646
- ```
4647
- @property attributes
4648
- @public
4649
- @static
4650
- @type {Map}
4651
- @readOnly
4652
- */
4653
- static get attributes() {
4654
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4655
- if (!test) {
4656
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4657
- }
4658
- })(this.modelName) : {};
4659
- const map = new Map();
4660
- this.eachComputedProperty((name, meta) => {
4661
- if (isAttributeSchema(meta)) {
4662
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4663
- if (!test) {
4664
- throw new Error("You may not set 'id' as an attribute on your model. Please remove any lines that look like: `id: attr('<type>')` from " + this.toString());
4665
- }
4666
- })(name !== 'id') : {};
4667
-
4668
- // TODO deprecate key being here
4669
- meta.key = name;
4670
- meta.name = name;
4671
- map.set(name, meta);
4672
- }
4673
- });
4674
- return map;
4675
- }
4676
-
4677
- /**
4678
- A map whose keys are the attributes of the model (properties
4679
- described by attr) and whose values are type of transformation
4680
- applied to each attribute. This map does not include any
4681
- attributes that do not have an transformation type.
4682
- Example
4683
- ```app/models/person.js
4684
- import Model, { attr } from '@ember-data/model';
4685
- export default class PersonModel extends Model {
4686
- @attr firstName;
4687
- @attr('string') lastName;
4688
- @attr('date') birthday;
4689
- }
4690
- ```
4691
- ```javascript
4692
- import Person from 'app/models/person';
4693
- let transformedAttributes = Person.transformedAttributes
4694
- transformedAttributes.forEach(function(field, type) {
4695
- // do thing
4696
- });
4697
- // prints:
4698
- // lastName string
4699
- // birthday date
4700
- ```
4701
- @property transformedAttributes
4702
- @public
4703
- @static
4704
- @type {Map}
4705
- @readOnly
4706
- */
4707
- static {
4708
- decorateMethodV2(this, "attributes", [computeOnce]);
4709
- }
4710
- static get transformedAttributes() {
4711
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4712
- if (!test) {
4713
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4714
- }
4715
- })(this.modelName) : {};
4716
- const map = new Map();
4717
- this.eachAttribute((name, meta) => {
4718
- if (meta.type) {
4719
- map.set(name, meta.type);
4720
- }
4721
- });
4722
- return map;
4723
- }
4724
-
4725
- /**
4726
- Iterates through the attributes of the model, calling the passed function on each
4727
- attribute.
4728
- The callback method you provide should have the following signature (all
4729
- parameters are optional):
4730
- ```javascript
4731
- function(name, meta);
4732
- ```
4733
- - `name` the name of the current property in the iteration
4734
- - `meta` the meta object for the attribute property in the iteration
4735
- Note that in addition to a callback, you can also pass an optional target
4736
- object that will be set as `this` on the context.
4737
- Example
4738
- ```javascript
4739
- import Model, { attr } from '@ember-data/model';
4740
- class PersonModel extends Model {
4741
- @attr('string') firstName;
4742
- @attr('string') lastName;
4743
- @attr('date') birthday;
4744
- }
4745
- PersonModel.eachAttribute(function(name, meta) {
4746
- // do thing
4747
- });
4748
- // prints:
4749
- // firstName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "firstName"}
4750
- // lastName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "lastName"}
4751
- // birthday {type: "date", kind: 'attribute', options: Object, parentType: function, name: "birthday"}
4752
- ```
4753
- @method eachAttribute
4754
- @public
4755
- @param {Function} callback The callback to execute
4756
- @param {Object} [binding] the value to which the callback's `this` should be bound
4757
- @static
4758
- */
4759
- static {
4760
- decorateMethodV2(this, "transformedAttributes", [computeOnce]);
4761
- }
4762
- static eachAttribute(callback, binding) {
4763
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4764
- if (!test) {
4765
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4766
- }
4767
- })(this.modelName) : {};
4768
- this.attributes.forEach((meta, name) => {
4769
- callback.call(binding, name, meta);
4770
- });
4771
- }
4772
-
4773
- /**
4774
- Iterates through the transformedAttributes of the model, calling
4775
- the passed function on each attribute. Note the callback will not be
4776
- called for any attributes that do not have an transformation type.
4777
- The callback method you provide should have the following signature (all
4778
- parameters are optional):
4779
- ```javascript
4780
- function(name, type);
4781
- ```
4782
- - `name` the name of the current property in the iteration
4783
- - `type` a string containing the name of the type of transformed
4784
- applied to the attribute
4785
- Note that in addition to a callback, you can also pass an optional target
4786
- object that will be set as `this` on the context.
4787
- Example
4788
- ```javascript
4789
- import Model, { attr } from '@ember-data/model';
4790
- let Person = Model.extend({
4791
- firstName: attr(),
4792
- lastName: attr('string'),
4793
- birthday: attr('date')
4794
- });
4795
- Person.eachTransformedAttribute(function(name, type) {
4796
- // do thing
4797
- });
4798
- // prints:
4799
- // lastName string
4800
- // birthday date
4801
- ```
4802
- @method eachTransformedAttribute
4803
- @public
4804
- @param {Function} callback The callback to execute
4805
- @param {Object} [binding] the value to which the callback's `this` should be bound
4806
- @static
4807
- */
4808
- static eachTransformedAttribute(callback, binding) {
4809
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4810
- if (!test) {
4811
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4812
- }
4813
- })(this.modelName) : {};
4814
- this.transformedAttributes.forEach((type, name) => {
4815
- callback.call(binding, name, type);
4816
- });
4817
- }
4818
-
4819
- /**
4820
- Returns the name of the model class.
4821
- @method toString
4822
- @public
4823
- @static
4824
- */
4825
- static toString() {
4826
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
4827
- if (!test) {
4828
- throw new Error(`Accessing schema information on Models without looking up the model via the store is disallowed.`);
4829
- }
4830
- })(this.modelName) : {};
4831
- return `model:${this.modelName}`;
4832
- }
4833
- }
4834
-
4835
- // @ts-expect-error TS doesn't know how to do `this` function overloads
4836
- Model.prototype.save = save;
4837
- // @ts-expect-error TS doesn't know how to do `this` function overloads
4838
- Model.prototype.destroyRecord = destroyRecord;
4839
- Model.prototype.unloadRecord = unloadRecord;
4840
- Model.prototype.hasMany = hasMany;
4841
- Model.prototype.belongsTo = belongsTo;
4842
- Model.prototype.serialize = serialize;
4843
- Model.prototype._createSnapshot = createSnapshot;
4844
- Model.prototype.deleteRecord = deleteRecord;
4845
- Model.prototype.changedAttributes = changedAttributes;
4846
- Model.prototype.rollbackAttributes = rollbackAttributes;
4847
- Model.prototype.reload = reload;
4848
- defineSignal(Model.prototype, 'isReloading', false);
4849
-
4850
- // this is required to prevent `init` from passing
4851
- // the values initialized during create to `setUnknownProperty`
4852
- Model.prototype._createProps = null;
4853
- Model.prototype._secretInit = null;
4854
- if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
4855
- const lookupDescriptor = function lookupDescriptor(obj, keyName) {
4856
- let current = obj;
4857
- do {
4858
- const descriptor = Object.getOwnPropertyDescriptor(current, keyName);
4859
- if (descriptor !== undefined) {
4860
- return descriptor;
4861
- }
4862
- current = Object.getPrototypeOf(current);
4863
- } while (current !== null);
4864
- return null;
4865
- };
4866
-
4867
- // eslint-disable-next-line @typescript-eslint/unbound-method
4868
- const init = Model.prototype.init;
4869
- Model.prototype.init = function (createArgs) {
4870
- init.call(this, createArgs);
4871
- const ourDescriptor = lookupDescriptor(Model.prototype, 'currentState');
4872
- const theirDescriptor = lookupDescriptor(this, 'currentState');
4873
- if (!ourDescriptor || !theirDescriptor) {
4874
- throw new Error(`Unable to determine if 'currentState' is a reserved property name on instances of classes extending Model. Please ensure that 'currentState' is not defined as a property on ${this.constructor.toString()}`);
4875
- }
4876
- const realState = this.___recordState;
4877
- if (ourDescriptor.get !== theirDescriptor.get || realState !== this.currentState) {
4878
- throw new Error(`'currentState' is a reserved property name on instances of classes extending Model. Please choose a different property name for ${this.constructor.toString()}`);
4879
- }
4880
- const ID_DESCRIPTOR = lookupDescriptor(Model.prototype, 'id');
4881
- const idDesc = lookupDescriptor(this, 'id');
4882
- if (!ID_DESCRIPTOR || !idDesc) {
4883
- throw new Error(`Unable to determine if 'id' is a reserved property name on instances of classes extending Model. Please ensure that 'id' is not defined as a property on ${this.constructor.toString()}`);
4884
- }
4885
- if (idDesc.get !== ID_DESCRIPTOR.get) {
4886
- throw new Error(`You may not set 'id' as an attribute on your model. Please remove any lines that look like: \`id: attr('<type>')\` from ${this.constructor.toString()}`);
4887
- }
4888
- };
4889
- delete Model.reopen;
4890
- delete Model.reopenClass;
4891
- }
4892
- function isRelationshipSchema(meta) {
4893
- const hasKind = typeof meta === 'object' && meta !== null && 'kind' in meta && 'options' in meta;
4894
- return hasKind && (meta.kind === 'hasMany' || meta.kind === 'belongsTo');
4895
- }
4896
- function isAttributeSchema(meta) {
4897
- return typeof meta === 'object' && meta !== null && 'kind' in meta && meta.kind === 'attribute';
4898
- }
4899
- export { Errors as E, LEGACY_SUPPORT as L, Model as M, PromiseBelongsTo as P, RecordState as R, PromiseManyArray as a, save as b, reload as c, destroyRecord as d, deleteRecord as e, changedAttributes as f, belongsTo as g, hasMany as h, createSnapshot as i, isElementDescriptor as j, lookupLegacySupport as l, normalizeModelName as n, rollbackAttributes as r, serialize as s, unloadRecord as u };
2605
+ export { Errors as E, LEGACY_SUPPORT as L, PromiseBelongsTo as P, PromiseManyArray as a, decorateMethodV2 as d, lookupLegacySupport as l };