feat(cli): let projects opt out of automatic proxying (#2591)

* feat(studio-server): serve H.264 proxies from the preview route

Wires the codec manifest and the transcoder into the preview surface: the route
negotiates a proxy via a query param and serves it through the existing range
and ETag machinery, composition HTML carries a codec map for the runtime, and
hostile assets pre-warm so a first play does not wait on a cold transcode.
Exposes the three subpath exports the CLI surfaces consume upstack.

Drops the TEMP fallow entry added with the transcoder: it has real importers now.

* fix(studio-server): publish media proxy exports

* fix(parsers): scan HTML comments linearly

* feat(cli): let projects opt out of automatic proxying

Adds media.autoProxy to hyperframes.json plus --proxy/--no-proxy flags, and
forwards the resolved value into the studio and preview servers and the vite
adapter. Lands before the runtime slice that turns auto-proxying on, so the
switch exists before there is any behavior to switch off.

* fix(cli): align media config schema
This commit is contained in:
Miguel Ángel
2026-07-16 23:01:14 -04:00
committed by GitHub
parent 67eab59f44
commit 6458807066
10 changed files with 292 additions and 5 deletions
+51 -1
View File
@@ -1,9 +1,59 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it } from "vitest";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { loadHyperframeRuntimeSource } from "@hyperframes/core";
import { loadRuntimeSource } from "./runtimeSource.js";
import { createStudioServer, type StudioServer } from "./studioServer.js";
describe("loadRuntimeSource", () => {
it("loads runtime source from the published core entrypoint", async () => {
await expect(loadRuntimeSource()).resolves.toBe(loadHyperframeRuntimeSource());
});
});
describe("createStudioServer autoProxy plumbing", () => {
const dirs: string[] = [];
let server: StudioServer | undefined;
function tmpProject(): string {
const dir = mkdtempSync(join(tmpdir(), "hf-studio-server-test-"));
dirs.push(dir);
return dir;
}
afterEach(() => {
server?.watcher.close();
server = undefined;
for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true });
});
it("hyperframes.json media.autoProxy=false flows through to the adapter", () => {
const projectDir = tmpProject();
writeFileSync(
join(projectDir, "hyperframes.json"),
JSON.stringify({ media: { autoProxy: false } }),
);
server = createStudioServer({ projectDir });
expect(server.adapter.autoProxy).toBe(false);
});
it("defaults the adapter to autoProxy=true when neither option nor config disables it", () => {
server = createStudioServer({ projectDir: tmpProject() });
expect(server.adapter.autoProxy).toBe(true);
});
it("an explicit option (the preview command's resolved --proxy flag) wins over config", () => {
const projectDir = tmpProject();
writeFileSync(
join(projectDir, "hyperframes.json"),
JSON.stringify({ media: { autoProxy: false } }),
);
server = createStudioServer({ projectDir, autoProxy: true });
expect(server.adapter.autoProxy).toBe(true);
});
});