diff --git a/package.json b/package.json index b00baed..f8654ee 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "scripts": { "start": "bun run src/server/index.tsx", "dev": "bun run --hot src/server/index.tsx", - "test": "bun test" + "test": "bun test", + "cli:build": "bun run scripts/build.ts", + "cli:build:all": "bun run scripts/build.ts --all", + "cli:install": "bun cli:build && sudo cp dist/toes /usr/local/bin" }, "devDependencies": { "@types/bun": "latest" diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..dffd576 --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,127 @@ +#!/usr/bin/env bun +// Usage: bun scripts/build.ts [--all | --target=] +// No flags: builds for current platform (dist/toes) +// --all: builds for all targets (macos-arm64, macos-x64, linux-arm64, linux-x64) +// --target=toes-macos-arm64: builds specific target +import { existsSync, mkdirSync } from 'fs' +import { join } from 'path' + +const DIST_DIR = join(import.meta.dir, '..', 'dist') +const ENTRY_POINT = join(import.meta.dir, '..', 'src', 'cli', 'index.ts') + +interface BuildTarget { + arch: string + name: string + os: string +} + +const TARGETS: BuildTarget[] = [ + { os: 'darwin', arch: 'arm64', name: 'toes-macos-arm64' }, + { os: 'darwin', arch: 'x64', name: 'toes-macos-x64' }, + { os: 'linux', arch: 'arm64', name: 'toes-linux-arm64' }, + { os: 'linux', arch: 'x64', name: 'toes-linux-x64' }, +] + +// Ensure dist directory exists +if (!existsSync(DIST_DIR)) { + mkdirSync(DIST_DIR, { recursive: true }) +} + +// Parse command line args +const args = process.argv.slice(2) +const buildAll = args.includes('--all') +const targetArg = args.find(arg => arg.startsWith('--target='))?.split('=')[1] + +async function buildTarget(target: BuildTarget) { + console.log(`Building ${target.name}...`) + + const output = join(DIST_DIR, target.name) + + const proc = Bun.spawn([ + 'bun', + 'build', + ENTRY_POINT, + '--compile', + '--target', + 'bun', + '--minify', + '--sourcemap=external', + '--outfile', + output, + ], { + stdout: 'inherit', + stderr: 'inherit', + env: { + ...process.env, + BUN_TARGET_OS: target.os, + BUN_TARGET_ARCH: target.arch, + }, + }) + + const exitCode = await proc.exited + + if (exitCode === 0) { + console.log(`✓ Built ${target.name}`) + } else { + console.error(`✗ Failed to build ${target.name}`) + process.exit(exitCode) + } +} + +async function buildCurrent() { + const platform = process.platform + const arch = process.arch + + console.log(`Building for current platform (${platform}-${arch})...`) + + const output = join(DIST_DIR, 'toes') + + const proc = Bun.spawn([ + 'bun', + 'build', + ENTRY_POINT, + '--compile', + '--target', + 'bun', + '--minify', + '--sourcemap=external', + '--outfile', + output, + ], { + stdout: 'inherit', + stderr: 'inherit', + }) + + const exitCode = await proc.exited + + if (exitCode === 0) { + console.log(`✓ Built toes at ${output}`) + console.log('\nTo install globally:') + console.log(` sudo cp ${output} /usr/local/bin/toes`) + } else { + console.error('✗ Build failed') + process.exit(exitCode) + } +} + +// Main build logic +if (buildAll) { + console.log('Building for all targets...\n') + for (const target of TARGETS) { + await buildTarget(target) + } + console.log('\n✓ All builds complete') +} else if (targetArg) { + const target = TARGETS.find(t => t.name === targetArg) + if (!target) { + console.error(`Unknown target: ${targetArg}`) + console.error('Available targets:') + for (const t of TARGETS) { + console.error(` ${t.name}`) + } + process.exit(1) + } + await buildTarget(target) +} else { + await buildCurrent() +}