@camstack/system 1.2.2 → 1.2.3
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 +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/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 +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/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 +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-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-DTTTjPCL.mjs → dist-72yufD8v.mjs} +2 -1
- package/dist/{dist-CkdNC8US.js → dist-CQZxGJ8u.js} +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +163 -21
- package/dist/index.mjs +156 -16
- package/dist/kernel/deps/ensure-native-prebuilds.d.ts +36 -0
- package/dist/kernel/deps/manifest-native-deps.d.ts +17 -0
- package/dist/{manifest-python-deps-s_-uULmp.mjs → manifest-python-deps-6__QF75g.mjs} +88 -2
- package/dist/{manifest-python-deps-DRq5MreI.js → manifest-python-deps-Cd7ocUBi.js} +93 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-CQZxGJ8u.js");
|
|
4
4
|
const require_model_download_service = require("./model-download-service-hf0ookyy.js");
|
|
5
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
5
|
+
const require_manifest_python_deps = require("./manifest-python-deps-Cd7ocUBi.js");
|
|
6
6
|
const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
|
|
7
7
|
const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
|
|
8
8
|
const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
|
|
@@ -184,7 +184,7 @@ function proxyToUpstream(opts) {
|
|
|
184
184
|
}
|
|
185
185
|
//#endregion
|
|
186
186
|
//#region src/python/python-env-manager.ts
|
|
187
|
-
var execFileAsync$
|
|
187
|
+
var execFileAsync$4 = (0, node_util.promisify)(node_child_process.execFile);
|
|
188
188
|
var PythonEnvManager = class {
|
|
189
189
|
venvPath;
|
|
190
190
|
cachedProbe = null;
|
|
@@ -194,12 +194,12 @@ var PythonEnvManager = class {
|
|
|
194
194
|
async probe() {
|
|
195
195
|
if (this.cachedProbe) return this.cachedProbe;
|
|
196
196
|
for (const cmd of ["python3", "python"]) try {
|
|
197
|
-
const { stdout } = await execFileAsync$
|
|
197
|
+
const { stdout } = await execFileAsync$4(cmd, ["--version"]);
|
|
198
198
|
const version = stdout.trim().replace("Python ", "");
|
|
199
199
|
const major = parseInt(version.split(".")[0] ?? "0", 10);
|
|
200
200
|
const minor = parseInt(version.split(".")[1] ?? "0", 10);
|
|
201
201
|
if (major < 3 || major === 3 && minor < 10) continue;
|
|
202
|
-
const { stdout: pathOut } = await execFileAsync$
|
|
202
|
+
const { stdout: pathOut } = await execFileAsync$4(cmd, ["-c", "import sys; print(sys.executable)"]);
|
|
203
203
|
this.cachedProbe = {
|
|
204
204
|
available: true,
|
|
205
205
|
version,
|
|
@@ -215,13 +215,13 @@ var PythonEnvManager = class {
|
|
|
215
215
|
async ensure(options) {
|
|
216
216
|
const probe = await this.probe();
|
|
217
217
|
if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
|
|
218
|
-
if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$
|
|
218
|
+
if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$4(probe.path, [
|
|
219
219
|
"-m",
|
|
220
220
|
"venv",
|
|
221
221
|
this.venvPath
|
|
222
222
|
]);
|
|
223
223
|
const venvPython = node_path.join(this.venvPath, "bin", "python");
|
|
224
|
-
if (options.packages.length > 0) await execFileAsync$
|
|
224
|
+
if (options.packages.length > 0) await execFileAsync$4(venvPython, [
|
|
225
225
|
"-m",
|
|
226
226
|
"pip",
|
|
227
227
|
"install",
|
|
@@ -1692,7 +1692,7 @@ function matchPath(pattern, path) {
|
|
|
1692
1692
|
}
|
|
1693
1693
|
//#endregion
|
|
1694
1694
|
//#region src/tls/cert-manager.ts
|
|
1695
|
-
var execFileAsync$
|
|
1695
|
+
var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
|
|
1696
1696
|
/**
|
|
1697
1697
|
* Ensure a self-signed TLS certificate exists in the given directory.
|
|
1698
1698
|
* Generates one if missing. Returns paths to cert and key files.
|
|
@@ -1729,7 +1729,7 @@ async function ensureTlsCert(dataDir, options) {
|
|
|
1729
1729
|
for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
|
|
1730
1730
|
for (const ip of sanIps) sanParts.push(`IP:${ip}`);
|
|
1731
1731
|
const sanString = sanParts.join(",");
|
|
1732
|
-
await execFileAsync$
|
|
1732
|
+
await execFileAsync$3("openssl", [
|
|
1733
1733
|
"req",
|
|
1734
1734
|
"-x509",
|
|
1735
1735
|
"-newkey",
|
|
@@ -2597,7 +2597,7 @@ var AddonEngineManager = class {
|
|
|
2597
2597
|
};
|
|
2598
2598
|
//#endregion
|
|
2599
2599
|
//#region src/kernel/fs-utils.ts
|
|
2600
|
-
var execFileAsync$
|
|
2600
|
+
var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
|
|
2601
2601
|
/**
|
|
2602
2602
|
* Ensure a directory exists (recursive).
|
|
2603
2603
|
* Single source of truth — replaces scattered mkdirSync calls.
|
|
@@ -2781,7 +2781,7 @@ function ensureLibraryBuilt(packageName, packagesDir) {
|
|
|
2781
2781
|
async function installPackageFromNpm(packageName, targetDir) {
|
|
2782
2782
|
const tmpDir = await node_fs.promises.mkdtemp(node_path.join(node_os.tmpdir(), "camstack-install-"));
|
|
2783
2783
|
try {
|
|
2784
|
-
const { stdout } = await execFileAsync$
|
|
2784
|
+
const { stdout } = await execFileAsync$2("npm", [
|
|
2785
2785
|
"pack",
|
|
2786
2786
|
packageName,
|
|
2787
2787
|
"--pack-destination",
|
|
@@ -2795,7 +2795,7 @@ async function installPackageFromNpm(packageName, targetDir) {
|
|
|
2795
2795
|
const tgzPath = node_path.join(tmpDir, tgzFilename);
|
|
2796
2796
|
const extractDir = node_path.join(tmpDir, "extracted");
|
|
2797
2797
|
ensureDir(extractDir);
|
|
2798
|
-
await execFileAsync$
|
|
2798
|
+
await execFileAsync$2("tar", [
|
|
2799
2799
|
"-xzf",
|
|
2800
2800
|
tgzPath,
|
|
2801
2801
|
"-C",
|
|
@@ -3031,7 +3031,7 @@ var AddonManifest = class {
|
|
|
3031
3031
|
};
|
|
3032
3032
|
//#endregion
|
|
3033
3033
|
//#region src/kernel/addon-installer.ts
|
|
3034
|
-
var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
|
|
3034
|
+
var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
|
|
3035
3035
|
function parseInstallSource(value) {
|
|
3036
3036
|
switch (value) {
|
|
3037
3037
|
case "npm":
|
|
@@ -3318,6 +3318,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3318
3318
|
await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
|
|
3319
3319
|
await copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
|
|
3320
3320
|
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3321
|
+
require_manifest_python_deps.copyBundledNativeModules(sourceDir, targetDir, this.logger);
|
|
3321
3322
|
await node_fs.promises.writeFile(node_path.join(targetDir, ".install-source"), "local");
|
|
3322
3323
|
const localPkgVersion = require_dist.asString(pkgData.version, "0.0.0");
|
|
3323
3324
|
this.manifest.upsert(packageName, {
|
|
@@ -3488,7 +3489,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3488
3489
|
const stagingDir = node_path.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
|
|
3489
3490
|
ensureDir(stagingDir);
|
|
3490
3491
|
try {
|
|
3491
|
-
await execFileAsync("tar", [
|
|
3492
|
+
await execFileAsync$1("tar", [
|
|
3492
3493
|
"-xzf",
|
|
3493
3494
|
tgzPath,
|
|
3494
3495
|
"-C",
|
|
@@ -80143,7 +80144,7 @@ var require_compression = /* @__PURE__ */ require_chunk.__commonJSMin(((exports,
|
|
|
80143
80144
|
var { defaultsDeep } = require_lodash();
|
|
80144
80145
|
var { parseByteString } = require_utils$3();
|
|
80145
80146
|
var zlib = require("zlib");
|
|
80146
|
-
var { promisify } = require("util");
|
|
80147
|
+
var { promisify: promisify$1 } = require("util");
|
|
80147
80148
|
/**
|
|
80148
80149
|
* This is a transmission compression middleware. It supports
|
|
80149
80150
|
* the `deflate`, `deflateRaw` & `gzip` compression methods.
|
|
@@ -80161,16 +80162,16 @@ var require_compression = /* @__PURE__ */ require_chunk.__commonJSMin(((exports,
|
|
|
80161
80162
|
const threshold = parseByteString(opts.threshold);
|
|
80162
80163
|
switch (opts.method) {
|
|
80163
80164
|
case "deflate":
|
|
80164
|
-
compress = promisify(zlib.deflate);
|
|
80165
|
-
decompress = promisify(zlib.inflate);
|
|
80165
|
+
compress = promisify$1(zlib.deflate);
|
|
80166
|
+
decompress = promisify$1(zlib.inflate);
|
|
80166
80167
|
break;
|
|
80167
80168
|
case "deflateRaw":
|
|
80168
|
-
compress = promisify(zlib.deflateRaw);
|
|
80169
|
-
decompress = promisify(zlib.inflateRaw);
|
|
80169
|
+
compress = promisify$1(zlib.deflateRaw);
|
|
80170
|
+
decompress = promisify$1(zlib.inflateRaw);
|
|
80170
80171
|
break;
|
|
80171
80172
|
case "gzip":
|
|
80172
|
-
compress = promisify(zlib.gzip);
|
|
80173
|
-
decompress = promisify(zlib.gunzip);
|
|
80173
|
+
compress = promisify$1(zlib.gzip);
|
|
80174
|
+
decompress = promisify$1(zlib.gunzip);
|
|
80174
80175
|
break;
|
|
80175
80176
|
default:
|
|
80176
80177
|
/* istanbul ignore next */
|
|
@@ -93397,6 +93398,145 @@ var LifecycleJobEngine = class {
|
|
|
93397
93398
|
}
|
|
93398
93399
|
};
|
|
93399
93400
|
//#endregion
|
|
93401
|
+
//#region src/kernel/deps/ensure-native-prebuilds.ts
|
|
93402
|
+
/**
|
|
93403
|
+
* `ensureNativePrebuilds` — the post-install native-prebuild ENSURE step the
|
|
93404
|
+
* shared `RootUpdateService` runs while staging a `@camstack/server` closure,
|
|
93405
|
+
* BEFORE its `findMissingNativePrebuilds` validator (in `@camstack/node-root`)
|
|
93406
|
+
* decides whether to arm the swap.
|
|
93407
|
+
*
|
|
93408
|
+
* Why this exists (Mac desktop incident, 2026-07-21): a runtime
|
|
93409
|
+
* `applyServerUpdate` on a packaged desktop stages the closure with
|
|
93410
|
+
* `npm install @camstack/server@X` under the app's BUNDLED bare Node. The one
|
|
93411
|
+
* TRADITIONAL (non-N-API) native, `better-sqlite3`, resolves its `.node` via
|
|
93412
|
+
* its `install` script `prebuild-install || node-gyp rebuild`. On a user's Mac
|
|
93413
|
+
* with no build toolchain (and where the auto `prebuild-install` does not
|
|
93414
|
+
* target the bundled Node's ABI/arch the way the DMG build's EXPLICIT
|
|
93415
|
+
* `prebuild-install --runtime node --target <bundled> --arch <arch>` call does)
|
|
93416
|
+
* that leaves the module SOURCE-ONLY → the closure has no `better-sqlite3`
|
|
93417
|
+
* `.node` → the validator refuses the swap ("staged closure missing native
|
|
93418
|
+
* prebuilds: better-sqlite3"). The docker image never hits this: its Node ABI
|
|
93419
|
+
* has a published prebuild the auto path fetches cleanly, and it carries a
|
|
93420
|
+
* build toolchain fallback.
|
|
93421
|
+
*
|
|
93422
|
+
* This mirrors the DMG build's explicit re-fetch (`scripts/stage-deps.mjs`)
|
|
93423
|
+
* into the runtime staging path: for each traditional native that is present
|
|
93424
|
+
* in the closure but missing its compiled `.node`, fetch the prebuild for the
|
|
93425
|
+
* RUNNING Node ABI/arch (the same Node that will load the swapped closure).
|
|
93426
|
+
*
|
|
93427
|
+
* N-API natives (`sharp`, `node-av`) are ABI-stable and ship their binaries as
|
|
93428
|
+
* platform SIBLING packages that npm fetches reliably with no compile step, so
|
|
93429
|
+
* they are not in scope here — a genuine miss there is a broken install the
|
|
93430
|
+
* validator should still reject, not something a prebuild re-fetch can heal.
|
|
93431
|
+
*
|
|
93432
|
+
* Injected into the update service from the construction site so the zero-dep
|
|
93433
|
+
* `@camstack/node-root` layer never depends on npm/@camstack/system, and the
|
|
93434
|
+
* fetch is unit-testable with a fake fetcher.
|
|
93435
|
+
*/
|
|
93436
|
+
var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
|
|
93437
|
+
/** Bounded recursive `.node` scan depth inside a module dir. */
|
|
93438
|
+
var NATIVE_SCAN_DEPTH = 4;
|
|
93439
|
+
/** Timeout for a single `prebuild-install` fetch. */
|
|
93440
|
+
var PREBUILD_FETCH_TIMEOUT_MS = 12e4;
|
|
93441
|
+
/**
|
|
93442
|
+
* Traditional (compile-or-prebuild) natives an installed closure must carry a
|
|
93443
|
+
* `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
|
|
93444
|
+
* are excluded (see file header).
|
|
93445
|
+
*/
|
|
93446
|
+
var TRADITIONAL_NATIVE_PACKAGES = ["better-sqlite3"];
|
|
93447
|
+
/** Bounded recursive scan for ANY `*.node` file under `dir`. */
|
|
93448
|
+
function hasDotNode(dir, maxDepth) {
|
|
93449
|
+
let entries;
|
|
93450
|
+
try {
|
|
93451
|
+
entries = node_fs.readdirSync(dir, { withFileTypes: true });
|
|
93452
|
+
} catch {
|
|
93453
|
+
return false;
|
|
93454
|
+
}
|
|
93455
|
+
for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".node")) return true;
|
|
93456
|
+
if (maxDepth <= 0) return false;
|
|
93457
|
+
for (const entry of entries) if (entry.isDirectory() && hasDotNode(node_path.join(dir, entry.name), maxDepth - 1)) return true;
|
|
93458
|
+
return false;
|
|
93459
|
+
}
|
|
93460
|
+
/** Locate the bundled `prebuild-install` bin.js inside the staged closure. */
|
|
93461
|
+
function resolvePrebuildInstallBin(closureDir, moduleDir) {
|
|
93462
|
+
return [node_path.join(moduleDir, "node_modules", "prebuild-install", "bin.js"), node_path.join(closureDir, "node_modules", "prebuild-install", "bin.js")].find((c) => node_fs.existsSync(c)) ?? null;
|
|
93463
|
+
}
|
|
93464
|
+
/**
|
|
93465
|
+
* Default fetcher: run the closure's own `prebuild-install` under the CURRENT
|
|
93466
|
+
* Node (`process.execPath`) — no reliance on `npx`/`npm` on PATH (a packaged
|
|
93467
|
+
* app ships a bare Node). Explicitly targets the running ABI/arch, mirroring
|
|
93468
|
+
* `scripts/stage-deps.mjs`.
|
|
93469
|
+
*/
|
|
93470
|
+
function makeDefaultFetch(closureDir, logger) {
|
|
93471
|
+
return async (moduleDir, target) => {
|
|
93472
|
+
const bin = resolvePrebuildInstallBin(closureDir, moduleDir);
|
|
93473
|
+
if (bin === null) throw new Error(`prebuild-install not found in the staged closure for ${moduleDir}`);
|
|
93474
|
+
logger.info("fetching native prebuild via prebuild-install", { meta: {
|
|
93475
|
+
moduleDir,
|
|
93476
|
+
bin,
|
|
93477
|
+
nodeVersion: target.nodeVersion,
|
|
93478
|
+
arch: target.arch
|
|
93479
|
+
} });
|
|
93480
|
+
await execFileAsync(process.execPath, [
|
|
93481
|
+
bin,
|
|
93482
|
+
"--runtime",
|
|
93483
|
+
"node",
|
|
93484
|
+
"--target",
|
|
93485
|
+
target.nodeVersion,
|
|
93486
|
+
"--arch",
|
|
93487
|
+
target.arch
|
|
93488
|
+
], {
|
|
93489
|
+
cwd: moduleDir,
|
|
93490
|
+
timeout: PREBUILD_FETCH_TIMEOUT_MS
|
|
93491
|
+
});
|
|
93492
|
+
};
|
|
93493
|
+
}
|
|
93494
|
+
/**
|
|
93495
|
+
* Ensure every traditional native in `<closureDir>/node_modules` carries its
|
|
93496
|
+
* compiled `.node`, fetching the prebuild for the running ABI when missing.
|
|
93497
|
+
*
|
|
93498
|
+
* A NO-OP when nothing is missing (docker / tests) and when a native package is
|
|
93499
|
+
* absent from the closure. Never throws for a single package's fetch failure —
|
|
93500
|
+
* it logs and continues so the downstream `findMissingNativePrebuilds`
|
|
93501
|
+
* validator makes the final swap/abort decision. Returns the packages whose
|
|
93502
|
+
* prebuild was successfully fetched (for logging/tests).
|
|
93503
|
+
*/
|
|
93504
|
+
async function ensureNativePrebuilds(closureDir, options) {
|
|
93505
|
+
const nm = node_path.join(closureDir, "node_modules");
|
|
93506
|
+
const target = options.target ?? {
|
|
93507
|
+
nodeVersion: process.versions.node,
|
|
93508
|
+
arch: process.arch
|
|
93509
|
+
};
|
|
93510
|
+
const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
|
|
93511
|
+
const fetchPrebuild = options.fetchPrebuild ?? makeDefaultFetch(closureDir, options.logger);
|
|
93512
|
+
const fetched = [];
|
|
93513
|
+
for (const pkg of packages) {
|
|
93514
|
+
const moduleDir = node_path.join(nm, pkg);
|
|
93515
|
+
if (!node_fs.existsSync(moduleDir)) continue;
|
|
93516
|
+
if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) continue;
|
|
93517
|
+
options.logger.warn("staged closure native prebuild missing — fetching for running ABI", { meta: {
|
|
93518
|
+
pkg,
|
|
93519
|
+
moduleDir,
|
|
93520
|
+
nodeVersion: target.nodeVersion,
|
|
93521
|
+
arch: target.arch
|
|
93522
|
+
} });
|
|
93523
|
+
try {
|
|
93524
|
+
await fetchPrebuild(moduleDir, target);
|
|
93525
|
+
} catch (err) {
|
|
93526
|
+
options.logger.error("native prebuild fetch failed (validator will decide)", { meta: {
|
|
93527
|
+
pkg,
|
|
93528
|
+
error: (0, _camstack_types_addon.errMsg)(err)
|
|
93529
|
+
} });
|
|
93530
|
+
continue;
|
|
93531
|
+
}
|
|
93532
|
+
if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) {
|
|
93533
|
+
fetched.push(pkg);
|
|
93534
|
+
options.logger.info("native prebuild fetched", { meta: { pkg } });
|
|
93535
|
+
} else options.logger.error("native prebuild still missing after fetch", { meta: { pkg } });
|
|
93536
|
+
}
|
|
93537
|
+
return fetched;
|
|
93538
|
+
}
|
|
93539
|
+
//#endregion
|
|
93400
93540
|
exports.AGENT_CAP_FWD_ACTION = require_manifest_python_deps.AGENT_CAP_FWD_ACTION;
|
|
93401
93541
|
exports.AGENT_CAP_FWD_SERVICE = require_manifest_python_deps.AGENT_CAP_FWD_SERVICE;
|
|
93402
93542
|
exports.AGENT_READINESS_SERVICE_NAME = AGENT_READINESS_SERVICE_NAME;
|
|
@@ -93494,6 +93634,7 @@ exports.StorageOrchestratorAddon = require_builtins_storage_orchestrator_storage
|
|
|
93494
93634
|
exports.StorageOrchestratorService = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorService;
|
|
93495
93635
|
exports.SystemConfigAddon = require_builtins_system_config_system_config_addon.SystemConfigAddon;
|
|
93496
93636
|
exports.SystemEventBus = SystemEventBus;
|
|
93637
|
+
exports.TRADITIONAL_NATIVE_PACKAGES = TRADITIONAL_NATIVE_PACKAGES;
|
|
93497
93638
|
exports.ToastService = ToastService;
|
|
93498
93639
|
exports.UDS_NO_ROUTE_PREFIX = require_manifest_python_deps.UDS_NO_ROUTE_PREFIX;
|
|
93499
93640
|
exports.UdsLocalTransportClient = require_manifest_python_deps.UdsLocalTransportClient;
|
|
@@ -93586,6 +93727,7 @@ Object.defineProperty(exports, "ensureFfmpeg", {
|
|
|
93586
93727
|
});
|
|
93587
93728
|
exports.ensureLibraryBuilt = ensureLibraryBuilt;
|
|
93588
93729
|
exports.ensureModel = require_model_download_service.ensureModel;
|
|
93730
|
+
exports.ensureNativePrebuilds = ensureNativePrebuilds;
|
|
93589
93731
|
Object.defineProperty(exports, "ensurePython", {
|
|
93590
93732
|
enumerable: true,
|
|
93591
93733
|
get: function() {
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { At as EventCategory$1, Dt as resolveCapMount, Et as readinessKey, F as kebabToCamel, I as lifecycleJobSchema, K as procedureAuthKey, M as isCollectionArrayMethod, N as isObjectInput, O as extractNestedAddonId, Ot as scopeKey, P as isVoidInput, Tt as parseJsonUnknown$1, U as objectInputDeclaresAddonId, _t as asString$1, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, j as isArrayOutputSchema, o as METHOD_ACCESS_MAP, ot as DATAPLANE_SECRET_HEADER$1, p as addonSettingsCapability, pt as ReadinessTimeoutError, s as RUNTIME_DEFAULTS, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, wt as parseJsonObject, xt as expandCapMethods, yt as emitDownForOwnedCaps, z as looseSchema } from "./dist-
|
|
1
|
+
import { At as EventCategory$1, Dt as resolveCapMount, Et as readinessKey, F as kebabToCamel, I as lifecycleJobSchema, K as procedureAuthKey, M as isCollectionArrayMethod, N as isObjectInput, O as extractNestedAddonId, Ot as scopeKey, P as isVoidInput, Tt as parseJsonUnknown$1, U as objectInputDeclaresAddonId, _t as asString$1, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, j as isArrayOutputSchema, o as METHOD_ACCESS_MAP, ot as DATAPLANE_SECRET_HEADER$1, p as addonSettingsCapability, pt as ReadinessTimeoutError, s as RUNTIME_DEFAULTS, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, wt as parseJsonObject, xt as expandCapMethods, yt as emitDownForOwnedCaps, z as looseSchema } from "./dist-72yufD8v.mjs";
|
|
2
2
|
import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
|
|
3
|
-
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as
|
|
3
|
+
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-6__QF75g.mjs";
|
|
4
4
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Le3l0qS2.mjs";
|
|
5
5
|
import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
|
|
6
6
|
import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
|
|
@@ -29,7 +29,7 @@ import { accessSync, constants, existsSync, mkdirSync, readFileSync } from "node
|
|
|
29
29
|
import * as path$39 from "node:path";
|
|
30
30
|
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
31
31
|
import { X509Certificate, createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
32
|
-
import { asJsonObject, parseJsonUnknown } from "@camstack/types/addon";
|
|
32
|
+
import { asJsonObject, errMsg, parseJsonUnknown } from "@camstack/types/addon";
|
|
33
33
|
import { execFile, spawn } from "node:child_process";
|
|
34
34
|
import * as util$10 from "node:util";
|
|
35
35
|
import { promisify } from "node:util";
|
|
@@ -176,7 +176,7 @@ function proxyToUpstream(opts) {
|
|
|
176
176
|
}
|
|
177
177
|
//#endregion
|
|
178
178
|
//#region src/python/python-env-manager.ts
|
|
179
|
-
var execFileAsync$
|
|
179
|
+
var execFileAsync$4 = promisify(execFile);
|
|
180
180
|
var PythonEnvManager = class {
|
|
181
181
|
venvPath;
|
|
182
182
|
cachedProbe = null;
|
|
@@ -186,12 +186,12 @@ var PythonEnvManager = class {
|
|
|
186
186
|
async probe() {
|
|
187
187
|
if (this.cachedProbe) return this.cachedProbe;
|
|
188
188
|
for (const cmd of ["python3", "python"]) try {
|
|
189
|
-
const { stdout } = await execFileAsync$
|
|
189
|
+
const { stdout } = await execFileAsync$4(cmd, ["--version"]);
|
|
190
190
|
const version = stdout.trim().replace("Python ", "");
|
|
191
191
|
const major = parseInt(version.split(".")[0] ?? "0", 10);
|
|
192
192
|
const minor = parseInt(version.split(".")[1] ?? "0", 10);
|
|
193
193
|
if (major < 3 || major === 3 && minor < 10) continue;
|
|
194
|
-
const { stdout: pathOut } = await execFileAsync$
|
|
194
|
+
const { stdout: pathOut } = await execFileAsync$4(cmd, ["-c", "import sys; print(sys.executable)"]);
|
|
195
195
|
this.cachedProbe = {
|
|
196
196
|
available: true,
|
|
197
197
|
version,
|
|
@@ -207,13 +207,13 @@ var PythonEnvManager = class {
|
|
|
207
207
|
async ensure(options) {
|
|
208
208
|
const probe = await this.probe();
|
|
209
209
|
if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
|
|
210
|
-
if (!fs$17.existsSync(path$39.join(this.venvPath, "bin", "python"))) await execFileAsync$
|
|
210
|
+
if (!fs$17.existsSync(path$39.join(this.venvPath, "bin", "python"))) await execFileAsync$4(probe.path, [
|
|
211
211
|
"-m",
|
|
212
212
|
"venv",
|
|
213
213
|
this.venvPath
|
|
214
214
|
]);
|
|
215
215
|
const venvPython = path$39.join(this.venvPath, "bin", "python");
|
|
216
|
-
if (options.packages.length > 0) await execFileAsync$
|
|
216
|
+
if (options.packages.length > 0) await execFileAsync$4(venvPython, [
|
|
217
217
|
"-m",
|
|
218
218
|
"pip",
|
|
219
219
|
"install",
|
|
@@ -1684,7 +1684,7 @@ function matchPath(pattern, path) {
|
|
|
1684
1684
|
}
|
|
1685
1685
|
//#endregion
|
|
1686
1686
|
//#region src/tls/cert-manager.ts
|
|
1687
|
-
var execFileAsync$
|
|
1687
|
+
var execFileAsync$3 = promisify(execFile);
|
|
1688
1688
|
/**
|
|
1689
1689
|
* Ensure a self-signed TLS certificate exists in the given directory.
|
|
1690
1690
|
* Generates one if missing. Returns paths to cert and key files.
|
|
@@ -1721,7 +1721,7 @@ async function ensureTlsCert(dataDir, options) {
|
|
|
1721
1721
|
for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
|
|
1722
1722
|
for (const ip of sanIps) sanParts.push(`IP:${ip}`);
|
|
1723
1723
|
const sanString = sanParts.join(",");
|
|
1724
|
-
await execFileAsync$
|
|
1724
|
+
await execFileAsync$3("openssl", [
|
|
1725
1725
|
"req",
|
|
1726
1726
|
"-x509",
|
|
1727
1727
|
"-newkey",
|
|
@@ -2589,7 +2589,7 @@ var AddonEngineManager = class {
|
|
|
2589
2589
|
};
|
|
2590
2590
|
//#endregion
|
|
2591
2591
|
//#region src/kernel/fs-utils.ts
|
|
2592
|
-
var execFileAsync$
|
|
2592
|
+
var execFileAsync$2 = promisify(execFile);
|
|
2593
2593
|
/**
|
|
2594
2594
|
* Ensure a directory exists (recursive).
|
|
2595
2595
|
* Single source of truth — replaces scattered mkdirSync calls.
|
|
@@ -2773,7 +2773,7 @@ function ensureLibraryBuilt(packageName, packagesDir) {
|
|
|
2773
2773
|
async function installPackageFromNpm(packageName, targetDir) {
|
|
2774
2774
|
const tmpDir = await fs$17.promises.mkdtemp(path$39.join(os$18.tmpdir(), "camstack-install-"));
|
|
2775
2775
|
try {
|
|
2776
|
-
const { stdout } = await execFileAsync$
|
|
2776
|
+
const { stdout } = await execFileAsync$2("npm", [
|
|
2777
2777
|
"pack",
|
|
2778
2778
|
packageName,
|
|
2779
2779
|
"--pack-destination",
|
|
@@ -2787,7 +2787,7 @@ async function installPackageFromNpm(packageName, targetDir) {
|
|
|
2787
2787
|
const tgzPath = path$39.join(tmpDir, tgzFilename);
|
|
2788
2788
|
const extractDir = path$39.join(tmpDir, "extracted");
|
|
2789
2789
|
ensureDir(extractDir);
|
|
2790
|
-
await execFileAsync$
|
|
2790
|
+
await execFileAsync$2("tar", [
|
|
2791
2791
|
"-xzf",
|
|
2792
2792
|
tgzPath,
|
|
2793
2793
|
"-C",
|
|
@@ -3023,7 +3023,7 @@ var AddonManifest = class {
|
|
|
3023
3023
|
};
|
|
3024
3024
|
//#endregion
|
|
3025
3025
|
//#region src/kernel/addon-installer.ts
|
|
3026
|
-
var execFileAsync = promisify(execFile);
|
|
3026
|
+
var execFileAsync$1 = promisify(execFile);
|
|
3027
3027
|
function parseInstallSource(value) {
|
|
3028
3028
|
switch (value) {
|
|
3029
3029
|
case "npm":
|
|
@@ -3310,6 +3310,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3310
3310
|
await fs$17.promises.writeFile(path$39.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
|
|
3311
3311
|
await copyDirRecursive(distDir, path$39.join(targetDir, "dist"));
|
|
3312
3312
|
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3313
|
+
copyBundledNativeModules(sourceDir, targetDir, this.logger);
|
|
3313
3314
|
await fs$17.promises.writeFile(path$39.join(targetDir, ".install-source"), "local");
|
|
3314
3315
|
const localPkgVersion = asString$1(pkgData.version, "0.0.0");
|
|
3315
3316
|
this.manifest.upsert(packageName, {
|
|
@@ -3480,7 +3481,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3480
3481
|
const stagingDir = path$39.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
|
|
3481
3482
|
ensureDir(stagingDir);
|
|
3482
3483
|
try {
|
|
3483
|
-
await execFileAsync("tar", [
|
|
3484
|
+
await execFileAsync$1("tar", [
|
|
3484
3485
|
"-xzf",
|
|
3485
3486
|
tgzPath,
|
|
3486
3487
|
"-C",
|
|
@@ -93389,4 +93390,143 @@ var LifecycleJobEngine = class {
|
|
|
93389
93390
|
}
|
|
93390
93391
|
};
|
|
93391
93392
|
//#endregion
|
|
93392
|
-
|
|
93393
|
+
//#region src/kernel/deps/ensure-native-prebuilds.ts
|
|
93394
|
+
/**
|
|
93395
|
+
* `ensureNativePrebuilds` — the post-install native-prebuild ENSURE step the
|
|
93396
|
+
* shared `RootUpdateService` runs while staging a `@camstack/server` closure,
|
|
93397
|
+
* BEFORE its `findMissingNativePrebuilds` validator (in `@camstack/node-root`)
|
|
93398
|
+
* decides whether to arm the swap.
|
|
93399
|
+
*
|
|
93400
|
+
* Why this exists (Mac desktop incident, 2026-07-21): a runtime
|
|
93401
|
+
* `applyServerUpdate` on a packaged desktop stages the closure with
|
|
93402
|
+
* `npm install @camstack/server@X` under the app's BUNDLED bare Node. The one
|
|
93403
|
+
* TRADITIONAL (non-N-API) native, `better-sqlite3`, resolves its `.node` via
|
|
93404
|
+
* its `install` script `prebuild-install || node-gyp rebuild`. On a user's Mac
|
|
93405
|
+
* with no build toolchain (and where the auto `prebuild-install` does not
|
|
93406
|
+
* target the bundled Node's ABI/arch the way the DMG build's EXPLICIT
|
|
93407
|
+
* `prebuild-install --runtime node --target <bundled> --arch <arch>` call does)
|
|
93408
|
+
* that leaves the module SOURCE-ONLY → the closure has no `better-sqlite3`
|
|
93409
|
+
* `.node` → the validator refuses the swap ("staged closure missing native
|
|
93410
|
+
* prebuilds: better-sqlite3"). The docker image never hits this: its Node ABI
|
|
93411
|
+
* has a published prebuild the auto path fetches cleanly, and it carries a
|
|
93412
|
+
* build toolchain fallback.
|
|
93413
|
+
*
|
|
93414
|
+
* This mirrors the DMG build's explicit re-fetch (`scripts/stage-deps.mjs`)
|
|
93415
|
+
* into the runtime staging path: for each traditional native that is present
|
|
93416
|
+
* in the closure but missing its compiled `.node`, fetch the prebuild for the
|
|
93417
|
+
* RUNNING Node ABI/arch (the same Node that will load the swapped closure).
|
|
93418
|
+
*
|
|
93419
|
+
* N-API natives (`sharp`, `node-av`) are ABI-stable and ship their binaries as
|
|
93420
|
+
* platform SIBLING packages that npm fetches reliably with no compile step, so
|
|
93421
|
+
* they are not in scope here — a genuine miss there is a broken install the
|
|
93422
|
+
* validator should still reject, not something a prebuild re-fetch can heal.
|
|
93423
|
+
*
|
|
93424
|
+
* Injected into the update service from the construction site so the zero-dep
|
|
93425
|
+
* `@camstack/node-root` layer never depends on npm/@camstack/system, and the
|
|
93426
|
+
* fetch is unit-testable with a fake fetcher.
|
|
93427
|
+
*/
|
|
93428
|
+
var execFileAsync = promisify(execFile);
|
|
93429
|
+
/** Bounded recursive `.node` scan depth inside a module dir. */
|
|
93430
|
+
var NATIVE_SCAN_DEPTH = 4;
|
|
93431
|
+
/** Timeout for a single `prebuild-install` fetch. */
|
|
93432
|
+
var PREBUILD_FETCH_TIMEOUT_MS = 12e4;
|
|
93433
|
+
/**
|
|
93434
|
+
* Traditional (compile-or-prebuild) natives an installed closure must carry a
|
|
93435
|
+
* `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
|
|
93436
|
+
* are excluded (see file header).
|
|
93437
|
+
*/
|
|
93438
|
+
var TRADITIONAL_NATIVE_PACKAGES = ["better-sqlite3"];
|
|
93439
|
+
/** Bounded recursive scan for ANY `*.node` file under `dir`. */
|
|
93440
|
+
function hasDotNode(dir, maxDepth) {
|
|
93441
|
+
let entries;
|
|
93442
|
+
try {
|
|
93443
|
+
entries = fs$17.readdirSync(dir, { withFileTypes: true });
|
|
93444
|
+
} catch {
|
|
93445
|
+
return false;
|
|
93446
|
+
}
|
|
93447
|
+
for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".node")) return true;
|
|
93448
|
+
if (maxDepth <= 0) return false;
|
|
93449
|
+
for (const entry of entries) if (entry.isDirectory() && hasDotNode(path$39.join(dir, entry.name), maxDepth - 1)) return true;
|
|
93450
|
+
return false;
|
|
93451
|
+
}
|
|
93452
|
+
/** Locate the bundled `prebuild-install` bin.js inside the staged closure. */
|
|
93453
|
+
function resolvePrebuildInstallBin(closureDir, moduleDir) {
|
|
93454
|
+
return [path$39.join(moduleDir, "node_modules", "prebuild-install", "bin.js"), path$39.join(closureDir, "node_modules", "prebuild-install", "bin.js")].find((c) => fs$17.existsSync(c)) ?? null;
|
|
93455
|
+
}
|
|
93456
|
+
/**
|
|
93457
|
+
* Default fetcher: run the closure's own `prebuild-install` under the CURRENT
|
|
93458
|
+
* Node (`process.execPath`) — no reliance on `npx`/`npm` on PATH (a packaged
|
|
93459
|
+
* app ships a bare Node). Explicitly targets the running ABI/arch, mirroring
|
|
93460
|
+
* `scripts/stage-deps.mjs`.
|
|
93461
|
+
*/
|
|
93462
|
+
function makeDefaultFetch(closureDir, logger) {
|
|
93463
|
+
return async (moduleDir, target) => {
|
|
93464
|
+
const bin = resolvePrebuildInstallBin(closureDir, moduleDir);
|
|
93465
|
+
if (bin === null) throw new Error(`prebuild-install not found in the staged closure for ${moduleDir}`);
|
|
93466
|
+
logger.info("fetching native prebuild via prebuild-install", { meta: {
|
|
93467
|
+
moduleDir,
|
|
93468
|
+
bin,
|
|
93469
|
+
nodeVersion: target.nodeVersion,
|
|
93470
|
+
arch: target.arch
|
|
93471
|
+
} });
|
|
93472
|
+
await execFileAsync(process.execPath, [
|
|
93473
|
+
bin,
|
|
93474
|
+
"--runtime",
|
|
93475
|
+
"node",
|
|
93476
|
+
"--target",
|
|
93477
|
+
target.nodeVersion,
|
|
93478
|
+
"--arch",
|
|
93479
|
+
target.arch
|
|
93480
|
+
], {
|
|
93481
|
+
cwd: moduleDir,
|
|
93482
|
+
timeout: PREBUILD_FETCH_TIMEOUT_MS
|
|
93483
|
+
});
|
|
93484
|
+
};
|
|
93485
|
+
}
|
|
93486
|
+
/**
|
|
93487
|
+
* Ensure every traditional native in `<closureDir>/node_modules` carries its
|
|
93488
|
+
* compiled `.node`, fetching the prebuild for the running ABI when missing.
|
|
93489
|
+
*
|
|
93490
|
+
* A NO-OP when nothing is missing (docker / tests) and when a native package is
|
|
93491
|
+
* absent from the closure. Never throws for a single package's fetch failure —
|
|
93492
|
+
* it logs and continues so the downstream `findMissingNativePrebuilds`
|
|
93493
|
+
* validator makes the final swap/abort decision. Returns the packages whose
|
|
93494
|
+
* prebuild was successfully fetched (for logging/tests).
|
|
93495
|
+
*/
|
|
93496
|
+
async function ensureNativePrebuilds(closureDir, options) {
|
|
93497
|
+
const nm = path$39.join(closureDir, "node_modules");
|
|
93498
|
+
const target = options.target ?? {
|
|
93499
|
+
nodeVersion: process.versions.node,
|
|
93500
|
+
arch: process.arch
|
|
93501
|
+
};
|
|
93502
|
+
const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
|
|
93503
|
+
const fetchPrebuild = options.fetchPrebuild ?? makeDefaultFetch(closureDir, options.logger);
|
|
93504
|
+
const fetched = [];
|
|
93505
|
+
for (const pkg of packages) {
|
|
93506
|
+
const moduleDir = path$39.join(nm, pkg);
|
|
93507
|
+
if (!fs$17.existsSync(moduleDir)) continue;
|
|
93508
|
+
if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) continue;
|
|
93509
|
+
options.logger.warn("staged closure native prebuild missing — fetching for running ABI", { meta: {
|
|
93510
|
+
pkg,
|
|
93511
|
+
moduleDir,
|
|
93512
|
+
nodeVersion: target.nodeVersion,
|
|
93513
|
+
arch: target.arch
|
|
93514
|
+
} });
|
|
93515
|
+
try {
|
|
93516
|
+
await fetchPrebuild(moduleDir, target);
|
|
93517
|
+
} catch (err) {
|
|
93518
|
+
options.logger.error("native prebuild fetch failed (validator will decide)", { meta: {
|
|
93519
|
+
pkg,
|
|
93520
|
+
error: errMsg(err)
|
|
93521
|
+
} });
|
|
93522
|
+
continue;
|
|
93523
|
+
}
|
|
93524
|
+
if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) {
|
|
93525
|
+
fetched.push(pkg);
|
|
93526
|
+
options.logger.info("native prebuild fetched", { meta: { pkg } });
|
|
93527
|
+
} else options.logger.error("native prebuild still missing after fetch", { meta: { pkg } });
|
|
93528
|
+
}
|
|
93529
|
+
return fetched;
|
|
93530
|
+
}
|
|
93531
|
+
//#endregion
|
|
93532
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { IScopedLogger } from '@camstack/types';
|
|
2
|
+
/**
|
|
3
|
+
* Traditional (compile-or-prebuild) natives an installed closure must carry a
|
|
4
|
+
* `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
|
|
5
|
+
* are excluded (see file header).
|
|
6
|
+
*/
|
|
7
|
+
export declare const TRADITIONAL_NATIVE_PACKAGES: readonly string[];
|
|
8
|
+
/** The running Node ABI/arch the fetched prebuild must match. */
|
|
9
|
+
export interface PrebuildTarget {
|
|
10
|
+
/** Node version, e.g. `process.versions.node` (`24.16.0`). */
|
|
11
|
+
readonly nodeVersion: string;
|
|
12
|
+
/** CPU arch, e.g. `process.arch` (`arm64` | `x64`). */
|
|
13
|
+
readonly arch: string;
|
|
14
|
+
}
|
|
15
|
+
/** Fetch a `<moduleDir>`'s prebuild for `target`. Test seam. */
|
|
16
|
+
export type PrebuildFetchFn = (moduleDir: string, target: PrebuildTarget) => Promise<void>;
|
|
17
|
+
export interface EnsureNativePrebuildsOptions {
|
|
18
|
+
readonly logger: IScopedLogger;
|
|
19
|
+
/** Defaults to the running process (`process.versions.node` / `process.arch`). */
|
|
20
|
+
readonly target?: PrebuildTarget;
|
|
21
|
+
/** Override the native package set (tests). */
|
|
22
|
+
readonly packages?: readonly string[];
|
|
23
|
+
/** Override the fetcher (tests). Production uses the bundled `prebuild-install`. */
|
|
24
|
+
readonly fetchPrebuild?: PrebuildFetchFn;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Ensure every traditional native in `<closureDir>/node_modules` carries its
|
|
28
|
+
* compiled `.node`, fetching the prebuild for the running ABI when missing.
|
|
29
|
+
*
|
|
30
|
+
* A NO-OP when nothing is missing (docker / tests) and when a native package is
|
|
31
|
+
* absent from the closure. Never throws for a single package's fetch failure —
|
|
32
|
+
* it logs and continues so the downstream `findMissingNativePrebuilds`
|
|
33
|
+
* validator makes the final swap/abort decision. Returns the packages whose
|
|
34
|
+
* prebuild was successfully fetched (for logging/tests).
|
|
35
|
+
*/
|
|
36
|
+
export declare function ensureNativePrebuilds(closureDir: string, options: EnsureNativePrebuildsOptions): Promise<readonly string[]>;
|