(targets: Target[], mode: BuildMode)
| 440 | const EMBEDDED_MIGRATIONS_STUB = `const migrations: Record<string, string> | null = null;\n\nexport default migrations;\n`; |
| 441 | |
| 442 | const buildBinaries = async (targets: Target[], mode: BuildMode) => { |
| 443 | const meta = await readMetadata(); |
| 444 | const binaries: Record<string, string> = {}; |
| 445 | const embeddedWebUIPath = join(cliRoot, "src/embedded-web-ui.gen.ts"); |
| 446 | const embeddedMigrationsPath = join(webRoot, "src/db/embedded-migrations.gen.ts"); |
| 447 | |
| 448 | await rm(distDir, { recursive: true, force: true }); |
| 449 | |
| 450 | // Cross-platform builds need every target's optional native packages |
| 451 | // (e.g. @napi-rs/keyring-darwin-arm64) so we can copy the right .node next |
| 452 | // to each target's executor. `bun install --frozen-lockfile --cpu=* --os=*` |
| 453 | // extracts them all without modifying the lockfile. |
| 454 | const needsCrossPlatform = targets.some((t) => !isCurrentPlatform(t)); |
| 455 | if (needsCrossPlatform) { |
| 456 | console.log("Installing optional native deps for all platforms..."); |
| 457 | const proc = Bun.spawn(["bun", "install", "--frozen-lockfile", "--cpu=*", "--os=*"], { |
| 458 | cwd: repoRoot, |
| 459 | stdio: ["ignore", "inherit", "inherit"], |
| 460 | }); |
| 461 | if ((await proc.exited) !== 0) { |
| 462 | throw new Error("bun install --cpu=* --os=* failed"); |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | console.log(`Generating embedded web UI bundle (${mode})...`); |
| 467 | const embeddedWebUI = await createEmbeddedWebUISource(mode); |
| 468 | await writeFile(embeddedWebUIPath, `${embeddedWebUI}\n`); |
| 469 | |
| 470 | console.log("Generating embedded drizzle migrations..."); |
| 471 | const embeddedMigrations = await createEmbeddedMigrationsSource(); |
| 472 | await writeFile(embeddedMigrationsPath, `${embeddedMigrations}\n`); |
| 473 | |
| 474 | const quickJsWasmPath = resolveQuickJsWasmPath(); |
| 475 | const mcpAppsShellPath = await ensureMcpAppsShell(); |
| 476 | const onePasswordCoreWasmPath = resolveOnePasswordCoreWasmPath(); |
| 477 | const workerBundlerDistPath = resolveWorkerBundlerDistPath(); |
| 478 | const packedWorkerBundlerSource = await createPackedWorkerBundlerSource(workerBundlerDistPath); |
| 479 | |
| 480 | try { |
| 481 | for (const target of targets) { |
| 482 | const name = targetPackageName(target); |
| 483 | const outDir = join(distDir, name); |
| 484 | const binDir = join(outDir, "bin"); |
| 485 | await mkdir(binDir, { recursive: true }); |
| 486 | |
| 487 | console.log(`Building ${name}...`); |
| 488 | |
| 489 | await Bun.build({ |
| 490 | entrypoints: [join(cliRoot, "src/main.ts")], |
| 491 | minify: mode === "production", |
| 492 | compile: { |
| 493 | target: bunTarget(target), |
| 494 | outfile: join(binDir, binaryName(target)), |
| 495 | }, |
| 496 | }); |
| 497 | |
| 498 | // Copy QuickJS WASM next to binary — loaded at runtime by the server |
| 499 | await cp(quickJsWasmPath, join(binDir, "emscripten-module.wasm")); |
no test coverage detected