@akiojin/gwt 6.0.2 → 6.0.6

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
@@ -75,6 +75,9 @@ cargo install --git https://github.com/akiojin/gwt --package gwt-cli --bin gwt -
75
75
 
76
76
  # ローカルチェックアウトからインストール
77
77
  cargo install --path crates/gwt-cli
78
+
79
+ # そのまま実行
80
+ cargo run -p gwt-cli
78
81
  ```
79
82
 
80
83
  ### ソースからビルド
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
 
@@ -75,6 +75,9 @@ cargo install --git https://github.com/akiojin/gwt --package gwt-cli --bin gwt -
75
75
 
76
76
  # Or, from a local checkout
77
77
  cargo install --path crates/gwt-cli
78
+
79
+ # Or run directly from source
80
+ cargo run -p gwt-cli
78
81
  ```
79
82
 
80
83
  ### 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.6",
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"