iobroker.bee 0.0.0-stage → 0.2.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.
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JobManager = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_fs_1 = require("node:fs");
6
+ const promises_1 = require("node:fs/promises");
7
+ const node_path_1 = require("node:path");
8
+ const planner_1 = require("./planner");
9
+ const util_1 = require("./util");
10
+ function pidAlive(pid) {
11
+ if (!pid) {
12
+ return false;
13
+ }
14
+ try {
15
+ process.kill(pid, 0);
16
+ return true;
17
+ }
18
+ catch (e) {
19
+ return e.code === 'EPERM';
20
+ }
21
+ }
22
+ class JobManager {
23
+ deps;
24
+ job = null;
25
+ jobFile;
26
+ runnerFile;
27
+ haltFile;
28
+ busy = false;
29
+ constructor(deps) {
30
+ this.deps = deps;
31
+ this.jobFile = (0, node_path_1.join)(deps.dataDir, 'job.json');
32
+ this.runnerFile = (0, node_path_1.join)(deps.dataDir, 'runner.json');
33
+ this.haltFile = (0, node_path_1.join)(deps.dataDir, 'halt');
34
+ }
35
+ async load() {
36
+ this.job = await (0, util_1.readJson)(this.jobFile);
37
+ if (this.job?.phase === 'finished') {
38
+ this.job = null;
39
+ }
40
+ }
41
+ isActive() {
42
+ return !!this.job && this.job.phase !== 'finished';
43
+ }
44
+ async save() {
45
+ if (this.job) {
46
+ await (0, util_1.writeJsonAtomic)(this.jobFile, this.job);
47
+ }
48
+ }
49
+ async setState(state, detail) {
50
+ if (!this.job) {
51
+ return;
52
+ }
53
+ const changed = this.job.state !== state || this.job.detail !== detail;
54
+ this.job.state = state;
55
+ this.job.detail = detail;
56
+ await this.save();
57
+ if (changed) {
58
+ await this.deps.report(this.job);
59
+ }
60
+ }
61
+ async setHalt(halt) {
62
+ if (halt) {
63
+ await (0, util_1.writeJsonAtomic)(this.haltFile, { ts: Date.now() });
64
+ }
65
+ else {
66
+ await (0, promises_1.rm)(this.haltFile, { force: true });
67
+ }
68
+ }
69
+ async spawnRunner(mode, steps, files) {
70
+ const file = {
71
+ mode,
72
+ steps,
73
+ ...(files && Object.keys(files).length ? { files } : {}),
74
+ iobroker: this.deps.iobrokerJs,
75
+ cwd: this.deps.cwd,
76
+ haltFile: this.haltFile,
77
+ logFile: (0, node_path_1.join)(this.deps.dataDir, 'runner.log'),
78
+ phase: 'start',
79
+ };
80
+ await (0, util_1.writeJsonAtomic)(this.runnerFile, file);
81
+ const child = (0, node_child_process_1.spawn)(process.execPath, [(0, node_path_1.join)(__dirname, '..', 'runner.js'), this.runnerFile], {
82
+ detached: true,
83
+ stdio: 'ignore',
84
+ cwd: this.deps.cwd,
85
+ windowsHide: true,
86
+ });
87
+ child.unref();
88
+ this.deps.log.info(`Runner started (${mode}, ${steps.length} steps, pid ${child.pid})`);
89
+ }
90
+ /**
91
+ * Starts a job
92
+ *
93
+ * @param desired desired state
94
+ * @param steps plan
95
+ * @param withBackup backup first
96
+ * @param files local packages per adapter instead of npm (the rollback takes npm)
97
+ */
98
+ async start(desired, steps, withBackup, files = {}) {
99
+ const profile = desired.profile;
100
+ const all = withBackup ? [{ action: 'backup', status: 'pending' }, ...steps] : steps;
101
+ this.job = {
102
+ key: `${profile.hash}:${desired.retry}`,
103
+ profileId: profile.id,
104
+ profileName: profile.name,
105
+ profileHash: profile.hash,
106
+ retry: desired.retry,
107
+ targets: Object.fromEntries(steps.map(s => [s.adapter, s.to ?? null])),
108
+ state: 'preflight',
109
+ detail: '',
110
+ steps: all,
111
+ phase: 'apply',
112
+ createdAt: Date.now(),
113
+ };
114
+ await this.save();
115
+ await this.spawnRunner('apply', all, files);
116
+ await this.setState(withBackup ? 'backup' : 'rollout', withBackup ? 'Sicherung wird erstellt' : 'Ausrollen');
117
+ }
118
+ /** Called periodically while a job is active */
119
+ async poll() {
120
+ if (!this.job || this.busy) {
121
+ return;
122
+ }
123
+ this.busy = true;
124
+ try {
125
+ if (this.job.phase === 'apply' || this.job.phase === 'rollback') {
126
+ await this.pollRunner();
127
+ }
128
+ else if (this.job.phase === 'verify') {
129
+ await this.verify();
130
+ }
131
+ }
132
+ catch (e) {
133
+ this.deps.log.error(`Job: ${e.stack || e.message}`);
134
+ }
135
+ finally {
136
+ this.busy = false;
137
+ }
138
+ }
139
+ async pollRunner() {
140
+ const job = this.job;
141
+ const runner = await (0, util_1.readJson)(this.runnerFile);
142
+ if (!runner) {
143
+ return;
144
+ }
145
+ const finished = runner.phase === 'done' || runner.phase === 'failed' || runner.phase === 'halted';
146
+ if (!finished && runner.phase === 'running' && !pidAlive(runner.pid)) {
147
+ // runner died (power loss, reboot)
148
+ runner.phase = 'failed';
149
+ runner.error = 'Ausführung wurde unterbrochen (Neustart oder Stromausfall)';
150
+ }
151
+ else if (!finished) {
152
+ if (job.phase === 'apply') {
153
+ job.steps = runner.steps;
154
+ const current = runner.steps.find(s => s.status === 'running');
155
+ if (current?.action === 'backup') {
156
+ await this.setState('backup', 'Sicherung wird erstellt');
157
+ }
158
+ else if (current) {
159
+ await this.setState('rollout', `${current.action} ${current.adapter} ${current.to ?? ''}`.trim());
160
+ }
161
+ }
162
+ return;
163
+ }
164
+ if (job.phase === 'apply') {
165
+ job.steps = runner.steps;
166
+ if (runner.phase === 'done') {
167
+ job.phase = 'verify';
168
+ job.verifyStartedAt = Date.now();
169
+ await this.setState('verify', 'Instanzen und Log werden geprüft');
170
+ }
171
+ else {
172
+ await this.startRollback(runner.phase === 'halted' ? 'Not-Aus während des Rollouts' : runner.error || 'Fehler', runner.phase === 'halted');
173
+ }
174
+ return;
175
+ }
176
+ // rollback finished
177
+ const ok = runner.phase === 'done';
178
+ const detail = `${job.failure}; ${ok ? 'vorheriger Stand wiederhergestellt' : `Rollback unvollständig (${runner.error}), Sicherung vorhanden`}`;
179
+ for (const s of runner.steps) {
180
+ const original = job.steps.find(o => o.adapter === s.adapter && o.status === 'ok');
181
+ if (original) {
182
+ original.status = s.status === 'ok' ? 'skipped' : 'error';
183
+ original.detail = s.status === 'ok' ? 'zurückgerollt' : `Rollback: ${s.detail || 'fehlgeschlagen'}`;
184
+ }
185
+ }
186
+ await this.finish(job.halted && ok ? 'waiting' : 'blocked', detail);
187
+ }
188
+ async startRollback(reason, halted = false) {
189
+ const job = this.job;
190
+ job.failure = reason;
191
+ job.halted = halted;
192
+ const steps = (0, planner_1.rollbackPlan)(job.steps);
193
+ if (!steps.length) {
194
+ await this.finish(halted ? 'waiting' : 'blocked', `${reason}; keine Änderung erfolgt`);
195
+ return;
196
+ }
197
+ job.phase = 'rollback';
198
+ await this.save();
199
+ await this.spawnRunner('rollback', steps);
200
+ await this.setState('rollback', reason);
201
+ }
202
+ async verify() {
203
+ const job = this.job;
204
+ const elapsed = (Date.now() - (job.verifyStartedAt ?? Date.now())) / 1000;
205
+ const installed = await this.deps.installed();
206
+ for (const [name, version] of Object.entries(job.targets)) {
207
+ if ((installed[name] ?? null) !== version) {
208
+ await this.startRollback(`${name}: installiert ${installed[name] ?? 'nichts'}, erwartet ${version ?? 'entfernt'}`);
209
+ return;
210
+ }
211
+ }
212
+ const changed = Object.entries(job.targets)
213
+ .filter(([, v]) => v)
214
+ .map(([n]) => n);
215
+ const errors = this.deps.errorsSince(job.verifyStartedAt, changed);
216
+ if (errors.length) {
217
+ await this.startRollback(`Fehler im Log von ${errors[0].from}: ${errors[0].message.slice(0, 200)}`);
218
+ return;
219
+ }
220
+ const down = [];
221
+ for (const name of changed) {
222
+ for (const inst of await this.deps.instancesOf(name)) {
223
+ if (!inst.alive) {
224
+ down.push(inst.id);
225
+ }
226
+ }
227
+ }
228
+ if (down.length) {
229
+ if (elapsed > this.deps.startTimeoutSeconds) {
230
+ await this.startRollback(`Instanz ${down.join(', ')} startet nach dem Update nicht`);
231
+ }
232
+ return;
233
+ }
234
+ if (elapsed >= this.deps.verifySeconds) {
235
+ const n = job.steps.filter(s => s.action !== 'backup').length;
236
+ await this.finish('done', `${n} Schritte erfolgreich, Instanzen laufen, keine neuen Fehler im Log`);
237
+ }
238
+ }
239
+ async finish(result, detail) {
240
+ const job = this.job;
241
+ job.phase = 'finished';
242
+ await this.setState(result === 'waiting' ? 'waiting' : result, detail);
243
+ await this.deps.onFinished(job, result);
244
+ this.job = null;
245
+ if ((0, node_fs_1.existsSync)(this.runnerFile)) {
246
+ await (0, promises_1.rm)(this.runnerFile, { force: true });
247
+ }
248
+ }
249
+ }
250
+ exports.JobManager = JobManager;
251
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/lib/jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MAX_PACKAGE_BYTES = void 0;
7
+ exports.trustedPackageUrl = trustedPackageUrl;
8
+ exports.packagesOf = packagesOf;
9
+ exports.packageFile = packageFile;
10
+ exports.ensurePackage = ensurePackage;
11
+ const node_crypto_1 = require("node:crypto");
12
+ const node_fs_1 = require("node:fs");
13
+ const promises_1 = require("node:fs/promises");
14
+ const node_http_1 = __importDefault(require("node:http"));
15
+ const node_https_1 = __importDefault(require("node:https"));
16
+ const node_path_1 = require("node:path");
17
+ /** Largest package that is loaded (the server accepts no larger ones) */
18
+ exports.MAX_PACKAGE_BYTES = 50 * 1024 * 1024;
19
+ /** Is the URL one of our own server? https, or http on this computer only (development) */
20
+ function trustedPackageUrl(url, serverUrls) {
21
+ let u;
22
+ try {
23
+ u = new URL(url);
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ const local = u.hostname === 'localhost' || u.hostname === '127.0.0.1';
29
+ if (u.protocol !== 'https:' && !(u.protocol === 'http:' && local)) {
30
+ return false;
31
+ }
32
+ return serverUrls.some(s => {
33
+ try {
34
+ return new URL(s).hostname === u.hostname;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ });
40
+ }
41
+ /** Steps of the plan that install from a package of the server: adapter -> package */
42
+ function packagesOf(desired, steps) {
43
+ const result = {};
44
+ for (const s of steps) {
45
+ const tarball = s.adapter && s.action !== 'remove' ? desired.profile?.adapters[s.adapter]?.tarball : undefined;
46
+ if (tarball) {
47
+ result[s.adapter] = tarball;
48
+ }
49
+ }
50
+ return result;
51
+ }
52
+ function packageFile(dir, sha256) {
53
+ return (0, node_path_1.join)(dir, `${sha256}.tgz`);
54
+ }
55
+ function hashFile(file) {
56
+ return new Promise(resolve => {
57
+ const hash = (0, node_crypto_1.createHash)('sha256');
58
+ (0, node_fs_1.createReadStream)(file)
59
+ .on('data', d => hash.update(d))
60
+ .on('end', () => resolve(hash.digest('hex')))
61
+ .on('error', () => resolve(null));
62
+ });
63
+ }
64
+ function download(url, target, maxBytes, ca) {
65
+ return new Promise((resolve, reject) => {
66
+ const u = new URL(url);
67
+ const get = u.protocol === 'https:' ? node_https_1.default.get : node_http_1.default.get;
68
+ const req = get(url, { ca, timeout: 60_000 }, res => {
69
+ if (res.statusCode !== 200) {
70
+ res.resume();
71
+ reject(new Error(`HTTP ${res.statusCode}`));
72
+ return;
73
+ }
74
+ const hash = (0, node_crypto_1.createHash)('sha256');
75
+ const out = (0, node_fs_1.createWriteStream)(target);
76
+ let size = 0;
77
+ let failed = false;
78
+ const fail = (e) => {
79
+ if (!failed) {
80
+ failed = true;
81
+ res.unpipe(out);
82
+ res.destroy();
83
+ out.destroy();
84
+ reject(e);
85
+ }
86
+ };
87
+ res.on('data', (d) => {
88
+ size += d.length;
89
+ if (size > maxBytes) {
90
+ fail(new Error('größer als angekündigt'));
91
+ return;
92
+ }
93
+ hash.update(d);
94
+ });
95
+ res.pipe(out);
96
+ res.on('error', fail);
97
+ out.on('error', fail);
98
+ out.on('finish', () => !failed && resolve(hash.digest('hex')));
99
+ });
100
+ req.on('timeout', () => req.destroy(new Error('Zeitüberschreitung')));
101
+ req.on('error', reject);
102
+ });
103
+ }
104
+ /**
105
+ * Path of the package on this device; loads it from the server if it is not here yet.
106
+ *
107
+ * @param dir directory of the packages (stays, see above)
108
+ * @param tarball package from the desired state
109
+ * @param opts URLs of the own server and the trusted CAs
110
+ * @param opts.serverUrls URLs of the own server (enrollment and broker)
111
+ * @param opts.ca trusted CAs for the server certificate
112
+ */
113
+ async function ensurePackage(dir, tarball, opts) {
114
+ if (!/^[0-9a-f]{64}$/.test(tarball.sha256)) {
115
+ throw new Error('ungültige Prüfsumme');
116
+ }
117
+ const file = packageFile(dir, tarball.sha256);
118
+ if ((await hashFile(file)) === tarball.sha256) {
119
+ return file;
120
+ }
121
+ if (!trustedPackageUrl(tarball.url, opts.serverUrls)) {
122
+ throw new Error(`${tarball.url} gehört nicht zum Flottenserver`);
123
+ }
124
+ await (0, promises_1.mkdir)(dir, { recursive: true });
125
+ const tmp = `${file}.part`;
126
+ try {
127
+ const sha = await download(tarball.url, tmp, Math.min(tarball.size || exports.MAX_PACKAGE_BYTES, exports.MAX_PACKAGE_BYTES), opts.ca);
128
+ if (sha !== tarball.sha256) {
129
+ throw new Error('Prüfsumme stimmt nicht');
130
+ }
131
+ await (0, promises_1.rename)(tmp, file);
132
+ return file;
133
+ }
134
+ finally {
135
+ // on Windows the file may still be open for a moment after an abort: then it is overwritten next time
136
+ await (0, promises_1.rm)(tmp, { force: true }).catch(() => { });
137
+ }
138
+ }
139
+ //# sourceMappingURL=packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.js","sourceRoot":"","sources":["../../src/lib/packages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.foreignAdapters = foreignAdapters;
7
+ exports.computePlan = computePlan;
8
+ exports.rollbackPlan = rollbackPlan;
9
+ exports.checkDependencies = checkDependencies;
10
+ const semver_1 = __importDefault(require("semver"));
11
+ const util_1 = require("./util");
12
+ /** Adapters installed locally that are neither in the profile, tolerated, nor scheduled for removal */
13
+ function foreignAdapters(desired, installed) {
14
+ if (!desired.profile) {
15
+ return [];
16
+ }
17
+ return Object.keys(installed)
18
+ .filter(n => !desired.profile.adapters[n] &&
19
+ !desired.tolerated.includes(n) &&
20
+ !desired.remove.includes(n) &&
21
+ // the controller itself is never an adapter of the profile
22
+ n !== 'js-controller')
23
+ .sort();
24
+ }
25
+ /**
26
+ * Steps to reach the profile. The agent (bee) is always updated last.
27
+ *
28
+ * @param desired desired state of the server
29
+ * @param installed installed versions
30
+ * @param selfName name of the agent adapter
31
+ * @param from where the adapters were installed from (installedFrom); with a package of the server and the
32
+ * same version installed from somewhere else, the package is installed once more (a build that kept
33
+ * the version number). Only given as long as that was not tried yet for this job.
34
+ */
35
+ function computePlan(desired, installed, selfName = 'bee', from) {
36
+ const steps = [];
37
+ if (!desired.profile) {
38
+ return steps;
39
+ }
40
+ for (const [name, target] of Object.entries(desired.profile.adapters)) {
41
+ const current = installed[name];
42
+ const source = from?.[name];
43
+ const otherBuild = !!target.tarball && !!source && !source.includes(target.tarball.sha256);
44
+ if (current === target.version && !otherBuild) {
45
+ continue;
46
+ }
47
+ steps.push({
48
+ action: !current
49
+ ? 'install'
50
+ : current === target.version || (0, util_1.compareVersions)(current, target.version) < 0
51
+ ? 'upgrade'
52
+ : 'downgrade',
53
+ adapter: name,
54
+ from: current ?? null,
55
+ to: target.version,
56
+ status: 'pending',
57
+ });
58
+ }
59
+ for (const name of desired.remove) {
60
+ if (installed[name] && name !== selfName) {
61
+ steps.push({ action: 'remove', adapter: name, from: installed[name], to: null, status: 'pending' });
62
+ }
63
+ }
64
+ // removals first (frees space), then installs/updates alphabetically, the agent last
65
+ const rank = (s) => (s.adapter === selfName ? 2 : s.action === 'remove' ? 0 : 1);
66
+ return steps.sort((a, b) => rank(a) - rank(b) || a.adapter.localeCompare(b.adapter));
67
+ }
68
+ /** Steps that restore the previous state after a failed rollout (reverse order) */
69
+ function rollbackPlan(steps) {
70
+ return steps
71
+ .filter(s => s.action !== 'backup' && s.status === 'ok')
72
+ .reverse()
73
+ .map(s => {
74
+ if (s.action === 'install') {
75
+ return { action: 'remove', adapter: s.adapter, from: s.to, to: null, status: 'pending' };
76
+ }
77
+ if (s.action === 'remove') {
78
+ return { action: 'install', adapter: s.adapter, from: null, to: s.from, status: 'pending' };
79
+ }
80
+ return {
81
+ action: s.action === 'upgrade' ? 'downgrade' : 'upgrade',
82
+ adapter: s.adapter,
83
+ from: s.to,
84
+ to: s.from,
85
+ status: 'pending',
86
+ };
87
+ });
88
+ }
89
+ /**
90
+ * Checks the dependencies of all target versions against the state after the plan
91
+ * (io-package.json dependencies, globalDependencies and engines.node of the target version).
92
+ *
93
+ * @returns list of violations; empty if everything fits
94
+ */
95
+ function checkDependencies(desired, installed, env) {
96
+ const errors = [];
97
+ if (!desired.profile) {
98
+ return errors;
99
+ }
100
+ const after = { ...installed };
101
+ for (const name of desired.remove) {
102
+ delete after[name];
103
+ }
104
+ for (const [name, a] of Object.entries(desired.profile.adapters)) {
105
+ after[name] = a.version;
106
+ }
107
+ for (const [name, a] of Object.entries(desired.profile.adapters)) {
108
+ if (installed[name] === a.version) {
109
+ continue;
110
+ }
111
+ if (a.node && semver_1.default.validRange(a.node) && !semver_1.default.satisfies(env.node, a.node)) {
112
+ errors.push(`${name}@${a.version} verlangt Node ${a.node}, installiert ist ${env.node}`);
113
+ }
114
+ for (const dep of [...(a.dependencies || []), ...(a.globalDependencies || [])]) {
115
+ for (const [depName, range] of Object.entries(dep)) {
116
+ const have = depName === 'js-controller' ? env.jsController : after[depName];
117
+ if (!have) {
118
+ errors.push(`${name}@${a.version} braucht ${depName} ${range}, das fehlt`);
119
+ }
120
+ else if (semver_1.default.validRange(range) && !semver_1.default.satisfies(have, range, { includePrerelease: true })) {
121
+ errors.push(`${name}@${a.version} braucht ${depName} ${range}, vorhanden ist ${have}`);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return errors;
127
+ }
128
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/lib/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compare = compare;
4
+ exports.freeDiskMb = freeDiskMb;
5
+ exports.preflight = preflight;
6
+ const promises_1 = require("node:fs/promises");
7
+ const util_1 = require("./util");
8
+ function coerce(value) {
9
+ const v = value.trim();
10
+ if (v === 'true' || v === 'false') {
11
+ return v === 'true';
12
+ }
13
+ if (v !== '' && !isNaN(Number(v))) {
14
+ return Number(v);
15
+ }
16
+ return v;
17
+ }
18
+ function compare(actual, op, expected) {
19
+ const exp = coerce(expected);
20
+ let act = actual;
21
+ if (typeof exp === 'number' && typeof actual === 'string' && !isNaN(Number(actual))) {
22
+ act = Number(actual);
23
+ }
24
+ if (typeof exp === 'boolean' && typeof actual !== 'boolean') {
25
+ act = actual === 'true' || actual === 1 || actual === '1';
26
+ }
27
+ switch (op) {
28
+ case '==':
29
+ return act == exp;
30
+ case '!=':
31
+ return act != exp;
32
+ case '<':
33
+ return Number(act) < Number(exp);
34
+ case '<=':
35
+ return Number(act) <= Number(exp);
36
+ case '>':
37
+ return Number(act) > Number(exp);
38
+ case '>=':
39
+ return Number(act) >= Number(exp);
40
+ default:
41
+ return false;
42
+ }
43
+ }
44
+ async function freeDiskMb(path) {
45
+ try {
46
+ const s = await (0, promises_1.statfs)(path);
47
+ return Math.round((s.bavail * s.bsize) / 1024 / 1024);
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ async function preflight(input) {
54
+ if (input.halted) {
55
+ return { ok: false, kind: 'wait', reason: `Not-Aus aktiv${input.haltReason ? `: ${input.haltReason}` : ''}` };
56
+ }
57
+ if (input.dependencyErrors.length) {
58
+ return { ok: false, kind: 'block', reason: `Abhängigkeiten: ${input.dependencyErrors.join('; ')}` };
59
+ }
60
+ const free = await freeDiskMb(input.diskPath);
61
+ if (free !== null && free < input.minFreeMb) {
62
+ return {
63
+ ok: false,
64
+ kind: 'block',
65
+ reason: `Zu wenig Speicher: ${free} MB frei, ${input.minFreeMb} MB nötig für Download, Entpacken und Sicherung`,
66
+ };
67
+ }
68
+ if (!input.window.ignore && !(0, util_1.inWindow)(input.now, input.window.start, input.window.end)) {
69
+ return {
70
+ ok: false,
71
+ kind: 'wait',
72
+ reason: `Außerhalb des Wartungsfensters (${input.window.start}–${input.window.end})`,
73
+ };
74
+ }
75
+ for (const c of input.conditions) {
76
+ if (!c.stateId) {
77
+ continue;
78
+ }
79
+ const val = await input.readState(c.stateId);
80
+ const label = c.label || c.stateId;
81
+ if (val === undefined || val === null) {
82
+ return { ok: false, kind: 'wait', reason: `${label}: Wert nicht verfügbar` };
83
+ }
84
+ if (!compare(val, c.op, c.value)) {
85
+ return { ok: false, kind: 'wait', reason: `${label}: ${String(val)} (verlangt ${c.op} ${c.value})` };
86
+ }
87
+ }
88
+ return { ok: true };
89
+ }
90
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/lib/preflight.ts"],"names":[],"mappings":"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"}