@ember-data/store 4.6.1 → 4.7.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.
Files changed (45) hide show
  1. package/addon/-debug/index.js +35 -13
  2. package/addon/-private/{identifier-cache.ts → caches/identifier-cache.ts} +148 -73
  3. package/addon/-private/caches/instance-cache.ts +690 -0
  4. package/addon/-private/{record-data-for.ts → caches/record-data-for.ts} +2 -7
  5. package/addon/-private/index.ts +44 -24
  6. package/addon/-private/{model → legacy-model-support}/record-reference.ts +15 -13
  7. package/addon/-private/{schema-definition-service.ts → legacy-model-support/schema-definition-service.ts} +13 -9
  8. package/addon/-private/{model → legacy-model-support}/shim-model-class.ts +18 -11
  9. package/addon/-private/managers/record-array-manager.ts +377 -0
  10. package/addon/-private/managers/record-data-manager.ts +845 -0
  11. package/addon/-private/managers/record-data-store-wrapper.ts +421 -0
  12. package/addon/-private/managers/record-notification-manager.ts +109 -0
  13. package/addon/-private/network/fetch-manager.ts +567 -0
  14. package/addon/-private/{finders.js → network/finders.js} +14 -17
  15. package/addon/-private/{request-cache.ts → network/request-cache.ts} +21 -18
  16. package/addon/-private/{snapshot-record-array.ts → network/snapshot-record-array.ts} +14 -31
  17. package/addon/-private/{snapshot.ts → network/snapshot.ts} +40 -49
  18. package/addon/-private/{promise-proxies.ts → proxies/promise-proxies.ts} +76 -15
  19. package/addon/-private/{promise-proxy-base.js → proxies/promise-proxy-base.js} +0 -0
  20. package/addon/-private/record-arrays/identifier-array.ts +924 -0
  21. package/addon/-private/{core-store.ts → store-service.ts} +574 -215
  22. package/addon/-private/{coerce-id.ts → utils/coerce-id.ts} +1 -1
  23. package/addon/-private/{common.js → utils/common.js} +1 -2
  24. package/addon/-private/utils/construct-resource.ts +2 -2
  25. package/addon/-private/{identifer-debug-consts.ts → utils/identifer-debug-consts.ts} +0 -0
  26. package/addon/-private/utils/is-non-empty-string.ts +1 -1
  27. package/addon/-private/{normalize-model-name.ts → utils/normalize-model-name.ts} +1 -3
  28. package/addon/-private/utils/promise-record.ts +5 -6
  29. package/addon/-private/{serializer-response.ts → utils/serializer-response.ts} +2 -2
  30. package/addon/-private/utils/uuid-polyfill.ts +73 -0
  31. package/package.json +12 -8
  32. package/addon/-private/backburner.js +0 -25
  33. package/addon/-private/errors-utils.js +0 -146
  34. package/addon/-private/fetch-manager.ts +0 -597
  35. package/addon/-private/identity-map.ts +0 -54
  36. package/addon/-private/instance-cache.ts +0 -387
  37. package/addon/-private/internal-model-factory.ts +0 -359
  38. package/addon/-private/internal-model-map.ts +0 -121
  39. package/addon/-private/model/internal-model.ts +0 -602
  40. package/addon/-private/record-array-manager.ts +0 -444
  41. package/addon/-private/record-arrays/adapter-populated-record-array.ts +0 -130
  42. package/addon/-private/record-arrays/record-array.ts +0 -318
  43. package/addon/-private/record-data-store-wrapper.ts +0 -243
  44. package/addon/-private/record-notification-manager.ts +0 -73
  45. package/addon/-private/weak-cache.ts +0 -125
@@ -35,7 +35,7 @@ export function ensureStringId(id: Coercable): string {
35
35
  throw new Error(`Expected id to be a string or number, received ${String(id)}`);
36
36
  }
37
37
 
38
- return normalized!;
38
+ return normalized;
39
39
  }
40
40
 
41
41
  export default coerceId;
@@ -1,5 +1,4 @@
1
1
  import { deprecate } from '@ember/debug';
2
- import { get } from '@ember/object';
3
2
  import { DEBUG } from '@glimmer/env';
4
3
 
5
4
  import { resolve } from 'rsvp';
@@ -27,7 +26,7 @@ export function _guard(promise, test) {
27
26
  }
28
27
 
29
28
  export function _objectIsAlive(object) {
30
- return !(get(object, 'isDestroyed') || get(object, 'isDestroying'));
29
+ return !(object.isDestroyed || object.isDestroying);
31
30
  }
32
31
 
33
32
  export function guardDestroyedStore(promise, store, label) {
@@ -5,8 +5,8 @@ import type {
5
5
  ResourceIdentifierObject,
6
6
  } from '@ember-data/types/q/ember-data-json-api';
7
7
 
8
- import coerceId from '../coerce-id';
9
- import { isStableIdentifier } from '../identifier-cache';
8
+ import { isStableIdentifier } from '../caches/identifier-cache';
9
+ import coerceId from './coerce-id';
10
10
  import isNonEmptyString from './is-non-empty-string';
11
11
 
12
12
  function constructResource(type: ResourceIdentifierObject): ResourceIdentifierObject;
@@ -1,3 +1,3 @@
1
1
  export default function isNonEmptyString(str: any): str is string {
2
- return typeof str === 'string' && str.length > 0;
2
+ return str && typeof str === 'string';
3
3
  }
@@ -4,9 +4,6 @@ import { dasherize } from '@ember/string';
4
4
  @module @ember-data/store
5
5
  */
6
6
 
7
- // All modelNames are dasherized internally. Changing this function may
8
- // require changes to other normalization hooks (such as typeForRoot).
9
-
10
7
  /**
11
8
  This method normalizes a modelName into the format Ember Data uses
12
9
  internally by dasherizing it.
@@ -14,6 +11,7 @@ import { dasherize } from '@ember/string';
14
11
  @method normalizeModelName
15
12
  @static
16
13
  @public
14
+ @deprecated
17
15
  @for @ember-data/store
18
16
  @param {String} modelName
19
17
  @return {String} normalizedModelName
@@ -1,16 +1,15 @@
1
1
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
2
2
  import type { RecordInstance } from '@ember-data/types/q/record-instance';
3
3
 
4
- import type Store from '../core-store';
5
- import type { PromiseObject } from '../promise-proxies';
6
- import { promiseObject } from '../promise-proxies';
4
+ import type { PromiseObject } from '../proxies/promise-proxies';
5
+ import { promiseObject } from '../proxies/promise-proxies';
6
+ import type Store from '../store-service';
7
7
 
8
8
  export default function promiseRecord(
9
9
  store: Store,
10
- promise: Promise<StableRecordIdentifier>,
11
- label?: string
10
+ promise: Promise<StableRecordIdentifier>
12
11
  ): PromiseObject<RecordInstance> {
13
12
  let toReturn = promise.then((identifier: StableRecordIdentifier) => store.peekRecord(identifier)!);
14
13
 
15
- return promiseObject(toReturn, label);
14
+ return promiseObject(toReturn);
16
15
  }
@@ -5,8 +5,8 @@ import type { JsonApiDocument } from '@ember-data/types/q/ember-data-json-api';
5
5
  import type { AdapterPayload } from '@ember-data/types/q/minimum-adapter-interface';
6
6
  import type { MinimumSerializerInterface, RequestType } from '@ember-data/types/q/minimum-serializer-interface';
7
7
 
8
- import type Store from './core-store';
9
- import type ShimModelClass from './model/shim-model-class';
8
+ import type ShimModelClass from '../legacy-model-support/shim-model-class';
9
+ import type Store from '../store-service';
10
10
 
11
11
  /**
12
12
  This is a helper method that validates a JSON API top-level document
@@ -0,0 +1,73 @@
1
+ /**
2
+ @module @ember-data/store
3
+ */
4
+ interface FastbootCrypto {
5
+ randomFillSync(v: Uint8Array): Uint8Array;
6
+ }
7
+
8
+ export default function installPolyfill() {
9
+ const isFastBoot = typeof FastBoot !== 'undefined';
10
+ const CRYPTO: Crypto = isFastBoot ? (FastBoot.require('crypto') as Crypto) : window.crypto;
11
+
12
+ if (!CRYPTO.randomUUID) {
13
+ // we might be able to optimize this by requesting more bytes than we need at a time
14
+ const rng = function (): Uint8Array {
15
+ // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
16
+ let rnds8 = new Uint8Array(16);
17
+
18
+ if (!CRYPTO.getRandomValues && !isFastBoot) {
19
+ throw new Error(`Unable to generate bytes for UUID`);
20
+ }
21
+
22
+ return CRYPTO.getRandomValues
23
+ ? CRYPTO.getRandomValues(rnds8)
24
+ : (CRYPTO as unknown as FastbootCrypto).randomFillSync(rnds8);
25
+ };
26
+
27
+ /*
28
+ * Convert array of 16 byte values to UUID string format of the form:
29
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
30
+ */
31
+ const byteToHex: string[] = [];
32
+ for (let i = 0; i < 256; ++i) {
33
+ byteToHex[i] = (i + 0x100).toString(16).substr(1);
34
+ }
35
+
36
+ const bytesToUuid = function (buf: Uint8Array) {
37
+ let bth = byteToHex;
38
+ // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
39
+ return [
40
+ bth[buf[0]],
41
+ bth[buf[1]],
42
+ bth[buf[2]],
43
+ bth[buf[3]],
44
+ '-',
45
+ bth[buf[4]],
46
+ bth[buf[5]],
47
+ '-',
48
+ bth[buf[6]],
49
+ bth[buf[7]],
50
+ '-',
51
+ bth[buf[8]],
52
+ bth[buf[9]],
53
+ '-',
54
+ bth[buf[10]],
55
+ bth[buf[11]],
56
+ bth[buf[12]],
57
+ bth[buf[13]],
58
+ bth[buf[14]],
59
+ bth[buf[15]],
60
+ ].join('');
61
+ };
62
+
63
+ CRYPTO.randomUUID = function uuidv4(): string {
64
+ let rnds = rng();
65
+
66
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
67
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
68
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
69
+
70
+ return bytesToUuid(rnds);
71
+ };
72
+ }
73
+ }
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "@ember-data/store",
3
- "version": "4.6.1",
4
- "description": "The default blueprint for ember-cli addons.",
3
+ "version": "4.7.0",
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"
7
7
  ],
8
- "repository": "https://github.com/emberjs/data/tree/master/packages/store",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+ssh://git@github.com:emberjs/data.git",
11
+ "directory": "packages/store"
12
+ },
9
13
  "license": "MIT",
10
14
  "author": "",
11
15
  "directories": {
@@ -17,8 +21,8 @@
17
21
  "start": "ember serve"
18
22
  },
19
23
  "dependencies": {
20
- "@ember-data/canary-features": "4.6.1",
21
- "@ember-data/private-build-infra": "4.6.1",
24
+ "@ember-data/canary-features": "4.7.0",
25
+ "@ember-data/private-build-infra": "4.7.0",
22
26
  "@ember/string": "^3.0.0",
23
27
  "@embroider/macros": "^1.8.3",
24
28
  "@glimmer/tracking": "^1.1.2",
@@ -29,10 +33,10 @@
29
33
  "ember-cli-typescript": "^5.1.0"
30
34
  },
31
35
  "devDependencies": {
32
- "@ember-data/unpublished-test-infra": "4.6.1",
36
+ "@ember-data/unpublished-test-infra": "4.7.0",
33
37
  "@ember/optional-features": "^2.0.0",
34
38
  "@ember/test-helpers": "~2.7.0",
35
- "@types/ember": "^4.0.0",
39
+ "@types/ember": "^4.0.1",
36
40
  "@types/rsvp": "^4.0.4",
37
41
  "broccoli-asset-rev": "^3.0.0",
38
42
  "ember-cli": "~4.6.0",
@@ -62,7 +66,7 @@
62
66
  "configPath": "tests/dummy/config"
63
67
  },
64
68
  "volta": {
65
- "node": "16.16.0",
69
+ "node": "16.17.0",
66
70
  "yarn": "1.22.19"
67
71
  }
68
72
  }
@@ -1,25 +0,0 @@
1
- /**
2
- @module @ember-data/store
3
- */
4
-
5
- import { registerWaiter } from '@ember/test';
6
- import { DEBUG } from '@glimmer/env';
7
- import Ember from 'ember';
8
-
9
- // TODO: expose Ember._Backburner as `import { _Backburner } from '@ember/runloop'` in ember-rfc176-data + emberjs/ember.js
10
- /*
11
- syncRelationships is used by the UI to grab updates from the graph
12
- and update the ManyArrays.
13
-
14
- We may be able to remove this once the new relationship layer is
15
- complete.
16
- */
17
- const backburner = new Ember._Backburner(['coalesce', 'sync', 'notify']);
18
-
19
- if (DEBUG) {
20
- registerWaiter(() => {
21
- return !backburner.currentInstance && !backburner.hasTimers();
22
- });
23
- }
24
-
25
- export default backburner;
@@ -1,146 +0,0 @@
1
- /**
2
- @module @ember-data/adapter/error
3
- */
4
-
5
- const SOURCE_POINTER_REGEXP = /^\/?data\/(attributes|relationships)\/(.*)/;
6
- const SOURCE_POINTER_PRIMARY_REGEXP = /^\/?data/;
7
- const PRIMARY_ATTRIBUTE_KEY = 'base';
8
-
9
- function makeArray(value) {
10
- return Array.isArray(value) ? value : [value];
11
- }
12
-
13
- /**
14
- Convert an hash of errors into an array with errors in JSON-API format.
15
- ```javascript
16
- import DS from 'ember-data';
17
-
18
- const { errorsHashToArray } = DS;
19
-
20
- let errors = {
21
- base: 'Invalid attributes on saving this record',
22
- name: 'Must be present',
23
- age: ['Must be present', 'Must be a number']
24
- };
25
- let errorsArray = errorsHashToArray(errors);
26
- // [
27
- // {
28
- // title: "Invalid Document",
29
- // detail: "Invalid attributes on saving this record",
30
- // source: { pointer: "/data" }
31
- // },
32
- // {
33
- // title: "Invalid Attribute",
34
- // detail: "Must be present",
35
- // source: { pointer: "/data/attributes/name" }
36
- // },
37
- // {
38
- // title: "Invalid Attribute",
39
- // detail: "Must be present",
40
- // source: { pointer: "/data/attributes/age" }
41
- // },
42
- // {
43
- // title: "Invalid Attribute",
44
- // detail: "Must be a number",
45
- // source: { pointer: "/data/attributes/age" }
46
- // }
47
- // ]
48
- ```
49
- @method errorsHashToArray
50
- @for @ember-data/adapter/error
51
- @static
52
- @public
53
- @param {Object} errors hash with errors as properties
54
- @return {Array} array of errors in JSON-API format
55
- */
56
- export function errorsHashToArray(errors) {
57
- let out = [];
58
-
59
- if (errors) {
60
- Object.keys(errors).forEach((key) => {
61
- let messages = makeArray(errors[key]);
62
- for (let i = 0; i < messages.length; i++) {
63
- let title = 'Invalid Attribute';
64
- let pointer = `/data/attributes/${key}`;
65
- if (key === PRIMARY_ATTRIBUTE_KEY) {
66
- title = 'Invalid Document';
67
- pointer = `/data`;
68
- }
69
- out.push({
70
- title: title,
71
- detail: messages[i],
72
- source: {
73
- pointer: pointer,
74
- },
75
- });
76
- }
77
- });
78
- }
79
-
80
- return out;
81
- }
82
-
83
- /**
84
- Convert an array of errors in JSON-API format into an object.
85
-
86
- ```javascript
87
- import DS from 'ember-data';
88
-
89
- const { errorsArrayToHash } = DS;
90
-
91
- let errorsArray = [
92
- {
93
- title: 'Invalid Attribute',
94
- detail: 'Must be present',
95
- source: { pointer: '/data/attributes/name' }
96
- },
97
- {
98
- title: 'Invalid Attribute',
99
- detail: 'Must be present',
100
- source: { pointer: '/data/attributes/age' }
101
- },
102
- {
103
- title: 'Invalid Attribute',
104
- detail: 'Must be a number',
105
- source: { pointer: '/data/attributes/age' }
106
- }
107
- ];
108
-
109
- let errors = errorsArrayToHash(errorsArray);
110
- // {
111
- // "name": ["Must be present"],
112
- // "age": ["Must be present", "must be a number"]
113
- // }
114
- ```
115
-
116
- @method errorsArrayToHash
117
- @static
118
- @for @ember-data/adapter/error
119
- @public
120
- @param {Array} errors array of errors in JSON-API format
121
- @return {Object}
122
- */
123
- export function errorsArrayToHash(errors) {
124
- let out = {};
125
-
126
- if (errors) {
127
- errors.forEach((error) => {
128
- if (error.source && error.source.pointer) {
129
- let key = error.source.pointer.match(SOURCE_POINTER_REGEXP);
130
-
131
- if (key) {
132
- key = key[2];
133
- } else if (error.source.pointer.search(SOURCE_POINTER_PRIMARY_REGEXP) !== -1) {
134
- key = PRIMARY_ATTRIBUTE_KEY;
135
- }
136
-
137
- if (key) {
138
- out[key] = out[key] || [];
139
- out[key].push(error.detail || error.title);
140
- }
141
- }
142
- });
143
- }
144
-
145
- return out;
146
- }