Update dependencies and enhance build scripts for Electrobun
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
- Updated `electrobun` dependency to version `1.18.4-beta.19` in `package.json` and `bun.lock`. - Added `rcedit` and `@tweenjs/tween.js` dependencies to `bun.lock`. - Modified `Jenkinsfile` to clean up additional staging directories for production builds. - Refactored `electrobun.config.ts` to dynamically read the `package.json` path. - Introduced new scripts for managing Hutch installation and execution, improving the build process. - Enhanced artifact finalization logic to support multiple build environments and streamline platform directory resolution.
This commit is contained in:
parent
e81bc235a8
commit
6690516be3
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -100,7 +100,7 @@ def prepareMacBuildWorkspace() {
|
|||||||
hdiutil detach "$vol" -force || true
|
hdiutil detach "$vol" -force || true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
rm -rf build/stable-macos-*/.dmg-staging build/stable-macos-*/.finalize-dmg-staging 2>/dev/null || true
|
rm -rf build/stable-macos-*/.dmg-staging build/stable-macos-*/.finalize-dmg-staging build/production-macos-*/.dmg-staging build/production-macos-*/.finalize-dmg-staging 2>/dev/null || true
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
bun.lock
15
bun.lock
@ -77,7 +77,7 @@
|
|||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
"@vitejs/plugin-react": "^5.0.2",
|
"@vitejs/plugin-react": "^5.0.2",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.2.1",
|
||||||
"electrobun": "^1.18.1",
|
"electrobun": "1.18.4-beta.19",
|
||||||
"electron": "^38.7.1",
|
"electron": "^38.7.1",
|
||||||
"electron-builder": "^26.0.12",
|
"electron-builder": "^26.0.12",
|
||||||
"electron-packager": "^17.1.2",
|
"electron-packager": "^17.1.2",
|
||||||
@ -93,6 +93,7 @@
|
|||||||
"png-to-ico": "^2.1.8",
|
"png-to-ico": "^2.1.8",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-eslint": "^16.4.2",
|
"prettier-eslint": "^16.4.2",
|
||||||
|
"rcedit": "^4.0.1",
|
||||||
"rollup-plugin-visualizer": "^6.0.5",
|
"rollup-plugin-visualizer": "^6.0.5",
|
||||||
"serve": "^14.2.4",
|
"serve": "^14.2.4",
|
||||||
"standard": "^17.1.2",
|
"standard": "^17.1.2",
|
||||||
@ -837,6 +838,8 @@
|
|||||||
|
|
||||||
"@tsparticles/updater-wobble": ["@tsparticles/updater-wobble@3.9.1", "", { "dependencies": { "@tsparticles/engine": "3.9.1" } }, "sha512-c99Ogy9q4QWO+zsDXol0UnpUwZiY2UucFb8ltuDv9AlbGUeprygoub8jhgT5pEDv+GdzWOJGSgq7rfgv9cHBrg=="],
|
"@tsparticles/updater-wobble": ["@tsparticles/updater-wobble@3.9.1", "", { "dependencies": { "@tsparticles/engine": "3.9.1" } }, "sha512-c99Ogy9q4QWO+zsDXol0UnpUwZiY2UucFb8ltuDv9AlbGUeprygoub8jhgT5pEDv+GdzWOJGSgq7rfgv9cHBrg=="],
|
||||||
|
|
||||||
|
"@tweenjs/tween.js": ["@tweenjs/tween.js@23.1.3", "", {}, "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="],
|
||||||
|
|
||||||
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "7.29.0", "@babel/types": "7.29.0", "@types/babel__generator": "7.27.0", "@types/babel__template": "7.4.4", "@types/babel__traverse": "7.28.0" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "7.29.0", "@babel/types": "7.29.0", "@types/babel__generator": "7.27.0", "@types/babel__template": "7.4.4", "@types/babel__traverse": "7.28.0" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||||
|
|
||||||
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "7.29.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "7.29.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
||||||
@ -907,12 +910,18 @@
|
|||||||
|
|
||||||
"@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="],
|
"@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="],
|
||||||
|
|
||||||
|
"@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="],
|
||||||
|
|
||||||
"@types/stylis": ["@types/stylis@4.2.7", "", {}, "sha512-VgDNokpBoKF+wrdvhAAfS55OMQpL6QRglwTwNC3kIgBrzZxA4WsFj+2eLfEA/uMUDzBcEhYmjSbwQakn/i3ajA=="],
|
"@types/stylis": ["@types/stylis@4.2.7", "", {}, "sha512-VgDNokpBoKF+wrdvhAAfS55OMQpL6QRglwTwNC3kIgBrzZxA4WsFj+2eLfEA/uMUDzBcEhYmjSbwQakn/i3ajA=="],
|
||||||
|
|
||||||
|
"@types/three": ["@types/three@0.165.0", "", { "dependencies": { "@tweenjs/tween.js": "~23.1.1", "@types/stats.js": "*", "@types/webxr": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.18.1" } }, "sha512-AJK8JZAFNBF0kBXiAIl5pggYlzAGGA8geVYQXAcPCEDRbyA+oEjkpUBcJJrtNz6IiALwzGexFJGZG2yV3WsYBw=="],
|
||||||
|
|
||||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||||
|
|
||||||
"@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
|
"@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
|
||||||
|
|
||||||
|
"@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="],
|
||||||
|
|
||||||
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@6.21.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "4.4.3" }, "optionalDependencies": { "typescript": "5.9.3" }, "peerDependencies": { "eslint": "8.57.1" } }, "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ=="],
|
"@typescript-eslint/parser": ["@typescript-eslint/parser@6.21.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "4.4.3" }, "optionalDependencies": { "typescript": "5.9.3" }, "peerDependencies": { "eslint": "8.57.1" } }, "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ=="],
|
||||||
@ -1307,7 +1316,7 @@
|
|||||||
|
|
||||||
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
||||||
|
|
||||||
"electrobun": ["electrobun@1.18.1", "", { "dependencies": { "@babylonjs/core": "^7.45.0", "@types/bun": "^1.3.8", "png-to-ico": "^2.1.8", "proxy-agent": "^6.5.0", "rcedit": "^4.0.1", "three": "^0.165.0" }, "bin": { "electrobun": "bin/electrobun.cjs" } }, "sha512-tgZ+WKGskn/1/Y5i1mpVCCkgRa1O31Tz7MIArBTK44GfPzT43uOq9c/HvxdQGrLeZV8ZvjK1lQrwqSXCgh6tvA=="],
|
"electrobun": ["electrobun@1.18.4-beta.19", "", { "dependencies": { "@babylonjs/core": "^7.45.0", "@types/bun": "^1.3.8", "@types/three": "^0.165.0", "png-to-ico": "^2.1.8", "proxy-agent": "^6.5.0", "rcedit": "^4.0.1", "three": "^0.165.0" }, "bin": { "electrobun": "bin/electrobun.cjs" } }, "sha512-u8/Zhcn9ml3U0zxWUnCm09mmri6z0gnwjGG3b4K45kaugpbJww5VQ/YkhVzms/tRhyj8MiRY/HOHZppFDtBkTw=="],
|
||||||
|
|
||||||
"electron": ["electron@38.8.6", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-lyBhcVi9QYAZL6FO6r5twAWAjWnYomo3iVDvrb5SJZlq928BGemHOKG0tPIq41NOLaCu9f3XdEEjMkjQPjprRg=="],
|
"electron": ["electron@38.8.6", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-lyBhcVi9QYAZL6FO6r5twAWAjWnYomo3iVDvrb5SJZlq928BGemHOKG0tPIq41NOLaCu9f3XdEEjMkjQPjprRg=="],
|
||||||
|
|
||||||
@ -1855,6 +1864,8 @@
|
|||||||
|
|
||||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||||
|
|
||||||
|
"meshoptimizer": ["meshoptimizer@0.18.1", "", {}, "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw=="],
|
||||||
|
|
||||||
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "4.1.12", "debug": "4.4.3", "decode-named-character-reference": "1.3.0", "devlop": "1.1.0", "micromark-core-commonmark": "2.0.3", "micromark-factory-space": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-combine-extensions": "2.0.1", "micromark-util-decode-numeric-character-reference": "2.0.2", "micromark-util-encode": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-sanitize-uri": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
|
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "4.1.12", "debug": "4.4.3", "decode-named-character-reference": "1.3.0", "devlop": "1.1.0", "micromark-core-commonmark": "2.0.3", "micromark-factory-space": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-combine-extensions": "2.0.1", "micromark-util-decode-numeric-character-reference": "2.0.2", "micromark-util-encode": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-sanitize-uri": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
|
||||||
|
|
||||||
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "1.3.0", "devlop": "1.1.0", "micromark-factory-destination": "2.0.1", "micromark-factory-label": "2.0.1", "micromark-factory-space": "2.0.1", "micromark-factory-title": "2.0.1", "micromark-factory-whitespace": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-classify-character": "2.0.1", "micromark-util-html-tag-name": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
|
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "1.3.0", "devlop": "1.1.0", "micromark-factory-destination": "2.0.1", "micromark-factory-label": "2.0.1", "micromark-factory-space": "2.0.1", "micromark-factory-title": "2.0.1", "micromark-factory-whitespace": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-classify-character": "2.0.1", "micromark-util-html-tag-name": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import type { ElectrobunConfig } from "electrobun";
|
import type { ElectrobunConfig } from "electrobun";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
|
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const packageJson = JSON.parse(
|
||||||
|
readFileSync(path.join(rootDir, "package.json"), "utf8"),
|
||||||
|
);
|
||||||
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
|
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
|
||||||
const isStable = buildEnv === "stable";
|
const isStable = buildEnv === "stable";
|
||||||
const canCodesign = Boolean(process.env.ELECTROBUN_DEVELOPER_ID);
|
const canCodesign = Boolean(process.env.ELECTROBUN_DEVELOPER_ID);
|
||||||
@ -29,6 +34,7 @@ export default {
|
|||||||
exitOnLastWindowClosed: true,
|
exitOnLastWindowClosed: true,
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
|
mainProcess: "bun",
|
||||||
buildFolder: "build",
|
buildFolder: "build",
|
||||||
artifactFolder: "app_dist",
|
artifactFolder: "app_dist",
|
||||||
// macOS WebKit loads views:// assets reliably from a flat app folder;
|
// macOS WebKit loads views:// assets reliably from a flat app folder;
|
||||||
|
|||||||
@ -80,12 +80,12 @@
|
|||||||
"description": "3D Printer ERP and Control Software.",
|
"description": "3D Printer ERP and Control Software.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=development vite",
|
"dev": "cross-env NODE_ENV=development vite",
|
||||||
"dev:app": "concurrently \"cross-env NODE_ENV=development bun run dev:renderer\" \"cross-env NODE_ENV=development electrobun dev\"",
|
"dev:app": "concurrently \"cross-env NODE_ENV=development bun run dev:renderer\" \"cross-env NODE_ENV=development bun scripts/run-hutch-electrobun.mjs dev\"",
|
||||||
"dev:renderer": "vite --port 5780 --no-open",
|
"dev:renderer": "vite --port 5780 --no-open",
|
||||||
"electron": "cross-env ELECTRON_START_URL=http://0.0.0.0:5780 && cross-env NODE_ENV=development && electron .",
|
"electron": "cross-env ELECTRON_START_URL=http://0.0.0.0:5780 && cross-env NODE_ENV=development && electron .",
|
||||||
"start": "serve -s build",
|
"start": "serve -s build",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"build:app": "electrobun build --env=stable",
|
"build:app": "bun scripts/run-hutch-electrobun.mjs build --env=stable",
|
||||||
"build:app:mac": "bun scripts/build-macos.mjs",
|
"build:app:mac": "bun scripts/build-macos.mjs",
|
||||||
"dev:electron": "concurrently \"cross-env NODE_ENV=development vite --port 5780 --no-open\" \"cross-env ELECTRON_START_URL=http://localhost:5780 NODE_ENV=development electron public/electron.js\"",
|
"dev:electron": "concurrently \"cross-env NODE_ENV=development vite --port 5780 --no-open\" \"cross-env ELECTRON_START_URL=http://localhost:5780 NODE_ENV=development electron public/electron.js\"",
|
||||||
"build:electron": "vite build && electron-builder",
|
"build:electron": "vite build && electron-builder",
|
||||||
@ -118,7 +118,7 @@
|
|||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
"@vitejs/plugin-react": "^5.0.2",
|
"@vitejs/plugin-react": "^5.0.2",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.2.1",
|
||||||
"electrobun": "^1.18.1",
|
"electrobun": "1.18.4-beta.19",
|
||||||
"electron": "^38.7.1",
|
"electron": "^38.7.1",
|
||||||
"jimp": "^1.6.1",
|
"jimp": "^1.6.1",
|
||||||
"png-to-ico": "^2.1.8",
|
"png-to-ico": "^2.1.8",
|
||||||
@ -134,6 +134,7 @@
|
|||||||
"globals": "^15.12.0",
|
"globals": "^15.12.0",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-eslint": "^16.4.2",
|
"prettier-eslint": "^16.4.2",
|
||||||
|
"rcedit": "^4.0.1",
|
||||||
"rollup-plugin-visualizer": "^6.0.5",
|
"rollup-plugin-visualizer": "^6.0.5",
|
||||||
"serve": "^14.2.4",
|
"serve": "^14.2.4",
|
||||||
"standard": "^17.1.2",
|
"standard": "^17.1.2",
|
||||||
|
|||||||
127
scripts/ensure-hutch.mjs
Normal file
127
scripts/ensure-hutch.mjs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||||
|
import { get } from "node:https";
|
||||||
|
import { homedir, platform, tmpdir } from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import {
|
||||||
|
getElectrobunVersion,
|
||||||
|
hutchIsInstalled,
|
||||||
|
resolveHutchCommand,
|
||||||
|
} from "./resolve-hutch-command.mjs";
|
||||||
|
|
||||||
|
const installerBaseUrl = "https://hutch.blackboard.sh/hutch";
|
||||||
|
const maxInstallerBytes = 1024 * 1024;
|
||||||
|
|
||||||
|
function download(url, redirects = 0) {
|
||||||
|
if (redirects > 5) {
|
||||||
|
return Promise.reject(new Error("too many installer redirects"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = get(url, (response) => {
|
||||||
|
if (
|
||||||
|
response.statusCode >= 300 &&
|
||||||
|
response.statusCode < 400 &&
|
||||||
|
response.headers.location
|
||||||
|
) {
|
||||||
|
response.resume();
|
||||||
|
resolve(
|
||||||
|
download(new URL(response.headers.location, url).href, redirects + 1),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
response.resume();
|
||||||
|
reject(
|
||||||
|
new Error(`installer download returned HTTP ${response.statusCode}`),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
let size = 0;
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
size += chunk.length;
|
||||||
|
if (size > maxInstallerBytes) {
|
||||||
|
request.destroy(new Error("installer download exceeded 1 MiB"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
response.on("end", () => resolve(Buffer.concat(chunks)));
|
||||||
|
});
|
||||||
|
request.on("error", reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkedSpawn(command, args, options) {
|
||||||
|
const result = spawnSync(command, args, options);
|
||||||
|
if (result.error) {
|
||||||
|
throw result.error;
|
||||||
|
}
|
||||||
|
if (result.status !== 0) {
|
||||||
|
throw new Error(`${command} exited with status ${result.status ?? "unknown"}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function installHutch(channel) {
|
||||||
|
const temporary = mkdtempSync(path.join(tmpdir(), "electrobun-hutch-"));
|
||||||
|
try {
|
||||||
|
if (platform() === "win32") {
|
||||||
|
const installer = path.join(temporary, "install.ps1");
|
||||||
|
writeFileSync(installer, await download(`${installerBaseUrl}/install.ps1`));
|
||||||
|
checkedSpawn(
|
||||||
|
"powershell.exe",
|
||||||
|
[
|
||||||
|
"-NoProfile",
|
||||||
|
"-NonInteractive",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
installer,
|
||||||
|
"-Channel",
|
||||||
|
channel,
|
||||||
|
],
|
||||||
|
{ env: process.env, stdio: "inherit" },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const installer = path.join(temporary, "install.sh");
|
||||||
|
writeFileSync(installer, await download(`${installerBaseUrl}/install.sh`), {
|
||||||
|
mode: 0o700,
|
||||||
|
});
|
||||||
|
checkedSpawn("sh", [installer, "--channel", channel, "--no-modify-path"], {
|
||||||
|
env: process.env,
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
rmSync(temporary, { force: true, recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const command = resolveHutchCommand();
|
||||||
|
if (hutchIsInstalled(command)) {
|
||||||
|
console.log(`ensure-hutch: ${command} already present`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = getElectrobunVersion();
|
||||||
|
const channel = version.includes("-") ? "canary" : "production";
|
||||||
|
|
||||||
|
if (process.env.ELECTROBUN_HUTCH_BINARY) {
|
||||||
|
console.error(`ensure-hutch: ELECTROBUN_HUTCH_BINARY does not exist: ${command}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(
|
||||||
|
`ensure-hutch: installing Hutch ${channel} for electrobun ${version}...`,
|
||||||
|
);
|
||||||
|
await installHutch(channel);
|
||||||
|
|
||||||
|
if (!existsSync(command)) {
|
||||||
|
console.error(`ensure-hutch: Hutch was not installed at ${command}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`ensure-hutch: ${command} ready`);
|
||||||
@ -14,6 +14,8 @@ import {
|
|||||||
getReleaseArch,
|
getReleaseArch,
|
||||||
getReleaseArtifactName,
|
getReleaseArtifactName,
|
||||||
getReleaseVersion,
|
getReleaseVersion,
|
||||||
|
getElectrobunOutputEnvName,
|
||||||
|
getElectrobunPlatformDirCandidates,
|
||||||
isBundleCefEnabled
|
isBundleCefEnabled
|
||||||
} from './release-artifact-utils.mjs'
|
} from './release-artifact-utils.mjs'
|
||||||
import {
|
import {
|
||||||
@ -59,13 +61,29 @@ function getBuildRoot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const baseName = path.basename(electrobunBuildDir)
|
const baseName = path.basename(electrobunBuildDir)
|
||||||
if (baseName.startsWith('stable-')) {
|
if (/^(stable|production|dev|canary)-/.test(baseName)) {
|
||||||
return path.dirname(electrobunBuildDir)
|
return path.dirname(electrobunBuildDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
return electrobunBuildDir
|
return electrobunBuildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolvePlatformDir(os, arch) {
|
||||||
|
const buildRoot = getBuildRoot()
|
||||||
|
|
||||||
|
for (const candidate of getElectrobunPlatformDirCandidates(os, arch, buildEnv)) {
|
||||||
|
const platformDir = path.join(buildRoot, candidate)
|
||||||
|
if (existsSync(platformDir)) {
|
||||||
|
return platformDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.join(
|
||||||
|
buildRoot,
|
||||||
|
`${getElectrobunOutputEnvName(buildEnv)}-${os}-${arch}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function walkFiles(dir) {
|
function walkFiles(dir) {
|
||||||
const files = []
|
const files = []
|
||||||
if (!existsSync(dir)) {
|
if (!existsSync(dir)) {
|
||||||
@ -92,7 +110,7 @@ function findByExtension(root, extension) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findMacAppBundle(arch) {
|
function findMacAppBundle(arch) {
|
||||||
const platformDir = path.join(getBuildRoot(), `stable-macos-${arch}`)
|
const platformDir = resolvePlatformDir('macos', arch)
|
||||||
if (!existsSync(platformDir)) {
|
if (!existsSync(platformDir)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -107,19 +125,19 @@ function findMacAppBundle(arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findMacDmgSource(arch) {
|
function findMacDmgSource(arch) {
|
||||||
|
const platformDir = resolvePlatformDir('macos', arch)
|
||||||
|
const platformDirName = path.basename(platformDir)
|
||||||
|
|
||||||
const prefixedArtifact = walkFiles(artifactDir).find(
|
const prefixedArtifact = walkFiles(artifactDir).find(
|
||||||
(filePath) =>
|
(filePath) =>
|
||||||
filePath.includes(`stable-macos-${arch}`) &&
|
filePath.includes(platformDirName) &&
|
||||||
filePath.toLowerCase().endsWith('.dmg')
|
filePath.toLowerCase().endsWith('.dmg')
|
||||||
)
|
)
|
||||||
if (prefixedArtifact) {
|
if (prefixedArtifact) {
|
||||||
return prefixedArtifact
|
return prefixedArtifact
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildDmg = findByExtension(
|
const buildDmg = findByExtension(platformDir, '.dmg')
|
||||||
path.join(getBuildRoot(), `stable-macos-${arch}`),
|
|
||||||
'.dmg'
|
|
||||||
)
|
|
||||||
if (buildDmg) {
|
if (buildDmg) {
|
||||||
return buildDmg
|
return buildDmg
|
||||||
}
|
}
|
||||||
@ -134,7 +152,7 @@ function findWindowsInstallerFiles() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const entry of readdirSync(buildRoot)) {
|
for (const entry of readdirSync(buildRoot)) {
|
||||||
if (!entry.startsWith('stable-win-')) {
|
if (!/^(stable|production|dev|canary)-win-/.test(entry)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +201,9 @@ function cleanStagingArtifacts(keepNames) {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
entry.includes('stable-macos-') ||
|
entry.includes('stable-macos-') ||
|
||||||
|
entry.includes('production-macos-') ||
|
||||||
entry.includes('stable-win-') ||
|
entry.includes('stable-win-') ||
|
||||||
|
entry.includes('production-win-') ||
|
||||||
entry.endsWith('-update.json') ||
|
entry.endsWith('-update.json') ||
|
||||||
entry.endsWith('.tar.gz')
|
entry.endsWith('.tar.gz')
|
||||||
) {
|
) {
|
||||||
@ -455,7 +475,7 @@ async function buildMacDmg(appBundlePath, arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanMacBuildDir(arch) {
|
function cleanMacBuildDir(arch) {
|
||||||
const platformDir = path.join(getBuildRoot(), `stable-macos-${arch}`)
|
const platformDir = resolvePlatformDir('macos', arch)
|
||||||
if (existsSync(platformDir)) {
|
if (existsSync(platformDir)) {
|
||||||
rmSync(platformDir, { recursive: true, force: true })
|
rmSync(platformDir, { recursive: true, force: true })
|
||||||
console.log(`Removed build output ${platformDir}`)
|
console.log(`Removed build output ${platformDir}`)
|
||||||
@ -494,7 +514,7 @@ function stageWindowsDeeplinkScript(appDir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanWinBuildDir(arch) {
|
function cleanWinBuildDir(arch) {
|
||||||
const platformDir = path.join(getBuildRoot(), `stable-win-${arch}`)
|
const platformDir = resolvePlatformDir('win', arch)
|
||||||
if (existsSync(platformDir)) {
|
if (existsSync(platformDir)) {
|
||||||
rmSync(platformDir, { recursive: true, force: true })
|
rmSync(platformDir, { recursive: true, force: true })
|
||||||
console.log(`Removed build output ${platformDir}`)
|
console.log(`Removed build output ${platformDir}`)
|
||||||
|
|||||||
@ -1,350 +1,23 @@
|
|||||||
import {
|
import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
||||||
cpSync,
|
|
||||||
existsSync,
|
|
||||||
mkdirSync,
|
|
||||||
readFileSync,
|
|
||||||
writeFileSync
|
|
||||||
} from 'node:fs'
|
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||||
const electrobunDir = path.join(rootDir, 'node_modules/electrobun')
|
const electrobunDir = path.join(rootDir, 'node_modules/electrobun')
|
||||||
const sharedSrcDir = path.join(electrobunDir, 'src/shared')
|
const rceditSrc = path.join(rootDir, 'node_modules/rcedit')
|
||||||
const sharedDistDir = path.join(electrobunDir, 'dist/api/shared')
|
const rceditDest = path.join(electrobunDir, 'node_modules/rcedit')
|
||||||
|
|
||||||
if (!existsSync(sharedDistDir)) {
|
if (!existsSync(rceditSrc)) {
|
||||||
console.error('patch-electrobun-src: electrobun dist/api/shared not found')
|
console.error(
|
||||||
|
'patch-electrobun-src: rcedit not found. Install it with `bun add -d rcedit`.'
|
||||||
|
)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdirSync(sharedSrcDir, { recursive: true })
|
mkdirSync(path.join(electrobunDir, 'node_modules'), { recursive: true })
|
||||||
|
cpSync(rceditSrc, rceditDest, { recursive: true, force: true })
|
||||||
for (const fileName of [
|
|
||||||
'cef-version.ts',
|
|
||||||
'bun-version.ts',
|
|
||||||
'electrobun-version.ts',
|
|
||||||
'naming.ts',
|
|
||||||
'rpc.ts'
|
|
||||||
]) {
|
|
||||||
const source = path.join(sharedDistDir, fileName)
|
|
||||||
const destination = path.join(sharedSrcDir, fileName)
|
|
||||||
if (existsSync(source)) {
|
|
||||||
cpSync(source, destination)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const platformPatch = `import { platform, arch } from "os";
|
|
||||||
|
|
||||||
export type SupportedOS = "macos" | "win" | "linux";
|
|
||||||
export type SupportedArch = "arm64" | "x64";
|
|
||||||
|
|
||||||
const platformName = platform();
|
|
||||||
const archName = arch();
|
|
||||||
|
|
||||||
export const OS: SupportedOS = (() => {
|
|
||||||
switch (platformName) {
|
|
||||||
case "win32":
|
|
||||||
return "win";
|
|
||||||
case "darwin":
|
|
||||||
return "macos";
|
|
||||||
case "linux":
|
|
||||||
return "linux";
|
|
||||||
default:
|
|
||||||
throw new Error(\`Unsupported platform: \${platformName}\`);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
function normalizeForcedArch(value) {
|
|
||||||
if (value === "arm64" || value === "aarch64") {
|
|
||||||
return "arm64";
|
|
||||||
}
|
|
||||||
if (value === "x64" || value === "amd64") {
|
|
||||||
return "x64";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ARCH: SupportedArch = (() => {
|
|
||||||
const forcedArch = normalizeForcedArch(
|
|
||||||
process.env.ELECTROBUN_FORCE_ARCH || process.env.ELECTROBUN_TARGET_ARCH,
|
|
||||||
);
|
|
||||||
if (forcedArch) {
|
|
||||||
return forcedArch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OS === "win") {
|
|
||||||
return "x64";
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (archName) {
|
|
||||||
case "arm64":
|
|
||||||
return "arm64";
|
|
||||||
case "x64":
|
|
||||||
return "x64";
|
|
||||||
default:
|
|
||||||
throw new Error(\`Unsupported architecture: \${archName}\`);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
export const HOST_ARCH: SupportedArch = (() => {
|
|
||||||
if (OS === "win") {
|
|
||||||
return "x64";
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (archName) {
|
|
||||||
case "arm64":
|
|
||||||
return "arm64";
|
|
||||||
case "x64":
|
|
||||||
return "x64";
|
|
||||||
default:
|
|
||||||
throw new Error(\`Unsupported architecture: \${archName}\`);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
export function getPlatformOS(): SupportedOS {
|
|
||||||
return OS;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPlatformArch(): SupportedArch {
|
|
||||||
return ARCH;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
writeFileSync(path.join(sharedSrcDir, 'platform.ts'), platformPatch)
|
|
||||||
|
|
||||||
const templatesDir = path.join(electrobunDir, 'src/cli/templates')
|
|
||||||
mkdirSync(templatesDir, { recursive: true })
|
|
||||||
writeFileSync(
|
|
||||||
path.join(templatesDir, 'embedded.ts'),
|
|
||||||
`export function getTemplateNames() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTemplate(name: string) {
|
|
||||||
throw new Error(\`Template not available in patched electrobun CLI: \${name}\`);
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
const RCEDIT_RESOLVER_FN = `function resolveProjectRceditPkgPath(projectRoot) {
|
|
||||||
const candidates = [
|
|
||||||
join(projectRoot, "node_modules/rcedit/package.json"),
|
|
||||||
join(projectRoot, "node_modules/electrobun/node_modules/rcedit/package.json"),
|
|
||||||
];
|
|
||||||
for (const candidate of candidates) {
|
|
||||||
if (existsSync(candidate)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error(
|
|
||||||
"rcedit not found under " + projectRoot + ". Install rcedit in the project (bun add -d rcedit).",
|
|
||||||
);
|
|
||||||
}`
|
|
||||||
|
|
||||||
const cliPath = path.join(electrobunDir, 'src/cli/index.ts')
|
|
||||||
let cliSource = readFileSync(cliPath, 'utf8')
|
|
||||||
if (!cliSource.includes('HOST_ARCH')) {
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'import { OS, ARCH } from "../shared/platform";',
|
|
||||||
'import { OS, ARCH, HOST_ARCH } from "../shared/platform";'
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'const hostPaths = getPlatformPaths(OS, ARCH);',
|
|
||||||
'const hostPaths = getPlatformPaths(OS, HOST_ARCH);'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (!cliSource.includes('toolPaths')) {
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'const targetPaths = getPlatformPaths(currentTarget.os, currentTarget.arch);',
|
|
||||||
'const targetPaths = getPlatformPaths(currentTarget.os, currentTarget.arch);\n\t\tconst toolPaths = getPlatformPaths(currentTarget.os, ARCH !== HOST_ARCH ? HOST_ARCH : ARCH);'
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replaceAll(
|
|
||||||
'const zstdPath = targetPaths.ZSTD;',
|
|
||||||
'const zstdPath = toolPaths.ZSTD;'
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replaceAll(
|
|
||||||
'const bsdiffpath = targetPaths.BSDIFF;',
|
|
||||||
'const bsdiffpath = toolPaths.BSDIFF;'
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'zigAsarCli = join(targetPaths.BSPATCH).replace("bspatch", "zig-asar");',
|
|
||||||
'zigAsarCli = join(toolPaths.BSPATCH).replace("bspatch", "zig-asar");'
|
|
||||||
)
|
|
||||||
writeFileSync(cliPath, cliSource)
|
|
||||||
cliSource = readFileSync(cliPath, 'utf8')
|
|
||||||
}
|
|
||||||
if (!cliSource.includes('hookBunBinary')) {
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
`const hostPaths = getPlatformPaths(OS, HOST_ARCH);
|
|
||||||
|
|
||||||
const result = Bun.spawnSync([hostPaths.BUN_BINARY, hookScript],`,
|
|
||||||
`const hostPaths = getPlatformPaths(OS, HOST_ARCH);
|
|
||||||
const hookBunBinary = existsSync(hostPaths.BUN_BINARY)
|
|
||||||
? hostPaths.BUN_BINARY
|
|
||||||
: process.execPath;
|
|
||||||
|
|
||||||
const result = Bun.spawnSync([hookBunBinary, hookScript],`
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'console.error("Tried to run with bun at:", hostPaths.BUN_BINARY);',
|
|
||||||
'console.error("Tried to run with bun at:", hookBunBinary);'
|
|
||||||
)
|
|
||||||
writeFileSync(cliPath, cliSource)
|
|
||||||
cliSource = readFileSync(cliPath, 'utf8')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cliSource.includes('resolveProjectRceditPkgPath')) {
|
|
||||||
cliSource = cliSource.replaceAll(
|
|
||||||
'const rceditPkgPath = require.resolve("rcedit/package.json");',
|
|
||||||
'const rceditPkgPath = resolveProjectRceditPkgPath(projectRoot);'
|
|
||||||
)
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
'function getPlatformPaths(',
|
|
||||||
`${RCEDIT_RESOLVER_FN}
|
|
||||||
|
|
||||||
function getPlatformPaths(`
|
|
||||||
)
|
|
||||||
writeFileSync(cliPath, cliSource)
|
|
||||||
cliSource = readFileSync(cliPath, 'utf8')
|
|
||||||
} else {
|
|
||||||
cliSource = cliSource.replace(
|
|
||||||
/function resolveProjectRceditPkgPath\(projectRoot\) \{[\s\S]*?\n\}/m,
|
|
||||||
RCEDIT_RESOLVER_FN
|
|
||||||
)
|
|
||||||
writeFileSync(cliPath, cliSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
const electrobunCjsPath = path.join(electrobunDir, 'bin/electrobun.cjs')
|
|
||||||
let electrobunCjs = readFileSync(electrobunCjsPath, 'utf8')
|
|
||||||
|
|
||||||
if (!electrobunCjs.includes('farmcontrol-use-patched-cli')) {
|
|
||||||
electrobunCjs = electrobunCjs.replace(
|
|
||||||
`async function main() {
|
|
||||||
try {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
const cliPath = await ensureCliBinary();
|
|
||||||
|
|
||||||
// Replace this process with the actual CLI
|
|
||||||
const child = spawn(cliPath, args, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
cwd: process.cwd()
|
|
||||||
});`,
|
|
||||||
`async function main() {
|
|
||||||
try {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
const patchedCliPath = join(electrobunDir, 'src', 'cli', 'index.ts');
|
|
||||||
|
|
||||||
if (existsSync(patchedCliPath)) {
|
|
||||||
// farmcontrol-use-patched-cli: bundled electrobun.exe cannot resolve project rcedit
|
|
||||||
const bunBinary = process.env.BUN_INSTALL
|
|
||||||
? join(process.env.BUN_INSTALL, 'bin', 'bun' + binExt)
|
|
||||||
: 'bun';
|
|
||||||
const child = spawn(bunBinary, [patchedCliPath, ...args], {
|
|
||||||
stdio: 'inherit',
|
|
||||||
cwd: process.cwd(),
|
|
||||||
env: process.env,
|
|
||||||
shell: platform === 'win',
|
|
||||||
});
|
|
||||||
|
|
||||||
child.on('exit', (code) => {
|
|
||||||
process.exit(code || 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
child.on('error', (error) => {
|
|
||||||
console.error('Failed to start electrobun patched CLI:', error.message);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cliPath = await ensureCliBinary();
|
|
||||||
|
|
||||||
// Replace this process with the actual CLI
|
|
||||||
const child = spawn(cliPath, args, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
cwd: process.cwd()
|
|
||||||
});`
|
|
||||||
)
|
|
||||||
writeFileSync(electrobunCjsPath, electrobunCjs)
|
|
||||||
}
|
|
||||||
|
|
||||||
const rceditSrc = path.join(rootDir, 'node_modules/rcedit')
|
|
||||||
const rceditDest = path.join(electrobunDir, 'node_modules/rcedit')
|
|
||||||
if (existsSync(rceditSrc)) {
|
|
||||||
mkdirSync(path.join(electrobunDir, 'node_modules'), { recursive: true })
|
|
||||||
cpSync(rceditSrc, rceditDest, { recursive: true, force: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
function patchNativeWrapperPath(nativeTsPath) {
|
|
||||||
if (!existsSync(nativeTsPath)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let source = readFileSync(nativeTsPath, 'utf8')
|
|
||||||
|
|
||||||
if (source.includes('function resolveNativeWrapperPath()')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!source.includes('existsSync')) {
|
|
||||||
if (source.includes('import { dirname, join } from "path";')) {
|
|
||||||
source = source.replace(
|
|
||||||
'import { dirname, join } from "path";',
|
|
||||||
'import { existsSync } from "fs";\nimport { dirname, join } from "path";'
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
source = source.replace(
|
|
||||||
'import { join } from "path";',
|
|
||||||
'import { existsSync } from "fs";\nimport { dirname, join } from "path";'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if (!source.includes('dirname')) {
|
|
||||||
source = source.replace(
|
|
||||||
'import { join } from "path";',
|
|
||||||
'import { dirname, join } from "path";'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const helper = `
|
|
||||||
function resolveNativeWrapperPath() {
|
|
||||||
\tconst fileName = \`libNativeWrapper.\${suffix}\`;
|
|
||||||
\tconst candidates = [
|
|
||||||
\t\tjoin(dirname(process.execPath), fileName),
|
|
||||||
\t\tjoin(process.cwd(), fileName),
|
|
||||||
\t];
|
|
||||||
\tfor (const candidate of candidates) {
|
|
||||||
\t\tif (existsSync(candidate)) {
|
|
||||||
\t\t\treturn candidate;
|
|
||||||
\t\t}
|
|
||||||
\t}
|
|
||||||
\treturn candidates[0]!;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
source = source.replace(
|
|
||||||
'export const native = (() => {',
|
|
||||||
`${helper}\nexport const native = (() => {`
|
|
||||||
)
|
|
||||||
|
|
||||||
source = source.replace(
|
|
||||||
/const nativeWrapperPath = join\((?:dirname\(process\.execPath\)|process\.cwd\(\)), `libNativeWrapper\.\$\{suffix\}`\);/,
|
|
||||||
'const nativeWrapperPath = resolveNativeWrapperPath();'
|
|
||||||
)
|
|
||||||
|
|
||||||
writeFileSync(nativeTsPath, source)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const distDir of ['dist', 'dist-macos-arm64', 'dist-win-x64']) {
|
|
||||||
patchNativeWrapperPath(
|
|
||||||
path.join(electrobunDir, distDir, 'api/bun/proc/native.ts')
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const markerPath = path.join(electrobunDir, '.farmcontrol-electrobun-patched')
|
const markerPath = path.join(electrobunDir, '.farmcontrol-electrobun-patched')
|
||||||
writeFileSync(markerPath, `patched-at=${new Date().toISOString()}\n`)
|
writeFileSync(markerPath, `patched-at=${new Date().toISOString()}\n`)
|
||||||
|
|
||||||
console.log(
|
console.log('patch-electrobun-src: rcedit ready for electrobun builds')
|
||||||
'patch-electrobun-src: electrobun src/shared ready for cross-arch builds'
|
|
||||||
)
|
|
||||||
|
|||||||
@ -26,3 +26,26 @@ export function getReleaseArtifactName(version, arch, ext, options = {}) {
|
|||||||
const cefSuffix = cef ? "-cef" : "";
|
const cefSuffix = cef ? "-cef" : "";
|
||||||
return `farmcontrol-${version}-${arch}${cefSuffix}.${ext}`;
|
return `farmcontrol-${version}-${arch}${cefSuffix}.${ext}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getElectrobunOutputEnvName(
|
||||||
|
buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable",
|
||||||
|
) {
|
||||||
|
if (buildEnv === "stable") {
|
||||||
|
return "production";
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getElectrobunPlatformDirCandidates(
|
||||||
|
os,
|
||||||
|
arch,
|
||||||
|
buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable",
|
||||||
|
) {
|
||||||
|
const outputEnv = getElectrobunOutputEnvName(buildEnv);
|
||||||
|
return [
|
||||||
|
`${outputEnv}-${os}-${arch}`,
|
||||||
|
`stable-${os}-${arch}`,
|
||||||
|
`${buildEnv}-${os}-${arch}`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|||||||
35
scripts/resolve-hutch-command.mjs
Normal file
35
scripts/resolve-hutch-command.mjs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { existsSync, readFileSync } from "node:fs";
|
||||||
|
import { homedir, platform } from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
function hutchChannelForElectrobunVersion(version) {
|
||||||
|
return version.includes("-") ? "canary" : "production";
|
||||||
|
}
|
||||||
|
|
||||||
|
function hutchBinaryName(channel) {
|
||||||
|
const base = channel === "canary" ? "hutch-canary" : "hutch";
|
||||||
|
return platform() === "win32" ? `${base}.exe` : base;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getElectrobunVersion() {
|
||||||
|
const packageJsonPath = path.join(rootDir, "node_modules/electrobun/package.json");
|
||||||
|
return JSON.parse(readFileSync(packageJsonPath, "utf8")).version;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveHutchCommand(environment = process.env) {
|
||||||
|
if (environment.ELECTROBUN_HUTCH_BINARY) {
|
||||||
|
return environment.ELECTROBUN_HUTCH_BINARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = hutchChannelForElectrobunVersion(getElectrobunVersion());
|
||||||
|
const dashHome = environment.DASH_HOME || path.join(homedir(), ".dash");
|
||||||
|
const pathApi = platform() === "win32" ? path.win32 : path.posix;
|
||||||
|
return pathApi.join(dashHome, "bin", hutchBinaryName(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hutchIsInstalled(command = resolveHutchCommand()) {
|
||||||
|
return existsSync(command);
|
||||||
|
}
|
||||||
@ -2,12 +2,9 @@ import { spawnSync } from "node:child_process";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||||
import { getReleaseArch, isBundleCefEnabled } from "./release-artifact-utils.mjs";
|
import { getReleaseArch, isBundleCefEnabled } from "./release-artifact-utils.mjs";
|
||||||
|
import { resolveHutchCommand } from "./resolve-hutch-command.mjs";
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const electrobunCli = path.join(
|
|
||||||
rootDir,
|
|
||||||
"node_modules/electrobun/src/cli/index.ts",
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable";
|
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable";
|
||||||
const targetArch = getReleaseArch(
|
const targetArch = getReleaseArch(
|
||||||
@ -17,16 +14,21 @@ const targetArch = getReleaseArch(
|
|||||||
);
|
);
|
||||||
const bundleCef = isBundleCefEnabled();
|
const bundleCef = isBundleCefEnabled();
|
||||||
|
|
||||||
const patchResult = spawnSync("bun", [path.join(rootDir, "scripts/patch-electrobun-src.mjs")], {
|
function runScript(scriptName) {
|
||||||
cwd: rootDir,
|
const result = spawnSync("bun", [path.join(rootDir, "scripts", scriptName)], {
|
||||||
stdio: "inherit",
|
cwd: rootDir,
|
||||||
env: process.env,
|
stdio: "inherit",
|
||||||
});
|
env: process.env,
|
||||||
|
});
|
||||||
|
|
||||||
if (patchResult.status !== 0) {
|
if (result.status !== 0) {
|
||||||
process.exit(patchResult.status ?? 1);
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runScript("ensure-hutch.mjs");
|
||||||
|
runScript("patch-electrobun-src.mjs");
|
||||||
|
|
||||||
const macosEffectsResult = spawnSync(
|
const macosEffectsResult = spawnSync(
|
||||||
"bun",
|
"bun",
|
||||||
[path.join(rootDir, "scripts/build-macos-effects.mjs")],
|
[path.join(rootDir, "scripts/build-macos-effects.mjs")],
|
||||||
@ -82,13 +84,15 @@ const env = {
|
|||||||
NODE_ENV: process.env.NODE_ENV || "production",
|
NODE_ENV: process.env.NODE_ENV || "production",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hutchCommand = resolveHutchCommand(env);
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`run-electrobun-build: env=${buildEnv} os=macos arch=${targetArch} cef=${bundleCef} (host ${getReleaseArch(process.arch)})`,
|
`run-electrobun-build: env=${buildEnv} os=macos arch=${targetArch} cef=${bundleCef} (host ${getReleaseArch(process.arch)})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = spawnSync(
|
const result = spawnSync(
|
||||||
"bun",
|
hutchCommand,
|
||||||
[electrobunCli, "build", `--env=${buildEnv}`],
|
["electrobun", "build", `--env=${buildEnv}`],
|
||||||
{
|
{
|
||||||
cwd: rootDir,
|
cwd: rootDir,
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
|
|||||||
35
scripts/run-hutch-electrobun.mjs
Normal file
35
scripts/run-hutch-electrobun.mjs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { resolveHutchCommand } from "./resolve-hutch-command.mjs";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const [, , subcommand, ...rest] = process.argv;
|
||||||
|
|
||||||
|
if (!subcommand) {
|
||||||
|
console.error("usage: run-hutch-electrobun.mjs <dev|build|run> [...args]");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ensureHutch = spawnSync(
|
||||||
|
"bun",
|
||||||
|
[path.join(rootDir, "scripts/ensure-hutch.mjs")],
|
||||||
|
{ cwd: rootDir, stdio: "inherit", env: process.env },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ensureHutch.status !== 0) {
|
||||||
|
process.exit(ensureHutch.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hutchCommand = resolveHutchCommand();
|
||||||
|
const result = spawnSync(
|
||||||
|
hutchCommand,
|
||||||
|
["electrobun", subcommand, ...rest],
|
||||||
|
{
|
||||||
|
cwd: rootDir,
|
||||||
|
stdio: "inherit",
|
||||||
|
env: process.env,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
Loading…
x
Reference in New Issue
Block a user