Replace platform-specific optionalDependencies with bun devDependency (#518)
* Replace platform-specific optionalDependencies with bun devDependency Fixes #222. The bun meta-package handles platform detection internally. Rollup resolves its own platform binaries transitively. Removes ~400MB of bloat for SDK consumers. Simplifies setup-bun.mjs accordingly. * Remove setup-bun.mjs, simplify prepare script No longer needed since the bun npm package handles binary installation and PATH registration automatically.
This commit is contained in:
parent
0af4cdc305
commit
62c75203b6
3 changed files with 85 additions and 451 deletions
136
package-lock.json
generated
136
package-lock.json
generated
|
|
@ -7,7 +7,6 @@
|
|||
"": {
|
||||
"name": "@modelcontextprotocol/ext-apps",
|
||||
"version": "1.1.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"examples/*"
|
||||
|
|
@ -20,6 +19,7 @@
|
|||
"@types/node": "20.19.27",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"bun": "^1.2.21",
|
||||
"caniuse-lite": "1.0.30001763",
|
||||
"cheerio": "1.1.2",
|
||||
"concurrently": "^9.2.1",
|
||||
|
|
@ -43,25 +43,6 @@
|
|||
"typescript": "^5.9.3",
|
||||
"zod": "^4.1.13"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oven/bun-darwin-aarch64": "^1.2.21",
|
||||
"@oven/bun-darwin-x64": "^1.2.21",
|
||||
"@oven/bun-darwin-x64-baseline": "^1.2.21",
|
||||
"@oven/bun-linux-aarch64": "^1.2.21",
|
||||
"@oven/bun-linux-aarch64-musl": "^1.2.21",
|
||||
"@oven/bun-linux-x64": "^1.2.21",
|
||||
"@oven/bun-linux-x64-baseline": "^1.2.21",
|
||||
"@oven/bun-linux-x64-musl": "^1.2.21",
|
||||
"@oven/bun-linux-x64-musl-baseline": "^1.2.21",
|
||||
"@oven/bun-windows-x64": "^1.2.21",
|
||||
"@oven/bun-windows-x64-baseline": "^1.2.21",
|
||||
"@rollup/rollup-darwin-arm64": "^4.53.3",
|
||||
"@rollup/rollup-darwin-x64": "^4.53.3",
|
||||
"@rollup/rollup-linux-arm64-gnu": "^4.53.3",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.53.3",
|
||||
"@rollup/rollup-win32-arm64-msvc": "^4.53.3",
|
||||
"@rollup/rollup-win32-x64-msvc": "^4.53.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.24.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
|
|
@ -3015,9 +2996,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@oven/bun-darwin-aarch64": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.3.6.tgz",
|
||||
"integrity": "sha512-27rypIapNkYboOSylkf1tD9UW9Ado2I+P1NBL46Qz29KmOjTL6WuJ7mHDC5O66CYxlOkF5r93NPDAC3lFHYBXw==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.3.10.tgz",
|
||||
"integrity": "sha512-PXgg5gqcS/rHwa1hF0JdM1y5TiyejVrMHoBmWY/DjtfYZoFTXie1RCFOkoG0b5diOOmUcuYarMpH7CSNTqwj+w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -3028,9 +3009,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-darwin-x64": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.3.6.tgz",
|
||||
"integrity": "sha512-I82xGzPkBxzBKgbl8DsA0RfMQCWTWjNmLjIEkW1ECiv3qK02kHGQ5FGUr/29L/SuvnGsULW4tBTRNZiMzL37nA==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.3.10.tgz",
|
||||
"integrity": "sha512-Nhssuh7GBpP5PiDSOl3+qnoIG7PJo+ec2oomDevnl9pRY6x6aD2gRt0JE+uf+A8Om2D6gjeHCxjEdrw5ZHE8mA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3041,9 +3022,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-darwin-x64-baseline": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.3.6.tgz",
|
||||
"integrity": "sha512-nqtr+pTsHqusYpG2OZc6s+AmpWDB/FmBvstrK0y5zkti4OqnCuu7Ev2xNjS7uyb47NrAFF40pWqkpaio5XEd7w==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.3.10.tgz",
|
||||
"integrity": "sha512-w1gaTlqU0IJCmJ1X+PGHkdNU1n8Gemx5YKkjhkJIguvFINXEBB5U1KG82QsT65Tk4KyNMfbLTlmy4giAvUoKfA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3054,9 +3035,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-aarch64": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.3.6.tgz",
|
||||
"integrity": "sha512-YaQEAYjBanoOOtpqk/c5GGcfZIyxIIkQ2m1TbHjedRmJNwxzWBhGinSARFkrRIc3F8pRIGAopXKvJ/2rjN1LzQ==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.3.10.tgz",
|
||||
"integrity": "sha512-OUgPHfL6+PM2Q+tFZjcaycN3D7gdQdYlWnwMI31DXZKY1r4HINWk9aEz9t/rNaHg65edwNrt7dsv9TF7xK8xIA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -3067,9 +3048,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-aarch64-musl": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.3.6.tgz",
|
||||
"integrity": "sha512-FR+iJt17rfFgYgpxL3M67AUwujOgjw52ZJzB9vElI5jQXNjTyOKf8eH4meSk4vjlYF3h/AjKYd6pmN0OIUlVKQ==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.3.10.tgz",
|
||||
"integrity": "sha512-Ui5pAgM7JE9MzHokF0VglRMkbak3lTisY4Mf1AZutPACXWgKJC5aGrgnHBfkl7QS6fEeYb0juy1q4eRznRHOsw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -3080,9 +3061,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.3.6.tgz",
|
||||
"integrity": "sha512-egfngj0dfJ868cf30E7B+ye9KUWSebYxOG4l9YP5eWeMXCtenpenx0zdKtAn9qxJgEJym5AN6trtlk+J6x8Lig==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.3.10.tgz",
|
||||
"integrity": "sha512-bzUgYj/PIZziB/ZesIP9HUyfvh6Vlf3od+TrbTTyVEuCSMKzDPQVW/yEbRp0tcHO3alwiEXwJDrWrHAguXlgiQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3093,9 +3074,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64-baseline": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.3.6.tgz",
|
||||
"integrity": "sha512-jRmnX18ak8WzqLrex3siw0PoVKyIeI5AiCv4wJLgSs7VKfOqrPycfHIWfIX2jdn7ngqbHFPzI09VBKANZ4Pckg==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.3.10.tgz",
|
||||
"integrity": "sha512-oqvMDYpX6dGJO03HgO5bXuccEsH3qbdO3MaAiAlO4CfkBPLUXz3N0DDElg5hz0L6ktdDVKbQVE5lfe+LAUISQg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3106,9 +3087,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64-musl": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.3.6.tgz",
|
||||
"integrity": "sha512-YeXcJ9K6vJAt1zSkeA21J6pTe7PgDMLTHKGI3nQBiMYnYf7Ob3K+b/ChSCznrJG7No5PCPiQPg4zTgA+BOTmSA==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.3.10.tgz",
|
||||
"integrity": "sha512-poVXvOShekbexHq45b4MH/mRjQKwACAC8lHp3Tz/hEDuz0/20oncqScnmKwzhBPEpqJvydXficXfBYuSim8opw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3119,9 +3100,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64-musl-baseline": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl-baseline/-/bun-linux-x64-musl-baseline-1.3.6.tgz",
|
||||
"integrity": "sha512-7FjVnxnRTp/AgWqSQRT/Vt9TYmvnZ+4M+d9QOKh/Lf++wIFXFGSeAgD6bV1X/yr2UPVmZDk+xdhr2XkU7l2v3w==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl-baseline/-/bun-linux-x64-musl-baseline-1.3.10.tgz",
|
||||
"integrity": "sha512-/hOZ6S1VsTX6vtbhWVL9aAnOrdpuO54mAGUWpTdMz7dFG5UBZ/VUEiK0pBkq9A1rlBk0GeD/6Y4NBFl8Ha7cRA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3131,10 +3112,24 @@
|
|||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-windows-aarch64": {
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-aarch64/-/bun-windows-aarch64-1.3.10.tgz",
|
||||
"integrity": "sha512-GXbz2swvN2DLw2dXZFeedMxSJtI64xQ9xp9Eg7Hjejg6mS2E4dP1xoQ2yAo2aZPi/2OBPAVaGzppI2q20XumHA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-windows-x64": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.3.6.tgz",
|
||||
"integrity": "sha512-Sr1KwUcbB0SEpnSPO22tNJppku2khjFluEst+mTGhxHzAGQTQncNeJxDnt3F15n+p9Q+mlcorxehd68n1siikQ==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.3.10.tgz",
|
||||
"integrity": "sha512-qaS1In3yfC/Z/IGQriVmF8GWwKuNqiw7feTSJWaQhH5IbL6ENR+4wGNPniZSJFaM/SKUO0e/YCRdoVBvgU4C1g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3145,9 +3140,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@oven/bun-windows-x64-baseline": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.3.6.tgz",
|
||||
"integrity": "sha512-PFUa7JL4lGoyyppeS4zqfuoXXih+gSE0XxhDMrCPVEUev0yhGNd/tbWBvcdpYnUth80owENoGjc8s5Knopv9wA==",
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.3.10.tgz",
|
||||
"integrity": "sha512-gh3UAHbUdDUG6fhLc1Csa4IGdtghue6U8oAIXWnUqawp6lwb3gOCRvp25IUnLF5vUHtgfMxuEUYV7YA2WxVutw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4652,6 +4647,41 @@
|
|||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/bun": {
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/bun/-/bun-1.3.10.tgz",
|
||||
"integrity": "sha512-S/CXaXXIyA4CMjdMkYQ4T2YMqnAn4s0ysD3mlsY4bUiOCqGlv28zck4Wd4H4kpvbekx15S9mUeLQ7Uxd0tYTLA==",
|
||||
"cpu": [
|
||||
"arm64",
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"win32"
|
||||
],
|
||||
"bin": {
|
||||
"bun": "bin/bun.exe",
|
||||
"bunx": "bin/bunx.exe"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oven/bun-darwin-aarch64": "1.3.10",
|
||||
"@oven/bun-darwin-x64": "1.3.10",
|
||||
"@oven/bun-darwin-x64-baseline": "1.3.10",
|
||||
"@oven/bun-linux-aarch64": "1.3.10",
|
||||
"@oven/bun-linux-aarch64-musl": "1.3.10",
|
||||
"@oven/bun-linux-x64": "1.3.10",
|
||||
"@oven/bun-linux-x64-baseline": "1.3.10",
|
||||
"@oven/bun-linux-x64-musl": "1.3.10",
|
||||
"@oven/bun-linux-x64-musl-baseline": "1.3.10",
|
||||
"@oven/bun-windows-aarch64": "1.3.10",
|
||||
"@oven/bun-windows-x64": "1.3.10",
|
||||
"@oven/bun-windows-x64-baseline": "1.3.10"
|
||||
}
|
||||
},
|
||||
"node_modules/bun-types": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.6.tgz",
|
||||
|
|
|
|||
23
package.json
23
package.json
|
|
@ -44,7 +44,6 @@
|
|||
"examples/*"
|
||||
],
|
||||
"scripts": {
|
||||
"postinstall": "node scripts/setup-bun.mjs || echo 'setup-bun.mjs failed or not available'",
|
||||
"start": "npm run examples:dev",
|
||||
"generate:schemas": "tsx scripts/generate-schemas.ts && prettier --write \"src/generated/**/*\"",
|
||||
"sync:snippets": "bun scripts/sync-snippets.ts",
|
||||
|
|
@ -62,7 +61,7 @@
|
|||
"examples:start": "NODE_ENV=development npm run build && bun examples/run-all.ts start",
|
||||
"examples:dev": "NODE_ENV=development bun examples/run-all.ts dev",
|
||||
"watch": "nodemon --watch src --ext ts,tsx --exec 'bun build.bun.ts'",
|
||||
"prepare": "node scripts/setup-bun.mjs && npm run build && husky",
|
||||
"prepare": "npm run build && husky",
|
||||
"docs": "typedoc",
|
||||
"docs:watch": "typedoc --watch",
|
||||
"generate:screenshots": "npm run build:all && docker run --rm -e EXAMPLE -v $(pwd):/work -w /work mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'apt-get update -qq && apt-get install -qq -y python3-venv curl > /dev/null && curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH=\"$HOME/.local/bin:$PATH\" && npm i -g bun && npm ci && npx playwright test tests/e2e/generate-grid-screenshots.spec.ts'",
|
||||
|
|
@ -101,6 +100,7 @@
|
|||
"typedoc": "^0.28.14",
|
||||
"typedoc-github-theme": "^0.4.0",
|
||||
"typescript": "^5.9.3",
|
||||
"bun": "^1.2.21",
|
||||
"zod": "^4.1.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -117,25 +117,6 @@
|
|||
"optional": true
|
||||
}
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oven/bun-darwin-aarch64": "^1.2.21",
|
||||
"@oven/bun-darwin-x64": "^1.2.21",
|
||||
"@oven/bun-darwin-x64-baseline": "^1.2.21",
|
||||
"@oven/bun-linux-aarch64": "^1.2.21",
|
||||
"@oven/bun-linux-aarch64-musl": "^1.2.21",
|
||||
"@oven/bun-linux-x64": "^1.2.21",
|
||||
"@oven/bun-linux-x64-baseline": "^1.2.21",
|
||||
"@oven/bun-linux-x64-musl": "^1.2.21",
|
||||
"@oven/bun-linux-x64-musl-baseline": "^1.2.21",
|
||||
"@oven/bun-windows-x64": "^1.2.21",
|
||||
"@oven/bun-windows-x64-baseline": "^1.2.21",
|
||||
"@rollup/rollup-darwin-arm64": "^4.53.3",
|
||||
"@rollup/rollup-darwin-x64": "^4.53.3",
|
||||
"@rollup/rollup-linux-arm64-gnu": "^4.53.3",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.53.3",
|
||||
"@rollup/rollup-win32-arm64-msvc": "^4.53.3",
|
||||
"@rollup/rollup-win32-x64-msvc": "^4.53.3"
|
||||
},
|
||||
"overrides": {
|
||||
"seroval": "1.4.1",
|
||||
"seroval-plugins": "1.4.2",
|
||||
|
|
|
|||
|
|
@ -1,377 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
// Immediate log to verify script execution
|
||||
console.log("[setup-bun] Script loaded");
|
||||
|
||||
/**
|
||||
* Postinstall script to set up bun from platform-specific optional dependencies.
|
||||
* Handles Windows ARM64 by downloading x64-baseline via emulation.
|
||||
*/
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
symlinkSync,
|
||||
unlinkSync,
|
||||
copyFileSync,
|
||||
chmodSync,
|
||||
writeFileSync,
|
||||
statSync,
|
||||
} from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { spawnSync } from "child_process";
|
||||
import { fileURLToPath } from "url";
|
||||
import { get } from "https";
|
||||
import { createGunzip } from "zlib";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = join(__dirname, "..");
|
||||
const nodeModules = join(projectRoot, "node_modules");
|
||||
const binDir = join(nodeModules, ".bin");
|
||||
|
||||
const os = process.platform;
|
||||
const arch = process.arch;
|
||||
const isWindows = os === "win32";
|
||||
const bunExe = isWindows ? "bun.exe" : "bun";
|
||||
|
||||
// Detect libc type on Linux (glibc vs musl)
|
||||
function detectLibc() {
|
||||
if (os !== "linux") return null;
|
||||
|
||||
// Check for musl-specific loader
|
||||
const muslLoaders = [
|
||||
`/lib/ld-musl-${arch === "arm64" ? "aarch64" : "x86_64"}.so.1`,
|
||||
"/lib/ld-musl-x86_64.so.1",
|
||||
"/lib/ld-musl-aarch64.so.1",
|
||||
];
|
||||
|
||||
for (const loader of muslLoaders) {
|
||||
if (existsSync(loader)) {
|
||||
console.log(` Detected musl libc (found ${loader})`);
|
||||
return "musl";
|
||||
}
|
||||
}
|
||||
|
||||
// Default to glibc on Linux
|
||||
console.log(" Detected glibc (no musl loader found)");
|
||||
return "glibc";
|
||||
}
|
||||
|
||||
// Platform to package mapping (matches @oven/bun-* package names)
|
||||
// For Linux, separate glibc and musl packages
|
||||
const platformPackages = {
|
||||
darwin: {
|
||||
arm64: ["bun-darwin-aarch64"],
|
||||
x64: ["bun-darwin-x64", "bun-darwin-x64-baseline"],
|
||||
},
|
||||
linux: {
|
||||
arm64: {
|
||||
glibc: ["bun-linux-aarch64"],
|
||||
musl: ["bun-linux-aarch64-musl"],
|
||||
},
|
||||
x64: {
|
||||
glibc: ["bun-linux-x64", "bun-linux-x64-baseline"],
|
||||
musl: ["bun-linux-x64-musl", "bun-linux-x64-musl-baseline"],
|
||||
},
|
||||
},
|
||||
win32: {
|
||||
x64: ["bun-windows-x64", "bun-windows-x64-baseline"],
|
||||
arm64: ["bun-windows-x64-baseline"], // x64 runs via emulation on ARM64
|
||||
},
|
||||
};
|
||||
|
||||
function findBunBinary() {
|
||||
let packages = platformPackages[os]?.[arch];
|
||||
|
||||
// For Linux, select packages based on libc type
|
||||
if (os === "linux" && packages && typeof packages === "object") {
|
||||
const libc = detectLibc();
|
||||
packages = packages[libc] || [];
|
||||
}
|
||||
|
||||
packages = packages || [];
|
||||
console.log(
|
||||
`Looking for bun packages: ${packages.join(", ") || "(none for this platform)"}`,
|
||||
);
|
||||
|
||||
for (const pkg of packages) {
|
||||
const binPath = join(nodeModules, "@oven", pkg, "bin", bunExe);
|
||||
console.log(` Checking: ${binPath}`);
|
||||
if (existsSync(binPath)) {
|
||||
console.log(` Found bun at: ${binPath}`);
|
||||
return binPath;
|
||||
} else {
|
||||
console.log(` Not found`);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function downloadBunForWindowsArm64() {
|
||||
// Windows ARM64 can run x64 binaries via emulation
|
||||
const pkg = "bun-windows-x64-baseline";
|
||||
const version = "1.2.21";
|
||||
const url = `https://registry.npmjs.org/@oven/${pkg}/-/${pkg}-${version}.tgz`;
|
||||
const destDir = join(nodeModules, "@oven", pkg);
|
||||
|
||||
console.log(`Downloading ${pkg} for Windows ARM64 emulation...`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
get(url, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
get(response.headers.location, handleResponse).on("error", reject);
|
||||
} else {
|
||||
handleResponse(response);
|
||||
}
|
||||
|
||||
function handleResponse(res) {
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`Failed to download: ${res.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
const chunks = [];
|
||||
const gunzip = createGunzip();
|
||||
|
||||
res.pipe(gunzip);
|
||||
|
||||
gunzip.on("data", (chunk) => chunks.push(chunk));
|
||||
gunzip.on("end", () => {
|
||||
try {
|
||||
extractTar(Buffer.concat(chunks), destDir);
|
||||
const binPath = join(destDir, "bin", bunExe);
|
||||
if (existsSync(binPath)) {
|
||||
resolve(binPath);
|
||||
} else {
|
||||
reject(new Error("Binary not found after extraction"));
|
||||
}
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
gunzip.on("error", reject);
|
||||
}
|
||||
}).on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
function extractTar(buffer, destDir) {
|
||||
// Simple tar extraction (512-byte blocks)
|
||||
let offset = 0;
|
||||
while (offset < buffer.length) {
|
||||
const name = buffer
|
||||
.toString("utf-8", offset, offset + 100)
|
||||
.replace(/\0.*$/, "")
|
||||
.replace("package/", "");
|
||||
const size = parseInt(
|
||||
buffer.toString("utf-8", offset + 124, offset + 136).trim(),
|
||||
8,
|
||||
);
|
||||
|
||||
offset += 512;
|
||||
|
||||
if (!isNaN(size) && size > 0 && name) {
|
||||
const filePath = join(destDir, name);
|
||||
const fileDir = dirname(filePath);
|
||||
if (!existsSync(fileDir)) {
|
||||
mkdirSync(fileDir, { recursive: true });
|
||||
}
|
||||
const content = buffer.subarray(offset, offset + size);
|
||||
writeFileSync(filePath, content);
|
||||
|
||||
// Make executable
|
||||
if (name.endsWith(bunExe) || name === "bin/bun") {
|
||||
try {
|
||||
chmodSync(filePath, 0o755);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
offset += Math.ceil(size / 512) * 512;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copyFileWithRetry(source, dest, maxRetries = 3, delay = 100) {
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
copyFileSync(source, dest);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (attempt === maxRetries) {
|
||||
throw err;
|
||||
}
|
||||
// Wait a bit before retrying (exponential backoff)
|
||||
const waitTime = delay * Math.pow(2, attempt - 1);
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < waitTime) {
|
||||
// Busy wait (simple delay without external dependencies)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setupBinLink(bunPath) {
|
||||
if (!existsSync(binDir)) {
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
}
|
||||
|
||||
const bunLink = join(binDir, bunExe);
|
||||
const bunxLink = join(binDir, isWindows ? "bunx.exe" : "bunx");
|
||||
|
||||
// Check if files already exist and are valid (same size as source)
|
||||
// This can help avoid unnecessary copy operations that might fail
|
||||
let needsCopy = true;
|
||||
if (existsSync(bunLink) && existsSync(bunxLink)) {
|
||||
try {
|
||||
const sourceStat = statSync(bunPath);
|
||||
const linkStat = statSync(bunLink);
|
||||
if (sourceStat.size === linkStat.size) {
|
||||
console.log(
|
||||
"Bun binaries already exist and appear valid, skipping copy",
|
||||
);
|
||||
needsCopy = false;
|
||||
}
|
||||
} catch {
|
||||
// If stat fails, proceed with copy
|
||||
needsCopy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsCopy) {
|
||||
// Remove existing links
|
||||
for (const link of [bunLink, bunxLink]) {
|
||||
try {
|
||||
unlinkSync(link);
|
||||
} catch {}
|
||||
}
|
||||
} else {
|
||||
console.log(`Bun linked to: ${bunLink}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWindows) {
|
||||
// On Windows, copy the binary (symlinks may not work without admin)
|
||||
// Use retry logic to handle file locking issues
|
||||
try {
|
||||
copyFileWithRetry(bunPath, bunLink);
|
||||
copyFileWithRetry(bunPath, bunxLink);
|
||||
} catch (err) {
|
||||
// If copy fails, try using Windows copy command as fallback
|
||||
console.log(`Copy failed, trying Windows copy command: ${err.message}`);
|
||||
try {
|
||||
if (isWindows) {
|
||||
// Use cmd /c copy for Windows with proper path quoting
|
||||
// Paths with spaces need to be quoted, and we need to handle backslashes
|
||||
const sourceQuoted = `"${bunPath}"`;
|
||||
const destQuoted = `"${bunLink}"`;
|
||||
const destxQuoted = `"${bunxLink}"`;
|
||||
|
||||
// Try copying with a small delay between attempts
|
||||
const result1 = spawnSync(
|
||||
"cmd.exe",
|
||||
["/c", "copy", "/Y", sourceQuoted, destQuoted],
|
||||
{ shell: false, stdio: "pipe" },
|
||||
);
|
||||
|
||||
// Small delay before second copy
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < 50) {}
|
||||
|
||||
const result2 = spawnSync(
|
||||
"cmd.exe",
|
||||
["/c", "copy", "/Y", sourceQuoted, destxQuoted],
|
||||
{ shell: false, stdio: "pipe" },
|
||||
);
|
||||
|
||||
if (result1.status !== 0) {
|
||||
const errorMsg =
|
||||
result1.stderr?.toString() ||
|
||||
result1.stdout?.toString() ||
|
||||
"Unknown error";
|
||||
throw new Error(
|
||||
`Windows copy command failed for bun.exe: ${errorMsg}`,
|
||||
);
|
||||
}
|
||||
if (result2.status !== 0) {
|
||||
const errorMsg =
|
||||
result2.stderr?.toString() ||
|
||||
result2.stdout?.toString() ||
|
||||
"Unknown error";
|
||||
throw new Error(
|
||||
`Windows copy command failed for bunx.exe: ${errorMsg}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Verify files were created
|
||||
if (!existsSync(bunLink) || !existsSync(bunxLink)) {
|
||||
throw new Error("Files were not created after copy command");
|
||||
}
|
||||
} else {
|
||||
// Fallback to original copyFileSync if not Windows
|
||||
copyFileSync(bunPath, bunLink);
|
||||
copyFileSync(bunPath, bunxLink);
|
||||
}
|
||||
} catch (fallbackErr) {
|
||||
// If all copy methods fail, log the error but don't throw
|
||||
// The script will exit gracefully and bun can be installed manually
|
||||
console.error(
|
||||
`All copy methods failed. Bun setup incomplete: ${fallbackErr.message}`,
|
||||
);
|
||||
console.error(
|
||||
"You may need to install bun manually or run this script with appropriate permissions.",
|
||||
);
|
||||
throw fallbackErr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// On Unix, use symlinks
|
||||
symlinkSync(bunPath, bunLink);
|
||||
symlinkSync(bunPath, bunxLink);
|
||||
}
|
||||
|
||||
console.log(`Bun linked to: ${bunLink}`);
|
||||
}
|
||||
|
||||
// Force immediate output
|
||||
process.stdout.write("[setup-bun] Script starting...\n");
|
||||
|
||||
async function main() {
|
||||
process.stdout.write(`[setup-bun] Setting up bun for ${os} ${arch}...\n`);
|
||||
process.stdout.write(`[setup-bun] Project root: ${projectRoot}\n`);
|
||||
process.stdout.write(`[setup-bun] Node modules: ${nodeModules}\n`);
|
||||
|
||||
let bunPath = findBunBinary();
|
||||
|
||||
if (!bunPath && os === "win32" && arch === "arm64") {
|
||||
try {
|
||||
bunPath = await downloadBunForWindowsArm64();
|
||||
} catch (err) {
|
||||
console.error("Failed to download bun for Windows ARM64:", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bunPath) {
|
||||
console.log("No bun binary found in optional dependencies.");
|
||||
console.log("Bun will need to be installed separately.");
|
||||
console.log("See: https://bun.sh/docs/installation");
|
||||
process.exit(0); // Don't fail the install
|
||||
}
|
||||
|
||||
try {
|
||||
setupBinLink(bunPath);
|
||||
|
||||
// Verify installation
|
||||
const result = spawnSync(bunPath, ["--version"], { encoding: "utf-8" });
|
||||
if (result.status === 0) {
|
||||
console.log(`Bun ${result.stdout.trim()} installed successfully!`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to set up bun:", err.message);
|
||||
process.exit(0); // Don't fail the install
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(0); // Don't fail the install
|
||||
});
|
||||
Loading…
Reference in a new issue