Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions skills/hyperframes-animation/scripts/package-loader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { spawnSync } from "node:child_process";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { createRequire } from "node:module";
import { tmpdir } from "node:os";
import { basename, delimiter, dirname, join, parse, resolve } from "node:path";
import { basename, delimiter, dirname, join, parse, resolve, win32 as win32Path } from "node:path";
import { createInterface } from "node:readline/promises";
import { fileURLToPath, pathToFileURL } from "node:url";

Expand Down Expand Up @@ -243,23 +243,54 @@ function ancestors(start) {
return dirs;
}

export function resolveNpmSpawnCommand(
args,
platform = process.platform,
env = process.env,
nodeExecPath = process.execPath,
pathExists = existsSync,
) {
if (platform !== "win32") {
return { cmd: "npm", args, opts: { stdio: "inherit" } };
}

const bundledNpmCli = win32Path.join(
win32Path.dirname(nodeExecPath),
"node_modules",
"npm",
"bin",
"npm-cli.js",
);
const npmCli = [env.npm_execpath, bundledNpmCli].find(
(candidate) => candidate && pathExists(candidate),
);
if (!npmCli) return null;
return {
cmd: env.npm_node_execpath || nodeExecPath,
args: [npmCli, ...args],
opts: { stdio: "inherit", windowsHide: true },
};
}

function bootstrapWithNpmInstall(packageNames) {
const installRoot = mkdtempSync(join(tmpdir(), "hyperframes-skill-deps-"));
const installResult = spawnSync(
process.platform === "win32" ? "npm.cmd" : "npm",
[
"install",
"--silent",
"--no-audit",
"--no-fund",
"--ignore-scripts",
"--no-save",
"--prefix",
installRoot,
...packageNames,
],
{ stdio: "inherit" },
);
const npmArgs = [
"install",
"--silent",
"--no-audit",
"--no-fund",
"--ignore-scripts",
"--no-save",
"--prefix",
installRoot,
...packageNames,
];
const npmCommand = resolveNpmSpawnCommand(npmArgs);
if (!npmCommand) {
rmSync(installRoot, { recursive: true, force: true });
throw new Error("Could not locate npm-cli.js for dependency bootstrap on Windows.");
}
const installResult = spawnSync(npmCommand.cmd, npmCommand.args, npmCommand.opts);

if (installResult.error) throw installResult.error;
if (installResult.status !== 0) {
Expand Down
35 changes: 35 additions & 0 deletions skills/hyperframes-animation/scripts/package-loader.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,45 @@ import { copyFileSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { tmpdir } from "node:os";
import { fileURLToPath } from "node:url";
import { resolveNpmSpawnCommand } from "./package-loader.mjs";

const HERE = dirname(fileURLToPath(import.meta.url));
const ENV = "HYPERFRAMES_SKILL_PKG_VERSION";

test("resolveNpmSpawnCommand routes Windows npm through node and npm-cli.js", () => {
const npmCli = "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js";
const node = "C:\\Program Files\\nodejs\\node.exe";
const resolved = resolveNpmSpawnCommand(
["install", "@hyperframes/producer@0.7.55", "value & calc"],
"win32",
{ npm_execpath: npmCli, npm_node_execpath: node },
node,
(path) => path === npmCli,
);

assert.deepEqual(resolved, {
cmd: node,
args: [npmCli, "install", "@hyperframes/producer@0.7.55", "value & calc"],
opts: { stdio: "inherit", windowsHide: true },
});
assert.equal(resolved.opts.shell, undefined);
});

test("resolveNpmSpawnCommand finds npm-cli.js beside node for direct Windows runs", () => {
const node = "C:\\Program Files\\nodejs\\node.exe";
const npmCli = "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js";
const resolved = resolveNpmSpawnCommand(
["install", "@hyperframes/producer@0.7.55"],
"win32",
{},
node,
(path) => path === npmCli,
);

assert.equal(resolved?.cmd, node);
assert.deepEqual(resolved?.args, [npmCli, "install", "@hyperframes/producer@0.7.55"]);
});

// (a) env override wins — no ancestor lookup, exact version echoed back.
test("hyperframesPackageSpec: env override wins", async () => {
const prev = process.env[ENV];
Expand Down
63 changes: 47 additions & 16 deletions skills/hyperframes-creative/scripts/package-loader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { spawnSync } from "node:child_process";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { createRequire } from "node:module";
import { tmpdir } from "node:os";
import { basename, delimiter, dirname, join, parse, resolve } from "node:path";
import { basename, delimiter, dirname, join, parse, resolve, win32 as win32Path } from "node:path";
import { createInterface } from "node:readline/promises";
import { fileURLToPath, pathToFileURL } from "node:url";

Expand Down Expand Up @@ -243,23 +243,54 @@ function ancestors(start) {
return dirs;
}

export function resolveNpmSpawnCommand(
args,
platform = process.platform,
env = process.env,
nodeExecPath = process.execPath,
pathExists = existsSync,
) {
if (platform !== "win32") {
return { cmd: "npm", args, opts: { stdio: "inherit" } };
}

const bundledNpmCli = win32Path.join(
win32Path.dirname(nodeExecPath),
"node_modules",
"npm",
"bin",
"npm-cli.js",
);
const npmCli = [env.npm_execpath, bundledNpmCli].find(
(candidate) => candidate && pathExists(candidate),
);
if (!npmCli) return null;
return {
cmd: env.npm_node_execpath || nodeExecPath,
args: [npmCli, ...args],
opts: { stdio: "inherit", windowsHide: true },
};
}

function bootstrapWithNpmInstall(packageNames) {
const installRoot = mkdtempSync(join(tmpdir(), "hyperframes-skill-deps-"));
const installResult = spawnSync(
process.platform === "win32" ? "npm.cmd" : "npm",
[
"install",
"--silent",
"--no-audit",
"--no-fund",
"--ignore-scripts",
"--no-save",
"--prefix",
installRoot,
...packageNames,
],
{ stdio: "inherit" },
);
const npmArgs = [
"install",
"--silent",
"--no-audit",
"--no-fund",
"--ignore-scripts",
"--no-save",
"--prefix",
installRoot,
...packageNames,
];
const npmCommand = resolveNpmSpawnCommand(npmArgs);
if (!npmCommand) {
rmSync(installRoot, { recursive: true, force: true });
throw new Error("Could not locate npm-cli.js for dependency bootstrap on Windows.");
}
const installResult = spawnSync(npmCommand.cmd, npmCommand.args, npmCommand.opts);

if (installResult.error) throw installResult.error;
if (installResult.status !== 0) {
Expand Down
35 changes: 35 additions & 0 deletions skills/hyperframes-creative/scripts/package-loader.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,45 @@ import { copyFileSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { tmpdir } from "node:os";
import { fileURLToPath } from "node:url";
import { resolveNpmSpawnCommand } from "./package-loader.mjs";

const HERE = dirname(fileURLToPath(import.meta.url));
const ENV = "HYPERFRAMES_SKILL_PKG_VERSION";

test("resolveNpmSpawnCommand routes Windows npm through node and npm-cli.js", () => {
const npmCli = "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js";
const node = "C:\\Program Files\\nodejs\\node.exe";
const resolved = resolveNpmSpawnCommand(
["install", "@hyperframes/producer@0.7.55", "value & calc"],
"win32",
{ npm_execpath: npmCli, npm_node_execpath: node },
node,
(path) => path === npmCli,
);

assert.deepEqual(resolved, {
cmd: node,
args: [npmCli, "install", "@hyperframes/producer@0.7.55", "value & calc"],
opts: { stdio: "inherit", windowsHide: true },
});
assert.equal(resolved.opts.shell, undefined);
});

test("resolveNpmSpawnCommand finds npm-cli.js beside node for direct Windows runs", () => {
const node = "C:\\Program Files\\nodejs\\node.exe";
const npmCli = "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js";
const resolved = resolveNpmSpawnCommand(
["install", "@hyperframes/producer@0.7.55"],
"win32",
{},
node,
(path) => path === npmCli,
);

assert.equal(resolved?.cmd, node);
assert.deepEqual(resolved?.args, [npmCli, "install", "@hyperframes/producer@0.7.55"]);
});

// (a) env override wins — no ancestor lookup, exact version echoed back.
test("hyperframesPackageSpec: env override wins", async () => {
const prev = process.env[ENV];
Expand Down
Loading