Files
hyperframes/packages/cli/tsup.config.ts
T
Vance Ingalls 92bccfdf78 feat(producer): add pngDecodeBlitWorkerPool (hf#732 PR 2/5) (#757)
## Summary

PR 2 of 5 in the hf#732 decomposition stack. Adds a `worker_threads`-based pool that offloads PNG decode + alpha-blit onto a fixed-size pool. **No production wiring yet** — the pool stands alone and ships behind a later PR in the stack.

### New files

- `packages/producer/src/services/pngDecodeBlitWorker.ts` — worker entry. Imports from `@hyperframes/engine/alpha-blit` (zero-import TS source, survives the `new Worker(<path>)` loader boundary).
- `packages/producer/src/services/pngDecodeBlitWorkerPool.ts` — fixed-size pool with `run()` API. Uses `transferList` for buffer ownership transfer (no 16bpc HDR buffer copies).
- `packages/producer/src/services/pngDecodeBlitWorkerPool.test.ts` — 6 vitest tests pinning byte-equivalence with inline path, transferList correctness, concurrent dispatch, termination semantics. All pass.

### Build wiring

- `packages/cli/tsup.config.ts`: second tsup entry emits `dist/pngDecodeBlitWorker.js` next to `dist/cli.js`. Without this entry the pool's `new Worker(<path>)` would fail at runtime in the shipped CLI.
- `packages/producer/build.mjs`: third esbuild entry mirrors the wiring for direct producer consumers.
- `packages/engine/package.json`: adds `./alpha-blit` subpath export pointing at `src/utils/alphaBlit.ts`.

## Stack

Stacked on top of #756 (PR 1: worker-count cap). No behavior change in any render.

## Test plan

- [x] 6 pool tests pass
- [x] Producer + engine typecheck clean
- [x] oxlint clean

— Vai
2026-05-13 14:52:38 -07:00

79 lines
2.5 KiB
TypeScript

import { defineConfig } from "tsup";
import { resolve } from "node:path";
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf-8")) as {
version: string;
};
export default defineConfig({
// hf#732 lever-4: emit BOTH the CLI bundle and the PNG decode + alpha-blit
// worker entry. The producer's `pngDecodeBlitWorkerPool` instantiates a
// Node `worker_threads` Worker via `new Worker(<path>)`, which is a
// filesystem load — it cannot share the parent module graph. The pool's
// path resolver probes for `pngDecodeBlitWorker.js` next to its own loaded
// module (which lives inside `dist/cli.js` after the producer is
// `noExternal`'d and bundled in). Without this entry the file would not
// exist at runtime and the pool would either crash or silently fall back
// to inline decode/blit, killing the perf gain.
entry: {
cli: "src/cli.ts",
pngDecodeBlitWorker: "../producer/src/services/pngDecodeBlitWorker.ts",
},
format: ["esm"],
outDir: "dist",
target: "node22",
platform: "node",
bundle: true,
splitting: false,
sourcemap: false,
clean: true,
banner: {
js: `import { createRequire as __hf_createRequire } from "node:module";
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
import { dirname as __hf_dirname } from "node:path";
var require = __hf_createRequire(import.meta.url);
var __filename = __hf_fileURLToPath(import.meta.url);
var __dirname = __hf_dirname(__filename);`,
},
external: [
"puppeteer-core",
"puppeteer",
"@puppeteer/browsers",
"open",
"hono",
"hono/*",
"@hono/node-server",
"mime-types",
"adm-zip",
"esbuild",
"giget",
"postcss",
],
noExternal: [
"@hyperframes/core",
"@hyperframes/producer",
"@hyperframes/engine",
"@clack/prompts",
"@clack/core",
"picocolors",
"linkedom",
"sisteransi",
"is-unicode-supported",
"citty",
],
define: {
__CLI_VERSION__: JSON.stringify(pkg.version),
},
esbuildOptions(options) {
options.alias = {
"@hyperframes/producer": resolve(__dirname, "../producer/src/index.ts"),
// hf#732 lever-4: alias for the PNG decode+blit worker's import.
// `alphaBlit.ts` is import-free (only zlib) so the worker survives
// the worker_thread loader boundary directly via this TS source.
"@hyperframes/engine/alpha-blit": resolve(__dirname, "../engine/src/utils/alphaBlit.ts"),
};
options.loader = { ...options.loader, ".browser.js": "text" };
},
});