@ember-data/model 4.4.0-alpha.5 → 4.4.0-alpha.8

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.
@@ -1,11 +1,29 @@
1
- import { A, makeArray } from '@ember/array';
1
+ import { A } from '@ember/array';
2
+ import type NativeArray from '@ember/array/-private/native-array';
2
3
  import ArrayProxy from '@ember/array/proxy';
3
4
  import { computed, get } from '@ember/object';
4
5
  import { mapBy, not } from '@ember/object/computed';
5
6
 
7
+ type ValidationError = {
8
+ attribute: string;
9
+ message: string;
10
+ };
6
11
  /**
7
- @module @ember-data/store
12
+ @module @ember-data/model
8
13
  */
14
+ interface ArrayProxyWithCustomOverrides<T, M = T> extends Omit<ArrayProxy<T, M>, 'clear' | 'content'> {
15
+ // Omit causes `content` to be merged with the class def for ArrayProxy
16
+ // which then causes it to be seen as a property, disallowing defining it
17
+ // as an accessor. This restores our ability to define it as an accessor.
18
+ content: NativeArray<T>;
19
+ clear(): void;
20
+ _has(name: string): boolean;
21
+ }
22
+
23
+ // we force the type here to our own construct because mixin and extend patterns
24
+ // lose generic signatures. We also do this because we need to Omit `clear` from
25
+ // the type of ArrayProxy as we override it's signature.
26
+ const ArrayProxyWithCustomOverrides = ArrayProxy as unknown as new <T, M = T>() => ArrayProxyWithCustomOverrides<T, M>;
9
27
 
10
28
  /**
11
29
  Holds validation errors for a given record, organized by attribute names.
@@ -82,28 +100,34 @@ import { mapBy, not } from '@ember/object/computed';
82
100
  @public
83
101
  @extends Ember.ArrayProxy
84
102
  */
85
- export default ArrayProxy.extend({
103
+ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationError> {
104
+ declare _registeredHandlers?: {
105
+ becameInvalid: () => void;
106
+ becameValid: () => void;
107
+ };
108
+
86
109
  /**
87
110
  Register with target handler
88
111
 
89
112
  @method _registerHandlers
90
113
  @private
91
114
  */
92
- _registerHandlers(becameInvalid, becameValid) {
115
+ _registerHandlers(becameInvalid: () => void, becameValid: () => void): void {
93
116
  this._registeredHandlers = {
94
117
  becameInvalid,
95
118
  becameValid,
96
119
  };
97
- },
120
+ }
98
121
 
99
122
  /**
100
123
  @property errorsByAttributeName
101
124
  @type {MapWithDefault}
102
125
  @private
103
126
  */
104
- errorsByAttributeName: computed(function () {
127
+ @computed()
128
+ get errorsByAttributeName(): Map<string, NativeArray<ValidationError>> {
105
129
  return new Map();
106
- }),
130
+ }
107
131
 
108
132
  /**
109
133
  Returns errors for a given attribute
@@ -124,13 +148,13 @@ export default ArrayProxy.extend({
124
148
  @param {String} attribute
125
149
  @return {Array}
126
150
  */
127
- errorsFor(attribute) {
128
- let map = get(this, 'errorsByAttributeName');
151
+ errorsFor(attribute: string): NativeArray<ValidationError> {
152
+ let map = this.errorsByAttributeName;
129
153
 
130
154
  let errors = map.get(attribute);
131
155
 
132
156
  if (errors === undefined) {
133
- errors = A();
157
+ errors = A<ValidationError>();
134
158
  map.set(attribute, errors);
135
159
  }
136
160
 
@@ -141,7 +165,7 @@ export default ArrayProxy.extend({
141
165
  get(errors, '[]');
142
166
 
143
167
  return errors;
144
- },
168
+ }
145
169
 
146
170
  /**
147
171
  An array containing all of the error messages for this
@@ -159,28 +183,30 @@ export default ArrayProxy.extend({
159
183
  @public
160
184
  @type {Array}
161
185
  */
162
- messages: mapBy('content', 'message'),
186
+ @mapBy('content', 'message')
187
+ declare messages: string[];
163
188
 
164
189
  /**
165
190
  @property content
166
191
  @type {Array}
167
192
  @private
168
193
  */
169
- content: computed(function () {
194
+ @computed()
195
+ get content(): NativeArray<ValidationError> {
170
196
  return A();
171
- }),
197
+ }
172
198
 
173
199
  /**
174
200
  @method unknownProperty
175
201
  @private
176
202
  */
177
- unknownProperty(attribute) {
203
+ unknownProperty(attribute: string) {
178
204
  let errors = this.errorsFor(attribute);
179
205
  if (errors.length === 0) {
180
206
  return undefined;
181
207
  }
182
208
  return errors;
183
- },
209
+ }
184
210
 
185
211
  /**
186
212
  Total number of errors.
@@ -199,7 +225,8 @@ export default ArrayProxy.extend({
199
225
  @public
200
226
  @readOnly
201
227
  */
202
- isEmpty: not('length').readOnly(),
228
+ @not('length')
229
+ declare isEmpty: boolean;
203
230
 
204
231
  /**
205
232
  Manually adds errors to the record. This will trigger the `becameInvalid` event/ lifecycle method on
@@ -233,20 +260,20 @@ export default ArrayProxy.extend({
233
260
  // { attribute: 'username', message: 'This field is required' },
234
261
  // ]
235
262
  ```
236
- @method add
263
+ @method add
237
264
  @public
238
- @param {string} attribute - the property name of an attribute or relationship
239
- @param {string[]|string} messages - an error message or array of error messages for the attribute
265
+ @param {string} attribute - the property name of an attribute or relationship
266
+ @param {string[]|string} messages - an error message or array of error messages for the attribute
240
267
  */
241
- add(attribute, messages) {
242
- let wasEmpty = get(this, 'isEmpty');
268
+ add(attribute: string, messages: string[] | string): void {
269
+ let wasEmpty: boolean = this.isEmpty;
243
270
 
244
271
  this._add(attribute, messages);
245
272
 
246
- if (wasEmpty && !get(this, 'isEmpty')) {
273
+ if (wasEmpty && !this.isEmpty) {
247
274
  this._registeredHandlers && this._registeredHandlers.becameInvalid();
248
275
  }
249
- },
276
+ }
250
277
 
251
278
  /**
252
279
  Adds error messages to a given attribute without sending event.
@@ -254,23 +281,23 @@ export default ArrayProxy.extend({
254
281
  @method _add
255
282
  @private
256
283
  */
257
- _add(attribute, messages) {
258
- messages = this._findOrCreateMessages(attribute, messages);
259
- this.addObjects(messages);
284
+ _add(attribute: string, messages: string[] | string) {
285
+ const errors = this._findOrCreateMessages(attribute, messages);
286
+ this.addObjects(errors);
260
287
 
261
- this.errorsFor(attribute).addObjects(messages);
288
+ this.errorsFor(attribute).addObjects(errors);
262
289
 
263
290
  this.notifyPropertyChange(attribute);
264
- },
291
+ }
265
292
 
266
293
  /**
267
294
  @method _findOrCreateMessages
268
295
  @private
269
296
  */
270
- _findOrCreateMessages(attribute, messages) {
297
+ _findOrCreateMessages(attribute: string, messages: string | string[]): ValidationError[] {
271
298
  let errors = this.errorsFor(attribute);
272
- let messagesArray = makeArray(messages);
273
- let _messages = new Array(messagesArray.length);
299
+ let messagesArray = Array.isArray(messages) ? messages : [messages];
300
+ let _messages: ValidationError[] = new Array(messagesArray.length) as ValidationError[];
274
301
 
275
302
  for (let i = 0; i < messagesArray.length; i++) {
276
303
  let message = messagesArray[i];
@@ -280,13 +307,13 @@ export default ArrayProxy.extend({
280
307
  } else {
281
308
  _messages[i] = {
282
309
  attribute: attribute,
283
- message: message,
310
+ message,
284
311
  };
285
312
  }
286
313
  }
287
314
 
288
315
  return _messages;
289
- },
316
+ }
290
317
 
291
318
  /**
292
319
  Manually removes all errors for a given member from the record.
@@ -315,17 +342,17 @@ export default ArrayProxy.extend({
315
342
  @public
316
343
  @param {string} member - the property name of an attribute or relationship
317
344
  */
318
- remove(attribute) {
319
- if (get(this, 'isEmpty')) {
345
+ remove(attribute: string) {
346
+ if (this.isEmpty) {
320
347
  return;
321
348
  }
322
349
 
323
350
  this._remove(attribute);
324
351
 
325
- if (get(this, 'isEmpty')) {
352
+ if (this.isEmpty) {
326
353
  this._registeredHandlers && this._registeredHandlers.becameValid();
327
354
  }
328
- },
355
+ }
329
356
 
330
357
  /**
331
358
  Removes all error messages from the given attribute without sending event.
@@ -333,13 +360,13 @@ export default ArrayProxy.extend({
333
360
  @method _remove
334
361
  @private
335
362
  */
336
- _remove(attribute) {
337
- if (get(this, 'isEmpty')) {
363
+ _remove(attribute: string) {
364
+ if (this.isEmpty) {
338
365
  return;
339
366
  }
340
367
 
341
368
  let content = this.rejectBy('attribute', attribute);
342
- get(this, 'content').setObjects(content);
369
+ this.content.setObjects(content);
343
370
 
344
371
  // Although errorsByAttributeName.delete is technically enough to sync errors state, we also
345
372
  // must mutate the array as well for autotracking
@@ -350,11 +377,11 @@ export default ArrayProxy.extend({
350
377
  errors.replace(i, 1);
351
378
  }
352
379
  }
353
- get(this, 'errorsByAttributeName').delete(attribute);
380
+ this.errorsByAttributeName.delete(attribute);
354
381
 
355
382
  this.notifyPropertyChange(attribute);
356
383
  this.notifyPropertyChange('length');
357
- },
384
+ }
358
385
 
359
386
  /**
360
387
  Manually clears all errors for the record.
@@ -393,16 +420,16 @@ export default ArrayProxy.extend({
393
420
  // => []
394
421
  ```
395
422
  @method clear
396
- @public
423
+ @public
397
424
  */
398
- clear() {
399
- if (get(this, 'isEmpty')) {
425
+ clear(): void {
426
+ if (this.isEmpty) {
400
427
  return;
401
428
  }
402
429
 
403
430
  this._clear();
404
431
  this._registeredHandlers && this._registeredHandlers.becameValid();
405
- },
432
+ }
406
433
 
407
434
  /**
408
435
  Removes all error messages.
@@ -411,13 +438,13 @@ export default ArrayProxy.extend({
411
438
  @method _clear
412
439
  @private
413
440
  */
414
- _clear() {
415
- if (get(this, 'isEmpty')) {
441
+ _clear(): void {
442
+ if (this.isEmpty) {
416
443
  return;
417
444
  }
418
445
 
419
- let errorsByAttributeName = get(this, 'errorsByAttributeName');
420
- let attributes = [];
446
+ let errorsByAttributeName = this.errorsByAttributeName;
447
+ let attributes: string[] = [];
421
448
 
422
449
  errorsByAttributeName.forEach(function (_, attribute) {
423
450
  attributes.push(attribute);
@@ -429,7 +456,7 @@ export default ArrayProxy.extend({
429
456
  });
430
457
 
431
458
  ArrayProxy.prototype.clear.call(this);
432
- },
459
+ }
433
460
 
434
461
  /**
435
462
  Checks if there are error messages for the given attribute.
@@ -454,7 +481,7 @@ export default ArrayProxy.extend({
454
481
  @param {String} attribute
455
482
  @return {Boolean} true if there some errors on given attribute
456
483
  */
457
- has(attribute) {
484
+ has(attribute: string): boolean {
458
485
  return this.errorsFor(attribute).length > 0;
459
- },
460
- });
486
+ }
487
+ }
@@ -2,6 +2,12 @@
2
2
  @module @ember-data/model
3
3
  */
4
4
 
5
+ export interface ArrayDiffResult {
6
+ firstChangeIndex: number | null;
7
+ removedCount: number;
8
+ addedCount: number;
9
+ }
10
+
5
11
  /**
6
12
  @method diffArray
7
13
  @internal
@@ -13,12 +19,12 @@
13
19
  removedCount: <integer> // 0 if no change
14
20
  }
15
21
  */
16
- export default function diffArray(oldArray, newArray) {
22
+ export default function diffArray(oldArray: unknown[], newArray: unknown[]): ArrayDiffResult {
17
23
  const oldLength = oldArray.length;
18
24
  const newLength = newArray.length;
19
25
 
20
26
  const shortestLength = Math.min(oldLength, newLength);
21
- let firstChangeIndex = null; // null signifies no changes
27
+ let firstChangeIndex: number | null = null; // null signifies no changes
22
28
 
23
29
  // find the first change
24
30
  for (let i = 0; i < shortestLength; i++) {
@@ -8,10 +8,36 @@ import EmberObject, { get } from '@ember/object';
8
8
 
9
9
  import { all } from 'rsvp';
10
10
 
11
+ import type { RelationshipRecordData } from '@ember-data/record-data/-private/ts-interfaces/relationship-record-data';
12
+ import type { InternalModel } from '@ember-data/store/-private';
11
13
  import { PromiseArray, recordDataFor } from '@ember-data/store/-private';
14
+ import type CoreStore from '@ember-data/store/-private/system/core-store';
15
+ import type { CreateRecordProperties } from '@ember-data/store/-private/system/core-store';
16
+ import ShimModelClass from '@ember-data/store/-private/system/model/shim-model-class';
17
+ import type { DSModelSchema } from '@ember-data/store/-private/ts-interfaces/ds-model';
18
+ import type { Links, PaginationLinks } from '@ember-data/store/-private/ts-interfaces/ember-data-json-api';
19
+ import type { RecordInstance } from '@ember-data/store/-private/ts-interfaces/record-instance';
20
+ import type { Dict } from '@ember-data/store/-private/ts-interfaces/utils';
12
21
 
13
22
  import diffArray from './diff-array';
14
23
 
24
+ interface MutableArrayWithObject<T, M = T> extends EmberObject, MutableArray<M> {}
25
+ const MutableArrayWithObject = EmberObject.extend(MutableArray) as unknown as new <
26
+ T,
27
+ M = T
28
+ >() => MutableArrayWithObject<T, M>;
29
+
30
+ export interface ManyArrayCreateArgs {
31
+ store: CoreStore;
32
+ type: ShimModelClass;
33
+ recordData: RelationshipRecordData;
34
+ key: string;
35
+ isPolymorphic: boolean;
36
+ isAsync: boolean;
37
+ _inverseIsAsync: boolean;
38
+ internalModel: InternalModel;
39
+ isLoaded: boolean;
40
+ }
15
41
  /**
16
42
  A `ManyArray` is a `MutableArray` that represents the contents of a has-many
17
43
  relationship.
@@ -57,12 +83,27 @@ import diffArray from './diff-array';
57
83
  @extends Ember.EmberObject
58
84
  @uses Ember.MutableArray
59
85
  */
60
- export default EmberObject.extend(MutableArray, {
61
- isAsync: false,
62
- isLoaded: false,
86
+ export default class ManyArray extends MutableArrayWithObject<InternalModel, RecordInstance> {
87
+ declare isAsync: boolean;
88
+ declare isLoaded: boolean;
89
+ declare isPolymorphic: boolean;
90
+ declare _isDirty: boolean;
91
+ declare _isUpdating: boolean;
92
+ declare _hasNotified: boolean;
93
+ declare __hasArrayObservers: boolean;
94
+ declare hasArrayObservers: boolean; // override the base declaration
95
+ declare _length: number;
96
+ declare _meta: Dict<unknown> | null;
97
+ declare _links: Links | PaginationLinks | null;
98
+ declare currentState: InternalModel[];
99
+ declare recordData: RelationshipRecordData;
100
+ declare internalModel: InternalModel;
101
+ declare store: CoreStore;
102
+ declare key: string;
103
+ declare type: DSModelSchema;
63
104
 
64
105
  init() {
65
- this._super(...arguments);
106
+ super.init();
66
107
 
67
108
  /**
68
109
  The loading state of this array
@@ -71,6 +112,7 @@ export default EmberObject.extend(MutableArray, {
71
112
  @public
72
113
  */
73
114
  this.isLoaded = this.isLoaded || false;
115
+ this.isAsync = this.isAsync || false;
74
116
 
75
117
  this._length = 0;
76
118
 
@@ -158,12 +200,13 @@ export default EmberObject.extend(MutableArray, {
158
200
  // make sure we initialize to the correct state
159
201
  // since the user has already accessed
160
202
  this.retrieveLatest();
161
- },
203
+ }
162
204
 
163
205
  // TODO refactor away _hasArrayObservers for tests
164
206
  get _hasArrayObservers() {
207
+ // cast necessary because hasArrayObservers is typed as a ComputedProperty<boolean> vs a boolean;
165
208
  return this.hasArrayObservers || this.__hasArrayObservers;
166
- },
209
+ }
167
210
 
168
211
  notify() {
169
212
  this._isDirty = true;
@@ -175,7 +218,7 @@ export default EmberObject.extend(MutableArray, {
175
218
  this.notifyPropertyChange('firstObject');
176
219
  this.notifyPropertyChange('lastObject');
177
220
  }
178
- },
221
+ }
179
222
 
180
223
  get length() {
181
224
  if (this._isDirty) {
@@ -185,11 +228,11 @@ export default EmberObject.extend(MutableArray, {
185
228
  get(this, '[]');
186
229
 
187
230
  return this._length;
188
- },
231
+ }
189
232
 
190
233
  set length(value) {
191
234
  this._length = value;
192
- },
235
+ }
193
236
 
194
237
  get links() {
195
238
  get(this, '[]');
@@ -197,10 +240,10 @@ export default EmberObject.extend(MutableArray, {
197
240
  this.retrieveLatest();
198
241
  }
199
242
  return this._links;
200
- },
243
+ }
201
244
  set links(v) {
202
245
  this._links = v;
203
- },
246
+ }
204
247
 
205
248
  get meta() {
206
249
  get(this, '[]');
@@ -208,12 +251,12 @@ export default EmberObject.extend(MutableArray, {
208
251
  this.retrieveLatest();
209
252
  }
210
253
  return this._meta;
211
- },
254
+ }
212
255
  set meta(v) {
213
256
  this._meta = v;
214
- },
257
+ }
215
258
 
216
- objectAt(index) {
259
+ objectAt(index: number): RecordInstance | undefined {
217
260
  if (this._isDirty) {
218
261
  this.retrieveLatest();
219
262
  }
@@ -223,12 +266,12 @@ export default EmberObject.extend(MutableArray, {
223
266
  }
224
267
 
225
268
  return internalModel.getRecord();
226
- },
269
+ }
227
270
 
228
- replace(idx, amt, objects) {
271
+ replace(idx: number, amt: number, objects?: RecordInstance[]) {
229
272
  assert(`Cannot push mutations to the cache while updating the relationship from cache`, !this._isUpdating);
230
273
  this.store._backburner.join(() => {
231
- let internalModels;
274
+ let internalModels: InternalModel[];
232
275
  if (amt > 0) {
233
276
  internalModels = this.currentState.slice(idx, idx + amt);
234
277
  this.recordData.removeFromHasMany(
@@ -243,13 +286,13 @@ export default EmberObject.extend(MutableArray, {
243
286
  );
244
287
  this.recordData.addToHasMany(
245
288
  this.key,
246
- objects.map((obj) => recordDataFor(obj)),
289
+ objects.map((obj: RecordInstance) => recordDataFor(obj)),
247
290
  idx
248
291
  );
249
292
  }
250
293
  this.notify();
251
294
  });
252
- },
295
+ }
253
296
 
254
297
  retrieveLatest() {
255
298
  // It’s possible the parent side of the relationship may have been destroyed by this point
@@ -260,7 +303,7 @@ export default EmberObject.extend(MutableArray, {
260
303
  this._isUpdating = true;
261
304
  let jsonApi = this.recordData.getHasMany(this.key);
262
305
 
263
- let internalModels = [];
306
+ let internalModels: InternalModel[] = [];
264
307
  if (jsonApi.data) {
265
308
  for (let i = 0; i < jsonApi.data.length; i++) {
266
309
  let im = this.store._internalModelForResource(jsonApi.data[i]);
@@ -298,7 +341,7 @@ export default EmberObject.extend(MutableArray, {
298
341
  }
299
342
 
300
343
  this._isUpdating = false;
301
- },
344
+ }
302
345
 
303
346
  /**
304
347
  Reloads all of the records in the manyArray. If the manyArray
@@ -324,8 +367,8 @@ export default EmberObject.extend(MutableArray, {
324
367
  */
325
368
  reload(options) {
326
369
  // TODO this is odd, we don't ask the store for anything else like this?
327
- return this.store.reloadManyArray(this, this.internalModel, this.key, options);
328
- },
370
+ return this.internalModel.reloadHasMany(this.key, options);
371
+ }
329
372
 
330
373
  /**
331
374
  Saves all of the records in the `ManyArray`.
@@ -347,7 +390,7 @@ export default EmberObject.extend(MutableArray, {
347
390
  */
348
391
  save() {
349
392
  let manyArray = this;
350
- let promiseLabel = 'DS: ManyArray#save ' + this.type;
393
+ let promiseLabel = 'DS: ManyArray#save ' + this.type.modelName;
351
394
  let promise = all(this.invoke('save'), promiseLabel).then(
352
395
  () => manyArray,
353
396
  null,
@@ -356,7 +399,7 @@ export default EmberObject.extend(MutableArray, {
356
399
 
357
400
  // TODO deprecate returning a promiseArray here
358
401
  return PromiseArray.create({ promise });
359
- },
402
+ }
360
403
 
361
404
  /**
362
405
  Create a child record within the owner
@@ -366,12 +409,12 @@ export default EmberObject.extend(MutableArray, {
366
409
  @param {Object} hash
367
410
  @return {Model} record
368
411
  */
369
- createRecord(hash) {
412
+ createRecord(hash: CreateRecordProperties): RecordInstance {
370
413
  const { store, type } = this;
371
414
 
372
- let record = store.createRecord(type.modelName, hash);
415
+ const record = store.createRecord(type.modelName, hash);
373
416
  this.pushObject(record);
374
417
 
375
418
  return record;
376
- },
377
- });
419
+ }
420
+ }
@@ -0,0 +1,72 @@
1
+ import { assert } from '@ember/debug';
2
+ import { computed } from '@ember/object';
3
+ import type PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
4
+ import type ObjectProxy from '@ember/object/proxy';
5
+
6
+ import type { InternalModel } from '@ember-data/store/-private';
7
+ import { PromiseObject } from '@ember-data/store/-private';
8
+ import type CoreStore from '@ember-data/store/-private/system/core-store';
9
+ import type { RecordInstance } from '@ember-data/store/-private/ts-interfaces/record-instance';
10
+ import type { Dict } from '@ember-data/store/-private/ts-interfaces/utils';
11
+
12
+ export interface BelongsToProxyMeta {
13
+ key: string;
14
+ store: CoreStore;
15
+ originatingInternalModel: InternalModel;
16
+ modelName: string;
17
+ }
18
+ export interface BelongsToProxyCreateArgs {
19
+ promise: Promise<RecordInstance | null>;
20
+ content?: RecordInstance | null;
21
+ _belongsToState: BelongsToProxyMeta;
22
+ }
23
+
24
+ interface PromiseObjectType<T extends object> extends PromiseProxyMixin<T | null>, ObjectProxy<T> {
25
+ new <T extends object>(...args: unknown[]): PromiseObjectType<T>;
26
+ }
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28
+ declare class PromiseObjectType<T extends object> {}
29
+
30
+ const Extended: PromiseObjectType<RecordInstance> = PromiseObject as unknown as PromiseObjectType<RecordInstance>;
31
+
32
+ /**
33
+ @module @ember-data/model
34
+ */
35
+
36
+ /**
37
+ A PromiseBelongsTo is a PromiseObject that also proxies certain method calls
38
+ to the underlying belongsTo model.
39
+ Right now we proxy:
40
+ * `reload()`
41
+ @class PromiseBelongsTo
42
+ @extends PromiseObject
43
+ @private
44
+ */
45
+ class PromiseBelongsTo extends Extended<RecordInstance> {
46
+ declare _belongsToState: BelongsToProxyMeta;
47
+ // we don't proxy meta because we would need to proxy it to the relationship state container
48
+ // however, meta on relationships does not trigger change notifications.
49
+ // if you need relationship meta, you should do `record.belongsTo(relationshipName).meta()`
50
+ @computed()
51
+ get meta() {
52
+ // eslint-disable-next-line no-constant-condition
53
+ if (1) {
54
+ assert(
55
+ 'You attempted to access meta on the promise for the async belongsTo relationship ' +
56
+ `${this.get('_belongsToState').modelName}:${this.get('_belongsToState').key}'.` +
57
+ '\nUse `record.belongsTo(relationshipName).meta()` instead.',
58
+ false
59
+ );
60
+ }
61
+ return;
62
+ }
63
+
64
+ async reload(options: Dict<unknown>): Promise<this> {
65
+ assert('You are trying to reload an async belongsTo before it has been created', this.content !== undefined);
66
+ let { key, store, originatingInternalModel } = this._belongsToState;
67
+ await store.reloadBelongsTo(this, originatingInternalModel, key, options);
68
+ return this;
69
+ }
70
+ }
71
+
72
+ export default PromiseBelongsTo;
@@ -1,4 +1,5 @@
1
1
  import ArrayMixin from '@ember/array';
2
+ import type ArrayProxy from '@ember/array/proxy';
2
3
  import { assert } from '@ember/debug';
3
4
  import { dependentKeyCompat } from '@ember/object/compat';
4
5
  import { tracked } from '@glimmer/tracking';
@@ -6,6 +7,16 @@ import Ember from 'ember';
6
7
 
7
8
  import { resolve } from 'rsvp';
8
9
 
10
+ import type { ManyArray } from 'ember-data/-private';
11
+
12
+ import type { InternalModel } from '@ember-data/store/-private';
13
+ import type { RecordInstance } from '@ember-data/store/-private/ts-interfaces/record-instance';
14
+
15
+ export interface HasManyProxyCreateArgs {
16
+ promise: Promise<ManyArray>;
17
+ content?: ManyArray;
18
+ }
19
+
9
20
  /**
10
21
  @module @ember-data/model
11
22
  */
@@ -31,12 +42,13 @@ import { resolve } from 'rsvp';
31
42
  @class PromiseManyArray
32
43
  @public
33
44
  */
45
+ export default interface PromiseManyArray extends Omit<ArrayProxy<InternalModel, RecordInstance>, 'destroy'> {}
34
46
  export default class PromiseManyArray {
35
- declare promise: Promise<any> | null;
47
+ declare promise: Promise<ManyArray> | null;
36
48
  declare isDestroyed: boolean;
37
49
  declare isDestroying: boolean;
38
50
 
39
- constructor(promise, content) {
51
+ constructor(promise: Promise<ManyArray>, content?: ManyArray) {
40
52
  this._update(promise, content);
41
53
  this.isDestroyed = false;
42
54
  this.isDestroying = false;
@@ -61,6 +73,9 @@ export default class PromiseManyArray {
61
73
  */
62
74
  @dependentKeyCompat
63
75
  get length(): number {
76
+ // shouldn't be needed, but ends up being needed
77
+ // for computed chains even in 4.x
78
+ this['[]'];
64
79
  return this.content ? this.content.length : 0;
65
80
  }
66
81
 
@@ -201,7 +216,7 @@ export default class PromiseManyArray {
201
216
 
202
217
  //---- Our own stuff
203
218
 
204
- _update(promise, content) {
219
+ _update(promise: Promise<ManyArray>, content?: ManyArray) {
205
220
  if (content !== undefined) {
206
221
  this.content = content;
207
222
  }
@@ -209,7 +224,7 @@ export default class PromiseManyArray {
209
224
  this.promise = tapPromise(this, promise);
210
225
  }
211
226
 
212
- static create({ promise, content }) {
227
+ static create({ promise, content }: HasManyProxyCreateArgs): PromiseManyArray {
213
228
  return new this(promise, content);
214
229
  }
215
230
 
@@ -230,7 +245,7 @@ export default class PromiseManyArray {
230
245
  }
231
246
  }
232
247
 
233
- function tapPromise(proxy, promise) {
248
+ function tapPromise(proxy: PromiseManyArray, promise: Promise<ManyArray>) {
234
249
  proxy.isPending = true;
235
250
  proxy.isSettled = false;
236
251
  proxy.isFulfilled = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ember-data/model",
3
- "version": "4.4.0-alpha.5",
3
+ "version": "4.4.0-alpha.8",
4
4
  "description": "The default blueprint for ember-cli addons.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -18,9 +18,9 @@
18
18
  "test:node": "mocha"
19
19
  },
20
20
  "dependencies": {
21
- "@ember-data/canary-features": "4.4.0-alpha.5",
22
- "@ember-data/private-build-infra": "4.4.0-alpha.5",
23
- "@ember-data/store": "4.4.0-alpha.5",
21
+ "@ember-data/canary-features": "4.4.0-alpha.8",
22
+ "@ember-data/private-build-infra": "4.4.0-alpha.8",
23
+ "@ember-data/store": "4.4.0-alpha.8",
24
24
  "@ember/edition-utils": "^1.2.0",
25
25
  "@ember/string": "^3.0.0",
26
26
  "ember-auto-import": "^2.2.4",
@@ -33,7 +33,7 @@
33
33
  "inflection": "~1.13.1"
34
34
  },
35
35
  "devDependencies": {
36
- "@ember-data/unpublished-test-infra": "4.4.0-alpha.5",
36
+ "@ember-data/unpublished-test-infra": "4.4.0-alpha.8",
37
37
  "@ember/optional-features": "^2.0.0",
38
38
  "@ember/test-helpers": "^2.6.0",
39
39
  "broccoli-asset-rev": "^3.0.0",
@@ -50,7 +50,7 @@
50
50
  "ember-maybe-import-regenerator": "^1.0.0",
51
51
  "ember-qunit": "^5.1.5",
52
52
  "ember-resolver": "^8.0.3",
53
- "ember-source": "~4.2.0",
53
+ "ember-source": "~4.3.0",
54
54
  "ember-source-channel-url": "^3.0.0",
55
55
  "ember-try": "^2.0.0",
56
56
  "loader.js": "^4.7.0",
@@ -1,41 +0,0 @@
1
- import { assert } from '@ember/debug';
2
- import { computed } from '@ember/object';
3
-
4
- import { PromiseObject } from '@ember-data/store/-private';
5
-
6
- /**
7
- @module @ember-data/model
8
- */
9
-
10
- /**
11
- A PromiseBelongsTo is a PromiseObject that also proxies certain method calls
12
- to the underlying belongsTo model.
13
- Right now we proxy:
14
-
15
- * `reload()`
16
-
17
- @class PromiseBelongsTo
18
- @extends PromiseObject
19
- @private
20
- */
21
- const PromiseBelongsTo = PromiseObject.extend({
22
- // we don't proxy meta because we would need to proxy it to the relationship state container
23
- // however, meta on relationships does not trigger change notifications.
24
- // if you need relationship meta, you should do `record.belongsTo(relationshipName).meta()`
25
- meta: computed(function () {
26
- assert(
27
- 'You attempted to access meta on the promise for the async belongsTo relationship ' +
28
- `${this.get('_belongsToState').modelName}:${this.get('_belongsToState').key}'.` +
29
- '\nUse `record.belongsTo(relationshipName).meta()` instead.',
30
- false
31
- );
32
- }),
33
-
34
- reload(options) {
35
- assert('You are trying to reload an async belongsTo before it has been created', this.get('content') !== undefined);
36
- let { key, store, originatingInternalModel } = this._belongsToState;
37
- return store.reloadBelongsTo(this, originatingInternalModel, key, options).then(() => this);
38
- },
39
- });
40
-
41
- export default PromiseBelongsTo;