mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 03:06:41 +00:00
* fix(skills): make hyperframes package version resolution non-fatal and overridable Global skill installs (e.g. ~/.claude/skills) have no hyperframes package.json in the loader's ancestor chain, so readBundledHyperframesVersion returns null and hyperframesPackageSpec threw. Because the spec is passed eagerly as an argument to importPackagesOrBootstrap, it threw even when @hyperframes/producer was already installed and no bootstrap was needed. Resolution order is now: HYPERFRAMES_SKILL_PKG_VERSION env override first, then the bundled/in-repo version, then a non-throwing @latest fallback that warns to stderr. @latest satisfies the pinned-spec guard so bootstrap still installs, and already-installed packages import fine; the eager argument is now harmless. In-repo resolution is unchanged (same pinned version). Applied to both package-loader.mjs copies (animation + creative) and documented the env var in animation-map.mjs and contrast-report.mjs usage. Adds a focused test covering override wins, in-repo pin, and unresolvable @latest fallback. * test(skills): cover creative package loader fallback
63 lines
2.5 KiB
JavaScript
63 lines
2.5 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { spawnSync } from "node:child_process";
|
|
import { copyFileSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
const ENV = "HYPERFRAMES_SKILL_PKG_VERSION";
|
|
|
|
// (a) env override wins — no ancestor lookup, exact version echoed back.
|
|
test("hyperframesPackageSpec: env override wins", async () => {
|
|
const prev = process.env[ENV];
|
|
process.env[ENV] = "9.9.9";
|
|
try {
|
|
const { hyperframesPackageSpec } = await import("./package-loader.mjs");
|
|
assert.equal(hyperframesPackageSpec("@hyperframes/producer"), "@hyperframes/producer@9.9.9");
|
|
} finally {
|
|
if (prev === undefined) delete process.env[ENV];
|
|
else process.env[ENV] = prev;
|
|
}
|
|
});
|
|
|
|
// (b) resolvable version (in-repo) pins the bundled hyperframes/@hyperframes/cli version.
|
|
test("hyperframesPackageSpec: resolvable in-repo version pins it", async () => {
|
|
const prev = process.env[ENV];
|
|
delete process.env[ENV];
|
|
try {
|
|
const { hyperframesPackageSpec } = await import("./package-loader.mjs");
|
|
const spec = hyperframesPackageSpec("@hyperframes/producer");
|
|
assert.match(spec, /^@hyperframes\/producer@\d+\.\d+\.\d+/);
|
|
} finally {
|
|
if (prev !== undefined) process.env[ENV] = prev;
|
|
}
|
|
});
|
|
|
|
// (c) unresolvable + no override -> @latest fallback, no throw (global-install case).
|
|
// Copy the loader into an isolated temp dir whose ancestor chain has no hyperframes
|
|
// package.json, and run node from there so cwd cannot resolve one either.
|
|
test("hyperframesPackageSpec: unresolvable falls back to @latest without throwing", () => {
|
|
const dir = mkdtempSync(join(tmpdir(), "hf-pkgloader-"));
|
|
try {
|
|
copyFileSync(join(HERE, "package-loader.mjs"), join(dir, "package-loader.mjs"));
|
|
const probe = join(dir, "probe.mjs");
|
|
writeFileSync(
|
|
probe,
|
|
[
|
|
'import { hyperframesPackageSpec } from "./package-loader.mjs";',
|
|
'process.stdout.write(hyperframesPackageSpec("@hyperframes/producer"));',
|
|
"",
|
|
].join("\n"),
|
|
);
|
|
const res = spawnSync(process.execPath, [probe], { cwd: dir, encoding: "utf8" });
|
|
assert.equal(res.status, 0, res.stderr);
|
|
assert.equal(res.stdout.trim(), "@hyperframes/producer@latest");
|
|
assert.match(res.stderr, /using @latest/);
|
|
assert.match(res.stderr, new RegExp(ENV));
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|