@ember-data/store 4.4.0 → 4.5.0-alpha.2

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 (33) hide show
  1. package/addon/-private/system/core-store.ts +136 -147
  2. package/addon/-private/system/ds-model-store.ts +1 -10
  3. package/addon/-private/system/fetch-manager.ts +48 -21
  4. package/addon/-private/system/model/internal-model.ts +263 -192
  5. package/addon/-private/system/model/states.js +5 -41
  6. package/addon/-private/system/{promise-proxies.js → promise-proxies.ts} +31 -21
  7. package/addon/-private/system/promise-proxy-base.js +7 -0
  8. package/addon/-private/system/{record-array-manager.js → record-array-manager.ts} +87 -60
  9. package/addon/-private/system/record-arrays/adapter-populated-record-array.ts +129 -0
  10. package/addon/-private/system/record-arrays/{record-array.js → record-array.ts} +96 -75
  11. package/addon/-private/system/record-data-for.ts +2 -0
  12. package/addon/-private/system/references/belongs-to.ts +3 -2
  13. package/addon/-private/system/references/has-many.ts +4 -2
  14. package/addon/-private/system/schema-definition-service.ts +2 -2
  15. package/addon/-private/system/snapshot-record-array.ts +12 -11
  16. package/addon/-private/system/snapshot.ts +24 -7
  17. package/addon/-private/system/store/common.js +24 -1
  18. package/addon/-private/system/store/finders.js +53 -5
  19. package/addon/-private/system/store/internal-model-factory.ts +8 -7
  20. package/addon/-private/system/store/record-data-store-wrapper.ts +7 -2
  21. package/addon/-private/system/store/serializer-response.ts +85 -0
  22. package/addon/-private/ts-interfaces/ds-model.ts +15 -7
  23. package/addon/-private/ts-interfaces/ember-data-json-api.ts +3 -0
  24. package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +19 -20
  25. package/addon/-private/ts-interfaces/minimum-serializer-interface.ts +27 -6
  26. package/addon/-private/ts-interfaces/record-data.ts +4 -1
  27. package/addon/-private/ts-interfaces/record-instance.ts +3 -1
  28. package/addon/-private/ts-interfaces/store.ts +1 -0
  29. package/addon/-private/utils/promise-record.ts +3 -3
  30. package/index.js +3 -0
  31. package/package.json +7 -6
  32. package/addon/-private/system/record-arrays/adapter-populated-record-array.js +0 -95
  33. package/addon/-private/system/store/serializer-response.js +0 -71
@@ -0,0 +1,129 @@
1
+ import type NativeArray from '@ember/array/-private/native-array';
2
+ import { assert } from '@ember/debug';
3
+
4
+ import type { PromiseArray, RecordArrayManager } from 'ember-data/-private';
5
+
6
+ import type { CollectionResourceDocument, Links, Meta, PaginationLinks } from '../../ts-interfaces/ember-data-json-api';
7
+ import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
8
+ import type { RecordInstance } from '../../ts-interfaces/record-instance';
9
+ import type { FindOptions } from '../../ts-interfaces/store';
10
+ import type { Dict } from '../../ts-interfaces/utils';
11
+ import type CoreStore from '../core-store';
12
+ import { promiseArray } from '../promise-proxies';
13
+ import SnapshotRecordArray from '../snapshot-record-array';
14
+ import RecordArray from './record-array';
15
+
16
+ export interface AdapterPopulatedRecordArrayCreateArgs {
17
+ modelName: string;
18
+ store: CoreStore;
19
+ manager: RecordArrayManager;
20
+ content: NativeArray<StableRecordIdentifier>;
21
+ isLoaded: boolean;
22
+ query?: Dict<unknown>;
23
+ meta?: Meta;
24
+ links?: Links | PaginationLinks | null;
25
+ }
26
+
27
+ /**
28
+ @module @ember-data/store
29
+ */
30
+
31
+ /**
32
+ Represents an ordered list of records whose order and membership is
33
+ determined by the adapter. For example, a query sent to the adapter
34
+ may trigger a search on the server, whose results would be loaded
35
+ into an instance of the `AdapterPopulatedRecordArray`.
36
+
37
+ This class should not be imported and instantiated by consuming applications.
38
+
39
+ ---
40
+
41
+ If you want to update the array and get the latest records from the
42
+ adapter, you can invoke [`update()`](AdapterPopulatedRecordArray/methods/update?anchor=update):
43
+
44
+ Example
45
+
46
+ ```javascript
47
+ // GET /users?isAdmin=true
48
+ store.query('user', { isAdmin: true }).then(function(admins) {
49
+
50
+ admins.then(function() {
51
+ console.log(admins.get("length")); // 42
52
+ });
53
+
54
+ // somewhere later in the app code, when new admins have been created
55
+ // in the meantime
56
+ //
57
+ // GET /users?isAdmin=true
58
+ admins.update().then(function() {
59
+ admins.get('isUpdating'); // false
60
+ console.log(admins.get("length")); // 123
61
+ });
62
+
63
+ admins.get('isUpdating'); // true
64
+ }
65
+ ```
66
+
67
+ @class AdapterPopulatedRecordArray
68
+ @public
69
+ @extends RecordArray
70
+ */
71
+ export default class AdapterPopulatedRecordArray extends RecordArray {
72
+ declare links: Links | PaginationLinks | null;
73
+ declare meta: Dict<unknown> | null;
74
+ declare query: Dict<unknown> | null;
75
+
76
+ init(props?: AdapterPopulatedRecordArrayCreateArgs) {
77
+ assert(`Cannot initialize AdapterPopulatedRecordArray with isUpdating`, !props || !('isUpdating' in props));
78
+ super.init();
79
+ this.query = this.query || null;
80
+ this.links = this.links || null;
81
+ this.meta = this.meta || null;
82
+ }
83
+
84
+ replace() {
85
+ throw new Error(`The result of a server query (on ${this.modelName}) is immutable.`);
86
+ }
87
+
88
+ _update(): PromiseArray<RecordInstance, AdapterPopulatedRecordArray> {
89
+ const { store, query } = this;
90
+
91
+ // TODO save options from initial request?
92
+ return promiseArray(store._query(this.modelName, query, this, {}));
93
+ }
94
+
95
+ _setObjects(identifiers: StableRecordIdentifier[], payload: CollectionResourceDocument) {
96
+ // TODO: initial load should not cause change events at all, only
97
+ // subsequent. This requires changing the public api of adapter.query, but
98
+ // hopefully we can do that soon.
99
+ this.content.setObjects(identifiers);
100
+
101
+ this.setProperties({
102
+ isLoaded: true,
103
+ isUpdating: false,
104
+ // TODO this assign kills the root reference but a deep-copy would be required
105
+ // for both meta and links to actually not be by-ref. We whould likely change
106
+ // this to a dev-only deep-freeze.
107
+ meta: Object.assign({}, payload.meta),
108
+ links: Object.assign({}, payload.links),
109
+ });
110
+
111
+ this.manager._associateWithRecordArray(identifiers, this);
112
+ }
113
+
114
+ _createSnapshot(options: FindOptions) {
115
+ // this is private for users, but public for ember-data internals
116
+ // meta will only be present for an AdapterPopulatedRecordArray
117
+ return new SnapshotRecordArray(this, this.meta, options);
118
+ }
119
+
120
+ /**
121
+ @method _setIdentifiers
122
+ @param {StableRecordIdentifier[]} identifiers
123
+ @param {Object} payload normalized payload
124
+ @private
125
+ */
126
+ _setIdentifiers(identifiers: StableRecordIdentifier[], payload: CollectionResourceDocument): void {
127
+ this._setObjects(identifiers, payload);
128
+ }
129
+ }
@@ -1,19 +1,37 @@
1
1
  /**
2
2
  @module @ember-data/store
3
3
  */
4
+ import type NativeArray from '@ember/array/-private/native-array';
4
5
  import ArrayProxy from '@ember/array/proxy';
6
+ import { assert } from '@ember/debug';
5
7
  import { computed, get, set } from '@ember/object';
8
+ import { tracked } from '@glimmer/tracking';
6
9
 
7
10
  import { Promise } from 'rsvp';
8
11
 
9
- import { PromiseArray } from '../promise-proxies';
12
+ import type { RecordArrayManager, Snapshot } from 'ember-data/-private';
13
+
14
+ import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
15
+ import type { RecordInstance } from '../../ts-interfaces/record-instance';
16
+ import type { FindOptions } from '../../ts-interfaces/store';
17
+ import type CoreStore from '../core-store';
18
+ import type { PromiseArray } from '../promise-proxies';
19
+ import { promiseArray } from '../promise-proxies';
10
20
  import SnapshotRecordArray from '../snapshot-record-array';
11
21
  import { internalModelFactoryFor } from '../store/internal-model-factory';
12
22
 
13
- function recordForIdentifier(store, identifier) {
23
+ function recordForIdentifier(store: CoreStore, identifier: StableRecordIdentifier): RecordInstance {
14
24
  return internalModelFactoryFor(store).lookup(identifier).getRecord();
15
25
  }
16
26
 
27
+ export interface RecordArrayCreateArgs {
28
+ modelName: string;
29
+ store: CoreStore;
30
+ manager: RecordArrayManager;
31
+ content: NativeArray<StableRecordIdentifier>;
32
+ isLoaded: boolean;
33
+ }
34
+
17
35
  /**
18
36
  A record array is an array that contains records of a certain modelName. The record
19
37
  array materializes records as needed when they are retrieved for the first
@@ -27,24 +45,21 @@ function recordForIdentifier(store, identifier) {
27
45
  @public
28
46
  @extends Ember.ArrayProxy
29
47
  */
48
+ export default class RecordArray extends ArrayProxy<StableRecordIdentifier, RecordInstance> {
49
+ /**
50
+ The array of client ids backing the record array. When a
51
+ record is requested from the record array, the record
52
+ for the client id at the same index is materialized, if
53
+ necessary, by the store.
30
54
 
31
- let RecordArray = ArrayProxy.extend({
32
- init(args) {
33
- this._super(args);
34
-
35
- /**
36
- The array of client ids backing the record array. When a
37
- record is requested from the record array, the record
38
- for the client id at the same index is materialized, if
39
- necessary, by the store.
40
-
41
- @property content
42
- @private
43
- @type Ember.Array
44
- */
45
- this.set('content', this.content || null);
46
-
47
- /**
55
+ @property content
56
+ @private
57
+ @type Ember.Array
58
+ */
59
+ declare content: NativeArray<StableRecordIdentifier>;
60
+ declare _getDeprecatedEventedInfo: () => string;
61
+ declare modelName: string;
62
+ /**
48
63
  The flag to signal a `RecordArray` is finished loading data.
49
64
 
50
65
  Example
@@ -57,42 +72,49 @@ let RecordArray = ArrayProxy.extend({
57
72
  @property isLoaded
58
73
  @public
59
74
  @type Boolean
75
+ */
76
+ declare isLoaded: boolean;
77
+ /**
78
+ The store that created this record array.
79
+
80
+ @property store
81
+ @private
82
+ @type Store
60
83
  */
61
- this.isLoaded = this.isLoaded || false;
62
- /**
63
- The flag to signal a `RecordArray` is currently loading data.
84
+ declare store: CoreStore;
85
+ declare _updatingPromise: PromiseArray<RecordInstance, RecordArray> | null;
86
+ declare manager: RecordArrayManager;
64
87
 
88
+ /**
89
+ The flag to signal a `RecordArray` is currently loading data.
65
90
  Example
66
-
67
91
  ```javascript
68
92
  let people = store.peekAll('person');
69
93
  people.get('isUpdating'); // false
70
94
  people.update();
71
95
  people.get('isUpdating'); // true
72
96
  ```
73
-
74
97
  @property isUpdating
75
98
  @public
76
99
  @type Boolean
77
- */
78
- this.isUpdating = false;
100
+ */
101
+ @tracked isUpdating: boolean = false;
79
102
 
80
- /**
81
- The store that created this record array.
103
+ init(props?: RecordArrayCreateArgs) {
104
+ assert(`Cannot initialize RecordArray with isUpdating`, !props || !('isUpdating' in props));
105
+ assert(`Cannot initialize RecordArray with isUpdating`, !props || !('_updatingPromise' in props));
106
+ super.init();
82
107
 
83
- @property store
84
- @private
85
- @type Store
86
- */
87
- this.store = this.store || null;
108
+ // TODO can we get rid of this?
109
+ this.set('content', this.content || null);
88
110
  this._updatingPromise = null;
89
- },
111
+ }
90
112
 
91
113
  replace() {
92
114
  throw new Error(
93
115
  `The result of a server query (for all ${this.modelName} types) is immutable. To modify contents, use toArray()`
94
116
  );
95
- },
117
+ }
96
118
 
97
119
  /**
98
120
  The modelClass represented by this record array.
@@ -101,12 +123,13 @@ let RecordArray = ArrayProxy.extend({
101
123
  @public
102
124
  @type {subclass of Model}
103
125
  */
104
- type: computed('modelName', function () {
126
+ @computed('modelName')
127
+ get type() {
105
128
  if (!this.modelName) {
106
129
  return null;
107
130
  }
108
131
  return this.store.modelFor(this.modelName);
109
- }).readOnly(),
132
+ }
110
133
 
111
134
  /**
112
135
  Retrieves an object from the content by index.
@@ -116,10 +139,10 @@ let RecordArray = ArrayProxy.extend({
116
139
  @param {Number} index
117
140
  @return {Model} record
118
141
  */
119
- objectAtContent(index) {
142
+ objectAtContent(index: number): RecordInstance | undefined {
120
143
  let identifier = get(this, 'content').objectAt(index);
121
144
  return identifier ? recordForIdentifier(this.store, identifier) : undefined;
122
- },
145
+ }
123
146
 
124
147
  /**
125
148
  Used to get the latest version of all of the records in this array
@@ -141,33 +164,34 @@ let RecordArray = ArrayProxy.extend({
141
164
  @method update
142
165
  @public
143
166
  */
144
- update() {
145
- if (get(this, 'isUpdating')) {
146
- return this._updatingPromise;
167
+ update(): PromiseArray<RecordInstance, RecordArray> {
168
+ if (this.isUpdating) {
169
+ return this._updatingPromise!;
147
170
  }
148
171
 
149
- this.set('isUpdating', true);
172
+ this.isUpdating = true;
150
173
 
151
- let updatingPromise = this._update().finally(() => {
174
+ let updatingPromise = this._update();
175
+ updatingPromise.finally(() => {
152
176
  this._updatingPromise = null;
153
- if (this.get('isDestroying') || this.get('isDestroyed')) {
177
+ if (this.isDestroying || this.isDestroyed) {
154
178
  return;
155
179
  }
156
- this.set('isUpdating', false);
180
+ this.isUpdating = false;
157
181
  });
158
182
 
159
183
  this._updatingPromise = updatingPromise;
160
184
 
161
185
  return updatingPromise;
162
- },
186
+ }
163
187
 
164
188
  /*
165
189
  Update this RecordArray and return a promise which resolves once the update
166
190
  is finished.
167
191
  */
168
- _update() {
192
+ _update(): PromiseArray<RecordInstance, RecordArray> {
169
193
  return this.store.findAll(this.modelName, { reload: true });
170
- },
194
+ }
171
195
 
172
196
  /**
173
197
  Saves all of the records in the `RecordArray`.
@@ -186,7 +210,7 @@ let RecordArray = ArrayProxy.extend({
186
210
  @public
187
211
  @return {PromiseArray} promise
188
212
  */
189
- save() {
213
+ save(): PromiseArray<RecordInstance, RecordArray> {
190
214
  let promiseLabel = `DS: RecordArray#save ${this.modelName}`;
191
215
  let promise = Promise.all(this.invoke('save'), promiseLabel).then(
192
216
  () => this,
@@ -194,8 +218,8 @@ let RecordArray = ArrayProxy.extend({
194
218
  'DS: RecordArray#save return RecordArray'
195
219
  );
196
220
 
197
- return PromiseArray.create({ promise });
198
- },
221
+ return promiseArray<RecordInstance, RecordArray>(promise);
222
+ }
199
223
 
200
224
  /**
201
225
  @method _unregisterFromManager
@@ -203,7 +227,7 @@ let RecordArray = ArrayProxy.extend({
203
227
  */
204
228
  _unregisterFromManager() {
205
229
  this.manager.unregisterRecordArray(this);
206
- },
230
+ }
207
231
 
208
232
  willDestroy() {
209
233
  this._unregisterFromManager();
@@ -215,33 +239,34 @@ let RecordArray = ArrayProxy.extend({
215
239
  // * the exception being: if an dominator has a reference to this object,
216
240
  // and must be informed to release e.g. e.g. removing itself from th
217
241
  // recordArrayMananger
218
- set(this, 'content', null);
242
+ set(this, 'content', null as unknown as NativeArray<StableRecordIdentifier>);
219
243
  set(this, 'length', 0);
220
- this._super(...arguments);
221
- },
244
+ super.willDestroy();
245
+ }
222
246
 
223
247
  /**
224
248
  @method _createSnapshot
225
249
  @private
226
250
  */
227
- _createSnapshot(options) {
251
+ _createSnapshot(options: FindOptions) {
228
252
  // this is private for users, but public for ember-data internals
229
- return new SnapshotRecordArray(this, this.get('meta'), options);
230
- },
253
+ // meta will only be present for an AdapterPopulatedRecordArray
254
+ return new SnapshotRecordArray(this, null, options);
255
+ }
231
256
 
232
257
  /**
233
258
  @method _dissociateFromOwnRecords
234
259
  @internal
235
260
  */
236
261
  _dissociateFromOwnRecords() {
237
- this.get('content').forEach((identifier) => {
262
+ this.content.forEach((identifier) => {
238
263
  let recordArrays = this.manager.getRecordArraysForIdentifier(identifier);
239
264
 
240
265
  if (recordArrays) {
241
266
  recordArrays.delete(this);
242
267
  }
243
268
  });
244
- },
269
+ }
245
270
 
246
271
  /**
247
272
  Adds identifiers to the `RecordArray` without duplicates
@@ -250,9 +275,9 @@ let RecordArray = ArrayProxy.extend({
250
275
  @internal
251
276
  @param {StableRecordIdentifier[]} identifiers
252
277
  */
253
- _pushIdentifiers(identifiers) {
254
- get(this, 'content').pushObjects(identifiers);
255
- },
278
+ _pushIdentifiers(identifiers: StableRecordIdentifier[]): void {
279
+ this.content.pushObjects(identifiers);
280
+ }
256
281
 
257
282
  /**
258
283
  Removes identifiers from the `RecordArray`.
@@ -261,19 +286,15 @@ let RecordArray = ArrayProxy.extend({
261
286
  @internal
262
287
  @param {StableRecordIdentifier[]} identifiers
263
288
  */
264
- _removeIdentifiers(identifiers) {
265
- get(this, 'content').removeObjects(identifiers);
266
- },
289
+ _removeIdentifiers(identifiers: StableRecordIdentifier[]): void {
290
+ this.content.removeObjects(identifiers);
291
+ }
267
292
 
268
293
  /**
269
294
  @method _takeSnapshot
270
295
  @internal
271
296
  */
272
- _takeSnapshot() {
273
- return get(this, 'content').map((identifier) =>
274
- internalModelFactoryFor(this.store).lookup(identifier).createSnapshot()
275
- );
276
- },
277
- });
278
-
279
- export default RecordArray;
297
+ _takeSnapshot(): Snapshot[] {
298
+ return this.content.map((identifier) => internalModelFactoryFor(this.store).lookup(identifier).createSnapshot());
299
+ }
300
+ }
@@ -3,6 +3,7 @@ import { DEBUG } from '@glimmer/env';
3
3
 
4
4
  import type { StableRecordIdentifier } from '../ts-interfaces/identifier';
5
5
  import type { RecordData } from '../ts-interfaces/record-data';
6
+ import type { RecordInstance } from '../ts-interfaces/record-instance';
6
7
  import WeakCache from './weak-cache';
7
8
 
8
9
  /*
@@ -40,6 +41,7 @@ export function removeRecordDataFor(identifier: StableRecordIdentifier): void {
40
41
 
41
42
  export default function recordDataFor(instance: StableRecordIdentifier): RecordData | null;
42
43
  export default function recordDataFor(instance: Instance): RecordData;
44
+ export default function recordDataFor(instance: RecordInstance): RecordData;
43
45
  export default function recordDataFor(instance: object): null;
44
46
  export default function recordDataFor(instance: Instance | object): RecordData | null {
45
47
  if (RecordDataForIdentifierCache.has(instance as StableRecordIdentifier)) {
@@ -8,6 +8,7 @@ import { assertPolymorphicType } from '@ember-data/store/-debug';
8
8
 
9
9
  import { SingleResourceDocument } from '../../ts-interfaces/ember-data-json-api';
10
10
  import { StableRecordIdentifier } from '../../ts-interfaces/identifier';
11
+ import { RecordInstance } from '../../ts-interfaces/record-instance';
11
12
  import CoreStore from '../core-store';
12
13
  import { NotificationType, unsubscribe } from '../record-notification-manager';
13
14
  import { internalModelFactoryFor, recordIdentifierFor } from '../store/internal-model-factory';
@@ -193,7 +194,7 @@ export default class BelongsToReference extends Reference {
193
194
  @param {Object|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
194
195
  @return {Promise<record>} A promise that resolves with the new value in this belongs-to relationship.
195
196
  */
196
- async push(data: SingleResourceDocument | Promise<SingleResourceDocument>): Promise<Object> {
197
+ async push(data: SingleResourceDocument | Promise<SingleResourceDocument>): Promise<RecordInstance> {
197
198
  const jsonApiDoc = await resolve(data);
198
199
  let record = this.store.push(jsonApiDoc);
199
200
 
@@ -267,7 +268,7 @@ export default class BelongsToReference extends Reference {
267
268
  @public
268
269
  @return {Model} the record in this relationship
269
270
  */
270
- value(): Object | null {
271
+ value(): RecordInstance | null {
271
272
  let resource = this._resource();
272
273
  if (resource && resource.data) {
273
274
  let inverseInternalModel = this.store._internalModelForResource(resource.data);
@@ -4,6 +4,8 @@ import { cached, tracked } from '@glimmer/tracking';
4
4
 
5
5
  import { resolve } from 'rsvp';
6
6
 
7
+ import { ManyArray } from 'ember-data/-private';
8
+
7
9
  import type { ManyRelationship } from '@ember-data/record-data/-private';
8
10
  import { assertPolymorphicType } from '@ember-data/store/-debug';
9
11
 
@@ -250,7 +252,7 @@ export default class HasManyReference extends Reference {
250
252
  */
251
253
  async push(
252
254
  objectOrPromise: ExistingResourceObject[] | CollectionResourceDocument | { data: SingleResourceDocument[] }
253
- ): Promise<any> {
255
+ ): Promise<ManyArray> {
254
256
  const payload = await resolve(objectOrPromise);
255
257
  let array: Array<ExistingResourceObject | SingleResourceDocument>;
256
258
 
@@ -291,7 +293,7 @@ export default class HasManyReference extends Reference {
291
293
  });
292
294
 
293
295
  // TODO IGOR it seems wrong that we were returning the many array here
294
- return internalModel.getHasMany(this.key);
296
+ return internalModel.getHasMany(this.key) as Promise<ManyArray> | ManyArray; // this cast is necessary because typescript does not work properly with custom thenables
295
297
  }
296
298
 
297
299
  _isLoaded() {
@@ -1,7 +1,7 @@
1
1
  import { getOwner } from '@ember/application';
2
2
  import { get } from '@ember/object';
3
3
 
4
- import require from 'require';
4
+ import { importSync } from '@embroider/macros';
5
5
 
6
6
  import type Model from '@ember-data/model';
7
7
  import { HAS_MODEL_PACKAGE } from '@ember-data/private-build-infra';
@@ -18,7 +18,7 @@ if (HAS_MODEL_PACKAGE) {
18
18
  let _found;
19
19
  _modelForMixin = function () {
20
20
  if (!_found) {
21
- _found = require('@ember-data/model/-private')._modelForMixin;
21
+ _found = (importSync('@ember-data/model/-private') as typeof import('@ember-data/model/-private'))._modelForMixin;
22
22
  }
23
23
  return _found(...arguments);
24
24
  };
@@ -3,40 +3,41 @@
3
3
  */
4
4
 
5
5
  import type { ModelSchema } from '../ts-interfaces/ds-model';
6
+ import { FindOptions } from '../ts-interfaces/store';
6
7
  import type { Dict } from '../ts-interfaces/utils';
7
8
  import type RecordArray from './record-arrays/record-array';
8
9
  import type Snapshot from './snapshot';
9
10
  /**
10
11
  SnapshotRecordArray is not directly instantiable.
11
12
  Instances are provided to consuming application's
12
- adapters for certain requests.
13
+ adapters for certain requests.
13
14
 
14
15
  @class SnapshotRecordArray
15
16
  @public
16
17
  */
17
18
  export default class SnapshotRecordArray {
18
- private _snapshots: Snapshot[] | null;
19
- private _recordArray: RecordArray | null;
20
- private _type: ModelSchema | null;
19
+ declare _snapshots: Snapshot[] | null;
20
+ declare _recordArray: RecordArray;
21
+ declare _type: ModelSchema | null;
21
22
 
22
- public length: number;
23
- public meta?: Dict<any>;
24
- public adapterOptions: Dict<any>;
25
- public include?: string;
23
+ declare length: number;
24
+ declare meta: Dict<unknown> | null;
25
+ declare adapterOptions?: Dict<unknown>;
26
+ declare include?: string;
26
27
 
27
28
  /**
28
29
  SnapshotRecordArray is not directly instantiable.
29
30
  Instances are provided to consuming application's
30
- adapters and serializers for certain requests.
31
+ adapters and serializers for certain requests.
31
32
 
32
33
  @method constructor
33
34
  @private
34
35
  @constructor
35
36
  @param {RecordArray} recordArray
36
37
  @param {Object} meta
37
- @param options
38
+ @param options
38
39
  */
39
- constructor(recordArray: RecordArray, meta?: Dict<any>, options: Dict<any> = {}) {
40
+ constructor(recordArray: RecordArray, meta: Dict<unknown> | null, options: FindOptions = {}) {
40
41
  /**
41
42
  An array of snapshots
42
43
  @private
@@ -4,10 +4,19 @@
4
4
  import { assert } from '@ember/debug';
5
5
  import { get } from '@ember/object';
6
6
 
7
+ import { importSync } from '@embroider/macros';
8
+
7
9
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
10
+ import type BelongsToRelationship from '@ember-data/record-data/addon/-private/relationships/state/belongs-to';
11
+ import type ManyRelationship from '@ember-data/record-data/addon/-private/relationships/state/has-many';
12
+ import type {
13
+ ExistingResourceIdentifierObject,
14
+ NewResourceIdentifierObject,
15
+ } from '@ember-data/store/-private/ts-interfaces/ember-data-json-api';
8
16
 
9
17
  import type { DSModel, DSModelSchema, ModelSchema } from '../ts-interfaces/ds-model';
10
18
  import type { StableRecordIdentifier } from '../ts-interfaces/identifier';
19
+ import { OptionsHash } from '../ts-interfaces/minimum-serializer-interface';
11
20
  import type { ChangedAttributesHash } from '../ts-interfaces/record-data';
12
21
  import type { AttributeSchema, RelationshipSchema } from '../ts-interfaces/record-data-schemas';
13
22
  import type { RecordInstance } from '../ts-interfaces/record-instance';
@@ -322,9 +331,11 @@ export default class Snapshot implements Snapshot {
322
331
  assert(`snapshot.belongsTo only supported when using the package @ember-data/record-data`);
323
332
  }
324
333
 
325
- const graphFor = require('@ember-data/record-data/-private').graphFor;
334
+ const graphFor = (
335
+ importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
336
+ ).graphFor;
326
337
  const { identifier } = this;
327
- const relationship = graphFor(this._store._storeWrapper).get(identifier, keyName);
338
+ const relationship = graphFor(this._store._storeWrapper).get(identifier, keyName) as BelongsToRelationship;
328
339
 
329
340
  assert(
330
341
  `You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but no such relationship was found.`,
@@ -421,9 +432,11 @@ export default class Snapshot implements Snapshot {
421
432
  assert(`snapshot.hasMany only supported when using the package @ember-data/record-data`);
422
433
  }
423
434
 
424
- const graphFor = require('@ember-data/record-data/-private').graphFor;
435
+ const graphFor = (
436
+ importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
437
+ ).graphFor;
425
438
  const { identifier } = this;
426
- const relationship = graphFor(this._store._storeWrapper).get(identifier, keyName);
439
+ const relationship = graphFor(this._store._storeWrapper).get(identifier, keyName) as ManyRelationship;
427
440
  assert(
428
441
  `You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id}, lid: ${identifier.lid} but no such relationship was found.`,
429
442
  relationship
@@ -441,7 +454,9 @@ export default class Snapshot implements Snapshot {
441
454
  let internalModel = store._internalModelForResource(member);
442
455
  if (!internalModel.isDeleted()) {
443
456
  if (returnModeIsIds) {
444
- (results as RecordId[]).push(member.id || null);
457
+ (results as RecordId[]).push(
458
+ (member as ExistingResourceIdentifierObject | NewResourceIdentifierObject).id || null
459
+ );
445
460
  } else {
446
461
  (results as Snapshot[]).push(internalModel.createSnapshot());
447
462
  }
@@ -534,7 +549,9 @@ export default class Snapshot implements Snapshot {
534
549
  @return {Object} an object whose values are primitive JSON values only
535
550
  @public
536
551
  */
537
- serialize(options: unknown): unknown {
538
- return this._store.serializerFor(this.modelName).serialize(this, options);
552
+ serialize(options?: OptionsHash): unknown {
553
+ const serializer = this._store.serializerFor(this.modelName);
554
+ assert(`Cannot serialize record, no serializer found`, serializer);
555
+ return serializer.serialize(this, options);
539
556
  }
540
557
  }