Skip to content

Commit 7f8a332

Browse files
jrusso1020claude
andcommitted
fix(aws-lambda): widen narrow format types to include webm
CI on PR #951 was failing at typecheck/build because the producer's `DistributedRenderConfig.format` widened to include webm in this PR but the aws-lambda package's narrow `"mp4" | "mov" | "png-sequence"` type literals in `events.ts`, `handler.ts`, and `validateConfig.ts` hadn't kept up. `renderToLambda.ts:87` passed `config.format` (now including webm) into a parameter typed against the narrow union, producing TS2345. This widening originally landed in PR #952 (test fixture PR) but needs to be atomic with the producer's widening here to keep each PR independently typecheck-clean. Also refactor `formatExtension` from a switch dispatch to a `Record<DistributedFormat, string>` lookup. Adding the webm case tipped the switch's CRAP to the 30.0 fallow threshold; the lookup table drops cyclomatic from 5 to 1 with the same compile-time exhaustiveness guarantee (TS errors on missing entries when `DistributedFormat` adds a new format). The runtime `_exhaustive: never` throw was only protecting against a string slipping past TS; `validateConfig.ts`'s `ALLOWED_FORMATS` already gates untrusted input at the SDK boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a4ed148 commit 7f8a332

5 files changed

Lines changed: 20 additions & 19 deletions

File tree

packages/aws-lambda/src/events.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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";
68+
Format: "mp4" | "mov" | "png-sequence" | "webm";
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";
83+
Format: "mp4" | "mov" | "png-sequence" | "webm";
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";
109+
Format: "mp4" | "mov" | "png-sequence" | "webm";
110110
HasAudio: boolean;
111111
AudioS3Uri: string | null;
112112
FfmpegVersion: string;

packages/aws-lambda/src/formatExtension.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66
* looks like vs a png-sequence.
77
*/
88

9-
export type DistributedFormat = "mp4" | "mov" | "png-sequence";
9+
export type DistributedFormat = "mp4" | "mov" | "png-sequence" | "webm";
10+
11+
// Closed-enum lookup table. TS enforces exhaustiveness via the
12+
// `Record<DistributedFormat, string>` annotation — adding a format to
13+
// `DistributedFormat` without adding the matching key here fails to
14+
// typecheck, which is the same exhaustiveness guarantee a switch +
15+
// `_exhaustive: never` arm provides but at lower complexity.
16+
const FORMAT_EXTENSIONS: Record<DistributedFormat, string> = {
17+
mp4: ".mp4",
18+
mov: ".mov",
19+
webm: ".webm",
20+
"png-sequence": "",
21+
};
1022

1123
export function formatExtension(format: DistributedFormat): string {
12-
switch (format) {
13-
case "mp4":
14-
return ".mp4";
15-
case "mov":
16-
return ".mov";
17-
case "png-sequence":
18-
return "";
19-
default: {
20-
const _exhaustive: never = format;
21-
throw new Error(`[formatExtension] unsupported format: ${_exhaustive as string}`);
22-
}
23-
}
24+
return FORMAT_EXTENSIONS[format];
2425
}

packages/aws-lambda/src/handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ async function downloadChunkObjects(
433433
s3: S3Client,
434434
uris: string[],
435435
workDir: string,
436-
format: "mp4" | "mov" | "png-sequence",
436+
format: "mp4" | "mov" | "png-sequence" | "webm",
437437
): Promise<string[]> {
438438
const chunksDir = join(workDir, "chunks");
439439
mkdirSync(chunksDir, { recursive: true });

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe("validateDistributedRenderConfig", () => {
5454
"unsupported format",
5555
{
5656
...VALID,
57-
format: "webm",
57+
format: "gif",
5858
} as unknown as SerializableDistributedRenderConfig,
5959
"config.format",
6060
],

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class InvalidConfigError extends Error {
3131
}
3232

3333
const ALLOWED_FPS = [24, 30, 60] as const;
34-
const ALLOWED_FORMATS = ["mp4", "mov", "png-sequence"] as const;
34+
const ALLOWED_FORMATS = ["mp4", "mov", "png-sequence", "webm"] as const;
3535
const ALLOWED_CODECS = ["h264", "h265"] as const;
3636
const ALLOWED_QUALITIES = ["draft", "standard", "high"] as const;
3737
const ALLOWED_RUNTIME_CAPS = ["lambda", "temporal", "cloud-run-job", "k8s-job", "none"] as const;

0 commit comments

Comments
 (0)