smart-home-engine 1.48.1 → 1.48.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.
@@ -1,4 +1,4 @@
1
- import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-DvjjOawt.js";/*!-----------------------------------------------------------------------------
1
+ import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-H1MMwTfd.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -175,7 +175,7 @@
175
175
  }
176
176
  })();
177
177
  </script>
178
- <script type="module" crossorigin src="/assets/index-DvjjOawt.js"></script>
178
+ <script type="module" crossorigin src="/assets/index-H1MMwTfd.js"></script>
179
179
  <link rel="modulepreload" crossorigin href="/assets/monaco-langs-DKJI_o9J.js">
180
180
  <link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
181
181
  <link rel="stylesheet" crossorigin href="/assets/index-BTq9iige.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-home-engine",
3
- "version": "1.48.1",
3
+ "version": "1.48.2",
4
4
  "description": "Node.js based script runner for use in MQTT based Smart Home environments",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -39,10 +39,10 @@ async function latestVersion(name, opts = {}) {
39
39
  if (!validName(name)) return null;
40
40
  const now = opts.now ?? Date.now();
41
41
  const hit = _cache.get(name);
42
- if (hit && !opts.force) {
43
- if (hit.promise) return hit.promise;
44
- if (now - hit.ts < TTL) return hit.version;
45
- }
42
+ // a forced lookup ignores the cached answer, but not a forced one already on its way:
43
+ // the same adapter installed on five hosts is one request, not five
44
+ if (hit && hit.promise && (!opts.force || hit.forced)) return hit.promise;
45
+ if (hit && !opts.force && now - hit.ts < TTL) return hit.version;
46
46
  const promise = (async () => {
47
47
  try {
48
48
  const res = await _fetch(`${REGISTRY}/${name}/latest`, { signal: AbortSignal.timeout(10000) });
@@ -53,7 +53,7 @@ async function latestVersion(name, opts = {}) {
53
53
  return hit ? hit.version : null; // keep the last good answer
54
54
  }
55
55
  })();
56
- _cache.set(name, { version: hit ? hit.version : null, ts: now, promise });
56
+ _cache.set(name, { version: hit ? hit.version : null, ts: now, promise, forced: Boolean(opts.force) });
57
57
  const version = await promise;
58
58
  _cache.set(name, { version, ts: now });
59
59
  return version;
@@ -63,10 +63,12 @@ async function latestVersion(name, opts = {}) {
63
63
  * Newer version available? null when unknown.
64
64
  * @param {string} name
65
65
  * @param {string|null} installed
66
+ * @param {{force?: boolean, now?: number}} [opts] `force` asks the registry again instead of
67
+ * answering from the 24 h cache — what the refresh button on a listing wants.
66
68
  * @returns {Promise<{latest: string|null, updateAvailable: boolean|null}>}
67
69
  */
68
- async function updateInfo(name, installed) {
69
- const latest = await latestVersion(name);
70
+ async function updateInfo(name, installed, opts = {}) {
71
+ const latest = await latestVersion(name, opts);
70
72
  if (!latest || !installed) return { latest, updateAvailable: null };
71
73
  let updateAvailable = null;
72
74
  try {
@@ -132,17 +132,18 @@ function publish(topic, payload) {
132
132
  });
133
133
  }
134
134
 
135
- // GET /she/services/instances
135
+ // GET /she/services/instances[?refresh=1]
136
136
  router.get('/instances', async (req, res) => {
137
137
  if (!_store) return res.json({ enabled: false, instances: [], coreCount: 0, legacyCount: 0 });
138
138
  const cfg = getServicesConfig(req);
139
139
  const result = analyzeServices(_store.mqttEntries());
140
- // update badge: one registry lookup per adapter (cached 24 h)
140
+ // update badge: one registry lookup per adapter (cached 24 h, asked again on a refresh)
141
141
  const adapters = [...new Set(result.instances.filter((i) => i.adapter).map((i) => i.adapter))];
142
- const latest = new Map(await Promise.all(adapters.map(async (a) => [a, await npmRegistry.latestVersion(a)])));
142
+ const latest = new Map(await Promise.all(adapters.map(async (a) => [a, await npmRegistry.latestVersion(a, { force: req.query.refresh === '1' })])));
143
143
  const instances = await Promise.all(
144
144
  result.instances.map(async (i) => {
145
145
  if (!i.adapter) return { ...i, latestVersion: null, updateAvailable: null };
146
+ // unforced on purpose: the lookup above just put the fresh answer in the cache
146
147
  const { updateAvailable } = await npmRegistry.updateInfo(i.adapter, i.version);
147
148
  return { ...i, latestVersion: latest.get(i.adapter) ?? null, updateAvailable };
148
149
  }),
@@ -556,7 +557,7 @@ router.get('/hosts', async (req, res) => {
556
557
  if (!fresh && _hostsCache && _hostsCache.key === key && Date.now() - _hostsCache.ts < HOSTS_TTL) {
557
558
  return res.json({ hosts: await _hostsCache.promise, cached: true });
558
559
  }
559
- const promise = listHosts(req);
560
+ const promise = listHosts(req, { force: fresh });
560
561
  _hostsCache = { key, ts: Date.now(), promise };
561
562
  res.json({ hosts: await promise, cached: false });
562
563
  });
@@ -574,7 +575,12 @@ function withCpuShare(hostName, instances, now = Date.now()) {
574
575
  });
575
576
  }
576
577
 
577
- async function listHosts(req) {
578
+ /**
579
+ * @param {object} req
580
+ * @param {{force?: boolean}} [opts] `force`: ask npm again for the latest versions instead of
581
+ * taking the 24 h cached answer — a refresh on the listing means "is any of this outdated now?"
582
+ */
583
+ async function listHosts(req, opts = {}) {
578
584
  return Promise.all(
579
585
  hostEntries(req).map(async ({ cfg, driver }) => {
580
586
  const base = {
@@ -588,11 +594,11 @@ async function listHosts(req) {
588
594
  const { stdout } = await driver.exec(['list']);
589
595
  const list = parseList(stdout);
590
596
  if (!cfg.hostname && list.hostname) saveHostname(req, cfg.name, list.hostname);
591
- // update badge per installed adapter: one registry lookup each (cached 24 h)
597
+ // update badge per installed adapter: one registry lookup each (cached 24 h, asked again on a refresh)
592
598
  const adapters = await Promise.all(
593
599
  (list.adapters || []).map(async (a) => {
594
600
  try {
595
- const { latest, updateAvailable } = await npmRegistry.updateInfo(a.name, a.version);
601
+ const { latest, updateAvailable } = await npmRegistry.updateInfo(a.name, a.version, { force: opts.force });
596
602
  return { ...a, latestVersion: latest || null, updateAvailable };
597
603
  } catch {
598
604
  return { ...a, latestVersion: null, updateAvailable: null };