@ember-data/legacy-compat 4.12.7 → 4.13.0-alpha.1

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 (60) hide show
  1. package/README.md +8 -0
  2. package/addon-main.cjs +5 -0
  3. package/{addon/fetch-manager-025964e9.js → dist/-private-BJlhRRce.js} +321 -194
  4. package/dist/-private-BJlhRRce.js.map +1 -0
  5. package/dist/-private.js +1 -0
  6. package/dist/builders.js +303 -0
  7. package/dist/builders.js.map +1 -0
  8. package/dist/index.js +1087 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/utils-XGHLsgBS.js +23 -0
  11. package/dist/utils-XGHLsgBS.js.map +1 -0
  12. package/dist/utils.js +246 -0
  13. package/dist/utils.js.map +1 -0
  14. package/package.json +72 -35
  15. package/unstable-preview-types/-private.d.ts +17 -0
  16. package/unstable-preview-types/-private.d.ts.map +1 -0
  17. package/unstable-preview-types/builders/find-all.d.ts +41 -0
  18. package/unstable-preview-types/builders/find-all.d.ts.map +1 -0
  19. package/unstable-preview-types/builders/find-record.d.ts +62 -0
  20. package/unstable-preview-types/builders/find-record.d.ts.map +1 -0
  21. package/unstable-preview-types/builders/query.d.ts +72 -0
  22. package/unstable-preview-types/builders/query.d.ts.map +1 -0
  23. package/unstable-preview-types/builders/save-record.d.ts +40 -0
  24. package/unstable-preview-types/builders/save-record.d.ts.map +1 -0
  25. package/unstable-preview-types/builders/utils.d.ts +6 -0
  26. package/unstable-preview-types/builders/utils.d.ts.map +1 -0
  27. package/unstable-preview-types/builders.d.ts +18 -0
  28. package/unstable-preview-types/builders.d.ts.map +1 -0
  29. package/unstable-preview-types/index.d.ts +163 -0
  30. package/unstable-preview-types/index.d.ts.map +1 -0
  31. package/unstable-preview-types/legacy-network-handler/fetch-manager.d.ts +49 -0
  32. package/unstable-preview-types/legacy-network-handler/fetch-manager.d.ts.map +1 -0
  33. package/unstable-preview-types/legacy-network-handler/identifier-has-id.d.ts +5 -0
  34. package/unstable-preview-types/legacy-network-handler/identifier-has-id.d.ts.map +1 -0
  35. package/unstable-preview-types/legacy-network-handler/legacy-data-fetch.d.ts +15 -0
  36. package/unstable-preview-types/legacy-network-handler/legacy-data-fetch.d.ts.map +1 -0
  37. package/unstable-preview-types/legacy-network-handler/legacy-data-utils.d.ts +8 -0
  38. package/unstable-preview-types/legacy-network-handler/legacy-data-utils.d.ts.map +1 -0
  39. package/unstable-preview-types/legacy-network-handler/legacy-network-handler.d.ts +5 -0
  40. package/unstable-preview-types/legacy-network-handler/legacy-network-handler.d.ts.map +1 -0
  41. package/unstable-preview-types/legacy-network-handler/minimum-adapter-interface.d.ts +549 -0
  42. package/unstable-preview-types/legacy-network-handler/minimum-adapter-interface.d.ts.map +1 -0
  43. package/unstable-preview-types/legacy-network-handler/minimum-serializer-interface.d.ts +235 -0
  44. package/unstable-preview-types/legacy-network-handler/minimum-serializer-interface.d.ts.map +1 -0
  45. package/unstable-preview-types/legacy-network-handler/serializer-response.d.ts +9 -0
  46. package/unstable-preview-types/legacy-network-handler/serializer-response.d.ts.map +1 -0
  47. package/unstable-preview-types/legacy-network-handler/snapshot-record-array.d.ts +96 -0
  48. package/unstable-preview-types/legacy-network-handler/snapshot-record-array.d.ts.map +1 -0
  49. package/unstable-preview-types/legacy-network-handler/snapshot.d.ts +257 -0
  50. package/unstable-preview-types/legacy-network-handler/snapshot.d.ts.map +1 -0
  51. package/unstable-preview-types/legacy-network-handler/utils.d.ts +8 -0
  52. package/unstable-preview-types/legacy-network-handler/utils.d.ts.map +1 -0
  53. package/unstable-preview-types/utils.d.ts +161 -0
  54. package/unstable-preview-types/utils.d.ts.map +1 -0
  55. package/addon/-private.js +0 -1
  56. package/addon/fetch-manager-025964e9.js.map +0 -1
  57. package/addon/index.js +0 -673
  58. package/addon/index.js.map +0 -1
  59. package/addon-main.js +0 -93
  60. /package/{addon → dist}/-private.js.map +0 -0
package/addon/index.js DELETED
@@ -1,673 +0,0 @@
1
- import { deprecate, assert } from '@ember/debug';
2
- import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
3
- import { g as guardDestroyedStore, _ as _objectIsAlive, p as payloadIsNotBlank, n as normalizeResponseHelper, c as _guard, i as iterateData, d as _bind, F as FetchManager, e as assertIdentifierHasId, a as SaveOp, S as SnapshotRecordArray } from "./fetch-manager-025964e9";
4
- function _findHasMany(adapter, store, identifier, link, relationship, options) {
5
- let promise = Promise.resolve().then(() => {
6
- const snapshot = store._fetchManager.createSnapshot(identifier, options);
7
- let useLink = !link || typeof link === 'string';
8
- let relatedLink = useLink ? link : link.href;
9
- return adapter.findHasMany(store, snapshot, relatedLink, relationship);
10
- });
11
- promise = guardDestroyedStore(promise, store);
12
- promise = promise.then(adapterPayload => {
13
- const record = store._instanceCache.getRecord(identifier);
14
- if (!_objectIsAlive(record)) {
15
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
16
- deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
17
- id: 'ember-data:rsvp-unresolved-async',
18
- until: '5.0',
19
- for: '@ember-data/store',
20
- since: {
21
- available: '4.5',
22
- enabled: '4.5'
23
- }
24
- });
25
- }
26
- }
27
- assert(`You made a 'findHasMany' request for a ${identifier.type}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
28
- const modelClass = store.modelFor(relationship.type);
29
- let serializer = store.serializerFor(relationship.type);
30
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
31
- assert(`fetched the hasMany relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: [] }`, 'data' in payload && Array.isArray(payload.data));
32
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
33
- return store._push(payload, true);
34
- }, null, `DS: Extract payload of '${identifier.type}' : hasMany '${relationship.type}'`);
35
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
36
- const record = store._instanceCache.getRecord(identifier);
37
- promise = _guard(promise, _bind(_objectIsAlive, record));
38
- }
39
- return promise;
40
- }
41
- function _findBelongsTo(store, identifier, link, relationship, options) {
42
- let promise = Promise.resolve().then(() => {
43
- let adapter = store.adapterFor(identifier.type);
44
- assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
45
- assert(`You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, typeof adapter.findBelongsTo === 'function');
46
- let snapshot = store._fetchManager.createSnapshot(identifier, options);
47
- let useLink = !link || typeof link === 'string';
48
- let relatedLink = useLink ? link : link.href;
49
- return adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
50
- });
51
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
52
- const record = store._instanceCache.getRecord(identifier);
53
- promise = guardDestroyedStore(promise, store);
54
- promise = _guard(promise, _bind(_objectIsAlive, record));
55
- }
56
- promise = promise.then(adapterPayload => {
57
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
58
- const record = store._instanceCache.getRecord(identifier);
59
- if (!_objectIsAlive(record)) {
60
- deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
61
- id: 'ember-data:rsvp-unresolved-async',
62
- until: '5.0',
63
- for: '@ember-data/store',
64
- since: {
65
- available: '4.5',
66
- enabled: '4.5'
67
- }
68
- });
69
- }
70
- }
71
- let modelClass = store.modelFor(relationship.type);
72
- let serializer = store.serializerFor(relationship.type);
73
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
74
- assert(`fetched the belongsTo relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: null }`, 'data' in payload && (payload.data === null || typeof payload.data === 'object' && !Array.isArray(payload.data)));
75
- if (!payload.data && !payload.links && !payload.meta) {
76
- return null;
77
- }
78
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
79
- return store._push(payload, true);
80
- }, null, `DS: Extract payload of ${identifier.type} : ${relationship.type}`);
81
- return promise;
82
- }
83
-
84
- // sync
85
- // iterate over records in payload.data
86
- // for each record
87
- // assert that record.relationships[inverse] is either undefined (so we can fix it)
88
- // or provide a data: {id, type} that matches the record that requested it
89
- // return the relationship data for the parent
90
- function syncRelationshipDataFromLink(store, payload, parentIdentifier, relationship) {
91
- // ensure the right hand side (incoming payload) points to the parent record that
92
- // requested this relationship
93
- let relationshipData = payload.data ? iterateData(payload.data, (data, index) => {
94
- const {
95
- id,
96
- type
97
- } = data;
98
- ensureRelationshipIsSetToParent(data, parentIdentifier, store, relationship, index);
99
- return {
100
- id,
101
- type
102
- };
103
- }) : null;
104
- const relatedDataHash = {};
105
- if ('meta' in payload) {
106
- relatedDataHash.meta = payload.meta;
107
- }
108
- if ('links' in payload) {
109
- relatedDataHash.links = payload.links;
110
- }
111
- if ('data' in payload) {
112
- relatedDataHash.data = relationshipData;
113
- }
114
-
115
- // now, push the left hand side (the parent record) to ensure things are in sync, since
116
- // the payload will be pushed with store._push
117
- const parentPayload = {
118
- id: parentIdentifier.id,
119
- type: parentIdentifier.type,
120
- relationships: {
121
- [relationship.key]: relatedDataHash
122
- }
123
- };
124
- if (!Array.isArray(payload.included)) {
125
- payload.included = [];
126
- }
127
- payload.included.push(parentPayload);
128
- return payload;
129
- }
130
- function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, parentRelationship, index) {
131
- let {
132
- id,
133
- type
134
- } = payload;
135
- if (!payload.relationships) {
136
- payload.relationships = {};
137
- }
138
- let {
139
- relationships
140
- } = payload;
141
- let inverse = getInverse(store, parentIdentifier, parentRelationship, type);
142
- if (inverse) {
143
- let {
144
- inverseKey,
145
- kind
146
- } = inverse;
147
- let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
148
- if (macroCondition(getOwnConfig().env.DEBUG)) {
149
- if (typeof relationshipData !== 'undefined' && !relationshipDataPointsToParent(relationshipData, parentIdentifier)) {
150
- let inspect = function inspect(thing) {
151
- return `'${JSON.stringify(thing)}'`;
152
- };
153
- let quotedType = inspect(type);
154
- let quotedInverse = inspect(inverseKey);
155
- let expected = inspect({
156
- id: parentIdentifier.id,
157
- type: parentIdentifier.type
158
- });
159
- let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
160
- let got = inspect(relationshipData);
161
- let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
162
- let path = `${prefix}.relationships.${inverseKey}.data`;
163
- let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
164
- let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
165
- let includedRecord = `<${type}:${id}>`;
166
- let message = [`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`, `The ${includedRecord} record loaded at ${prefix} in the payload specified ${other} as its ${quotedInverse}, but should have specified ${expectedModel} (the record the relationship is being loaded from) as its ${quotedInverse} instead.`, `This could mean that the response for ${relationshipFetched} may have accidentally returned ${quotedType} records that aren't related to ${expectedModel} and could be related to a different ${parentIdentifier.type} record instead.`, `Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`, `Please update the response from the server or change your serializer to either ensure that the response for only includes ${quotedType} records that specify ${expectedModel} as their ${quotedInverse}, or omit the ${quotedInverse} relationship from the response.`].join('\n');
167
- assert(message);
168
- }
169
- }
170
- if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
171
- relationships[inverseKey] = relationships[inverseKey] || {};
172
- relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentIdentifier);
173
- }
174
- }
175
- }
176
- function metaIsRelationshipDefinition(meta) {
177
- return typeof meta._inverseKey === 'function';
178
- }
179
- function inverseForRelationship(store, identifier, key) {
180
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
181
- if (!definition) {
182
- return null;
183
- }
184
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE)) {
185
- if (metaIsRelationshipDefinition(definition)) {
186
- const modelClass = store.modelFor(identifier.type);
187
- return definition._inverseKey(store, modelClass);
188
- }
189
- }
190
- assert(`Expected the relationship defintion to specify the inverse type or null.`, definition.options?.inverse === null || typeof definition.options?.inverse === 'string' && definition.options.inverse.length > 0);
191
- return definition.options.inverse;
192
- }
193
- function getInverse(store, parentIdentifier, parentRelationship, type) {
194
- let {
195
- name: lhs_relationshipName
196
- } = parentRelationship;
197
- let {
198
- type: parentType
199
- } = parentIdentifier;
200
- let inverseKey = inverseForRelationship(store, {
201
- type: parentType
202
- }, lhs_relationshipName);
203
- if (inverseKey) {
204
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({
205
- type
206
- });
207
- let {
208
- kind
209
- } = definition[inverseKey];
210
- return {
211
- inverseKey,
212
- kind
213
- };
214
- }
215
- }
216
- function relationshipDataPointsToParent(relationshipData, identifier) {
217
- if (relationshipData === null) {
218
- return false;
219
- }
220
- if (Array.isArray(relationshipData)) {
221
- if (relationshipData.length === 0) {
222
- return false;
223
- }
224
- for (let i = 0; i < relationshipData.length; i++) {
225
- let entry = relationshipData[i];
226
- if (validateRelationshipEntry(entry, identifier)) {
227
- return true;
228
- }
229
- }
230
- } else {
231
- return validateRelationshipEntry(relationshipData, identifier);
232
- }
233
- return false;
234
- }
235
- function fixRelationshipData(relationshipData, relationshipKind, {
236
- id,
237
- type
238
- }) {
239
- let parentRelationshipData = {
240
- id,
241
- type
242
- };
243
- let payload;
244
- if (relationshipKind === 'hasMany') {
245
- payload = relationshipData || [];
246
- if (relationshipData) {
247
- // these arrays could be massive so this is better than filter
248
- // Note: this is potentially problematic if type/id are not in the
249
- // same state of normalization.
250
- let found = relationshipData.find(v => {
251
- return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
252
- });
253
- if (!found) {
254
- payload.push(parentRelationshipData);
255
- }
256
- } else {
257
- payload.push(parentRelationshipData);
258
- }
259
- } else {
260
- payload = relationshipData || {};
261
- Object.assign(payload, parentRelationshipData);
262
- }
263
- return payload;
264
- }
265
- function validateRelationshipEntry({
266
- id
267
- }, {
268
- id: parentModelID
269
- }) {
270
- return id && id.toString() === parentModelID;
271
- }
272
- const PotentialLegacyOperations = new Set(['findRecord', 'findAll', 'query', 'queryRecord', 'findBelongsTo', 'findHasMany', 'updateRecord', 'createRecord', 'deleteRecord']);
273
- const LegacyNetworkHandler = {
274
- request(context, next) {
275
- // if we are not a legacy request, move on
276
- if (context.request.url || !context.request.op || !PotentialLegacyOperations.has(context.request.op)) {
277
- return next(context.request);
278
- }
279
- const {
280
- store
281
- } = context.request;
282
- if (!store._fetchManager) {
283
- store._fetchManager = new FetchManager(store);
284
- }
285
- switch (context.request.op) {
286
- case 'findRecord':
287
- return findRecord(context);
288
- case 'findAll':
289
- return findAll(context);
290
- case 'query':
291
- return query(context);
292
- case 'queryRecord':
293
- return queryRecord(context);
294
- case 'findBelongsTo':
295
- return findBelongsTo(context);
296
- case 'findHasMany':
297
- return findHasMany(context);
298
- case 'updateRecord':
299
- return saveRecord(context);
300
- case 'createRecord':
301
- return saveRecord(context);
302
- case 'deleteRecord':
303
- return saveRecord(context);
304
- default:
305
- return next(context.request);
306
- }
307
- }
308
- };
309
- function findBelongsTo(context) {
310
- const {
311
- store,
312
- data,
313
- records: identifiers
314
- } = context.request;
315
- const {
316
- options,
317
- record,
318
- links,
319
- useLink,
320
- field
321
- } = data;
322
- const identifier = identifiers?.[0];
323
-
324
- // short circuit if we are already loading
325
- let pendingRequest = identifier && store._fetchManager.getPendingFetch(identifier, options);
326
- if (pendingRequest) {
327
- return pendingRequest;
328
- }
329
- if (useLink) {
330
- return _findBelongsTo(store, record, links.related, field, options);
331
- }
332
- assert(`Expected an identifier`, Array.isArray(identifiers) && identifiers.length === 1);
333
- const manager = store._fetchManager;
334
- assertIdentifierHasId(identifier);
335
- return options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
336
- }
337
- function findHasMany(context) {
338
- const {
339
- store,
340
- data,
341
- records: identifiers
342
- } = context.request;
343
- const {
344
- options,
345
- record,
346
- links,
347
- useLink,
348
- field
349
- } = data;
350
-
351
- // link case
352
- if (useLink) {
353
- const adapter = store.adapterFor(record.type);
354
- /*
355
- If a relationship was originally populated by the adapter as a link
356
- (as opposed to a list of IDs), this method is called when the
357
- relationship is fetched.
358
- The link (which is usually a URL) is passed through unchanged, so the
359
- adapter can make whatever request it wants.
360
- The usual use-case is for the server to register a URL as a link, and
361
- then use that URL in the future to make a request for the relationship.
362
- */
363
- assert(`You tried to load a hasMany relationship but you have no adapter (for ${record.type})`, adapter);
364
- assert(`You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, typeof adapter.findHasMany === 'function');
365
- return _findHasMany(adapter, store, record, links.related, field, options);
366
- }
367
-
368
- // identifiers case
369
-
370
- const fetches = new Array(identifiers.length);
371
- const manager = store._fetchManager;
372
- for (let i = 0; i < identifiers.length; i++) {
373
- let identifier = identifiers[i];
374
- // TODO we probably can be lenient here and return from cache for the isNew case
375
- assertIdentifierHasId(identifier);
376
- fetches[i] = options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
377
- }
378
- return Promise.all(fetches);
379
- }
380
- function saveRecord(context) {
381
- const {
382
- store,
383
- data,
384
- op: operation
385
- } = context.request;
386
- const {
387
- options,
388
- record: identifier
389
- } = data;
390
- const saveOptions = Object.assign({
391
- [SaveOp]: operation
392
- }, options);
393
- const fetchManagerPromise = store._fetchManager.scheduleSave(identifier, saveOptions);
394
- return fetchManagerPromise.then(payload => {
395
- if (macroCondition(getOwnConfig().debug.LOG_PAYLOADS)) {
396
- try {
397
- let data = payload ? JSON.parse(JSON.stringify(payload)) : payload;
398
- // eslint-disable-next-line no-console
399
- console.log(`EmberData | Payload - ${operation}`, data);
400
- } catch (e) {
401
- // eslint-disable-next-line no-console
402
- console.log(`EmberData | Payload - ${operation}`, payload);
403
- }
404
- }
405
- let result;
406
- /*
407
- // TODO @runspired re-evaluate the below claim now that
408
- // the save request pipeline is more streamlined.
409
- Note to future spelunkers hoping to optimize.
410
- We rely on this `run` to create a run loop if needed
411
- that `store._push` and `store.saveRecord` will both share.
412
- We use `join` because it is often the case that we
413
- have an outer run loop available still from the first
414
- call to `store._push`;
415
- */
416
- store._join(() => {
417
- //We first make sure the primary data has been updated
418
- const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? store._instanceCache.getResourceCache(identifier) : store.cache;
419
- result = cache.didCommit(identifier, {
420
- request: context.request,
421
- content: payload
422
- });
423
- if (payload && payload.included) {
424
- store._push({
425
- data: null,
426
- included: payload.included
427
- }, true);
428
- }
429
- });
430
- return store.peekRecord(result.data);
431
- }).catch(e => {
432
- let err = e;
433
- if (!e) {
434
- err = new Error(`Unknown Error Occurred During Request`);
435
- } else if (typeof e === 'string') {
436
- err = new Error(e);
437
- }
438
- adapterDidInvalidate(store, identifier, err);
439
- throw err;
440
- });
441
- }
442
- function adapterDidInvalidate(store, identifier, error) {
443
- if (error && error.isAdapterError === true && error.code === 'InvalidError') {
444
- let serializer = store.serializerFor(identifier.type);
445
-
446
- // TODO @deprecate extractErrors being called
447
- // TODO remove extractErrors from the default serializers.
448
- if (serializer && typeof serializer.extractErrors === 'function') {
449
- let errorsHash = serializer.extractErrors(store, store.modelFor(identifier.type), error, identifier.id);
450
- error.errors = errorsHashToArray(errorsHash);
451
- }
452
- }
453
- const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? store._instanceCache.getResourceCache(identifier) : store.cache;
454
- if (error.errors) {
455
- assert(`Expected the cache in use by resource ${String(identifier)} to have a getErrors(identifier) method for retreiving errors.`, typeof cache.getErrors === 'function');
456
- let jsonApiErrors = error.errors;
457
- if (jsonApiErrors.length === 0) {
458
- jsonApiErrors = [{
459
- title: 'Invalid Error',
460
- detail: '',
461
- source: {
462
- pointer: '/data'
463
- }
464
- }];
465
- }
466
- cache.commitWasRejected(identifier, jsonApiErrors);
467
- } else {
468
- cache.commitWasRejected(identifier);
469
- }
470
- }
471
- function makeArray(value) {
472
- return Array.isArray(value) ? value : [value];
473
- }
474
- const PRIMARY_ATTRIBUTE_KEY = 'base';
475
- function errorsHashToArray(errors) {
476
- const out = [];
477
- if (errors) {
478
- Object.keys(errors).forEach(key => {
479
- let messages = makeArray(errors[key]);
480
- for (let i = 0; i < messages.length; i++) {
481
- let title = 'Invalid Attribute';
482
- let pointer = `/data/attributes/${key}`;
483
- if (key === PRIMARY_ATTRIBUTE_KEY) {
484
- title = 'Invalid Document';
485
- pointer = `/data`;
486
- }
487
- out.push({
488
- title: title,
489
- detail: messages[i],
490
- source: {
491
- pointer: pointer
492
- }
493
- });
494
- }
495
- });
496
- }
497
- return out;
498
- }
499
- function findRecord(context) {
500
- const {
501
- store,
502
- data
503
- } = context.request;
504
- const {
505
- record: identifier,
506
- options
507
- } = data;
508
- let promise;
509
-
510
- // if not loaded start loading
511
- if (!store._instanceCache.recordIsLoaded(identifier)) {
512
- promise = store._fetchManager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
513
-
514
- // Refetch if the reload option is passed
515
- } else if (options.reload) {
516
- assertIdentifierHasId(identifier);
517
- promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
518
- } else {
519
- let snapshot = null;
520
- let adapter = store.adapterFor(identifier.type);
521
-
522
- // Refetch the record if the adapter thinks the record is stale
523
- if (typeof options.reload === 'undefined' && adapter.shouldReloadRecord && adapter.shouldReloadRecord(store, snapshot = store._fetchManager.createSnapshot(identifier, options))) {
524
- assertIdentifierHasId(identifier);
525
- if (macroCondition(getOwnConfig().env.DEBUG)) {
526
- promise = store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
527
- reload: true
528
- }), context.request);
529
- } else {
530
- options.reload = true;
531
- promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
532
- }
533
- } else {
534
- // Trigger the background refetch if backgroundReload option is passed
535
- if (options.backgroundReload !== false && (options.backgroundReload || !adapter.shouldBackgroundReloadRecord || adapter.shouldBackgroundReloadRecord(store, snapshot = snapshot || store._fetchManager.createSnapshot(identifier, options)))) {
536
- assertIdentifierHasId(identifier);
537
- if (macroCondition(getOwnConfig().env.DEBUG)) {
538
- void store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
539
- backgroundReload: true
540
- }), context.request);
541
- } else {
542
- options.backgroundReload = true;
543
- void store._fetchManager.scheduleFetch(identifier, options, context.request);
544
- }
545
- }
546
-
547
- // Return the cached record
548
- promise = Promise.resolve(identifier);
549
- }
550
- }
551
- return promise.then(identifier => store.peekRecord(identifier));
552
- }
553
- function findAll(context) {
554
- const {
555
- store,
556
- data
557
- } = context.request;
558
- const {
559
- type,
560
- options
561
- } = data;
562
- const adapter = store.adapterFor(type);
563
- assert(`You tried to load all records but you have no adapter (for ${type})`, adapter);
564
- assert(`You tried to load all records but your adapter does not implement 'findAll'`, typeof adapter.findAll === 'function');
565
-
566
- // avoid initializing the liveArray just to set `isUpdating`
567
- const maybeRecordArray = store.recordArrayManager._live.get(type);
568
- const snapshotArray = new SnapshotRecordArray(store, type, options);
569
- const shouldReload = options.reload || options.reload !== false && (adapter.shouldReloadAll && adapter.shouldReloadAll(store, snapshotArray) || !adapter.shouldReloadAll && snapshotArray.length === 0);
570
- let fetch;
571
- if (shouldReload) {
572
- maybeRecordArray && (maybeRecordArray.isUpdating = true);
573
- fetch = _findAll(adapter, store, type, snapshotArray, context.request, true);
574
- } else {
575
- fetch = Promise.resolve(store.peekAll(type));
576
- if (options.backgroundReload || options.backgroundReload !== false && (!adapter.shouldBackgroundReloadAll || adapter.shouldBackgroundReloadAll(store, snapshotArray))) {
577
- maybeRecordArray && (maybeRecordArray.isUpdating = true);
578
- void _findAll(adapter, store, type, snapshotArray, context.request, false);
579
- }
580
- }
581
- return fetch;
582
- }
583
- function _findAll(adapter, store, type, snapshotArray, request, isAsyncFlush) {
584
- const schema = store.modelFor(type);
585
- let promise = Promise.resolve().then(() => adapter.findAll(store, schema, null, snapshotArray));
586
- promise = guardDestroyedStore(promise, store);
587
- promise = promise.then(adapterPayload => {
588
- assert(`You made a 'findAll' request for '${type}' records, but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
589
- const serializer = store.serializerFor(type);
590
- const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'findAll');
591
- store._push(payload, isAsyncFlush);
592
- snapshotArray._recordArray.isUpdating = false;
593
- if (macroCondition(getOwnConfig().debug.LOG_PAYLOADS)) {
594
- // eslint-disable-next-line no-console
595
- console.log(`request: findAll<${type}> background reload complete`);
596
- }
597
- return snapshotArray._recordArray;
598
- });
599
- if (macroCondition(getOwnConfig().env.TESTING)) {
600
- if (!request.disableTestWaiter) {
601
- const {
602
- waitForPromise
603
- } = importSync('@ember/test-waiters');
604
- promise = waitForPromise(promise);
605
- }
606
- }
607
- return promise;
608
- }
609
- function query(context) {
610
- const {
611
- store,
612
- data
613
- } = context.request;
614
- let {
615
- options
616
- } = data;
617
- const {
618
- type,
619
- query
620
- } = data;
621
- const adapter = store.adapterFor(type);
622
- assert(`You tried to make a query but you have no adapter (for ${type})`, adapter);
623
- assert(`You tried to make a query but your adapter does not implement 'query'`, typeof adapter.query === 'function');
624
- const recordArray = options._recordArray || store.recordArrayManager.createArray({
625
- type,
626
- query
627
- });
628
- if (macroCondition(getOwnConfig().env.DEBUG)) {
629
- options = Object.assign({}, options);
630
- delete options._recordArray;
631
- } else {
632
- delete options._recordArray;
633
- }
634
- const schema = store.modelFor(type);
635
- let promise = Promise.resolve().then(() => adapter.query(store, schema, query, recordArray, options));
636
- promise = guardDestroyedStore(promise, store);
637
- return promise.then(adapterPayload => {
638
- const serializer = store.serializerFor(type);
639
- const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'query');
640
- const identifiers = store._push(payload, true);
641
- assert('The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', Array.isArray(identifiers));
642
- store.recordArrayManager.populateManagedArray(recordArray, identifiers, payload);
643
- return recordArray;
644
- });
645
- }
646
- function assertSingleResourceDocument(payload) {
647
- assert(`Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`, !Array.isArray(payload.data));
648
- }
649
- function queryRecord(context) {
650
- const {
651
- store,
652
- data
653
- } = context.request;
654
- const {
655
- type,
656
- query,
657
- options
658
- } = data;
659
- const adapter = store.adapterFor(type);
660
- assert(`You tried to make a query but you have no adapter (for ${type})`, adapter);
661
- assert(`You tried to make a query but your adapter does not implement 'queryRecord'`, typeof adapter.queryRecord === 'function');
662
- const schema = store.modelFor(type);
663
- let promise = Promise.resolve().then(() => adapter.queryRecord(store, schema, query, options));
664
- promise = guardDestroyedStore(promise, store);
665
- return promise.then(adapterPayload => {
666
- const serializer = store.serializerFor(type);
667
- const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'queryRecord');
668
- assertSingleResourceDocument(payload);
669
- const identifier = store._push(payload, true);
670
- return identifier ? store.peekRecord(identifier) : null;
671
- });
672
- }
673
- export { LegacyNetworkHandler };