@akiojin/gwt 6.0.2 → 6.0.7

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.ja.md CHANGED
@@ -64,10 +64,7 @@ bunx @akiojin/gwt
64
64
  Cargo で CLI を直接インストールできます:
65
65
 
66
66
  ```bash
67
- # crates.io からインストール(Rustユーザー推奨)
68
- cargo install gwt-cli
69
-
70
- # cargo-binstall でインストール(高速、プリビルドバイナリをダウンロード)
67
+ # cargo-binstall でインストール(高速、GitHub Releasesからプリビルドバイナリをダウンロード)
71
68
  cargo binstall gwt-cli
72
69
 
73
70
  # GitHub からインストール(最新開発版)
@@ -75,6 +72,9 @@ cargo install --git https://github.com/akiojin/gwt --package gwt-cli --bin gwt -
75
72
 
76
73
  # ローカルチェックアウトからインストール
77
74
  cargo install --path crates/gwt-cli
75
+
76
+ # そのまま実行
77
+ cargo run -p gwt-cli
78
78
  ```
79
79
 
80
80
  ### ソースからビルド
package/README.md CHANGED
@@ -10,7 +10,7 @@ Interactive Git worktree manager with Coding Agent selection (Claude Code / Code
10
10
 
11
11
  ## Migration Status
12
12
 
13
- The Rust implementation covers the core CLI/TUI workflow and the Web UI (REST + WebSocket terminal). Remaining work is focused on Git backend fallback coverage, documentation polish, and release packaging.
13
+ The Rust implementation covers the core CLI/TUI workflow and the Web UI (REST + WebSocket terminal). The migration from TypeScript/Bun to Rust is complete. Remaining work is focused on documentation polish and continuous improvements.
14
14
 
15
15
  ## Key Features
16
16
 
@@ -26,7 +26,7 @@ The Rust implementation covers the core CLI/TUI workflow and the Web UI (REST +
26
26
 
27
27
  ## Installation
28
28
 
29
- GitHub Releases are the source of truth for prebuilt binaries. The npm/bunx wrapper downloads the matching release asset on install.
29
+ GitHub Releases are the source of truth for prebuilt binaries. The npm/bunx wrapper automatically downloads the matching release asset on install.
30
30
 
31
31
  ### From GitHub Releases (Recommended)
32
32
 
@@ -64,10 +64,7 @@ bunx @akiojin/gwt
64
64
  Install the CLI with Cargo:
65
65
 
66
66
  ```bash
67
- # From crates.io (recommended for Rust users)
68
- cargo install gwt-cli
69
-
70
- # With cargo-binstall (faster, downloads prebuilt binary)
67
+ # With cargo-binstall (faster, downloads prebuilt binary from GitHub Releases)
71
68
  cargo binstall gwt-cli
72
69
 
73
70
  # From GitHub (latest development version)
@@ -75,6 +72,9 @@ cargo install --git https://github.com/akiojin/gwt --package gwt-cli --bin gwt -
75
72
 
76
73
  # Or, from a local checkout
77
74
  cargo install --path crates/gwt-cli
75
+
76
+ # Or run directly from source
77
+ cargo run -p gwt-cli
78
78
  ```
79
79
 
80
80
  ### Build from Source
package/bin/gwt.js CHANGED
@@ -2,45 +2,166 @@
2
2
  /**
3
3
  * Wrapper script to execute the gwt Rust binary.
4
4
  * This allows npm/bunx distribution of the Rust CLI.
5
+ *
6
+ * If the binary is not found (e.g., bunx skips postinstall),
7
+ * it will be downloaded on-demand from GitHub Releases.
5
8
  */
6
9
 
7
10
  import { spawn } from 'child_process';
8
11
  import { dirname, join } from 'path';
9
12
  import { fileURLToPath } from 'url';
10
- import { existsSync } from 'fs';
13
+ import { existsSync, createWriteStream, mkdirSync, chmodSync, unlinkSync } from 'fs';
14
+ import { get } from 'https';
11
15
 
12
16
  const __filename = fileURLToPath(import.meta.url);
13
17
  const __dirname = dirname(__filename);
14
18
 
19
+ const REPO = 'akiojin/gwt';
15
20
  const BIN_NAME = process.platform === 'win32' ? 'gwt.exe' : 'gwt';
16
21
  const BIN_PATH = join(__dirname, BIN_NAME);
17
22
 
18
- if (!existsSync(BIN_PATH)) {
19
- console.error('Error: gwt binary not found.');
20
- console.error('');
21
- console.error('The binary may not have been downloaded during installation.');
22
- console.error('Please try reinstalling: npm install -g @akiojin/gwt');
23
- console.error('');
24
- console.error('Or download manually from:');
25
- console.error('https://github.com/akiojin/gwt/releases');
26
- process.exit(1);
23
+ function getPlatformArtifact() {
24
+ const platform = process.platform;
25
+ const arch = process.arch;
26
+
27
+ const mapping = {
28
+ 'darwin-x64': 'gwt-macos-x86_64',
29
+ 'darwin-arm64': 'gwt-macos-aarch64',
30
+ 'linux-x64': 'gwt-linux-x86_64',
31
+ 'linux-arm64': 'gwt-linux-aarch64',
32
+ 'win32-x64': 'gwt-windows-x86_64.exe',
33
+ };
34
+
35
+ const key = `${platform}-${arch}`;
36
+ return mapping[key];
37
+ }
38
+
39
+ async function getLatestReleaseUrl(artifact) {
40
+ return new Promise((resolve, reject) => {
41
+ const options = {
42
+ hostname: 'api.github.com',
43
+ path: `/repos/${REPO}/releases/latest`,
44
+ headers: {
45
+ 'User-Agent': 'gwt-wrapper',
46
+ 'Accept': 'application/vnd.github.v3+json',
47
+ },
48
+ };
49
+
50
+ get(options, (res) => {
51
+ let data = '';
52
+ res.on('data', (chunk) => data += chunk);
53
+ res.on('end', () => {
54
+ try {
55
+ const release = JSON.parse(data);
56
+ const asset = release.assets?.find(a => a.name === artifact);
57
+ if (asset) {
58
+ resolve(asset.browser_download_url);
59
+ } else {
60
+ resolve(`https://github.com/${REPO}/releases/latest/download/${artifact}`);
61
+ }
62
+ } catch {
63
+ resolve(`https://github.com/${REPO}/releases/latest/download/${artifact}`);
64
+ }
65
+ });
66
+ }).on('error', reject);
67
+ });
68
+ }
69
+
70
+ async function downloadFile(url, dest) {
71
+ return new Promise((resolve, reject) => {
72
+ const file = createWriteStream(dest);
73
+
74
+ const request = (url) => {
75
+ get(url, (res) => {
76
+ if (res.statusCode === 301 || res.statusCode === 302) {
77
+ request(res.headers.location);
78
+ return;
79
+ }
80
+
81
+ if (res.statusCode !== 200) {
82
+ reject(new Error(`Failed to download: HTTP ${res.statusCode}`));
83
+ return;
84
+ }
85
+
86
+ res.pipe(file);
87
+ file.on('finish', () => {
88
+ file.close();
89
+ resolve();
90
+ });
91
+ }).on('error', (err) => {
92
+ if (existsSync(dest)) unlinkSync(dest);
93
+ reject(err);
94
+ });
95
+ };
96
+
97
+ request(url);
98
+ });
99
+ }
100
+
101
+ async function downloadBinary() {
102
+ const artifact = getPlatformArtifact();
103
+
104
+ if (!artifact) {
105
+ console.error(`Unsupported platform: ${process.platform}-${process.arch}`);
106
+ console.error('Supported platforms: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64');
107
+ process.exit(1);
108
+ }
109
+
110
+ console.log(`Downloading gwt binary for ${process.platform}-${process.arch}...`);
111
+
112
+ const url = await getLatestReleaseUrl(artifact);
113
+ console.log(`Downloading from: ${url}`);
114
+
115
+ if (!existsSync(__dirname)) {
116
+ mkdirSync(__dirname, { recursive: true });
117
+ }
118
+
119
+ await downloadFile(url, BIN_PATH);
120
+
121
+ if (process.platform !== 'win32') {
122
+ chmodSync(BIN_PATH, 0o755);
123
+ }
124
+
125
+ console.log('gwt binary installed successfully!');
126
+ console.log('');
27
127
  }
28
128
 
29
- // Forward all arguments to the native binary
30
- const child = spawn(BIN_PATH, process.argv.slice(2), {
31
- stdio: 'inherit',
32
- env: process.env,
33
- });
34
-
35
- child.on('error', (err) => {
36
- console.error('Failed to start gwt:', err.message);
37
- process.exit(1);
38
- });
39
-
40
- child.on('exit', (code, signal) => {
41
- if (signal) {
42
- process.kill(process.pid, signal);
43
- } else {
44
- process.exit(code ?? 0);
129
+ function runBinary() {
130
+ const child = spawn(BIN_PATH, process.argv.slice(2), {
131
+ stdio: 'inherit',
132
+ env: process.env,
133
+ });
134
+
135
+ child.on('error', (err) => {
136
+ console.error('Failed to start gwt:', err.message);
137
+ process.exit(1);
138
+ });
139
+
140
+ child.on('exit', (code, signal) => {
141
+ if (signal) {
142
+ process.kill(process.pid, signal);
143
+ } else {
144
+ process.exit(code ?? 0);
145
+ }
146
+ });
147
+ }
148
+
149
+ async function main() {
150
+ if (!existsSync(BIN_PATH)) {
151
+ try {
152
+ await downloadBinary();
153
+ } catch (error) {
154
+ console.error('Failed to download gwt binary:', error.message);
155
+ console.error('');
156
+ console.error('You can manually download the binary from:');
157
+ console.error(`https://github.com/${REPO}/releases`);
158
+ console.error('');
159
+ console.error('Or build from source with: cargo build --release');
160
+ process.exit(1);
161
+ }
45
162
  }
46
- });
163
+
164
+ runBinary();
165
+ }
166
+
167
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akiojin/gwt",
3
- "version": "6.0.2",
3
+ "version": "6.0.7",
4
4
  "description": "Interactive Git worktree manager with Coding Agent selection (Claude Code / Codex CLI / Gemini CLI)",
5
5
  "bin": {
6
6
  "gwt": "bin/gwt.js"