Skip to content

Commit 656544d

Browse files
jrusso1020claude
andcommitted
refactor: extract DistributedFormat type + trim font-cache resolver
Second simplify-review pass on the webm stack flagged two cleanups: 1. **`DistributedFormat` type duplicated 10 times.** Every file in the distributed pipeline carried its own copy of `"mp4" | "mov" | "png-sequence" | "webm"` — adding a new format meant a 10-place edit with no compile-time guarantee they stayed in sync. Extract a single source of truth in `packages/producer/src/services/distributed/shared.ts`, re-export from `@hyperframes/producer/distributed` and `@hyperframes/aws-lambda/sdk`, and have all callers pull from there. The aws-lambda `ALLOWED_FORMATS` runtime tuple and the CLI's `FORMATS` tuple now both use `satisfies readonly DistributedFormat[]` so the compiler enforces the runtime allowlist stays in sync with the type. 2. **`deterministicFonts.ts` font-cache resolver was over-commented.** Trim the 7-line block to 4 lines (drop the aspirational "and other read-only-FS execution environments" — only Lambda is detected — and the warm-container `/tmp` persistence narration — anyone reading already knows Lambda /tmp semantics). Collapse the two-step `if (explicit && explicit.length > 0)` into a single nullish-coalesce expression now that the empty-string defensive check is gone (`process.env.X` is `string | undefined`, no third shape to guard against). Out-of-scope skips (called out by the agents, deferred): - In-process `RenderConfig.format` and the in-process CLI's `render.ts` format union still carry their own inline copies. The union happens to coincide today but they're separate concerns — leaving them alone limits this PR's blast radius. - `fontCacheDir(slug)` / `resolveFontCacheRoot()` naming asymmetry flagged as taste; skipping. - Pre-existing redundant `existsSync` before `mkdirSync({ recursive: true })` in `fontCacheDir` — out of scope. All tests + typecheck still pass. Lambda render still works end-to-end (no functional changes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6e38c6e commit 656544d

17 files changed

Lines changed: 69 additions & 34 deletions

packages/aws-lambda/src/events.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* results per §2.4).
1717
*/
1818

19-
import type { DistributedRenderConfig } from "@hyperframes/producer/distributed";
19+
import type { DistributedFormat, DistributedRenderConfig } from "@hyperframes/producer/distributed";
2020

2121
/** Discriminator for the three roles the one Lambda image fulfills. */
2222
export type LambdaAction = "plan" | "renderChunk" | "assemble";
@@ -65,7 +65,7 @@ export interface RenderChunkEvent {
6565
/** S3 URI prefix where the chunk output should be uploaded (`s3://bucket/{prefix}/`). */
6666
ChunkOutputS3Prefix: string;
6767
/** Output container format from the plan's encoder.json; drives file vs frame-dir handling. */
68-
Format: "mp4" | "mov" | "png-sequence" | "webm";
68+
Format: DistributedFormat;
6969
}
7070

7171
/** Activity C: fetch planDir + all chunks + audio, assemble, upload final. */
@@ -80,7 +80,7 @@ export interface AssembleEvent {
8080
/** Final output S3 URI (`s3://bucket/key.mp4`). */
8181
OutputS3Uri: string;
8282
/** Output container format; drives file vs frame-dir handling. */
83-
Format: "mp4" | "mov" | "png-sequence" | "webm";
83+
Format: DistributedFormat;
8484
}
8585

8686
/**
@@ -106,7 +106,7 @@ export interface PlanLambdaResult {
106106
Fps: 24 | 30 | 60;
107107
Width: number;
108108
Height: number;
109-
Format: "mp4" | "mov" | "png-sequence" | "webm";
109+
Format: DistributedFormat;
110110
HasAudio: boolean;
111111
AudioS3Uri: string | null;
112112
FfmpegVersion: string;

packages/aws-lambda/src/formatExtension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
* looks like vs a png-sequence.
77
*/
88

9-
export type DistributedFormat = "mp4" | "mov" | "png-sequence" | "webm";
9+
import type { DistributedFormat } from "@hyperframes/producer/distributed";
10+
11+
export type { DistributedFormat } from "@hyperframes/producer/distributed";
1012

1113
// Closed-enum lookup table. TS enforces exhaustiveness via the
1214
// `Record<DistributedFormat, string>` annotation — adding a format to

packages/aws-lambda/src/handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
renderChunk,
2626
} from "@hyperframes/producer/distributed";
2727
import { resolveChromeExecutablePath } from "./chromium.js";
28-
import { formatExtension } from "./formatExtension.js";
28+
import { type DistributedFormat, formatExtension } from "./formatExtension.js";
2929
import type {
3030
AssembleEvent,
3131
AssembleLambdaResult,
@@ -433,7 +433,7 @@ async function downloadChunkObjects(
433433
s3: S3Client,
434434
uris: string[],
435435
workDir: string,
436-
format: "mp4" | "mov" | "png-sequence" | "webm",
436+
format: DistributedFormat,
437437
): Promise<string[]> {
438438
const chunksDir = join(workDir, "chunks");
439439
mkdirSync(chunksDir, { recursive: true });

packages/aws-lambda/src/sdk/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ export {
2424
} from "./costAccounting.js";
2525
export { InvalidConfigError, validateDistributedRenderConfig } from "./validateConfig.js";
2626
export type { SerializableDistributedRenderConfig } from "../events.js";
27+
export type { DistributedFormat } from "../formatExtension.js";

packages/aws-lambda/src/sdk/validateConfig.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* size cap, GPU mode at runtime) needs the actual planner.
1919
*/
2020

21+
import type { DistributedFormat } from "../formatExtension.js";
2122
import type { SerializableDistributedRenderConfig } from "../events.js";
2223

2324
/** Thrown for any client-side `SerializableDistributedRenderConfig` violation. */
@@ -32,7 +33,12 @@ export class InvalidConfigError extends Error {
3233
}
3334

3435
const ALLOWED_FPS = [24, 30, 60] as const;
35-
const ALLOWED_FORMATS = ["mp4", "mov", "png-sequence", "webm"] as const;
36+
const ALLOWED_FORMATS = [
37+
"mp4",
38+
"mov",
39+
"png-sequence",
40+
"webm",
41+
] as const satisfies readonly DistributedFormat[];
3642
const ALLOWED_CODECS = ["h264", "h265"] as const;
3743
const ALLOWED_QUALITIES = ["draft", "standard", "high"] as const;
3844
const ALLOWED_RUNTIME_CAPS = ["lambda", "temporal", "cloud-run-job", "k8s-job", "none"] as const;

packages/cli/src/commands/lambda.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import { defineCommand } from "citty";
12+
import type { DistributedFormat } from "@hyperframes/aws-lambda/sdk";
1213
import type { Example } from "./_examples.js";
1314
import { c } from "../ui/colors.js";
1415

@@ -325,7 +326,12 @@ function parseEnum<T extends string>(
325326
throw new Error(`${errorPrefix} must be ${allowed.join("|")}; got ${s}`);
326327
}
327328

328-
const FORMATS = ["mp4", "mov", "png-sequence", "webm"] as const;
329+
const FORMATS = [
330+
"mp4",
331+
"mov",
332+
"png-sequence",
333+
"webm",
334+
] as const satisfies readonly DistributedFormat[];
329335
const CODECS = ["h264", "h265"] as const;
330336
const QUALITIES = ["draft", "standard", "high"] as const;
331337
const CHROME_SOURCES = ["sparticuz", "chrome-headless-shell"] as const;

packages/cli/src/commands/lambda/render.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
*/
66

77
import { resolve as resolvePath } from "node:path";
8-
import type { SerializableDistributedRenderConfig } from "@hyperframes/aws-lambda/sdk";
8+
import type {
9+
DistributedFormat,
10+
SerializableDistributedRenderConfig,
11+
} from "@hyperframes/aws-lambda/sdk";
912
import { c } from "../../ui/colors.js";
1013
import { requireStack, stateFilePath } from "./state.js";
1114

@@ -23,7 +26,7 @@ export interface RenderArgs {
2326
fps: 24 | 30 | 60;
2427
width: number;
2528
height: number;
26-
format: "mp4" | "mov" | "png-sequence" | "webm";
29+
format: DistributedFormat;
2730
codec?: "h264" | "h265";
2831
quality?: "draft" | "standard" | "high";
2932
chunkSize?: number;

packages/producer/src/distributed.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export {
7070
// ── Assemble (Activity C) ───────────────────────────────────────────────────
7171
export { assemble, type AssembleResult } from "./services/distributed/assemble.js";
7272

73+
// ── Format union ────────────────────────────────────────────────────────────
74+
// Canonical output-format type. The aws-lambda package re-exports it so
75+
// CLI / adopter SDKs can derive runtime allowlists from one source.
76+
export type { DistributedFormat } from "./services/distributed/shared.js";
77+
7378
// ── Plan-time shared types from `freezePlan` ───────────────────────────────
7479
// Re-exported so adopters that deserialize a planDir's `meta/encoder.json`
7580
// or `meta/chunks.json` see the same shapes the producer wrote them as.

packages/producer/src/regression-harness-distributed.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { existsSync, mkdirSync } from "node:fs";
3535
import { join } from "node:path";
3636
import type { Fps } from "@hyperframes/core";
3737
import { assemble, plan, renderChunk } from "./distributed.js";
38+
import type { DistributedFormat } from "./services/distributed/shared.js";
3839

3940
/**
4041
* Three-mode contract that backs `--mode=<value>` on the regression
@@ -81,7 +82,7 @@ export type DistributedSupportResult = { supported: true } | { supported: false;
8182
*/
8283
export function checkDistributedSupport(renderConfig: {
8384
fps: Fps;
84-
format?: "mp4" | "webm" | "mov" | "png-sequence";
85+
format?: DistributedFormat;
8586
hdr?: boolean;
8687
}): DistributedSupportResult {
8788
if (renderConfig.fps.den !== 1) {
@@ -120,7 +121,7 @@ export interface RunDistributedSimulatedInput {
120121
renderedOutputPath: string;
121122
/** From the fixture's renderConfig — must pass `checkDistributedSupport`. */
122123
fps: 24 | 30 | 60;
123-
format: "mp4" | "mov" | "png-sequence" | "webm";
124+
format: DistributedFormat;
124125
/**
125126
* Codec for `format: "mp4"`. Defaults to `"h264"`; pass `"h265"` to
126127
* exercise the libx265 closed-GOP path. Ignored for non-mp4 formats —

packages/producer/src/regression-harness-lambda-local-types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* type-check pass.
1010
*/
1111

12+
import type { DistributedFormat } from "./services/distributed/shared.js";
13+
1214
/** Inputs for {@link runLambdaLocalRender}. Same contract as `runDistributedSimulatedRender`. */
1315
export interface RunLambdaLocalInput {
1416
projectDir: string;
@@ -26,7 +28,7 @@ export interface RunLambdaLocalInput {
2628
*/
2729
width: number;
2830
height: number;
29-
format: "mp4" | "mov" | "png-sequence" | "webm";
31+
format: DistributedFormat;
3032
codec?: "h264" | "h265";
3133
chunkSize?: number;
3234
maxParallelChunks?: number;

0 commit comments

Comments
 (0)