test(repo): verify packed consumers

This commit is contained in:
James
2026-07-13 11:35:37 -04:00
parent 758a6d2152
commit 979e9d0902
2 changed files with 161 additions and 10 deletions
+131 -9
View File
@@ -1,7 +1,15 @@
#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs";
import {
existsSync,
mkdirSync,
mkdtempSync,
readdirSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { extname, join, posix } from "node:path";
import { tmpdir } from "node:os";
import { fileURLToPath } from "node:url";
@@ -272,25 +280,139 @@ function verifyPackedWorkspace(workspace, filename) {
verifyPackedJavaScriptImports(workspace, filename, packedFiles);
}
function verifyWorkspace(workspace) {
export function packageExportSpecifier(packageName, exportKey) {
return exportKey === "." ? packageName : `${packageName}/${exportKey.replace(/^\.\//, "")}`;
}
export function listPackedExportContracts(packedWorkspaces) {
return packedWorkspaces.flatMap(({ packedPackage }) =>
Object.entries(packedPackage.exports ?? {}).map(([exportKey, target]) => ({
specifier: packageExportSpecifier(packedPackage.name, exportKey),
typechecked: Boolean(target?.types),
})),
);
}
function writeConsumerFixture(packDir, packedWorkspaces) {
const fixtureDir = join(packDir, "consumer");
mkdirSync(fixtureDir);
const rootPackage = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
const dependencies = Object.fromEntries(
packedWorkspaces.map(({ filename, packedPackage }) => [packedPackage.name, `file:${filename}`]),
);
dependencies.typescript = rootPackage.devDependencies.typescript;
dependencies["@types/node"] = rootPackage.devDependencies["@types/node"];
writeFileSync(
join(fixtureDir, "package.json"),
JSON.stringify(
{ name: "packed-consumer", private: true, type: "module", dependencies },
null,
2,
),
);
const contracts = listPackedExportContracts(packedWorkspaces);
const typeImports = contracts
.filter(({ typechecked }) => typechecked)
.map(({ specifier }) => `import ${JSON.stringify(specifier)};`)
.join("\n");
writeFileSync(join(fixtureDir, "consumer.ts"), `${typeImports}\n`);
writeFileSync(
join(fixtureDir, "tsconfig.json"),
JSON.stringify(
{
compilerOptions: {
target: "ES2022",
module: "NodeNext",
moduleResolution: "NodeNext",
lib: ["ES2022", "DOM", "DOM.Iterable"],
strict: true,
skipLibCheck: true,
noEmit: true,
},
include: ["consumer.ts"],
},
null,
2,
),
);
const specifiers = contracts.map(({ specifier }) => specifier);
writeFileSync(
join(fixtureDir, "consumer-smoke.mjs"),
`const specifiers = ${JSON.stringify(specifiers, null, 2)};\n` +
`for (const specifier of specifiers) import.meta.resolve(specifier);\n` +
`const sdk = await import("@hyperframes/sdk");\n` +
`if (typeof sdk.openComposition !== "function") throw new Error("SDK root export missing");\n` +
`const memory = await import("@hyperframes/sdk/adapters/memory");\n` +
`if (typeof memory.createMemoryAdapter !== "function") throw new Error("memory adapter missing");\n` +
`const fsAdapter = await import("@hyperframes/sdk/adapters/fs");\n` +
`if (typeof fsAdapter.createFsAdapter !== "function") throw new Error("fs adapter missing");\n` +
`await import("@hyperframes/core");\n` +
`await import("@hyperframes/parsers");\n` +
`await import("@hyperframes/lint");\n` +
`await import("@hyperframes/studio-server");\n` +
`console.log(\`Resolved \${specifiers.length} packed exports and loaded public SDK adapters.\`);\n`,
);
return fixtureDir;
}
function verifyPackedConsumer(packDir, packedWorkspaces) {
const fixtureDir = writeConsumerFixture(packDir, packedWorkspaces);
execFileSync("bun", ["install", "--ignore-scripts"], {
cwd: fixtureDir,
encoding: "utf8",
stdio: "pipe",
});
execFileSync(process.execPath, [join(fixtureDir, "node_modules", "typescript", "bin", "tsc")], {
cwd: fixtureDir,
encoding: "utf8",
stdio: "pipe",
});
const smokeOutput = execFileSync("node", ["consumer-smoke.mjs"], {
cwd: fixtureDir,
encoding: "utf8",
});
const cliOutput = execFileSync(
join(fixtureDir, "node_modules", ".bin", "hyperframes"),
["--help"],
{
cwd: fixtureDir,
encoding: "utf8",
env: { ...process.env, HYPERFRAMES_TELEMETRY_DISABLED: "1" },
},
);
if (!cliOutput.toLowerCase().includes("hyperframes")) {
throw new Error("Packed CLI help did not identify HyperFrames");
}
console.log(smokeOutput.trim());
console.log("Verified clean packed consumer install, type resolution, and CLI startup.");
}
function packAndVerifyWorkspace(workspace, packDir) {
const sourcePackageJson = readWorkspacePackage(workspace);
if (sourcePackageJson.private) return;
if (sourcePackageJson.private) return null;
assertPublishedExportsMatchSource(workspace, sourcePackageJson);
const filename = packWorkspace(workspace, packDir);
verifyPackedWorkspace(workspace, filename);
const packedPackage = readPackedPackage(filename);
console.log(`Verified ${workspace}: packed manifest is publish-safe.`);
return { workspace, filename, packedPackage };
}
function main() {
const packDir = mkdtempSync(join(tmpdir(), "hyperframes-pack-"));
try {
verifyPackedWorkspace(workspace, packWorkspace(workspace, packDir));
console.log(`Verified ${workspace}: packed manifest is publish-safe.`);
const packedWorkspaces = listWorkspacePackageDirs()
.map((workspace) => packAndVerifyWorkspace(workspace, packDir))
.filter(Boolean);
verifyPackedConsumer(packDir, packedWorkspaces);
} finally {
rmSync(packDir, { force: true, recursive: true });
}
}
function main() {
listWorkspacePackageDirs().forEach(verifyWorkspace);
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
main();
}
+30 -1
View File
@@ -4,9 +4,38 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { describe, it } from "node:test";
import { listPackedJavaScriptImportIssues } from "./verify-packed-manifests.mjs";
import {
listPackedExportContracts,
listPackedJavaScriptImportIssues,
packageExportSpecifier,
} from "./verify-packed-manifests.mjs";
describe("packed manifest verifier", () => {
it("derives consumer specifiers from the packed export map", () => {
assert.equal(packageExportSpecifier("@hyperframes/sdk", "."), "@hyperframes/sdk");
assert.equal(
packageExportSpecifier("@hyperframes/sdk", "./adapters/fs"),
"@hyperframes/sdk/adapters/fs",
);
assert.deepEqual(
listPackedExportContracts([
{
packedPackage: {
name: "@hyperframes/example",
exports: {
".": { import: "./dist/index.js", types: "./dist/index.d.ts" },
"./runtime": "./dist/runtime.js",
},
},
},
]),
[
{ specifier: "@hyperframes/example", typechecked: true },
{ specifier: "@hyperframes/example/runtime", typechecked: false },
],
);
});
function withPackedFiles(files, packedFiles, callback) {
const dir = mkdtempSync(join(tmpdir(), "hyperframes-pack-test-"));
try {