@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
@@ -1,8 +1,11 @@
1
+ import { deprecate } from '@ember/debug';
1
2
  import { get } from '@ember/object';
2
3
  import { DEBUG } from '@glimmer/env';
3
4
 
4
5
  import { resolve } from 'rsvp';
5
6
 
7
+ import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
8
+
6
9
  /**
7
10
  @module @ember-data/store
8
11
  */
@@ -32,7 +35,27 @@ export function guardDestroyedStore(promise, store, label) {
32
35
  if (DEBUG) {
33
36
  token = store._trackAsyncRequestStart(label);
34
37
  }
35
- let wrapperPromise = resolve(promise, label).then((v) => promise);
38
+ let wrapperPromise = resolve(promise, label).then((_v) => {
39
+ if (!_objectIsAlive(store)) {
40
+ if (DEPRECATE_RSVP_PROMISE) {
41
+ deprecate(
42
+ `A Promise did not resolve by the time the store was destroyed. This will error in a future release.`,
43
+ false,
44
+ {
45
+ id: 'ember-data:rsvp-unresolved-async',
46
+ until: '5.0',
47
+ for: '@ember-data/store',
48
+ since: {
49
+ available: '4.5',
50
+ enabled: '4.5',
51
+ },
52
+ }
53
+ );
54
+ }
55
+ }
56
+
57
+ return promise;
58
+ });
36
59
 
37
60
  return _guard(wrapperPromise, () => {
38
61
  if (DEBUG) {
@@ -1,8 +1,10 @@
1
- import { assert } from '@ember/debug';
1
+ import { assert, deprecate } from '@ember/debug';
2
2
  import { DEBUG } from '@glimmer/env';
3
3
 
4
4
  import { Promise } from 'rsvp';
5
5
 
6
+ import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
7
+
6
8
  import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './common';
7
9
  import { normalizeResponseHelper } from './serializer-response';
8
10
 
@@ -212,10 +214,26 @@ export function _findHasMany(adapter, store, internalModel, link, relationship,
212
214
  let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`;
213
215
 
214
216
  promise = guardDestroyedStore(promise, store, label);
215
- promise = _guard(promise, _bind(_objectIsAlive, internalModel));
216
-
217
- return promise.then(
217
+ promise = promise.then(
218
218
  (adapterPayload) => {
219
+ if (!_objectIsAlive(internalModel)) {
220
+ if (DEPRECATE_RSVP_PROMISE) {
221
+ deprecate(
222
+ `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
223
+ false,
224
+ {
225
+ id: 'ember-data:rsvp-unresolved-async',
226
+ until: '5.0',
227
+ for: '@ember-data/store',
228
+ since: {
229
+ available: '4.5',
230
+ enabled: '4.5',
231
+ },
232
+ }
233
+ );
234
+ }
235
+ }
236
+
219
237
  assert(
220
238
  `You made a 'findHasMany' request for a ${internalModel.modelName}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`,
221
239
  payloadIsNotBlank(adapterPayload)
@@ -236,6 +254,12 @@ export function _findHasMany(adapter, store, internalModel, link, relationship,
236
254
  null,
237
255
  `DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'`
238
256
  );
257
+
258
+ if (DEPRECATE_RSVP_PROMISE) {
259
+ promise = _guard(promise, _bind(_objectIsAlive, internalModel));
260
+ }
261
+
262
+ return promise;
239
263
  }
240
264
 
241
265
  export function _findBelongsTo(adapter, store, internalModel, link, relationship, options) {
@@ -249,8 +273,26 @@ export function _findBelongsTo(adapter, store, internalModel, link, relationship
249
273
  promise = guardDestroyedStore(promise, store, label);
250
274
  promise = _guard(promise, _bind(_objectIsAlive, internalModel));
251
275
 
252
- return promise.then(
276
+ promise = promise.then(
253
277
  (adapterPayload) => {
278
+ if (!_objectIsAlive(internalModel)) {
279
+ if (DEPRECATE_RSVP_PROMISE) {
280
+ deprecate(
281
+ `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
282
+ false,
283
+ {
284
+ id: 'ember-data:rsvp-unresolved-async',
285
+ until: '5.0',
286
+ for: '@ember-data/store',
287
+ since: {
288
+ available: '4.5',
289
+ enabled: '4.5',
290
+ },
291
+ }
292
+ );
293
+ }
294
+ }
295
+
254
296
  let serializer = store.serializerFor(relationship.type);
255
297
  let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
256
298
 
@@ -271,6 +313,12 @@ export function _findBelongsTo(adapter, store, internalModel, link, relationship
271
313
  null,
272
314
  `DS: Extract payload of ${internalModel.modelName} : ${relationship.type}`
273
315
  );
316
+
317
+ if (DEPRECATE_RSVP_PROMISE) {
318
+ promise = _guard(promise, _bind(_objectIsAlive, internalModel));
319
+ }
320
+
321
+ return promise;
274
322
  }
275
323
 
276
324
  export function _findAll(adapter, store, modelName, options) {
@@ -9,6 +9,7 @@ import type {
9
9
  ResourceIdentifierObject,
10
10
  } from '../../ts-interfaces/ember-data-json-api';
11
11
  import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
12
+ import type { RecordData } from '../../ts-interfaces/record-data';
12
13
  import type { RecordInstance } from '../../ts-interfaces/record-instance';
13
14
  import constructResource from '../../utils/construct-resource';
14
15
  import type CoreStore from '../core-store';
@@ -20,19 +21,19 @@ import WeakCache from '../weak-cache';
20
21
  /**
21
22
  @module @ember-data/store
22
23
  */
23
-
24
24
  const FactoryCache = new WeakCache<CoreStore, InternalModelFactory>(DEBUG ? 'internal-model-factory' : '');
25
25
  FactoryCache._generator = (store: CoreStore) => {
26
26
  return new InternalModelFactory(store);
27
27
  };
28
28
  type NewResourceInfo = { type: string; id: string | null };
29
29
 
30
- const RecordCache = new WeakCache<RecordInstance, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
30
+ const RecordCache = new WeakCache<RecordInstance | RecordData, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
31
31
  if (DEBUG) {
32
- RecordCache._expectMsg = (key: RecordInstance) => `${key} is not a record instantiated by @ember-data/store`;
32
+ RecordCache._expectMsg = (key: RecordInstance | RecordData) =>
33
+ `${String(key)} is not a record instantiated by @ember-data/store`;
33
34
  }
34
35
 
35
- export function peekRecordIdentifier(record: any): StableRecordIdentifier | undefined {
36
+ export function peekRecordIdentifier(record: RecordInstance | RecordData): StableRecordIdentifier | undefined {
36
37
  return RecordCache.get(record);
37
38
  }
38
39
 
@@ -60,11 +61,11 @@ export function peekRecordIdentifier(record: any): StableRecordIdentifier | unde
60
61
  @param {Object} record a record instance previously obstained from the store.
61
62
  @returns {StableRecordIdentifier}
62
63
  */
63
- export function recordIdentifierFor(record: RecordInstance): StableRecordIdentifier {
64
+ export function recordIdentifierFor(record: RecordInstance | RecordData): StableRecordIdentifier {
64
65
  return RecordCache.getWithError(record);
65
66
  }
66
67
 
67
- export function setRecordIdentifier(record: RecordInstance, identifier: StableRecordIdentifier): void {
68
+ export function setRecordIdentifier(record: RecordInstance | RecordData, identifier: StableRecordIdentifier): void {
68
69
  if (DEBUG && RecordCache.has(record)) {
69
70
  throw new Error(`${record} was already assigned an identifier`);
70
71
  }
@@ -160,7 +161,7 @@ export default class InternalModelFactory {
160
161
  TODO @runspired consider adding this to make polymorphism even nicer
161
162
  if (HAS_RECORD_DATA_PACKAGE) {
162
163
  if (identifier.type !== matchedIdentifier.type) {
163
- const graphFor = require('@ember-data/record-data/-private').graphFor;
164
+ const graphFor = importSync('@ember-data/record-data/-private').graphFor;
164
165
  graphFor(this).registerPolymorphicType(identifier.type, matchedIdentifier.type);
165
166
  }
166
167
  }
@@ -1,3 +1,5 @@
1
+ import { importSync } from '@embroider/macros';
2
+
1
3
  import type { RelationshipDefinition } from '@ember-data/model/-private/system/relationships/relationship-meta';
2
4
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
3
5
 
@@ -10,6 +12,7 @@ import type {
10
12
  RelationshipsSchema,
11
13
  } from '../../ts-interfaces/record-data-schemas';
12
14
  import type { RecordDataStoreWrapper as StoreWrapper } from '../../ts-interfaces/record-data-store-wrapper';
15
+ import { RecordInstance } from '../../ts-interfaces/record-instance';
13
16
  import constructResource from '../../utils/construct-resource';
14
17
  import type CoreStore from '../core-store';
15
18
  import { internalModelFactoryFor } from './internal-model-factory';
@@ -26,7 +29,9 @@ let peekGraph;
26
29
  if (HAS_RECORD_DATA_PACKAGE) {
27
30
  let _peekGraph;
28
31
  peekGraph = (wrapper) => {
29
- _peekGraph = _peekGraph || require('@ember-data/record-data/-private').peekGraph;
32
+ _peekGraph =
33
+ _peekGraph ||
34
+ (importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')).peekGraph;
30
35
  return _peekGraph(wrapper);
31
36
  };
32
37
  }
@@ -220,7 +225,7 @@ export default class RecordDataStoreWrapper implements StoreWrapper {
220
225
  return false;
221
226
  }
222
227
 
223
- const record = internalModel._record;
228
+ const record = internalModel._record as RecordInstance;
224
229
  return record && !(record.isDestroyed || record.isDestroying);
225
230
  }
226
231
 
@@ -0,0 +1,85 @@
1
+ import { assert } from '@ember/debug';
2
+ import { DEBUG } from '@glimmer/env';
3
+
4
+ import { JsonApiDocument } from '../../ts-interfaces/ember-data-json-api';
5
+ import { AdapterPayload } from '../../ts-interfaces/minimum-adapter-interface';
6
+ import { MinimumSerializerInterface, RequestType } from '../../ts-interfaces/minimum-serializer-interface';
7
+ import CoreStore from '../core-store';
8
+ import ShimModelClass from '../model/shim-model-class';
9
+
10
+ /**
11
+ This is a helper method that validates a JSON API top-level document
12
+
13
+ The format of a document is described here:
14
+ http://jsonapi.org/format/#document-top-level
15
+
16
+ @internal
17
+ */
18
+ function validateDocumentStructure(doc?: AdapterPayload | JsonApiDocument): asserts doc is JsonApiDocument {
19
+ if (DEBUG) {
20
+ let errors: string[] = [];
21
+ if (!doc || typeof doc !== 'object') {
22
+ errors.push('Top level of a JSON API document must be an object');
23
+ } else {
24
+ if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) {
25
+ errors.push('One or more of the following keys must be present: "data", "errors", "meta".');
26
+ } else {
27
+ if ('data' in doc && 'errors' in doc) {
28
+ errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document');
29
+ }
30
+ }
31
+ if ('data' in doc) {
32
+ if (!(doc.data === null || Array.isArray(doc.data) || typeof doc.data === 'object')) {
33
+ errors.push('data must be null, an object, or an array');
34
+ }
35
+ }
36
+ if ('meta' in doc) {
37
+ if (typeof doc.meta !== 'object') {
38
+ errors.push('meta must be an object');
39
+ }
40
+ }
41
+ if ('errors' in doc) {
42
+ if (!Array.isArray(doc.errors)) {
43
+ errors.push('errors must be an array');
44
+ }
45
+ }
46
+ if ('links' in doc) {
47
+ if (typeof doc.links !== 'object') {
48
+ errors.push('links must be an object');
49
+ }
50
+ }
51
+ if ('jsonapi' in doc) {
52
+ if (typeof doc.jsonapi !== 'object') {
53
+ errors.push('jsonapi must be an object');
54
+ }
55
+ }
56
+ if ('included' in doc) {
57
+ if (typeof doc.included !== 'object') {
58
+ errors.push('included must be an array');
59
+ }
60
+ }
61
+ }
62
+
63
+ assert(
64
+ `Response must be normalized to a valid JSON API document:\n\t* ${errors.join('\n\t* ')}`,
65
+ errors.length === 0
66
+ );
67
+ }
68
+ }
69
+
70
+ export function normalizeResponseHelper(
71
+ serializer: MinimumSerializerInterface | null,
72
+ store: CoreStore,
73
+ modelClass: ShimModelClass,
74
+ payload: AdapterPayload,
75
+ id: string | null,
76
+ requestType: RequestType
77
+ ): JsonApiDocument {
78
+ let normalizedResponse = serializer
79
+ ? serializer.normalizeResponse(store, modelClass, payload, id, requestType)
80
+ : payload;
81
+
82
+ validateDocumentStructure(normalizedResponse);
83
+
84
+ return normalizedResponse;
85
+ }
@@ -1,15 +1,20 @@
1
- import EmberObject from '@ember/object';
1
+ import type EmberObject from '@ember/object';
2
2
 
3
- import RSVP from 'rsvp';
3
+ import type { Errors } from '@ember-data/model/-private';
4
4
 
5
+ import type CoreStore from '../system/core-store';
6
+ import type InternalModel from '../system/model/internal-model';
5
7
  import type { JsonApiValidationError } from './record-data-json-api';
6
- import type { AttributeSchema, RelationshipSchema } from './record-data-schemas';
7
- import { RecordInstance } from './record-instance';
8
+ import type { AttributeSchema, RelationshipSchema, RelationshipsSchema } from './record-data-schemas';
8
9
 
9
10
  // Placeholder until model.js is typed
10
- export interface DSModel extends RecordInstance, EmberObject {
11
+ export interface DSModel extends EmberObject {
12
+ constructor: DSModelSchema;
13
+ store: CoreStore;
14
+ errors: Errors;
15
+ _internalModel: InternalModel;
11
16
  toString(): string;
12
- save(): RSVP.Promise<DSModel>;
17
+ save(): Promise<DSModel>;
13
18
  eachRelationship<T>(callback: (this: T, key: string, meta: RelationshipSchema) => void, binding?: T): void;
14
19
  eachAttribute<T>(callback: (this: T, key: string, meta: AttributeSchema) => void, binding?: T): void;
15
20
  invalidErrorsChanged(errors: JsonApiValidationError[]): void;
@@ -17,7 +22,7 @@ export interface DSModel extends RecordInstance, EmberObject {
17
22
  isDeleted: boolean;
18
23
  deleteRecord(): void;
19
24
  unloadRecord(): void;
20
- errors: any;
25
+ _notifyProperties(keys: string[]): void;
21
26
  }
22
27
 
23
28
  // Implemented by both ShimModelClass and DSModel
@@ -39,4 +44,7 @@ export interface ModelSchema {
39
44
  // once we can type it.
40
45
  export interface DSModelSchema extends ModelSchema {
41
46
  isModel: true;
47
+ relationshipsObject: RelationshipsSchema;
48
+ extend(...mixins: unknown[]): DSModelSchema;
49
+ reopenClass(...mixins: unknown[]): void;
42
50
  }
@@ -125,6 +125,9 @@ export interface ExistingResourceObject extends ExistingResourceIdentifierObject
125
125
  interface Document {
126
126
  meta?: Dict<JSONValue>;
127
127
  included?: ExistingResourceObject[];
128
+ jsonapi?: Dict<JSONValue>;
129
+ links?: Dict<string | JSONValue>;
130
+ errors?: JSONValue[];
128
131
  }
129
132
 
130
133
  export interface EmptyResourceDocument extends Document {
@@ -1,7 +1,3 @@
1
- // the above eslint rule checks return types. This is an interface
2
- // and we intend Promise whether it is Native or polyfilled is of
3
- // no consequence.
4
-
5
1
  import type Store from '../system/core-store';
6
2
  import type AdapterPopulatedRecordArray from '../system/record-arrays/adapter-populated-record-array';
7
3
  import type Snapshot from '../system/snapshot';
@@ -11,7 +7,12 @@ import type { RelationshipSchema } from './record-data-schemas';
11
7
  import type { Dict } from './utils';
12
8
 
13
9
  type Group = Snapshot[];
14
-
10
+ // TODO this should probably just alias unknown
11
+ // since in theory a user could pass a blob or a string
12
+ // however those deserialization cases are handled
13
+ // far easier in the adapter itself and are unlikely
14
+ // to be passed to the serializer today.
15
+ export type AdapterPayload = Dict<unknown> | unknown[];
15
16
  /**
16
17
  * @module @ember-data/adapter
17
18
  */
@@ -26,7 +27,7 @@ type Group = Snapshot[];
26
27
  @class MinimumAdapterInterface
27
28
  @public
28
29
  */
29
- interface Adapter {
30
+ export interface MinimumAdapterInterface {
30
31
  /**
31
32
  * `adapter.findRecord` takes a request for a resource of a given `type` and `id` combination
32
33
  * and should return a `Promise` which fulfills with data for a single resource matching that
@@ -54,7 +55,7 @@ interface Adapter {
54
55
  * @param {Snapshot} snapshot
55
56
  * @return {Promise} a promise resolving with resource data to feed to the associated serializer
56
57
  */
57
- findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<unknown>;
58
+ findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<AdapterPayload>;
58
59
 
59
60
  /**
60
61
  * `adapter.findAll` takes a request for resources of a given `type` and should return
@@ -91,7 +92,7 @@ interface Adapter {
91
92
  schema: ModelSchema,
92
93
  sinceToken: null,
93
94
  snapshotRecordArray: SnapshotRecordArray
94
- ): Promise<unknown>;
95
+ ): Promise<AdapterPayload>;
95
96
 
96
97
  /**
97
98
  * `adapter.query` takes a request for resources of a given `type` and should return
@@ -127,10 +128,10 @@ interface Adapter {
127
128
  query(
128
129
  store: Store,
129
130
  schema: ModelSchema,
130
- query: Dict<any>,
131
+ query: Dict<unknown>,
131
132
  recordArray: AdapterPopulatedRecordArray,
132
133
  options: { adapterOptions?: unknown }
133
- ): Promise<unknown>;
134
+ ): Promise<AdapterPayload>;
134
135
 
135
136
  /**
136
137
  * `adapter.queryRecord` takes a request for resource of a given `type` and should return
@@ -158,9 +159,9 @@ interface Adapter {
158
159
  queryRecord(
159
160
  store: Store,
160
161
  schema: ModelSchema,
161
- query: Dict<any>,
162
+ query: Dict<unknown>,
162
163
  options: { adapterOptions?: unknown }
163
- ): Promise<unknown>;
164
+ ): Promise<AdapterPayload>;
164
165
 
165
166
  /**
166
167
  * `adapter.createRecord` takes a request to create a resource of a given `type` and should
@@ -213,7 +214,7 @@ interface Adapter {
213
214
  * @param {Snapshot} snapshot
214
215
  * @return {Promise} a promise resolving with resource data to feed to the associated serializer
215
216
  */
216
- createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
217
+ createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
217
218
 
218
219
  /**
219
220
  * `adapter.updateRecord` takes a request to update a resource of a given `type` and should
@@ -265,7 +266,7 @@ interface Adapter {
265
266
  * the type, attributes and relationships of the primary type associated with the request.
266
267
  * @param {Snapshot} snapshot
267
268
  */
268
- updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
269
+ updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
269
270
 
270
271
  /**
271
272
  * `adapter.deleteRecord` takes a request to delete a resource of a given `type` and
@@ -293,7 +294,7 @@ interface Adapter {
293
294
  * @param {Snapshot} snapshot A Snapshot containing the record's current data
294
295
  * @return
295
296
  */
296
- deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
297
+ deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
297
298
 
298
299
  /**
299
300
  * `adapter.findBelongsTo` takes a request to fetch a related resource located at a
@@ -330,7 +331,7 @@ interface Adapter {
330
331
  snapshot: Snapshot,
331
332
  relatedLink: string,
332
333
  relationship: RelationshipSchema
333
- ): Promise<unknown>;
334
+ ): Promise<AdapterPayload>;
334
335
 
335
336
  /**
336
337
  * `adapter.findHasMany` takes a request to fetch a related resource collection located
@@ -368,7 +369,7 @@ interface Adapter {
368
369
  snapshot: Snapshot,
369
370
  relatedLink: string,
370
371
  relationship: RelationshipSchema
371
- ): Promise<unknown>;
372
+ ): Promise<AdapterPayload>;
372
373
 
373
374
  /**
374
375
  * ⚠️ This Method is only called if `coalesceFindRequests` is `true`. The array passed to it is determined
@@ -399,7 +400,7 @@ interface Adapter {
399
400
  * @param {Array<Snapshot>} snapshots An array of snapshots of the available data for the resources to fetch
400
401
  * @return {Promise} a promise resolving with resource data to feed to the associated serializer
401
402
  */
402
- findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<unknown>;
403
+ findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload>;
403
404
 
404
405
  /**
405
406
  * This method provides the ability to generate an ID to assign to a new record whenever `store.createRecord`
@@ -581,5 +582,3 @@ interface Adapter {
581
582
  */
582
583
  destroy?(): void;
583
584
  }
584
-
585
- export default Adapter;
@@ -4,10 +4,21 @@ import type Store from '../system/core-store';
4
4
  import type Snapshot from '../system/snapshot';
5
5
  import type { ModelSchema } from './ds-model';
6
6
  import type { JsonApiDocument, SingleResourceDocument } from './ember-data-json-api';
7
+ import type { AdapterPayload } from './minimum-adapter-interface';
7
8
  import type { Dict } from './utils';
8
9
 
9
- type OptionsHash = Dict<any>;
10
-
10
+ export type OptionsHash = Dict<unknown>;
11
+ export type RequestType =
12
+ | 'findRecord'
13
+ | 'queryRecord'
14
+ | 'findAll'
15
+ | 'findBelongsTo'
16
+ | 'findHasMany'
17
+ | 'findMany'
18
+ | 'query'
19
+ | 'createRecord'
20
+ | 'deleteRecord'
21
+ | 'updateRecord';
11
22
  /**
12
23
  @module @ember-data/serializer
13
24
  */
@@ -22,7 +33,7 @@ type OptionsHash = Dict<any>;
22
33
  @class MinimumSerializerInterface
23
34
  @public
24
35
  */
25
- interface Serializer {
36
+ export interface MinimumSerializerInterface {
26
37
  /**
27
38
  * This method is responsible for normalizing the value resolved from the promise returned
28
39
  * by an Adapter request into the format expected by the `Store`.
@@ -56,7 +67,7 @@ interface Serializer {
56
67
  normalizeResponse(
57
68
  store: Store,
58
69
  schema: ModelSchema,
59
- rawPayload: JSONObject,
70
+ rawPayload: AdapterPayload,
60
71
  id: string | null,
61
72
  requestType:
62
73
  | 'findRecord'
@@ -231,6 +242,16 @@ interface Serializer {
231
242
  * @returns {void}
232
243
  */
233
244
  pushPayload?(store: Store, rawPayload: JSONObject): void;
234
- }
235
245
 
236
- export default Serializer;
246
+ /**
247
+ * In some situations the serializer may need to perform cleanup when destroyed,
248
+ * that cleanup can be done in `destroy`.
249
+ *
250
+ * If not implemented, the store does not inform the serializer of destruction.
251
+ *
252
+ * @method destroy [OPTIONAL]
253
+ * @public
254
+ * @optional
255
+ */
256
+ destroy?(): void;
257
+ }
@@ -12,7 +12,10 @@ export interface ChangedAttributesHash {
12
12
 
13
13
  export interface RecordData {
14
14
  getResourceIdentifier(): RecordIdentifier | undefined;
15
- pushData(data: JsonApiResource, calculateChange?: boolean): void;
15
+
16
+ pushData(data: JsonApiResource, calculateChange: true): string[];
17
+ pushData(data: JsonApiResource, calculateChange?: false): void;
18
+ pushData(data: JsonApiResource, calculateChange?: boolean): string[] | void;
16
19
  clientDidCreate(): void;
17
20
  willCommit(): void;
18
21
 
@@ -1,3 +1,5 @@
1
+ import type { DSModel } from './ds-model';
2
+ import type { Dict } from './utils';
1
3
  /**
2
4
  @module @ember-data/store
3
5
  */
@@ -13,4 +15,4 @@
13
15
  The type belows allows for anything extending object.
14
16
  */
15
17
 
16
- export type RecordInstance = Object;
18
+ export type RecordInstance = DSModel | Dict<unknown>;
@@ -6,4 +6,5 @@ export interface FindOptions {
6
6
  include?: string;
7
7
  adapterOptions?: Dict<unknown>;
8
8
  preload?: Dict<unknown>;
9
+ isReloading?: boolean;
9
10
  }
@@ -1,7 +1,7 @@
1
1
  import type InternalModel from '../system/model/internal-model';
2
+ import type { PromiseObject } from '../system/promise-proxies';
2
3
  import { promiseObject } from '../system/promise-proxies';
3
- import type { DSModel } from '../ts-interfaces/ds-model';
4
- import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
4
+ import type { RecordInstance } from '../ts-interfaces/record-instance';
5
5
 
6
6
  /**
7
7
  @module @ember-data/store
@@ -18,7 +18,7 @@ import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
18
18
  export default function promiseRecord(
19
19
  internalModelPromise: Promise<InternalModel>,
20
20
  label: string
21
- ): PromiseProxy<DSModel> {
21
+ ): PromiseObject<RecordInstance> {
22
22
  let toReturn = internalModelPromise.then((internalModel) => internalModel.getRecord());
23
23
 
24
24
  return promiseObject(toReturn, label);
package/index.js CHANGED
@@ -35,6 +35,9 @@ module.exports = Object.assign({}, addonBaseConfig, {
35
35
  '@ember/test',
36
36
  '@ember/utils',
37
37
 
38
+ '@embroider/macros/es-compat',
39
+ '@embroider/macros/runtime',
40
+
38
41
  'ember-inflector',
39
42
  'ember',
40
43
  'rsvp',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ember-data/store",
3
- "version": "4.4.0",
3
+ "version": "4.5.0-alpha.2",
4
4
  "description": "The default blueprint for ember-cli addons.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -17,9 +17,10 @@
17
17
  "start": "ember serve"
18
18
  },
19
19
  "dependencies": {
20
- "@ember-data/canary-features": "4.4.0",
21
- "@ember-data/private-build-infra": "4.4.0",
20
+ "@ember-data/canary-features": "4.5.0-alpha.2",
21
+ "@ember-data/private-build-infra": "4.5.0-alpha.2",
22
22
  "@ember/string": "^3.0.0",
23
+ "@embroider/macros": "^1.2.0",
23
24
  "@glimmer/tracking": "^1.0.4",
24
25
  "ember-auto-import": "^2.2.4",
25
26
  "ember-cached-decorator-polyfill": "^0.1.4",
@@ -28,14 +29,14 @@
28
29
  "ember-cli-typescript": "^5.0.0"
29
30
  },
30
31
  "devDependencies": {
31
- "@ember-data/unpublished-test-infra": "4.4.0",
32
+ "@ember-data/unpublished-test-infra": "4.5.0-alpha.2",
32
33
  "@ember/optional-features": "^2.0.0",
33
34
  "@ember/test-helpers": "^2.6.0",
34
35
  "@types/ember": "^4.0.0",
35
36
  "@types/rsvp": "^4.0.4",
36
37
  "broccoli-asset-rev": "^3.0.0",
37
38
  "ember-cli": "~4.3.0",
38
- "ember-cli-dependency-checker": "^3.2.0",
39
+ "ember-cli-dependency-checker": "^3.3.1",
39
40
  "ember-cli-htmlbars": "^6.0.1",
40
41
  "ember-cli-inject-live-reload": "^2.0.2",
41
42
  "ember-cli-sri": "^2.1.1",
@@ -46,7 +47,7 @@
46
47
  "ember-maybe-import-regenerator": "^1.0.0",
47
48
  "ember-qunit": "^5.1.5",
48
49
  "ember-resolver": "^8.0.3",
49
- "ember-source": "~4.4.0",
50
+ "ember-source": "~4.3.0",
50
51
  "ember-source-channel-url": "^3.0.0",
51
52
  "ember-try": "^2.0.0",
52
53
  "loader.js": "^4.7.0",