@warp-drive/legacy 5.8.0-alpha.4 → 5.8.0-alpha.40

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 (213) hide show
  1. package/README.md +14 -27
  2. package/declarations/adapter/error.d.ts +5 -5
  3. package/declarations/adapter/json-api.d.ts +6 -8
  4. package/declarations/adapter/rest.d.ts +5 -8
  5. package/declarations/adapter.d.ts +4 -6
  6. package/declarations/compat/-private.d.ts +1 -1
  7. package/declarations/compat/builders/find-all.d.ts +6 -6
  8. package/declarations/compat/builders/find-record.d.ts +8 -8
  9. package/declarations/compat/builders/query.d.ts +12 -12
  10. package/declarations/compat/extensions.d.ts +1 -1
  11. package/declarations/compat/legacy-network-handler/minimum-adapter-interface.d.ts +7 -9
  12. package/declarations/compat/legacy-network-handler/minimum-serializer-interface.d.ts +20 -30
  13. package/declarations/compat/utils.d.ts +17 -17
  14. package/declarations/compat.d.ts +35 -11
  15. package/declarations/index.d.ts +70 -0
  16. package/declarations/model/-private/attr.d.ts +5 -6
  17. package/declarations/model/-private/belongs-to.d.ts +4 -5
  18. package/declarations/model/-private/has-many.d.ts +4 -5
  19. package/declarations/model/-private/hooks.d.ts +1 -1
  20. package/declarations/model/-private/legacy-relationships-support.d.ts +2 -2
  21. package/declarations/model/-private/model.d.ts +8 -8
  22. package/declarations/model/-private/record-state.d.ts +1 -1
  23. package/declarations/model/-private/references/belongs-to.d.ts +5 -5
  24. package/declarations/model/-private/references/has-many.d.ts +3 -3
  25. package/declarations/model/migration-support.d.ts +46 -21
  26. package/declarations/model-fragments/extensions/fragment-array.d.ts +16 -0
  27. package/declarations/model-fragments/extensions/fragment.d.ts +15 -0
  28. package/declarations/model-fragments/hooks/model-for.d.ts +20 -0
  29. package/declarations/model-fragments/index.d.ts +5 -0
  30. package/declarations/model-fragments/instance-initializers/fragment-extensions.d.ts +9 -0
  31. package/declarations/model-fragments/utilities/with-array-defaults.d.ts +15 -0
  32. package/declarations/model-fragments/utilities/with-fragment-array-defaults.d.ts +20 -0
  33. package/declarations/model-fragments/utilities/with-fragment-defaults.d.ts +19 -0
  34. package/declarations/model-fragments/utilities/with-legacy.d.ts +3 -0
  35. package/declarations/model-fragments.d.ts +9 -0
  36. package/declarations/model.d.ts +2 -2
  37. package/declarations/serializer/-private/embedded-records-mixin.d.ts +1 -6
  38. package/declarations/serializer/-private/transforms/boolean.d.ts +2 -2
  39. package/declarations/serializer/-private/transforms/date.d.ts +2 -2
  40. package/declarations/serializer/-private/transforms/number.d.ts +1 -1
  41. package/declarations/serializer/-private/transforms/string.d.ts +1 -1
  42. package/declarations/serializer/json-api.d.ts +7 -9
  43. package/declarations/serializer/json.d.ts +7 -9
  44. package/declarations/serializer/rest.d.ts +4 -6
  45. package/declarations/serializer.d.ts +9 -12
  46. package/dist/{-private-8UmnAf9J.js → -private-B1pSSN52.js} +1 -1
  47. package/dist/adapter/-private.js +1 -1
  48. package/dist/adapter/error.js +12 -13
  49. package/dist/adapter/json-api.js +4 -1
  50. package/dist/adapter/rest.js +6 -9
  51. package/dist/adapter.js +4 -6
  52. package/dist/compat/-private.js +1 -1
  53. package/dist/compat/builders.js +26 -26
  54. package/dist/compat/utils.js +17 -18
  55. package/dist/compat.js +58 -41
  56. package/dist/{errors-8kD2mSe_.js → errors-CIGPcDvd.js} +87 -65
  57. package/dist/hooks-QqRnX108.js +74 -0
  58. package/dist/index.js +195 -0
  59. package/dist/{json-DziiodPf.js → json-BNrV8EYG.js} +12 -16
  60. package/dist/model/-private.js +1 -1
  61. package/dist/model/migration-support.js +54 -24
  62. package/dist/model-for-CqXsIKws.js +221 -0
  63. package/dist/model-fragments.js +76 -0
  64. package/dist/model.js +18 -90
  65. package/dist/{schema-provider-DQu4Rjco.js → schema-provider-g5MfTj8n.js} +18 -20
  66. package/dist/{serialize-into-hash-CS0MIv4F.js → serialize-into-hash-BnYvPex3.js} +1 -1
  67. package/dist/serializer/json-api.js +17 -44
  68. package/dist/serializer/json.js +1 -1
  69. package/dist/serializer/rest.js +14 -21
  70. package/dist/serializer/transform.js +15 -6
  71. package/dist/serializer.js +9 -13
  72. package/dist/store.js +3 -0
  73. package/dist/unpkg/dev/-private-DbaSCSym.js +1205 -0
  74. package/dist/unpkg/dev/adapter/-private.js +1 -0
  75. package/dist/unpkg/dev/adapter/error.js +335 -0
  76. package/dist/unpkg/dev/adapter/json-api.js +271 -0
  77. package/dist/unpkg/dev/adapter/rest.js +1255 -0
  78. package/dist/unpkg/dev/adapter.js +1252 -0
  79. package/dist/unpkg/dev/compat/-private.js +1 -0
  80. package/dist/unpkg/dev/compat/builders.js +275 -0
  81. package/dist/unpkg/dev/compat/extensions.js +242 -0
  82. package/dist/unpkg/dev/compat/utils.js +223 -0
  83. package/dist/unpkg/dev/compat.js +1146 -0
  84. package/dist/unpkg/dev/errors-DD96TBEs.js +2591 -0
  85. package/dist/unpkg/dev/hooks-CqWjNWeL.js +73 -0
  86. package/dist/unpkg/dev/index.js +197 -0
  87. package/dist/unpkg/dev/json-CCU-ZQ4b.js +1269 -0
  88. package/dist/unpkg/dev/model/-private.js +1 -0
  89. package/dist/unpkg/dev/model/migration-support.js +551 -0
  90. package/dist/unpkg/dev/model-for-CqXsIKws.js +221 -0
  91. package/dist/unpkg/dev/model-fragments.js +76 -0
  92. package/dist/unpkg/dev/model.js +678 -0
  93. package/dist/unpkg/dev/runtime-BPCpkOf1-BKOwiRJp.js +65 -0
  94. package/dist/unpkg/dev/schema-provider-B8jiJOYC.js +2229 -0
  95. package/dist/unpkg/dev/serialize-into-hash-CPAZXrQU.js +259 -0
  96. package/dist/unpkg/dev/serializer/json-api.js +648 -0
  97. package/dist/unpkg/dev/serializer/json.js +4 -0
  98. package/dist/unpkg/dev/serializer/rest.js +1242 -0
  99. package/dist/unpkg/dev/serializer/transform.js +278 -0
  100. package/dist/unpkg/dev/serializer.js +248 -0
  101. package/dist/unpkg/dev/store.js +636 -0
  102. package/dist/unpkg/dev/util-DvanW33H.js +20 -0
  103. package/dist/unpkg/dev/utils-BhvS1iTS.js +8 -0
  104. package/dist/unpkg/dev-deprecated/-private-DbaSCSym.js +1205 -0
  105. package/dist/unpkg/dev-deprecated/adapter/-private.js +1 -0
  106. package/dist/unpkg/dev-deprecated/adapter/error.js +335 -0
  107. package/dist/unpkg/dev-deprecated/adapter/json-api.js +271 -0
  108. package/dist/unpkg/dev-deprecated/adapter/rest.js +1255 -0
  109. package/dist/unpkg/dev-deprecated/adapter.js +1252 -0
  110. package/dist/unpkg/dev-deprecated/compat/-private.js +1 -0
  111. package/dist/unpkg/dev-deprecated/compat/builders.js +275 -0
  112. package/dist/unpkg/dev-deprecated/compat/extensions.js +242 -0
  113. package/dist/unpkg/dev-deprecated/compat/utils.js +223 -0
  114. package/dist/unpkg/dev-deprecated/compat.js +1146 -0
  115. package/dist/unpkg/dev-deprecated/errors-DEnabIZj.js +2594 -0
  116. package/dist/unpkg/dev-deprecated/hooks-CAll-Ets.js +73 -0
  117. package/dist/unpkg/dev-deprecated/index.js +196 -0
  118. package/dist/unpkg/dev-deprecated/json-CCU-ZQ4b.js +1269 -0
  119. package/dist/unpkg/dev-deprecated/model/-private.js +1 -0
  120. package/dist/unpkg/dev-deprecated/model/migration-support.js +568 -0
  121. package/dist/unpkg/dev-deprecated/model-for-CqXsIKws.js +221 -0
  122. package/dist/unpkg/dev-deprecated/model-fragments.js +76 -0
  123. package/dist/unpkg/dev-deprecated/model.js +682 -0
  124. package/dist/unpkg/dev-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +65 -0
  125. package/dist/unpkg/dev-deprecated/schema-provider-k2qXQTBg.js +2254 -0
  126. package/dist/unpkg/dev-deprecated/serialize-into-hash-CPAZXrQU.js +259 -0
  127. package/dist/unpkg/dev-deprecated/serializer/json-api.js +648 -0
  128. package/dist/unpkg/dev-deprecated/serializer/json.js +4 -0
  129. package/dist/unpkg/dev-deprecated/serializer/rest.js +1242 -0
  130. package/dist/unpkg/dev-deprecated/serializer/transform.js +278 -0
  131. package/dist/unpkg/dev-deprecated/serializer.js +248 -0
  132. package/dist/unpkg/dev-deprecated/store.js +636 -0
  133. package/dist/unpkg/dev-deprecated/util-CWr5WQOT.js +24 -0
  134. package/dist/unpkg/dev-deprecated/utils-C9PJehtL.js +12 -0
  135. package/dist/unpkg/prod/-private-Cvf_97EG.js +970 -0
  136. package/dist/unpkg/prod/adapter/-private.js +1 -0
  137. package/dist/unpkg/prod/adapter/error.js +330 -0
  138. package/dist/unpkg/prod/adapter/json-api.js +266 -0
  139. package/dist/unpkg/prod/adapter/rest.js +1218 -0
  140. package/dist/unpkg/prod/adapter.js +1219 -0
  141. package/dist/unpkg/prod/compat/-private.js +1 -0
  142. package/dist/unpkg/prod/compat/builders.js +210 -0
  143. package/dist/unpkg/prod/compat/extensions.js +232 -0
  144. package/dist/unpkg/prod/compat/utils.js +218 -0
  145. package/dist/unpkg/prod/compat.js +726 -0
  146. package/dist/unpkg/prod/errors-CXnfnBfQ.js +2343 -0
  147. package/dist/unpkg/prod/hooks-DvyWhLNg.js +41 -0
  148. package/dist/unpkg/prod/index.js +151 -0
  149. package/dist/unpkg/prod/json-BYrUP8ao.js +1256 -0
  150. package/dist/unpkg/prod/model/-private.js +1 -0
  151. package/dist/unpkg/prod/model/migration-support.js +544 -0
  152. package/dist/unpkg/prod/model-for-CqXsIKws.js +221 -0
  153. package/dist/unpkg/prod/model-fragments.js +76 -0
  154. package/dist/unpkg/prod/model.js +593 -0
  155. package/dist/unpkg/prod/runtime-BPCpkOf1-BKOwiRJp.js +65 -0
  156. package/dist/unpkg/prod/schema-provider-CHujJvA9.js +1904 -0
  157. package/dist/unpkg/prod/serialize-into-hash-DYU2egXl.js +215 -0
  158. package/dist/unpkg/prod/serializer/json-api.js +591 -0
  159. package/dist/unpkg/prod/serializer/json.js +4 -0
  160. package/dist/unpkg/prod/serializer/rest.js +1210 -0
  161. package/dist/unpkg/prod/serializer/transform.js +278 -0
  162. package/dist/unpkg/prod/serializer.js +248 -0
  163. package/dist/unpkg/prod/store.js +504 -0
  164. package/dist/unpkg/prod/util-DvanW33H.js +20 -0
  165. package/dist/unpkg/prod/utils-BhvS1iTS.js +8 -0
  166. package/dist/unpkg/prod-deprecated/-private-Cvf_97EG.js +970 -0
  167. package/dist/unpkg/prod-deprecated/adapter/-private.js +1 -0
  168. package/dist/unpkg/prod-deprecated/adapter/error.js +330 -0
  169. package/dist/unpkg/prod-deprecated/adapter/json-api.js +266 -0
  170. package/dist/unpkg/prod-deprecated/adapter/rest.js +1218 -0
  171. package/dist/unpkg/prod-deprecated/adapter.js +1219 -0
  172. package/dist/unpkg/prod-deprecated/compat/-private.js +1 -0
  173. package/dist/unpkg/prod-deprecated/compat/builders.js +210 -0
  174. package/dist/unpkg/prod-deprecated/compat/extensions.js +232 -0
  175. package/dist/unpkg/prod-deprecated/compat/utils.js +218 -0
  176. package/dist/unpkg/prod-deprecated/compat.js +726 -0
  177. package/dist/unpkg/prod-deprecated/errors-CG1SPYVg.js +2346 -0
  178. package/dist/unpkg/prod-deprecated/hooks-BIUBiNGR.js +41 -0
  179. package/dist/unpkg/prod-deprecated/index.js +150 -0
  180. package/dist/unpkg/prod-deprecated/json-BYrUP8ao.js +1256 -0
  181. package/dist/unpkg/prod-deprecated/model/-private.js +1 -0
  182. package/dist/unpkg/prod-deprecated/model/migration-support.js +561 -0
  183. package/dist/unpkg/prod-deprecated/model-for-CqXsIKws.js +221 -0
  184. package/dist/unpkg/prod-deprecated/model-fragments.js +76 -0
  185. package/dist/unpkg/prod-deprecated/model.js +596 -0
  186. package/dist/unpkg/prod-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +65 -0
  187. package/dist/unpkg/prod-deprecated/schema-provider-BJ4TWnZf.js +1947 -0
  188. package/dist/unpkg/prod-deprecated/serialize-into-hash-DYU2egXl.js +215 -0
  189. package/dist/unpkg/prod-deprecated/serializer/json-api.js +591 -0
  190. package/dist/unpkg/prod-deprecated/serializer/json.js +4 -0
  191. package/dist/unpkg/prod-deprecated/serializer/rest.js +1210 -0
  192. package/dist/unpkg/prod-deprecated/serializer/transform.js +278 -0
  193. package/dist/unpkg/prod-deprecated/serializer.js +248 -0
  194. package/dist/unpkg/prod-deprecated/store.js +504 -0
  195. package/dist/unpkg/prod-deprecated/util-B6cn-i93.js +23 -0
  196. package/dist/unpkg/prod-deprecated/utils-BUWwQwCh.js +11 -0
  197. package/logos/README.md +2 -2
  198. package/logos/logo-yellow-slab.svg +1 -0
  199. package/logos/word-mark-black.svg +1 -0
  200. package/logos/word-mark-white.svg +1 -0
  201. package/package.json +14 -6
  202. package/logos/NCC-1701-a-blue.svg +0 -4
  203. package/logos/NCC-1701-a-gold.svg +0 -4
  204. package/logos/NCC-1701-a-gold_100.svg +0 -1
  205. package/logos/NCC-1701-a-gold_base-64.txt +0 -1
  206. package/logos/NCC-1701-a.svg +0 -4
  207. package/logos/docs-badge.svg +0 -2
  208. package/logos/ember-data-logo-dark.svg +0 -12
  209. package/logos/ember-data-logo-light.svg +0 -12
  210. package/logos/social1.png +0 -0
  211. package/logos/social2.png +0 -0
  212. package/logos/warp-drive-logo-dark.svg +0 -4
  213. package/logos/warp-drive-logo-gold.svg +0 -4
@@ -0,0 +1,970 @@
1
+ import { Context } from '@warp-drive/core/reactive/-private';
2
+ import { createDeferred } from '@warp-drive/core/request';
3
+ import { assertPrivateStore } from '@warp-drive/core/store/-private';
4
+ import { getOrSetGlobal } from '@warp-drive/core/types/-private';
5
+
6
+ /**
7
+ SnapshotRecordArray is not directly instantiable.
8
+ Instances are provided to consuming application's
9
+ adapters for certain `findAll` requests.
10
+
11
+ @hideconstructor
12
+ @public
13
+ */
14
+ class SnapshotRecordArray {
15
+ /**
16
+ * An array of snapshots
17
+ *
18
+ * @internal
19
+ */
20
+
21
+ /** @internal */
22
+
23
+ /**
24
+ * The ResourceType of the underlying records for the {@link Snapshot | Snapshots} in the array
25
+ */
26
+
27
+ /** @internal */
28
+
29
+ /**
30
+ * A hash of adapter options passed into the store method for this request.
31
+ Example
32
+ ```js [app/adapters/post.js]
33
+ import MyCustomAdapter from './custom-adapter';
34
+ export default class PostAdapter extends MyCustomAdapter {
35
+ findAll(store, type, sinceToken, snapshotRecordArray) {
36
+ if (snapshotRecordArray.adapterOptions.subscribe) {
37
+ // ...
38
+ }
39
+ // ...
40
+ }
41
+ }
42
+ ```
43
+ */
44
+
45
+ /**
46
+ * The relationships to include for this request.
47
+ Example
48
+ ```js [app/adapters/application.js]
49
+ import Adapter from '@ember-data/adapter';
50
+ export default class ApplicationAdapter extends Adapter {
51
+ findAll(store, type, snapshotRecordArray) {
52
+ let url = `/${type.modelName}?include=${encodeURIComponent(snapshotRecordArray.include)}`;
53
+ return fetch(url).then((response) => response.json())
54
+ }
55
+ }
56
+ ```
57
+ */
58
+
59
+ /**
60
+ SnapshotRecordArray is not directly instantiable.
61
+ Instances are provided to consuming application's
62
+ adapters and serializers for certain requests.
63
+ @private
64
+ @constructor
65
+ @param {Store} store
66
+ @param {String} type
67
+ @param options
68
+ */
69
+ constructor(store, type, options = {}) {
70
+ this.__store = store;
71
+ this._snapshots = null;
72
+ this.modelName = type;
73
+ this.adapterOptions = options.adapterOptions;
74
+ this.include = options.include;
75
+ }
76
+
77
+ /**
78
+ An array of records
79
+ @internal
80
+ */
81
+ get _recordArray() {
82
+ return this.__store.peekAll(this.modelName);
83
+ }
84
+
85
+ /**
86
+ Number of records in the array
87
+ Example
88
+ ```js [app/adapters/post.js]
89
+ import JSONAPIAdapter from '@ember-data/adapter/json-api';
90
+ export default class PostAdapter extends JSONAPIAdapter {
91
+ shouldReloadAll(store, snapshotRecordArray) {
92
+ return !snapshotRecordArray.length;
93
+ }
94
+ });
95
+ ```
96
+ */
97
+ get length() {
98
+ return this._recordArray.length;
99
+ }
100
+
101
+ /**
102
+ Get snapshots of the underlying record array
103
+ Example
104
+ ```js [app/adapters/post.js]
105
+ import JSONAPIAdapter from '@ember-data/adapter/json-api';
106
+ export default class PostAdapter extends JSONAPIAdapter {
107
+ shouldReloadAll(store, snapshotArray) {
108
+ let snapshots = snapshotArray.snapshots();
109
+ return snapshots.any(function(ticketSnapshot) {
110
+ let timeDiff = moment().diff(ticketSnapshot.attr('lastAccessedAt'), 'minutes');
111
+ if (timeDiff > 20) {
112
+ return true;
113
+ } else {
114
+ return false;
115
+ }
116
+ });
117
+ }
118
+ }
119
+ ```
120
+ @public
121
+ @return Array of snapshots
122
+ */
123
+ snapshots() {
124
+ if (this._snapshots !== null) {
125
+ return this._snapshots;
126
+ }
127
+ upgradeStore(this.__store);
128
+ const {
129
+ _fetchManager
130
+ } = this.__store;
131
+ const LiveArrayContext = this._recordArray[Context];
132
+ this._snapshots = LiveArrayContext.source.map(identifier => _fetchManager.createSnapshot(identifier));
133
+ return this._snapshots;
134
+ }
135
+ }
136
+
137
+ /**
138
+ This is a helper method that validates a JSON API top-level document
139
+
140
+ The format of a document is described here:
141
+ http://jsonapi.org/format/#document-top-level
142
+
143
+ @internal
144
+ */
145
+ function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) {
146
+ const normalizedResponse = serializer ? serializer.normalizeResponse(store, modelClass, payload, id, requestType) : payload;
147
+ return normalizedResponse;
148
+ }
149
+
150
+ /**
151
+ Snapshot is not directly instantiable.
152
+ Instances are provided to a consuming application's
153
+ adapters and serializers for certain requests.
154
+
155
+ Snapshots are only available when using `@ember-data/legacy-compat`
156
+ for legacy compatibility with adapters and serializers.
157
+
158
+ For serialization of records in modern paradigms, request data from
159
+ the cache or off the record directly.
160
+
161
+ @hideconstructor
162
+ @public
163
+ */
164
+ class Snapshot {
165
+ /** @internal */
166
+
167
+ /** @internal */
168
+
169
+ /** @internal */
170
+
171
+ /** @internal */
172
+
173
+ /** @internal */
174
+
175
+ /** @internal */
176
+
177
+ /** @internal */
178
+
179
+ /**
180
+ The unique ResourceKey associated with this Snapshot.
181
+ @public
182
+ */
183
+
184
+ /**
185
+ The ResourceType of the underlying record for this Snapshot, as a string.
186
+ @public
187
+ */
188
+
189
+ /**
190
+ The id of the snapshot's underlying record
191
+ Example
192
+ ```js
193
+ // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
194
+ postSnapshot.id; // => '1'
195
+ ```
196
+ @public
197
+ */
198
+
199
+ /**
200
+ If `include` was passed to the options for the request, the value
201
+ would be available here.
202
+ @public
203
+ */
204
+
205
+ /**
206
+ The adapterOptions passed to the request which generated this Snapshot, if any
207
+ @public
208
+ */
209
+
210
+ constructor(options, identifier, store) {
211
+ this._store = store;
212
+ this.__attributes = null;
213
+ this._belongsToRelationships = Object.create(null);
214
+ this._belongsToIds = Object.create(null);
215
+ this._hasManyRelationships = Object.create(null);
216
+ this._hasManyIds = Object.create(null);
217
+ assertPrivateStore(store);
218
+ const hasRecord = !!store._instanceCache.peek(identifier);
219
+ this.modelName = identifier.type;
220
+ this.identifier = identifier;
221
+
222
+ /*
223
+ If the we do not yet have a record, then we are
224
+ likely a snapshot being provided to a find request, so we
225
+ populate __attributes lazily. Else, to preserve the "moment
226
+ in time" in which a snapshot is created, we greedily grab
227
+ the values.
228
+ */
229
+ if (hasRecord) {
230
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
231
+ this._attributes;
232
+ }
233
+ this.id = identifier.id;
234
+ this.adapterOptions = options.adapterOptions;
235
+ this.include = options.include;
236
+ this.modelName = identifier.type;
237
+ if (hasRecord) {
238
+ const cache = this._store.cache;
239
+ this._changedAttributes = cache.changedAttrs(identifier);
240
+ }
241
+ }
242
+
243
+ /**
244
+ The underlying record for this snapshot. Can be used to access methods and
245
+ properties defined on the record.
246
+ ```js
247
+ const someValue = snapshot.record.someProp;
248
+ ```
249
+ @property record
250
+ @public
251
+ */
252
+ get record() {
253
+ const record = this._store.peekRecord(this.identifier);
254
+ return record;
255
+ }
256
+
257
+ /** @internal */
258
+ get _attributes() {
259
+ if (this.__attributes !== null) {
260
+ return this.__attributes;
261
+ }
262
+ const attributes = this.__attributes = Object.create(null);
263
+ const {
264
+ identifier
265
+ } = this;
266
+ const cache = this._store.cache;
267
+ this.eachAttribute((key, meta) => {
268
+ attributes[key] = cache.getAttr(identifier, key);
269
+ });
270
+ return attributes;
271
+ }
272
+ get isNew() {
273
+ const cache = this._store.cache;
274
+ return cache?.isNew(this.identifier) || false;
275
+ }
276
+
277
+ /**
278
+ Returns the value of an attribute.
279
+ Example
280
+ ```javascript
281
+ // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
282
+ postSnapshot.attr('author'); // => 'Tomster'
283
+ postSnapshot.attr('title'); // => 'Ember.js rocks'
284
+ ```
285
+ Note: Values are loaded eagerly and cached when the snapshot is created.
286
+ @return The attribute value or undefined
287
+ @public
288
+ */
289
+ attr(keyName) {
290
+ if (keyName in this._attributes) {
291
+ return this._attributes[keyName];
292
+ }
293
+ }
294
+
295
+ /**
296
+ Returns all attributes and their corresponding values.
297
+ ::: warning ⚠️ WARNING
298
+ Attributes are SHALLOW copied from the cache.
299
+ Because they are NOT deep copied from the cache, mutating
300
+ any object or array fields will cause unintended side-effects
301
+ and bugs.
302
+ :::
303
+ Example
304
+ ```js
305
+ // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
306
+ postSnapshot.attributes(); // => { author: 'Tomster', title: 'Ember.js rocks' }
307
+ ```
308
+ @return All attributes of the current snapshot
309
+ @public
310
+ */
311
+ attributes() {
312
+ return {
313
+ ...this._attributes
314
+ };
315
+ }
316
+
317
+ /**
318
+ Returns all changed attributes and their old and new values.
319
+ Example
320
+ ```js
321
+ // store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
322
+ postModel.set('title', 'Ember.js rocks!');
323
+ postSnapshot.changedAttributes(); // => { title: ['Ember.js rocks', 'Ember.js rocks!'] }
324
+ ```
325
+ @return All changed attributes of the current snapshot
326
+ @public
327
+ */
328
+ changedAttributes() {
329
+ const changedAttributes = Object.create(null);
330
+ if (!this._changedAttributes) {
331
+ return changedAttributes;
332
+ }
333
+ const changedAttributeKeys = Object.keys(this._changedAttributes);
334
+ for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
335
+ const key = changedAttributeKeys[i];
336
+ changedAttributes[key] = this._changedAttributes[key].slice();
337
+ }
338
+ return changedAttributes;
339
+ }
340
+
341
+ /**
342
+ Returns the current value of a belongsTo relationship.
343
+ `belongsTo` takes an optional hash of options as a second parameter,
344
+ currently supported options are:
345
+ - `id`: set to `true` if you only want the ID of the related record to be
346
+ returned.
347
+ Example
348
+ ```js
349
+ // store.push('post', { id: 1, title: 'Hello World' });
350
+ // store.createRecord('comment', { body: 'Lorem ipsum', post: post });
351
+ commentSnapshot.belongsTo('post'); // => Snapshot
352
+ commentSnapshot.belongsTo('post', { id: true }); // => '1'
353
+ // store.push('comment', { id: 1, body: 'Lorem ipsum' });
354
+ commentSnapshot.belongsTo('post'); // => undefined
355
+ ```
356
+ Calling `belongsTo` will return a new Snapshot as long as there's any known
357
+ data for the relationship available, such as an ID. If the relationship is
358
+ known but unset, `belongsTo` will return `null`. If the contents of the
359
+ relationship is unknown `belongsTo` will return `undefined`.
360
+ Note: Relationships are loaded lazily and cached upon first access.
361
+ @public
362
+ @return A snapshot or ID of a known relationship or null if the
363
+ relationship is known but unset. undefined will be returned if the
364
+ contents of the relationship are unknown.
365
+ */
366
+ belongsTo(keyName, options) {
367
+ const returnModeIsId = !!(options && options.id);
368
+ let result;
369
+ const store = this._store;
370
+ if (returnModeIsId === true && keyName in this._belongsToIds) {
371
+ return this._belongsToIds[keyName];
372
+ }
373
+ if (returnModeIsId === false && keyName in this._belongsToRelationships) {
374
+ return this._belongsToRelationships[keyName];
375
+ }
376
+ store.schema.fields({
377
+ type: this.modelName
378
+ }).get(keyName);
379
+ const {
380
+ identifier
381
+ } = this;
382
+ const value = this._store.cache.getRelationship(identifier, keyName);
383
+ const data = value && value.data;
384
+ const inverseIdentifier = data ? store.cacheKeyManager.getOrCreateRecordIdentifier(data) : null;
385
+ if (value && value.data !== undefined) {
386
+ const cache = store.cache;
387
+ if (inverseIdentifier && !cache.isDeleted(inverseIdentifier)) {
388
+ if (returnModeIsId) {
389
+ result = inverseIdentifier.id;
390
+ } else {
391
+ result = store._fetchManager.createSnapshot(inverseIdentifier);
392
+ }
393
+ } else {
394
+ result = null;
395
+ }
396
+ }
397
+ if (returnModeIsId) {
398
+ this._belongsToIds[keyName] = result;
399
+ } else {
400
+ this._belongsToRelationships[keyName] = result;
401
+ }
402
+ return result;
403
+ }
404
+
405
+ /**
406
+ Returns the current value of a hasMany relationship.
407
+ `hasMany` takes an optional hash of options as a second parameter,
408
+ currently supported options are:
409
+ - `ids`: set to `true` if you only want the IDs of the related records to be
410
+ returned.
411
+ Example
412
+ ```javascript
413
+ // store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] });
414
+ postSnapshot.hasMany('comments'); // => [Snapshot, Snapshot]
415
+ postSnapshot.hasMany('comments', { ids: true }); // => ['2', '3']
416
+ // store.push('post', { id: 1, title: 'Hello World' });
417
+ postSnapshot.hasMany('comments'); // => undefined
418
+ ```
419
+ Note: Relationships are loaded lazily and cached upon first access.
420
+ @public
421
+ @return An array of snapshots or IDs of a known
422
+ relationship or an empty array if the relationship is known but unset.
423
+ undefined will be returned if the contents of the relationship is unknown.
424
+ */
425
+ hasMany(keyName, options) {
426
+ const returnModeIsIds = !!(options && options.ids);
427
+ let results;
428
+ const cachedIds = this._hasManyIds[keyName];
429
+ const cachedSnapshots = this._hasManyRelationships[keyName];
430
+ if (returnModeIsIds === true && keyName in this._hasManyIds) {
431
+ return cachedIds;
432
+ }
433
+ if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
434
+ return cachedSnapshots;
435
+ }
436
+ const store = this._store;
437
+ store.schema.fields({
438
+ type: this.modelName
439
+ }).get(keyName);
440
+ const {
441
+ identifier
442
+ } = this;
443
+ const value = this._store.cache.getRelationship(identifier, keyName);
444
+ if (value.data) {
445
+ results = [];
446
+ value.data.forEach(member => {
447
+ const inverseIdentifier = store.cacheKeyManager.getOrCreateRecordIdentifier(member);
448
+ const cache = store.cache;
449
+ if (!cache.isDeleted(inverseIdentifier)) {
450
+ if (returnModeIsIds) {
451
+ results.push(inverseIdentifier.id);
452
+ } else {
453
+ results.push(store._fetchManager.createSnapshot(inverseIdentifier));
454
+ }
455
+ }
456
+ });
457
+ }
458
+
459
+ // we assign even if `undefined` so that we don't reprocess the relationship
460
+ // on next access. This works with the `keyName in` checks above.
461
+ if (returnModeIsIds) {
462
+ this._hasManyIds[keyName] = results;
463
+ } else {
464
+ this._hasManyRelationships[keyName] = results;
465
+ }
466
+ return results;
467
+ }
468
+
469
+ /**
470
+ Iterates through all the attributes of the model, calling the passed
471
+ function on each attribute.
472
+ Example
473
+ ```javascript
474
+ snapshot.eachAttribute(function(name, meta) {
475
+ // ...
476
+ });
477
+ ```
478
+ @param callback the callback to execute
479
+ @param binding the optional value to which the callback's `this` should be bound
480
+ @public
481
+ */
482
+ eachAttribute(callback, binding) {
483
+ // if the store has a modelFor implementation, we use it to iterate attributes. This allows
484
+ // a custom "ModelSchema" class for legacy serializers to adapt to new fields if desired.
485
+ if (typeof this._store.modelFor === 'function') {
486
+ const modelSchema = this._store.modelFor(this.identifier.type);
487
+ modelSchema.eachAttribute(callback, binding);
488
+ } else {
489
+ const fields = this._store.schema.fields(this.identifier);
490
+ fields.forEach((field, key) => {
491
+ if (field.kind === 'attribute') {
492
+ callback.call(binding, key, field);
493
+ }
494
+ });
495
+ }
496
+ }
497
+
498
+ /**
499
+ Iterates through all the relationships of the model, calling the passed
500
+ function on each relationship.
501
+ Example
502
+ ```javascript
503
+ snapshot.eachRelationship(function(name, relationship) {
504
+ // ...
505
+ });
506
+ ```
507
+ @param callback the callback to execute
508
+ @param binding the optional value to which the callback's `this` should be bound
509
+ @public
510
+ */
511
+ eachRelationship(callback, binding) {
512
+ // if the store has a modelFor implementation, we use it to iterate relationships. This allows
513
+ // a custom "ModelSchema" class for legacy serializers to adapt to new fields if desired.
514
+ if (typeof this._store.modelFor === 'function') {
515
+ const modelSchema = this._store.modelFor(this.identifier.type);
516
+ modelSchema.eachRelationship(callback, binding);
517
+ } else {
518
+ const fields = this._store.schema.fields(this.identifier);
519
+ fields.forEach((field, key) => {
520
+ if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
521
+ callback.call(binding, key, field);
522
+ }
523
+ });
524
+ }
525
+ }
526
+
527
+ /**
528
+ Serializes the snapshot using the serializer for the model.
529
+ Example
530
+ ```js [app/adapters/application.js]
531
+ import Adapter from '@ember-data/adapter';
532
+ export default Adapter.extend({
533
+ createRecord(store, type, snapshot) {
534
+ let data = snapshot.serialize({ includeId: true });
535
+ let url = `/${type.modelName}`;
536
+ return fetch(url, {
537
+ method: 'POST',
538
+ body: data,
539
+ }).then((response) => response.json())
540
+ }
541
+ });
542
+ ```
543
+ @return an object whose values are primitive JSON values only
544
+ @public
545
+ */
546
+ serialize(options) {
547
+ upgradeStore(this._store);
548
+ const serializer = this._store.serializerFor(this.modelName);
549
+ return serializer.serialize(this, options);
550
+ }
551
+ }
552
+ const SaveOp = getOrSetGlobal('SaveOp', Symbol('SaveOp'));
553
+ /**
554
+ * @private
555
+ */
556
+ class FetchManager {
557
+ /**
558
+ * @internal
559
+ */
560
+
561
+ /** @internal */
562
+
563
+ // fetches pending in the runloop, waiting to be coalesced
564
+ /**
565
+ * @internal
566
+ */
567
+
568
+ /** @internal */
569
+
570
+ constructor(store) {
571
+ assertPrivateStore(store);
572
+ this._store = store;
573
+ // used to keep track of all the find requests that need to be coalesced
574
+ this._pendingFetch = new Map();
575
+ this.requestCache = store.getRequestStateService();
576
+ this.isDestroyed = false;
577
+ }
578
+ createSnapshot(identifier, options = {}) {
579
+ return new Snapshot(options, identifier, this._store);
580
+ }
581
+
582
+ /**
583
+ This method is called by `record.save`, and gets passed a
584
+ resolver for the promise that `record.save` returns.
585
+ It schedules saving to happen at the end of the run loop.
586
+ @private
587
+ */
588
+ scheduleSave(identifier, options) {
589
+ const resolver = createDeferred();
590
+ const query = {
591
+ op: 'saveRecord',
592
+ recordIdentifier: identifier,
593
+ options
594
+ };
595
+ const queryRequest = {
596
+ data: [query]
597
+ };
598
+ const snapshot = this.createSnapshot(identifier, options);
599
+ const pendingSaveItem = {
600
+ snapshot: snapshot,
601
+ resolver: resolver,
602
+ identifier,
603
+ options,
604
+ queryRequest
605
+ };
606
+ const monitored = this.requestCache._enqueue(resolver.promise, pendingSaveItem.queryRequest);
607
+ _flushPendingSave(this._store, pendingSaveItem);
608
+ return monitored;
609
+ }
610
+ scheduleFetch(identifier, options, request) {
611
+ const query = {
612
+ op: 'findRecord',
613
+ recordIdentifier: identifier,
614
+ options
615
+ };
616
+ const queryRequest = {
617
+ data: [query]
618
+ };
619
+ const pendingFetch = this.getPendingFetch(identifier, options);
620
+ if (pendingFetch) {
621
+ return pendingFetch;
622
+ }
623
+ const modelName = identifier.type;
624
+ const resolver = createDeferred();
625
+ const pendingFetchItem = {
626
+ identifier,
627
+ resolver,
628
+ options,
629
+ queryRequest
630
+ };
631
+ const resolverPromise = resolver.promise;
632
+ const store = this._store;
633
+ const isInitialLoad = !store._instanceCache.recordIsLoaded(identifier); // we don't use isLoading directly because we are the request
634
+
635
+ const monitored = this.requestCache._enqueue(resolverPromise, pendingFetchItem.queryRequest);
636
+ let promise = monitored.then(payload => {
637
+ // ensure that regardless of id returned we assign to the correct record
638
+ if (payload.data && !Array.isArray(payload.data)) {
639
+ payload.data.lid = identifier.lid;
640
+ }
641
+
642
+ // additional data received in the payload
643
+ // may result in the merging of identifiers (and thus records)
644
+ const potentiallyNewIm = store._push(payload, options.reload);
645
+ if (potentiallyNewIm && !Array.isArray(potentiallyNewIm)) {
646
+ return potentiallyNewIm;
647
+ }
648
+ return identifier;
649
+ }, error => {
650
+ const cache = store.cache;
651
+ if (!cache || cache.isEmpty(identifier) || isInitialLoad) {
652
+ let isReleasable = true;
653
+ if (store._graph) {
654
+ const graph = store._graph;
655
+ if (!cache) {
656
+ isReleasable = graph.isReleasable(identifier);
657
+ if (!isReleasable) {
658
+ graph.unload(identifier, true);
659
+ }
660
+ }
661
+ }
662
+ if (cache || isReleasable) {
663
+ store._enableAsyncFlush = true;
664
+ store._instanceCache.unloadRecord(identifier);
665
+ store._enableAsyncFlush = null;
666
+ }
667
+ }
668
+ throw error;
669
+ });
670
+ if (this._pendingFetch.size === 0) {
671
+ void new Promise(resolve => setTimeout(resolve, 0)).then(() => {
672
+ this.flushAllPendingFetches();
673
+ });
674
+ }
675
+ const fetchesByType = this._pendingFetch;
676
+ let fetchesById = fetchesByType.get(modelName);
677
+ if (!fetchesById) {
678
+ fetchesById = new Map();
679
+ fetchesByType.set(modelName, fetchesById);
680
+ }
681
+ let requestsForIdentifier = fetchesById.get(identifier);
682
+ if (!requestsForIdentifier) {
683
+ requestsForIdentifier = [];
684
+ fetchesById.set(identifier, requestsForIdentifier);
685
+ }
686
+ requestsForIdentifier.push(pendingFetchItem);
687
+ pendingFetchItem.promise = promise;
688
+ return promise;
689
+ }
690
+ getPendingFetch(identifier, options) {
691
+ const pendingFetches = this._pendingFetch.get(identifier.type)?.get(identifier);
692
+
693
+ // We already have a pending fetch for this
694
+ if (pendingFetches) {
695
+ const matchingPendingFetch = pendingFetches.find(fetch => isSameRequest(options, fetch.options));
696
+ if (matchingPendingFetch) {
697
+ return matchingPendingFetch.promise;
698
+ }
699
+ }
700
+ }
701
+ flushAllPendingFetches() {
702
+ if (this.isDestroyed) {
703
+ return;
704
+ }
705
+ const store = this._store;
706
+ this._pendingFetch.forEach((fetchItem, type) => _flushPendingFetchForType(store, fetchItem, type));
707
+ this._pendingFetch.clear();
708
+ }
709
+ fetchDataIfNeededForIdentifier(identifier, options = {}, request) {
710
+ // pre-loading will change the isEmpty value
711
+ const isEmpty = _isEmpty(this._store._instanceCache, identifier);
712
+ const isLoading = _isLoading(this._store._instanceCache, identifier);
713
+ let promise;
714
+ if (isEmpty) {
715
+ {
716
+ options.reload = true;
717
+ promise = this.scheduleFetch(identifier, options, request);
718
+ }
719
+ } else if (isLoading) {
720
+ promise = this.getPendingFetch(identifier, options);
721
+ } else {
722
+ promise = Promise.resolve(identifier);
723
+ }
724
+ return promise;
725
+ }
726
+ destroy() {
727
+ this.isDestroyed = true;
728
+ }
729
+ }
730
+
731
+ /**
732
+ * This type exists for internal use only for
733
+ * where intimate contracts still exist either for
734
+ * the Test Suite or for Legacy code.
735
+ *
736
+ * @private
737
+ */
738
+
739
+ function _isEmpty(instanceCache, identifier) {
740
+ const cache = instanceCache.cache;
741
+ if (!cache) {
742
+ return true;
743
+ }
744
+ const isNew = cache.isNew(identifier);
745
+ const isDeleted = cache.isDeleted(identifier);
746
+ const isEmpty = cache.isEmpty(identifier);
747
+ return (!isNew || isDeleted) && isEmpty;
748
+ }
749
+ function _isLoading(cache, identifier) {
750
+ const req = cache.store.getRequestStateService();
751
+ // const fulfilled = req.getLastRequestForRecord(identifier);
752
+ const isLoaded = cache.recordIsLoaded(identifier);
753
+ return !isLoaded &&
754
+ // fulfilled === null &&
755
+ req.getPendingRequestsForRecord(identifier).some(r => r.type === 'query');
756
+ }
757
+ function includesSatisfies(current, existing) {
758
+ // if we have no includes we are good
759
+ if (!current?.length) {
760
+ return true;
761
+ }
762
+
763
+ // if we are here we have includes,
764
+ // and if existing has no includes then we will need a new request
765
+ if (!existing?.length) {
766
+ return false;
767
+ }
768
+ const arrCurrent = (Array.isArray(current) ? current : current.split(',')).sort();
769
+ const arrExisting = (Array.isArray(existing) ? existing : existing.split(',')).sort();
770
+
771
+ // includes are identical
772
+ if (arrCurrent.join(',') === arrExisting.join(',')) {
773
+ return true;
774
+ }
775
+
776
+ // if all of current includes are in existing includes then we are good
777
+ // so if we find one that is not in existing then we need a new request
778
+ for (let i = 0; i < arrCurrent.length; i++) {
779
+ if (!arrExisting.includes(arrCurrent[i])) {
780
+ return false;
781
+ }
782
+ }
783
+ return true;
784
+ }
785
+ function optionsSatisfies(current, existing) {
786
+ return !current || current === existing || Object.keys(current).length === 0;
787
+ }
788
+
789
+ // this function helps resolve whether we have a pending request that we should use instead
790
+ function isSameRequest(options = {}, existingOptions = {}) {
791
+ return optionsSatisfies(options.adapterOptions, existingOptions.adapterOptions) && includesSatisfies(options.include, existingOptions.include);
792
+ }
793
+ function _findMany(store, adapter, modelName, snapshots) {
794
+ const modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still
795
+ const promise = Promise.resolve().then(() => {
796
+ const ids = snapshots.map(s => s.id);
797
+ const ret = adapter.findMany(store, modelClass, ids, snapshots);
798
+ return ret;
799
+ });
800
+ return promise.then(adapterPayload => {
801
+ const serializer = store.serializerFor(modelName);
802
+ const payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany');
803
+ return payload;
804
+ });
805
+ }
806
+ function rejectFetchedItems(fetchMap, snapshots, error) {
807
+ for (let i = 0, l = snapshots.length; i < l; i++) {
808
+ const snapshot = snapshots[i];
809
+ const pair = fetchMap.get(snapshot);
810
+ if (pair) {
811
+ pair.resolver.reject(error || new Error(`Expected: '<${snapshot.modelName}:${snapshot.id}>' to be present in the adapter provided payload, but it was not found.`));
812
+ }
813
+ }
814
+ }
815
+ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
816
+ /*
817
+ It is possible that the same ID is included multiple times
818
+ via multiple snapshots. This happens when more than one
819
+ options hash was supplied, each of which must be uniquely
820
+ accounted for.
821
+ However, since we can't map from response to a specific
822
+ options object, we resolve all snapshots by id with
823
+ the first response we see.
824
+ */
825
+ const snapshotsById = new Map();
826
+ for (let i = 0; i < snapshots.length; i++) {
827
+ const id = snapshots[i].id;
828
+ let snapshotGroup = snapshotsById.get(id);
829
+ if (!snapshotGroup) {
830
+ snapshotGroup = [];
831
+ snapshotsById.set(id, snapshotGroup);
832
+ }
833
+ snapshotGroup.push(snapshots[i]);
834
+ }
835
+ const included = Array.isArray(coalescedPayload.included) ? coalescedPayload.included : [];
836
+
837
+ // resolve found records
838
+ const resources = coalescedPayload.data;
839
+ for (let i = 0, l = resources.length; i < l; i++) {
840
+ const resource = resources[i];
841
+ const snapshotGroup = snapshotsById.get(resource.id);
842
+ snapshotsById.delete(resource.id);
843
+ if (!snapshotGroup) {
844
+ // TODO consider whether this should be a deprecation/assertion
845
+ included.push(resource);
846
+ } else {
847
+ snapshotGroup.forEach(snapshot => {
848
+ const pair = fetchMap.get(snapshot);
849
+ const resolver = pair.resolver;
850
+ resolver.resolve({
851
+ data: resource
852
+ });
853
+ });
854
+ }
855
+ }
856
+ if (included.length > 0) {
857
+ store._push({
858
+ data: null,
859
+ included
860
+ }, true);
861
+ }
862
+ if (snapshotsById.size === 0) {
863
+ return;
864
+ }
865
+
866
+ // reject missing records
867
+ const rejected = [];
868
+ snapshotsById.forEach(snapshotArray => {
869
+ rejected.push(...snapshotArray);
870
+ });
871
+ rejectFetchedItems(fetchMap, rejected);
872
+ }
873
+ function _fetchRecord(store, adapter, fetchItem) {
874
+ const identifier = fetchItem.identifier;
875
+ const modelName = identifier.type;
876
+ const snapshot = store._fetchManager.createSnapshot(identifier, fetchItem.options);
877
+ const klass = store.modelFor(identifier.type);
878
+ const id = identifier.id;
879
+ let promise = Promise.resolve().then(() => {
880
+ return adapter.findRecord(store, klass, identifier.id, snapshot);
881
+ });
882
+ promise = promise.then(adapterPayload => {
883
+ const serializer = store.serializerFor(modelName);
884
+ const payload = normalizeResponseHelper(serializer, store, klass, adapterPayload, id, 'findRecord');
885
+ return payload;
886
+ });
887
+ fetchItem.resolver.resolve(promise);
888
+ }
889
+ function _processCoalescedGroup(store, fetchMap, group, adapter, modelName) {
890
+ if (group.length > 1) {
891
+ _findMany(store, adapter, modelName, group).then(payloads => {
892
+ handleFoundRecords(store, fetchMap, group, payloads);
893
+ }).catch(error => {
894
+ rejectFetchedItems(fetchMap, group, error);
895
+ });
896
+ } else if (group.length === 1) {
897
+ _fetchRecord(store, adapter, fetchMap.get(group[0]));
898
+ } else ;
899
+ }
900
+ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
901
+ const adapter = store.adapterFor(modelName);
902
+ const shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
903
+ if (shouldCoalesce) {
904
+ const pendingFetchItems = [];
905
+ pendingFetchMap.forEach((requestsForIdentifier, identifier) => {
906
+ if (requestsForIdentifier.length > 1) {
907
+ return;
908
+ }
909
+
910
+ // remove this entry from the map so it's not processed again
911
+ pendingFetchMap.delete(identifier);
912
+ pendingFetchItems.push(requestsForIdentifier[0]);
913
+ });
914
+ const totalItems = pendingFetchItems.length;
915
+ if (totalItems > 1) {
916
+ const snapshots = new Array(totalItems);
917
+ const fetchMap = new Map();
918
+ for (let i = 0; i < totalItems; i++) {
919
+ const fetchItem = pendingFetchItems[i];
920
+ snapshots[i] = store._fetchManager.createSnapshot(fetchItem.identifier, fetchItem.options);
921
+ fetchMap.set(snapshots[i], fetchItem);
922
+ }
923
+ let groups;
924
+ if (adapter.groupRecordsForFindMany) {
925
+ groups = adapter.groupRecordsForFindMany(store, snapshots);
926
+ } else {
927
+ groups = [snapshots];
928
+ }
929
+ for (let i = 0, l = groups.length; i < l; i++) {
930
+ _processCoalescedGroup(store, fetchMap, groups[i], adapter, modelName);
931
+ }
932
+ } else if (totalItems === 1) {
933
+ _fetchRecord(store, adapter, pendingFetchItems[0]);
934
+ }
935
+ }
936
+ pendingFetchMap.forEach(pendingFetchItems => {
937
+ pendingFetchItems.forEach(pendingFetchItem => {
938
+ _fetchRecord(store, adapter, pendingFetchItem);
939
+ });
940
+ });
941
+ }
942
+ function _flushPendingSave(store, pending) {
943
+ const {
944
+ snapshot,
945
+ resolver,
946
+ identifier,
947
+ options
948
+ } = pending;
949
+ const adapter = store.adapterFor(identifier.type);
950
+ const operation = options[SaveOp];
951
+ const modelName = snapshot.modelName;
952
+ const modelClass = store.modelFor(modelName);
953
+ let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
954
+ const serializer = store.serializerFor(modelName);
955
+ promise = promise.then(adapterPayload => {
956
+ if (adapterPayload) {
957
+ return normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
958
+ }
959
+ });
960
+ resolver.resolve(promise);
961
+ }
962
+
963
+ /**
964
+ * Utilities - often temporary - for maintaining backwards compatibility with
965
+ * older parts of WarpDrive.
966
+ *
967
+ @module
968
+ */
969
+ function upgradeStore(store) {}
970
+ export { FetchManager as F, SaveOp as S, SnapshotRecordArray as a, Snapshot as b, normalizeResponseHelper as n, upgradeStore as u };