@camstack/system 1.2.2 → 1.2.4
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 +6 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +6 -2
- 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 +2 -0
- package/dist/index.js +289 -12
- package/dist/index.mjs +286 -14
- package/dist/kernel/deps/ensure-addon-natives.d.ts +41 -0
- package/dist/kernel/deps/ensure-native-prebuilds.d.ts +40 -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",
|
|
@@ -3030,6 +3030,268 @@ var AddonManifest = class {
|
|
|
3030
3030
|
}
|
|
3031
3031
|
};
|
|
3032
3032
|
//#endregion
|
|
3033
|
+
//#region src/kernel/deps/ensure-native-prebuilds.ts
|
|
3034
|
+
/**
|
|
3035
|
+
* `ensureNativePrebuilds` — the post-install native-prebuild ENSURE step the
|
|
3036
|
+
* shared `RootUpdateService` runs while staging a `@camstack/server` closure,
|
|
3037
|
+
* BEFORE its `findMissingNativePrebuilds` validator (in `@camstack/node-root`)
|
|
3038
|
+
* decides whether to arm the swap.
|
|
3039
|
+
*
|
|
3040
|
+
* Why this exists (Mac desktop incident, 2026-07-21): a runtime
|
|
3041
|
+
* `applyServerUpdate` on a packaged desktop stages the closure with
|
|
3042
|
+
* `npm install @camstack/server@X` under the app's BUNDLED bare Node. The one
|
|
3043
|
+
* TRADITIONAL (non-N-API) native, `better-sqlite3`, resolves its `.node` via
|
|
3044
|
+
* its `install` script `prebuild-install || node-gyp rebuild`. On a user's Mac
|
|
3045
|
+
* with no build toolchain (and where the auto `prebuild-install` does not
|
|
3046
|
+
* target the bundled Node's ABI/arch the way the DMG build's EXPLICIT
|
|
3047
|
+
* `prebuild-install --runtime node --target <bundled> --arch <arch>` call does)
|
|
3048
|
+
* that leaves the module SOURCE-ONLY → the closure has no `better-sqlite3`
|
|
3049
|
+
* `.node` → the validator refuses the swap ("staged closure missing native
|
|
3050
|
+
* prebuilds: better-sqlite3"). The docker image never hits this: its Node ABI
|
|
3051
|
+
* has a published prebuild the auto path fetches cleanly, and it carries a
|
|
3052
|
+
* build toolchain fallback.
|
|
3053
|
+
*
|
|
3054
|
+
* This mirrors the DMG build's explicit re-fetch (`scripts/stage-deps.mjs`)
|
|
3055
|
+
* into the runtime staging path: for each traditional native that is present
|
|
3056
|
+
* in the closure but missing its compiled `.node`, fetch the prebuild for the
|
|
3057
|
+
* RUNNING Node ABI/arch (the same Node that will load the swapped closure).
|
|
3058
|
+
*
|
|
3059
|
+
* N-API natives (`sharp`, `node-av`) are ABI-stable and ship their binaries as
|
|
3060
|
+
* platform SIBLING packages that npm fetches reliably with no compile step, so
|
|
3061
|
+
* they are not in scope here — a genuine miss there is a broken install the
|
|
3062
|
+
* validator should still reject, not something a prebuild re-fetch can heal.
|
|
3063
|
+
*
|
|
3064
|
+
* Injected into the update service from the construction site so the zero-dep
|
|
3065
|
+
* `@camstack/node-root` layer never depends on npm/@camstack/system, and the
|
|
3066
|
+
* fetch is unit-testable with a fake fetcher.
|
|
3067
|
+
*/
|
|
3068
|
+
var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
|
|
3069
|
+
/** Bounded recursive `.node` scan depth inside a module dir. */
|
|
3070
|
+
var NATIVE_SCAN_DEPTH = 4;
|
|
3071
|
+
/** Timeout for a single `prebuild-install` fetch. */
|
|
3072
|
+
var PREBUILD_FETCH_TIMEOUT_MS = 12e4;
|
|
3073
|
+
/**
|
|
3074
|
+
* Traditional (compile-or-prebuild) natives an installed closure must carry a
|
|
3075
|
+
* `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
|
|
3076
|
+
* are excluded (see file header).
|
|
3077
|
+
*/
|
|
3078
|
+
var TRADITIONAL_NATIVE_PACKAGES = ["better-sqlite3"];
|
|
3079
|
+
/** Bounded recursive scan for ANY `*.node` file under `dir`. */
|
|
3080
|
+
function hasDotNode(dir, maxDepth) {
|
|
3081
|
+
let entries;
|
|
3082
|
+
try {
|
|
3083
|
+
entries = node_fs.readdirSync(dir, { withFileTypes: true });
|
|
3084
|
+
} catch {
|
|
3085
|
+
return false;
|
|
3086
|
+
}
|
|
3087
|
+
for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".node")) return true;
|
|
3088
|
+
if (maxDepth <= 0) return false;
|
|
3089
|
+
for (const entry of entries) if (entry.isDirectory() && hasDotNode(node_path.join(dir, entry.name), maxDepth - 1)) return true;
|
|
3090
|
+
return false;
|
|
3091
|
+
}
|
|
3092
|
+
/** Locate the bundled `prebuild-install` bin.js inside the staged closure. */
|
|
3093
|
+
function resolvePrebuildInstallBin(closureDir, moduleDir) {
|
|
3094
|
+
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;
|
|
3095
|
+
}
|
|
3096
|
+
/**
|
|
3097
|
+
* Default fetcher: run the closure's own `prebuild-install` under the CURRENT
|
|
3098
|
+
* Node (`process.execPath`) — no reliance on `npx`/`npm` on PATH (a packaged
|
|
3099
|
+
* app ships a bare Node). Explicitly targets the running ABI/arch, mirroring
|
|
3100
|
+
* `scripts/stage-deps.mjs`.
|
|
3101
|
+
*/
|
|
3102
|
+
function makeDefaultFetch(closureDir, logger) {
|
|
3103
|
+
return async (moduleDir, target) => {
|
|
3104
|
+
const bin = resolvePrebuildInstallBin(closureDir, moduleDir);
|
|
3105
|
+
if (bin === null) throw new Error(`prebuild-install not found in the staged closure for ${moduleDir}`);
|
|
3106
|
+
logger.info("fetching native prebuild via prebuild-install", { meta: {
|
|
3107
|
+
moduleDir,
|
|
3108
|
+
bin,
|
|
3109
|
+
nodeVersion: target.nodeVersion,
|
|
3110
|
+
arch: target.arch
|
|
3111
|
+
} });
|
|
3112
|
+
await execFileAsync$1(process.execPath, [
|
|
3113
|
+
bin,
|
|
3114
|
+
"--runtime",
|
|
3115
|
+
"node",
|
|
3116
|
+
"--target",
|
|
3117
|
+
target.nodeVersion,
|
|
3118
|
+
"--arch",
|
|
3119
|
+
target.arch
|
|
3120
|
+
], {
|
|
3121
|
+
cwd: moduleDir,
|
|
3122
|
+
timeout: PREBUILD_FETCH_TIMEOUT_MS
|
|
3123
|
+
});
|
|
3124
|
+
};
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Ensure every traditional native in `<closureDir>/node_modules` carries its
|
|
3128
|
+
* compiled `.node`, fetching the prebuild for the running ABI when missing.
|
|
3129
|
+
*
|
|
3130
|
+
* A NO-OP when nothing is missing (docker / tests) and when a native package is
|
|
3131
|
+
* absent from the closure. Never throws for a single package's fetch failure —
|
|
3132
|
+
* it logs and continues so the downstream `findMissingNativePrebuilds`
|
|
3133
|
+
* validator makes the final swap/abort decision. Returns the packages whose
|
|
3134
|
+
* prebuild was successfully fetched (for logging/tests).
|
|
3135
|
+
*/
|
|
3136
|
+
async function ensureNativePrebuilds(closureDir, options) {
|
|
3137
|
+
const nm = node_path.join(closureDir, "node_modules");
|
|
3138
|
+
const target = options.target ?? {
|
|
3139
|
+
nodeVersion: process.versions.node,
|
|
3140
|
+
arch: process.arch
|
|
3141
|
+
};
|
|
3142
|
+
const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
|
|
3143
|
+
const fetchPrebuild = options.fetchPrebuild ?? makeDefaultFetch(closureDir, options.logger);
|
|
3144
|
+
const fetched = [];
|
|
3145
|
+
for (const pkg of packages) {
|
|
3146
|
+
const moduleDir = node_path.join(nm, pkg);
|
|
3147
|
+
if (!node_fs.existsSync(moduleDir)) continue;
|
|
3148
|
+
if (hasDotNode(moduleDir, 4)) continue;
|
|
3149
|
+
options.logger.warn("staged closure native prebuild missing — fetching for running ABI", { meta: {
|
|
3150
|
+
pkg,
|
|
3151
|
+
moduleDir,
|
|
3152
|
+
nodeVersion: target.nodeVersion,
|
|
3153
|
+
arch: target.arch
|
|
3154
|
+
} });
|
|
3155
|
+
try {
|
|
3156
|
+
await fetchPrebuild(moduleDir, target);
|
|
3157
|
+
} catch (err) {
|
|
3158
|
+
options.logger.error("native prebuild fetch failed (validator will decide)", { meta: {
|
|
3159
|
+
pkg,
|
|
3160
|
+
error: (0, _camstack_types_addon.errMsg)(err)
|
|
3161
|
+
} });
|
|
3162
|
+
continue;
|
|
3163
|
+
}
|
|
3164
|
+
if (hasDotNode(moduleDir, 4)) {
|
|
3165
|
+
fetched.push(pkg);
|
|
3166
|
+
options.logger.info("native prebuild fetched", { meta: { pkg } });
|
|
3167
|
+
} else options.logger.error("native prebuild still missing after fetch", { meta: { pkg } });
|
|
3168
|
+
}
|
|
3169
|
+
return fetched;
|
|
3170
|
+
}
|
|
3171
|
+
//#endregion
|
|
3172
|
+
//#region src/kernel/deps/ensure-addon-natives.ts
|
|
3173
|
+
/**
|
|
3174
|
+
* `ensureAddonNativePrebuilds` — the POST-install native-prebuild ENSURE pass an
|
|
3175
|
+
* addon install runs on the INSTALLED addon dir AFTER `npm install`.
|
|
3176
|
+
*
|
|
3177
|
+
* Why this exists (Mac desktop first-boot FATAL, 2026-07-21): `installCopy`
|
|
3178
|
+
* copies `dist/`, plants prebuilt natives from the bundled addon copy
|
|
3179
|
+
* (`copyBundledNativeModules`), then `npm install`s the addon's runtime deps.
|
|
3180
|
+
* On a TOOLCHAIN-LESS host that `npm install` RE-CREATES the traditional native
|
|
3181
|
+
* `better-sqlite3` SOURCE-ONLY — clobbering the good `.node` the pre-install
|
|
3182
|
+
* copy just planted — and the runner later dies at addon init with a cryptic
|
|
3183
|
+
* "Could not locate the bindings file". The copy-BEFORE-install fix was
|
|
3184
|
+
* empirically insufficient: npm's own install in the copied dir replaces the
|
|
3185
|
+
* satisfied dep without its binary.
|
|
3186
|
+
*
|
|
3187
|
+
* This pass runs LAST, so it always sees the final on-disk state npm left, and
|
|
3188
|
+
* per referenced traditional native still lacking its compiled `.node`:
|
|
3189
|
+
* 1. bundled-copy first — if the bundled addon copy carries the matching
|
|
3190
|
+
* `.node` (same machine → same platform/arch/ABI), re-plant it DIRECTLY.
|
|
3191
|
+
* Cheapest + offline-safe; runs BEFORE any network fetch.
|
|
3192
|
+
* 2. fetch fallback — otherwise fetch the prebuild for the running ABI via the
|
|
3193
|
+
* shared `ensureNativePrebuilds` pointed at the addon dir.
|
|
3194
|
+
* 3. FAIL LOUD — if the native is STILL source-only after both, log a clear
|
|
3195
|
+
* error naming module + addon and THROW so the install fails at install
|
|
3196
|
+
* time rather than at addon init.
|
|
3197
|
+
*
|
|
3198
|
+
* N-API natives (`sharp`, `node-av`) ship their binaries as ABI-stable platform
|
|
3199
|
+
* SIBLING packages npm fetches without a compile step, so they are excluded from
|
|
3200
|
+
* the default set — a miss there is a broken install, not something a prebuild
|
|
3201
|
+
* re-fetch heals (same rationale as `ensureNativePrebuilds`).
|
|
3202
|
+
*/
|
|
3203
|
+
/**
|
|
3204
|
+
* Re-plant `<srcModuleDir>` → `<dstModuleDir>` when the source carries a `.node`.
|
|
3205
|
+
* Returns whether the destination ends up with a compiled binary.
|
|
3206
|
+
*/
|
|
3207
|
+
function replantFromBundled(srcModuleDir, dstModuleDir, hasNative) {
|
|
3208
|
+
if (!hasNative(srcModuleDir)) return false;
|
|
3209
|
+
try {
|
|
3210
|
+
node_fs.rmSync(dstModuleDir, {
|
|
3211
|
+
recursive: true,
|
|
3212
|
+
force: true
|
|
3213
|
+
});
|
|
3214
|
+
node_fs.mkdirSync(node_path.dirname(dstModuleDir), { recursive: true });
|
|
3215
|
+
node_fs.cpSync(srcModuleDir, dstModuleDir, {
|
|
3216
|
+
recursive: true,
|
|
3217
|
+
dereference: true
|
|
3218
|
+
});
|
|
3219
|
+
} catch {
|
|
3220
|
+
return false;
|
|
3221
|
+
}
|
|
3222
|
+
return hasNative(dstModuleDir);
|
|
3223
|
+
}
|
|
3224
|
+
/**
|
|
3225
|
+
* Ensure every referenced traditional native in `<addonDir>/node_modules`
|
|
3226
|
+
* carries its compiled `.node` after the addon's `npm install`. Bundled-copy
|
|
3227
|
+
* first (offline), prebuild-fetch fallback, LOUD throw on a residual miss.
|
|
3228
|
+
*
|
|
3229
|
+
* SKIPS a native absent from the addon's own `node_modules` (it resolves via a
|
|
3230
|
+
* hoisted host copy — not this addon's concern). A NO-OP in docker / dev where
|
|
3231
|
+
* npm produced a working `.node` (already-present). Returns the per-native
|
|
3232
|
+
* outcomes for logging/tests.
|
|
3233
|
+
*
|
|
3234
|
+
* @throws if any required native is still source-only after copy + fetch.
|
|
3235
|
+
*/
|
|
3236
|
+
async function ensureAddonNativePrebuilds(addonDir, options) {
|
|
3237
|
+
const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
|
|
3238
|
+
const hasNative = options.hasNative ?? ((dir) => hasDotNode(dir, 4));
|
|
3239
|
+
const nm = node_path.join(addonDir, "node_modules");
|
|
3240
|
+
const results = [];
|
|
3241
|
+
const missing = [];
|
|
3242
|
+
for (const pkg of packages) {
|
|
3243
|
+
const moduleDir = node_path.join(nm, pkg);
|
|
3244
|
+
if (!node_fs.existsSync(moduleDir)) continue;
|
|
3245
|
+
if (hasNative(moduleDir)) {
|
|
3246
|
+
results.push({
|
|
3247
|
+
pkg,
|
|
3248
|
+
outcome: "already-present"
|
|
3249
|
+
});
|
|
3250
|
+
continue;
|
|
3251
|
+
}
|
|
3252
|
+
if (options.bundledSourceDir) {
|
|
3253
|
+
const src = node_path.join(options.bundledSourceDir, "node_modules", pkg);
|
|
3254
|
+
if (replantFromBundled(src, moduleDir, hasNative)) {
|
|
3255
|
+
options.logger.info("addon native prebuild re-planted from bundled copy (offline)", { meta: {
|
|
3256
|
+
addon: options.addonName,
|
|
3257
|
+
pkg,
|
|
3258
|
+
src,
|
|
3259
|
+
moduleDir
|
|
3260
|
+
} });
|
|
3261
|
+
results.push({
|
|
3262
|
+
pkg,
|
|
3263
|
+
outcome: "copied"
|
|
3264
|
+
});
|
|
3265
|
+
continue;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
if ((await ensureNativePrebuilds(addonDir, {
|
|
3269
|
+
logger: options.logger,
|
|
3270
|
+
packages: [pkg],
|
|
3271
|
+
...options.target ? { target: options.target } : {},
|
|
3272
|
+
...options.fetchPrebuild ? { fetchPrebuild: options.fetchPrebuild } : {}
|
|
3273
|
+
})).includes(pkg)) {
|
|
3274
|
+
results.push({
|
|
3275
|
+
pkg,
|
|
3276
|
+
outcome: "fetched"
|
|
3277
|
+
});
|
|
3278
|
+
continue;
|
|
3279
|
+
}
|
|
3280
|
+
options.logger.error("addon native prebuild MISSING after ensure — module has no compiled .node", { meta: {
|
|
3281
|
+
addon: options.addonName,
|
|
3282
|
+
pkg,
|
|
3283
|
+
moduleDir
|
|
3284
|
+
} });
|
|
3285
|
+
results.push({
|
|
3286
|
+
pkg,
|
|
3287
|
+
outcome: "missing"
|
|
3288
|
+
});
|
|
3289
|
+
missing.push(pkg);
|
|
3290
|
+
}
|
|
3291
|
+
if (missing.length > 0) throw new Error(`${options.addonName} — required native module(s) missing a compiled .node after install (bundled-copy + prebuild-fetch both failed): ${missing.join(", ")}`);
|
|
3292
|
+
return results;
|
|
3293
|
+
}
|
|
3294
|
+
//#endregion
|
|
3033
3295
|
//#region src/kernel/addon-installer.ts
|
|
3034
3296
|
var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
|
|
3035
3297
|
function parseInstallSource(value) {
|
|
@@ -3318,6 +3580,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3318
3580
|
await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
|
|
3319
3581
|
await copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
|
|
3320
3582
|
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3583
|
+
require_manifest_python_deps.copyBundledNativeModules(sourceDir, targetDir, this.logger);
|
|
3321
3584
|
await node_fs.promises.writeFile(node_path.join(targetDir, ".install-source"), "local");
|
|
3322
3585
|
const localPkgVersion = require_dist.asString(pkgData.version, "0.0.0");
|
|
3323
3586
|
this.manifest.upsert(packageName, {
|
|
@@ -3339,6 +3602,11 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3339
3602
|
} catch (err) {
|
|
3340
3603
|
this.logger.warn(`${packageName} — native deps install failed (continuing)`, { meta: { error: require_dist.errMsg(err) } });
|
|
3341
3604
|
}
|
|
3605
|
+
await ensureAddonNativePrebuilds(targetDir, {
|
|
3606
|
+
addonName: packageName,
|
|
3607
|
+
logger: this.logger,
|
|
3608
|
+
bundledSourceDir: sourceDir
|
|
3609
|
+
});
|
|
3342
3610
|
this.logger.info(`${packageName} — copied from ${sourceDir}`);
|
|
3343
3611
|
return {
|
|
3344
3612
|
name: pkgData.name,
|
|
@@ -3525,6 +3793,10 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3525
3793
|
} catch (nativeErr) {
|
|
3526
3794
|
throw new Error(`${pkgView.name} — native deps install failed: ${require_dist.errMsg(nativeErr)}`, { cause: nativeErr });
|
|
3527
3795
|
}
|
|
3796
|
+
await ensureAddonNativePrebuilds(pkgDir, {
|
|
3797
|
+
addonName: pkgView.name,
|
|
3798
|
+
logger: this.logger
|
|
3799
|
+
});
|
|
3528
3800
|
await this.evictInstallDir(targetDir);
|
|
3529
3801
|
ensureDir(node_path.dirname(targetDir));
|
|
3530
3802
|
await node_fs.promises.rename(pkgDir, targetDir);
|
|
@@ -93463,6 +93735,7 @@ exports.LogRingBuffer = LogRingBuffer;
|
|
|
93463
93735
|
exports.METHOD_ACCESS_MAP = require_dist.METHOD_ACCESS_MAP;
|
|
93464
93736
|
exports.ModelDownloadService = require_model_download_service.ModelDownloadService;
|
|
93465
93737
|
exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_python_deps.NATIVE_PROVIDER_SERVICE_INFIX;
|
|
93738
|
+
exports.NATIVE_SCAN_DEPTH = NATIVE_SCAN_DEPTH;
|
|
93466
93739
|
exports.NativeMetricsAddon = require_builtins_native_metrics_native_metrics_addon.default;
|
|
93467
93740
|
exports.NativeMetricsProvider = require_builtins_native_metrics_native_metrics_addon.NativeMetricsProvider;
|
|
93468
93741
|
exports.NetworkQualityTracker = NetworkQualityTracker;
|
|
@@ -93494,6 +93767,7 @@ exports.StorageOrchestratorAddon = require_builtins_storage_orchestrator_storage
|
|
|
93494
93767
|
exports.StorageOrchestratorService = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorService;
|
|
93495
93768
|
exports.SystemConfigAddon = require_builtins_system_config_system_config_addon.SystemConfigAddon;
|
|
93496
93769
|
exports.SystemEventBus = SystemEventBus;
|
|
93770
|
+
exports.TRADITIONAL_NATIVE_PACKAGES = TRADITIONAL_NATIVE_PACKAGES;
|
|
93497
93771
|
exports.ToastService = ToastService;
|
|
93498
93772
|
exports.UDS_NO_ROUTE_PREFIX = require_manifest_python_deps.UDS_NO_ROUTE_PREFIX;
|
|
93499
93773
|
exports.UdsLocalTransportClient = require_manifest_python_deps.UdsLocalTransportClient;
|
|
@@ -93571,6 +93845,7 @@ exports.downloadFile = require_model_download_service.downloadFile;
|
|
|
93571
93845
|
exports.downloadModel = require_model_download_service.downloadModel;
|
|
93572
93846
|
exports.emitDownForOwnedCaps = require_dist.emitDownForOwnedCaps;
|
|
93573
93847
|
exports.encodeFrame = require_manifest_python_deps.encodeFrame;
|
|
93848
|
+
exports.ensureAddonNativePrebuilds = ensureAddonNativePrebuilds;
|
|
93574
93849
|
Object.defineProperty(exports, "ensureBinary", {
|
|
93575
93850
|
enumerable: true,
|
|
93576
93851
|
get: function() {
|
|
@@ -93586,6 +93861,7 @@ Object.defineProperty(exports, "ensureFfmpeg", {
|
|
|
93586
93861
|
});
|
|
93587
93862
|
exports.ensureLibraryBuilt = ensureLibraryBuilt;
|
|
93588
93863
|
exports.ensureModel = require_model_download_service.ensureModel;
|
|
93864
|
+
exports.ensureNativePrebuilds = ensureNativePrebuilds;
|
|
93589
93865
|
Object.defineProperty(exports, "ensurePython", {
|
|
93590
93866
|
enumerable: true,
|
|
93591
93867
|
get: function() {
|
|
@@ -93630,6 +93906,7 @@ Object.defineProperty(exports, "getPythonDownloadUrl", {
|
|
|
93630
93906
|
exports.getRestartMarkerPath = getRestartMarkerPath;
|
|
93631
93907
|
exports.getSinglePidStats = require_resource_monitor.getSinglePidStats;
|
|
93632
93908
|
exports.getWorkerDeviceRegistry = require_manifest_python_deps.getWorkerDeviceRegistry;
|
|
93909
|
+
exports.hasDotNode = hasDotNode;
|
|
93633
93910
|
exports.hashClusterSecret = hashClusterSecret;
|
|
93634
93911
|
exports.installManifestNativeDeps = require_manifest_python_deps.installManifestNativeDeps;
|
|
93635
93912
|
exports.installManifestPythonDeps = require_manifest_python_deps.installManifestPythonDeps;
|