buildwithnexus 0.3.4 → 0.3.6

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/bin.js CHANGED
@@ -438,59 +438,59 @@ async function getPortBlocker(port) {
438
438
  return null;
439
439
  }
440
440
  }
441
- async function findFreePort(preferred, max = 20) {
442
- for (let offset = 0; offset < max; offset++) {
443
- if (await isPortFree(preferred + offset)) return preferred + offset;
444
- }
445
- throw new Error(`No free port found near ${preferred}`);
446
- }
447
441
  async function resolvePortConflicts(ports) {
448
442
  const labels = { ssh: "SSH", http: "HTTP", https: "HTTPS" };
449
443
  const resolved = { ...ports };
444
+ const claimed = /* @__PURE__ */ new Set();
450
445
  for (const [key, port] of Object.entries(ports)) {
451
- if (await isPortFree(port)) continue;
452
- const blocker = await getPortBlocker(port);
453
- const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "unknown process";
454
- const altPort = await findFreePort(port + 1).catch(() => null);
455
- const choices = [];
456
- if (blocker) {
457
- choices.push({
458
- name: `Kill ${desc} and use port ${port}`,
459
- value: "kill"
460
- });
446
+ if (await isPortFree(port) && !claimed.has(port)) {
447
+ claimed.add(port);
448
+ continue;
449
+ }
450
+ let altPort = null;
451
+ for (let offset = 1; offset <= 50; offset++) {
452
+ const candidate = port + offset;
453
+ if (!claimed.has(candidate) && await isPortFree(candidate)) {
454
+ altPort = candidate;
455
+ break;
456
+ }
461
457
  }
462
458
  if (altPort) {
463
- choices.push({
464
- name: `Use alternate port ${altPort} instead`,
465
- value: "alt"
459
+ resolved[key] = altPort;
460
+ claimed.add(altPort);
461
+ const blocker = await getPortBlocker(port);
462
+ const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "another process";
463
+ console.log(chalk5.yellow(` \u26A0 Port ${port} (${labels[key]}) in use by ${desc} \u2192 using ${altPort}`));
464
+ } else {
465
+ const blocker = await getPortBlocker(port);
466
+ const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "unknown process";
467
+ console.log("");
468
+ console.log(chalk5.red(` \u2717 Port ${port} (${labels[key]}) is in use by ${desc} and no free port found nearby`));
469
+ const action = await select({
470
+ message: `No free ${labels[key]} port found. Kill ${desc} to free port ${port}?`,
471
+ choices: [
472
+ ...blocker ? [{ name: `Kill ${desc} and use port ${port}`, value: "kill" }] : [],
473
+ { name: "Abort init", value: "abort" }
474
+ ]
466
475
  });
467
- }
468
- choices.push({ name: "Abort init", value: "abort" });
469
- console.log("");
470
- console.log(chalk5.yellow(` \u26A0 Port ${port} (${labels[key]}) is in use by ${desc}`));
471
- const action = await select({
472
- message: `How would you like to resolve the ${labels[key]} port conflict?`,
473
- choices
474
- });
475
- if (action === "kill" && blocker) {
476
- try {
477
- process.kill(blocker.pid, "SIGTERM");
478
- await new Promise((r) => setTimeout(r, 1e3));
479
- if (!await isPortFree(port)) {
480
- process.kill(blocker.pid, "SIGKILL");
481
- await new Promise((r) => setTimeout(r, 500));
476
+ if (action === "kill" && blocker) {
477
+ try {
478
+ process.kill(blocker.pid, "SIGTERM");
479
+ await new Promise((r) => setTimeout(r, 1e3));
480
+ if (!await isPortFree(port)) {
481
+ process.kill(blocker.pid, "SIGKILL");
482
+ await new Promise((r) => setTimeout(r, 500));
483
+ }
484
+ claimed.add(port);
485
+ console.log(chalk5.green(` \u2713 Killed ${desc}, port ${port} is now free`));
486
+ } catch {
487
+ console.log(chalk5.red(` \u2717 Failed to kill PID ${blocker.pid}. Try: sudo kill ${blocker.pid}`));
488
+ process.exit(1);
482
489
  }
483
- console.log(chalk5.green(` \u2713 Killed ${desc}, port ${port} is now free`));
484
- } catch {
485
- console.log(chalk5.red(` \u2717 Failed to kill PID ${blocker.pid}. Try: sudo kill ${blocker.pid}`));
486
- process.exit(1);
490
+ } else {
491
+ console.log(chalk5.dim(" Init aborted."));
492
+ process.exit(0);
487
493
  }
488
- } else if (action === "alt" && altPort) {
489
- resolved[key] = altPort;
490
- console.log(chalk5.green(` \u2713 Using port ${altPort} for ${labels[key]}`));
491
- } else {
492
- console.log(chalk5.dim(" Init aborted."));
493
- process.exit(0);
494
494
  }
495
495
  }
496
496
  return resolved;
@@ -938,13 +938,13 @@ async function renderCloudInit(data, templateContent) {
938
938
  }
939
939
  const safeData = { ...data, sshPubKey: yamlEscape(trimmedPubKey), keys: safeKeys };
940
940
  const rendered = ejs.render(templateContent, safeData);
941
- const outputPath = path5.join(CONFIGS_DIR, "user-data.yaml");
941
+ const outputPath = path5.join(CONFIGS_DIR, "user-data");
942
942
  fs5.writeFileSync(outputPath, rendered, { mode: 384 });
943
- audit("cloudinit_rendered", "user-data.yaml written");
943
+ audit("cloudinit_rendered", "user-data written");
944
944
  return outputPath;
945
945
  }
946
946
  async function createCloudInitIso(userDataPath) {
947
- const metaDataPath = path5.join(CONFIGS_DIR, "meta-data.yaml");
947
+ const metaDataPath = path5.join(CONFIGS_DIR, "meta-data");
948
948
  fs5.writeFileSync(metaDataPath, "instance-id: nexus-vm-1\nlocal-hostname: nexus-vm\n", { mode: 384 });
949
949
  const isoPath = path5.join(IMAGES_DIR2, "init.iso");
950
950
  const env = scrubEnv();
@@ -1005,7 +1005,7 @@ async function createCloudInitIso(userDataPath) {
1005
1005
  fs5.unlinkSync(metaDataPath);
1006
1006
  } catch {
1007
1007
  }
1008
- audit("cloudinit_plaintext_deleted", "user-data.yaml and meta-data.yaml removed");
1008
+ audit("cloudinit_plaintext_deleted", "user-data and meta-data removed");
1009
1009
  }
1010
1010
  }
1011
1011
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buildwithnexus",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Launch an autonomous AI runtime with triple-nested VM isolation in one command",
5
5
  "type": "module",
6
6
  "bin": {