@ember-data/model 4.8.0-alpha.0 → 4.8.0-alpha.3
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.
- package/addon/-private/attr.js +13 -2
- package/addon/-private/belongs-to.js +9 -3
- package/addon/-private/errors.ts +6 -6
- package/addon/-private/has-many.js +7 -3
- package/addon/-private/legacy-data-fetch.js +9 -7
- package/addon/-private/legacy-data-utils.ts +1 -1
- package/addon/-private/legacy-relationships-support.ts +33 -42
- package/addon/-private/many-array.ts +13 -7
- package/addon/-private/model-for-mixin.ts +2 -4
- package/addon/-private/model.js +425 -108
- package/addon/-private/notify-changes.ts +1 -1
- package/addon/-private/promise-many-array.ts +170 -112
- package/addon/-private/record-state.ts +61 -38
- package/addon/-private/references/belongs-to.ts +5 -5
- package/addon/-private/references/has-many.ts +6 -8
- package/addon/-private/relationship-meta.ts +2 -2
- package/index.js +1 -0
- package/package.json +6 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cacheFor } from '@ember/object/internals';
|
|
2
2
|
|
|
3
3
|
import type Store from '@ember-data/store';
|
|
4
|
-
import type { NotificationType } from '@ember-data/store/-private/record-notification-manager';
|
|
4
|
+
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
|
|
5
5
|
import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
|
|
6
6
|
|
|
7
7
|
import type Model from './model';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ArrayMixin, { NativeArray } from '@ember/array';
|
|
2
2
|
import type ArrayProxy from '@ember/array/proxy';
|
|
3
|
-
import { assert } from '@ember/debug';
|
|
3
|
+
import { assert, deprecate } from '@ember/debug';
|
|
4
4
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
5
5
|
import { tracked } from '@glimmer/tracking';
|
|
6
6
|
import Ember from 'ember';
|
|
@@ -9,8 +9,10 @@ import { resolve } from 'rsvp';
|
|
|
9
9
|
|
|
10
10
|
import type { ManyArray } from 'ember-data/-private';
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
import { DEPRECATE_PROMISE_MANY_ARRAY_BEHAVIORS } from '@ember-data/private-build-infra/deprecations';
|
|
13
|
+
import { StableRecordIdentifier } from '@ember-data/types/q/identifier';
|
|
13
14
|
import type { RecordInstance } from '@ember-data/types/q/record-instance';
|
|
15
|
+
import { FindOptions } from '@ember-data/types/q/store';
|
|
14
16
|
|
|
15
17
|
export interface HasManyProxyCreateArgs {
|
|
16
18
|
promise: Promise<ManyArray>;
|
|
@@ -24,16 +26,10 @@ export interface HasManyProxyCreateArgs {
|
|
|
24
26
|
This class is returned as the result of accessing an async hasMany relationship
|
|
25
27
|
on an instance of a Model extending from `@ember-data/model`.
|
|
26
28
|
|
|
27
|
-
A PromiseManyArray is an
|
|
28
|
-
|
|
29
|
+
A PromiseManyArray is an iterable proxy that allows templates to consume related
|
|
30
|
+
ManyArrays and update once their contents are no longer pending.
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* `reload()`
|
|
33
|
-
* `createRecord()`
|
|
34
|
-
|
|
35
|
-
This promise-proxy behavior is primarily to ensure that async relationship interact
|
|
36
|
-
nicely with templates. In your JS code you should resolve the promise first.
|
|
32
|
+
In your JS code you should resolve the promise first.
|
|
37
33
|
|
|
38
34
|
```js
|
|
39
35
|
const comments = await post.comments;
|
|
@@ -42,10 +38,14 @@ export interface HasManyProxyCreateArgs {
|
|
|
42
38
|
@class PromiseManyArray
|
|
43
39
|
@public
|
|
44
40
|
*/
|
|
45
|
-
export default interface PromiseManyArray extends Omit<ArrayProxy<
|
|
41
|
+
export default interface PromiseManyArray extends Omit<ArrayProxy<StableRecordIdentifier, RecordInstance>, 'destroy'> {
|
|
42
|
+
createRecord(): RecordInstance;
|
|
43
|
+
reload(options: FindOptions): PromiseManyArray;
|
|
44
|
+
}
|
|
46
45
|
export default class PromiseManyArray {
|
|
47
46
|
declare promise: Promise<ManyArray> | null;
|
|
48
47
|
declare isDestroyed: boolean;
|
|
48
|
+
// @deprecated (isDestroyed is not deprecated)
|
|
49
49
|
declare isDestroying: boolean;
|
|
50
50
|
|
|
51
51
|
constructor(promise: Promise<ManyArray>, content?: ManyArray) {
|
|
@@ -90,6 +90,8 @@ export default class PromiseManyArray {
|
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Iterate the proxied content. Called by the glimmer iterator in #each
|
|
93
|
+
* We do not guarantee that forEach will always be available. This
|
|
94
|
+
* may eventually be made to use Symbol.Iterator once glimmer supports it.
|
|
93
95
|
*
|
|
94
96
|
* @method forEach
|
|
95
97
|
* @param cb
|
|
@@ -103,6 +105,19 @@ export default class PromiseManyArray {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Reload the relationship
|
|
110
|
+
* @method reload
|
|
111
|
+
* @public
|
|
112
|
+
* @param options
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
reload(options: FindOptions) {
|
|
116
|
+
assert('You are trying to reload an async manyArray before it has been created', this.content);
|
|
117
|
+
this.content.reload(options);
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
|
|
106
121
|
//---- Properties/Methods from the PromiseProxyMixin that we will keep as our API
|
|
107
122
|
|
|
108
123
|
/**
|
|
@@ -201,19 +216,6 @@ export default class PromiseManyArray {
|
|
|
201
216
|
return this.content ? this.content.meta : undefined;
|
|
202
217
|
}
|
|
203
218
|
|
|
204
|
-
/**
|
|
205
|
-
* Reload the relationship
|
|
206
|
-
* @method reload
|
|
207
|
-
* @public
|
|
208
|
-
* @param options
|
|
209
|
-
* @returns
|
|
210
|
-
*/
|
|
211
|
-
reload(options) {
|
|
212
|
-
assert('You are trying to reload an async manyArray before it has been created', this.content);
|
|
213
|
-
this.content.reload(options);
|
|
214
|
-
return this;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
219
|
//---- Our own stuff
|
|
218
220
|
|
|
219
221
|
_update(promise: Promise<ManyArray>, content?: ManyArray) {
|
|
@@ -227,22 +229,55 @@ export default class PromiseManyArray {
|
|
|
227
229
|
static create({ promise, content }: HasManyProxyCreateArgs): PromiseManyArray {
|
|
228
230
|
return new this(promise, content);
|
|
229
231
|
}
|
|
232
|
+
}
|
|
230
233
|
|
|
231
|
-
|
|
232
|
-
createRecord(...args) {
|
|
234
|
+
if (DEPRECATE_PROMISE_MANY_ARRAY_BEHAVIORS) {
|
|
235
|
+
PromiseManyArray.prototype.createRecord = function createRecord(...args) {
|
|
236
|
+
deprecate(
|
|
237
|
+
`The createRecord method on ember-data's PromiseManyArray is deprecated. await the promise and work with the ManyArray directly.`,
|
|
238
|
+
false,
|
|
239
|
+
{
|
|
240
|
+
id: 'ember-data:deprecate-promise-many-array-behaviors',
|
|
241
|
+
until: '5.0',
|
|
242
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
243
|
+
for: 'ember-data',
|
|
244
|
+
}
|
|
245
|
+
);
|
|
233
246
|
assert('You are trying to createRecord on an async manyArray before it has been created', this.content);
|
|
234
247
|
return this.content.createRecord(...args);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Properties/Methods on ArrayProxy we should deprecate
|
|
238
|
-
|
|
239
|
-
get firstObject() {
|
|
240
|
-
return this.content ? this.content.firstObject : undefined;
|
|
241
|
-
}
|
|
248
|
+
};
|
|
242
249
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
250
|
+
Object.defineProperty(PromiseManyArray.prototype, 'firstObject', {
|
|
251
|
+
get() {
|
|
252
|
+
deprecate(
|
|
253
|
+
`The firstObject property on ember-data's PromiseManyArray is deprecated. await the promise and work with the ManyArray directly.`,
|
|
254
|
+
false,
|
|
255
|
+
{
|
|
256
|
+
id: 'ember-data:deprecate-promise-many-array-behaviors',
|
|
257
|
+
until: '5.0',
|
|
258
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
259
|
+
for: 'ember-data',
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
return this.content ? this.content.firstObject : undefined;
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
Object.defineProperty(PromiseManyArray.prototype, 'lastObject', {
|
|
267
|
+
get() {
|
|
268
|
+
deprecate(
|
|
269
|
+
`The lastObject property on ember-data's PromiseManyArray is deprecated. await the promise and work with the ManyArray directly.`,
|
|
270
|
+
false,
|
|
271
|
+
{
|
|
272
|
+
id: 'ember-data:deprecate-promise-many-array-behaviors',
|
|
273
|
+
until: '5.0',
|
|
274
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
275
|
+
for: 'ember-data',
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
return this.content ? this.content.lastObject : undefined;
|
|
279
|
+
},
|
|
280
|
+
});
|
|
246
281
|
}
|
|
247
282
|
|
|
248
283
|
function tapPromise(proxy: PromiseManyArray, promise: Promise<ManyArray>) {
|
|
@@ -268,78 +303,101 @@ function tapPromise(proxy: PromiseManyArray, promise: Promise<ManyArray>) {
|
|
|
268
303
|
);
|
|
269
304
|
}
|
|
270
305
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
306
|
+
if (DEPRECATE_PROMISE_MANY_ARRAY_BEHAVIORS) {
|
|
307
|
+
const EmberObjectMethods = [
|
|
308
|
+
'addObserver',
|
|
309
|
+
'cacheFor',
|
|
310
|
+
'decrementProperty',
|
|
311
|
+
'get',
|
|
312
|
+
'getProperties',
|
|
313
|
+
'incrementProperty',
|
|
314
|
+
'notifyPropertyChange',
|
|
315
|
+
'removeObserver',
|
|
316
|
+
'set',
|
|
317
|
+
'setProperties',
|
|
318
|
+
'toggleProperty',
|
|
319
|
+
];
|
|
320
|
+
EmberObjectMethods.forEach((method) => {
|
|
321
|
+
PromiseManyArray.prototype[method] = function delegatedMethod(...args) {
|
|
322
|
+
deprecate(
|
|
323
|
+
`The ${method} method on ember-data's PromiseManyArray is deprecated. await the promise and work with the ManyArray directly.`,
|
|
324
|
+
false,
|
|
325
|
+
{
|
|
326
|
+
id: 'ember-data:deprecate-promise-many-array-behaviors',
|
|
327
|
+
until: '5.0',
|
|
328
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
329
|
+
for: 'ember-data',
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
return Ember[method](this, ...args);
|
|
333
|
+
};
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const InheritedProxyMethods = [
|
|
337
|
+
'addArrayObserver',
|
|
338
|
+
'addObject',
|
|
339
|
+
'addObjects',
|
|
340
|
+
'any',
|
|
341
|
+
'arrayContentDidChange',
|
|
342
|
+
'arrayContentWillChange',
|
|
343
|
+
'clear',
|
|
344
|
+
'compact',
|
|
345
|
+
'every',
|
|
346
|
+
'filter',
|
|
347
|
+
'filterBy',
|
|
348
|
+
'find',
|
|
349
|
+
'findBy',
|
|
350
|
+
'getEach',
|
|
351
|
+
'includes',
|
|
352
|
+
'indexOf',
|
|
353
|
+
'insertAt',
|
|
354
|
+
'invoke',
|
|
355
|
+
'isAny',
|
|
356
|
+
'isEvery',
|
|
357
|
+
'lastIndexOf',
|
|
358
|
+
'map',
|
|
359
|
+
'mapBy',
|
|
360
|
+
// TODO update RFC to note objectAt was deprecated (forEach was left for iteration)
|
|
361
|
+
'objectAt',
|
|
362
|
+
'objectsAt',
|
|
363
|
+
'popObject',
|
|
364
|
+
'pushObject',
|
|
365
|
+
'pushObjects',
|
|
366
|
+
'reduce',
|
|
367
|
+
'reject',
|
|
368
|
+
'rejectBy',
|
|
369
|
+
'removeArrayObserver',
|
|
370
|
+
'removeAt',
|
|
371
|
+
'removeObject',
|
|
372
|
+
'removeObjects',
|
|
373
|
+
'replace',
|
|
374
|
+
'reverseObjects',
|
|
375
|
+
'setEach',
|
|
376
|
+
'setObjects',
|
|
377
|
+
'shiftObject',
|
|
378
|
+
'slice',
|
|
379
|
+
'sortBy',
|
|
380
|
+
'toArray',
|
|
381
|
+
'uniq',
|
|
382
|
+
'uniqBy',
|
|
383
|
+
'unshiftObject',
|
|
384
|
+
'unshiftObjects',
|
|
385
|
+
'without',
|
|
386
|
+
];
|
|
387
|
+
InheritedProxyMethods.forEach((method) => {
|
|
388
|
+
PromiseManyArray.prototype[method] = function proxiedMethod(...args) {
|
|
389
|
+
deprecate(
|
|
390
|
+
`The ${method} method on ember-data's PromiseManyArray is deprecated. await the promise and work with the ManyArray directly.`,
|
|
391
|
+
false,
|
|
392
|
+
{
|
|
393
|
+
id: 'ember-data:deprecate-promise-many-array-behaviors',
|
|
394
|
+
until: '5.0',
|
|
395
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
396
|
+
for: 'ember-data',
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
assert(`Cannot call ${method} before content is assigned.`, this.content);
|
|
400
|
+
return this.content[method](...args);
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
}
|
|
@@ -5,14 +5,17 @@ import { cached, tracked } from '@glimmer/tracking';
|
|
|
5
5
|
|
|
6
6
|
import type Store from '@ember-data/store';
|
|
7
7
|
import { storeFor } from '@ember-data/store';
|
|
8
|
-
import {
|
|
9
|
-
import type { NotificationType } from '@ember-data/store/-private/record-notification-manager';
|
|
10
|
-
import type RequestCache from '@ember-data/store/-private/request-cache';
|
|
8
|
+
import { recordIdentifierFor } from '@ember-data/store/-private';
|
|
9
|
+
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
|
|
10
|
+
import type RequestCache from '@ember-data/store/-private/network/request-cache';
|
|
11
11
|
import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
|
|
12
12
|
import type { RecordData } from '@ember-data/types/q/record-data';
|
|
13
13
|
|
|
14
14
|
type Model = InstanceType<typeof import('./model')>;
|
|
15
15
|
|
|
16
|
+
const SOURCE_POINTER_REGEXP = /^\/?data\/(attributes|relationships)\/(.*)/;
|
|
17
|
+
const SOURCE_POINTER_PRIMARY_REGEXP = /^\/?data/;
|
|
18
|
+
const PRIMARY_ATTRIBUTE_KEY = 'base';
|
|
16
19
|
function isInvalidError(error) {
|
|
17
20
|
return error && error.isAdapterError === true && error.code === 'InvalidError';
|
|
18
21
|
}
|
|
@@ -101,8 +104,9 @@ export function tagged(_target, key, desc) {
|
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
/**
|
|
104
|
-
Historically
|
|
105
|
-
the currentState for which
|
|
107
|
+
Historically EmberData managed a state machine
|
|
108
|
+
for each record, the currentState for which
|
|
109
|
+
was reflected onto Model.
|
|
106
110
|
|
|
107
111
|
This implements the flags and stateName for backwards compat
|
|
108
112
|
with the state tree that used to be possible (listed below).
|
|
@@ -150,6 +154,7 @@ export default class RecordState {
|
|
|
150
154
|
declare recordData: RecordData;
|
|
151
155
|
declare _errorRequests: any[];
|
|
152
156
|
declare _lastError: any;
|
|
157
|
+
declare handler: object;
|
|
153
158
|
|
|
154
159
|
constructor(record: Model) {
|
|
155
160
|
const store = storeFor(record)!;
|
|
@@ -176,7 +181,6 @@ export default class RecordState {
|
|
|
176
181
|
break;
|
|
177
182
|
case 'rejected':
|
|
178
183
|
this.isSaving = false;
|
|
179
|
-
|
|
180
184
|
this._lastError = req;
|
|
181
185
|
if (!(req.response && isInvalidError(req.response.data))) {
|
|
182
186
|
this._errorRequests.push(req);
|
|
@@ -230,47 +234,67 @@ export default class RecordState {
|
|
|
230
234
|
}
|
|
231
235
|
}
|
|
232
236
|
|
|
233
|
-
notifications.subscribe(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
break;
|
|
237
|
+
this.handler = notifications.subscribe(
|
|
238
|
+
identity,
|
|
239
|
+
(identifier: StableRecordIdentifier, type: NotificationType, key?: string) => {
|
|
240
|
+
switch (type) {
|
|
241
|
+
case 'state':
|
|
242
|
+
this.notify('isNew');
|
|
243
|
+
this.notify('isDeleted');
|
|
244
|
+
this.notify('isDirty');
|
|
245
|
+
break;
|
|
246
|
+
case 'attributes':
|
|
247
|
+
this.notify('isEmpty');
|
|
248
|
+
this.notify('isDirty');
|
|
249
|
+
break;
|
|
250
|
+
case 'unload':
|
|
251
|
+
this.notify('isNew');
|
|
252
|
+
this.notify('isDeleted');
|
|
253
|
+
break;
|
|
254
|
+
case 'errors':
|
|
255
|
+
this.updateInvalidErrors(this.record.errors);
|
|
256
|
+
this.notify('isValid');
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
256
259
|
}
|
|
257
|
-
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
destroy() {
|
|
264
|
+
storeFor(this.record)!._notificationManager.unsubscribe(this.handler);
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
notify(key) {
|
|
261
268
|
getTag(this, key).notify();
|
|
262
269
|
}
|
|
263
270
|
|
|
264
|
-
updateInvalidErrors() {
|
|
265
|
-
|
|
271
|
+
updateInvalidErrors(errors) {
|
|
272
|
+
assert(
|
|
273
|
+
`Expected the RecordData instance for ${this.identifier} to implement getErrors(identifier)`,
|
|
274
|
+
typeof this.recordData.getErrors === 'function'
|
|
275
|
+
);
|
|
276
|
+
let jsonApiErrors = this.recordData.getErrors(this.identifier);
|
|
266
277
|
|
|
267
|
-
const { errors } = this.record;
|
|
268
278
|
errors.clear();
|
|
269
|
-
let newErrors = errorsArrayToHash(jsonApiErrors);
|
|
270
|
-
let errorKeys = Object.keys(newErrors);
|
|
271
279
|
|
|
272
|
-
for (let i = 0; i <
|
|
273
|
-
|
|
280
|
+
for (let i = 0; i < jsonApiErrors.length; i++) {
|
|
281
|
+
let error = jsonApiErrors[i];
|
|
282
|
+
|
|
283
|
+
if (error.source && error.source.pointer) {
|
|
284
|
+
let keyMatch = error.source.pointer.match(SOURCE_POINTER_REGEXP);
|
|
285
|
+
let key: string | undefined;
|
|
286
|
+
|
|
287
|
+
if (keyMatch) {
|
|
288
|
+
key = keyMatch[2];
|
|
289
|
+
} else if (error.source.pointer.search(SOURCE_POINTER_PRIMARY_REGEXP) !== -1) {
|
|
290
|
+
key = PRIMARY_ATTRIBUTE_KEY;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (key) {
|
|
294
|
+
let errMsg = error.detail || error.title;
|
|
295
|
+
errors.add(key, errMsg);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
274
298
|
}
|
|
275
299
|
}
|
|
276
300
|
|
|
@@ -289,7 +313,6 @@ export default class RecordState {
|
|
|
289
313
|
return !this.isLoaded && this.pendingCount > 0 && this.fulfilledCount === 0;
|
|
290
314
|
}
|
|
291
315
|
|
|
292
|
-
// TODO @runspired handle "unloadRecord" see note in InternalModel
|
|
293
316
|
@tagged
|
|
294
317
|
get isLoaded() {
|
|
295
318
|
if (this.isNew) {
|
|
@@ -8,8 +8,8 @@ import type { BelongsToRelationship } from '@ember-data/record-data/-private';
|
|
|
8
8
|
import type Store from '@ember-data/store';
|
|
9
9
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
10
10
|
import { recordIdentifierFor } from '@ember-data/store/-private';
|
|
11
|
-
import type { NotificationType } from '@ember-data/store/-private/record-notification-manager';
|
|
12
|
-
import type { DebugWeakCache } from '@ember-data/store/-private/weak-cache';
|
|
11
|
+
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
|
|
12
|
+
import type { DebugWeakCache } from '@ember-data/store/-private/utils/weak-cache';
|
|
13
13
|
import type {
|
|
14
14
|
LinkObject,
|
|
15
15
|
Links,
|
|
@@ -125,7 +125,7 @@ export default class BelongsToReference {
|
|
|
125
125
|
`type()` and `id()` methods form a composite key for the identity
|
|
126
126
|
map. This can be used to access the id of an async relationship
|
|
127
127
|
without triggering a fetch that would normally happen if you
|
|
128
|
-
attempted to use `record.
|
|
128
|
+
attempted to use `record.relationship.id`.
|
|
129
129
|
|
|
130
130
|
Example
|
|
131
131
|
|
|
@@ -277,7 +277,7 @@ export default class BelongsToReference {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
_resource() {
|
|
280
|
-
return this.store._instanceCache.
|
|
280
|
+
return this.store._instanceCache.getRecordData(this.#identifier).getBelongsTo(this.key);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
/**
|
|
@@ -404,7 +404,7 @@ export default class BelongsToReference {
|
|
|
404
404
|
|
|
405
405
|
/**
|
|
406
406
|
`value()` synchronously returns the current value of the belongs-to
|
|
407
|
-
relationship. Unlike `record.
|
|
407
|
+
relationship. Unlike `record.relationshipName`, calling
|
|
408
408
|
`value()` on a reference does not trigger a fetch if the async
|
|
409
409
|
relationship is not yet loaded. If the relationship is not loaded
|
|
410
410
|
it will always return `null`.
|
|
@@ -11,8 +11,8 @@ import type { ManyRelationship } from '@ember-data/record-data/-private';
|
|
|
11
11
|
import type Store from '@ember-data/store';
|
|
12
12
|
import { recordIdentifierFor } from '@ember-data/store';
|
|
13
13
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
14
|
-
import type { NotificationType } from '@ember-data/store/-private/record-notification-manager';
|
|
15
|
-
import type { DebugWeakCache } from '@ember-data/store/-private/weak-cache';
|
|
14
|
+
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
|
|
15
|
+
import type { DebugWeakCache } from '@ember-data/store/-private/utils/weak-cache';
|
|
16
16
|
import type {
|
|
17
17
|
CollectionResourceDocument,
|
|
18
18
|
CollectionResourceRelationship,
|
|
@@ -131,7 +131,7 @@ export default class HasManyReference {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
_resource() {
|
|
134
|
-
return this.store._instanceCache.
|
|
134
|
+
return this.store._instanceCache.getRecordData(this.#identifier).getHasMany(this.key);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
@@ -435,16 +435,14 @@ export default class HasManyReference {
|
|
|
435
435
|
|
|
436
436
|
let members = this.hasManyRelationship.currentState;
|
|
437
437
|
|
|
438
|
-
//TODO @runspired determine isLoaded via a better means
|
|
439
438
|
return members.every((identifier) => {
|
|
440
|
-
|
|
441
|
-
return internalModel.isLoaded === true;
|
|
439
|
+
return this.store._instanceCache.recordIsLoaded(identifier, true) === true;
|
|
442
440
|
});
|
|
443
441
|
}
|
|
444
442
|
|
|
445
443
|
/**
|
|
446
444
|
`value()` synchronously returns the current value of the has-many
|
|
447
|
-
relationship. Unlike `record.
|
|
445
|
+
relationship. Unlike `record.relationshipName`, calling
|
|
448
446
|
`value()` on a reference does not trigger a fetch if the async
|
|
449
447
|
relationship is not yet loaded. If the relationship is not loaded
|
|
450
448
|
it will always return `null`.
|
|
@@ -474,7 +472,7 @@ export default class HasManyReference {
|
|
|
474
472
|
|
|
475
473
|
let commentsRef = post.hasMany('comments');
|
|
476
474
|
|
|
477
|
-
post.
|
|
475
|
+
post.comments.then(function(comments) {
|
|
478
476
|
commentsRef.value() === comments
|
|
479
477
|
})
|
|
480
478
|
```
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { dasherize } from '@ember/string';
|
|
1
2
|
import { DEBUG } from '@glimmer/env';
|
|
2
3
|
|
|
3
4
|
import { singularize } from 'ember-inflector';
|
|
4
5
|
|
|
5
6
|
import type Store from '@ember-data/store';
|
|
6
|
-
import { normalizeModelName } from '@ember-data/store/-private';
|
|
7
7
|
import type { RelationshipSchema } from '@ember-data/types/q/record-data-schemas';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -11,7 +11,7 @@ import type { RelationshipSchema } from '@ember-data/types/q/record-data-schemas
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
function typeForRelationshipMeta(meta) {
|
|
14
|
-
let modelName =
|
|
14
|
+
let modelName = dasherize(meta.type || meta.key);
|
|
15
15
|
|
|
16
16
|
if (meta.kind === 'hasMany') {
|
|
17
17
|
modelName = singularize(modelName);
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/model",
|
|
3
|
-
"version": "4.8.0-alpha.
|
|
3
|
+
"version": "4.8.0-alpha.3",
|
|
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.8.0-alpha.
|
|
22
|
-
"@ember-data/private-build-infra": "4.8.0-alpha.
|
|
23
|
-
"@ember-data/store": "4.8.0-alpha.
|
|
21
|
+
"@ember-data/canary-features": "4.8.0-alpha.3",
|
|
22
|
+
"@ember-data/private-build-infra": "4.8.0-alpha.3",
|
|
23
|
+
"@ember-data/store": "4.8.0-alpha.3",
|
|
24
24
|
"@ember/edition-utils": "^1.2.0",
|
|
25
25
|
"@ember/string": "^3.0.0",
|
|
26
26
|
"@embroider/macros": "^1.8.3",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"inflection": "~1.13.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@ember-data/unpublished-test-infra": "4.8.0-alpha.
|
|
37
|
+
"@ember-data/unpublished-test-infra": "4.8.0-alpha.3",
|
|
38
38
|
"@ember/optional-features": "^2.0.0",
|
|
39
39
|
"@ember/test-helpers": "~2.7.0",
|
|
40
40
|
"broccoli-asset-rev": "^3.0.0",
|
|
@@ -61,8 +61,7 @@
|
|
|
61
61
|
"webpack": "^5.74.0"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
|
-
"node": "^14.8.0 || 16.* || >= 18.*"
|
|
65
|
-
"yarn": "1.22.19"
|
|
64
|
+
"node": "^14.8.0 || 16.* || >= 18.*"
|
|
66
65
|
},
|
|
67
66
|
"ember-addon": {
|
|
68
67
|
"configPath": "tests/dummy/config"
|