@ember-data/model 5.3.10 → 5.3.12
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/LICENSE.md +19 -7
- package/README.md +2 -2
- package/dist/-private.js +3 -2
- package/dist/-private.js.map +1 -1
- package/dist/{has-many-B7JDN69X.js → has-many-DZX7l2bT.js} +1 -1
- package/dist/has-many-DZX7l2bT.js.map +1 -0
- package/dist/{hooks-CW9adWmR.js → hooks-RqMlE4Jk.js} +2 -2
- package/dist/{hooks-CW9adWmR.js.map → hooks-RqMlE4Jk.js.map} +1 -1
- package/dist/hooks.js +2 -2
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/migration-support.js +2 -2
- package/dist/migration-support.js.map +1 -1
- package/dist/{model-CAqu4cYw.js → model-6Exz3e1N.js} +108 -520
- package/dist/model-6Exz3e1N.js.map +1 -0
- package/dist/{schema-provider-BtvdNYTK.js → schema-provider-B-FIifVG.js} +1 -1
- package/dist/schema-provider-B-FIifVG.js.map +1 -0
- package/logos/NCC-1701-a-blue.svg +4 -0
- package/logos/NCC-1701-a-gold.svg +4 -0
- package/logos/NCC-1701-a-gold_100.svg +1 -0
- package/logos/NCC-1701-a-gold_base-64.txt +1 -0
- package/logos/NCC-1701-a.svg +4 -0
- package/logos/README.md +4 -0
- package/logos/docs-badge.svg +2 -0
- package/logos/github-header.svg +444 -0
- package/logos/social1.png +0 -0
- package/logos/social2.png +0 -0
- package/logos/warp-drive-logo-dark.svg +4 -0
- package/logos/warp-drive-logo-gold.svg +4 -0
- package/package.json +32 -63
- package/unstable-preview-types/-private/belongs-to.d.ts +1 -0
- package/unstable-preview-types/-private/belongs-to.d.ts.map +1 -1
- package/unstable-preview-types/-private/debug/assert-polymorphic-type.d.ts.map +1 -1
- package/unstable-preview-types/-private/legacy-relationships-support.d.ts +1 -1
- package/unstable-preview-types/-private/legacy-relationships-support.d.ts.map +1 -1
- package/unstable-preview-types/-private/model.d.ts +21 -23
- package/unstable-preview-types/-private/model.d.ts.map +1 -1
- package/unstable-preview-types/-private/notify-changes.d.ts.map +1 -1
- package/unstable-preview-types/-private/promise-many-array.d.ts +1 -1
- package/unstable-preview-types/-private/promise-many-array.d.ts.map +1 -1
- package/unstable-preview-types/-private/promise-proxy-base.d.ts +5 -0
- package/unstable-preview-types/-private/promise-proxy-base.d.ts.map +1 -0
- package/unstable-preview-types/-private/record-state.d.ts +1 -1
- package/unstable-preview-types/-private/references/has-many.d.ts +1 -1
- package/unstable-preview-types/-private/references/has-many.d.ts.map +1 -1
- package/unstable-preview-types/-private/schema-provider.d.ts +7 -7
- package/unstable-preview-types/-private/schema-provider.d.ts.map +1 -1
- package/unstable-preview-types/-private/type-utils.d.ts +1 -1
- package/unstable-preview-types/-private/type-utils.d.ts.map +1 -1
- package/unstable-preview-types/-private.d.ts +1 -1
- package/unstable-preview-types/-private.d.ts.map +1 -1
- package/unstable-preview-types/index.d.ts +19 -19
- package/unstable-preview-types/index.d.ts.map +1 -1
- package/unstable-preview-types/migration-support.d.ts +11 -4
- package/unstable-preview-types/migration-support.d.ts.map +1 -1
- package/dist/has-many-B7JDN69X.js.map +0 -1
- package/dist/model-CAqu4cYw.js.map +0 -1
- package/dist/schema-provider-BtvdNYTK.js.map +0 -1
- package/unstable-preview-types/-private/many-array.d.ts +0 -196
- package/unstable-preview-types/-private/many-array.d.ts.map +0 -1
- /package/{ember-data-logo-dark.svg → logos/ember-data-logo-dark.svg} +0 -0
- /package/{ember-data-logo-light.svg → logos/ember-data-logo-light.svg} +0 -0
|
@@ -3,15 +3,16 @@ import { dasherize } from '@ember-data/request-utils/string';
|
|
|
3
3
|
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
4
4
|
import EmberObject, { computed, get } from '@ember/object';
|
|
5
5
|
import { recordIdentifierFor as recordIdentifierFor$1, storeFor as storeFor$1 } from '@ember-data/store';
|
|
6
|
-
import {
|
|
6
|
+
import { isStableIdentifier, recordIdentifierFor, storeFor, peekCache, SOURCE, fastPush, RelatedCollection, coerceId } from '@ember-data/store/-private';
|
|
7
7
|
import { cached, compat } from '@ember-data/tracking';
|
|
8
|
-
import {
|
|
8
|
+
import { defineSignal, peekSignal, addToTransaction, getSignal, subscribe } from '@ember-data/tracking/-private';
|
|
9
9
|
import { RecordStore } from '@warp-drive/core-types/symbols';
|
|
10
10
|
import { A } from '@ember/array';
|
|
11
11
|
import ArrayProxy from '@ember/array/proxy';
|
|
12
12
|
import { mapBy, not } from '@ember/object/computed';
|
|
13
13
|
import { upgradeStore } from '@ember-data/legacy-compat/-private';
|
|
14
14
|
import { getOrSetGlobal } from '@warp-drive/core-types/-private';
|
|
15
|
+
import { EnableHydration } from '@warp-drive/core-types/request';
|
|
15
16
|
import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
|
|
16
17
|
import ObjectProxy from '@ember/object/proxy';
|
|
17
18
|
import { cacheFor } from '@ember/object/internals';
|
|
@@ -46,466 +47,6 @@ function normalizeModelName(type) {
|
|
|
46
47
|
}
|
|
47
48
|
return type;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
@module @ember-data/store
|
|
52
|
-
*/
|
|
53
|
-
/**
|
|
54
|
-
A `ManyArray` is a `MutableArray` that represents the contents of a has-many
|
|
55
|
-
relationship.
|
|
56
|
-
|
|
57
|
-
The `ManyArray` is instantiated lazily the first time the relationship is
|
|
58
|
-
requested.
|
|
59
|
-
|
|
60
|
-
This class is not intended to be directly instantiated by consuming applications.
|
|
61
|
-
|
|
62
|
-
### Inverses
|
|
63
|
-
|
|
64
|
-
Often, the relationships in Ember Data applications will have
|
|
65
|
-
an inverse. For example, imagine the following models are
|
|
66
|
-
defined:
|
|
67
|
-
|
|
68
|
-
```app/models/post.js
|
|
69
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
70
|
-
|
|
71
|
-
export default class PostModel extends Model {
|
|
72
|
-
@hasMany('comment') comments;
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
```app/models/comment.js
|
|
77
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
78
|
-
|
|
79
|
-
export default class CommentModel extends Model {
|
|
80
|
-
@belongsTo('post') post;
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
If you created a new instance of `Post` and added
|
|
85
|
-
a `Comment` record to its `comments` has-many
|
|
86
|
-
relationship, you would expect the comment's `post`
|
|
87
|
-
property to be set to the post that contained
|
|
88
|
-
the has-many.
|
|
89
|
-
|
|
90
|
-
We call the record to which a relationship belongs-to the
|
|
91
|
-
relationship's _owner_.
|
|
92
|
-
|
|
93
|
-
@class ManyArray
|
|
94
|
-
@public
|
|
95
|
-
*/
|
|
96
|
-
class RelatedCollection extends LiveArray {
|
|
97
|
-
/**
|
|
98
|
-
The loading state of this array
|
|
99
|
-
@property {Boolean} isLoaded
|
|
100
|
-
@public
|
|
101
|
-
*/
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
`true` if the relationship is polymorphic, `false` otherwise.
|
|
105
|
-
@property {Boolean} isPolymorphic
|
|
106
|
-
@private
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
Metadata associated with the request for async hasMany relationships.
|
|
111
|
-
Example
|
|
112
|
-
Given that the server returns the following JSON payload when fetching a
|
|
113
|
-
hasMany relationship:
|
|
114
|
-
```js
|
|
115
|
-
{
|
|
116
|
-
"comments": [{
|
|
117
|
-
"id": 1,
|
|
118
|
-
"comment": "This is the first comment",
|
|
119
|
-
}, {
|
|
120
|
-
// ...
|
|
121
|
-
}],
|
|
122
|
-
"meta": {
|
|
123
|
-
"page": 1,
|
|
124
|
-
"total": 5
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
You can then access the meta data via the `meta` property:
|
|
129
|
-
```js
|
|
130
|
-
let comments = await post.comments;
|
|
131
|
-
let meta = comments.meta;
|
|
132
|
-
// meta.page => 1
|
|
133
|
-
// meta.total => 5
|
|
134
|
-
```
|
|
135
|
-
@property {Object | null} meta
|
|
136
|
-
@public
|
|
137
|
-
*/
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Retrieve the links for this relationship
|
|
141
|
-
*
|
|
142
|
-
@property {Object | null} links
|
|
143
|
-
@public
|
|
144
|
-
*/
|
|
145
|
-
|
|
146
|
-
constructor(options) {
|
|
147
|
-
super(options);
|
|
148
|
-
this.isLoaded = options.isLoaded || false;
|
|
149
|
-
this.isAsync = options.isAsync || false;
|
|
150
|
-
this.isPolymorphic = options.isPolymorphic || false;
|
|
151
|
-
this.identifier = options.identifier;
|
|
152
|
-
this.key = options.key;
|
|
153
|
-
}
|
|
154
|
-
[MUTATE](target, receiver, prop, args, _SIGNAL) {
|
|
155
|
-
switch (prop) {
|
|
156
|
-
case 'length 0':
|
|
157
|
-
{
|
|
158
|
-
Reflect.set(target, 'length', 0);
|
|
159
|
-
mutateReplaceRelatedRecords(this, [], _SIGNAL);
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
case 'replace cell':
|
|
163
|
-
{
|
|
164
|
-
const [index, prior, value] = args;
|
|
165
|
-
target[index] = value;
|
|
166
|
-
mutateReplaceRelatedRecord(this, {
|
|
167
|
-
value,
|
|
168
|
-
prior,
|
|
169
|
-
index
|
|
170
|
-
}, _SIGNAL);
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
case 'push':
|
|
174
|
-
{
|
|
175
|
-
const newValues = extractIdentifiersFromRecords(args);
|
|
176
|
-
assertNoDuplicates(this, target, currentState => currentState.push(...newValues), `Cannot push duplicates to a hasMany's state.`);
|
|
177
|
-
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
178
|
-
// dedupe
|
|
179
|
-
const seen = new Set(target);
|
|
180
|
-
const unique = new Set();
|
|
181
|
-
args.forEach(item => {
|
|
182
|
-
const identifier = recordIdentifierFor(item);
|
|
183
|
-
if (!seen.has(identifier)) {
|
|
184
|
-
seen.add(identifier);
|
|
185
|
-
unique.add(item);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
const newArgs = Array.from(unique);
|
|
189
|
-
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
190
|
-
if (newArgs.length) {
|
|
191
|
-
mutateAddToRelatedRecords(this, {
|
|
192
|
-
value: extractIdentifiersFromRecords(newArgs)
|
|
193
|
-
}, _SIGNAL);
|
|
194
|
-
}
|
|
195
|
-
return result;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// else, no dedupe, error on duplicates
|
|
199
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
200
|
-
if (newValues.length) {
|
|
201
|
-
mutateAddToRelatedRecords(this, {
|
|
202
|
-
value: newValues
|
|
203
|
-
}, _SIGNAL);
|
|
204
|
-
}
|
|
205
|
-
return result;
|
|
206
|
-
}
|
|
207
|
-
case 'pop':
|
|
208
|
-
{
|
|
209
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
210
|
-
if (result) {
|
|
211
|
-
mutateRemoveFromRelatedRecords(this, {
|
|
212
|
-
value: recordIdentifierFor(result)
|
|
213
|
-
}, _SIGNAL);
|
|
214
|
-
}
|
|
215
|
-
return result;
|
|
216
|
-
}
|
|
217
|
-
case 'unshift':
|
|
218
|
-
{
|
|
219
|
-
const newValues = extractIdentifiersFromRecords(args);
|
|
220
|
-
assertNoDuplicates(this, target, currentState => currentState.unshift(...newValues), `Cannot unshift duplicates to a hasMany's state.`);
|
|
221
|
-
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
222
|
-
// dedupe
|
|
223
|
-
const seen = new Set(target);
|
|
224
|
-
const unique = new Set();
|
|
225
|
-
args.forEach(item => {
|
|
226
|
-
const identifier = recordIdentifierFor(item);
|
|
227
|
-
if (!seen.has(identifier)) {
|
|
228
|
-
seen.add(identifier);
|
|
229
|
-
unique.add(item);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
const newArgs = Array.from(unique);
|
|
233
|
-
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
234
|
-
if (newArgs.length) {
|
|
235
|
-
mutateAddToRelatedRecords(this, {
|
|
236
|
-
value: extractIdentifiersFromRecords(newArgs),
|
|
237
|
-
index: 0
|
|
238
|
-
}, _SIGNAL);
|
|
239
|
-
}
|
|
240
|
-
return result;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// else, no dedupe, error on duplicates
|
|
244
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
245
|
-
if (newValues.length) {
|
|
246
|
-
mutateAddToRelatedRecords(this, {
|
|
247
|
-
value: newValues,
|
|
248
|
-
index: 0
|
|
249
|
-
}, _SIGNAL);
|
|
250
|
-
}
|
|
251
|
-
return result;
|
|
252
|
-
}
|
|
253
|
-
case 'shift':
|
|
254
|
-
{
|
|
255
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
256
|
-
if (result) {
|
|
257
|
-
mutateRemoveFromRelatedRecords(this, {
|
|
258
|
-
value: recordIdentifierFor(result),
|
|
259
|
-
index: 0
|
|
260
|
-
}, _SIGNAL);
|
|
261
|
-
}
|
|
262
|
-
return result;
|
|
263
|
-
}
|
|
264
|
-
case 'sort':
|
|
265
|
-
{
|
|
266
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
267
|
-
mutateSortRelatedRecords(this, result.map(recordIdentifierFor), _SIGNAL);
|
|
268
|
-
return result;
|
|
269
|
-
}
|
|
270
|
-
case 'splice':
|
|
271
|
-
{
|
|
272
|
-
const [start, deleteCount, ...adds] = args;
|
|
273
|
-
|
|
274
|
-
// detect a full replace
|
|
275
|
-
if (start === 0 && deleteCount === this[SOURCE].length) {
|
|
276
|
-
const newValues = extractIdentifiersFromRecords(adds);
|
|
277
|
-
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot replace a hasMany's state with a new state that contains duplicates.`);
|
|
278
|
-
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
279
|
-
// dedupe
|
|
280
|
-
const current = new Set(adds);
|
|
281
|
-
const unique = Array.from(current);
|
|
282
|
-
const newArgs = [start, deleteCount].concat(unique);
|
|
283
|
-
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
284
|
-
mutateReplaceRelatedRecords(this, extractIdentifiersFromRecords(unique), _SIGNAL);
|
|
285
|
-
return result;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// else, no dedupe, error on duplicates
|
|
289
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
290
|
-
mutateReplaceRelatedRecords(this, newValues, _SIGNAL);
|
|
291
|
-
return result;
|
|
292
|
-
}
|
|
293
|
-
const newValues = extractIdentifiersFromRecords(adds);
|
|
294
|
-
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot splice a hasMany's state with a new state that contains duplicates.`);
|
|
295
|
-
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
296
|
-
// dedupe
|
|
297
|
-
const currentState = target.slice();
|
|
298
|
-
currentState.splice(start, deleteCount);
|
|
299
|
-
const seen = new Set(currentState);
|
|
300
|
-
const unique = [];
|
|
301
|
-
adds.forEach(item => {
|
|
302
|
-
const identifier = recordIdentifierFor(item);
|
|
303
|
-
if (!seen.has(identifier)) {
|
|
304
|
-
seen.add(identifier);
|
|
305
|
-
unique.push(item);
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
const newArgs = [start, deleteCount, ...unique];
|
|
309
|
-
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
310
|
-
if (deleteCount > 0) {
|
|
311
|
-
mutateRemoveFromRelatedRecords(this, {
|
|
312
|
-
value: result.map(recordIdentifierFor),
|
|
313
|
-
index: start
|
|
314
|
-
}, _SIGNAL);
|
|
315
|
-
}
|
|
316
|
-
if (unique.length > 0) {
|
|
317
|
-
mutateAddToRelatedRecords(this, {
|
|
318
|
-
value: extractIdentifiersFromRecords(unique),
|
|
319
|
-
index: start
|
|
320
|
-
}, _SIGNAL);
|
|
321
|
-
}
|
|
322
|
-
return result;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// else, no dedupe, error on duplicates
|
|
326
|
-
const result = Reflect.apply(target[prop], receiver, args);
|
|
327
|
-
if (deleteCount > 0) {
|
|
328
|
-
mutateRemoveFromRelatedRecords(this, {
|
|
329
|
-
value: result.map(recordIdentifierFor),
|
|
330
|
-
index: start
|
|
331
|
-
}, _SIGNAL);
|
|
332
|
-
}
|
|
333
|
-
if (newValues.length > 0) {
|
|
334
|
-
mutateAddToRelatedRecords(this, {
|
|
335
|
-
value: newValues,
|
|
336
|
-
index: start
|
|
337
|
-
}, _SIGNAL);
|
|
338
|
-
}
|
|
339
|
-
return result;
|
|
340
|
-
}
|
|
341
|
-
default:
|
|
342
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
343
|
-
{
|
|
344
|
-
throw new Error(`unable to convert ${prop} into a transaction that updates the cache state for this record array`);
|
|
345
|
-
}
|
|
346
|
-
})() : {};
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
notify() {
|
|
350
|
-
const signal = this[ARRAY_SIGNAL];
|
|
351
|
-
signal.shouldReset = true;
|
|
352
|
-
notifyArray(this);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
Reloads all of the records in the manyArray. If the manyArray
|
|
357
|
-
holds a relationship that was originally fetched using a links url
|
|
358
|
-
EmberData will revisit the original links url to repopulate the
|
|
359
|
-
relationship.
|
|
360
|
-
If the ManyArray holds the result of a `store.query()` reload will
|
|
361
|
-
re-run the original query.
|
|
362
|
-
Example
|
|
363
|
-
```javascript
|
|
364
|
-
let user = store.peekRecord('user', '1')
|
|
365
|
-
await login(user);
|
|
366
|
-
let permissions = await user.permissions;
|
|
367
|
-
await permissions.reload();
|
|
368
|
-
```
|
|
369
|
-
@method reload
|
|
370
|
-
@public
|
|
371
|
-
*/
|
|
372
|
-
reload(options) {
|
|
373
|
-
// TODO this is odd, we don't ask the store for anything else like this?
|
|
374
|
-
return this._manager.reloadHasMany(this.key, options);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
Saves all of the records in the `ManyArray`.
|
|
379
|
-
Example
|
|
380
|
-
```javascript
|
|
381
|
-
let inbox = await store.findRecord('inbox', '1');
|
|
382
|
-
let messages = await inbox.messages;
|
|
383
|
-
messages.forEach((message) => {
|
|
384
|
-
message.isRead = true;
|
|
385
|
-
});
|
|
386
|
-
messages.save();
|
|
387
|
-
```
|
|
388
|
-
@method save
|
|
389
|
-
@public
|
|
390
|
-
@return {PromiseArray} promise
|
|
391
|
-
*/
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
Create a child record within the owner
|
|
395
|
-
@method createRecord
|
|
396
|
-
@public
|
|
397
|
-
@param {Object} hash
|
|
398
|
-
@return {Model} record
|
|
399
|
-
*/
|
|
400
|
-
createRecord(hash) {
|
|
401
|
-
const {
|
|
402
|
-
store
|
|
403
|
-
} = this;
|
|
404
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
405
|
-
if (!test) {
|
|
406
|
-
throw new Error(`Expected modelName to be set`);
|
|
407
|
-
}
|
|
408
|
-
})(this.modelName) : {};
|
|
409
|
-
const record = store.createRecord(this.modelName, hash);
|
|
410
|
-
this.push(record);
|
|
411
|
-
return record;
|
|
412
|
-
}
|
|
413
|
-
destroy() {
|
|
414
|
-
super.destroy(false);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
RelatedCollection.prototype.isAsync = false;
|
|
418
|
-
RelatedCollection.prototype.isPolymorphic = false;
|
|
419
|
-
RelatedCollection.prototype.identifier = null;
|
|
420
|
-
RelatedCollection.prototype.cache = null;
|
|
421
|
-
RelatedCollection.prototype._inverseIsAsync = false;
|
|
422
|
-
RelatedCollection.prototype.key = '';
|
|
423
|
-
RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
|
|
424
|
-
function assertRecordPassedToHasMany(record) {
|
|
425
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
426
|
-
if (!test) {
|
|
427
|
-
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed ${typeof record}`);
|
|
428
|
-
}
|
|
429
|
-
})(function () {
|
|
430
|
-
try {
|
|
431
|
-
recordIdentifierFor(record);
|
|
432
|
-
return true;
|
|
433
|
-
} catch {
|
|
434
|
-
return false;
|
|
435
|
-
}
|
|
436
|
-
}()) : {};
|
|
437
|
-
}
|
|
438
|
-
function extractIdentifiersFromRecords(records) {
|
|
439
|
-
return records.map(extractIdentifierFromRecord$1);
|
|
440
|
-
}
|
|
441
|
-
function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
|
|
442
|
-
assertRecordPassedToHasMany(recordOrPromiseRecord);
|
|
443
|
-
return recordIdentifierFor(recordOrPromiseRecord);
|
|
444
|
-
}
|
|
445
|
-
function assertNoDuplicates(collection, target, callback, reason) {
|
|
446
|
-
const state = target.slice();
|
|
447
|
-
callback(state);
|
|
448
|
-
if (state.length !== new Set(state).size) {
|
|
449
|
-
const duplicates = state.filter((currentValue, currentIndex) => state.indexOf(currentValue) !== currentIndex);
|
|
450
|
-
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
451
|
-
deprecate(`${reason} This behavior is deprecated. Found duplicates for the following records within the new state provided to \`<${collection.identifier.type}:${collection.identifier.id || collection.identifier.lid}>.${collection.key}\`\n\t- ${Array.from(new Set(duplicates)).map(r => isStableIdentifier(r) ? r.lid : recordIdentifierFor(r).lid).sort((a, b) => a.localeCompare(b)).join('\n\t- ')}`, false, {
|
|
452
|
-
id: 'ember-data:deprecate-many-array-duplicates',
|
|
453
|
-
for: 'ember-data',
|
|
454
|
-
until: '6.0',
|
|
455
|
-
since: {
|
|
456
|
-
enabled: '5.3',
|
|
457
|
-
available: '4.13'
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
} else {
|
|
461
|
-
throw new Error(`${reason} Found duplicates for the following records within the new state provided to \`<${collection.identifier.type}:${collection.identifier.id || collection.identifier.lid}>.${collection.key}\`\n\t- ${Array.from(new Set(duplicates)).map(r => isStableIdentifier(r) ? r.lid : recordIdentifierFor(r).lid).sort((a, b) => a.localeCompare(b)).join('\n\t- ')}`);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
466
|
-
mutate(collection, {
|
|
467
|
-
op: 'addToRelatedRecords',
|
|
468
|
-
record: collection.identifier,
|
|
469
|
-
field: collection.key,
|
|
470
|
-
...operationInfo
|
|
471
|
-
}, _SIGNAL);
|
|
472
|
-
}
|
|
473
|
-
function mutateRemoveFromRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
474
|
-
mutate(collection, {
|
|
475
|
-
op: 'removeFromRelatedRecords',
|
|
476
|
-
record: collection.identifier,
|
|
477
|
-
field: collection.key,
|
|
478
|
-
...operationInfo
|
|
479
|
-
}, _SIGNAL);
|
|
480
|
-
}
|
|
481
|
-
function mutateReplaceRelatedRecord(collection, operationInfo, _SIGNAL) {
|
|
482
|
-
mutate(collection, {
|
|
483
|
-
op: 'replaceRelatedRecord',
|
|
484
|
-
record: collection.identifier,
|
|
485
|
-
field: collection.key,
|
|
486
|
-
...operationInfo
|
|
487
|
-
}, _SIGNAL);
|
|
488
|
-
}
|
|
489
|
-
function mutateReplaceRelatedRecords(collection, value, _SIGNAL) {
|
|
490
|
-
mutate(collection, {
|
|
491
|
-
op: 'replaceRelatedRecords',
|
|
492
|
-
record: collection.identifier,
|
|
493
|
-
field: collection.key,
|
|
494
|
-
value
|
|
495
|
-
}, _SIGNAL);
|
|
496
|
-
}
|
|
497
|
-
function mutateSortRelatedRecords(collection, value, _SIGNAL) {
|
|
498
|
-
mutate(collection, {
|
|
499
|
-
op: 'sortRelatedRecords',
|
|
500
|
-
record: collection.identifier,
|
|
501
|
-
field: collection.key,
|
|
502
|
-
value
|
|
503
|
-
}, _SIGNAL);
|
|
504
|
-
}
|
|
505
|
-
function mutate(collection, mutation, _SIGNAL) {
|
|
506
|
-
collection._manager.mutate(mutation);
|
|
507
|
-
addToTransaction(_SIGNAL);
|
|
508
|
-
}
|
|
509
50
|
const PromiseObject = ObjectProxy.extend(PromiseProxyMixin);
|
|
510
51
|
const deferred = /* @__PURE__ */new WeakMap();
|
|
511
52
|
function deferDecorator(proto, prop, desc) {
|
|
@@ -895,16 +436,18 @@ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
|
895
436
|
}
|
|
896
437
|
if (parentDefinition.isPolymorphic) {
|
|
897
438
|
const meta = store.schema.fields(addedIdentifier)?.get(parentDefinition.inverseKey);
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
439
|
+
if (meta) {
|
|
440
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
441
|
+
if (!test) {
|
|
442
|
+
throw new Error(`Expected the schema for the field ${parentDefinition.inverseKey} on ${addedIdentifier.type} to be for a legacy relationship`);
|
|
443
|
+
}
|
|
444
|
+
})(meta.kind === 'belongsTo' || meta.kind === 'hasMany') : {};
|
|
445
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
446
|
+
if (!test) {
|
|
447
|
+
throw new Error(`The schema for the relationship '${parentDefinition.inverseKey}' on '${addedIdentifier.type}' type does not implement '${parentDefinition.type}' and thus cannot be assigned to the '${parentDefinition.key}' relationship in '${parentIdentifier.type}'. The definition should specify 'as: "${parentDefinition.type}"' in options.`);
|
|
448
|
+
}
|
|
449
|
+
})(meta?.options?.as === parentDefinition.type) : {};
|
|
450
|
+
}
|
|
908
451
|
}
|
|
909
452
|
};
|
|
910
453
|
}
|
|
@@ -994,9 +537,9 @@ class HasManyReference {
|
|
|
994
537
|
* @public
|
|
995
538
|
*/
|
|
996
539
|
get identifiers() {
|
|
540
|
+
ensureRefCanSubscribe(this);
|
|
997
541
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
998
|
-
this._ref;
|
|
999
|
-
|
|
542
|
+
this._ref;
|
|
1000
543
|
const resource = this._resource();
|
|
1001
544
|
const map = this.___relatedTokenMap;
|
|
1002
545
|
this.___relatedTokenMap = new Map();
|
|
@@ -1378,10 +921,7 @@ class HasManyReference {
|
|
|
1378
921
|
*/
|
|
1379
922
|
value() {
|
|
1380
923
|
const support = LEGACY_SUPPORT.get(this.___identifier);
|
|
1381
|
-
|
|
1382
|
-
if (!loaded) {
|
|
1383
|
-
// subscribe to changes
|
|
1384
|
-
// for when we are not loaded yet
|
|
924
|
+
if (!ensureRefCanSubscribe(this)) {
|
|
1385
925
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1386
926
|
this._ref;
|
|
1387
927
|
return null;
|
|
@@ -1501,6 +1041,26 @@ function isMaybeResource(object) {
|
|
|
1501
1041
|
const keys = Object.keys(object).filter(k => k !== 'id' && k !== 'type' && k !== 'lid');
|
|
1502
1042
|
return keys.length > 0;
|
|
1503
1043
|
}
|
|
1044
|
+
function ensureRefCanSubscribe(rel) {
|
|
1045
|
+
const loaded = rel._isLoaded();
|
|
1046
|
+
if (!loaded) {
|
|
1047
|
+
// subscribe to changes
|
|
1048
|
+
// for when we are not loaded yet
|
|
1049
|
+
//
|
|
1050
|
+
// because the graph optimizes the case where a relationship has never been subscribed,
|
|
1051
|
+
// we force accessed to be true here. When we make the graph public we should create a
|
|
1052
|
+
// subscribe/unsubscribe API
|
|
1053
|
+
const edge = rel.graph.get(rel.___identifier, rel.key);
|
|
1054
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1055
|
+
if (!test) {
|
|
1056
|
+
throw new Error(`Expected a hasMany relationship for ${rel.___identifier.type}:${rel.key}`);
|
|
1057
|
+
}
|
|
1058
|
+
})('accessed' in edge) : {};
|
|
1059
|
+
edge.accessed = true;
|
|
1060
|
+
return false;
|
|
1061
|
+
}
|
|
1062
|
+
return true;
|
|
1063
|
+
}
|
|
1504
1064
|
function isResourceIdentiferWithRelatedLinks(value) {
|
|
1505
1065
|
return Boolean(value && value.links && value.links.related);
|
|
1506
1066
|
}
|
|
@@ -2245,6 +1805,7 @@ class LegacySupport {
|
|
|
2245
1805
|
isPolymorphic: definition.isPolymorphic,
|
|
2246
1806
|
isAsync: definition.isAsync,
|
|
2247
1807
|
_inverseIsAsync: definition.inverseIsAsync,
|
|
1808
|
+
// @ts-expect-error Typescript doesn't have a way for us to thread the generic backwards so it infers unknown instead of T
|
|
2248
1809
|
manager: this,
|
|
2249
1810
|
isLoaded: !definition.isAsync,
|
|
2250
1811
|
allowMutation: true
|
|
@@ -2469,14 +2030,22 @@ class LegacySupport {
|
|
|
2469
2030
|
throw new Error(`Expected stable identifiers`);
|
|
2470
2031
|
}
|
|
2471
2032
|
})(!identifiers || identifiers.every(isStableIdentifier)) : {};
|
|
2472
|
-
|
|
2033
|
+
const req = field.options.linksMode ? {
|
|
2034
|
+
url: getRelatedLink(resource),
|
|
2035
|
+
op: 'findHasMany',
|
|
2036
|
+
method: 'GET',
|
|
2037
|
+
records: identifiers || [],
|
|
2038
|
+
data: request,
|
|
2039
|
+
[EnableHydration]: false
|
|
2040
|
+
} : {
|
|
2473
2041
|
op: 'findHasMany',
|
|
2474
2042
|
records: identifiers || [],
|
|
2475
2043
|
data: request,
|
|
2476
2044
|
cacheOptions: {
|
|
2477
2045
|
[Symbol.for('wd:skip-cache')]: true
|
|
2478
2046
|
}
|
|
2479
|
-
}
|
|
2047
|
+
};
|
|
2048
|
+
return this.store.request(req);
|
|
2480
2049
|
}
|
|
2481
2050
|
const preferLocalCache = hasReceivedData && !isEmpty;
|
|
2482
2051
|
const hasLocalPartialData = hasDematerializedInverse || isEmpty && Array.isArray(identifiers) && identifiers.length > 0;
|
|
@@ -2561,15 +2130,23 @@ class LegacySupport {
|
|
|
2561
2130
|
|
|
2562
2131
|
// fetch via link
|
|
2563
2132
|
if (shouldFindViaLink) {
|
|
2564
|
-
const
|
|
2133
|
+
const req = field.options.linksMode ? {
|
|
2134
|
+
url: getRelatedLink(resource),
|
|
2135
|
+
op: 'findBelongsTo',
|
|
2136
|
+
method: 'GET',
|
|
2137
|
+
records: identifier ? [identifier] : [],
|
|
2138
|
+
data: request,
|
|
2139
|
+
[EnableHydration]: false
|
|
2140
|
+
} : {
|
|
2565
2141
|
op: 'findBelongsTo',
|
|
2566
2142
|
records: identifier ? [identifier] : [],
|
|
2567
2143
|
data: request,
|
|
2568
2144
|
cacheOptions: {
|
|
2569
2145
|
[Symbol.for('wd:skip-cache')]: true
|
|
2570
2146
|
}
|
|
2571
|
-
}
|
|
2572
|
-
|
|
2147
|
+
};
|
|
2148
|
+
const future = this.store.request(req);
|
|
2149
|
+
this._pending[key] = future.then(doc => field.options.linksMode ? doc.content.data : doc.content).finally(() => {
|
|
2573
2150
|
this._pending[key] = undefined;
|
|
2574
2151
|
});
|
|
2575
2152
|
return this._pending[key];
|
|
@@ -2639,6 +2216,15 @@ class LegacySupport {
|
|
|
2639
2216
|
this.isDestroyed = true;
|
|
2640
2217
|
}
|
|
2641
2218
|
}
|
|
2219
|
+
function getRelatedLink(resource) {
|
|
2220
|
+
const related = resource.links?.related;
|
|
2221
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2222
|
+
if (!test) {
|
|
2223
|
+
throw new Error(`Expected a related link`);
|
|
2224
|
+
}
|
|
2225
|
+
})(related) : {};
|
|
2226
|
+
return typeof related === 'object' ? related.href : related;
|
|
2227
|
+
}
|
|
2642
2228
|
function handleCompletedRelationshipRequest(recordExt, key, relationship, value, error) {
|
|
2643
2229
|
delete recordExt._relationshipPromisesCache[key];
|
|
2644
2230
|
relationship.state.shouldForceReload = false;
|
|
@@ -3190,30 +2776,35 @@ function createSnapshot() {
|
|
|
3190
2776
|
return store._fetchManager.createSnapshot(recordIdentifierFor$1(this));
|
|
3191
2777
|
}
|
|
3192
2778
|
function notifyChanges(identifier, value, key, record, store) {
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
notifyRelationship(identifier,
|
|
3213
|
-
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
2779
|
+
switch (value) {
|
|
2780
|
+
case 'added':
|
|
2781
|
+
case 'attributes':
|
|
2782
|
+
if (key) {
|
|
2783
|
+
notifyAttribute(store, identifier, key, record);
|
|
2784
|
+
} else {
|
|
2785
|
+
record.eachAttribute(name => {
|
|
2786
|
+
notifyAttribute(store, identifier, name, record);
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
break;
|
|
2790
|
+
case 'relationships':
|
|
2791
|
+
if (key) {
|
|
2792
|
+
const meta = record.constructor.relationshipsByName.get(key);
|
|
2793
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2794
|
+
if (!test) {
|
|
2795
|
+
throw new Error(`Expected to find a relationship for ${key} on ${identifier.type}`);
|
|
2796
|
+
}
|
|
2797
|
+
})(meta) : {};
|
|
2798
|
+
notifyRelationship(identifier, key, record, meta);
|
|
2799
|
+
} else {
|
|
2800
|
+
record.eachRelationship((name, meta) => {
|
|
2801
|
+
notifyRelationship(identifier, name, record, meta);
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
break;
|
|
2805
|
+
case 'identity':
|
|
2806
|
+
record.notifyPropertyChange('id');
|
|
2807
|
+
break;
|
|
3217
2808
|
}
|
|
3218
2809
|
}
|
|
3219
2810
|
function notifyRelationship(identifier, key, record, meta) {
|
|
@@ -3812,9 +3403,8 @@ class Model extends EmberObject {
|
|
|
3812
3403
|
```javascript
|
|
3813
3404
|
let record = store.createRecord('model');
|
|
3814
3405
|
record.isLoaded; // true
|
|
3815
|
-
store.findRecord('model', 1)
|
|
3816
|
-
|
|
3817
|
-
});
|
|
3406
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
3407
|
+
model.isLoaded;
|
|
3818
3408
|
```
|
|
3819
3409
|
@property isLoaded
|
|
3820
3410
|
@public
|
|
@@ -3837,11 +3427,10 @@ class Model extends EmberObject {
|
|
|
3837
3427
|
```javascript
|
|
3838
3428
|
let record = store.createRecord('model');
|
|
3839
3429
|
record.hasDirtyAttributes; // true
|
|
3840
|
-
store.findRecord('model', 1)
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
});
|
|
3430
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
3431
|
+
model.hasDirtyAttributes; // false
|
|
3432
|
+
model.foo = 'some value';
|
|
3433
|
+
model.hasDirtyAttributes; // true
|
|
3845
3434
|
```
|
|
3846
3435
|
@since 1.13.0
|
|
3847
3436
|
@property hasDirtyAttributes
|
|
@@ -4042,9 +3631,8 @@ class Model extends EmberObject {
|
|
|
4042
3631
|
```javascript
|
|
4043
3632
|
let record = store.createRecord('model');
|
|
4044
3633
|
record.id; // null
|
|
4045
|
-
store.findRecord('model', 1)
|
|
4046
|
-
|
|
4047
|
-
});
|
|
3634
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
3635
|
+
model.id; // '1'
|
|
4048
3636
|
```
|
|
4049
3637
|
@property id
|
|
4050
3638
|
@public
|
|
@@ -5117,7 +4705,7 @@ class Model extends EmberObject {
|
|
|
5117
4705
|
if (isAttributeSchema(meta)) {
|
|
5118
4706
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5119
4707
|
if (!test) {
|
|
5120
|
-
throw new Error("You may not set
|
|
4708
|
+
throw new Error("You may not set 'id' as an attribute on your model. Please remove any lines that look like: `id: attr('<type>')` from " + this.toString());
|
|
5121
4709
|
}
|
|
5122
4710
|
})(name !== 'id') : {};
|
|
5123
4711
|
|
|
@@ -5352,4 +4940,4 @@ function isRelationshipSchema(meta) {
|
|
|
5352
4940
|
function isAttributeSchema(meta) {
|
|
5353
4941
|
return typeof meta === 'object' && meta !== null && 'kind' in meta && meta.kind === 'attribute';
|
|
5354
4942
|
}
|
|
5355
|
-
export { Errors as E, LEGACY_SUPPORT as L, Model as M, PromiseBelongsTo as P,
|
|
4943
|
+
export { Errors as E, LEGACY_SUPPORT as L, Model as M, PromiseBelongsTo as P, RecordState as R, PromiseManyArray as a, save as b, reload as c, destroyRecord as d, deleteRecord as e, changedAttributes as f, belongsTo as g, hasMany as h, createSnapshot as i, isElementDescriptor as j, lookupLegacySupport as l, normalizeModelName as n, rollbackAttributes as r, serialize as s, unloadRecord as u };
|