@camstack/system 1.2.14 → 1.2.16
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/addon-runner.js +2 -2
- package/dist/addon-runner.mjs +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +73 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +73 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +3 -38
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +2 -2
- package/dist/builtins/platform-probe/index.js +2 -2
- package/dist/builtins/platform-probe/index.mjs +3 -2
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-backup/system-backup.service.d.ts +14 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/chunk-CNf5ZN-e.mjs +37 -0
- package/dist/{dist-yttC1aUI.js → dist-3AzhkmeY.js} +1325 -1129
- package/dist/{dist-eOaraBhT.mjs → dist-BU-QPlE8.mjs} +1325 -1129
- package/dist/framework-resolver-hook.mjs +2 -0
- package/dist/index.js +224 -32
- package/dist/index.mjs +227 -34
- package/dist/kernel/addon-installer.d.ts +86 -7
- package/dist/kernel/fs-utils.d.ts +18 -5
- package/dist/lib-5THG9eKz.mjs +15545 -0
- package/dist/lib-CZ3g2WTS.js +15549 -0
- package/dist/{manifest-python-deps-bn3qrsxR.mjs → manifest-python-deps-D7-WBIg_.mjs} +1 -1
- package/dist/{manifest-python-deps-DSrmih6E.js → manifest-python-deps-DRN3x53E.js} +1 -1
- package/dist/{resource-monitor-Le3l0qS2.mjs → resource-monitor-BkP504Vq.mjs} +1 -1
- package/package.json +1 -1
|
@@ -33,6 +33,13 @@ export interface AddonInstallerConfig {
|
|
|
33
33
|
readonly installSource?: InstallSource;
|
|
34
34
|
}
|
|
35
35
|
export type { InstalledPackage };
|
|
36
|
+
/** Outcome of {@link AddonInstaller.sweepBackups}. Absolute paths. */
|
|
37
|
+
export interface BackupSweepResult {
|
|
38
|
+
/** Backup dirs reclaimed by the sweep. */
|
|
39
|
+
readonly removed: readonly string[];
|
|
40
|
+
/** Backup dirs deliberately retained (rollback target / last copy). */
|
|
41
|
+
readonly kept: readonly string[];
|
|
42
|
+
}
|
|
36
43
|
export declare class AddonInstaller {
|
|
37
44
|
readonly addonsDir: string;
|
|
38
45
|
private readonly registry;
|
|
@@ -222,10 +229,14 @@ export declare class AddonInstaller {
|
|
|
222
229
|
* 1. Rename current install dir → {addonsDir}/.backups/{name}/{ts}/
|
|
223
230
|
* 2. Run a fresh install (npm or local depending on installSource)
|
|
224
231
|
* 3. Record `lastBackupDir` in the manifest entry
|
|
232
|
+
* 4. Prune every OTHER backup of this addon — the previous one just
|
|
233
|
+
* lost its only pointer and would otherwise be orphaned forever.
|
|
225
234
|
*
|
|
226
|
-
* The post-install caller (
|
|
227
|
-
*
|
|
228
|
-
*
|
|
235
|
+
* The post-install caller (restart + health-check) is responsible for
|
|
236
|
+
* verifying the new version actually works, and for calling either
|
|
237
|
+
* `clearBackup()` on success or `rollbackAddon()` on failure. This
|
|
238
|
+
* method must NOT delete the backup itself: at this point the new
|
|
239
|
+
* version has not been proven to work.
|
|
229
240
|
*
|
|
230
241
|
* Throws if there is no installed version to update — caller should
|
|
231
242
|
* prefer plain `install()` for first-time installs.
|
|
@@ -263,12 +274,80 @@ export declare class AddonInstaller {
|
|
|
263
274
|
* backup to roll back to.
|
|
264
275
|
*/
|
|
265
276
|
rollbackAddon(packageName: string): Promise<string | null>;
|
|
277
|
+
/** Root of the pre-update rollback copies: `{addonsDir}/.backups`. */
|
|
278
|
+
private get backupsRoot();
|
|
279
|
+
/**
|
|
280
|
+
* True only when `target` resolves to something strictly INSIDE
|
|
281
|
+
* `{addonsDir}/.backups/`.
|
|
282
|
+
*
|
|
283
|
+
* Every deletion in this section funnels through here. `lastBackupDir`
|
|
284
|
+
* is read back from a manifest file on disk — an operator edit, a
|
|
285
|
+
* restored manifest from another host, or a `..` in the recorded path
|
|
286
|
+
* must never turn "reclaim a backup" into "delete the live install".
|
|
287
|
+
*/
|
|
288
|
+
private isInsideBackups;
|
|
289
|
+
/**
|
|
290
|
+
* Best-effort removal of one path under `.backups/`.
|
|
291
|
+
*
|
|
292
|
+
* Never throws: an undeleted backup is a disk-space problem, whereas a
|
|
293
|
+
* throw on the post-update success path would turn a working update into
|
|
294
|
+
* a reported outage. Returns true only when the path is gone.
|
|
295
|
+
*/
|
|
296
|
+
private removeBackupPath;
|
|
297
|
+
/** List the timestamped backup dirs recorded for one package. */
|
|
298
|
+
private listBackupsFor;
|
|
299
|
+
/**
|
|
300
|
+
* Keep at most ONE backup per addon: drop every backup dir for
|
|
301
|
+
* `packageName` except `keepDir`.
|
|
302
|
+
*
|
|
303
|
+
* Called right after a new backup is recorded. Without this, a second
|
|
304
|
+
* update overwrites `lastBackupDir` and the previous backup becomes
|
|
305
|
+
* unreachable — no pointer, so neither `rollbackAddon` nor `clearBackup`
|
|
306
|
+
* can ever see it again. That is how the live hub accumulated two 398 MiB
|
|
307
|
+
* copies of one addon. Never throws.
|
|
308
|
+
*/
|
|
309
|
+
private pruneBackups;
|
|
310
|
+
/** Drop `.backups/{pkg}` (and its `@scope` parent) once they are empty. */
|
|
311
|
+
private removeEmptyBackupDirs;
|
|
312
|
+
/**
|
|
313
|
+
* Drop the recorded backup for an addon — call once the post-update
|
|
314
|
+
* health check confirms the new version actually works.
|
|
315
|
+
*
|
|
316
|
+
* Never throws and never rejects. The manifest pointer is cleared even
|
|
317
|
+
* when the bytes could not be removed: a pointer at a half-deleted tree
|
|
318
|
+
* would make `rollbackAddon` restore a gutted install, and the boot sweep
|
|
319
|
+
* reclaims the residue on the next start.
|
|
320
|
+
*/
|
|
321
|
+
clearBackup(packageName: string): Promise<void>;
|
|
322
|
+
/**
|
|
323
|
+
* Boot-time retention sweep over `{addonsDir}/.backups/`.
|
|
324
|
+
*
|
|
325
|
+
* RULE: for each addon, the ONLY backup that survives is the one the
|
|
326
|
+
* manifest's `lastBackupDir` points at — everything else is unreachable
|
|
327
|
+
* by construction (no pointer ⇒ neither `rollbackAddon` nor `clearBackup`
|
|
328
|
+
* can ever reach it). One exception: when the addon's LIVE install dir is
|
|
329
|
+
* missing, the newest backup is the only surviving copy of that addon (a
|
|
330
|
+
* crash between the rename-aside and the manifest write in `applyUpdate`),
|
|
331
|
+
* so it is kept instead of reclaimed.
|
|
332
|
+
*
|
|
333
|
+
* Why not "delete everything once the addon is healthy": this installer
|
|
334
|
+
* has no health signal, and the pointed-at backup is precisely the one a
|
|
335
|
+
* failed update left for the operator's Rollback button. Bounding to one
|
|
336
|
+
* per addon is enough — the observed 814 MiB was duplicate copies, not a
|
|
337
|
+
* single retained rollback target.
|
|
338
|
+
*
|
|
339
|
+
* Never throws. Safe to run on every boot; runs before any update can be
|
|
340
|
+
* in flight.
|
|
341
|
+
*/
|
|
342
|
+
sweepBackups(): Promise<BackupSweepResult>;
|
|
266
343
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
344
|
+
* Which backup of `packageName` survives the sweep: the manifest's
|
|
345
|
+
* rollback target, or — when the live install is gone — the newest copy,
|
|
346
|
+
* which is then the only one that exists. `null` means "reclaim them all".
|
|
270
347
|
*/
|
|
271
|
-
|
|
348
|
+
private resolveBackupToKeep;
|
|
349
|
+
/** Package names that have a `.backups/{pkg}` directory, scoped or not. */
|
|
350
|
+
private listBackedUpPackages;
|
|
272
351
|
uninstall(packageName: string): Promise<void>;
|
|
273
352
|
listInstalled(): InstalledPackage[];
|
|
274
353
|
isInstalled(packageName: string): boolean;
|
|
@@ -15,11 +15,24 @@ export declare function ensureDir(dirPath: string): void;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function copyDirRecursive(src: string, dest: string): Promise<void>;
|
|
17
17
|
/**
|
|
18
|
-
* Runtime
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* Runtime deps a stripped addon package.json must KEEP so the installer still
|
|
19
|
+
* `npm install`s them into the addon dir.
|
|
20
|
+
*
|
|
21
|
+
* Empty by design: every native an addon can import is now HOST-EXTERNAL
|
|
22
|
+
* (node-av, sharp, node-pty — resolved from the framework closure via the
|
|
23
|
+
* resolver hook, see host-externals.ts), and every pure-JS lib (ssh2, werift,
|
|
24
|
+
* @simplewebauthn, mqtt, aws-sdk, …) is inlined by the self-contained vite
|
|
25
|
+
* bundle. So a self-contained dist requires NOTHING from a local node_modules —
|
|
26
|
+
* `addons/` stays node_modules-free, which is what lets the backup tar the whole
|
|
27
|
+
* folder with no exclusion list (see ADR-0027). An addon that genuinely needs an
|
|
28
|
+
* un-bundleable runtime dep declares it explicitly in
|
|
29
|
+
* `camstack.runtimeDependencies`; the debug escape hatch
|
|
30
|
+
* `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy install-everything path.
|
|
31
|
+
*
|
|
32
|
+
* (Historically this mirrored the build preset's COMMON_NATIVE_DEPS and
|
|
33
|
+
* per-addon-installed node-av/sharp/onnxruntime-node/ssh2/werift/systeminformation
|
|
34
|
+
* — 74k files / 1.34 GB of redundant node_modules on the live hub. That redundancy
|
|
35
|
+
* is removed: the natives come from the framework, the pure-JS from the bundle.)
|
|
23
36
|
*/
|
|
24
37
|
export declare const RUNTIME_NATIVE_KEEP: readonly string[];
|
|
25
38
|
/**
|