refactor(repo): resolve changed-code audit

This commit is contained in:
James
2026-07-20 11:59:57 -07:00
parent cbcf45facf
commit ab8b50afd7
21 changed files with 54 additions and 51 deletions
+5 -16
View File
@@ -1,8 +1,8 @@
import { promises as fs } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { readStore, writeStore } from "../../auth/store.js";
import { setupTempAuthEnv, type EnvFixture } from "../../auth/_test-utils.js";
import { CliRuntimeError } from "../../utils/commandResult.js";
// Mock only AuthClient — keep the real store/resolver so the test
@@ -43,19 +43,13 @@ const telemetry = vi.hoisted(() => ({
}));
vi.mock("../../telemetry/index.js", () => telemetry);
const ENV_KEYS = ["HEYGEN_API_KEY", "HYPERFRAMES_API_KEY", "HEYGEN_CONFIG_DIR"] as const;
describe("auth login --api-key rollback", () => {
let dir: string;
const saved: Partial<Record<(typeof ENV_KEYS)[number], string | undefined>> = {};
let envFixture: EnvFixture;
beforeEach(async () => {
dir = await fs.mkdtemp(join(tmpdir(), "hf-login-"));
for (const k of ENV_KEYS) {
saved[k] = process.env[k];
delete process.env[k];
}
process.env["HEYGEN_CONFIG_DIR"] = dir;
envFixture = await setupTempAuthEnv("hf-login-");
dir = envFixture.dir;
verifyState.reject = false;
verifyState.user = { email: "alice@example.com" };
for (const fn of Object.values(telemetry)) fn.mockClear();
@@ -65,12 +59,7 @@ describe("auth login --api-key rollback", () => {
afterEach(async () => {
vi.restoreAllMocks();
for (const k of ENV_KEYS) {
const v = saved[k];
if (v === undefined) delete process.env[k];
else process.env[k] = v;
}
await fs.rm(dir, { recursive: true, force: true });
await envFixture.restore();
});
async function runLogin(apiKey: string): Promise<void> {
@@ -1,9 +1,6 @@
// fallow-ignore-file code-duplication
import { promises as fs } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { writeStore } from "../../auth/store.js";
import { setupTempAuthEnv, type EnvFixture } from "../../auth/_test-utils.js";
import { consumeCommandResult } from "../../utils/commandResult.js";
// Mock only AuthClient so the live /v3/users/me probe is controllable;
@@ -33,20 +30,12 @@ vi.mock("../../auth/index.js", async (orig) => {
return { ...actual, AuthClient: MockAuthClient };
});
const ENV_KEYS = ["HEYGEN_API_KEY", "HYPERFRAMES_API_KEY", "HEYGEN_CONFIG_DIR"] as const;
describe("auth status — persisted user block surface", () => {
let dir: string;
const saved: Partial<Record<(typeof ENV_KEYS)[number], string | undefined>> = {};
let envFixture: EnvFixture;
let stdout: string[];
beforeEach(async () => {
dir = await fs.mkdtemp(join(tmpdir(), "hf-status-"));
for (const k of ENV_KEYS) {
saved[k] = process.env[k];
delete process.env[k];
}
process.env["HEYGEN_CONFIG_DIR"] = dir;
envFixture = await setupTempAuthEnv("hf-status-");
probeState.apiReject = false;
probeState.user = { email: "live@example.com" };
stdout = [];
@@ -60,12 +49,7 @@ describe("auth status — persisted user block surface", () => {
afterEach(async () => {
consumeCommandResult();
vi.restoreAllMocks();
for (const k of ENV_KEYS) {
const v = saved[k];
if (v === undefined) delete process.env[k];
else process.env[k] = v;
}
await fs.rm(dir, { recursive: true, force: true });
await envFixture.restore();
});
async function runStatus(asJson: boolean): Promise<number> {
+14 -12
View File
@@ -525,6 +525,18 @@ async function runSites(args: Record<string, unknown>): Promise<void> {
// ── render ──────────────────────────────────────────────────────────────────
function resolveCloudRunFps(
args: Record<string, unknown>,
projectDir: string,
command: "render" | "render-batch",
): 24 | 30 | 60 {
const fps =
parseIntFlag(args.fps) ?? readAllowedCompositionFpsFromDir(projectDir, [24, 30, 60]) ?? 30;
if (fps === 24 || fps === 30 || fps === 60) return fps;
console.error(`[cloudrun ${command}] --fps must be 24, 30, or 60; got ${fps}.`);
failCommand();
}
// fallow-ignore-next-line complexity
async function runRender(args: Record<string, unknown>): Promise<void> {
const projectDir = args.target as string | undefined;
@@ -540,12 +552,7 @@ async function runRender(args: Record<string, unknown>): Promise<void> {
console.error("[cloudrun render] --width and --height are required.");
failCommand();
}
const fps =
parseIntFlag(args.fps) ?? readAllowedCompositionFpsFromDir(projectDir, [24, 30, 60]) ?? 30;
if (fps !== 24 && fps !== 30 && fps !== 60) {
console.error(`[cloudrun render] --fps must be 24, 30, or 60; got ${fps}.`);
failCommand();
}
const fps = resolveCloudRunFps(args, projectDir, "render");
const state = readState(args);
const variables = resolveAndValidateVariables(args, resolve(projectDir));
const config = buildRenderConfig(args, fps, width, height, variables);
@@ -651,12 +658,7 @@ async function runRenderBatch(args: Record<string, unknown>): Promise<void> {
console.error("[cloudrun render-batch] --width and --height are required.");
failCommand();
}
const fps =
parseIntFlag(args.fps) ?? readAllowedCompositionFpsFromDir(projectDir, [24, 30, 60]) ?? 30;
if (fps !== 24 && fps !== 30 && fps !== 60) {
console.error(`[cloudrun render-batch] --fps must be 24, 30, or 60; got ${fps}.`);
failCommand();
}
const fps = resolveCloudRunFps(args, projectDir, "render-batch");
if (!existsSync(resolve(batchPath))) {
console.error(`[cloudrun render-batch] batch file not found: ${batchPath}`);
failCommand();
+1
View File
@@ -5,6 +5,7 @@ import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, rmSync }
import { createRenderPlan, resolveBrowserGpuForCli, type RenderFormat } from "./render/plan.js";
import { presentRenderPlan } from "./render/present.js";
import { executeRenderPlan, renderLintContinuationHint } from "./render/execute.js";
// Test-only seams retained at the command boundary for render behavior tests.
export { resolveBrowserGpuForCli, renderLintContinuationHint };
export const examples: Example[] = [
@@ -33,6 +33,8 @@ export interface RenderExecutionDependencies {
checkResolution: ResolutionPreflight;
}
// Exported only through render.ts so command tests can lock the user-facing guidance.
// fallow-ignore-next-line unused-export
export function renderLintContinuationHint(strictErrors: boolean): string {
return strictErrors
? " Continuing render despite lint warnings. Use --strict-all to block warnings."
@@ -156,6 +158,7 @@ async function ensureRenderBrowser(plan: RenderPlan): Promise<string> {
}
}
// fallow-ignore-next-line complexity
async function runRenderLint(plan: RenderPlan): Promise<void> {
// lintProject's explicit-entry contract is an absolute source path;
// entryFile remains project-relative for the producer.
+2
View File
@@ -454,6 +454,8 @@ export function renderOutputDirectory(plan: RenderPlan): string {
}
/** Resolve browser GPU mode from Docker, CLI, env, then the auto default. */
// Re-exported by render.ts to preserve its tested public seam.
// fallow-ignore-next-line unused-export
export function resolveBrowserGpuForCli(
useDocker: boolean,
browserGpuArg: boolean | undefined,
@@ -5,6 +5,8 @@ import { c } from "../../ui/colors.js";
import type { RenderPlan } from "./plan.js";
/** Present warnings and the human render plan. JSON batch output stays silent. */
// This phase intentionally owns every mutually exclusive human-output branch.
// fallow-ignore-next-line complexity
export async function presentRenderPlan(plan: RenderPlan): Promise<void> {
await presentRenderWarnings(plan);
if (plan.effectiveQuiet || plan.batchPath) return;