@camstack/system 1.2.58 → 1.2.59
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/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 +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/binding-mirror.d.ts +65 -0
- package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +56 -11
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +248 -26
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +248 -26
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- 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 +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- 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 +2 -2
- package/dist/builtins/snapshot/index.mjs +2 -2
- 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/retired-settings-keys.d.ts +94 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +142 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +142 -2
- 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-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/{dist-UrXyJ9Zm.mjs → dist-BqJJWCS8.mjs} +369 -24
- package/dist/{dist-Chl2MvMd.js → dist-CV6XTApk.js} +380 -23
- package/dist/index.js +187 -39
- package/dist/index.mjs +187 -39
- package/dist/kernel/addon-installer.d.ts +55 -7
- package/dist/kernel/addon-manifest.d.ts +36 -16
- package/package.json +1 -1
|
@@ -66,6 +66,37 @@ export interface BackupSweepResult {
|
|
|
66
66
|
/** Backup dirs deliberately retained (rollback target / last copy). */
|
|
67
67
|
readonly kept: readonly string[];
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* A staging tree younger than this may belong to an install still running —
|
|
71
|
+
* possibly in another process. Only older trees are residue worth sweeping.
|
|
72
|
+
* Generous on purpose: an addon's runtime-dependency `npm install` on a slow
|
|
73
|
+
* host is minutes, and the cost of leaving residue one deploy longer is disk,
|
|
74
|
+
* while the cost of sweeping a live one is a FAILED deploy.
|
|
75
|
+
*/
|
|
76
|
+
export declare const STAGING_RESIDUE_MIN_AGE_MS: number;
|
|
77
|
+
export interface StagingEntryAge {
|
|
78
|
+
readonly name: string;
|
|
79
|
+
/** Age of the entry's mtime, in ms. */
|
|
80
|
+
readonly ageMs: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Pick the staging entries that are safe to delete.
|
|
84
|
+
*
|
|
85
|
+
* `installFromTgz` used to clear the WHOLE `.staging` root before creating its
|
|
86
|
+
* own dir. Two deploys arriving within one install's lifetime — the normal case
|
|
87
|
+
* when the hub propagates two packages back to back — meant the second one
|
|
88
|
+
* deleted the first one's tree out from under its running `npm install`:
|
|
89
|
+
*
|
|
90
|
+
* npm error code ENOENT
|
|
91
|
+
* npm error path …/.staging/install-14820-2026-08-07T12-28-28-875Z/package/package.json
|
|
92
|
+
*
|
|
93
|
+
* which the propagation then reported as `runtime dependency install failed`.
|
|
94
|
+
* Observed on the Mac desktop agent and on little-unraid on 2026-08-07.
|
|
95
|
+
*
|
|
96
|
+
* So a sweep only removes what cannot be live: not a tree this process is
|
|
97
|
+
* building, and not one young enough to belong to anybody's in-flight install.
|
|
98
|
+
*/
|
|
99
|
+
export declare function selectSweepableStaging(entries: readonly StagingEntryAge[], inFlight: ReadonlySet<string>, minAgeMs?: number): readonly string[];
|
|
69
100
|
export declare class AddonInstaller {
|
|
70
101
|
readonly addonsDir: string;
|
|
71
102
|
private readonly registry;
|
|
@@ -82,6 +113,11 @@ export declare class AddonInstaller {
|
|
|
82
113
|
* `getAddonInstallSource`).
|
|
83
114
|
*/
|
|
84
115
|
readonly manifest: AddonManifest;
|
|
116
|
+
/**
|
|
117
|
+
* Basenames under `.staging` this process is currently building. Never swept
|
|
118
|
+
* — see {@link selectSweepableStaging}.
|
|
119
|
+
*/
|
|
120
|
+
private readonly inFlightStaging;
|
|
85
121
|
constructor(config: AddonInstallerConfig, logger?: IScopedLogger);
|
|
86
122
|
/**
|
|
87
123
|
* Where a bootstrapped npm lives when the host has none on PATH (packaged
|
|
@@ -154,14 +190,17 @@ export declare class AddonInstaller {
|
|
|
154
190
|
*/
|
|
155
191
|
ensureRequiredPackages(packages?: readonly string[]): Promise<void>;
|
|
156
192
|
/**
|
|
157
|
-
* Reconcile the install manifest
|
|
158
|
-
* disk
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
193
|
+
* Reconcile the install manifest against the addons actually present on
|
|
194
|
+
* disk: register seeded addons, correct a version that disagrees with the
|
|
195
|
+
* installed `package.json`, and drop entries naming a directory that does
|
|
196
|
+
* not exist. Call once after `ensureRequiredPackages`, before any update
|
|
197
|
+
* can be in flight. See `AddonManifest.reconcileFromDisk` for the rules.
|
|
198
|
+
*
|
|
199
|
+
* Every correction is logged by name — a manifest that silently disagreed
|
|
200
|
+
* with disk is what made "@camstack/system 1.2.29" read as installed on a
|
|
201
|
+
* hub that deliberately has no copy of it.
|
|
163
202
|
*
|
|
164
|
-
* Returns the number of
|
|
203
|
+
* Returns the number of changes.
|
|
165
204
|
*/
|
|
166
205
|
reconcileManifest(): number;
|
|
167
206
|
/**
|
|
@@ -252,6 +291,15 @@ export declare class AddonInstaller {
|
|
|
252
291
|
* on the next deploy.
|
|
253
292
|
*/
|
|
254
293
|
private evictInstallDir;
|
|
294
|
+
/**
|
|
295
|
+
* Best-effort removal of `.staging` residue left by a CRASHED earlier deploy.
|
|
296
|
+
*
|
|
297
|
+
* Deliberately not `sweepGraveyard`: an evicted `.evicting/*` dir is dead by
|
|
298
|
+
* construction, but a `.staging/*` dir may be an install still running — in
|
|
299
|
+
* this process or another one. Deleting one of those fails a live deploy with
|
|
300
|
+
* an ENOENT on its own package.json, which is what happened on 2026-08-07.
|
|
301
|
+
*/
|
|
302
|
+
private sweepStagingResidue;
|
|
255
303
|
/** Best-effort removal of leftover `.evicting/*` dirs from earlier deploys. */
|
|
256
304
|
private sweepGraveyard;
|
|
257
305
|
/** Install addon from a tgz file (uploaded or downloaded) */
|
|
@@ -23,6 +23,15 @@ export interface AddonManifestEntry {
|
|
|
23
23
|
*/
|
|
24
24
|
meta?: Record<string, unknown>;
|
|
25
25
|
}
|
|
26
|
+
/** One correction `reconcileFromDisk` made to bring the manifest back to disk truth. */
|
|
27
|
+
export interface ManifestReconcileChange {
|
|
28
|
+
readonly kind: 'added' | 'version-corrected' | 'pruned';
|
|
29
|
+
readonly name: string;
|
|
30
|
+
/** Version the manifest claimed before the change. Absent for `added`. */
|
|
31
|
+
readonly from?: string;
|
|
32
|
+
/** Version now recorded. Absent for `pruned`. */
|
|
33
|
+
readonly to?: string;
|
|
34
|
+
}
|
|
26
35
|
export interface AddonManifestFile {
|
|
27
36
|
/**
|
|
28
37
|
* Schema version. Increment whenever the on-disk shape changes
|
|
@@ -67,26 +76,37 @@ export declare class AddonManifest {
|
|
|
67
76
|
*/
|
|
68
77
|
invalidate(): void;
|
|
69
78
|
/**
|
|
70
|
-
* Reconcile the manifest
|
|
79
|
+
* Reconcile the manifest against what is actually present on disk.
|
|
71
80
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* version and timestamps are authoritative — a later install/update
|
|
76
|
-
* overwrites them through `upsert`).
|
|
81
|
+
* **The directory is the truth.** It is what `AddonLoader` runs; a manifest
|
|
82
|
+
* that disagrees with it is a lie the update flow and the admin UI then
|
|
83
|
+
* repeat. Three corrections, all idempotent and safe on every boot:
|
|
77
84
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* present and skips, never calling `upsert`)
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
85
|
+
* - **added** — an on-disk addon with no entry gets one, source `'seed'`.
|
|
86
|
+
* Addons baked into the Docker/Electron image are copied straight into
|
|
87
|
+
* `addonsDir` by the container entrypoint (`ensureRequiredPackages` then
|
|
88
|
+
* sees `package.json` present and skips, never calling `upsert`), so they
|
|
89
|
+
* would otherwise stay untracked and `applyUpdate` would reject them with
|
|
90
|
+
* "not currently tracked in manifest" — what broke "Update all" on a
|
|
91
|
+
* fresh image.
|
|
92
|
+
* - **version-corrected** — an entry whose version disagrees with the
|
|
93
|
+
* installed `package.json` adopts the DISK version. Provenance (`source`,
|
|
94
|
+
* `installedAt`) is NOT derivable from disk and stays authoritative here;
|
|
95
|
+
* `updatedAt` is left alone because the correction is not an update, and
|
|
96
|
+
* stamping `now` would claim an install that never happened.
|
|
97
|
+
* - **pruned** — an entry naming a directory that does not exist. The live
|
|
98
|
+
* hub carried three (`@camstack/system 1.2.29`, `addon-viewer-ui 1.1.39`,
|
|
99
|
+
* `addon-agent-ui 1.2.4`); `@camstack/system` in particular is
|
|
100
|
+
* host-provided and deliberately NOT seeded under `addonsDir`
|
|
101
|
+
* ([D45]), so its entry advertised a copy that must not exist.
|
|
102
|
+
* An entry holding a `lastBackupDir` is NEVER pruned: that pointer is the
|
|
103
|
+
* only reference to a pre-update backup, and the launcher's backup sweep
|
|
104
|
+
* reclaims anything the manifest does not point at.
|
|
86
105
|
*
|
|
87
|
-
*
|
|
106
|
+
* `onChange` receives one record per correction, so the caller can log
|
|
107
|
+
* exactly what moved. Returns the total number of changes.
|
|
88
108
|
*/
|
|
89
|
-
reconcileFromDisk(addonsDir: string): number;
|
|
109
|
+
reconcileFromDisk(addonsDir: string, onChange?: (change: ManifestReconcileChange) => void): number;
|
|
90
110
|
/**
|
|
91
111
|
* Migration helper: if the manifest is empty but the addons directory
|
|
92
112
|
* has packages with `.install-source` markers (the legacy per-addon
|