@projectcaluma/ember-core 14.6.0 → 14.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,13 +2,9 @@ import { getOwner, setOwner } from "@ember/application";
2
2
  import { assert } from "@ember/debug";
3
3
  import { tracked } from "@glimmer/tracking";
4
4
  import { queryManager } from "ember-apollo-client";
5
- import {
6
- enqueueTask,
7
- lastValue,
8
- restartableTask,
9
- task,
10
- } from "ember-concurrency";
5
+ import { task } from "ember-concurrency";
11
6
  import { gql } from "graphql-tag";
7
+ import { TrackedArray } from "tracked-built-ins";
12
8
 
13
9
  export default class BaseQuery {
14
10
  @queryManager apollo;
@@ -66,17 +62,7 @@ export default class BaseQuery {
66
62
  }
67
63
 
68
64
  get value() {
69
- const Model = getOwner(this).factoryFor(
70
- `caluma-query-model:${this.modelName}`,
71
- ).class;
72
-
73
- return this.items.map((item) => {
74
- const instance = new Model(item);
75
-
76
- setOwner(instance, getOwner(this));
77
-
78
- return instance;
79
- });
65
+ return this.items;
80
66
  }
81
67
 
82
68
  fetch(...args) {
@@ -94,30 +80,33 @@ export default class BaseQuery {
94
80
  return this._fetch.perform({ filter: this.filter, order: this.order });
95
81
  }
96
82
 
97
- @restartableTask
98
- *_fetch({ filter = [], order = [], queryOptions = {} } = {}) {
99
- yield this._fetchPage.cancelAll({ resetState: true });
83
+ _fetch = task(
84
+ { restartable: true },
85
+ async ({ filter = [], order = [], queryOptions = {} } = {}) => {
86
+ await this._fetchPage.cancelAll({ resetState: true });
100
87
 
101
- this.items = [];
88
+ this.items = new TrackedArray();
102
89
 
103
- this.filter = filter;
104
- this.order = order;
105
- this.queryOptions = { ...(this.queryOptions ?? {}), ...queryOptions };
90
+ this.filter = filter;
91
+ this.order = order;
92
+ this.queryOptions = { ...(this.queryOptions ?? {}), ...queryOptions };
106
93
 
107
- return yield this._fetchPage.linked().perform();
108
- }
94
+ return await this._fetchPage.linked().perform();
95
+ },
96
+ );
109
97
 
110
- @enqueueTask
111
- *_fetchMore() {
98
+ _fetchMore = task({ enqueue: true }, async () => {
112
99
  if (!this._data) return;
113
100
 
114
- return yield this._fetchPage.linked().perform();
101
+ return await this._fetchPage.linked().perform();
102
+ });
103
+
104
+ get _data() {
105
+ return this._fetchPage.lastSuccessful?.value;
115
106
  }
116
107
 
117
- @lastValue("_fetchPage") _data;
118
- @task
119
- *_fetchPage() {
120
- const data = yield this.apollo.query({
108
+ _fetchPage = task(async () => {
109
+ const data = await this.apollo.query({
121
110
  query: gql`
122
111
  ${this.query}
123
112
  `,
@@ -131,13 +120,39 @@ export default class BaseQuery {
131
120
  ...this.queryOptions,
132
121
  });
133
122
 
134
- this.items = yield this.processAll([
135
- ...this.items,
136
- ...(yield this.processNew(
137
- data[this.dataKey].edges.map(({ node }) => node),
138
- )),
139
- ]);
123
+ const rawNewItems = data[this.dataKey].edges.map(({ node }) => node);
124
+
125
+ await this.#parsePage(rawNewItems);
140
126
 
141
127
  return data;
128
+ });
129
+
130
+ #createModel(item) {
131
+ const instance = new this.modelClass(item);
132
+ setOwner(instance, getOwner(this));
133
+ return instance;
134
+ }
135
+
136
+ async #parsePage(rawNewItems) {
137
+ const processedNewItems = await this.processNew(rawNewItems);
138
+ const rawExistingItems = this.items.map((model) => model.raw);
139
+
140
+ const allRawItems = [...processedNewItems, ...rawExistingItems];
141
+ const allProcessedItems = await this.processAll(allRawItems);
142
+
143
+ // Superficially check if `this.processAll` changed anything on the raw data
144
+ if (JSON.stringify(allRawItems) !== JSON.stringify(allProcessedItems)) {
145
+ // If so, we need to re-create the already existing models and reassign
146
+ // the `this.items` property in order to trigger a rerender for **all**
147
+ // items.
148
+ this.items = new TrackedArray(
149
+ allProcessedItems.map((i) => this.#createModel(i)),
150
+ );
151
+ } else {
152
+ // If not, only the newly added items need to be converted to models and
153
+ // added to the existing items in order to only trigger a partial rerender
154
+ // for the newly added items.
155
+ this.items.push(...processedNewItems.map((i) => this.#createModel(i)));
156
+ }
142
157
  }
143
158
  }
@@ -51,7 +51,7 @@ export default class CalumaQueryResource extends Resource {
51
51
  event.preventDefault();
52
52
  }
53
53
 
54
- this.query.fetchMore();
54
+ return this.query.fetchMore();
55
55
  }
56
56
 
57
57
  @action
@@ -60,7 +60,7 @@ export default class CalumaQueryResource extends Resource {
60
60
  event.preventDefault();
61
61
  }
62
62
 
63
- this.query.refresh();
63
+ return this.query.refresh();
64
64
  }
65
65
 
66
66
  get value() {
@@ -9,15 +9,22 @@ import { pluralize } from "ember-inflector";
9
9
 
10
10
  const toArrayIsDeprecated = dependencySatisfies("ember-data", "^4.7.0");
11
11
 
12
- /**
13
- * Decorator to define a type resolver in the scheduler service.
14
- *
15
- * @function typeResolver
16
- * @param {"group"|"user"} type The type of the objects to resolve
17
- * @returns {Function} The decorator function that returns an enqueued task to resolve the requested objects
18
- */
19
- function typeResolver(type) {
20
- return task(function* () {
12
+ export default class PrivateSchedulerService extends Service {
13
+ @service calumaOptions;
14
+
15
+ @tracked groupCache = [];
16
+ @tracked userCache = [];
17
+
18
+ resolveGroup = task(
19
+ { enqueue: true },
20
+ async () => await this.#resolveType("group"),
21
+ );
22
+ resolveUser = task(
23
+ { enqueue: true },
24
+ async () => await this.#resolveType("user"),
25
+ );
26
+
27
+ async #resolveType(type) {
21
28
  const identifiers = [...(this[type]?.identifiers ?? [])];
22
29
  const callbacks = [...(this[type]?.callbacks ?? [])];
23
30
 
@@ -37,7 +44,7 @@ function typeResolver(type) {
37
44
 
38
45
  const methodName = camelize(`resolve-${pluralize(type)}`);
39
46
  const result = uncachedIdentifiers.length
40
- ? yield this.calumaOptions[methodName]?.(uncachedIdentifiers)
47
+ ? await this.calumaOptions[methodName]?.(uncachedIdentifiers)
41
48
  : [];
42
49
 
43
50
  const allResults = toArrayIsDeprecated
@@ -48,20 +55,10 @@ function typeResolver(type) {
48
55
  this[`${type}Cache`] = allResults;
49
56
  }
50
57
 
51
- yield Promise.all(callbacks.map((callback) => callback(allResults)));
58
+ await Promise.all(callbacks.map((callback) => callback(allResults)));
52
59
 
53
60
  return allResults;
54
- }).enqueue();
55
- }
56
-
57
- export default class PrivateSchedulerService extends Service {
58
- @service calumaOptions;
59
-
60
- @tracked groupCache = [];
61
- @tracked userCache = [];
62
-
63
- @typeResolver("group") resolveGroup;
64
- @typeResolver("user") resolveUser;
61
+ }
65
62
 
66
63
  /**
67
64
  * Resolve a certain object of a type only once in the runloop.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectcaluma/ember-core",
3
- "version": "14.6.0",
3
+ "version": "14.7.1",
4
4
  "description": "Ember core addon for working with Caluma.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -17,7 +17,7 @@
17
17
  "ember-auto-import": "^2.10.0",
18
18
  "ember-cli-babel": "^8.2.0",
19
19
  "ember-cli-htmlbars": "^6.3.0",
20
- "ember-concurrency": "^4.0.2",
20
+ "ember-concurrency": "^4.0.2 || ^5.1.0",
21
21
  "ember-inflector": "^4.0.3 || ^5.0.1",
22
22
  "ember-intl": "^7.1.1",
23
23
  "ember-modify-based-class-resource": "^1.1.1",
@@ -27,15 +27,16 @@
27
27
  "graphql-tag": "^2.12.6",
28
28
  "jexl": "^2.3.0",
29
29
  "lodash.clonedeep": "^4.5.0",
30
- "slugify": "^1.6.6"
30
+ "slugify": "^1.6.6",
31
+ "tracked-built-ins": "^3.4.0 || ^4.0.0"
31
32
  },
32
33
  "devDependencies": {
33
- "@ember/optional-features": "2.2.0",
34
+ "@ember/optional-features": "2.3.0",
34
35
  "@ember/render-modifiers": "3.0.0",
35
36
  "@ember/test-helpers": "4.0.4",
36
37
  "@embroider/test-setup": "4.0.0",
37
- "@embroider/util": "1.13.4",
38
- "@faker-js/faker": "10.0.0",
38
+ "@embroider/util": "1.13.5",
39
+ "@faker-js/faker": "10.2.0",
39
40
  "@glimmer/component": "1.1.2",
40
41
  "@glimmer/tracking": "1.1.2",
41
42
  "broccoli-asset-rev": "3.0.0",
@@ -55,12 +56,12 @@
55
56
  "ember-source-channel-url": "3.0.0",
56
57
  "ember-try": "4.0.0",
57
58
  "loader.js": "4.7.0",
58
- "qunit": "2.24.1",
59
+ "qunit": "2.25.0",
59
60
  "qunit-dom": "3.5.0",
60
- "sinon": "21.0.0",
61
- "uikit": "3.23.13",
62
- "webpack": "5.101.3",
63
- "@projectcaluma/ember-testing": "14.6.0"
61
+ "sinon": "21.0.1",
62
+ "uikit": "3.25.6",
63
+ "webpack": "5.104.1",
64
+ "@projectcaluma/ember-testing": "14.7.1"
64
65
  },
65
66
  "peerDependencies": {
66
67
  "ember-data": "*",