@ember-data/store 4.10.0-alpha.2 → 4.10.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/addon/-private.js +1 -0
  2. package/addon/-private.js.map +1 -0
  3. package/addon/index-12e1fcb9.js +7660 -0
  4. package/addon/index-12e1fcb9.js.map +1 -0
  5. package/addon/index.js +1 -0
  6. package/addon/index.js.map +1 -0
  7. package/addon-main.js +90 -0
  8. package/package.json +44 -15
  9. package/addon/-private/caches/identifier-cache.ts +0 -686
  10. package/addon/-private/caches/instance-cache.ts +0 -695
  11. package/addon/-private/caches/record-data-for.ts +0 -34
  12. package/addon/-private/index.ts +0 -59
  13. package/addon/-private/legacy-model-support/record-reference.ts +0 -240
  14. package/addon/-private/legacy-model-support/schema-definition-service.ts +0 -148
  15. package/addon/-private/legacy-model-support/shim-model-class.ts +0 -97
  16. package/addon/-private/managers/record-array-manager.ts +0 -379
  17. package/addon/-private/managers/record-data-manager.ts +0 -845
  18. package/addon/-private/managers/record-data-store-wrapper.ts +0 -425
  19. package/addon/-private/managers/record-notification-manager.ts +0 -111
  20. package/addon/-private/network/fetch-manager.ts +0 -567
  21. package/addon/-private/network/finders.js +0 -104
  22. package/addon/-private/network/request-cache.ts +0 -132
  23. package/addon/-private/network/snapshot-record-array.ts +0 -209
  24. package/addon/-private/network/snapshot.ts +0 -563
  25. package/addon/-private/proxies/promise-proxies.ts +0 -228
  26. package/addon/-private/proxies/promise-proxy-base.js +0 -7
  27. package/addon/-private/record-arrays/identifier-array.ts +0 -929
  28. package/addon/-private/store-service.ts +0 -2896
  29. package/addon/-private/utils/coerce-id.ts +0 -41
  30. package/addon/-private/utils/common.js +0 -65
  31. package/addon/-private/utils/construct-resource.ts +0 -61
  32. package/addon/-private/utils/identifer-debug-consts.ts +0 -3
  33. package/addon/-private/utils/is-non-empty-string.ts +0 -3
  34. package/addon/-private/utils/normalize-model-name.ts +0 -21
  35. package/addon/-private/utils/promise-record.ts +0 -15
  36. package/addon/-private/utils/serializer-response.ts +0 -86
  37. package/addon/-private/utils/uuid-polyfill.ts +0 -73
  38. package/addon/index.ts +0 -14
  39. package/index.js +0 -49
@@ -1,563 +0,0 @@
1
- /**
2
- @module @ember-data/store
3
- */
4
- import { assert, deprecate } from '@ember/debug';
5
-
6
- import { importSync } from '@embroider/macros';
7
-
8
- import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
9
- import { DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS } from '@ember-data/private-build-infra/deprecations';
10
- import type BelongsToRelationship from '@ember-data/record-data/-private/relationships/state/belongs-to';
11
- import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
12
- import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
13
- import type { OptionsHash } from '@ember-data/types/q/minimum-serializer-interface';
14
- import type { ChangedAttributesHash } from '@ember-data/types/q/record-data';
15
- import type { AttributeSchema, RelationshipSchema } from '@ember-data/types/q/record-data-schemas';
16
- import type { RecordInstance } from '@ember-data/types/q/record-instance';
17
- import type { FindOptions } from '@ember-data/types/q/store';
18
- import type { Dict } from '@ember-data/types/q/utils';
19
-
20
- import type Store from '../store-service';
21
-
22
- type RecordId = string | null;
23
-
24
- /**
25
- Snapshot is not directly instantiable.
26
- Instances are provided to a consuming application's
27
- adapters and serializers for certain requests.
28
-
29
- @class Snapshot
30
- @public
31
- */
32
- export default class Snapshot implements Snapshot {
33
- declare __attributes: Dict<unknown> | null;
34
- declare _belongsToRelationships: Dict<Snapshot>;
35
- declare _belongsToIds: Dict<RecordId>;
36
- declare _hasManyRelationships: Dict<Snapshot[]>;
37
- declare _hasManyIds: Dict<RecordId[]>;
38
- declare _changedAttributes: ChangedAttributesHash;
39
-
40
- declare identifier: StableRecordIdentifier;
41
- declare modelName: string;
42
- declare id: string | null;
43
- declare include?: unknown;
44
- declare adapterOptions?: Dict<unknown>;
45
- declare _store: Store;
46
-
47
- /**
48
- * @method constructor
49
- * @constructor
50
- * @private
51
- * @param options
52
- * @param identifier
53
- * @param _store
54
- */
55
- constructor(options: FindOptions, identifier: StableRecordIdentifier, store: Store) {
56
- this._store = store;
57
-
58
- this.__attributes = null;
59
- this._belongsToRelationships = Object.create(null);
60
- this._belongsToIds = Object.create(null);
61
- this._hasManyRelationships = Object.create(null);
62
- this._hasManyIds = Object.create(null);
63
-
64
- const hasRecord = !!store._instanceCache.peek({ identifier, bucket: 'record' });
65
- this.modelName = identifier.type;
66
-
67
- /**
68
- The unique RecordIdentifier associated with this Snapshot.
69
-
70
- @property identifier
71
- @public
72
- @type {StableRecordIdentifier}
73
- */
74
- this.identifier = identifier;
75
-
76
- /*
77
- If the we do not yet have a record, then we are
78
- likely a snapshot being provided to a find request, so we
79
- populate __attributes lazily. Else, to preserve the "moment
80
- in time" in which a snapshot is created, we greedily grab
81
- the values.
82
- */
83
- if (hasRecord) {
84
- this._attributes;
85
- }
86
-
87
- /**
88
- The id of the snapshot's underlying record
89
-
90
- Example
91
-
92
- ```javascript
93
- // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
94
- postSnapshot.id; // => '1'
95
- ```
96
-
97
- @property id
98
- @type {String}
99
- @public
100
- */
101
- this.id = identifier.id;
102
-
103
- /**
104
- A hash of adapter options
105
- @property adapterOptions
106
- @type {Object}
107
- @public
108
- */
109
- this.adapterOptions = options.adapterOptions;
110
-
111
- /**
112
- If `include` was passed to the options hash for the request, the value
113
- would be available here.
114
-
115
- @property include
116
- @type {String|Array}
117
- @public
118
- */
119
- this.include = options.include;
120
-
121
- /**
122
- The name of the type of the underlying record for this snapshot, as a string.
123
-
124
- @property modelName
125
- @type {String}
126
- @public
127
- */
128
- this.modelName = identifier.type;
129
- if (hasRecord) {
130
- this._changedAttributes = this._store._instanceCache.getRecordData(identifier).changedAttrs(identifier);
131
- }
132
- }
133
-
134
- /**
135
- The underlying record for this snapshot. Can be used to access methods and
136
- properties defined on the record.
137
-
138
- Example
139
-
140
- ```javascript
141
- let json = snapshot.record.toJSON();
142
- ```
143
-
144
- @property record
145
- @type {Model}
146
- @public
147
- */
148
- get record(): RecordInstance {
149
- return this._store._instanceCache.getRecord(this.identifier);
150
- }
151
-
152
- get _attributes(): Dict<any> {
153
- if (this.__attributes !== null) {
154
- return this.__attributes;
155
- }
156
- let attributes = (this.__attributes = Object.create(null));
157
- const { identifier } = this;
158
- let attrs = Object.keys(this._store.getSchemaDefinitionService().attributesDefinitionFor(identifier));
159
- let recordData = this._store._instanceCache.getRecordData(identifier);
160
-
161
- attrs.forEach((keyName) => {
162
- attributes[keyName] = recordData.getAttr(identifier, keyName);
163
- });
164
-
165
- return attributes;
166
- }
167
-
168
- /**
169
- The type of the underlying record for this snapshot, as a Model.
170
-
171
- @property type
172
- @public
173
- @deprecated
174
- @type {Model}
175
- */
176
-
177
- get isNew(): boolean {
178
- const recordData = this._store._instanceCache.peek({ identifier: this.identifier, bucket: 'recordData' });
179
- return recordData?.isNew(this.identifier) || false;
180
- }
181
-
182
- /**
183
- Returns the value of an attribute.
184
-
185
- Example
186
-
187
- ```javascript
188
- // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
189
- postSnapshot.attr('author'); // => 'Tomster'
190
- postSnapshot.attr('title'); // => 'Ember.js rocks'
191
- ```
192
-
193
- Note: Values are loaded eagerly and cached when the snapshot is created.
194
-
195
- @method attr
196
- @param {String} keyName
197
- @return {Object} The attribute value or undefined
198
- @public
199
- */
200
- attr(keyName: string): unknown {
201
- if (keyName in this._attributes) {
202
- return this._attributes[keyName];
203
- }
204
- assert(`Model '${this.identifier}' has no attribute named '${keyName}' defined.`, false);
205
- }
206
-
207
- /**
208
- Returns all attributes and their corresponding values.
209
-
210
- Example
211
-
212
- ```javascript
213
- // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
214
- postSnapshot.attributes(); // => { author: 'Tomster', title: 'Ember.js rocks' }
215
- ```
216
-
217
- @method attributes
218
- @return {Object} All attributes of the current snapshot
219
- @public
220
- */
221
- attributes(): Dict<unknown> {
222
- return { ...this._attributes };
223
- }
224
-
225
- /**
226
- Returns all changed attributes and their old and new values.
227
-
228
- Example
229
-
230
- ```javascript
231
- // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
232
- postModel.set('title', 'Ember.js rocks!');
233
- postSnapshot.changedAttributes(); // => { title: ['Ember.js rocks', 'Ember.js rocks!'] }
234
- ```
235
-
236
- @method changedAttributes
237
- @return {Object} All changed attributes of the current snapshot
238
- @public
239
- */
240
- changedAttributes(): ChangedAttributesHash {
241
- let changedAttributes = Object.create(null);
242
- if (!this._changedAttributes) {
243
- return changedAttributes;
244
- }
245
-
246
- let changedAttributeKeys = Object.keys(this._changedAttributes);
247
-
248
- for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
249
- let key = changedAttributeKeys[i];
250
- changedAttributes[key] = this._changedAttributes[key].slice();
251
- }
252
-
253
- return changedAttributes;
254
- }
255
-
256
- /**
257
- Returns the current value of a belongsTo relationship.
258
-
259
- `belongsTo` takes an optional hash of options as a second parameter,
260
- currently supported options are:
261
-
262
- - `id`: set to `true` if you only want the ID of the related record to be
263
- returned.
264
-
265
- Example
266
-
267
- ```javascript
268
- // store.push('post', { id: 1, title: 'Hello World' });
269
- // store.createRecord('comment', { body: 'Lorem ipsum', post: post });
270
- commentSnapshot.belongsTo('post'); // => Snapshot
271
- commentSnapshot.belongsTo('post', { id: true }); // => '1'
272
-
273
- // store.push('comment', { id: 1, body: 'Lorem ipsum' });
274
- commentSnapshot.belongsTo('post'); // => undefined
275
- ```
276
-
277
- Calling `belongsTo` will return a new Snapshot as long as there's any known
278
- data for the relationship available, such as an ID. If the relationship is
279
- known but unset, `belongsTo` will return `null`. If the contents of the
280
- relationship is unknown `belongsTo` will return `undefined`.
281
-
282
- Note: Relationships are loaded lazily and cached upon first access.
283
-
284
- @method belongsTo
285
- @param {String} keyName
286
- @param {Object} [options]
287
- @public
288
- @return {(Snapshot|String|null|undefined)} A snapshot or ID of a known
289
- relationship or null if the relationship is known but unset. undefined
290
- will be returned if the contents of the relationship is unknown.
291
- */
292
- belongsTo(keyName: string, options?: { id?: boolean }): Snapshot | RecordId | undefined {
293
- let returnModeIsId = !!(options && options.id);
294
- let result: Snapshot | RecordId | undefined;
295
- let store = this._store;
296
-
297
- if (returnModeIsId === true && keyName in this._belongsToIds) {
298
- return this._belongsToIds[keyName];
299
- }
300
-
301
- if (returnModeIsId === false && keyName in this._belongsToRelationships) {
302
- return this._belongsToRelationships[keyName];
303
- }
304
-
305
- let relationshipMeta = store.getSchemaDefinitionService().relationshipsDefinitionFor({ type: this.modelName })[
306
- keyName
307
- ];
308
- assert(
309
- `Model '${this.identifier}' has no belongsTo relationship named '${keyName}' defined.`,
310
- relationshipMeta && relationshipMeta.kind === 'belongsTo'
311
- );
312
-
313
- // TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
314
- // this check is not a regression in behavior because relationships don't currently
315
- // function without access to intimate API contracts between RecordData and Model.
316
- // This is a requirement we should fix as soon as the relationship layer does not require
317
- // this intimate API usage.
318
- if (!HAS_RECORD_DATA_PACKAGE) {
319
- assert(`snapshot.belongsTo only supported when using the package @ember-data/record-data`);
320
- }
321
-
322
- const graphFor = (
323
- importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
324
- ).graphFor;
325
- const { identifier } = this;
326
- const relationship = graphFor(this._store).get(identifier, keyName) as BelongsToRelationship;
327
-
328
- assert(
329
- `You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but no such relationship was found.`,
330
- relationship
331
- );
332
- assert(
333
- `You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but that relationship is a hasMany.`,
334
- relationship.definition.kind === 'belongsTo'
335
- );
336
-
337
- let value = relationship.getData();
338
- let data = value && value.data;
339
-
340
- let inverseIdentifier = data ? store.identifierCache.getOrCreateRecordIdentifier(data) : null;
341
-
342
- if (value && value.data !== undefined) {
343
- if (inverseIdentifier && !store._instanceCache.getRecordData(inverseIdentifier).isDeleted(inverseIdentifier)) {
344
- if (returnModeIsId) {
345
- result = inverseIdentifier.id;
346
- } else {
347
- result = store._instanceCache.createSnapshot(inverseIdentifier);
348
- }
349
- } else {
350
- result = null;
351
- }
352
- }
353
-
354
- if (returnModeIsId) {
355
- this._belongsToIds[keyName] = result as RecordId;
356
- } else {
357
- this._belongsToRelationships[keyName] = result as Snapshot;
358
- }
359
-
360
- return result;
361
- }
362
-
363
- /**
364
- Returns the current value of a hasMany relationship.
365
-
366
- `hasMany` takes an optional hash of options as a second parameter,
367
- currently supported options are:
368
-
369
- - `ids`: set to `true` if you only want the IDs of the related records to be
370
- returned.
371
-
372
- Example
373
-
374
- ```javascript
375
- // store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] });
376
- postSnapshot.hasMany('comments'); // => [Snapshot, Snapshot]
377
- postSnapshot.hasMany('comments', { ids: true }); // => ['2', '3']
378
-
379
- // store.push('post', { id: 1, title: 'Hello World' });
380
- postSnapshot.hasMany('comments'); // => undefined
381
- ```
382
-
383
- Note: Relationships are loaded lazily and cached upon first access.
384
-
385
- @method hasMany
386
- @param {String} keyName
387
- @param {Object} [options]
388
- @public
389
- @return {(Array|undefined)} An array of snapshots or IDs of a known
390
- relationship or an empty array if the relationship is known but unset.
391
- undefined will be returned if the contents of the relationship is unknown.
392
- */
393
- hasMany(keyName: string, options?: { ids?: boolean }): RecordId[] | Snapshot[] | undefined {
394
- let returnModeIsIds = !!(options && options.ids);
395
- let results: RecordId[] | Snapshot[] | undefined;
396
- let cachedIds: RecordId[] | undefined = this._hasManyIds[keyName];
397
- let cachedSnapshots: Snapshot[] | undefined = this._hasManyRelationships[keyName];
398
-
399
- if (returnModeIsIds === true && keyName in this._hasManyIds) {
400
- return cachedIds;
401
- }
402
-
403
- if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
404
- return cachedSnapshots;
405
- }
406
-
407
- let store = this._store;
408
- let relationshipMeta = store.getSchemaDefinitionService().relationshipsDefinitionFor({ type: this.modelName })[
409
- keyName
410
- ];
411
- assert(
412
- `Model '${this.identifier}' has no hasMany relationship named '${keyName}' defined.`,
413
- relationshipMeta && relationshipMeta.kind === 'hasMany'
414
- );
415
-
416
- // TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
417
- // this check is not a regression in behavior because relationships don't currently
418
- // function without access to intimate API contracts between RecordData and Model.
419
- // This is a requirement we should fix as soon as the relationship layer does not require
420
- // this intimate API usage.
421
- if (!HAS_RECORD_DATA_PACKAGE) {
422
- assert(`snapshot.hasMany only supported when using the package @ember-data/record-data`);
423
- }
424
-
425
- const graphFor = (
426
- importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
427
- ).graphFor;
428
- const { identifier } = this;
429
- const relationship = graphFor(this._store).get(identifier, keyName) as ManyRelationship;
430
- assert(
431
- `You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but no such relationship was found.`,
432
- relationship
433
- );
434
- assert(
435
- `You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but that relationship is a belongsTo.`,
436
- relationship.definition.kind === 'hasMany'
437
- );
438
-
439
- let value = relationship.getData();
440
-
441
- if (value.data) {
442
- results = [];
443
- value.data.forEach((member) => {
444
- let inverseIdentifier = store.identifierCache.getOrCreateRecordIdentifier(member);
445
- if (!store._instanceCache.getRecordData(inverseIdentifier).isDeleted(inverseIdentifier)) {
446
- if (returnModeIsIds) {
447
- (results as RecordId[]).push(inverseIdentifier.id);
448
- } else {
449
- (results as Snapshot[]).push(store._instanceCache.createSnapshot(inverseIdentifier));
450
- }
451
- }
452
- });
453
- }
454
-
455
- // we assign even if `undefined` so that we don't reprocess the relationship
456
- // on next access. This works with the `keyName in` checks above.
457
- if (returnModeIsIds) {
458
- this._hasManyIds[keyName] = results as RecordId[];
459
- } else {
460
- this._hasManyRelationships[keyName] = results as Snapshot[];
461
- }
462
-
463
- return results;
464
- }
465
-
466
- /**
467
- Iterates through all the attributes of the model, calling the passed
468
- function on each attribute.
469
-
470
- Example
471
-
472
- ```javascript
473
- snapshot.eachAttribute(function(name, meta) {
474
- // ...
475
- });
476
- ```
477
-
478
- @method eachAttribute
479
- @param {Function} callback the callback to execute
480
- @param {Object} [binding] the value to which the callback's `this` should be bound
481
- @public
482
- */
483
- eachAttribute(callback: (key: string, meta: AttributeSchema) => void, binding?: unknown): void {
484
- let attrDefs = this._store.getSchemaDefinitionService().attributesDefinitionFor(this.identifier);
485
- Object.keys(attrDefs).forEach((key) => {
486
- callback.call(binding, key, attrDefs[key] as AttributeSchema);
487
- });
488
- }
489
-
490
- /**
491
- Iterates through all the relationships of the model, calling the passed
492
- function on each relationship.
493
-
494
- Example
495
-
496
- ```javascript
497
- snapshot.eachRelationship(function(name, relationship) {
498
- // ...
499
- });
500
- ```
501
-
502
- @method eachRelationship
503
- @param {Function} callback the callback to execute
504
- @param {Object} [binding] the value to which the callback's `this` should be bound
505
- @public
506
- */
507
- eachRelationship(callback: (key: string, meta: RelationshipSchema) => void, binding?: unknown): void {
508
- let relationshipDefs = this._store.getSchemaDefinitionService().relationshipsDefinitionFor(this.identifier);
509
- Object.keys(relationshipDefs).forEach((key) => {
510
- callback.call(binding, key, relationshipDefs[key] as RelationshipSchema);
511
- });
512
- }
513
-
514
- /**
515
- Serializes the snapshot using the serializer for the model.
516
-
517
- Example
518
-
519
- ```app/adapters/application.js
520
- import Adapter from '@ember-data/adapter';
521
-
522
- export default Adapter.extend({
523
- createRecord(store, type, snapshot) {
524
- let data = snapshot.serialize({ includeId: true });
525
- let url = `/${type.modelName}`;
526
-
527
- return fetch(url, {
528
- method: 'POST',
529
- body: data,
530
- }).then((response) => response.json())
531
- }
532
- });
533
- ```
534
-
535
- @method serialize
536
- @param {Object} options
537
- @return {Object} an object whose values are primitive JSON values only
538
- @public
539
- */
540
- serialize(options?: OptionsHash): unknown {
541
- const serializer = this._store.serializerFor(this.modelName);
542
- assert(`Cannot serialize record, no serializer found`, serializer);
543
- return serializer.serialize(this, options);
544
- }
545
- }
546
-
547
- if (DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS) {
548
- Object.defineProperty(Snapshot.prototype, 'type', {
549
- get() {
550
- deprecate(
551
- `Using Snapshot.type to access the ModelClass for a record is deprecated. Use store.modelFor(<modelName>) instead.`,
552
- false,
553
- {
554
- id: 'ember-data:deprecate-snapshot-model-class-access',
555
- until: '5.0',
556
- for: 'ember-data',
557
- since: { available: '4.5.0', enabled: '4.5.0' },
558
- }
559
- );
560
- return this._store.modelFor(this.identifier.type);
561
- },
562
- });
563
- }