@schukai/monster 4.73.0 → 4.73.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.73.2] - 2026-01-03
6
+
7
+ ### Bug Fixes
8
+
9
+ - lookup [#360](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/360)
10
+
11
+
12
+
13
+ ## [4.73.1] - 2026-01-03
14
+
15
+ ### Bug Fixes
16
+
17
+ - Enhance collectLookupIds with sourcePath parameter for flexibility
18
+ ### Changes
19
+
20
+ - update tests
21
+
22
+
23
+
5
24
  ## [4.73.0] - 2026-01-03
6
25
 
7
26
  ### Add Features
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.73.0"}
1
+ {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.73.2"}
@@ -66,6 +66,7 @@ const readRequestIdSymbol = Symbol("readRequestId");
66
66
  const writeRequestIdSymbol = Symbol("writeRequestId");
67
67
  const lookupCacheSymbol = Symbol("lookupCache");
68
68
  const lookupPendingSymbol = Symbol("lookupPending");
69
+ const lookupPendingFetchSymbol = Symbol("lookupPendingFetch");
69
70
 
70
71
  /**
71
72
  * A rest api datasource
@@ -823,11 +824,31 @@ async function resolveRemoteLookup(requestId, name, cfg) {
823
824
 
824
825
  const cache = getLookupCache.call(this, name);
825
826
  const pending = getLookupPending.call(this, name);
827
+ const pendingFetches = getLookupPendingFetches.call(this, name);
826
828
 
827
- const ids = collectLookupIds.call(this, key);
829
+ const ids = collectLookupIds.call(
830
+ this,
831
+ key,
832
+ this.getOption("lookups.sourcePath", "dataset"),
833
+ );
828
834
  const missingIds = ids.filter((id) => !cache.has(id) && !pending.has(id));
829
835
 
830
836
  if (missingIds.length === 0) {
837
+ if (pending.size > 0) {
838
+ updateLookupRows.call(this, requestId, (rows) => {
839
+ if (!isString(cfg.loadingKey)) return;
840
+ for (const row of rows) {
841
+ if (pending.has(String(row[key]))) {
842
+ row[cfg.loadingKey] = true;
843
+ }
844
+ }
845
+ });
846
+
847
+ if (pendingFetches.size > 0) {
848
+ const fetches = Array.from(pendingFetches);
849
+ await Promise.all(fetches.map((promise) => promise.catch(() => null)));
850
+ }
851
+ }
831
852
  applyLookupCache.call(this, requestId, cfg, cache);
832
853
  return;
833
854
  }
@@ -835,7 +856,7 @@ async function resolveRemoteLookup(requestId, name, cfg) {
835
856
  updateLookupRows.call(this, requestId, (rows) => {
836
857
  if (!isString(cfg.loadingKey)) return;
837
858
  for (const row of rows) {
838
- if (missingIds.includes(String(row[key]))) {
859
+ if (missingIds.includes(String(row[key])) || pending.has(String(row[key]))) {
839
860
  row[cfg.loadingKey] = true;
840
861
  }
841
862
  }
@@ -843,7 +864,14 @@ async function resolveRemoteLookup(requestId, name, cfg) {
843
864
 
844
865
  missingIds.forEach((id) => pending.add(id));
845
866
 
846
- const response = await fetchLookupEntries.call(this, cfg, missingIds);
867
+ const fetchPromise = fetchLookupEntries.call(this, cfg, missingIds);
868
+ pendingFetches.add(fetchPromise);
869
+ let response;
870
+ try {
871
+ response = await fetchPromise;
872
+ } finally {
873
+ pendingFetches.delete(fetchPromise);
874
+ }
847
875
  response.forEach((entry, id) => cache.set(id, entry));
848
876
  missingIds.forEach((id) => pending.delete(id));
849
877
 
@@ -878,8 +906,8 @@ function applyLookupCache(requestId, cfg, cache) {
878
906
  * @param {string} key
879
907
  * @return {string[]}
880
908
  */
881
- function collectLookupIds(key) {
882
- const rows = resolveLookupRows.call(this);
909
+ function collectLookupIds(key, sourcePath) {
910
+ const rows = resolveLookupRows.call(this, undefined, sourcePath);
883
911
  if (!isArray(rows)) {
884
912
  return [];
885
913
  }
@@ -1133,6 +1161,21 @@ function getLookupPending(name) {
1133
1161
  return this[lookupPendingSymbol].get(name);
1134
1162
  }
1135
1163
 
1164
+ /**
1165
+ * @private
1166
+ * @param {string} name
1167
+ * @return {Set<Promise<Map<string, object>>>}
1168
+ */
1169
+ function getLookupPendingFetches(name) {
1170
+ if (!this[lookupPendingFetchSymbol]) {
1171
+ this[lookupPendingFetchSymbol] = new Map();
1172
+ }
1173
+ if (!this[lookupPendingFetchSymbol].has(name)) {
1174
+ this[lookupPendingFetchSymbol].set(name, new Set());
1175
+ }
1176
+ return this[lookupPendingFetchSymbol].get(name);
1177
+ }
1178
+
1136
1179
  /**
1137
1180
  * @private
1138
1181
  * @return {string}
@@ -228,9 +228,16 @@ describe('Select', function () {
228
228
  ]);
229
229
  mocks.appendChild(select);
230
230
 
231
- setTimeout(() => {
231
+ const startedAt = Date.now();
232
+ const poll = () => {
232
233
  try {
233
234
  const options = select.getOption('options');
235
+ if (options?.[0]?.value !== 'Alpha') {
236
+ if (Date.now() - startedAt < 1500) {
237
+ return setTimeout(poll, 50);
238
+ }
239
+ }
240
+
234
241
  expect(options[0].value).to.equal('Alpha');
235
242
  expect(options[0].label).to.equal('Alpha');
236
243
  expect(options[0].visibility).to.equal('visible');
@@ -245,7 +252,9 @@ describe('Select', function () {
245
252
  }
246
253
 
247
254
  done();
248
- }, 350);
255
+ };
256
+
257
+ setTimeout(poll, 50);
249
258
  });
250
259
 
251
260
  it('should not parse options arrays with multiple string entries', function (done) {
@@ -14,11 +14,11 @@ describe('DeadMansSwitch', function () {
14
14
  const ms2 = Date.now();
15
15
 
16
16
  const diff = ms2 - ms1;
17
- if (diff < 100) {
18
- done('to short ' + diff);
19
- return;
20
- }
21
- done();
17
+ if (diff < 90) {
18
+ done(new Error('to short ' + diff));
19
+ return;
20
+ }
21
+ done();
22
22
  })
23
23
 
24
24
 
@@ -42,7 +42,7 @@ describe('DeadMansSwitch', function () {
42
42
  return;
43
43
  }
44
44
 
45
- if (diff < 600) {
45
+ if (diff < 550) {
46
46
  done(new Error('to short ' + diff));
47
47
  return;
48
48
  }
@@ -68,4 +68,4 @@ describe('DeadMansSwitch', function () {
68
68
  });
69
69
  });
70
70
 
71
- });
71
+ });