fix(cli): reject blank default composition entries (#3392)

* fix(cli): reject blank default composition entry

* fix(cli): complete blank entry safeguards
This commit is contained in:
Miguel Ángel
2026-08-21 11:00:43 -04:00
committed by GitHub
parent 1b86b56127
commit a9ea07edde
11 changed files with 412 additions and 26 deletions
+46 -1
View File
@@ -3,7 +3,7 @@ import { mkdirSync, mkdtempSync, writeFileSync, rmSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import type { HyperframeLintFinding } from "@hyperframes/core/lint";
import { lintProject, shouldBlockRender } from "./lintProject.js";
import { hasDefinitiveEntryMismatch, lintProject, shouldBlockRender } from "./lintProject.js";
function tmpProject(name: string): string {
return mkdtempSync(join(tmpdir(), `hf-test-${name}-`));
@@ -249,6 +249,51 @@ describe("lintProject", () => {
});
});
describe("hasDefinitiveEntryMismatch", () => {
it("distinguishes the blank-default-entry failure from ordinary lint errors", () => {
const result = {
results: [
{
file: "index.html",
contentHash: "abc",
result: {
ok: false,
errorCount: 1,
warningCount: 0,
infoCount: 0,
findings: [
{
code: "blank_root_with_standalone_composition",
severity: "error" as const,
message: "wrong entry",
},
],
},
},
],
totalErrors: 1,
totalWarnings: 0,
totalInfos: 0,
};
expect(hasDefinitiveEntryMismatch(result)).toBe(true);
expect(
hasDefinitiveEntryMismatch({
...result,
results: [
{
...result.results[0]!,
result: {
...result.results[0]!.result,
findings: [{ code: "media_missing_id", severity: "error", message: "missing" }],
},
},
],
}),
).toBe(false);
});
});
function validHtmlWithAudio(compId = "main"): string {
return `<html><body>
<div data-composition-id="${compId}" data-width="1920" data-height="1080">
+11 -1
View File
@@ -1,3 +1,13 @@
// ponytail: thin re-export — lintProject lives in @hyperframes/lint so it's usable without the CLI
// CLI facade: the linter stays reusable without the CLI, while command-specific gates live here.
export { lintProject, shouldBlockRender } from "@hyperframes/lint";
export type { ProjectLintResult } from "@hyperframes/lint";
import type { ProjectLintResult } from "@hyperframes/lint";
export function hasDefinitiveEntryMismatch(result: ProjectLintResult): boolean {
return result.results.some((entry) =>
entry.result.findings.some(
(finding) => finding.code === "blank_root_with_standalone_composition",
),
);
}