68 lines
3.0 KiB
TypeScript
Executable File
68 lines
3.0 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
|
|
// Embeds mupdf's `mupdf-wasm.wasm` into the compiled single-file binary.
|
|
//
|
|
// mupdf loads its wasm by reading the `mupdf-wasm.wasm` sibling of its own
|
|
// module via `new URL(..., import.meta.url)` + `readFileSync`. A `bun --compile`
|
|
// binary has no node_modules, so that read fails (`ENOENT .../mupdf-wasm.wasm`),
|
|
// and marking mupdf `--external` instead makes `bun --compile` eagerly fail to
|
|
// resolve the package at startup (the static `import * as mupdf` lives in a lazy
|
|
// chunk but is hoisted). So the binary build bundles mupdf and embeds the wasm
|
|
// bytes here, handing them to the WASM module as `$libmupdf_wasm_Module.wasmBinary`
|
|
// (see src/utils/markit.ts).
|
|
//
|
|
// `--generate` copies the wasm next to src/utils/mupdf-wasm-embed.ts and rewrites
|
|
// that module to import it via `with { type: "file" }`; `--reset` restores the
|
|
// checked-in placeholder and removes the copy. The npm `dist/cli.js` bundle never
|
|
// runs this — it keeps mupdf external and loads the wasm from node_modules.
|
|
|
|
import * as fs from "node:fs/promises";
|
|
import { createRequire } from "node:module";
|
|
import * as path from "node:path";
|
|
|
|
const utilsDir = path.join(import.meta.dir, "..", "src", "utils");
|
|
const helperPath = path.join(utilsDir, "mupdf-wasm-embed.ts");
|
|
const wasmCopyPath = path.join(utilsDir, "mupdf-wasm.wasm");
|
|
|
|
const placeholder = `// AUTOGENERATED -- managed by scripts/embed-mupdf-wasm.ts. Do not edit by hand.
|
|
//
|
|
// Compiled single-file binaries cannot let mupdf resolve its \`mupdf-wasm.wasm\`
|
|
// sibling from the read-only bunfs, so the binary build (scripts/build-binary.ts
|
|
// and scripts/ci-release-build-binaries.ts) regenerates this module to embed the
|
|
// wasm bytes via \`with { type: "file" }\` and copies the wasm next to it. Source
|
|
// checkouts, \`bun test\`, and the npm \`dist/cli.js\` bundle keep mupdf external and
|
|
// load the wasm from node_modules, so this placeholder returns undefined and the
|
|
// build resets back to it afterward.
|
|
export function loadEmbeddedMupdfWasm(): Uint8Array | undefined {
|
|
\treturn undefined;
|
|
}
|
|
`;
|
|
|
|
const generated = `// AUTOGENERATED -- managed by scripts/embed-mupdf-wasm.ts. Do not edit or commit.
|
|
import { readFileSync } from "node:fs";
|
|
import wasmPath from "./mupdf-wasm.wasm" with { type: "file" };
|
|
|
|
export function loadEmbeddedMupdfWasm(): Uint8Array | undefined {
|
|
\treturn readFileSync(wasmPath);
|
|
}
|
|
`;
|
|
|
|
if (process.argv.includes("--reset")) {
|
|
await Bun.write(helperPath, placeholder);
|
|
try {
|
|
await fs.unlink(wasmCopyPath);
|
|
} catch (err) {
|
|
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
const wasmSource = path.join(path.dirname(createRequire(import.meta.url).resolve("mupdf")), "mupdf-wasm.wasm");
|
|
const wasmFile = Bun.file(wasmSource);
|
|
if (!(await wasmFile.exists())) {
|
|
throw new Error(`mupdf wasm not found at ${wasmSource}; run \`bun install\` first.`);
|
|
}
|
|
await Bun.write(wasmCopyPath, wasmFile);
|
|
await Bun.write(helperPath, generated);
|
|
console.log(`Embedded mupdf wasm (${wasmFile.size} bytes) into ${path.relative(process.cwd(), wasmCopyPath)}`);
|