@ember-data/store 4.10.0-alpha.2 → 4.10.0-alpha.21

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 (39) hide show
  1. package/addon/-private.js +1 -0
  2. package/addon/-private.js.map +1 -0
  3. package/addon/index-12e1fcb9.js +7660 -0
  4. package/addon/index-12e1fcb9.js.map +1 -0
  5. package/addon/index.js +1 -0
  6. package/addon/index.js.map +1 -0
  7. package/addon-main.js +90 -0
  8. package/package.json +44 -15
  9. package/addon/-private/caches/identifier-cache.ts +0 -686
  10. package/addon/-private/caches/instance-cache.ts +0 -695
  11. package/addon/-private/caches/record-data-for.ts +0 -34
  12. package/addon/-private/index.ts +0 -59
  13. package/addon/-private/legacy-model-support/record-reference.ts +0 -240
  14. package/addon/-private/legacy-model-support/schema-definition-service.ts +0 -148
  15. package/addon/-private/legacy-model-support/shim-model-class.ts +0 -97
  16. package/addon/-private/managers/record-array-manager.ts +0 -379
  17. package/addon/-private/managers/record-data-manager.ts +0 -845
  18. package/addon/-private/managers/record-data-store-wrapper.ts +0 -425
  19. package/addon/-private/managers/record-notification-manager.ts +0 -111
  20. package/addon/-private/network/fetch-manager.ts +0 -567
  21. package/addon/-private/network/finders.js +0 -104
  22. package/addon/-private/network/request-cache.ts +0 -132
  23. package/addon/-private/network/snapshot-record-array.ts +0 -209
  24. package/addon/-private/network/snapshot.ts +0 -563
  25. package/addon/-private/proxies/promise-proxies.ts +0 -228
  26. package/addon/-private/proxies/promise-proxy-base.js +0 -7
  27. package/addon/-private/record-arrays/identifier-array.ts +0 -929
  28. package/addon/-private/store-service.ts +0 -2896
  29. package/addon/-private/utils/coerce-id.ts +0 -41
  30. package/addon/-private/utils/common.js +0 -65
  31. package/addon/-private/utils/construct-resource.ts +0 -61
  32. package/addon/-private/utils/identifer-debug-consts.ts +0 -3
  33. package/addon/-private/utils/is-non-empty-string.ts +0 -3
  34. package/addon/-private/utils/normalize-model-name.ts +0 -21
  35. package/addon/-private/utils/promise-record.ts +0 -15
  36. package/addon/-private/utils/serializer-response.ts +0 -86
  37. package/addon/-private/utils/uuid-polyfill.ts +0 -73
  38. package/addon/index.ts +0 -14
  39. package/index.js +0 -49
@@ -1,379 +0,0 @@
1
- /**
2
- @module @ember-data/store
3
- */
4
- import { addToTransaction } from '@ember-data/tracking/-private';
5
- import type { CollectionResourceDocument } from '@ember-data/types/q/ember-data-json-api';
6
- import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
7
- import type { Dict } from '@ember-data/types/q/utils';
8
-
9
- import IdentifierArray, {
10
- Collection,
11
- CollectionCreateOptions,
12
- IDENTIFIER_ARRAY_TAG,
13
- SOURCE,
14
- } from '../record-arrays/identifier-array';
15
- import type Store from '../store-service';
16
-
17
- const RecordArraysCache = new Map<StableRecordIdentifier, Set<Collection>>();
18
- const FAKE_ARR = {};
19
-
20
- const SLICE_BATCH_SIZE = 1200;
21
- /**
22
- * This is a clever optimization.
23
- *
24
- * clever optimizations rarely stand the test of time, so if you're
25
- * ever curious or think something better is possible please benchmark
26
- * and discuss. The benchmark for this at the time of writing is in
27
- * `scripts/benchmark-push.js`
28
- *
29
- * This approach turns out to be 150x faster in Chrome and node than
30
- * simply using push or concat. It's highly susceptible to the specifics
31
- * of the batch size, and may require tuning.
32
- *
33
- * Clever optimizations should always come with a `why`. This optimization
34
- * exists for two reasons.
35
- *
36
- * 1) array.push(...objects) and Array.prototype.push.apply(arr, objects)
37
- * are susceptible to stack overflows. The size of objects at which this
38
- * occurs varies by environment, browser, and current stack depth and memory
39
- * pressure; however, it occurs in all browsers in fairly pristine conditions
40
- * somewhere around 125k to 200k elements. Since EmberData regularly encounters
41
- * arrays larger than this in size, we cannot use push.
42
- *
43
- * 2) `array.concat` or simply setting the array to a new reference is often an
44
- * easier approach; however, native Proxy to an array cannot swap it's target array
45
- * and attempts at juggling multiple array sources have proven to be victim to a number
46
- * of browser implementation bugs. Should these bugs be addressed then we could
47
- * simplify to using `concat`, however, do note this is currently 150x faster
48
- * than concat, and due to the overloaded signature of concat will likely always
49
- * be faster.
50
- *
51
- * Sincerely,
52
- * - runspired (Chris Thoburn) 08/21/2022
53
- *
54
- * @function fastPush
55
- * @internal
56
- * @param target the array to push into
57
- * @param source the items to push into target
58
- */
59
- export function fastPush<T>(target: T[], source: T[]) {
60
- let startLength = 0;
61
- let newLength = source.length;
62
- while (newLength - startLength > SLICE_BATCH_SIZE) {
63
- // eslint-disable-next-line prefer-spread
64
- target.push.apply(target, source.slice(startLength, startLength + SLICE_BATCH_SIZE));
65
- startLength += SLICE_BATCH_SIZE;
66
- }
67
- // eslint-disable-next-line prefer-spread
68
- target.push.apply(target, source.slice(startLength));
69
- }
70
-
71
- type ChangeSet = Map<StableRecordIdentifier, 'add' | 'del'>;
72
-
73
- /**
74
- @class RecordArrayManager
75
- @internal
76
- */
77
- class RecordArrayManager {
78
- declare store: Store;
79
- declare isDestroying: boolean;
80
- declare isDestroyed: boolean;
81
- declare _live: Map<string, IdentifierArray>;
82
- declare _managed: Set<IdentifierArray>;
83
- declare _pending: Map<IdentifierArray, ChangeSet>;
84
- declare _identifiers: Map<StableRecordIdentifier, Set<Collection>>;
85
- declare _staged: Map<string, ChangeSet>;
86
-
87
- constructor(options: { store: Store }) {
88
- this.store = options.store;
89
- this.isDestroying = false;
90
- this.isDestroyed = false;
91
- this._live = new Map();
92
- this._managed = new Set();
93
- this._pending = new Map();
94
- this._staged = new Map();
95
- this._identifiers = RecordArraysCache;
96
- }
97
-
98
- _syncArray(array: IdentifierArray) {
99
- const pending = this._pending.get(array);
100
-
101
- if (!pending || this.isDestroying || this.isDestroyed) {
102
- return;
103
- }
104
-
105
- sync(array, pending);
106
- this._pending.delete(array);
107
- }
108
-
109
- /**
110
- Get the `RecordArray` for a modelName, which contains all loaded records of
111
- given modelName.
112
-
113
- @method liveArrayFor
114
- @internal
115
- @param {String} modelName
116
- @return {RecordArray}
117
- */
118
- liveArrayFor(type: string): IdentifierArray {
119
- let array = this._live.get(type);
120
- let identifiers: StableRecordIdentifier[] = [];
121
- let staged = this._staged.get(type);
122
- if (staged) {
123
- staged.forEach((value, key) => {
124
- if (value === 'add') {
125
- identifiers.push(key);
126
- }
127
- });
128
- this._staged.delete(type);
129
- }
130
-
131
- if (!array) {
132
- array = new IdentifierArray({
133
- type,
134
- identifiers,
135
- store: this.store,
136
- allowMutation: false,
137
- manager: this,
138
- });
139
- this._live.set(type, array);
140
- }
141
-
142
- return array;
143
- }
144
-
145
- createArray(config: {
146
- type: string;
147
- query?: Dict<unknown>;
148
- identifiers?: StableRecordIdentifier[];
149
- doc?: CollectionResourceDocument;
150
- }): Collection {
151
- let options: CollectionCreateOptions = {
152
- type: config.type,
153
- links: config.doc?.links || null,
154
- meta: config.doc?.meta || null,
155
- query: config.query || null,
156
- identifiers: config.identifiers || [],
157
- isLoaded: !!config.identifiers?.length,
158
- allowMutation: false,
159
- store: this.store,
160
- manager: this,
161
- };
162
- let array = new Collection(options);
163
- this._managed.add(array);
164
- if (config.identifiers) {
165
- associate(array, config.identifiers);
166
- }
167
-
168
- return array;
169
- }
170
-
171
- dirtyArray(array: IdentifierArray, delta: number): void {
172
- if (array === FAKE_ARR) {
173
- return;
174
- }
175
- let tag = array[IDENTIFIER_ARRAY_TAG];
176
- if (!tag.shouldReset) {
177
- tag.shouldReset = true;
178
- addToTransaction(tag);
179
- } else if (delta > 0 && tag.t) {
180
- addToTransaction(tag);
181
- }
182
- }
183
-
184
- _getPendingFor(
185
- identifier: StableRecordIdentifier,
186
- includeManaged: boolean,
187
- isRemove?: boolean
188
- ): Map<IdentifierArray, ChangeSet> | void {
189
- if (this.isDestroying || this.isDestroyed) {
190
- return;
191
- }
192
-
193
- let liveArray = this._live.get(identifier.type);
194
- const allPending = this._pending;
195
- let pending: Map<IdentifierArray, ChangeSet> = new Map();
196
-
197
- if (includeManaged) {
198
- let managed = RecordArraysCache.get(identifier);
199
- if (managed) {
200
- managed.forEach((arr) => {
201
- let changes = allPending.get(arr);
202
- if (!changes) {
203
- changes = new Map();
204
- allPending.set(arr, changes);
205
- }
206
- pending.set(arr, changes);
207
- });
208
- }
209
- }
210
-
211
- // during unloadAll we can ignore removes since we've already
212
- // cleared the array.
213
- if (liveArray && liveArray[SOURCE].length === 0 && isRemove) {
214
- const pendingLive = allPending.get(liveArray);
215
- if (!pendingLive || pendingLive.size === 0) {
216
- return pending;
217
- }
218
- }
219
-
220
- if (!liveArray) {
221
- // start building a changeset for when we eventually
222
- // do have a live array
223
- let changes = this._staged.get(identifier.type);
224
- if (!changes) {
225
- changes = new Map();
226
- this._staged.set(identifier.type, changes);
227
- }
228
- pending.set(FAKE_ARR as IdentifierArray, changes);
229
- } else {
230
- let changes = allPending.get(liveArray);
231
- if (!changes) {
232
- changes = new Map();
233
- allPending.set(liveArray, changes);
234
- }
235
- pending.set(liveArray, changes);
236
- }
237
-
238
- return pending;
239
- }
240
-
241
- populateManagedArray(array: Collection, identifiers: StableRecordIdentifier[], payload: CollectionResourceDocument) {
242
- this._pending.delete(array);
243
- const source = array[SOURCE];
244
- const old = source.slice();
245
- source.length = 0;
246
- fastPush(source, identifiers);
247
- array[IDENTIFIER_ARRAY_TAG].ref = null;
248
- array.meta = payload.meta || null;
249
- array.links = payload.links || null;
250
- array.isLoaded = true;
251
-
252
- disassociate(array, old);
253
- associate(array, identifiers);
254
- }
255
-
256
- identifierAdded(identifier: StableRecordIdentifier): void {
257
- let changeSets = this._getPendingFor(identifier, false);
258
- if (changeSets) {
259
- changeSets.forEach((changes, array) => {
260
- let existing = changes.get(identifier);
261
- if (existing === 'del') {
262
- changes.delete(identifier);
263
- } else {
264
- changes.set(identifier, 'add');
265
-
266
- this.dirtyArray(array, changes.size);
267
- }
268
- });
269
- }
270
- }
271
-
272
- identifierRemoved(identifier: StableRecordIdentifier): void {
273
- let changeSets = this._getPendingFor(identifier, true, true);
274
- if (changeSets) {
275
- changeSets.forEach((changes, array) => {
276
- let existing = changes.get(identifier);
277
- if (existing === 'add') {
278
- changes.delete(identifier);
279
- } else {
280
- changes.set(identifier, 'del');
281
-
282
- this.dirtyArray(array, changes.size);
283
- }
284
- });
285
- }
286
- }
287
-
288
- identifierChanged(identifier: StableRecordIdentifier): void {
289
- let newState = this.store._instanceCache.recordIsLoaded(identifier, true);
290
-
291
- if (newState) {
292
- this.identifierAdded(identifier);
293
- } else {
294
- this.identifierRemoved(identifier);
295
- }
296
- }
297
-
298
- clear() {
299
- this._live.forEach((array) => array.destroy());
300
- this._managed.forEach((array) => array.destroy());
301
- this._managed.clear();
302
- RecordArraysCache.clear();
303
- }
304
-
305
- destroy() {
306
- this.isDestroying = true;
307
- this.clear();
308
- this._live.clear();
309
- this.isDestroyed = true;
310
- }
311
- }
312
-
313
- function associate(array: Collection, identifiers: StableRecordIdentifier[]) {
314
- for (let i = 0; i < identifiers.length; i++) {
315
- let identifier = identifiers[i];
316
- let cache = RecordArraysCache.get(identifier);
317
- if (!cache) {
318
- cache = new Set();
319
- RecordArraysCache.set(identifier, cache);
320
- }
321
- cache.add(array);
322
- }
323
- }
324
-
325
- function disassociate(array: Collection, identifiers: StableRecordIdentifier[]) {
326
- for (let i = 0; i < identifiers.length; i++) {
327
- disassociateIdentifier(array, identifiers[i]);
328
- }
329
- }
330
-
331
- export function disassociateIdentifier(array: Collection, identifier: StableRecordIdentifier) {
332
- let cache = RecordArraysCache.get(identifier);
333
- if (cache) {
334
- cache.delete(array);
335
- }
336
- }
337
-
338
- function sync(array: IdentifierArray, changes: Map<StableRecordIdentifier, 'add' | 'del'>) {
339
- let state = array[SOURCE];
340
- const adds: StableRecordIdentifier[] = [];
341
- const removes: StableRecordIdentifier[] = [];
342
- changes.forEach((value, key) => {
343
- if (value === 'add') {
344
- // likely we want to keep a Set along-side
345
- if (state.includes(key)) {
346
- return;
347
- }
348
- adds.push(key);
349
- } else {
350
- removes.push(key);
351
- }
352
- });
353
- if (removes.length) {
354
- if (removes.length === state.length) {
355
- state.length = 0;
356
- // changing the reference breaks the Proxy
357
- // state = array[SOURCE] = [];
358
- } else {
359
- removes.forEach((i) => {
360
- state.splice(state.indexOf(i), 1);
361
- });
362
- }
363
- }
364
-
365
- if (adds.length) {
366
- fastPush(state, adds);
367
- // changing the reference breaks the Proxy
368
- // else we could do this
369
- /*
370
- if (state.length === 0) {
371
- array[SOURCE] = adds;
372
- } else {
373
- array[SOURCE] = state.concat(adds);
374
- }
375
- */
376
- }
377
- }
378
-
379
- export default RecordArrayManager;