Skip to content

Commit 72c1955

Browse files
committed
feat: compile to platform binaries for fast install
- Add script/build.ts: cross-compile to darwin-arm64/x64, linux-arm64/x64, windows-x64 - Rewrite bin/codeblog: find platform binary, fallback to bun source - Add optionalDependencies for platform-specific binary packages - Bump to v1.4.0
1 parent ca44a5e commit 72c1955

4 files changed

Lines changed: 222 additions & 4 deletions

File tree

‎packages/codeblog/bin/codeblog‎

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,65 @@
1-
#!/usr/bin/env bun
2-
import "../src/index.ts"
1+
#!/usr/bin/env node
2+
3+
const childProcess = require("child_process")
4+
const fs = require("fs")
5+
const path = require("path")
6+
const os = require("os")
7+
8+
function run(target) {
9+
const result = childProcess.spawnSync(target, process.argv.slice(2), {
10+
stdio: "inherit",
11+
})
12+
if (result.error) {
13+
console.error(result.error.message)
14+
process.exit(1)
15+
}
16+
process.exit(typeof result.status === "number" ? result.status : 0)
17+
}
18+
19+
const scriptDir = path.dirname(fs.realpathSync(__filename))
20+
21+
const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" }
22+
const archMap = { x64: "x64", arm64: "arm64" }
23+
const platform = platformMap[os.platform()] || os.platform()
24+
const arch = archMap[os.arch()] || os.arch()
25+
const base = "codeblog-app-" + platform + "-" + arch
26+
const binary = platform === "windows" ? "codeblog.exe" : "codeblog"
27+
28+
function findBinary(startDir) {
29+
let current = startDir
30+
for (;;) {
31+
const modules = path.join(current, "node_modules")
32+
if (fs.existsSync(modules)) {
33+
const candidate = path.join(modules, base, "bin", binary)
34+
if (fs.existsSync(candidate)) return candidate
35+
}
36+
const parent = path.dirname(current)
37+
if (parent === current) return
38+
current = parent
39+
}
40+
}
41+
42+
const resolved = findBinary(scriptDir)
43+
if (resolved) {
44+
run(resolved)
45+
} else {
46+
// Fallback: run with bun from source
47+
const bun = process.env.BUN_INSTALL
48+
? path.join(process.env.BUN_INSTALL, "bin", "bun")
49+
: path.join(os.homedir(), ".bun", "bin", "bun")
50+
51+
if (fs.existsSync(bun)) {
52+
const src = path.join(scriptDir, "..", "src", "index.ts")
53+
const result = childProcess.spawnSync(bun, ["run", src, ...process.argv.slice(2)], {
54+
stdio: "inherit",
55+
})
56+
process.exit(typeof result.status === "number" ? result.status : 0)
57+
}
58+
59+
console.error(
60+
"Could not find codeblog binary for your platform (" + base + ").\n" +
61+
"Try: npm install -g codeblog-app@latest\n" +
62+
"Or install bun: curl -fsSL https://bun.sh/install | bash"
63+
)
64+
process.exit(1)
65+
}

‎packages/codeblog/package.json‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/package.json",
33
"name": "codeblog-app",
4-
"version": "1.3.0",
4+
"version": "1.4.0",
55
"description": "CLI client for CodeBlog — the forum where AI writes the posts",
66
"type": "module",
77
"license": "MIT",
@@ -55,6 +55,13 @@
5555
"drizzle-kit": "1.0.0-beta.12-a5629fb",
5656
"typescript": "5.8.2"
5757
},
58+
"optionalDependencies": {
59+
"codeblog-app-darwin-arm64": "1.4.0",
60+
"codeblog-app-darwin-x64": "1.4.0",
61+
"codeblog-app-linux-arm64": "1.4.0",
62+
"codeblog-app-linux-x64": "1.4.0",
63+
"codeblog-app-windows-x64": "1.4.0"
64+
},
5865
"dependencies": {
5966
"@ai-sdk/amazon-bedrock": "^4.0.60",
6067
"@ai-sdk/anthropic": "^3.0.44",

‎packages/codeblog/script/build.ts‎

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env bun
2+
3+
import solidPlugin from "../node_modules/@opentui/solid/scripts/solid-plugin"
4+
import path from "path"
5+
import fs from "fs"
6+
import { $ } from "bun"
7+
8+
const dir = path.resolve(import.meta.dirname, "..")
9+
process.chdir(dir)
10+
11+
const pkg = JSON.parse(await Bun.file(path.join(dir, "package.json")).text())
12+
const version = pkg.version
13+
14+
// Load migration SQL
15+
const migrationFile = path.join(dir, "drizzle", "0000_init.sql")
16+
const migrationSQL = await Bun.file(migrationFile).text()
17+
18+
const singleFlag = process.argv.includes("--single")
19+
20+
const allTargets: { os: string; arch: "arm64" | "x64" }[] = [
21+
{ os: "darwin", arch: "arm64" },
22+
{ os: "darwin", arch: "x64" },
23+
{ os: "linux", arch: "arm64" },
24+
{ os: "linux", arch: "x64" },
25+
{ os: "win32", arch: "x64" },
26+
]
27+
28+
const targets = singleFlag
29+
? allTargets.filter((t) => t.os === process.platform && t.arch === process.arch)
30+
: allTargets
31+
32+
await $`rm -rf dist`
33+
34+
// Install platform-specific native deps for cross-compilation
35+
if (!singleFlag) {
36+
await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`
37+
}
38+
39+
for (const item of targets) {
40+
const name = [
41+
"codeblog-app",
42+
item.os === "win32" ? "windows" : item.os,
43+
item.arch,
44+
].join("-")
45+
46+
console.log(`building ${name}...`)
47+
await $`mkdir -p dist/${name}/bin`
48+
49+
const binary = item.os === "win32" ? "codeblog.exe" : "codeblog"
50+
51+
await Bun.build({
52+
conditions: ["browser"],
53+
tsconfig: "./tsconfig.json",
54+
plugins: [solidPlugin],
55+
sourcemap: "none",
56+
compile: {
57+
autoloadBunfig: false,
58+
autoloadDotenv: false,
59+
// @ts-ignore
60+
autoloadTsconfig: true,
61+
autoloadPackageJson: true,
62+
target: name.replace("codeblog-app", "bun") as any,
63+
outfile: `dist/${name}/bin/${binary}`,
64+
execArgv: ["--use-system-ca", "--"],
65+
windows: {},
66+
},
67+
entrypoints: ["./src/index.ts"],
68+
define: {
69+
CODEBLOG_VERSION: `'${version}'`,
70+
CODEBLOG_MIGRATION_SQL: JSON.stringify(migrationSQL),
71+
},
72+
})
73+
74+
// Write platform package.json
75+
await Bun.file(`dist/${name}/package.json`).write(
76+
JSON.stringify(
77+
{
78+
name,
79+
version,
80+
description: `CodeBlog CLI binary for ${item.os} ${item.arch}`,
81+
os: [item.os],
82+
cpu: [item.arch],
83+
bin: { codeblog: `bin/${binary}` },
84+
},
85+
null,
86+
2,
87+
),
88+
)
89+
90+
console.log(` ✓ ${name}`)
91+
}
92+
93+
// Create main wrapper package
94+
await $`mkdir -p dist/codeblog-app`
95+
const optionalDeps: Record<string, string> = {}
96+
for (const item of targets) {
97+
const name = [
98+
"codeblog-app",
99+
item.os === "win32" ? "windows" : item.os,
100+
item.arch,
101+
].join("-")
102+
optionalDeps[name] = version
103+
}
104+
105+
await Bun.file("dist/codeblog-app/package.json").write(
106+
JSON.stringify(
107+
{
108+
name: "codeblog-app",
109+
version,
110+
description: "CLI client for CodeBlog — the forum where AI writes the posts",
111+
license: "MIT",
112+
author: "CodeBlog-ai",
113+
homepage: "https://github.com/CodeBlog-ai/codeblog-app",
114+
repository: { type: "git", url: "https://github.com/CodeBlog-ai/codeblog-app" },
115+
bin: { codeblog: "bin/codeblog" },
116+
optionalDependencies: optionalDeps,
117+
},
118+
null,
119+
2,
120+
),
121+
)
122+
123+
// Copy the launcher script
124+
await $`mkdir -p dist/codeblog-app/bin`
125+
await Bun.file("dist/codeblog-app/bin/codeblog").write(
126+
await Bun.file(path.join(dir, "bin", "codeblog")).text(),
127+
)
128+
await $`chmod +x dist/codeblog-app/bin/codeblog`
129+
130+
console.log("")
131+
console.log(`Built ${targets.length} platform binaries for v${version}`)
132+
console.log("")
133+
134+
// If --publish flag, publish all packages
135+
if (process.argv.includes("--publish")) {
136+
for (const item of targets) {
137+
const name = [
138+
"codeblog-app",
139+
item.os === "win32" ? "windows" : item.os,
140+
item.arch,
141+
].join("-")
142+
console.log(`Publishing ${name}@${version}...`)
143+
await $`npm publish --access public`.cwd(`dist/${name}`)
144+
}
145+
console.log(`Publishing codeblog-app@${version}...`)
146+
await $`npm publish --access public`.cwd(`dist/codeblog-app`)
147+
console.log("All packages published!")
148+
}

‎packages/codeblog/src/index.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { WeeklyDigestCommand } from "./cli/cmd/weekly-digest"
3535
import { TagsCommand } from "./cli/cmd/tags"
3636
import { ExploreCommand } from "./cli/cmd/explore"
3737

38-
const VERSION = "1.3.0"
38+
const VERSION = "1.4.0"
3939

4040
process.on("unhandledRejection", (e) => {
4141
Log.Default.error("rejection", {

0 commit comments

Comments
 (0)