@camstack/system 1.1.37 → 1.1.39
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 +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +47 -24
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +47 -24
- package/dist/builtins/system-backup/system-backup.service.d.ts +20 -2
- package/dist/index.js +93 -4
- package/dist/index.mjs +93 -4
- package/dist/kernel/fs-utils.d.ts +28 -0
- package/dist/kernel/lifecycle/staging-area.d.ts +8 -0
- package/dist/{manifest-python-deps-B6ahe90k.js → manifest-python-deps-BGvIVCm_.js} +2 -1
- package/dist/{manifest-python-deps-4QvOLiBn.mjs → manifest-python-deps-BjxBfiFd.mjs} +2 -1
- package/package.json +1 -1
package/dist/addon-runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
2
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
2
|
+
const require_manifest_python_deps = require("./manifest-python-deps-BGvIVCm_.js");
|
|
3
3
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
4
4
|
let node_fs = require("node:fs");
|
|
5
5
|
node_fs = require_chunk.__toESM(node_fs);
|
package/dist/addon-runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as createUdsLoggerWithControl, I as LocalChildClient, i as createUdsAddonContext, it as setWorkerNativeCapsChangeListener, nt as getWorkerNativeCapSnapshot, ot as validateProviderRegistrations, t as installManifestPythonDeps, tt as getWorkerNativeCapProvider, vt as installManifestNativeDeps, yt as resolveAddonClass } from "./manifest-python-deps-
|
|
1
|
+
import { F as createUdsLoggerWithControl, I as LocalChildClient, i as createUdsAddonContext, it as setWorkerNativeCapsChangeListener, nt as getWorkerNativeCapSnapshot, ot as validateProviderRegistrations, t as installManifestPythonDeps, tt as getWorkerNativeCapProvider, vt as installManifestNativeDeps, yt as resolveAddonClass } from "./manifest-python-deps-BjxBfiFd.mjs";
|
|
2
2
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
3
3
|
import { register } from "node:module";
|
|
4
4
|
import * as fs from "node:fs";
|
|
@@ -3021,6 +3021,7 @@ var DEFAULT_BACKUP_LOCATIONS = [
|
|
|
3021
3021
|
];
|
|
3022
3022
|
/** Path of the manifest file embedded inside every archive. */
|
|
3023
3023
|
var ARCHIVE_MANIFEST_NAME = ".camstack-backup-manifest.json";
|
|
3024
|
+
var DEFAULT_STAT_CACHE_TTL_MS = 6e4;
|
|
3024
3025
|
/**
|
|
3025
3026
|
* System-level archive primitives. Construct one per server boot;
|
|
3026
3027
|
* methods are pure I/O.
|
|
@@ -3028,33 +3029,55 @@ var ARCHIVE_MANIFEST_NAME = ".camstack-backup-manifest.json";
|
|
|
3028
3029
|
var SystemBackupService = class {
|
|
3029
3030
|
dataDir;
|
|
3030
3031
|
logger;
|
|
3031
|
-
|
|
3032
|
+
statCacheTtlMs;
|
|
3033
|
+
statCache = /* @__PURE__ */ new Map();
|
|
3034
|
+
constructor(dataDir, logger, opts) {
|
|
3032
3035
|
this.dataDir = dataDir;
|
|
3033
3036
|
this.logger = logger;
|
|
3037
|
+
this.statCacheTtlMs = opts?.statCacheTtlMs ?? DEFAULT_STAT_CACHE_TTL_MS;
|
|
3034
3038
|
}
|
|
3035
3039
|
/**
|
|
3036
3040
|
* Snapshot the current size + file count of each well-known
|
|
3037
3041
|
* location. Used by the admin UI to render an opt-in checklist
|
|
3038
3042
|
* before triggering a backup, and by `createArchive` to derive the
|
|
3039
3043
|
* embedded manifest.
|
|
3044
|
+
*
|
|
3045
|
+
* The walk is async (yields to the event loop per directory) and
|
|
3046
|
+
* per-location results are cached + single-flighted: the service
|
|
3047
|
+
* runs in-process in the hub, and a synchronous walk of the 70k+
|
|
3048
|
+
* file `addons` location blocked the event loop long enough to kill
|
|
3049
|
+
* WS keepalives cluster-wide.
|
|
3040
3050
|
*/
|
|
3041
3051
|
statLocations(locations = DEFAULT_BACKUP_LOCATIONS) {
|
|
3042
|
-
return locations.map((loc) =>
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
name: loc,
|
|
3053
|
-
sizeBytes: walked.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3054
|
-
fileCount: walked.filter((e) => e.kind === "file").length,
|
|
3055
|
-
present: true
|
|
3056
|
-
};
|
|
3052
|
+
return Promise.all(locations.map((loc) => this.statLocationCached(loc)));
|
|
3053
|
+
}
|
|
3054
|
+
statLocationCached(loc) {
|
|
3055
|
+
const now = Date.now();
|
|
3056
|
+
const hit = this.statCache.get(loc);
|
|
3057
|
+
if (hit && now - hit.at < this.statCacheTtlMs) return hit.value;
|
|
3058
|
+
const value = this.statLocation(loc);
|
|
3059
|
+
this.statCache.set(loc, {
|
|
3060
|
+
at: now,
|
|
3061
|
+
value
|
|
3057
3062
|
});
|
|
3063
|
+
value.catch(() => this.statCache.delete(loc));
|
|
3064
|
+
return value;
|
|
3065
|
+
}
|
|
3066
|
+
async statLocation(loc) {
|
|
3067
|
+
const abs = node_path.isAbsolute(loc) ? loc : node_path.join(this.dataDir, loc);
|
|
3068
|
+
if (!node_fs.existsSync(abs)) return {
|
|
3069
|
+
name: loc,
|
|
3070
|
+
sizeBytes: 0,
|
|
3071
|
+
fileCount: 0,
|
|
3072
|
+
present: false
|
|
3073
|
+
};
|
|
3074
|
+
const walked = await walkAbs(abs, abs);
|
|
3075
|
+
return {
|
|
3076
|
+
name: loc,
|
|
3077
|
+
sizeBytes: walked.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3078
|
+
fileCount: walked.filter((e) => e.kind === "file").length,
|
|
3079
|
+
present: true
|
|
3080
|
+
};
|
|
3058
3081
|
}
|
|
3059
3082
|
/**
|
|
3060
3083
|
* Create a tar.gz of the given locations. Uses the `tar` npm package
|
|
@@ -3082,8 +3105,8 @@ var SystemBackupService = class {
|
|
|
3082
3105
|
const entries = [];
|
|
3083
3106
|
for (const loc of present) {
|
|
3084
3107
|
const abs = node_path.join(this.dataDir, loc);
|
|
3085
|
-
const stat =
|
|
3086
|
-
if (stat.isDirectory()) for (const e of walkAbs(abs, this.dataDir)) entries.push(e);
|
|
3108
|
+
const stat = await node_fs_promises.stat(abs);
|
|
3109
|
+
if (stat.isDirectory()) for (const e of await walkAbs(abs, this.dataDir)) entries.push(e);
|
|
3087
3110
|
else entries.push(toArchiveEntry(abs, this.dataDir, stat));
|
|
3088
3111
|
}
|
|
3089
3112
|
const manifest = {
|
|
@@ -3258,15 +3281,15 @@ var SystemBackupService = class {
|
|
|
3258
3281
|
* path. Symlinks are dereferenced (matches the `follow: true` flag we
|
|
3259
3282
|
* pass to tar.create).
|
|
3260
3283
|
*/
|
|
3261
|
-
function walkAbs(absRoot, dataDir) {
|
|
3284
|
+
async function walkAbs(absRoot, dataDir) {
|
|
3262
3285
|
const out = [];
|
|
3263
|
-
walkRec(absRoot, dataDir, out);
|
|
3286
|
+
await walkRec(absRoot, dataDir, out);
|
|
3264
3287
|
return out;
|
|
3265
3288
|
}
|
|
3266
|
-
function walkRec(abs, dataDir, out) {
|
|
3289
|
+
async function walkRec(abs, dataDir, out) {
|
|
3267
3290
|
let stat;
|
|
3268
3291
|
try {
|
|
3269
|
-
stat =
|
|
3292
|
+
stat = await node_fs_promises.stat(abs);
|
|
3270
3293
|
} catch {
|
|
3271
3294
|
return;
|
|
3272
3295
|
}
|
|
@@ -3274,11 +3297,11 @@ function walkRec(abs, dataDir, out) {
|
|
|
3274
3297
|
if (stat.isDirectory()) {
|
|
3275
3298
|
let children;
|
|
3276
3299
|
try {
|
|
3277
|
-
children =
|
|
3300
|
+
children = await node_fs_promises.readdir(abs);
|
|
3278
3301
|
} catch {
|
|
3279
3302
|
return;
|
|
3280
3303
|
}
|
|
3281
|
-
for (const child of children) walkRec(node_path.join(abs, child), dataDir, out);
|
|
3304
|
+
for (const child of children) await walkRec(node_path.join(abs, child), dataDir, out);
|
|
3282
3305
|
}
|
|
3283
3306
|
}
|
|
3284
3307
|
function toArchiveEntry(abs, dataDir, stat) {
|
|
@@ -3006,6 +3006,7 @@ var DEFAULT_BACKUP_LOCATIONS = [
|
|
|
3006
3006
|
];
|
|
3007
3007
|
/** Path of the manifest file embedded inside every archive. */
|
|
3008
3008
|
var ARCHIVE_MANIFEST_NAME = ".camstack-backup-manifest.json";
|
|
3009
|
+
var DEFAULT_STAT_CACHE_TTL_MS = 6e4;
|
|
3009
3010
|
/**
|
|
3010
3011
|
* System-level archive primitives. Construct one per server boot;
|
|
3011
3012
|
* methods are pure I/O.
|
|
@@ -3013,33 +3014,55 @@ var ARCHIVE_MANIFEST_NAME = ".camstack-backup-manifest.json";
|
|
|
3013
3014
|
var SystemBackupService = class {
|
|
3014
3015
|
dataDir;
|
|
3015
3016
|
logger;
|
|
3016
|
-
|
|
3017
|
+
statCacheTtlMs;
|
|
3018
|
+
statCache = /* @__PURE__ */ new Map();
|
|
3019
|
+
constructor(dataDir, logger, opts) {
|
|
3017
3020
|
this.dataDir = dataDir;
|
|
3018
3021
|
this.logger = logger;
|
|
3022
|
+
this.statCacheTtlMs = opts?.statCacheTtlMs ?? DEFAULT_STAT_CACHE_TTL_MS;
|
|
3019
3023
|
}
|
|
3020
3024
|
/**
|
|
3021
3025
|
* Snapshot the current size + file count of each well-known
|
|
3022
3026
|
* location. Used by the admin UI to render an opt-in checklist
|
|
3023
3027
|
* before triggering a backup, and by `createArchive` to derive the
|
|
3024
3028
|
* embedded manifest.
|
|
3029
|
+
*
|
|
3030
|
+
* The walk is async (yields to the event loop per directory) and
|
|
3031
|
+
* per-location results are cached + single-flighted: the service
|
|
3032
|
+
* runs in-process in the hub, and a synchronous walk of the 70k+
|
|
3033
|
+
* file `addons` location blocked the event loop long enough to kill
|
|
3034
|
+
* WS keepalives cluster-wide.
|
|
3025
3035
|
*/
|
|
3026
3036
|
statLocations(locations = DEFAULT_BACKUP_LOCATIONS) {
|
|
3027
|
-
return locations.map((loc) =>
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
name: loc,
|
|
3038
|
-
sizeBytes: walked.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3039
|
-
fileCount: walked.filter((e) => e.kind === "file").length,
|
|
3040
|
-
present: true
|
|
3041
|
-
};
|
|
3037
|
+
return Promise.all(locations.map((loc) => this.statLocationCached(loc)));
|
|
3038
|
+
}
|
|
3039
|
+
statLocationCached(loc) {
|
|
3040
|
+
const now = Date.now();
|
|
3041
|
+
const hit = this.statCache.get(loc);
|
|
3042
|
+
if (hit && now - hit.at < this.statCacheTtlMs) return hit.value;
|
|
3043
|
+
const value = this.statLocation(loc);
|
|
3044
|
+
this.statCache.set(loc, {
|
|
3045
|
+
at: now,
|
|
3046
|
+
value
|
|
3042
3047
|
});
|
|
3048
|
+
value.catch(() => this.statCache.delete(loc));
|
|
3049
|
+
return value;
|
|
3050
|
+
}
|
|
3051
|
+
async statLocation(loc) {
|
|
3052
|
+
const abs = path$1.isAbsolute(loc) ? loc : path$1.join(this.dataDir, loc);
|
|
3053
|
+
if (!fs.existsSync(abs)) return {
|
|
3054
|
+
name: loc,
|
|
3055
|
+
sizeBytes: 0,
|
|
3056
|
+
fileCount: 0,
|
|
3057
|
+
present: false
|
|
3058
|
+
};
|
|
3059
|
+
const walked = await walkAbs(abs, abs);
|
|
3060
|
+
return {
|
|
3061
|
+
name: loc,
|
|
3062
|
+
sizeBytes: walked.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3063
|
+
fileCount: walked.filter((e) => e.kind === "file").length,
|
|
3064
|
+
present: true
|
|
3065
|
+
};
|
|
3043
3066
|
}
|
|
3044
3067
|
/**
|
|
3045
3068
|
* Create a tar.gz of the given locations. Uses the `tar` npm package
|
|
@@ -3067,8 +3090,8 @@ var SystemBackupService = class {
|
|
|
3067
3090
|
const entries = [];
|
|
3068
3091
|
for (const loc of present) {
|
|
3069
3092
|
const abs = path$1.join(this.dataDir, loc);
|
|
3070
|
-
const stat =
|
|
3071
|
-
if (stat.isDirectory()) for (const e of walkAbs(abs, this.dataDir)) entries.push(e);
|
|
3093
|
+
const stat = await fsp.stat(abs);
|
|
3094
|
+
if (stat.isDirectory()) for (const e of await walkAbs(abs, this.dataDir)) entries.push(e);
|
|
3072
3095
|
else entries.push(toArchiveEntry(abs, this.dataDir, stat));
|
|
3073
3096
|
}
|
|
3074
3097
|
const manifest = {
|
|
@@ -3243,15 +3266,15 @@ var SystemBackupService = class {
|
|
|
3243
3266
|
* path. Symlinks are dereferenced (matches the `follow: true` flag we
|
|
3244
3267
|
* pass to tar.create).
|
|
3245
3268
|
*/
|
|
3246
|
-
function walkAbs(absRoot, dataDir) {
|
|
3269
|
+
async function walkAbs(absRoot, dataDir) {
|
|
3247
3270
|
const out = [];
|
|
3248
|
-
walkRec(absRoot, dataDir, out);
|
|
3271
|
+
await walkRec(absRoot, dataDir, out);
|
|
3249
3272
|
return out;
|
|
3250
3273
|
}
|
|
3251
|
-
function walkRec(abs, dataDir, out) {
|
|
3274
|
+
async function walkRec(abs, dataDir, out) {
|
|
3252
3275
|
let stat;
|
|
3253
3276
|
try {
|
|
3254
|
-
stat =
|
|
3277
|
+
stat = await fsp.stat(abs);
|
|
3255
3278
|
} catch {
|
|
3256
3279
|
return;
|
|
3257
3280
|
}
|
|
@@ -3259,11 +3282,11 @@ function walkRec(abs, dataDir, out) {
|
|
|
3259
3282
|
if (stat.isDirectory()) {
|
|
3260
3283
|
let children;
|
|
3261
3284
|
try {
|
|
3262
|
-
children =
|
|
3285
|
+
children = await fsp.readdir(abs);
|
|
3263
3286
|
} catch {
|
|
3264
3287
|
return;
|
|
3265
3288
|
}
|
|
3266
|
-
for (const child of children) walkRec(path$1.join(abs, child), dataDir, out);
|
|
3289
|
+
for (const child of children) await walkRec(path$1.join(abs, child), dataDir, out);
|
|
3267
3290
|
}
|
|
3268
3291
|
}
|
|
3269
3292
|
function toArchiveEntry(abs, dataDir, stat) {
|
|
@@ -64,6 +64,14 @@ export interface LocationStat {
|
|
|
64
64
|
/** False when the location doesn't exist under dataDir. */
|
|
65
65
|
readonly present: boolean;
|
|
66
66
|
}
|
|
67
|
+
export interface SystemBackupServiceOptions {
|
|
68
|
+
/**
|
|
69
|
+
* How long a `statLocations` walk result stays fresh. The `addons`
|
|
70
|
+
* location holds tens of thousands of files; without a cache every
|
|
71
|
+
* admin-UI visit re-walks it.
|
|
72
|
+
*/
|
|
73
|
+
readonly statCacheTtlMs?: number;
|
|
74
|
+
}
|
|
67
75
|
/**
|
|
68
76
|
* System-level archive primitives. Construct one per server boot;
|
|
69
77
|
* methods are pure I/O.
|
|
@@ -71,14 +79,24 @@ export interface LocationStat {
|
|
|
71
79
|
export declare class SystemBackupService {
|
|
72
80
|
private readonly dataDir;
|
|
73
81
|
private readonly logger;
|
|
74
|
-
|
|
82
|
+
private readonly statCacheTtlMs;
|
|
83
|
+
private readonly statCache;
|
|
84
|
+
constructor(dataDir: string, logger: IScopedLogger, opts?: SystemBackupServiceOptions);
|
|
75
85
|
/**
|
|
76
86
|
* Snapshot the current size + file count of each well-known
|
|
77
87
|
* location. Used by the admin UI to render an opt-in checklist
|
|
78
88
|
* before triggering a backup, and by `createArchive` to derive the
|
|
79
89
|
* embedded manifest.
|
|
90
|
+
*
|
|
91
|
+
* The walk is async (yields to the event loop per directory) and
|
|
92
|
+
* per-location results are cached + single-flighted: the service
|
|
93
|
+
* runs in-process in the hub, and a synchronous walk of the 70k+
|
|
94
|
+
* file `addons` location blocked the event loop long enough to kill
|
|
95
|
+
* WS keepalives cluster-wide.
|
|
80
96
|
*/
|
|
81
|
-
statLocations(locations?: readonly string[]): readonly LocationStat[]
|
|
97
|
+
statLocations(locations?: readonly string[]): Promise<readonly LocationStat[]>;
|
|
98
|
+
private statLocationCached;
|
|
99
|
+
private statLocation;
|
|
82
100
|
/**
|
|
83
101
|
* Create a tar.gz of the given locations. Uses the `tar` npm package
|
|
84
102
|
* (used by npm itself) instead of shelling out — gives us:
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
|
|
|
21
21
|
require("./builtins/local-auth/index.js");
|
|
22
22
|
const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
|
|
23
23
|
require("./builtins/device-manager/index.js");
|
|
24
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
24
|
+
const require_manifest_python_deps = require("./manifest-python-deps-BGvIVCm_.js");
|
|
25
25
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
26
26
|
let _camstack_types_node = require("@camstack/types/node");
|
|
27
27
|
let zod = require("zod");
|
|
@@ -2587,6 +2587,71 @@ async function copyDirRecursive(src, dest) {
|
|
|
2587
2587
|
});
|
|
2588
2588
|
}
|
|
2589
2589
|
/**
|
|
2590
|
+
* Runtime natives that must stay installable even when an addon forgets to
|
|
2591
|
+
* declare them: the mirror of the build preset's `COMMON_NATIVE_DEPS`
|
|
2592
|
+
* (tools/build/vite-lib.preset.ts — build tooling, not loadable at runtime).
|
|
2593
|
+
* These are the ONLY packages a self-contained dist genuinely `require()`s
|
|
2594
|
+
* from node_modules; everything else is already inlined by the bundle.
|
|
2595
|
+
*/
|
|
2596
|
+
var RUNTIME_NATIVE_KEEP = [
|
|
2597
|
+
"better-sqlite3",
|
|
2598
|
+
"node-av",
|
|
2599
|
+
"onnxruntime-node",
|
|
2600
|
+
"sharp",
|
|
2601
|
+
"ssh2",
|
|
2602
|
+
"werift",
|
|
2603
|
+
"systeminformation"
|
|
2604
|
+
];
|
|
2605
|
+
/** Read `camstack.runtimeDependencies` (extra non-native deps the dist
|
|
2606
|
+
* requires at runtime — versions come from the manifest's own dep maps). */
|
|
2607
|
+
function readRuntimeDependencies(pkg) {
|
|
2608
|
+
const camstack = pkg.camstack;
|
|
2609
|
+
if (camstack === null || typeof camstack !== "object" || Array.isArray(camstack)) return [];
|
|
2610
|
+
const raw = camstack.runtimeDependencies;
|
|
2611
|
+
if (!Array.isArray(raw)) return [];
|
|
2612
|
+
return raw.filter((entry) => typeof entry === "string");
|
|
2613
|
+
}
|
|
2614
|
+
/**
|
|
2615
|
+
* Strip every dependency an addon's self-contained dist has already bundled,
|
|
2616
|
+
* keeping ONLY what must resolve from node_modules at runtime:
|
|
2617
|
+
*
|
|
2618
|
+
* keep = RUNTIME_NATIVE_KEEP ∪ camstack.runtimeDependencies (minus @camstack/*)
|
|
2619
|
+
*
|
|
2620
|
+
* Addon dists are fully bundled (vite `externals: 'self-contained'`), yet the
|
|
2621
|
+
* blanket `npm install` of the manifest's dependencies re-installed the whole
|
|
2622
|
+
* tree the dist already contains — 98% of the deployed addons dir was
|
|
2623
|
+
* redundant node_modules (74k files / 1.34 GB on the live hub; it stalled the
|
|
2624
|
+
* backup walk and bloated every deploy). Kept PEER deps are folded into
|
|
2625
|
+
* `dependencies` so `--omit=peer` installs can't drop them (pipeline's
|
|
2626
|
+
* patched `werift`).
|
|
2627
|
+
*
|
|
2628
|
+
* Escape hatch: `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy behaviour
|
|
2629
|
+
* (strip only @camstack/*) for debugging a suspected undeclared runtime dep.
|
|
2630
|
+
*
|
|
2631
|
+
* Returns a new object (immutable).
|
|
2632
|
+
*/
|
|
2633
|
+
function stripBundledDeps(pkg) {
|
|
2634
|
+
if (process.env.CAMSTACK_INSTALL_FULL_DEPS === "1") return stripCamstackDeps(pkg);
|
|
2635
|
+
const camstack = pkg.camstack;
|
|
2636
|
+
if (camstack !== null && typeof camstack === "object" && !Array.isArray(camstack) && camstack.system === true) return stripCamstackDeps(pkg);
|
|
2637
|
+
const keep = new Set([...RUNTIME_NATIVE_KEEP, ...readRuntimeDependencies(pkg)]);
|
|
2638
|
+
const kept = {};
|
|
2639
|
+
for (const depType of ["dependencies", "peerDependencies"]) {
|
|
2640
|
+
const rawDeps = pkg[depType];
|
|
2641
|
+
if (rawDeps === null || typeof rawDeps !== "object" || Array.isArray(rawDeps)) continue;
|
|
2642
|
+
for (const [name, version] of Object.entries(rawDeps)) {
|
|
2643
|
+
if (name.startsWith("@camstack/")) continue;
|
|
2644
|
+
if (!keep.has(name) || typeof version !== "string") continue;
|
|
2645
|
+
if (!(name in kept)) kept[name] = version;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
const result = { ...pkg };
|
|
2649
|
+
result.dependencies = Object.keys(kept).length > 0 ? kept : void 0;
|
|
2650
|
+
result.peerDependencies = void 0;
|
|
2651
|
+
delete result.devDependencies;
|
|
2652
|
+
return result;
|
|
2653
|
+
}
|
|
2654
|
+
/**
|
|
2590
2655
|
* Strip @camstack/* dependencies and devDependencies from a package.json object.
|
|
2591
2656
|
* Used when installing addons into the addons directory — @camstack packages
|
|
2592
2657
|
* are provided by the host runtime, not installed per-addon.
|
|
@@ -3171,7 +3236,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3171
3236
|
force: true
|
|
3172
3237
|
});
|
|
3173
3238
|
ensureDir(targetDir);
|
|
3174
|
-
await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(
|
|
3239
|
+
await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
|
|
3175
3240
|
await copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
|
|
3176
3241
|
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3177
3242
|
await node_fs.promises.writeFile(node_path.join(targetDir, ".install-source"), "local");
|
|
@@ -3180,7 +3245,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3180
3245
|
version: localPkgVersion,
|
|
3181
3246
|
source: "local"
|
|
3182
3247
|
});
|
|
3183
|
-
const strippedDeps =
|
|
3248
|
+
const strippedDeps = stripBundledDeps(pkgData);
|
|
3184
3249
|
if (strippedDeps["dependencies"] && typeof strippedDeps["dependencies"] === "object" && Object.keys(strippedDeps["dependencies"]).length > 0) try {
|
|
3185
3250
|
await execFileAsync("npm", [
|
|
3186
3251
|
"install",
|
|
@@ -3358,7 +3423,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3358
3423
|
if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
|
|
3359
3424
|
if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
|
|
3360
3425
|
const targetDir = node_path.join(this.addonsDir, pkgView.name);
|
|
3361
|
-
const strippedManifest =
|
|
3426
|
+
const strippedManifest = stripBundledDeps(pkgView.raw);
|
|
3362
3427
|
await node_fs.promises.writeFile(pkgJsonPath, JSON.stringify(strippedManifest, null, 2));
|
|
3363
3428
|
const strippedRuntimeDeps = strippedManifest["dependencies"];
|
|
3364
3429
|
if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
|
|
@@ -92987,6 +93052,30 @@ var StagingArea = class {
|
|
|
92987
93052
|
force: true
|
|
92988
93053
|
});
|
|
92989
93054
|
}
|
|
93055
|
+
/**
|
|
93056
|
+
* Remove every staged dir under `stagingDir`. Safe — and meant — to run once
|
|
93057
|
+
* at boot: `cleanup(jobId)` only fires when a lifecycle job finishes, so a
|
|
93058
|
+
* restart (or crash) that interrupts a job mid-flight leaves its
|
|
93059
|
+
* `<stagingDir>/<jobId>/` behind forever. At boot no job is in flight, so any
|
|
93060
|
+
* entry present is an orphan. Returns the number of orphan dirs removed.
|
|
93061
|
+
*/
|
|
93062
|
+
sweepOrphans() {
|
|
93063
|
+
let entries;
|
|
93064
|
+
try {
|
|
93065
|
+
entries = node_fs.readdirSync(this.stagingDir);
|
|
93066
|
+
} catch {
|
|
93067
|
+
return 0;
|
|
93068
|
+
}
|
|
93069
|
+
let removed = 0;
|
|
93070
|
+
for (const name of entries) try {
|
|
93071
|
+
node_fs.rmSync(node_path.join(this.stagingDir, name), {
|
|
93072
|
+
recursive: true,
|
|
93073
|
+
force: true
|
|
93074
|
+
});
|
|
93075
|
+
removed += 1;
|
|
93076
|
+
} catch {}
|
|
93077
|
+
return removed;
|
|
93078
|
+
}
|
|
92990
93079
|
};
|
|
92991
93080
|
//#endregion
|
|
92992
93081
|
//#region src/kernel/lifecycle/lifecycle-job-engine.ts
|
package/dist/index.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { LocalAuthAddon, a as require_ms, c as __esmMin, d as __toCommonJS, f as
|
|
|
19
19
|
import "./builtins/local-auth/index.mjs";
|
|
20
20
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
21
21
|
import "./builtins/device-manager/index.mjs";
|
|
22
|
-
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-
|
|
22
|
+
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-BjxBfiFd.mjs";
|
|
23
23
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
24
24
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
25
25
|
import { z } from "zod";
|
|
@@ -2579,6 +2579,71 @@ async function copyDirRecursive(src, dest) {
|
|
|
2579
2579
|
});
|
|
2580
2580
|
}
|
|
2581
2581
|
/**
|
|
2582
|
+
* Runtime natives that must stay installable even when an addon forgets to
|
|
2583
|
+
* declare them: the mirror of the build preset's `COMMON_NATIVE_DEPS`
|
|
2584
|
+
* (tools/build/vite-lib.preset.ts — build tooling, not loadable at runtime).
|
|
2585
|
+
* These are the ONLY packages a self-contained dist genuinely `require()`s
|
|
2586
|
+
* from node_modules; everything else is already inlined by the bundle.
|
|
2587
|
+
*/
|
|
2588
|
+
var RUNTIME_NATIVE_KEEP = [
|
|
2589
|
+
"better-sqlite3",
|
|
2590
|
+
"node-av",
|
|
2591
|
+
"onnxruntime-node",
|
|
2592
|
+
"sharp",
|
|
2593
|
+
"ssh2",
|
|
2594
|
+
"werift",
|
|
2595
|
+
"systeminformation"
|
|
2596
|
+
];
|
|
2597
|
+
/** Read `camstack.runtimeDependencies` (extra non-native deps the dist
|
|
2598
|
+
* requires at runtime — versions come from the manifest's own dep maps). */
|
|
2599
|
+
function readRuntimeDependencies(pkg) {
|
|
2600
|
+
const camstack = pkg.camstack;
|
|
2601
|
+
if (camstack === null || typeof camstack !== "object" || Array.isArray(camstack)) return [];
|
|
2602
|
+
const raw = camstack.runtimeDependencies;
|
|
2603
|
+
if (!Array.isArray(raw)) return [];
|
|
2604
|
+
return raw.filter((entry) => typeof entry === "string");
|
|
2605
|
+
}
|
|
2606
|
+
/**
|
|
2607
|
+
* Strip every dependency an addon's self-contained dist has already bundled,
|
|
2608
|
+
* keeping ONLY what must resolve from node_modules at runtime:
|
|
2609
|
+
*
|
|
2610
|
+
* keep = RUNTIME_NATIVE_KEEP ∪ camstack.runtimeDependencies (minus @camstack/*)
|
|
2611
|
+
*
|
|
2612
|
+
* Addon dists are fully bundled (vite `externals: 'self-contained'`), yet the
|
|
2613
|
+
* blanket `npm install` of the manifest's dependencies re-installed the whole
|
|
2614
|
+
* tree the dist already contains — 98% of the deployed addons dir was
|
|
2615
|
+
* redundant node_modules (74k files / 1.34 GB on the live hub; it stalled the
|
|
2616
|
+
* backup walk and bloated every deploy). Kept PEER deps are folded into
|
|
2617
|
+
* `dependencies` so `--omit=peer` installs can't drop them (pipeline's
|
|
2618
|
+
* patched `werift`).
|
|
2619
|
+
*
|
|
2620
|
+
* Escape hatch: `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy behaviour
|
|
2621
|
+
* (strip only @camstack/*) for debugging a suspected undeclared runtime dep.
|
|
2622
|
+
*
|
|
2623
|
+
* Returns a new object (immutable).
|
|
2624
|
+
*/
|
|
2625
|
+
function stripBundledDeps(pkg) {
|
|
2626
|
+
if (process.env.CAMSTACK_INSTALL_FULL_DEPS === "1") return stripCamstackDeps(pkg);
|
|
2627
|
+
const camstack = pkg.camstack;
|
|
2628
|
+
if (camstack !== null && typeof camstack === "object" && !Array.isArray(camstack) && camstack.system === true) return stripCamstackDeps(pkg);
|
|
2629
|
+
const keep = new Set([...RUNTIME_NATIVE_KEEP, ...readRuntimeDependencies(pkg)]);
|
|
2630
|
+
const kept = {};
|
|
2631
|
+
for (const depType of ["dependencies", "peerDependencies"]) {
|
|
2632
|
+
const rawDeps = pkg[depType];
|
|
2633
|
+
if (rawDeps === null || typeof rawDeps !== "object" || Array.isArray(rawDeps)) continue;
|
|
2634
|
+
for (const [name, version] of Object.entries(rawDeps)) {
|
|
2635
|
+
if (name.startsWith("@camstack/")) continue;
|
|
2636
|
+
if (!keep.has(name) || typeof version !== "string") continue;
|
|
2637
|
+
if (!(name in kept)) kept[name] = version;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
const result = { ...pkg };
|
|
2641
|
+
result.dependencies = Object.keys(kept).length > 0 ? kept : void 0;
|
|
2642
|
+
result.peerDependencies = void 0;
|
|
2643
|
+
delete result.devDependencies;
|
|
2644
|
+
return result;
|
|
2645
|
+
}
|
|
2646
|
+
/**
|
|
2582
2647
|
* Strip @camstack/* dependencies and devDependencies from a package.json object.
|
|
2583
2648
|
* Used when installing addons into the addons directory — @camstack packages
|
|
2584
2649
|
* are provided by the host runtime, not installed per-addon.
|
|
@@ -3163,7 +3228,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3163
3228
|
force: true
|
|
3164
3229
|
});
|
|
3165
3230
|
ensureDir(targetDir);
|
|
3166
|
-
await fs$17.promises.writeFile(path$39.join(targetDir, "package.json"), JSON.stringify(
|
|
3231
|
+
await fs$17.promises.writeFile(path$39.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
|
|
3167
3232
|
await copyDirRecursive(distDir, path$39.join(targetDir, "dist"));
|
|
3168
3233
|
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3169
3234
|
await fs$17.promises.writeFile(path$39.join(targetDir, ".install-source"), "local");
|
|
@@ -3172,7 +3237,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3172
3237
|
version: localPkgVersion,
|
|
3173
3238
|
source: "local"
|
|
3174
3239
|
});
|
|
3175
|
-
const strippedDeps =
|
|
3240
|
+
const strippedDeps = stripBundledDeps(pkgData);
|
|
3176
3241
|
if (strippedDeps["dependencies"] && typeof strippedDeps["dependencies"] === "object" && Object.keys(strippedDeps["dependencies"]).length > 0) try {
|
|
3177
3242
|
await execFileAsync("npm", [
|
|
3178
3243
|
"install",
|
|
@@ -3350,7 +3415,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3350
3415
|
if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
|
|
3351
3416
|
if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
|
|
3352
3417
|
const targetDir = path$39.join(this.addonsDir, pkgView.name);
|
|
3353
|
-
const strippedManifest =
|
|
3418
|
+
const strippedManifest = stripBundledDeps(pkgView.raw);
|
|
3354
3419
|
await fs$17.promises.writeFile(pkgJsonPath, JSON.stringify(strippedManifest, null, 2));
|
|
3355
3420
|
const strippedRuntimeDeps = strippedManifest["dependencies"];
|
|
3356
3421
|
if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
|
|
@@ -92979,6 +93044,30 @@ var StagingArea = class {
|
|
|
92979
93044
|
force: true
|
|
92980
93045
|
});
|
|
92981
93046
|
}
|
|
93047
|
+
/**
|
|
93048
|
+
* Remove every staged dir under `stagingDir`. Safe — and meant — to run once
|
|
93049
|
+
* at boot: `cleanup(jobId)` only fires when a lifecycle job finishes, so a
|
|
93050
|
+
* restart (or crash) that interrupts a job mid-flight leaves its
|
|
93051
|
+
* `<stagingDir>/<jobId>/` behind forever. At boot no job is in flight, so any
|
|
93052
|
+
* entry present is an orphan. Returns the number of orphan dirs removed.
|
|
93053
|
+
*/
|
|
93054
|
+
sweepOrphans() {
|
|
93055
|
+
let entries;
|
|
93056
|
+
try {
|
|
93057
|
+
entries = fs$17.readdirSync(this.stagingDir);
|
|
93058
|
+
} catch {
|
|
93059
|
+
return 0;
|
|
93060
|
+
}
|
|
93061
|
+
let removed = 0;
|
|
93062
|
+
for (const name of entries) try {
|
|
93063
|
+
fs$17.rmSync(path$39.join(this.stagingDir, name), {
|
|
93064
|
+
recursive: true,
|
|
93065
|
+
force: true
|
|
93066
|
+
});
|
|
93067
|
+
removed += 1;
|
|
93068
|
+
} catch {}
|
|
93069
|
+
return removed;
|
|
93070
|
+
}
|
|
92982
93071
|
};
|
|
92983
93072
|
//#endregion
|
|
92984
93073
|
//#region src/kernel/lifecycle/lifecycle-job-engine.ts
|
|
@@ -14,6 +14,34 @@ export declare function ensureDir(dirPath: string): void;
|
|
|
14
14
|
* `fs.promises.cp` keeps the I/O off the event loop. (Node ≥18 stable.)
|
|
15
15
|
*/
|
|
16
16
|
export declare function copyDirRecursive(src: string, dest: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Runtime natives that must stay installable even when an addon forgets to
|
|
19
|
+
* declare them: the mirror of the build preset's `COMMON_NATIVE_DEPS`
|
|
20
|
+
* (tools/build/vite-lib.preset.ts — build tooling, not loadable at runtime).
|
|
21
|
+
* These are the ONLY packages a self-contained dist genuinely `require()`s
|
|
22
|
+
* from node_modules; everything else is already inlined by the bundle.
|
|
23
|
+
*/
|
|
24
|
+
export declare const RUNTIME_NATIVE_KEEP: readonly string[];
|
|
25
|
+
/**
|
|
26
|
+
* Strip every dependency an addon's self-contained dist has already bundled,
|
|
27
|
+
* keeping ONLY what must resolve from node_modules at runtime:
|
|
28
|
+
*
|
|
29
|
+
* keep = RUNTIME_NATIVE_KEEP ∪ camstack.runtimeDependencies (minus @camstack/*)
|
|
30
|
+
*
|
|
31
|
+
* Addon dists are fully bundled (vite `externals: 'self-contained'`), yet the
|
|
32
|
+
* blanket `npm install` of the manifest's dependencies re-installed the whole
|
|
33
|
+
* tree the dist already contains — 98% of the deployed addons dir was
|
|
34
|
+
* redundant node_modules (74k files / 1.34 GB on the live hub; it stalled the
|
|
35
|
+
* backup walk and bloated every deploy). Kept PEER deps are folded into
|
|
36
|
+
* `dependencies` so `--omit=peer` installs can't drop them (pipeline's
|
|
37
|
+
* patched `werift`).
|
|
38
|
+
*
|
|
39
|
+
* Escape hatch: `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy behaviour
|
|
40
|
+
* (strip only @camstack/*) for debugging a suspected undeclared runtime dep.
|
|
41
|
+
*
|
|
42
|
+
* Returns a new object (immutable).
|
|
43
|
+
*/
|
|
44
|
+
export declare function stripBundledDeps(pkg: Record<string, unknown>): Record<string, unknown>;
|
|
17
45
|
/**
|
|
18
46
|
* Strip @camstack/* dependencies and devDependencies from a package.json object.
|
|
19
47
|
* Used when installing addons into the addons directory — @camstack packages
|
|
@@ -18,5 +18,13 @@ export declare class StagingArea {
|
|
|
18
18
|
stagedPath: string;
|
|
19
19
|
}>;
|
|
20
20
|
cleanup(jobId: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Remove every staged dir under `stagingDir`. Safe — and meant — to run once
|
|
23
|
+
* at boot: `cleanup(jobId)` only fires when a lifecycle job finishes, so a
|
|
24
|
+
* restart (or crash) that interrupts a job mid-flight leaves its
|
|
25
|
+
* `<stagingDir>/<jobId>/` behind forever. At boot no job is in flight, so any
|
|
26
|
+
* entry present is an orphan. Returns the number of orphan dirs removed.
|
|
27
|
+
*/
|
|
28
|
+
sweepOrphans(): number;
|
|
21
29
|
}
|
|
22
30
|
export {};
|
|
@@ -4529,7 +4529,8 @@ var LocalChildClient = class {
|
|
|
4529
4529
|
capName: msg.capName,
|
|
4530
4530
|
method: msg.method,
|
|
4531
4531
|
args: msg.args,
|
|
4532
|
-
...msg.deviceId !== void 0 ? { deviceId: msg.deviceId } : {}
|
|
4532
|
+
...msg.deviceId !== void 0 ? { deviceId: msg.deviceId } : {},
|
|
4533
|
+
...msg.addonId !== void 0 ? { addonId: msg.addonId } : {}
|
|
4533
4534
|
});
|
|
4534
4535
|
if (msg.kind === "addon-call") {
|
|
4535
4536
|
if (this.addonCallHandler === null) throw new Error(`LocalChildClient: addon-call for "${msg.addonId}" arrived but no onAddonCall handler is registered`);
|
|
@@ -4527,7 +4527,8 @@ var LocalChildClient = class {
|
|
|
4527
4527
|
capName: msg.capName,
|
|
4528
4528
|
method: msg.method,
|
|
4529
4529
|
args: msg.args,
|
|
4530
|
-
...msg.deviceId !== void 0 ? { deviceId: msg.deviceId } : {}
|
|
4530
|
+
...msg.deviceId !== void 0 ? { deviceId: msg.deviceId } : {},
|
|
4531
|
+
...msg.addonId !== void 0 ? { addonId: msg.addonId } : {}
|
|
4531
4532
|
});
|
|
4532
4533
|
if (msg.kind === "addon-call") {
|
|
4533
4534
|
if (this.addonCallHandler === null) throw new Error(`LocalChildClient: addon-call for "${msg.addonId}" arrived but no onAddonCall handler is registered`);
|