Merge remote-tracking branch 'origin/main' into fix/ci-chrome-pin-and-psnr-harness

This commit is contained in:
James
2026-05-18 00:18:55 +00:00
14 changed files with 182 additions and 49 deletions
+1
View File
@@ -130,6 +130,7 @@ jobs:
publish_pkg "@hyperframes/producer" "@hyperframes/producer"
publish_pkg "@hyperframes/shader-transitions" "@hyperframes/shader-transitions"
publish_pkg "@hyperframes/studio" "@hyperframes/studio"
publish_pkg "@hyperframes/aws-lambda" "@hyperframes/aws-lambda"
# CLI is @hyperframes/cli in the monorepo but published as unscoped "hyperframes" on npm.
# Rewrite the name in package.json before publishing, then use npm publish directly
+1 -1
View File
@@ -11,7 +11,7 @@
"type": "module",
"scripts": {
"dev": "bun run studio",
"build": "bun run --filter @hyperframes/core build && bun run --filter '@hyperframes/{core,engine,producer,player,studio,shader-transitions}' build && bun run --filter @hyperframes/cli build",
"build": "bun run --filter @hyperframes/core build && bun run --filter '@hyperframes/{core,engine,producer,player,studio,shader-transitions,aws-lambda}' build && bun run --filter @hyperframes/cli build",
"build:producer": "bun run --filter @hyperframes/producer build",
"studio": "bun run --filter @hyperframes/studio dev",
"build:hyperframes-runtime": "bun run --filter @hyperframes/core build:hyperframes-runtime",
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env node
/**
* Build script for @hyperframes/aws-lambda (public OSS package).
*
* Bundles each subpath barrel via esbuild → dist/, then emits .d.ts via tsc.
*
* Subpaths (each gets its own dist entry so adopters that import one path
* don't load the others' transitive graphs at module-load time):
*
* . (the umbrella barrel: handler + sdk + cdk types re-exported)
* ./handler (the Lambda runtime entry — what `scripts/build-zip.ts` ZIPs)
* ./sdk (client-side helpers — AWS-SDK only, no chromium/puppeteer)
* ./cdk (CDK L2 construct — aws-cdk-lib is a peer dep)
*
* All production deps and peer deps are kept external so consumers resolve
* them via their own node_modules.
*/
import { build } from "esbuild";
import { execSync } from "node:child_process";
import { mkdirSync, rmSync } from "node:fs";
rmSync("dist", { recursive: true, force: true });
mkdirSync("dist", { recursive: true });
const sharedOpts = {
bundle: true,
platform: "node",
target: "node22",
format: "esm",
minify: false,
sourcemap: true,
external: [
"@aws-sdk/client-s3",
"@aws-sdk/client-sfn",
"@hyperframes/producer",
"@hyperframes/producer/distributed",
"@sparticuz/chromium",
"aws-cdk-lib",
"constructs",
"ffmpeg-static",
"ffprobe-static",
"puppeteer-core",
"tar",
],
};
await Promise.all([
build({ ...sharedOpts, entryPoints: ["src/index.ts"], outfile: "dist/index.js" }),
build({ ...sharedOpts, entryPoints: ["src/handler.ts"], outfile: "dist/handler.js" }),
build({ ...sharedOpts, entryPoints: ["src/sdk/index.ts"], outfile: "dist/sdk/index.js" }),
build({ ...sharedOpts, entryPoints: ["src/cdk/index.ts"], outfile: "dist/cdk/index.js" }),
]);
// esbuild doesn't emit .d.ts. tsc does, with a build-only tsconfig that
// drops the workspace `paths` overrides so `@hyperframes/producer` resolves
// through node_modules to the sibling package's already-built `dist/`
// types instead of pulling its full source tree into emit (which would
// violate rootDir).
execSync("tsc -p tsconfig.build.json --emitDeclarationOnly", { stdio: "inherit" });
console.log("[Build] Complete: dist/{index,handler,sdk/index,cdk/index}.js + .d.ts");
+21 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@hyperframes/aws-lambda",
"version": "0.0.1",
"version": "0.6.20",
"description": "AWS Lambda adapter for HyperFrames distributed rendering — handler, client-side SDK, and CDK construct.",
"repository": {
"type": "git",
@@ -8,25 +8,37 @@
"directory": "packages/aws-lambda"
},
"files": [
"src/",
"dist/",
"scripts/",
"README.md"
],
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./src/index.ts",
"./handler": "./src/handler.ts",
"./sdk": "./src/sdk/index.ts",
"./cdk": "./src/cdk/index.ts"
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./handler": {
"import": "./dist/handler.js",
"types": "./dist/handler.d.ts"
},
"./sdk": {
"import": "./dist/sdk/index.js",
"types": "./dist/sdk/index.d.ts"
},
"./cdk": {
"import": "./dist/cdk/index.js",
"types": "./dist/cdk/index.d.ts"
}
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "tsc --noEmit",
"build": "node build.mjs",
"build:zip": "tsx scripts/build-zip.ts",
"probe:beginframe": "tsx scripts/probe-beginframe.ts",
"probe:beginframe:docker": "docker build -f scripts/probe-beginframe.dockerfile -t hyperframes-lambda-probe:local ../.. && docker run --rm hyperframes-lambda-probe:local",
+12
View File
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"paths": {},
"noEmit": false,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
+1 -1
View File
@@ -15,5 +15,5 @@
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "src/**/*.test.ts", "scripts"]
"exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/**/__fixtures__/**", "scripts"]
}
@@ -0,0 +1,37 @@
/**
* Public-facing types for `./regression-harness-lambda-local.ts`.
*
* Kept in its own file because the implementation imports
* `@hyperframes/aws-lambda`, which can't be resolved by producer's
* tsc emit pass until aws-lambda's own dist/ is built. Splitting the
* types out lets producer's regression harness reference the lambda
* adapter's shape without pulling the aws-lambda graph into producer's
* type-check pass.
*/
/** Inputs for {@link runLambdaLocalRender}. Same contract as `runDistributedSimulatedRender`. */
export interface RunLambdaLocalInput {
projectDir: string;
tempRoot: string;
renderedOutputPath: string;
fps: 24 | 30 | 60;
/**
* Width/height from the fixture's renderConfig. Forwarded directly to
* the Lambda event so this mode catches drift if the handler ever
* starts honouring `Config.width/height` for canvas sizing rather
* than reading the composition's `data-width`/`data-height`. The
* `distributed-simulated` mode hardcodes 1920×1080 because it
* bypasses the event-serialization boundary; lambda-local goes
* through it, which is the whole point.
*/
width: number;
height: number;
format: "mp4" | "mov" | "png-sequence";
codec?: "h264" | "h265";
chunkSize?: number;
maxParallelChunks?: number;
variables?: Record<string, unknown>;
}
/** Public signature of the dynamically-loaded `runLambdaLocalRender`. */
export type RunLambdaLocalRender = (input: RunLambdaLocalInput) => Promise<void>;
@@ -46,29 +46,8 @@ import type {
SerializableDistributedRenderConfig,
} from "@hyperframes/aws-lambda";
/** Inputs for {@link runLambdaLocalRender}. Same contract as `runDistributedSimulatedRender`. */
export interface RunLambdaLocalInput {
projectDir: string;
tempRoot: string;
renderedOutputPath: string;
fps: 24 | 30 | 60;
/**
* Width/height from the fixture's renderConfig. Forwarded directly to
* the Lambda event so this mode catches drift if the handler ever
* starts honouring `Config.width/height` for canvas sizing rather
* than reading the composition's `data-width`/`data-height`. The
* `distributed-simulated` mode hardcodes 1920×1080 because it
* bypasses the event-serialization boundary; lambda-local goes
* through it, which is the whole point.
*/
width: number;
height: number;
format: "mp4" | "mov" | "png-sequence";
codec?: "h264" | "h265";
chunkSize?: number;
maxParallelChunks?: number;
variables?: Record<string, unknown>;
}
export type { RunLambdaLocalInput } from "./regression-harness-lambda-local-types.js";
import type { RunLambdaLocalInput } from "./regression-harness-lambda-local-types.js";
const FAKE_BUCKET = "harness-lambda-local";
+21 -4
View File
@@ -37,10 +37,27 @@ import {
// In Dockerfile.test the workspace copy of aws-lambda's src isn't present,
// so a static import here would fail at module-load time even when
// running `--mode=in-process`. Load it on demand instead.
async function loadLambdaLocalRender(): Promise<
typeof import("./regression-harness-lambda-local.js").runLambdaLocalRender
> {
const mod = await import("./regression-harness-lambda-local.js");
//
// The signature is typed via `RunLambdaLocalRender` (in its own types-only
// file) instead of `typeof import(...)` so producer's tsc doesn't have to
// type-check the implementation. The implementation imports
// `@hyperframes/aws-lambda`, whose types come from `dist/index.d.ts` after
// aws-lambda's build runs — a chicken-and-egg with producer's tsc that
// would otherwise fail the whole-repo build.
//
// The dynamic import path is indirected through a variable so tsc can't
// statically resolve the target file. Without this indirection tsc still
// pulls `regression-harness-lambda-local.ts` (and its `@hyperframes/aws-lambda`
// imports) into the program even though the tsconfig `exclude` list
// nominally hides it. `tsx` resolves the path normally at runtime.
import type { RunLambdaLocalRender } from "./regression-harness-lambda-local-types.js";
const LAMBDA_LOCAL_MODULE = "./regression-harness-lambda-local.js";
async function loadLambdaLocalRender(): Promise<RunLambdaLocalRender> {
const mod = (await import(LAMBDA_LOCAL_MODULE)) as {
runLambdaLocalRender: RunLambdaLocalRender;
};
return mod.runLambdaLocalRender;
}
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6aba60a5a3919132986e785b89f4b3434d23d337d95958a515b1fe2e11906721
size 5154704
oid sha256:821a6b69e412a09560e9412ce0faaa0b1fe78163a2c520173408d6ac19129d3c
size 8383424
@@ -492,7 +492,7 @@
var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
};
var __hfRootSelector = null || (__hfCompId
var __hfRootSelector = "[data-composition-id=\"mondrian-bg\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: "");
var __hfRoot = null;
@@ -754,7 +754,8 @@
var __hfRun = function() {
try {
(function(document, gsap, window, __hyperframes) {
(function () {
(function () {
const tl = gsap.timeline({ paused: true });
tl.to(".bar-1", { left: "100%", duration: 0.45, ease: "expo.out" }, 1.1);
@@ -764,6 +765,7 @@
window.__timelines["mondrian-bg"] = tl;
})();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err);
@@ -782,7 +784,7 @@
var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
};
var __hfRootSelector = null || (__hfCompId
var __hfRootSelector = "[data-composition-id=\"mondrian-colors\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: "");
var __hfRoot = null;
@@ -1044,7 +1046,8 @@
var __hfRun = function() {
try {
(function(document, gsap, window, __hyperframes) {
(function () {
(function () {
const TRANSCRIPT = [
{ text: "We", start: 0.14, end: 0.239 },
{ text: "asked", start: 0.28, end: 0.459 },
@@ -1181,6 +1184,7 @@
window.__timelines["mondrian-colors"] = tl;
})();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err);
@@ -1199,7 +1203,7 @@
var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
};
var __hfRootSelector = null || (__hfCompId
var __hfRootSelector = "[data-composition-id=\"mondrian-captions\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: "");
var __hfRoot = null;
@@ -1461,7 +1465,8 @@
var __hfRun = function() {
try {
(function(document, gsap, window, __hyperframes) {
(function () {
(function () {
const TRANSCRIPT = [
{ text: "We", start: 0.14, end: 0.239 },
{ text: "asked", start: 0.28, end: 0.459 },
@@ -1551,6 +1556,7 @@
window.__timelines["mondrian-captions"] = tl;
})();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err);
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:04de22fa8fe2bd25a40ffb6577fcf6da7d0317a44ed753c291f238f1ae048ccc
size 8714819
oid sha256:2a46a4d49cc13ca5650ec44addb3dc276f23906e98e3f581ac59594eddedfc8e
size 11090919
+7 -1
View File
@@ -20,5 +20,11 @@
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/**/__test_utils__/**"]
"exclude": [
"node_modules",
"dist",
"src/**/*.test.ts",
"src/**/__test_utils__/**",
"src/regression-harness-lambda-local.ts"
]
}
+1
View File
@@ -25,6 +25,7 @@ const PACKAGES = [
"packages/shader-transitions",
"packages/studio",
"packages/cli",
"packages/aws-lambda",
];
const ROOT = join(import.meta.dirname, "..");