smart-home-engine 1.43.0 → 1.44.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/dist/web/assets/index-C5CNdJWG.js +289 -0
- package/dist/web/assets/{index-dFdInRyC.css → index-DDpHIMRc.css} +1 -1
- package/dist/web/assets/{tsMode-B4v7bdgd.js → tsMode-IQCYIRzL.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/service/she-servicectl +6 -3
- package/src/lib/node-releases.js +65 -0
- package/src/web/services-api.js +12 -4
- package/dist/web/assets/index-Crx1MbU9.js +0 -290
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-
|
|
1
|
+
import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-C5CNdJWG.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
package/dist/web/index.html
CHANGED
|
@@ -172,10 +172,10 @@
|
|
|
172
172
|
}
|
|
173
173
|
})();
|
|
174
174
|
</script>
|
|
175
|
-
<script type="module" crossorigin src="/assets/index-
|
|
175
|
+
<script type="module" crossorigin src="/assets/index-C5CNdJWG.js"></script>
|
|
176
176
|
<link rel="modulepreload" crossorigin href="/assets/monaco-langs-DKJI_o9J.js">
|
|
177
177
|
<link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
|
|
178
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
178
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DDpHIMRc.css">
|
|
179
179
|
</head>
|
|
180
180
|
<body>
|
|
181
181
|
<div id="app"></div>
|
package/package.json
CHANGED
package/service/she-servicectl
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
# she-servicectl files <adapter> <instance> JSON listing of /etc/<adapter>/ and /var/lib/<adapter>/<instance>/
|
|
32
32
|
# she-servicectl file <adapter> <instance> read|write <path> a file inside those two directories (write: content on stdin)
|
|
33
33
|
# she-servicectl asset <adapter> <relpath> a file shipped in the adapter package (example, schema)
|
|
34
|
-
# she-servicectl node update [--lts]
|
|
34
|
+
# she-servicectl node update [--lts|--latest] install/refresh tj/n (downloaded, no npm), then n install lts (or latest) — JSON with the version before and after
|
|
35
35
|
# she-servicectl restart-all restart every running instance on this host (after a node update, say)
|
|
36
36
|
# she-servicectl self-update replace this script with the one on stdin (she ships it)
|
|
37
37
|
# she-servicectl remove-key drop the public key on stdin from the calling user's authorized_keys
|
|
@@ -693,11 +693,14 @@ cmd_node() {
|
|
|
693
693
|
action=$1
|
|
694
694
|
shift
|
|
695
695
|
[ "$action" = update ] || die "unknown node action: $action"
|
|
696
|
-
|
|
696
|
+
# n's labels: lts = newest long-term-support release, latest = newest release of all.
|
|
697
|
+
# (n also accepts "stable", but only as its own old alias for lts — not a third channel.)
|
|
698
|
+
spec=lts
|
|
697
699
|
while [ $# -gt 0 ]; do
|
|
698
700
|
case "$1" in
|
|
699
701
|
--lts) spec=lts ;;
|
|
700
|
-
--
|
|
702
|
+
--latest) spec=latest ;;
|
|
703
|
+
--stable) spec=lts ;;
|
|
701
704
|
*) die "unknown option: $1" ;;
|
|
702
705
|
esac
|
|
703
706
|
shift
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Which Node.js versions a host could be updated to — the two labels tj/n understands:
|
|
5
|
+
* `lts` (newest Long Term Support release) and `latest` (newest official release).
|
|
6
|
+
*
|
|
7
|
+
* she asks nodejs.org once for all hosts and caches the answer, so the Hosts tab can show
|
|
8
|
+
* what a click would install and hide the button when the host already runs it. Best-effort:
|
|
9
|
+
* every failure yields the last good answer, or nulls — nothing throws.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const INDEX_URL = 'https://nodejs.org/dist/index.json';
|
|
13
|
+
const TTL = 6 * 60 * 60 * 1000;
|
|
14
|
+
|
|
15
|
+
let _fetch = (...args) => fetch(...args);
|
|
16
|
+
|
|
17
|
+
/** Test hook: replace the fetch implementation. */
|
|
18
|
+
function setFetch(fn) {
|
|
19
|
+
_fetch = fn;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** @type {{lts: string|null, ltsName: string|null, latest: string|null, ts: number, ok: boolean}|null} */
|
|
23
|
+
let _cache = null;
|
|
24
|
+
/** @type {Promise<object>|null} */
|
|
25
|
+
let _inflight = null;
|
|
26
|
+
|
|
27
|
+
function clearCache() {
|
|
28
|
+
_cache = null;
|
|
29
|
+
_inflight = null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {{force?: boolean, now?: number}} [opts]
|
|
34
|
+
* @returns {Promise<{lts: string|null, ltsName: string|null, latest: string|null, fetchedAt: number|null, stale: boolean}>}
|
|
35
|
+
*/
|
|
36
|
+
async function releases(opts = {}) {
|
|
37
|
+
const now = opts.now ?? Date.now();
|
|
38
|
+
if (_cache && !opts.force && now - _cache.ts < TTL) {
|
|
39
|
+
return { lts: _cache.lts, ltsName: _cache.ltsName, latest: _cache.latest, fetchedAt: _cache.ts, stale: !_cache.ok };
|
|
40
|
+
}
|
|
41
|
+
if (_inflight) return _inflight;
|
|
42
|
+
|
|
43
|
+
_inflight = (async () => {
|
|
44
|
+
try {
|
|
45
|
+
const res = await _fetch(INDEX_URL, { signal: AbortSignal.timeout(15000) });
|
|
46
|
+
if (!res.ok) throw new Error(String(res.status));
|
|
47
|
+
const list = await res.json();
|
|
48
|
+
if (!Array.isArray(list) || list.length === 0) throw new Error('unexpected index.json');
|
|
49
|
+
// index.json is ordered newest first; an LTS entry carries its codename in `lts`
|
|
50
|
+
const latest = typeof list[0].version === 'string' ? list[0].version : null;
|
|
51
|
+
const ltsEntry = list.find((e) => e && e.lts && typeof e.version === 'string') || null;
|
|
52
|
+
_cache = { lts: ltsEntry ? ltsEntry.version : null, ltsName: ltsEntry ? String(ltsEntry.lts) : null, latest, ts: now, ok: true };
|
|
53
|
+
} catch {
|
|
54
|
+
// keep whatever was known before, just mark it stale
|
|
55
|
+
_cache = _cache ? { ..._cache, ts: now, ok: false } : { lts: null, ltsName: null, latest: null, ts: now, ok: false };
|
|
56
|
+
} finally {
|
|
57
|
+
_inflight = null;
|
|
58
|
+
}
|
|
59
|
+
return { lts: _cache.lts, ltsName: _cache.ltsName, latest: _cache.latest, fetchedAt: _cache.ok ? _cache.ts : null, stale: !_cache.ok };
|
|
60
|
+
})();
|
|
61
|
+
|
|
62
|
+
return _inflight;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = { releases, setFetch, clearCache, INDEX_URL, TTL };
|
package/src/web/services-api.js
CHANGED
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
* GET /she/services/ssh/pubkey public key of the services identity (I5)
|
|
30
30
|
* POST /she/services/ssh/keygen generate it
|
|
31
31
|
* POST /she/services/hosts/:host/test run `she-servicectl version` → ok / code
|
|
32
|
-
*
|
|
32
|
+
* GET /she/services/node/releases[?refresh=1] what a node update would install: the newest lts and latest release
|
|
33
|
+
* POST /she/services/hosts/:host/node/update { channel: lts|latest } update Node.js with tj/n (helper v13)
|
|
33
34
|
* POST /she/services/hosts/:host/instances/restart-all restart every running instance (after a node update)
|
|
34
35
|
* POST /she/services/hosts/:host/helper/deploy scp the helper to a remote host, install it, print the sudoers line
|
|
35
36
|
* POST /she/services/hosts/:host/helper/remove { mode: key|all, force? } remove she from the host (I11), drop the host entry
|
|
@@ -56,6 +57,7 @@ const dns = require('dns');
|
|
|
56
57
|
const { analyzeServices, wipeTopics, LOG_LEVELS } = require('../lib/services-inventory');
|
|
57
58
|
const { shapeDevices, discoverTarget } = require('../lib/device-discovery');
|
|
58
59
|
const npmRegistry = require('../lib/npm-registry');
|
|
60
|
+
const nodeReleases = require('../lib/node-releases');
|
|
59
61
|
const catalog = require('../lib/services-catalog');
|
|
60
62
|
const os = require('os');
|
|
61
63
|
const path = require('path');
|
|
@@ -1043,12 +1045,18 @@ function nodeHostError(res, err) {
|
|
|
1043
1045
|
return hostError(res, err);
|
|
1044
1046
|
}
|
|
1045
1047
|
|
|
1046
|
-
//
|
|
1048
|
+
// GET /she/services/node/releases[?refresh=1] — what the update buttons would install
|
|
1049
|
+
router.get('/node/releases', async (req, res) => {
|
|
1050
|
+
res.json(await nodeReleases.releases({ force: req.query.refresh === '1' }));
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
// POST /she/services/hosts/:host/node/update { channel?: 'lts' | 'latest' }
|
|
1047
1054
|
router.post('/hosts/:host/node/update', async (req, res) => {
|
|
1048
1055
|
const entry = resolve(req, res);
|
|
1049
1056
|
if (!entry) return;
|
|
1050
|
-
|
|
1051
|
-
|
|
1057
|
+
// 'stable' is n's old alias for lts — accepted so an older client keeps working
|
|
1058
|
+
const channel = (req.body && req.body.channel) === 'stable' ? 'lts' : (req.body && req.body.channel) || 'lts';
|
|
1059
|
+
if (channel !== 'lts' && channel !== 'latest') return res.status(400).json({ error: "channel must be 'lts' or 'latest'" });
|
|
1052
1060
|
try {
|
|
1053
1061
|
// downloading and unpacking a node build on a small host takes a while
|
|
1054
1062
|
const { stdout } = await entry.driver.exec(['node', 'update', '--' + channel], { timeout: 900000 });
|