Compare commits

...

4 Commits

Author SHA1 Message Date
9f38636d76 refactor(server): use Bun.Build.CompileTarget and derive host target instead of manual map 2026-02-08 22:47:39 +08:00
63906ec09b refactor(server): use util.parseArgs for declarative CLI arg parsing in compile.ts 2026-02-08 22:38:49 +08:00
8c4e4ad150 refactor(server): use type guard to eliminate as Target casts in compile.ts 2026-02-08 22:33:02 +08:00
e171db8196 refactor: simplify compile.ts to single-target and add per-platform compile scripts
- Rewrite compile.ts from 112 to 66 lines: single target with auto-detect host, remove multi-target batch logic
- Add compile:linux/mac/win scripts to server, root, and turbo configs
- Wire desktop dist:* to depend on matching server compile:* (avoid unnecessary cross-platform compilation)
- Update AGENTS.md docs across root, server, and desktop
2026-02-08 22:25:30 +08:00
9 changed files with 79 additions and 93 deletions

View File

@@ -20,7 +20,10 @@ Guidelines for AI agents working in this Bun monorepo.
```bash
bun dev # Start all apps in dev mode
bun build # Build all apps
bun compile # Compile server to standalone binary (depends on build)
bun compile # Compile server to standalone binary (current platform, depends on build)
bun compile:linux # Compile server for Linux x64
bun compile:mac # Compile server for macOS arm64
bun compile:win # Compile server for Windows x64
bun dist # Full packaging pipeline: server build → compile → desktop distributable (current platform)
bun dist:linux # Full pipeline → Linux distributable
bun dist:mac # Full pipeline → macOS distributable
@@ -33,7 +36,10 @@ bun typecheck # TypeScript check across monorepo
```bash
bun dev # Vite dev server (localhost:3000)
bun build # Production build -> .output/
bun compile # Compile to standalone binary
bun compile # Compile to standalone binary (current platform)
bun compile:linux # Compile for Linux x64
bun compile:mac # Compile for macOS arm64
bun compile:win # Compile for Windows x64
bun fix # Biome auto-fix
bun typecheck # TypeScript check

View File

@@ -61,7 +61,7 @@ bun typecheck # TypeScript check
From monorepo root, run `bun dist` to execute the full pipeline automatically (via Turbo task dependencies):
1. **Build server**: `apps/server``vite build``.output/`
2. **Compile server**: `apps/server``bun compile.ts``out/server-{platform}`
2. **Compile server**: `apps/server``bun compile.ts``out/server-{os}-{arch}`
3. **Package desktop**: `apps/desktop``electron-vite build` + `electron-builder` → distributable
The `electron-builder.yml` `extraResources` config reads binaries directly from `../server/out/`, no manual copy needed.

View File

@@ -1,14 +1,15 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/electron-userland/electron-builder/refs/heads/master/packages/app-builder-lib/scheme.json
appId: com.furtherverse.app
productName: Furtherverse
directories:
buildResources: build
files:
- '!**/.vscode/*'
- '!src/*'
- '!electron.vite.config.{js,ts,mjs,cjs}'
- '!{.env,.env.*,bun.lock}'
- '!{tsconfig.json,tsconfig.node.json}'
- '!{AGENTS.md,README.md,CHANGELOG.md}'
- "!**/.vscode/*"
- "!src/*"
- "!electron.vite.config.{js,ts,mjs,cjs}"
- "!{.env,.env.*,bun.lock}"
- "!{tsconfig.json,tsconfig.node.json}"
- "!{AGENTS.md,README.md,CHANGELOG.md}"
asarUnpack:
- resources/**
win:

View File

@@ -25,8 +25,10 @@ bun db:studio # Drizzle Studio GUI
# Build
bun build # Production build → .output/
bun compile # Compile to standalone binary (depends on build)
# Also triggered automatically by root `bun dist`
bun compile # Compile to standalone binary (current platform, depends on build)
bun compile:linux # Compile for Linux x64
bun compile:mac # Compile for macOS arm64
bun compile:win # Compile for Windows x64
# Code Quality
bun fix # Biome auto-fix

View File

@@ -1,111 +1,64 @@
import { rm } from 'node:fs/promises'
import path from 'node:path'
import process from 'node:process'
const ALL_TARGETS = [
'bun-windows-x64',
'bun-darwin-arm64',
'bun-darwin-x64',
'bun-linux-x64',
'bun-linux-arm64',
] as const
type BunTarget = (typeof ALL_TARGETS)[number]
import { parseArgs } from 'node:util'
const ENTRYPOINT = '.output/server/index.mjs'
const OUTDIR = 'out'
const OUTFILE_BASE = 'server'
const DEFAULT_TARGETS: BunTarget[] = [
const SUPPORTED_TARGETS: readonly Bun.Build.CompileTarget[] = [
'bun-windows-x64',
'bun-darwin-arm64',
'bun-linux-x64',
'bun-linux-arm64',
]
const suffixFor = (target: BunTarget) => target.replace('bun-', '')
const isSupportedTarget = (value: string): value is Bun.Build.CompileTarget =>
(SUPPORTED_TARGETS as readonly string[]).includes(value)
const isTarget = (value: string): value is BunTarget =>
(ALL_TARGETS as readonly string[]).includes(value)
const { values } = parseArgs({
options: { target: { type: 'string' } },
strict: true,
allowPositionals: false,
})
const parseTargets = (): BunTarget[] => {
const args = process.argv.slice(2)
const targets: string[] = []
for (let i = 0; i < args.length; i++) {
const arg = args[i]
const next = args[i + 1]
if (arg === '--target' && next) {
targets.push(next)
i++
} else if (arg === '--targets' && next) {
targets.push(...next.split(','))
i++
const resolveTarget = (): Bun.Build.CompileTarget => {
if (values.target !== undefined) {
if (!isSupportedTarget(values.target)) {
throw new Error(
`Invalid target: ${values.target}\nAllowed: ${SUPPORTED_TARGETS.join(', ')}`,
)
}
return values.target
}
if (targets.length === 0) return DEFAULT_TARGETS
const invalid = targets.filter((t) => !isTarget(t))
if (invalid.length) {
throw new Error(
`Unknown target(s): ${invalid.join(', ')}\nAllowed: ${ALL_TARGETS.join(', ')}`,
)
const os = process.platform === 'win32' ? 'windows' : process.platform
const candidate = `bun-${os}-${process.arch}`
if (!isSupportedTarget(candidate)) {
throw new Error(`Unsupported host: ${process.platform}-${process.arch}`)
}
return targets as BunTarget[]
return candidate
}
const buildOne = async (target: BunTarget) => {
const suffix = suffixFor(target)
const outfile = `${OUTFILE_BASE}-${suffix}`
const main = async () => {
const target = resolveTarget()
const suffix = target.replace('bun-', '')
const outfile = `server-${suffix}`
await rm(OUTDIR, { recursive: true, force: true })
const result = await Bun.build({
entrypoints: [ENTRYPOINT],
outdir: OUTDIR,
compile: {
outfile,
target,
},
compile: { outfile, target },
})
if (!result.success) {
throw new Error(
`Build failed for ${target}:\n${result.logs.map(String).join('\n')}`,
)
throw new Error(result.logs.map(String).join('\n'))
}
return {
target,
outputs: result.outputs.map((o) => path.relative('.', o.path)),
}
}
const main = async () => {
const targets = parseTargets()
await rm(OUTDIR, { recursive: true, force: true })
console.log(`✓ 已清理输出目录: ${OUTDIR}`)
// Bun cross-compile 不支持真正并行,逐目标串行构建
const results: Awaited<ReturnType<typeof buildOne>>[] = []
for (const target of targets) {
const start = Date.now()
process.stdout.write(`🔨 构建 ${target}... `)
const result = await buildOne(target)
results.push(result)
console.log(`完成 (${Date.now() - start}ms)`)
}
console.log('\n📦 构建完成:')
for (const r of results) {
console.log(` ${r.target}:`)
for (const p of r.outputs) {
console.log(` - ${p}`)
}
}
console.log(`${target}${OUTDIR}/${outfile}`)
}
main().catch((err) => {
console.error('\n❌ 构建失败:')
console.error(err instanceof Error ? err.message : err)
console.error('❌', err instanceof Error ? err.message : err)
process.exit(1)
})

View File

@@ -6,6 +6,9 @@
"scripts": {
"build": "vite build",
"compile": "bun compile.ts",
"compile:linux": "bun compile.ts --target bun-linux-x64",
"compile:mac": "bun compile.ts --target bun-darwin-arm64",
"compile:win": "bun compile.ts --target bun-windows-x64",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",

View File

@@ -8,6 +8,15 @@
},
"compile": {
"outputs": ["out/**"]
},
"compile:linux": {
"outputs": ["out/**"]
},
"compile:mac": {
"outputs": ["out/**"]
},
"compile:win": {
"outputs": ["out/**"]
}
}
}

View File

@@ -10,6 +10,9 @@
"scripts": {
"build": "turbo run build",
"compile": "turbo run compile",
"compile:linux": "turbo run compile:linux",
"compile:mac": "turbo run compile:mac",
"compile:win": "turbo run compile:win",
"dev": "turbo run dev",
"dist": "turbo run dist",
"dist:linux": "turbo run dist:linux",

View File

@@ -9,6 +9,15 @@
"compile": {
"dependsOn": ["build"]
},
"compile:linux": {
"dependsOn": ["build"]
},
"compile:mac": {
"dependsOn": ["build"]
},
"compile:win": {
"dependsOn": ["build"]
},
"dist": {},
"dist:linux": {},
"dist:mac": {},
@@ -17,13 +26,13 @@
"dependsOn": ["@furtherverse/server#compile"]
},
"@furtherverse/desktop#dist:linux": {
"dependsOn": ["@furtherverse/server#compile"]
"dependsOn": ["@furtherverse/server#compile:linux"]
},
"@furtherverse/desktop#dist:mac": {
"dependsOn": ["@furtherverse/server#compile"]
"dependsOn": ["@furtherverse/server#compile:mac"]
},
"@furtherverse/desktop#dist:win": {
"dependsOn": ["@furtherverse/server#compile"]
"dependsOn": ["@furtherverse/server#compile:win"]
},
"dev": {
"cache": false,