@camstack/system 1.0.7 → 1.0.8

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.
@@ -154,7 +154,7 @@ var StorageOrchestratorService = class {
154
154
  const resolver = this.nodeLocalResolver;
155
155
  if (!resolver) return;
156
156
  let stamped = 0;
157
- for (const [id, loc] of [...this.locations]) {
157
+ for (const [id, loc] of Array.from(this.locations)) {
158
158
  if (loc.nodeId) continue;
159
159
  if (resolver(loc.providerId) !== true) continue;
160
160
  const updated = {
@@ -294,7 +294,7 @@ var StorageOrchestratorService = class {
294
294
  this.logger.warn("storage-orchestrator: skipping prune — no location declarations loaded (fail-safe)");
295
295
  return;
296
296
  }
297
- for (const [id, loc] of [...this.locations]) {
297
+ for (const [id, loc] of Array.from(this.locations)) {
298
298
  if (this.registry.cardinalityOf(loc.type) !== null) continue;
299
299
  if (loc.isSystem) {
300
300
  this.locations.delete(id);
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
20
20
  require("./builtins/local-auth/index.js");
21
21
  const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
22
22
  require("./builtins/device-manager/index.js");
23
- const require_manifest_python_deps = require("./manifest-python-deps-eBDj5HEY.js");
23
+ const require_manifest_python_deps = require("./manifest-python-deps-BWURo7dc.js");
24
24
  const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
25
25
  const require_graceful_fs$1 = require("./graceful-fs-lg19SZNz.js");
26
26
  let _camstack_types_node = require("@camstack/types/node");
@@ -183,7 +183,7 @@ function proxyToUpstream(opts) {
183
183
  }
184
184
  //#endregion
185
185
  //#region src/python/python-env-manager.ts
186
- var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
186
+ var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
187
187
  var PythonEnvManager = class {
188
188
  venvPath;
189
189
  cachedProbe = null;
@@ -193,12 +193,12 @@ var PythonEnvManager = class {
193
193
  async probe() {
194
194
  if (this.cachedProbe) return this.cachedProbe;
195
195
  for (const cmd of ["python3", "python"]) try {
196
- const { stdout } = await execFileAsync$2(cmd, ["--version"]);
196
+ const { stdout } = await execFileAsync$3(cmd, ["--version"]);
197
197
  const version = stdout.trim().replace("Python ", "");
198
198
  const major = parseInt(version.split(".")[0] ?? "0", 10);
199
199
  const minor = parseInt(version.split(".")[1] ?? "0", 10);
200
200
  if (major < 3 || major === 3 && minor < 10) continue;
201
- const { stdout: pathOut } = await execFileAsync$2(cmd, ["-c", "import sys; print(sys.executable)"]);
201
+ const { stdout: pathOut } = await execFileAsync$3(cmd, ["-c", "import sys; print(sys.executable)"]);
202
202
  this.cachedProbe = {
203
203
  available: true,
204
204
  version,
@@ -214,13 +214,13 @@ var PythonEnvManager = class {
214
214
  async ensure(options) {
215
215
  const probe = await this.probe();
216
216
  if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
217
- if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$2(probe.path, [
217
+ if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$3(probe.path, [
218
218
  "-m",
219
219
  "venv",
220
220
  this.venvPath
221
221
  ]);
222
222
  const venvPython = node_path.join(this.venvPath, "bin", "python");
223
- if (options.packages.length > 0) await execFileAsync$2(venvPython, [
223
+ if (options.packages.length > 0) await execFileAsync$3(venvPython, [
224
224
  "-m",
225
225
  "pip",
226
226
  "install",
@@ -1419,12 +1419,11 @@ var StorageManager = class {
1419
1419
  return namespace ? this.createNamespacedLocation(location, namespace) : location;
1420
1420
  }
1421
1421
  createLegacyShim() {
1422
- const self = this;
1423
1422
  return {
1424
1423
  async initialize() {},
1425
1424
  async shutdown() {},
1426
- getLocation(name) {
1427
- return self.getLocation(name);
1425
+ getLocation: (name) => {
1426
+ return this.getLocation(name);
1428
1427
  }
1429
1428
  };
1430
1429
  }
@@ -1700,7 +1699,7 @@ function matchPath(pattern, path) {
1700
1699
  }
1701
1700
  //#endregion
1702
1701
  //#region src/tls/cert-manager.ts
1703
- var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
1702
+ var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
1704
1703
  /**
1705
1704
  * Ensure a self-signed TLS certificate exists in the given directory.
1706
1705
  * Generates one if missing. Returns paths to cert and key files.
@@ -1737,7 +1736,7 @@ async function ensureTlsCert(dataDir, options) {
1737
1736
  for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
1738
1737
  for (const ip of sanIps) sanParts.push(`IP:${ip}`);
1739
1738
  const sanString = sanParts.join(",");
1740
- await execFileAsync$1("openssl", [
1739
+ await execFileAsync$2("openssl", [
1741
1740
  "req",
1742
1741
  "-x509",
1743
1742
  "-newkey",
@@ -2570,6 +2569,7 @@ var AddonEngineManager = class {
2570
2569
  };
2571
2570
  //#endregion
2572
2571
  //#region src/kernel/fs-utils.ts
2572
+ var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
2573
2573
  /**
2574
2574
  * Ensure a directory exists (recursive).
2575
2575
  * Single source of truth — replaces scattered mkdirSync calls.
@@ -2578,18 +2578,20 @@ function ensureDir(dirPath) {
2578
2578
  node_fs.mkdirSync(dirPath, { recursive: true });
2579
2579
  }
2580
2580
  /**
2581
- * Copy a directory recursively.
2582
- * Single source of truth — extracted from addon-installer + first-boot-installer.
2581
+ * Copy a directory recursively — ASYNC so it never blocks the event loop.
2582
+ *
2583
+ * The hub installs addons into `/data/addons`, which on Unraid is a slow
2584
+ * shfs/FUSE mount. The former synchronous `fs.copyFileSync`-per-file loop
2585
+ * blocked the Node event loop for the whole copy of a large bundle (e.g.
2586
+ * `addon-pipeline`), which froze the hub's HTTP listener mid-`camstack deploy`
2587
+ * (accept backlog piling up, existing connections stuck in CLOSE_WAIT). Using
2588
+ * `fs.promises.cp` keeps the I/O off the event loop. (Node ≥18 stable.)
2583
2589
  */
2584
- function copyDirRecursive(src, dest) {
2585
- ensureDir(dest);
2586
- const entries = node_fs.readdirSync(src, { withFileTypes: true });
2587
- for (const entry of entries) {
2588
- const srcPath = node_path.join(src, entry.name);
2589
- const destPath = node_path.join(dest, entry.name);
2590
- if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
2591
- else node_fs.copyFileSync(srcPath, destPath);
2592
- }
2590
+ async function copyDirRecursive(src, dest) {
2591
+ await node_fs.promises.cp(src, dest, {
2592
+ recursive: true,
2593
+ force: true
2594
+ });
2593
2595
  }
2594
2596
  /**
2595
2597
  * Strip @camstack/* dependencies and devDependencies from a package.json object.
@@ -2619,7 +2621,7 @@ function stripCamstackDeps(pkg) {
2619
2621
  * Copies directories (not individual files) from source to destination.
2620
2622
  * Skips "dist" (already handled) and glob patterns.
2621
2623
  */
2622
- function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
2624
+ async function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
2623
2625
  const rawFiles = pkgJson.files;
2624
2626
  if (!Array.isArray(rawFiles)) return;
2625
2627
  for (const fileEntry of rawFiles) {
@@ -2628,11 +2630,11 @@ function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
2628
2630
  const srcPath = node_path.join(sourceDir, fileEntry);
2629
2631
  if (!node_fs.existsSync(srcPath)) continue;
2630
2632
  const destPath = node_path.join(destDir, fileEntry);
2631
- const stat = node_fs.statSync(srcPath);
2632
- if (stat.isDirectory()) copyDirRecursive(srcPath, destPath);
2633
+ const stat = await node_fs.promises.stat(srcPath);
2634
+ if (stat.isDirectory()) await copyDirRecursive(srcPath, destPath);
2633
2635
  else if (stat.isFile()) {
2634
2636
  ensureDir(node_path.dirname(destPath));
2635
- node_fs.copyFileSync(srcPath, destPath);
2637
+ await node_fs.promises.copyFile(srcPath, destPath);
2636
2638
  }
2637
2639
  }
2638
2640
  }
@@ -2677,12 +2679,16 @@ function ensureLibraryBuilt(packageName, packagesDir) {
2677
2679
  /**
2678
2680
  * Install a single npm package into a target directory (package.json + dist/).
2679
2681
  * No validation on camstack.addons -- works for any @camstack/* package.
2680
- * Uses synchronous child_process calls (suitable for first-boot and update paths).
2682
+ *
2683
+ * ASYNC: uses `execFile`/`fs.promises` throughout so a package install on a
2684
+ * live node never blocks the event loop (the `npm pack` + tar extract + copy to
2685
+ * the slow shfs/FUSE `/data` would otherwise freeze the HTTP listener). See
2686
+ * `copyDirRecursive` for the wedge this prevents.
2681
2687
  */
2682
- function installPackageFromNpmSync(packageName, targetDir) {
2683
- const tmpDir = node_fs.mkdtempSync(node_path.join(node_os.tmpdir(), "camstack-install-"));
2688
+ async function installPackageFromNpm(packageName, targetDir) {
2689
+ const tmpDir = await node_fs.promises.mkdtemp(node_path.join(node_os.tmpdir(), "camstack-install-"));
2684
2690
  try {
2685
- const tgzFilename = (0, node_child_process.execFileSync)("npm", [
2691
+ const { stdout } = await execFileAsync$1("npm", [
2686
2692
  "pack",
2687
2693
  packageName,
2688
2694
  "--pack-destination",
@@ -2690,12 +2696,13 @@ function installPackageFromNpmSync(packageName, targetDir) {
2690
2696
  ], {
2691
2697
  timeout: 12e4,
2692
2698
  encoding: "utf-8"
2693
- }).trim().split("\n").pop()?.trim();
2699
+ });
2700
+ const tgzFilename = stdout.trim().split("\n").pop()?.trim();
2694
2701
  if (!tgzFilename) throw new Error("npm pack produced no output");
2695
2702
  const tgzPath = node_path.join(tmpDir, tgzFilename);
2696
2703
  const extractDir = node_path.join(tmpDir, "extracted");
2697
2704
  ensureDir(extractDir);
2698
- (0, node_child_process.execFileSync)("tar", [
2705
+ await execFileAsync$1("tar", [
2699
2706
  "-xzf",
2700
2707
  tgzPath,
2701
2708
  "-C",
@@ -2703,20 +2710,20 @@ function installPackageFromNpmSync(packageName, targetDir) {
2703
2710
  ], { timeout: 3e4 });
2704
2711
  const packageSubDir = node_path.join(extractDir, "package");
2705
2712
  const srcPkgJsonDir = node_fs.existsSync(node_path.join(packageSubDir, "package.json")) ? packageSubDir : extractDir;
2706
- node_fs.rmSync(targetDir, {
2713
+ await node_fs.promises.rm(targetDir, {
2707
2714
  recursive: true,
2708
2715
  force: true
2709
2716
  });
2710
2717
  ensureDir(targetDir);
2711
- node_fs.copyFileSync(node_path.join(srcPkgJsonDir, "package.json"), node_path.join(targetDir, "package.json"));
2718
+ await node_fs.promises.copyFile(node_path.join(srcPkgJsonDir, "package.json"), node_path.join(targetDir, "package.json"));
2712
2719
  const distSrc = node_path.join(srcPkgJsonDir, "dist");
2713
- if (node_fs.existsSync(distSrc)) copyDirRecursive(distSrc, node_path.join(targetDir, "dist"));
2720
+ if (node_fs.existsSync(distSrc)) await copyDirRecursive(distSrc, node_path.join(targetDir, "dist"));
2714
2721
  try {
2715
- const npmPkg = (0, _camstack_types.asJsonObject)((0, _camstack_types.parseJsonUnknown)(node_fs.readFileSync(node_path.join(srcPkgJsonDir, "package.json"), "utf-8")));
2716
- if (npmPkg) copyExtraFileDirs(npmPkg, srcPkgJsonDir, targetDir);
2722
+ const npmPkg = (0, _camstack_types.asJsonObject)((0, _camstack_types.parseJsonUnknown)(await node_fs.promises.readFile(node_path.join(srcPkgJsonDir, "package.json"), "utf-8")));
2723
+ if (npmPkg) await copyExtraFileDirs(npmPkg, srcPkgJsonDir, targetDir);
2717
2724
  } catch {}
2718
2725
  } finally {
2719
- node_fs.rmSync(tmpDir, {
2726
+ await node_fs.promises.rm(tmpDir, {
2720
2727
  recursive: true,
2721
2728
  force: true
2722
2729
  });
@@ -3166,15 +3173,15 @@ var AddonInstaller = class AddonInstaller {
3166
3173
  await this.ensureBuilt(packageName, sourceDir, pkgData);
3167
3174
  const distDir = node_path.join(sourceDir, "dist");
3168
3175
  if (!node_fs.existsSync(distDir)) throw new Error(`${packageName} has no dist/ after build`);
3169
- node_fs.rmSync(targetDir, {
3176
+ await node_fs.promises.rm(targetDir, {
3170
3177
  recursive: true,
3171
3178
  force: true
3172
3179
  });
3173
3180
  ensureDir(targetDir);
3174
- node_fs.writeFileSync(node_path.join(targetDir, "package.json"), JSON.stringify(stripCamstackDeps(pkgData), null, 2));
3175
- copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
3176
- copyExtraFileDirs(pkgData, sourceDir, targetDir);
3177
- node_fs.writeFileSync(node_path.join(targetDir, ".install-source"), "local");
3181
+ await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(stripCamstackDeps(pkgData), null, 2));
3182
+ await copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
3183
+ await copyExtraFileDirs(pkgData, sourceDir, targetDir);
3184
+ await node_fs.promises.writeFile(node_path.join(targetDir, ".install-source"), "local");
3178
3185
  const localPkgVersion = (0, _camstack_types.asString)(pkgData.version, "0.0.0");
3179
3186
  this.manifest.upsert(packageName, {
3180
3187
  version: localPkgVersion,
@@ -3294,17 +3301,17 @@ var AddonInstaller = class AddonInstaller {
3294
3301
  if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
3295
3302
  if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
3296
3303
  const targetDir = node_path.join(this.addonsDir, pkgView.name);
3297
- node_fs.rmSync(targetDir, {
3304
+ await node_fs.promises.rm(targetDir, {
3298
3305
  recursive: true,
3299
3306
  force: true
3300
3307
  });
3301
3308
  ensureDir(targetDir);
3302
3309
  const sourceDir = node_path.dirname(pkgJsonPath);
3303
3310
  const strippedManifest = stripCamstackDeps(pkgView.raw);
3304
- node_fs.writeFileSync(node_path.join(targetDir, "package.json"), JSON.stringify(strippedManifest, null, 2));
3311
+ await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(strippedManifest, null, 2));
3305
3312
  const sourceDist = node_path.join(sourceDir, "dist");
3306
- if (node_fs.existsSync(sourceDist)) copyDirRecursive(sourceDist, node_path.join(targetDir, "dist"));
3307
- copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
3313
+ if (node_fs.existsSync(sourceDist)) await copyDirRecursive(sourceDist, node_path.join(targetDir, "dist"));
3314
+ await copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
3308
3315
  const strippedRuntimeDeps = strippedManifest["dependencies"];
3309
3316
  if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
3310
3317
  this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: { targetDir } });
@@ -3328,7 +3335,7 @@ var AddonInstaller = class AddonInstaller {
3328
3335
  try {
3329
3336
  await require_manifest_python_deps.installManifestNativeDeps(targetDir, pkgView.raw, this.logger, this.registry);
3330
3337
  } catch (nativeErr) {
3331
- node_fs.rmSync(targetDir, {
3338
+ await node_fs.promises.rm(targetDir, {
3332
3339
  recursive: true,
3333
3340
  force: true
3334
3341
  });
@@ -3343,7 +3350,7 @@ var AddonInstaller = class AddonInstaller {
3343
3350
  version: pkgView.version
3344
3351
  };
3345
3352
  } finally {
3346
- node_fs.rmSync(tmpDir, {
3353
+ await node_fs.promises.rm(tmpDir, {
3347
3354
  recursive: true,
3348
3355
  force: true
3349
3356
  });
@@ -4111,7 +4118,7 @@ var CapabilityRegistry = class CapabilityRegistry {
4111
4118
  const bare = this.bareAddonId(addonId);
4112
4119
  const nodeMap = this.singletonNodeOverrides.get(capabilityName);
4113
4120
  if (nodeMap) {
4114
- for (const [nodeId, ov] of [...nodeMap]) if (ov === bare) nodeMap.delete(nodeId);
4121
+ for (const [nodeId, ov] of Array.from(nodeMap)) if (ov === bare) nodeMap.delete(nodeId);
4115
4122
  if (nodeMap.size === 0) this.singletonNodeOverrides.delete(capabilityName);
4116
4123
  }
4117
4124
  this.logger.info("Provider unregistered from capability", {
@@ -7388,20 +7395,20 @@ var ConfigManager = class ConfigManager {
7388
7395
  setSettingsStore(store) {
7389
7396
  this.settingsStore = store;
7390
7397
  }
7391
- get(path) {
7392
- return this.resolveConfigValue(path);
7398
+ get(configPath) {
7399
+ return this.resolveConfigValue(configPath);
7393
7400
  }
7394
- resolveConfigValue(path) {
7395
- const bootstrapValue = this.getFromBootstrap(path);
7401
+ resolveConfigValue(configPath) {
7402
+ const bootstrapValue = this.getFromBootstrap(configPath);
7396
7403
  if (bootstrapValue !== void 0) return bootstrapValue;
7397
7404
  if (this.settingsStore !== null) {
7398
- const storeValue = this.settingsStore.getSystem(path);
7405
+ const storeValue = this.settingsStore.getSystem(configPath);
7399
7406
  if (storeValue !== void 0) return storeValue;
7400
- const nested = this.getNestedFromSystemSettings(path);
7407
+ const nested = this.getNestedFromSystemSettings(configPath);
7401
7408
  if (nested !== null) return nested;
7402
7409
  }
7403
- if (path in _camstack_types.RUNTIME_DEFAULTS) return _camstack_types.RUNTIME_DEFAULTS[path];
7404
- return this.getFromRuntimeDefaults(path) ?? void 0;
7410
+ if (configPath in _camstack_types.RUNTIME_DEFAULTS) return _camstack_types.RUNTIME_DEFAULTS[configPath];
7411
+ return this.getFromRuntimeDefaults(configPath) ?? void 0;
7405
7412
  }
7406
7413
  /**
7407
7414
  * Write a value to the settings-store.
@@ -7617,8 +7624,8 @@ var ConfigManager = class ConfigManager {
7617
7624
  };
7618
7625
  this.saveRuntimeState();
7619
7626
  }
7620
- getBootstrap(path) {
7621
- return this.getFromBootstrap(path);
7627
+ getBootstrap(configPath) {
7628
+ return this.getFromBootstrap(configPath);
7622
7629
  }
7623
7630
  /** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
7624
7631
  get features() {
@@ -7708,8 +7715,8 @@ var ConfigManager = class ConfigManager {
7708
7715
  * Deep-set a value in a nested plain object using a dot-notation path.
7709
7716
  * Returns a new object (immutable).
7710
7717
  */
7711
- setNested(obj, path, value) {
7712
- const [head, ...rest] = path.split(".");
7718
+ setNested(obj, configPath, value) {
7719
+ const [head, ...rest] = configPath.split(".");
7713
7720
  if (!head) return obj;
7714
7721
  if (rest.length === 0) return {
7715
7722
  ...obj,
@@ -7749,8 +7756,8 @@ var ConfigManager = class ConfigManager {
7749
7756
  warnDefaultCredentials() {
7750
7757
  if (this.bootstrapConfig.auth.adminPassword === "changeme") console.warn("[ConfigManager] Warning: Using default admin password \"changeme\". Set auth.adminPassword in your config.yaml or the CAMSTACK_ADMIN_PASS env var.");
7751
7758
  }
7752
- getFromBootstrap(path) {
7753
- const keys = path.split(".");
7759
+ getFromBootstrap(configPath) {
7760
+ const keys = configPath.split(".");
7754
7761
  let current = this.bootstrapConfig;
7755
7762
  for (const key of keys) {
7756
7763
  if (!isRecord(current)) return void 0;
@@ -7758,8 +7765,8 @@ var ConfigManager = class ConfigManager {
7758
7765
  }
7759
7766
  return current;
7760
7767
  }
7761
- getFromRuntimeDefaults(path) {
7762
- const prefix = path + ".";
7768
+ getFromRuntimeDefaults(configPath) {
7769
+ const prefix = configPath + ".";
7763
7770
  const result = {};
7764
7771
  let found = false;
7765
7772
  for (const [key, value] of Object.entries(_camstack_types.RUNTIME_DEFAULTS)) if (key.startsWith(prefix)) {
@@ -7774,10 +7781,10 @@ var ConfigManager = class ConfigManager {
7774
7781
  * e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
7775
7782
  * Returns an object keyed by the sub-key, or undefined if nothing is found.
7776
7783
  */
7777
- getNestedFromSystemSettings(path) {
7784
+ getNestedFromSystemSettings(configPath) {
7778
7785
  if (this.settingsStore === null) return null;
7779
7786
  const all = this.settingsStore.getAllSystem();
7780
- const prefix = path + ".";
7787
+ const prefix = configPath + ".";
7781
7788
  const result = {};
7782
7789
  let found = false;
7783
7790
  for (const [key, value] of Object.entries(all)) if (key.startsWith(prefix)) {
@@ -90938,7 +90945,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
90938
90945
  respawned.restartCount = prevRestartCount + 1;
90939
90946
  });
90940
90947
  restarted.push(name);
90941
- } catch (err) {
90948
+ } catch {
90942
90949
  failed.push(name);
90943
90950
  }
90944
90951
  return {
@@ -91333,8 +91340,8 @@ var LifecycleJobEngine = class {
91333
91340
  } finally {
91334
91341
  clearTimeout(timer);
91335
91342
  }
91336
- if (packages.length === 0) throw new Error("stageFramework returned no packages");
91337
91343
  const [firstPackage] = packages;
91344
+ if (!firstPackage) throw new Error("stageFramework returned no packages");
91338
91345
  this.advance(job.jobId, task, "staged", { stagedPath: firstPackage.stagedPath });
91339
91346
  requestFrameworkSwap({
91340
91347
  jobId: job.jobId,
@@ -91357,14 +91364,15 @@ var LifecycleJobEngine = class {
91357
91364
  */
91358
91365
  async fetchAddonsBounded(job, addonTasks) {
91359
91366
  const limit = Math.max(1, this.deps.fetchConcurrency ?? DEFAULT_FETCH_CONCURRENCY);
91360
- const outcomes = new Array(addonTasks.length);
91367
+ const outcomes = Array.from({ length: addonTasks.length });
91361
91368
  let nextIndex = 0;
91362
91369
  const worker = async () => {
91363
91370
  for (;;) {
91364
91371
  const index = nextIndex;
91365
91372
  nextIndex += 1;
91366
- if (index >= addonTasks.length) return;
91367
- outcomes[index] = await this.fetchAddonTask(job, addonTasks[index]);
91373
+ const addonTask = addonTasks[index];
91374
+ if (addonTask === void 0) return;
91375
+ outcomes[index] = await this.fetchAddonTask(job, addonTask);
91368
91376
  }
91369
91377
  };
91370
91378
  const workerCount = Math.min(limit, addonTasks.length);
@@ -91732,7 +91740,7 @@ exports.getWorkerDeviceRegistry = require_manifest_python_deps.getWorkerDeviceRe
91732
91740
  exports.hashClusterSecret = hashClusterSecret;
91733
91741
  exports.installManifestNativeDeps = require_manifest_python_deps.installManifestNativeDeps;
91734
91742
  exports.installManifestPythonDeps = require_manifest_python_deps.installManifestPythonDeps;
91735
- exports.installPackageFromNpmSync = installPackageFromNpmSync;
91743
+ exports.installPackageFromNpm = installPackageFromNpm;
91736
91744
  Object.defineProperty(exports, "installPythonPackages", {
91737
91745
  enumerable: true,
91738
91746
  get: function() {