electrobun 1.18.4-beta.18 → 1.18.4-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,15 @@ curl -fsSL https://hutch.blackboard.sh/hutch/install.sh | sh
25
25
  hutch electrobun init
26
26
  ```
27
27
 
28
+ Or bootstrap the same interactive initializer from npm or Bun. This installs
29
+ Hutch when it is not already available:
30
+
31
+ ```bash
32
+ npx electrobun init
33
+ # or
34
+ bunx electrobun init
35
+ ```
36
+
28
37
  Don't miss our:
29
38
  - self-extracting bundles that use Zstandard compression for compact distributables
30
39
  - a Zig-optimized BSDIFF implementation that can produce kilobyte-scale updates
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { existsSync, mkdtempSync, rmSync, writeFileSync } = require("node:fs");
5
+ const { get } = require("node:https");
6
+ const { homedir, tmpdir } = require("node:os");
7
+ const path = require("node:path");
8
+ const { spawnSync } = require("node:child_process");
9
+
10
+ const packageVersion = require("../package.json").version;
11
+ const installerBaseUrl = "https://hutch.blackboard.sh/hutch";
12
+ const maxInstallerBytes = 1024 * 1024;
13
+
14
+ function normalizeChannel(value) {
15
+ if (value === "stable") return "production";
16
+ if (value === "production" || value === "canary") return value;
17
+ return null;
18
+ }
19
+
20
+ function channelForVersion(version, environment) {
21
+ for (const key of ["ELECTROBUN_HUTCH_CHANNEL", "HUTCH_ACTIVE_CHANNEL"]) {
22
+ const selected = normalizeChannel(environment[key]);
23
+ if (selected) return selected;
24
+ }
25
+ return version.includes("-") ? "canary" : "production";
26
+ }
27
+
28
+ function hutchBinaryPath(channel, environment, platform, userHome) {
29
+ if (environment.ELECTROBUN_HUTCH_BINARY) {
30
+ return environment.ELECTROBUN_HUTCH_BINARY;
31
+ }
32
+ const dashHome = environment.DASH_HOME || path.join(userHome, ".dash");
33
+ const command = channel === "canary" ? "hutch-canary" : "hutch";
34
+ const pathApi = platform === "win32" ? path.win32 : path.posix;
35
+ return pathApi.join(dashHome, "bin", `${command}${platform === "win32" ? ".exe" : ""}`);
36
+ }
37
+
38
+ function download(url, redirects = 0) {
39
+ if (redirects > 5) return Promise.reject(new Error("too many installer redirects"));
40
+ return new Promise((resolve, reject) => {
41
+ const request = get(url, (response) => {
42
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
43
+ response.resume();
44
+ resolve(download(new URL(response.headers.location, url).href, redirects + 1));
45
+ return;
46
+ }
47
+ if (response.statusCode !== 200) {
48
+ response.resume();
49
+ reject(new Error(`installer download returned HTTP ${response.statusCode}`));
50
+ return;
51
+ }
52
+
53
+ const chunks = [];
54
+ let size = 0;
55
+ response.on("data", (chunk) => {
56
+ size += chunk.length;
57
+ if (size > maxInstallerBytes) {
58
+ request.destroy(new Error("installer download exceeded 1 MiB"));
59
+ return;
60
+ }
61
+ chunks.push(chunk);
62
+ });
63
+ response.on("end", () => resolve(Buffer.concat(chunks)));
64
+ });
65
+ request.on("error", reject);
66
+ });
67
+ }
68
+
69
+ function checkedSpawn(command, args, options) {
70
+ const result = spawnSync(command, args, options);
71
+ if (result.error) throw result.error;
72
+ if (result.status !== 0) {
73
+ throw new Error(`${command} exited with status ${result.status ?? "unknown"}`);
74
+ }
75
+ }
76
+
77
+ async function installHutch({ channel, environment, platform }) {
78
+ const temporary = mkdtempSync(path.join(tmpdir(), "electrobun-hutch-"));
79
+ try {
80
+ if (platform === "win32") {
81
+ const installer = path.join(temporary, "install.ps1");
82
+ writeFileSync(installer, await download(`${installerBaseUrl}/install.ps1`));
83
+ checkedSpawn(
84
+ "powershell.exe",
85
+ [
86
+ "-NoProfile",
87
+ "-NonInteractive",
88
+ "-ExecutionPolicy",
89
+ "Bypass",
90
+ "-File",
91
+ installer,
92
+ "-Channel",
93
+ channel,
94
+ ],
95
+ { env: environment, stdio: "inherit" },
96
+ );
97
+ } else {
98
+ const installer = path.join(temporary, "install.sh");
99
+ writeFileSync(installer, await download(`${installerBaseUrl}/install.sh`), {
100
+ mode: 0o700,
101
+ });
102
+ checkedSpawn("sh", [installer, "--channel", channel], {
103
+ env: environment,
104
+ stdio: "inherit",
105
+ });
106
+ }
107
+ } finally {
108
+ rmSync(temporary, { force: true, recursive: true });
109
+ }
110
+ }
111
+
112
+ function runHutch({ binary, args, environment }) {
113
+ const result = spawnSync(binary, ["electrobun", ...args], {
114
+ env: environment,
115
+ stdio: "inherit",
116
+ });
117
+ if (result.error) throw result.error;
118
+ if (result.status !== null) return result.status;
119
+ return result.signal === "SIGINT" ? 130 : result.signal === "SIGTERM" ? 143 : 1;
120
+ }
121
+
122
+ async function main(options = {}) {
123
+ const args = options.args || process.argv.slice(2);
124
+ if (args[0] !== "init") {
125
+ throw new Error(
126
+ "the npm entry point supports only `electrobun init`; use `hutch electrobun` for project commands",
127
+ );
128
+ }
129
+ const environment = options.environment || process.env;
130
+ const platform = options.platform || process.platform;
131
+ const version = options.version || packageVersion;
132
+ const userHome = options.userHome || homedir();
133
+ const fileExists = options.existsSync || existsSync;
134
+ const install = options.installHutch || installHutch;
135
+ const run = options.runHutch || runHutch;
136
+ const channel = channelForVersion(version, environment);
137
+ const binary = hutchBinaryPath(channel, environment, platform, userHome);
138
+
139
+ if (!fileExists(binary)) {
140
+ if (environment.ELECTROBUN_HUTCH_BINARY) {
141
+ throw new Error(`ELECTROBUN_HUTCH_BINARY does not exist: ${binary}`);
142
+ }
143
+ console.error(`Electrobun requires Hutch; installing the latest ${channel} release...`);
144
+ await install({ channel, environment, platform });
145
+ }
146
+ if (!fileExists(binary)) throw new Error(`Hutch was not installed at ${binary}`);
147
+ return run({ binary, args, environment });
148
+ }
149
+
150
+ if (require.main === module) {
151
+ main()
152
+ .then((status) => {
153
+ process.exitCode = status;
154
+ })
155
+ .catch((error) => {
156
+ console.error(`electrobun: ${error.message}`);
157
+ process.exitCode = 1;
158
+ });
159
+ }
160
+
161
+ module.exports = {
162
+ channelForVersion,
163
+ hutchBinaryPath,
164
+ main,
165
+ };
package/dash.config.ts CHANGED
@@ -1,4 +1,4 @@
1
- // @dash cli=0.5.0-canary.8 cottontail=0.2.3
1
+ // @dash cli=0.5.0-canary.9 cottontail=0.2.3
2
2
  export default {
3
3
  scripts: {
4
4
  start: "hutch src/sdks/main/index.ts",
@@ -46,7 +46,7 @@ export default {
46
46
  "test:deployment-target": "node scripts/run-cottontail-test.js scripts/verify-macho-deployment-target.test.ts",
47
47
  "test:linux-abi": "node scripts/run-cottontail-test.js scripts/verify-linux-elf-abi.test.ts",
48
48
  "test:linux-extractor": "node scripts/test-linux-adjacent-extractor.mjs",
49
- "test:npm-bootstrap": "node scripts/run-cottontail-test.js bin/npm-bootstrap-retirement.test.ts",
49
+ "test:npm-bootstrap": "node scripts/run-cottontail-test.js bin/npm-bootstrap.test.ts",
50
50
  "test:release-notes": "node scripts/release-notes-contract.test.mjs",
51
51
  "test:spell-check": "node --test src/shared/spell-check.test.js",
52
52
  "test:macos-spell-check": "scripts/test-macos-spell-check.sh",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrobun",
3
- "version": "1.18.4-beta.18",
3
+ "version": "1.18.4-beta.19",
4
4
  "description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
5
5
  "license": "MIT",
6
6
  "author": "Blackboard Technologies Inc.",
@@ -56,6 +56,9 @@
56
56
  "type": "git",
57
57
  "url": "git+https://github.com/blackboardsh/electrobun.git"
58
58
  },
59
+ "bin": {
60
+ "electrobun": "./bin/electrobun.cjs"
61
+ },
59
62
  "scripts": {
60
63
  "build:local": "node scripts/build-local.js"
61
64
  },