Previously only vendor/audio-capture was copied. Ripgrep was left to a postinstall download script, but no-split builds have no postinstall step. Now both builds get the ripgrep binary directly.
114 lines
3.9 KiB
TypeScript
114 lines
3.9 KiB
TypeScript
import { readdir, readFile, writeFile, cp } from 'fs/promises'
|
|
import { join } from 'path'
|
|
import { getMacroDefines } from './scripts/defines.ts'
|
|
import { DEFAULT_BUILD_FEATURES } from './scripts/defines.ts'
|
|
|
|
const outdir = 'dist'
|
|
|
|
// Step 1: Clean output directory
|
|
const { rmSync } = await import('fs')
|
|
rmSync(outdir, { recursive: true, force: true })
|
|
|
|
// Collect FEATURE_* env vars → Bun.build features
|
|
const envFeatures = Object.keys(process.env)
|
|
.filter(k => k.startsWith('FEATURE_'))
|
|
.map(k => k.replace('FEATURE_', ''))
|
|
const features = [...new Set([...DEFAULT_BUILD_FEATURES, ...envFeatures])]
|
|
|
|
// Step 2: Bundle with splitting
|
|
const result = await Bun.build({
|
|
entrypoints: ['src/entrypoints/cli.tsx'],
|
|
outdir,
|
|
target: 'bun',
|
|
splitting: true,
|
|
define: getMacroDefines(),
|
|
features,
|
|
})
|
|
|
|
if (!result.success) {
|
|
console.error('Build failed:')
|
|
for (const log of result.logs) {
|
|
console.error(log)
|
|
}
|
|
process.exit(1)
|
|
}
|
|
|
|
// Step 3: Post-process — replace Bun-only `import.meta.require` with Node.js compatible version
|
|
const files = await readdir(outdir)
|
|
const IMPORT_META_REQUIRE = 'var __require = import.meta.require;'
|
|
const COMPAT_REQUIRE = `var __require = typeof import.meta.require === "function" ? import.meta.require : (await import("module")).createRequire(import.meta.url);`
|
|
|
|
let patched = 0
|
|
for (const file of files) {
|
|
if (!file.endsWith('.js')) continue
|
|
const filePath = join(outdir, file)
|
|
const content = await readFile(filePath, 'utf-8')
|
|
if (content.includes(IMPORT_META_REQUIRE)) {
|
|
await writeFile(
|
|
filePath,
|
|
content.replace(IMPORT_META_REQUIRE, COMPAT_REQUIRE),
|
|
)
|
|
patched++
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for Node.js compat)`,
|
|
)
|
|
|
|
// Step 4: Copy vendor binaries (audio-capture, ripgrep)
|
|
const distVendorAudio = join(outdir, 'vendor', 'audio-capture')
|
|
await cp('vendor/audio-capture', distVendorAudio, { recursive: true })
|
|
console.log(`Copied vendor/audio-capture/ → ${distVendorAudio}/`)
|
|
|
|
const distVendorRg = join(outdir, 'vendor', 'ripgrep')
|
|
await cp('src/utils/vendor/ripgrep', distVendorRg, { recursive: true })
|
|
console.log(`Copied src/utils/vendor/ripgrep/ → ${distVendorRg}/`)
|
|
|
|
// Step 5: Bundle download-ripgrep script as standalone JS for postinstall
|
|
const rgScript = await Bun.build({
|
|
entrypoints: ['scripts/download-ripgrep.ts'],
|
|
outdir,
|
|
target: 'node',
|
|
})
|
|
if (!rgScript.success) {
|
|
console.error('Failed to bundle download-ripgrep script:')
|
|
for (const log of rgScript.logs) {
|
|
console.error(log)
|
|
}
|
|
// Non-fatal — postinstall fallback to bun run scripts/download-ripgrep.ts
|
|
} else {
|
|
console.log(`Bundled download-ripgrep script to ${outdir}/`)
|
|
}
|
|
|
|
// Step 6: Build no-split single-file bundle for `ccb` CLI
|
|
// Code-split build hangs on chunk lazy-loading with Bun 1.3.11,
|
|
// so we provide a no-split alternative for the `ccb` launcher.
|
|
const noSplitDir = 'dist-nosplit'
|
|
rmSync(noSplitDir, { recursive: true, force: true })
|
|
const noSplitResult = await Bun.build({
|
|
entrypoints: ['src/entrypoints/cli.tsx'],
|
|
outdir: noSplitDir,
|
|
target: 'bun',
|
|
splitting: false,
|
|
define: getMacroDefines(),
|
|
features,
|
|
})
|
|
if (!noSplitResult.success) {
|
|
console.error('No-split build failed:')
|
|
for (const log of noSplitResult.logs) console.error(log)
|
|
} else {
|
|
console.log(
|
|
`No-split bundle: ${noSplitResult.outputs.length} file → ${noSplitDir}/`,
|
|
)
|
|
|
|
// Copy vendor binaries to no-split output so ripgrep and audio-capture work
|
|
const noSplitVendorAudio = join(noSplitDir, 'vendor', 'audio-capture')
|
|
await cp('vendor/audio-capture', noSplitVendorAudio, { recursive: true })
|
|
console.log(`Copied vendor/audio-capture/ → ${noSplitVendorAudio}/`)
|
|
|
|
const noSplitVendorRg = join(noSplitDir, 'vendor', 'ripgrep')
|
|
await cp('src/utils/vendor/ripgrep', noSplitVendorRg, { recursive: true })
|
|
console.log(`Copied src/utils/vendor/ripgrep/ → ${noSplitVendorRg}/`)
|
|
}
|