@ember-data/store 4.8.0-beta.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -1,6 +1,8 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019
3
+ Copyright (C) 2017-2022 Ember.js contributors
4
+ Portions Copyright (C) 2011-2017 Tilde, Inc. and contributors.
5
+ Portions Copyright (C) 2011 LivingSocial Inc.
4
6
 
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
8
 
@@ -266,14 +266,16 @@ export class IdentifierCache {
266
266
  // one level up
267
267
  keyOptions.lid.set(identifier.lid, identifier);
268
268
 
269
- if (LOG_IDENTIFIERS && shouldGenerate) {
270
- // eslint-disable-next-line no-console
271
- console.log(`Identifiers: generated ${String(identifier)} for`, resource);
272
- if (resource[DEBUG_IDENTIFIER_BUCKET]) {
269
+ if (LOG_IDENTIFIERS) {
270
+ if (shouldGenerate) {
273
271
  // eslint-disable-next-line no-console
274
- console.trace(
275
- `[WARNING] Identifiers: generated a new identifier from a previously used identifier. This is likely a bug.`
276
- );
272
+ console.log(`Identifiers: generated ${String(identifier)} for`, resource);
273
+ if (resource[DEBUG_IDENTIFIER_BUCKET]) {
274
+ // eslint-disable-next-line no-console
275
+ console.trace(
276
+ `[WARNING] Identifiers: generated a new identifier from a previously used identifier. This is likely a bug.`
277
+ );
278
+ }
277
279
  }
278
280
  }
279
281
  }
@@ -84,8 +84,10 @@ export function recordIdentifierFor(record: RecordInstance): StableRecordIdentif
84
84
  }
85
85
 
86
86
  export function setRecordIdentifier(record: RecordInstance, identifier: StableRecordIdentifier): void {
87
- if (DEBUG && RecordCache.has(record) && RecordCache.get(record) !== identifier) {
88
- throw new Error(`${String(record)} was already assigned an identifier`);
87
+ if (DEBUG) {
88
+ if (RecordCache.has(record) && RecordCache.get(record) !== identifier) {
89
+ throw new Error(`${String(record)} was already assigned an identifier`);
90
+ }
89
91
  }
90
92
 
91
93
  /*
@@ -260,8 +262,8 @@ export class InstanceCache {
260
262
  getRecordData(identifier: StableRecordIdentifier): RecordData {
261
263
  let recordData = this.__instances.recordData.get(identifier);
262
264
 
263
- if (!recordData) {
264
- if (DEPRECATE_V1CACHE_STORE_APIS && this.store.createRecordDataFor.length > 2) {
265
+ if (DEPRECATE_V1CACHE_STORE_APIS) {
266
+ if (!recordData && this.store.createRecordDataFor.length > 2) {
265
267
  deprecate(
266
268
  `Store.createRecordDataFor(<type>, <id>, <lid>, <storeWrapper>) has been deprecated in favor of Store.createRecordDataFor(<identifier>, <storeWrapper>)`,
267
269
  false,
@@ -269,7 +271,7 @@ export class InstanceCache {
269
271
  id: 'ember-data:deprecate-v1cache-store-apis',
270
272
  for: 'ember-data',
271
273
  until: '5.0',
272
- since: { enabled: '4.8', available: '4.8' },
274
+ since: { enabled: '4.7', available: '4.7' },
273
275
  }
274
276
  );
275
277
  let recordDataInstance = this.store.createRecordDataFor(
@@ -285,19 +287,22 @@ export class InstanceCache {
285
287
  recordData = this.__cacheManager =
286
288
  this.__cacheManager || new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
287
289
  }
290
+ }
291
+ }
292
+
293
+ if (!recordData) {
294
+ let recordDataInstance = this.store.createRecordDataFor(identifier, this._storeWrapper);
295
+ if (DEPRECATE_V1_RECORD_DATA) {
296
+ recordData = new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
288
297
  } else {
289
- let recordDataInstance = this.store.createRecordDataFor(identifier, this._storeWrapper);
290
- if (DEPRECATE_V1_RECORD_DATA) {
291
- recordData = new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
298
+ if (DEBUG) {
299
+ recordData = this.__cacheManager = this.__cacheManager || new SingletonRecordDataManager();
300
+ (recordData as SingletonRecordDataManager)._addRecordData(identifier, recordDataInstance as RecordData);
292
301
  } else {
293
- if (DEBUG) {
294
- recordData = this.__cacheManager = this.__cacheManager || new SingletonRecordDataManager();
295
- (recordData as SingletonRecordDataManager)._addRecordData(identifier, recordDataInstance as RecordData);
296
- } else {
297
- recordData = recordDataInstance as RecordData;
298
- }
302
+ recordData = recordDataInstance as RecordData;
299
303
  }
300
304
  }
305
+
301
306
  setRecordDataFor(identifier, recordData);
302
307
 
303
308
  this.__instances.recordData.set(identifier, recordData);
@@ -30,7 +30,7 @@ export function normalizeModelName(modelName: string) {
30
30
  id: 'ember-data:deprecate-normalize-modelname-helper',
31
31
  for: 'ember-data',
32
32
  until: '5.0',
33
- since: { available: '4.8', enabled: '4.8' },
33
+ since: { available: '4.7', enabled: '4.7' },
34
34
  }
35
35
  );
36
36
  return _normalize(modelName);
@@ -39,18 +39,22 @@ export class DSModelSchemaDefinitionService {
39
39
  // Following the existing RD implementation
40
40
  attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
41
41
  let modelName, attributes;
42
- if (DEPRECATE_STRING_ARG_SCHEMAS && typeof identifier === 'string') {
43
- deprecate(
44
- `attributesDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
45
- false,
46
- {
47
- id: 'ember-data:deprecate-string-arg-schemas',
48
- for: 'ember-data',
49
- until: '5.0',
50
- since: { enabled: '4.5', available: '4.5' },
51
- }
52
- );
53
- modelName = identifier;
42
+ if (DEPRECATE_STRING_ARG_SCHEMAS) {
43
+ if (typeof identifier === 'string') {
44
+ deprecate(
45
+ `attributesDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
46
+ false,
47
+ {
48
+ id: 'ember-data:deprecate-string-arg-schemas',
49
+ for: 'ember-data',
50
+ until: '5.0',
51
+ since: { enabled: '4.5', available: '4.5' },
52
+ }
53
+ );
54
+ modelName = identifier;
55
+ } else {
56
+ modelName = identifier.type;
57
+ }
54
58
  } else {
55
59
  modelName = identifier.type;
56
60
  }
@@ -72,18 +76,22 @@ export class DSModelSchemaDefinitionService {
72
76
  // Following the existing RD implementation
73
77
  relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
74
78
  let modelName, relationships;
75
- if (DEPRECATE_STRING_ARG_SCHEMAS && typeof identifier === 'string') {
76
- deprecate(
77
- `relationshipsDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
78
- false,
79
- {
80
- id: 'ember-data:deprecate-string-arg-schemas',
81
- for: 'ember-data',
82
- until: '5.0',
83
- since: { enabled: '4.5', available: '4.5' },
84
- }
85
- );
86
- modelName = identifier;
79
+ if (DEPRECATE_STRING_ARG_SCHEMAS) {
80
+ if (typeof identifier === 'string') {
81
+ deprecate(
82
+ `relationshipsDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
83
+ false,
84
+ {
85
+ id: 'ember-data:deprecate-string-arg-schemas',
86
+ for: 'ember-data',
87
+ until: '5.0',
88
+ since: { enabled: '4.5', available: '4.5' },
89
+ }
90
+ );
91
+ modelName = identifier;
92
+ } else {
93
+ modelName = identifier.type;
94
+ }
87
95
  } else {
88
96
  modelName = identifier.type;
89
97
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  @module @ember-data/store
3
3
  */
4
+ import { addToTransaction } from '@ember-data/tracking/-private';
4
5
  import type { CollectionResourceDocument } from '@ember-data/types/q/ember-data-json-api';
5
6
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
6
7
  import type { Dict } from '@ember-data/types/q/utils';
@@ -60,7 +61,7 @@ export function fastPush<T>(target: T[], source: T[]) {
60
61
  let newLength = source.length;
61
62
  while (newLength - startLength > SLICE_BATCH_SIZE) {
62
63
  // eslint-disable-next-line prefer-spread
63
- target.push.apply(target, source.slice(startLength, SLICE_BATCH_SIZE));
64
+ target.push.apply(target, source.slice(startLength, startLength + SLICE_BATCH_SIZE));
64
65
  startLength += SLICE_BATCH_SIZE;
65
66
  }
66
67
  // eslint-disable-next-line prefer-spread
@@ -167,14 +168,16 @@ class RecordArrayManager {
167
168
  return array;
168
169
  }
169
170
 
170
- dirtyArray(array: IdentifierArray): void {
171
+ dirtyArray(array: IdentifierArray, delta: number): void {
171
172
  if (array === FAKE_ARR) {
172
173
  return;
173
174
  }
174
175
  let tag = array[IDENTIFIER_ARRAY_TAG];
175
176
  if (!tag.shouldReset) {
176
177
  tag.shouldReset = true;
177
- tag.ref = null;
178
+ addToTransaction(tag);
179
+ } else if (delta > 0 && tag.t) {
180
+ addToTransaction(tag);
178
181
  }
179
182
  }
180
183
 
@@ -257,9 +260,7 @@ class RecordArrayManager {
257
260
  } else {
258
261
  changes.set(identifier, 'add');
259
262
 
260
- if (changes.size === 1) {
261
- this.dirtyArray(array);
262
- }
263
+ this.dirtyArray(array, changes.size);
263
264
  }
264
265
  });
265
266
  }
@@ -275,9 +276,7 @@ class RecordArrayManager {
275
276
  } else {
276
277
  changes.set(identifier, 'del');
277
278
 
278
- if (changes.size === 1) {
279
- this.dirtyArray(array);
280
- }
279
+ this.dirtyArray(array, changes.size);
281
280
  }
282
281
  });
283
282
  }
@@ -76,7 +76,7 @@ export class NonSingletonRecordDataManager implements RecordData {
76
76
  {
77
77
  id: 'ember-data:deprecate-v1-cache',
78
78
  until: '5.0',
79
- since: { available: '4.8', enabled: '4.8' },
79
+ since: { available: '4.7', enabled: '4.7' },
80
80
  for: 'ember-data',
81
81
  }
82
82
  );
@@ -414,7 +414,7 @@ export class NonSingletonRecordDataManager implements RecordData {
414
414
  * @method hasChangedAttributes
415
415
  * @public
416
416
  * @deprecated
417
- * @returns
417
+ * @returns {boolean}
418
418
  */
419
419
  hasChangedAttributes(): boolean {
420
420
  const recordData = this.#recordData;
@@ -429,7 +429,7 @@ export class NonSingletonRecordDataManager implements RecordData {
429
429
  * @method hasChangedAttrs
430
430
  * @public
431
431
  * @param identifier
432
- * @returns
432
+ * @returns {boolean}
433
433
  */
434
434
  hasChangedAttrs(identifier: StableRecordIdentifier): boolean {
435
435
  const recordData = this.#recordData;
@@ -99,7 +99,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
99
99
  id: 'ember-data:deprecate-v1cache-store-apis',
100
100
  for: 'ember-data',
101
101
  until: '5.0',
102
- since: { enabled: '4.8', available: '4.8' },
102
+ since: { enabled: '4.7', available: '4.7' },
103
103
  });
104
104
  }
105
105
  const resource = constructResource(type, id, lid);
@@ -117,7 +117,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
117
117
  id: 'ember-data:deprecate-v1cache-store-apis',
118
118
  for: 'ember-data',
119
119
  until: '5.0',
120
- since: { enabled: '4.8', available: '4.8' },
120
+ since: { enabled: '4.7', available: '4.7' },
121
121
  }
122
122
  );
123
123
  }
@@ -133,7 +133,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
133
133
  id: 'ember-data:deprecate-v1cache-store-apis',
134
134
  for: 'ember-data',
135
135
  until: '5.0',
136
- since: { enabled: '4.8', available: '4.8' },
136
+ since: { enabled: '4.7', available: '4.7' },
137
137
  }
138
138
  );
139
139
  }
@@ -152,7 +152,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
152
152
  id: 'ember-data:deprecate-v1cache-store-apis',
153
153
  for: 'ember-data',
154
154
  until: '5.0',
155
- since: { enabled: '4.8', available: '4.8' },
155
+ since: { enabled: '4.7', available: '4.7' },
156
156
  });
157
157
  }
158
158
  const resource = constructResource(type, id, lid);
@@ -169,7 +169,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
169
169
  id: 'ember-data:deprecate-v1cache-store-apis',
170
170
  for: 'ember-data',
171
171
  until: '5.0',
172
- since: { enabled: '4.8', available: '4.8' },
172
+ since: { enabled: '4.7', available: '4.7' },
173
173
  });
174
174
  }
175
175
  const resource = constructResource(type, id, lid);
@@ -185,7 +185,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
185
185
  id: 'ember-data:deprecate-v1cache-store-apis',
186
186
  for: 'ember-data',
187
187
  until: '5.0',
188
- since: { enabled: '4.8', available: '4.8' },
188
+ since: { enabled: '4.7', available: '4.7' },
189
189
  });
190
190
  }
191
191
  const resource = constructResource(type, id, lid);
@@ -202,7 +202,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
202
202
  id: 'ember-data:deprecate-v1cache-store-apis',
203
203
  for: 'ember-data',
204
204
  until: '5.0',
205
- since: { enabled: '4.8', available: '4.8' },
205
+ since: { enabled: '4.7', available: '4.7' },
206
206
  });
207
207
  }
208
208
  const resource = constructResource(type, id, lid);
@@ -277,7 +277,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
277
277
  id: 'ember-data:deprecate-v1cache-store-apis',
278
278
  for: 'ember-data',
279
279
  until: '5.0',
280
- since: { enabled: '4.8', available: '4.8' },
280
+ since: { enabled: '4.7', available: '4.7' },
281
281
  });
282
282
  }
283
283
  const resource = constructResource(type, id, lid);
@@ -297,19 +297,23 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
297
297
  disconnectRecord(type: StableRecordIdentifier): void;
298
298
  disconnectRecord(type: string | StableRecordIdentifier, id?: string | null, lid?: string | null): void {
299
299
  let identifier: StableRecordIdentifier;
300
- if (DEPRECATE_V1CACHE_STORE_APIS && typeof type === 'string') {
301
- deprecate(
302
- `StoreWrapper.disconnectRecord(<type>) has been deprecated in favor of StoreWrapper.disconnectRecord(<identifier>)`,
303
- false,
304
- {
305
- id: 'ember-data:deprecate-v1cache-store-apis',
306
- for: 'ember-data',
307
- until: '5.0',
308
- since: { enabled: '4.8', available: '4.8' },
309
- }
310
- );
311
- let resource = constructResource(type, id, lid) as RecordIdentifier;
312
- identifier = this.identifierCache.peekRecordIdentifier(resource)!;
300
+ if (DEPRECATE_V1CACHE_STORE_APIS) {
301
+ if (typeof type === 'string') {
302
+ deprecate(
303
+ `StoreWrapper.disconnectRecord(<type>) has been deprecated in favor of StoreWrapper.disconnectRecord(<identifier>)`,
304
+ false,
305
+ {
306
+ id: 'ember-data:deprecate-v1cache-store-apis',
307
+ for: 'ember-data',
308
+ until: '5.0',
309
+ since: { enabled: '4.7', available: '4.7' },
310
+ }
311
+ );
312
+ let resource = constructResource(type, id, lid) as RecordIdentifier;
313
+ identifier = this.identifierCache.peekRecordIdentifier(resource)!;
314
+ } else {
315
+ identifier = type as StableRecordIdentifier;
316
+ }
313
317
  } else {
314
318
  identifier = type as StableRecordIdentifier;
315
319
  }
@@ -24,9 +24,11 @@ export interface NotificationCallback {
24
24
  // TODO this isn't importable anyway, remove and use a map on the manager?
25
25
  export function unsubscribe(token: UnsubscribeToken) {
26
26
  let identifier = Tokens.get(token);
27
- if (LOG_NOTIFICATIONS && !identifier) {
28
- // eslint-disable-next-line no-console
29
- console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
27
+ if (LOG_NOTIFICATIONS) {
28
+ if (!identifier) {
29
+ // eslint-disable-next-line no-console
30
+ console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
31
+ }
30
32
  }
31
33
  if (identifier) {
32
34
  Tokens.delete(token);
@@ -5,7 +5,7 @@ import { assert, deprecate, warn } from '@ember/debug';
5
5
  import { _backburner as emberBackburner } from '@ember/runloop';
6
6
  import { DEBUG } from '@glimmer/env';
7
7
 
8
- import { importSync } from '@embroider/macros';
8
+ import { importSync, isDevelopingApp } from '@embroider/macros';
9
9
  import { default as RSVP, resolve } from 'rsvp';
10
10
 
11
11
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
@@ -147,7 +147,7 @@ export default class FetchManager {
147
147
 
148
148
  scheduleFetch(identifier: StableExistingRecordIdentifier, options: FindOptions): Promise<StableRecordIdentifier> {
149
149
  // TODO Probably the store should pass in the query object
150
- let shouldTrace = DEBUG && this._store.generateStackTracesForTrackedRequests;
150
+ let shouldTrace = isDevelopingApp() && this._store.generateStackTracesForTrackedRequests;
151
151
 
152
152
  let query: FindRecordQuery = {
153
153
  op: 'findRecord',
@@ -7,8 +7,8 @@ import { importSync } from '@embroider/macros';
7
7
 
8
8
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
9
9
  import { DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS } from '@ember-data/private-build-infra/deprecations';
10
- import type BelongsToRelationship from '@ember-data/record-data/addon/-private/relationships/state/belongs-to';
11
- import type ManyRelationship from '@ember-data/record-data/addon/-private/relationships/state/has-many';
10
+ import type BelongsToRelationship from '@ember-data/record-data/-private/relationships/state/belongs-to';
11
+ import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
12
12
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
13
13
  import type { OptionsHash } from '@ember-data/types/q/minimum-serializer-interface';
14
14
  import type { ChangedAttributesHash } from '@ember-data/types/q/record-data';
@@ -1,6 +1,8 @@
1
1
  import { deprecate } from '@ember/debug';
2
+ import { get } from '@ember/object';
2
3
  import type ComputedProperty from '@ember/object/computed';
3
4
  import { reads } from '@ember/object/computed';
5
+ import { DEBUG } from '@glimmer/env';
4
6
 
5
7
  import { resolve } from 'rsvp';
6
8
 
@@ -105,6 +107,7 @@ function _promiseArray<I, T extends EmberArrayLike<I>>(promise: Promise<T>, labe
105
107
 
106
108
  // constructor is accessed in some internals but not including it in the copyright for the deprecation
107
109
  const ALLOWABLE_METHODS = ['constructor', 'then', 'catch', 'finally'];
110
+ const ALLOWABLE_PROPS = ['__ec_yieldable__', '__ec_cancel__'];
108
111
  const PROXIED_ARRAY_PROPS = [
109
112
  'length',
110
113
  '[]',
@@ -123,11 +126,17 @@ const PROXIED_OBJECT_PROPS = ['content', 'isPending', 'isSettled', 'isRejected',
123
126
 
124
127
  export function promiseArray<I, T extends EmberArrayLike<I>>(promise: Promise<T>): PromiseArray<I, T> {
125
128
  const promiseObjectProxy: PromiseArray<I, T> = _promiseArray(promise);
129
+ if (!DEBUG) {
130
+ return promiseObjectProxy;
131
+ }
126
132
  const handler = {
127
- get(target: object, prop: string, receiver?: object): unknown {
133
+ get(target: object, prop: string, receiver: object): unknown {
128
134
  if (typeof prop === 'symbol') {
129
135
  return Reflect.get(target, prop, receiver);
130
136
  }
137
+ if (ALLOWABLE_PROPS.includes(prop)) {
138
+ return receiver[prop];
139
+ }
131
140
  if (!ALLOWABLE_METHODS.includes(prop)) {
132
141
  deprecate(
133
142
  `Accessing ${prop} on this PromiseArray is deprecated. The return type is being changed from PromiseArray to a Promise. The only available methods to access on this promise are .then, .catch and .finally`,
@@ -137,8 +146,8 @@ export function promiseArray<I, T extends EmberArrayLike<I>>(promise: Promise<T>
137
146
  until: '5.0',
138
147
  for: '@ember-data/store',
139
148
  since: {
140
- available: '4.8',
141
- enabled: '4.8',
149
+ available: '4.7',
150
+ enabled: '4.7',
142
151
  },
143
152
  }
144
153
  );
@@ -160,13 +169,30 @@ export function promiseArray<I, T extends EmberArrayLike<I>>(promise: Promise<T>
160
169
  return new Proxy(promiseObjectProxy, handler);
161
170
  }
162
171
 
172
+ const ProxySymbolString = String(Symbol.for('PROXY_CONTENT'));
173
+
163
174
  export function promiseObject<T>(promise: Promise<T>): PromiseObjectProxy<T> {
164
175
  const promiseObjectProxy: PromiseObjectProxy<T> = _promiseObject(promise);
176
+ if (!DEBUG) {
177
+ return promiseObjectProxy;
178
+ }
165
179
  const handler = {
166
- get(target: object, prop: string, receiver?: object): unknown {
180
+ get(target: object, prop: string, receiver: object): unknown {
167
181
  if (typeof prop === 'symbol') {
182
+ if (String(prop) === ProxySymbolString) {
183
+ return;
184
+ }
168
185
  return Reflect.get(target, prop, receiver);
169
186
  }
187
+
188
+ if (prop === 'constructor') {
189
+ return target.constructor;
190
+ }
191
+
192
+ if (ALLOWABLE_PROPS.includes(prop)) {
193
+ return receiver[prop];
194
+ }
195
+
170
196
  if (!ALLOWABLE_METHODS.includes(prop)) {
171
197
  deprecate(
172
198
  `Accessing ${prop} on this PromiseObject is deprecated. The return type is being changed from PromiseObject to a Promise. The only available methods to access on this promise are .then, .catch and .finally`,
@@ -176,20 +202,22 @@ export function promiseObject<T>(promise: Promise<T>): PromiseObjectProxy<T> {
176
202
  until: '5.0',
177
203
  for: '@ember-data/store',
178
204
  since: {
179
- available: '4.8',
180
- enabled: '4.8',
205
+ available: '4.7',
206
+ enabled: '4.7',
181
207
  },
182
208
  }
183
209
  );
210
+ } else {
211
+ return (target[prop] as () => unknown).bind(target);
184
212
  }
185
213
 
186
- const value: unknown = target[prop];
187
- if (value && typeof value === 'function' && typeof value.bind === 'function') {
188
- return value.bind(target);
214
+ if (PROXIED_OBJECT_PROPS.includes(prop)) {
215
+ return target[prop];
189
216
  }
190
217
 
191
- if (PROXIED_OBJECT_PROPS.includes(prop)) {
192
- return value;
218
+ const value: unknown = get(target, prop);
219
+ if (value && typeof value === 'function' && typeof value.bind === 'function') {
220
+ return value.bind(receiver);
193
221
  }
194
222
 
195
223
  return undefined;
@@ -15,6 +15,7 @@ import {
15
15
  DEPRECATE_PROMISE_PROXIES,
16
16
  DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS,
17
17
  } from '@ember-data/private-build-infra/deprecations';
18
+ import { addToTransaction, subscribe } from '@ember-data/tracking/-private';
18
19
  import { Links, PaginationLinks } from '@ember-data/types/q/ember-data-json-api';
19
20
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
20
21
  import type { RecordInstance } from '@ember-data/types/q/record-instance';
@@ -76,6 +77,7 @@ function convertToInt(prop: KeyType): number | null {
76
77
  class Tag {
77
78
  @tracked ref = null;
78
79
  shouldReset: boolean = false;
80
+ t = false;
79
81
  }
80
82
 
81
83
  type ProxiedMethod = (...args: unknown[]) => unknown;
@@ -102,7 +104,7 @@ function deprecateArrayLike(className: string, fnName: string, replName: string)
102
104
  {
103
105
  id: 'ember-data:deprecate-array-like',
104
106
  until: '5.0',
105
- since: { enabled: '4.8', available: '4.8' },
107
+ since: { enabled: '4.7', available: '4.7' },
106
108
  for: 'ember-data',
107
109
  }
108
110
  );
@@ -219,27 +221,28 @@ class IdentifierArray {
219
221
  let index = convertToInt(prop);
220
222
  if (_TAG.shouldReset && (index !== null || SYNC_PROPS.has(prop) || isArrayGetter(prop))) {
221
223
  options.manager._syncArray(receiver as unknown as IdentifierArray);
224
+ _TAG.t = false;
222
225
  _TAG.shouldReset = false;
223
226
  }
224
227
 
225
228
  if (index !== null) {
226
229
  const identifier = target[index];
227
230
  if (!transaction) {
228
- _TAG.ref;
231
+ subscribe(_TAG);
229
232
  }
230
233
  return identifier && store._instanceCache.getRecord(identifier);
231
234
  }
232
235
 
233
- if (prop === 'meta') return _TAG.ref, PrivateState.meta;
234
- if (prop === 'links') return _TAG.ref, PrivateState.links;
235
- if (prop === '[]') return _TAG.ref, receiver;
236
+ if (prop === 'meta') return subscribe(_TAG), PrivateState.meta;
237
+ if (prop === 'links') return subscribe(_TAG), PrivateState.links;
238
+ if (prop === '[]') return subscribe(_TAG), receiver;
236
239
 
237
240
  if (isArrayGetter(prop)) {
238
241
  let fn = boundFns.get(prop);
239
242
 
240
243
  if (fn === undefined) {
241
244
  fn = function () {
242
- _TAG.ref;
245
+ subscribe(_TAG);
243
246
  // array functions must run through Reflect to work properly
244
247
  // binding via other means will not work.
245
248
  transaction = true;
@@ -270,7 +273,7 @@ class IdentifierArray {
270
273
  transaction = true;
271
274
  let result = Reflect.apply(target[prop] as ProxiedMethod, receiver, args) as unknown;
272
275
  self[MUTATE]!(prop as string, args, result);
273
- _TAG.ref = null;
276
+ addToTransaction(_TAG);
274
277
  // TODO handle cache updates
275
278
  transaction = false;
276
279
  return result;
@@ -286,10 +289,10 @@ class IdentifierArray {
286
289
  if (DEPRECATE_ARRAY_LIKE) {
287
290
  if (prop === 'firstObject') {
288
291
  deprecateArrayLike(self.DEPRECATED_CLASS_NAME, prop, '[0]');
289
- return receiver.at(0);
292
+ return receiver[0];
290
293
  } else if (prop === 'lastObject') {
291
294
  deprecateArrayLike(self.DEPRECATED_CLASS_NAME, prop, 'at(-1)');
292
- return receiver.at(-1);
295
+ return receiver[receiver.length - 1];
293
296
  }
294
297
  }
295
298
 
@@ -300,7 +303,7 @@ class IdentifierArray {
300
303
 
301
304
  if (typeof outcome === 'function') {
302
305
  fn = function () {
303
- _TAG.ref;
306
+ subscribe(_TAG);
304
307
  // array functions must run through Reflect to work properly
305
308
  // binding via other means will not work.
306
309
  return Reflect.apply(outcome as ProxiedMethod, receiver, arguments) as unknown;
@@ -310,7 +313,7 @@ class IdentifierArray {
310
313
  return fn;
311
314
  }
312
315
 
313
- return _TAG.ref, outcome;
316
+ return subscribe(_TAG), outcome;
314
317
  }
315
318
 
316
319
  return target[prop];
@@ -320,7 +323,7 @@ class IdentifierArray {
320
323
  if (prop === 'length') {
321
324
  if (!transaction && value === 0) {
322
325
  transaction = true;
323
- _TAG.ref = null;
326
+ addToTransaction(_TAG);
324
327
  Reflect.set(target, prop, value);
325
328
  self[MUTATE]!('length 0', []);
326
329
  transaction = false;
@@ -359,7 +362,7 @@ class IdentifierArray {
359
362
  (target as unknown as Record<KeyType, unknown>)[index] = newIdentifier;
360
363
  if (!transaction) {
361
364
  self[MUTATE]!('replace cell', [index, original, newIdentifier]);
362
- _TAG.ref = null;
365
+ addToTransaction(_TAG);
363
366
  }
364
367
 
365
368
  return true;
@@ -384,7 +387,7 @@ class IdentifierArray {
384
387
  deprecate(`Do not call A() on EmberData RecordArrays`, false, {
385
388
  id: 'ember-data:no-a-with-array-like',
386
389
  until: '5.0',
387
- since: { enabled: '4.8', available: '4.8' },
390
+ since: { enabled: '4.7', available: '4.7' },
388
391
  for: 'ember-data',
389
392
  });
390
393
  // @ts-expect-error ArrayMixin is more than a type
@@ -567,7 +570,7 @@ if (DEPRECATE_ARRAY_LIKE) {
567
570
  {
568
571
  id: 'ember-data:deprecate-array-like',
569
572
  until: '5.0',
570
- since: { enabled: '4.8', available: '4.8' },
573
+ since: { enabled: '4.7', available: '4.7' },
571
574
  for: 'ember-data',
572
575
  }
573
576
  );
@@ -631,12 +634,14 @@ if (DEPRECATE_ARRAY_LIKE) {
631
634
 
632
635
  IdentifierArray.prototype.objectAt = function (index: number) {
633
636
  deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'objectAt', 'at');
634
- return this.at(index);
637
+ //For negative index values go back from the end of the array
638
+ let arrIndex = Math.sign(index) === -1 ? this.length + index : index;
639
+ return this[arrIndex];
635
640
  };
636
641
 
637
642
  IdentifierArray.prototype.objectsAt = function (indeces: number[]) {
638
643
  deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'objectsAt', 'at');
639
- return indeces.map((index) => this.at(index)!);
644
+ return indeces.map((index) => this.objectAt(index)!);
640
645
  };
641
646
 
642
647
  IdentifierArray.prototype.removeAt = function (index: number) {
@@ -664,7 +669,7 @@ if (DEPRECATE_ARRAY_LIKE) {
664
669
  };
665
670
 
666
671
  IdentifierArray.prototype.toArray = function () {
667
- deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'unshiftObjects', 'unshift');
672
+ deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'toArray', 'slice');
668
673
  return this.slice();
669
674
  };
670
675
 
@@ -746,12 +751,12 @@ if (DEPRECATE_ARRAY_LIKE) {
746
751
  IdentifierArray.prototype.filterBy = function (key: string, value?: unknown) {
747
752
  deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'filterBy', 'filter');
748
753
  if (arguments.length === 2) {
749
- return this.filter((value) => {
750
- return Boolean(get(value, key));
754
+ return this.filter((record) => {
755
+ return get(record, key) === value;
751
756
  });
752
757
  }
753
- return this.filter((value) => {
754
- return Boolean(get(value, key));
758
+ return this.filter((record) => {
759
+ return Boolean(get(record, key));
755
760
  });
756
761
  };
757
762
 
@@ -13,6 +13,7 @@ import { reject, resolve } from 'rsvp';
13
13
 
14
14
  import type DSModelClass from '@ember-data/model';
15
15
  import { HAS_MODEL_PACKAGE, HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
16
+ import { LOG_PAYLOADS } from '@ember-data/private-build-infra/debugging';
16
17
  import {
17
18
  DEPRECATE_HAS_RECORD,
18
19
  DEPRECATE_JSON_API_FALLBACK,
@@ -72,6 +73,7 @@ import promiseRecord from './utils/promise-record';
72
73
 
73
74
  export { storeFor };
74
75
 
76
+ // hello world
75
77
  type RecordDataConstruct = typeof RecordDataClass;
76
78
  let _RecordData: RecordDataConstruct | undefined;
77
79
 
@@ -2119,6 +2121,16 @@ class Store extends Service {
2119
2121
  if (DEBUG) {
2120
2122
  assertDestroyingStore(this, '_push');
2121
2123
  }
2124
+ if (LOG_PAYLOADS) {
2125
+ try {
2126
+ let data = JSON.parse(JSON.stringify(jsonApiDoc));
2127
+ // eslint-disable-next-line no-console
2128
+ console.log('EmberData | Payload - push', data);
2129
+ } catch (e) {
2130
+ // eslint-disable-next-line no-console
2131
+ console.log('EmberData | Payload - push', jsonApiDoc);
2132
+ }
2133
+ }
2122
2134
  let ret;
2123
2135
  this._join(() => {
2124
2136
  let included = jsonApiDoc.included;
@@ -2300,6 +2312,16 @@ class Store extends Service {
2300
2312
  let fetchManagerPromise = this._fetchManager.scheduleSave(identifier, saveOptions);
2301
2313
  return fetchManagerPromise.then(
2302
2314
  (payload) => {
2315
+ if (LOG_PAYLOADS) {
2316
+ try {
2317
+ let data = payload ? JSON.parse(JSON.stringify(payload)) : payload;
2318
+ // eslint-disable-next-line no-console
2319
+ console.log(`EmberData | Payload - ${operation}`, data);
2320
+ } catch (e) {
2321
+ // eslint-disable-next-line no-console
2322
+ console.log(`EmberData | Payload - ${operation}`, payload);
2323
+ }
2324
+ }
2303
2325
  /*
2304
2326
  // TODO @runspired re-evaluate the below claim now that
2305
2327
  // the save request pipeline is more streamlined.
@@ -2376,30 +2398,32 @@ class Store extends Service {
2376
2398
  // a cycle we can't easily fix (or clearly pin point) at present.
2377
2399
  //
2378
2400
  // it can be reproduced in partner tests by running
2379
- // node ./scripts/packages-for-commit.js && yarn test-external:ember-observer
2401
+ // node ./scripts/packages-for-commit.js && pnpm test-external:ember-observer
2380
2402
  if (_RecordData === undefined) {
2381
2403
  _RecordData = (
2382
2404
  importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
2383
2405
  ).RecordData;
2384
2406
  }
2385
2407
 
2386
- if (DEPRECATE_V1CACHE_STORE_APIS && arguments.length === 4) {
2387
- deprecate(
2388
- `Store.createRecordDataFor(<type>, <id>, <lid>, <storeWrapper>) has been deprecated in favor of Store.createRecordDataFor(<identifier>, <storeWrapper>)`,
2389
- false,
2390
- {
2391
- id: 'ember-data:deprecate-v1cache-store-apis',
2392
- for: 'ember-data',
2393
- until: '5.0',
2394
- since: { enabled: '4.8', available: '4.8' },
2395
- }
2396
- );
2397
- identifier = this.identifierCache.getOrCreateRecordIdentifier({
2398
- type: arguments[0],
2399
- id: arguments[1],
2400
- lid: arguments[2],
2401
- });
2402
- storeWrapper = arguments[3];
2408
+ if (DEPRECATE_V1CACHE_STORE_APIS) {
2409
+ if (arguments.length === 4) {
2410
+ deprecate(
2411
+ `Store.createRecordDataFor(<type>, <id>, <lid>, <storeWrapper>) has been deprecated in favor of Store.createRecordDataFor(<identifier>, <storeWrapper>)`,
2412
+ false,
2413
+ {
2414
+ id: 'ember-data:deprecate-v1cache-store-apis',
2415
+ for: 'ember-data',
2416
+ until: '5.0',
2417
+ since: { enabled: '4.7', available: '4.7' },
2418
+ }
2419
+ );
2420
+ identifier = this.identifierCache.getOrCreateRecordIdentifier({
2421
+ type: arguments[0],
2422
+ id: arguments[1],
2423
+ lid: arguments[2],
2424
+ });
2425
+ storeWrapper = arguments[3];
2426
+ }
2403
2427
  }
2404
2428
 
2405
2429
  this.__private_singleton_recordData = this.__private_singleton_recordData || new _RecordData(storeWrapper);
@@ -2829,26 +2853,28 @@ function extractIdentifierFromRecord(
2829
2853
  }
2830
2854
  const extract = isForV1 ? recordDataFor : recordIdentifierFor;
2831
2855
 
2832
- if (DEPRECATE_PROMISE_PROXIES && isPromiseRecord(recordOrPromiseRecord)) {
2833
- let content = recordOrPromiseRecord.content;
2834
- assert(
2835
- 'You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.',
2836
- content !== undefined
2837
- );
2838
- deprecate(
2839
- `You passed in a PromiseProxy to a Relationship API that now expects a resolved value. await the value before setting it.`,
2840
- false,
2841
- {
2842
- id: 'ember-data:deprecate-promise-proxies',
2843
- until: '5.0',
2844
- since: {
2845
- enabled: '4.8',
2846
- available: '4.8',
2847
- },
2848
- for: 'ember-data',
2849
- }
2850
- );
2851
- return content ? extract(content) : null;
2856
+ if (DEPRECATE_PROMISE_PROXIES) {
2857
+ if (isPromiseRecord(recordOrPromiseRecord)) {
2858
+ let content = recordOrPromiseRecord.content;
2859
+ assert(
2860
+ 'You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.',
2861
+ content !== undefined
2862
+ );
2863
+ deprecate(
2864
+ `You passed in a PromiseProxy to a Relationship API that now expects a resolved value. await the value before setting it.`,
2865
+ false,
2866
+ {
2867
+ id: 'ember-data:deprecate-promise-proxies',
2868
+ until: '5.0',
2869
+ since: {
2870
+ enabled: '4.7',
2871
+ available: '4.7',
2872
+ },
2873
+ for: 'ember-data',
2874
+ }
2875
+ );
2876
+ return content ? extract(content) : null;
2877
+ }
2852
2878
  }
2853
2879
 
2854
2880
  return extract(recordOrPromiseRecord);
package/index.js CHANGED
@@ -13,7 +13,7 @@ module.exports = Object.assign({}, addonBaseConfig, {
13
13
  'ember-cached-decorator-polyfill',
14
14
 
15
15
  '@ember-data/canary-features',
16
- '@ember-data/store/-debug',
16
+ '@ember-data/tracking/-private',
17
17
 
18
18
  '@ember/application',
19
19
  '@ember/array/proxy',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ember-data/store",
3
- "version": "4.8.0-beta.0",
3
+ "version": "4.8.0",
4
4
  "description": "The core of EmberData. Provides the Store service which coordinates the cache with the network and presentation layers.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -12,61 +12,50 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "",
15
- "directories": {
16
- "doc": "doc",
17
- "test": "tests"
15
+ "directories": {},
16
+ "peerDependencies": {
17
+ "@ember-data/model": "workspace:4.9.0-alpha.6",
18
+ "@ember-data/record-data": "workspace:4.9.0-alpha.6",
19
+ "@ember-data/tracking": "workspace:4.9.0-alpha.6",
20
+ "@ember/string": "^3.0.0",
21
+ "@glimmer/tracking": "^1.1.2"
22
+ },
23
+ "peerDependenciesMeta": {
24
+ "@ember-data/record-data": {
25
+ "optional": true
26
+ },
27
+ "@ember-data/model": {
28
+ "optional": true
29
+ }
18
30
  },
19
- "scripts": {
20
- "build": "ember build",
21
- "start": "ember serve"
31
+ "dependenciesMeta": {
32
+ "@ember-data/canary-features": {
33
+ "injected": true
34
+ },
35
+ "@ember-data/private-build-infra": {
36
+ "injected": true
37
+ }
22
38
  },
23
39
  "dependencies": {
24
- "@ember-data/canary-features": "4.8.0-beta.0",
25
- "@ember-data/private-build-infra": "4.8.0-beta.0",
26
- "@ember/string": "^3.0.0",
27
- "@embroider/macros": "^1.8.3",
28
- "@glimmer/tracking": "^1.1.2",
29
- "ember-auto-import": "^2.4.2",
30
- "ember-cached-decorator-polyfill": "^0.1.4",
31
- "ember-cli-babel": "^7.26.11",
32
- "ember-cli-path-utils": "^1.0.0",
33
- "ember-cli-typescript": "^5.1.0"
40
+ "@ember-data/canary-features": "workspace:4.8.0",
41
+ "@ember-data/private-build-infra": "workspace:4.8.0",
42
+ "@embroider/macros": "^1.9.0",
43
+ "ember-auto-import": "^2.4.3",
44
+ "ember-cached-decorator-polyfill": "^1.0.1",
45
+ "ember-cli-babel": "^7.26.11"
34
46
  },
35
47
  "devDependencies": {
36
- "@ember-data/unpublished-test-infra": "4.8.0-beta.0",
37
- "@ember/optional-features": "^2.0.0",
38
- "@ember/test-helpers": "~2.7.0",
39
- "@types/ember": "^4.0.1",
40
- "@types/rsvp": "^4.0.4",
41
- "broccoli-asset-rev": "^3.0.0",
42
- "ember-cli": "~4.6.0",
43
- "ember-cli-dependency-checker": "^3.3.1",
44
- "ember-cli-htmlbars": "^6.1.0",
45
- "ember-cli-inject-live-reload": "^2.1.0",
46
- "ember-cli-sri": "^2.1.1",
47
- "ember-cli-terser": "~4.0.2",
48
- "ember-disable-prototype-extensions": "^1.1.3",
49
- "ember-export-application-global": "^2.0.1",
50
- "ember-load-initializers": "^2.1.2",
51
- "ember-maybe-import-regenerator": "^1.0.0",
52
- "ember-qunit": "^5.1.5",
53
- "ember-resolver": "^8.0.3",
54
- "ember-source": "~4.6.0",
55
- "ember-source-channel-url": "^3.0.0",
56
- "ember-try": "^2.0.0",
57
- "loader.js": "^4.7.0",
58
- "qunit": "^2.19.1",
59
- "qunit-dom": "^2.0.0",
48
+ "@babel/core": "^7.19.6",
49
+ "@glimmer/component": "^1.1.2",
50
+ "ember-source": "~4.8.0",
60
51
  "webpack": "^5.74.0"
61
52
  },
62
53
  "engines": {
63
54
  "node": "^14.8.0 || 16.* || >= 18.*"
64
55
  },
65
- "ember-addon": {
66
- "configPath": "tests/dummy/config"
67
- },
56
+ "ember-addon": {},
68
57
  "volta": {
69
- "node": "16.17.0",
70
- "yarn": "1.22.19"
71
- }
58
+ "extends": "../../package.json"
59
+ },
60
+ "packageManager": "pnpm@7.14.1"
72
61
  }
@@ -1,69 +0,0 @@
1
- import { assert } from '@ember/debug';
2
- import { DEBUG } from '@glimmer/env';
3
-
4
- import { DEPRECATE_NON_EXPLICIT_POLYMORPHISM } from '@ember-data/private-build-infra/deprecations';
5
-
6
- /*
7
- Assert that `addedRecord` has a valid type so it can be added to the
8
- relationship of the `record`.
9
-
10
- The assert basically checks if the `addedRecord` can be added to the
11
- relationship (specified via `relationshipMeta`) of the `record`.
12
-
13
- This utility should only be used internally, as both record parameters must
14
- be stable record identifiers and the `relationshipMeta` needs to be the meta
15
- information about the relationship, retrieved via
16
- `record.relationshipFor(key)`.
17
- */
18
- let assertPolymorphicType;
19
-
20
- if (DEBUG) {
21
- let checkPolymorphic = function checkPolymorphic(modelClass, addedModelClass) {
22
- if (modelClass.__isMixin) {
23
- return (
24
- modelClass.__mixin.detect(addedModelClass.PrototypeMixin) ||
25
- // handle native class extension e.g. `class Post extends Model.extend(Commentable) {}`
26
- modelClass.__mixin.detect(Object.getPrototypeOf(addedModelClass).PrototypeMixin)
27
- );
28
- }
29
-
30
- return addedModelClass.prototype instanceof modelClass || modelClass.detect(addedModelClass);
31
- };
32
-
33
- assertPolymorphicType = function assertPolymorphicType(parentIdentifier, parentDefinition, addedIdentifier, store) {
34
- let asserted = false;
35
-
36
- if (parentDefinition.inverseIsImplicit) {
37
- return;
38
- }
39
- if (parentDefinition.isPolymorphic) {
40
- let meta = store.getSchemaDefinitionService().relationshipsDefinitionFor(addedIdentifier)[
41
- parentDefinition.inverseKey
42
- ];
43
- if (meta?.options?.as) {
44
- asserted = true;
45
- assert(
46
- `The schema for the relationship '${parentDefinition.inverseKey}' on '${addedIdentifier.type}' type does not implement '${parentDefinition.type}' and thus cannot be assigned to the '${parentDefinition.key}' relationship in '${parentIdentifier.type}'. The definition should specify 'as: "${parentDefinition.type}"' in options.`,
47
- meta.options.as === parentDefinition.type
48
- );
49
- }
50
- }
51
-
52
- if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM && !asserted) {
53
- store = store._store ? store._store : store; // allow usage with storeWrapper
54
- let addedModelName = addedIdentifier.type;
55
- let parentModelName = parentIdentifier.type;
56
- let key = parentDefinition.key;
57
- let relationshipModelName = parentDefinition.type;
58
- let relationshipClass = store.modelFor(relationshipModelName);
59
- let addedClass = store.modelFor(addedModelName);
60
-
61
- let assertionMessage = `The '${addedModelName}' type does not implement '${relationshipModelName}' and thus cannot be assigned to the '${key}' relationship in '${parentModelName}'. Make it a descendant of '${relationshipModelName}' or use a mixin of the same name.`;
62
- let isPolymorphic = checkPolymorphic(relationshipClass, addedClass);
63
-
64
- assert(assertionMessage, isPolymorphic);
65
- }
66
- };
67
- }
68
-
69
- export { assertPolymorphicType };
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = function (/* environment, appConfig */) {
4
- return {};
5
- };