Files
orca/config/scripts/build-node-server.mjs
T

76 lines
2.7 KiB
JavaScript

import { cpSync, existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { build } from 'esbuild'
const repoRoot = resolve(import.meta.dirname, '..', '..')
const packageRoot = join(repoRoot, 'resources', 'npm-server')
const distRoot = join(packageRoot, 'dist')
const facadePath = join(repoRoot, 'src', 'node-server', 'node-host-electron-facade.ts')
const external = ['@parcel/watcher', 'node-pty', 'ssh2', 'tweetnacl', 'ws']
const common = {
absWorkingDir: repoRoot,
alias: { electron: facadePath, 'electron-updater': facadePath },
bundle: true,
define: {
ORCA_BUILD_IDENTITY: 'null',
ORCA_DIAGNOSTICS_TOKEN_URL: 'null',
ORCA_POSTHOG_WRITE_KEY: 'null'
},
external,
format: 'cjs',
logLevel: 'info',
mainFields: ['module', 'main'],
metafile: true,
platform: 'node',
sourcemap: false,
target: 'node24'
}
rmSync(distRoot, { force: true, recursive: true })
mkdirSync(distRoot, { recursive: true })
const serverResult = await build({
...common,
entryPoints: [join(repoRoot, 'src', 'node-server', 'package-cli.ts')],
outfile: join(distRoot, 'cli.js')
})
const daemonResult = await build({
...common,
entryPoints: [join(repoRoot, 'src', 'main', 'daemon', 'daemon-entry.ts')],
outfile: join(distRoot, 'daemon-entry.js')
})
const webRoot = join(repoRoot, 'out', 'web')
if (!existsSync(join(webRoot, 'web-index.html'))) {
throw new Error('Missing out/web/web-index.html; run build:web-from-renderer first')
}
cpSync(webRoot, join(distRoot, 'web'), { recursive: true })
cpSync(join(repoRoot, 'LICENSE'), join(distRoot, 'LICENSE'))
verifyPlainNodeBundle(serverResult.metafile, 'server')
verifyPlainNodeBundle(daemonResult.metafile, 'daemon')
const packageJson = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))
const rootPackageJson = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8'))
if (packageJson.version !== rootPackageJson.version) {
throw new Error(
`Server package version ${packageJson.version} does not match root ${rootPackageJson.version}`
)
}
function verifyPlainNodeBundle(metafile, label) {
const forbiddenExternal = new Set(['electron', 'electron-updater'])
const forbiddenPackages = ['agent-browser', 'serve-sim', 'sherpa-onnx']
for (const [output, metadata] of Object.entries(metafile.outputs)) {
for (const imported of metadata.imports) {
if (forbiddenExternal.has(imported.path)) {
throw new Error(`${label} bundle ${output} imports forbidden runtime ${imported.path}`)
}
}
}
for (const input of Object.keys(metafile.inputs)) {
if (forbiddenPackages.some((name) => input.includes(`/node_modules/${name}/`))) {
throw new Error(`${label} bundle includes desktop-only package ${input}`)
}
}
}