History

Package workerd for local binaries

Rhys Sullivan committed 4 months ago

Commit 4be58bc1 parent da4f37c8 files · +491 −56Browse files

Showing the changes to apps/cli/src (2 of 8 files). Show all

Unified · Split

2 files
  1. apps/cli/src/build.ts +92 −1
  2. apps/cli/src/native-bindings.ts +19 −5
apps/cli/src/build.ts+92−1
@@ -2,7 +2,7 @@ import { cp, mkdir, rm, writeFile, chmod } from "node:fs/promises"; · 1 unmodified line
2import { existsSync } from "node:fs";2import { existsSync } from "node:fs";
3import { createRequire } from "node:module";3import { createRequire } from "node:module";
4import { resolve, join, dirname } from "node:path";4import { resolve, join, dirname } from "node:path";
5import { fileURLToPath } from "node:url";5import { fileURLToPath, pathToFileURL } from "node:url";
6import { parseArgs } from "node:util";6import { parseArgs } from "node:util";
7import { $ } from "bun";7import { $ } from "bun";
8 8
@@ -11,6 +11,8 @@ const cliRoot = resolve(repoRoot, "apps/cli"); · 2 unmodified lines
11const webRoot = resolve(repoRoot, "apps/local");11const webRoot = resolve(repoRoot, "apps/local");
12const distDir = resolve(cliRoot, "dist");12const distDir = resolve(cliRoot, "dist");
13const ONEPASSWORD_CORE_WASM_FILENAME = "onepassword-core_bg.wasm";13const ONEPASSWORD_CORE_WASM_FILENAME = "onepassword-core_bg.wasm";
14const WORKERD_VERSION = "1.20260708.1";
15const WORKER_BUNDLER_DIRNAME = "worker-bundler";
14 16
15const resolveQuickJsWasmPath = (): string => {17const resolveQuickJsWasmPath = (): string => {
16 const req = createRequire(join(repoRoot, "packages/kernel/runtime-quickjs/package.json"));18 const req = createRequire(join(repoRoot, "packages/kernel/runtime-quickjs/package.json"));
@@ -33,6 +35,34 @@ const resolveOnePasswordCoreWasmPath = (): string => { · 16 unmodified lines
33 return wasmPath;35 return wasmPath;
34};36};
35 37
38const resolveWorkerBundlerDistPath = (): string => {
39 const req = createRequire(join(repoRoot, "packages/plugins/apps/package.json"));
40 const pkgJson = req.resolve("@cloudflare/worker-bundler/package.json");
41 const distPath = join(dirname(pkgJson), "dist");
42 if (!existsSync(join(distPath, "index.js")) || !existsSync(join(distPath, "esbuild.wasm"))) {
43 throw new Error(`@cloudflare/worker-bundler dist files not found at ${distPath}`);
44 }
45 return distPath;
46};
47
48const createPackedWorkerBundlerSource = async (distPath: string): Promise<string> => {
49 const esbuildPath = join(repoRoot, "node_modules/.bun/node_modules/esbuild/lib/main.js");
50 if (!existsSync(esbuildPath)) throw new Error(`esbuild not found at ${esbuildPath}`);
51 const { build } = await import(pathToFileURL(esbuildPath).href);
52 const result = await build({
53 entryPoints: [join(distPath, "index.js")],
54 bundle: true,
55 format: "esm",
56 platform: "browser",
57 external: ["./esbuild.wasm"],
58 logLevel: "silent",
59 write: false,
60 });
61 const source = result.outputFiles[0]?.text;
62 if (source === undefined) throw new Error("failed to bundle @cloudflare/worker-bundler");
63 return source;
64};
65
36// ---------------------------------------------------------------------------66// ---------------------------------------------------------------------------
37// Metadata67// Metadata
38// ---------------------------------------------------------------------------68// ---------------------------------------------------------------------------
@@ -119,6 +149,7 @@ const bunTarget = (t: Target): Bun.Build.CompileTarget => { · 80 unmodified lines
119};149};
120 150
121const binaryName = (t: Target) => (t.os === "win32" ? "executor.exe" : "executor");151const binaryName = (t: Target) => (t.os === "win32" ? "executor.exe" : "executor");
152const workerdBinaryName = (t: Target) => (t.os === "win32" ? "workerd.exe" : "workerd");
122 153
123const isCurrentPlatform = (t: Target) =>154const isCurrentPlatform = (t: Target) =>
124 t.os === process.platform && t.arch === process.arch && !t.abi;155 t.os === process.platform && t.arch === process.arch && !t.abi;
@@ -211,6 +242,41 @@ const resolveLibsqlNative = (t: Target): string | null => { · 86 unmodified lines
211 }242 }
212};243};
213 244
245const resolveWorkerdBinary = (t: Target): string | null => {
246 const platformMap: Record<string, string> = {
247 "darwin-arm64": "@cloudflare/workerd-darwin-arm64",
248 "darwin-x64": "@cloudflare/workerd-darwin-64",
249 "linux-arm64": "@cloudflare/workerd-linux-arm64",
250 "linux-x64": "@cloudflare/workerd-linux-64",
251 "win32-x64": "@cloudflare/workerd-windows-64",
252 };
253 const key = [t.os, t.arch, t.abi].filter(Boolean).join("-");
254 const pkg = platformMap[key];
255 if (!pkg) return null;
256 const binary = workerdBinaryName(t);
257 try {
258 const req = createRequire(
259 join(repoRoot, "packages/kernel/runtime-workerd-subprocess/package.json"),
260 );
261 const pkgJson = req.resolve(`${pkg}/package.json`);
262 for (const candidate of [
263 join(dirname(pkgJson), "bin", binary),
264 join(dirname(pkgJson), binary),
265 ]) {
266 if (existsSync(candidate)) return candidate;
267 }
268 } catch {
269 const packageRoot = join(
270 repoRoot,
271 `node_modules/.bun/${pkg.replace("/", "+")}@${WORKERD_VERSION}/node_modules/${pkg}`,
272 );
273 for (const candidate of [join(packageRoot, "bin", binary), join(packageRoot, binary)]) {
274 if (existsSync(candidate)) return candidate;
275 }
276 }
277 return null;
278};
279
214// ---------------------------------------------------------------------------280// ---------------------------------------------------------------------------
215// Build mode281// Build mode
216// ---------------------------------------------------------------------------282// ---------------------------------------------------------------------------
@@ -333,6 +399,8 @@ const buildBinaries = async (targets: Target[], mode: BuildMode) => { · 116 unmodified lines
333 399
334 const quickJsWasmPath = resolveQuickJsWasmPath();400 const quickJsWasmPath = resolveQuickJsWasmPath();
335 const onePasswordCoreWasmPath = resolveOnePasswordCoreWasmPath();401 const onePasswordCoreWasmPath = resolveOnePasswordCoreWasmPath();
402 const workerBundlerDistPath = resolveWorkerBundlerDistPath();
403 const packedWorkerBundlerSource = await createPackedWorkerBundlerSource(workerBundlerDistPath);
336 404
337 try {405 try {
338 for (const target of targets) {406 for (const target of targets) {
@@ -375,12 +443,35 @@ const buildBinaries = async (targets: Target[], mode: BuildMode) => { · 36 unmodified lines
375 await cp(libsqlNative, join(binDir, "libsql.node"));443 await cp(libsqlNative, join(binDir, "libsql.node"));
376 }444 }
377 445
446 const workerdBinary = resolveWorkerdBinary(target);
447 if (workerdBinary && existsSync(workerdBinary)) {
448 await cp(workerdBinary, join(binDir, workerdBinaryName(target)));
449 if (target.os !== "win32") await chmod(join(binDir, workerdBinaryName(target)), 0o755);
450 }
451
452 await cp(workerBundlerDistPath, join(binDir, WORKER_BUNDLER_DIRNAME, "dist"), {
453 recursive: true,
454 });
455 await writeFile(
456 join(binDir, WORKER_BUNDLER_DIRNAME, "dist", "index.bundled.js"),
457 packedWorkerBundlerSource,
458 );
459
378 // Smoke test on current platform460 // Smoke test on current platform
379 if (isCurrentPlatform(target)) {461 if (isCurrentPlatform(target)) {
380 const bin = join(binDir, binaryName(target));462 const bin = join(binDir, binaryName(target));
381 console.log(` Smoke test: ${bin} --version`);463 console.log(` Smoke test: ${bin} --version`);
382 const version = await $`${bin} --version`.text();464 const version = await $`${bin} --version`.text();
383 console.log(` OK: ${version.trim()}`);465 console.log(` OK: ${version.trim()}`);
466 console.log(` Smoke test: packed apps source sync and invoke`);
467 const smoke = Bun.spawn(
468 ["bun", "run", join(cliRoot, "scripts/smoke-packed-apps.ts"), bin],
469 {
470 cwd: repoRoot,
471 stdio: ["ignore", "inherit", "inherit"],
472 },
473 );
474 if ((await smoke.exited) !== 0) throw new Error("packed apps smoke failed");
384 }475 }
385 476
386 // Variant package.json. All variants publish to the SAME npm package477 // Variant package.json. All variants publish to the SAME npm package
apps/cli/src/native-bindings.ts+19−5
@@ -1,11 +1,10 @@
1// ---------------------------------------------------------------------------1// ---------------------------------------------------------------------------
2// Native-binding bootstrap for the `bun build --compile` binary.2// Native-binding bootstrap for the `bun build --compile` binary.
3//3//
4// `bun --compile` bundles JS into bunfs but does NOT include `.node` native4// `bun --compile` bundles JS into bunfs but does NOT include native binaries,
5// addons, so a dynamic `require('@libsql/<platform>')` / keyring walk inside5// wasm sidecars, or runtime-read package files. build.ts copies those artifacts
6// the binary fails. build.ts copies each platform's `.node` next to the6// next to the executable; here we publish their on-disk paths via env vars the
7// executable (`libsql.node`, `keyring.node`); here we publish their on-disk7// loaders read.
8// paths via env vars the loaders read.
9//8//
10// This MUST be the FIRST import in main.ts. ES modules evaluate every import9// This MUST be the FIRST import in main.ts. ES modules evaluate every import
11// before the importer's own body, and libSQL resolves its native addon EAGERLY10// before the importer's own body, and libSQL resolves its native addon EAGERLY
@@ -43,3 +42,18 @@ if ( · 31 unmodified lines
43) {42) {
44 process.env.EXECUTOR_KEYRING_NATIVE_PATH = keyringNodeOnDisk;43 process.env.EXECUTOR_KEYRING_NATIVE_PATH = keyringNodeOnDisk;
45}44}
45
46const workerdOnDisk = join(execDir, process.platform === "win32" ? "workerd.exe" : "workerd");
47if (typeof Bun !== "undefined" && !process.env.EXECUTOR_WORKERD_BIN && existsSync(workerdOnDisk)) {
48 process.env.EXECUTOR_WORKERD_BIN = workerdOnDisk;
49}
50
51const workerBundlerOnDisk = join(execDir, "worker-bundler");
52if (
53 typeof Bun !== "undefined" &&
54 !process.env.EXECUTOR_WORKER_BUNDLER_DIR &&
55 existsSync(join(workerBundlerOnDisk, "dist", "index.js")) &&
56 existsSync(join(workerBundlerOnDisk, "dist", "esbuild.wasm"))
57) {
58 process.env.EXECUTOR_WORKER_BUNDLER_DIR = workerBundlerOnDisk;
59}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t