#!/usr/bin/env node /** * Build the Node.js sidecar for Tauri production. * * Bundles packages/server/src/local/service.ts into a single JS file * at app/src-tauri/resources/service.js using esbuild JS API. * * Usage: * node scripts/build-sidecar.mjs */ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(__dirname, '..'); const resourcesDir = path.join(root, 'app', 'src-tauri', 'resources'); const outFile = path.join(resourcesDir, 'service.js'); const entryPoint = path.join(root, 'packages', 'server', 'src', 'local', 'service.ts'); // Metafile goes to a temp path (NOT resources/) so it's neither bundled into // the app nor left as an untracked repo artifact. stage-sidecar-deps.mjs reads // it back from the same well-known path. Keep the two in sync. const metaFile = path.join(os.tmpdir(), 'waggle-sidecar-meta.json'); // Ensure resources directory exists fs.mkdirSync(resourcesDir, { recursive: true }); console.log('[build-sidecar] Bundling server into', outFile); // Native modules that can't be bundled — must be installed alongside the sidecar const EXTERNAL = [ 'better-sqlite3', '@vscode/sqlite3', 'bullmq', 'ioredis', 'pg', 'postgres', 'drizzle-orm', 'drizzle-orm/*', 'mammoth', 'pdf-parse', 'exceljs', 'archiver', '@fastify/static', '@huggingface/transformers', 'onnxruntime-node', 'onnxruntime-common', 'onnxruntime-web', 'sharp', 'playwright-core', 'playwright-core/*', '@playwright/*', 'chromium-bidi', 'chromium-bidi/*', ]; try { // Dynamic import esbuild (available via vite dependency) const esbuild = await import('esbuild'); const result = await esbuild.build({ entryPoints: [entryPoint], bundle: true, platform: 'node', target: 'node20', format: 'esm', outfile: outFile, external: EXTERNAL, // P4/D12: @waggle/shared and @waggle/hive-mind-core export ONLY their // gitignored dist/ (unlike core/agent/server, which export src/*.ts). // Without these aliases the bundle silently embeds whatever dist/ was // last compiled — the same stale-server-in-the-binary class D12 exists // to kill — and a clean checkout can't build at all without // build:packages. Alias to source so the bundle ALWAYS compiles from // src, like the vitest aliases do. (No subpath imports of either // package exist — verified before aliasing the bare names.) alias: { '@waggle/shared': path.join(root, 'packages', 'shared', 'src', 'index.ts'), '@waggle/hive-mind-core': path.join(root, 'packages', 'hive-mind-core', 'src', 'index.ts'), }, sourcemap: true, minify: true, // metafile lets stage-sidecar-deps.mjs enumerate exactly which of the // EXTERNAL packages the bundle actually `require()`s at runtime, so it // stages precisely that set (and its transitive prod deps) into // resources/node_modules/ — no more, no less. Written next to the bundle. metafile: true, banner: { js: '// Waggle Sidecar — bundled server for Tauri desktop\n' + '// Generated by scripts/build-sidecar.mjs\n' + 'import { createRequire } from "node:module";\n' + 'const require = createRequire(import.meta.url);\n', }, logLevel: 'warning', }); if (result.errors.length > 0) { console.error('[build-sidecar] Build errors:', result.errors); process.exit(1); } if (result.warnings.length > 0) { console.warn(`[build-sidecar] ${result.warnings.length} warnings (non-blocking)`); } fs.writeFileSync(metaFile, JSON.stringify(result.metafile)); console.log('[build-sidecar] Wrote esbuild metafile', metaFile); const stat = fs.statSync(outFile); const sizeMB = (stat.size / 1024 / 1024).toFixed(1); console.log(`[build-sidecar] Done. Output: ${sizeMB} MB`); // Copy marketplace seed database if it exists const marketplaceDb = path.join(root, 'packages', 'marketplace', 'seed', 'marketplace.db'); if (fs.existsSync(marketplaceDb)) { fs.copyFileSync(marketplaceDb, path.join(resourcesDir, 'marketplace.db')); console.log('[build-sidecar] Copied marketplace.db seed'); } } catch (err) { console.error('[build-sidecar] Build failed:', err.message); process.exit(1); }