Skip to content

Commit b694b50

Browse files
committed
wip add simple tui binary class
1 parent 81e67f0 commit b694b50

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

src/cfg/setting.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ export interface Settings {
5252
transactionsPath: string;
5353
};
5454
tools: {
55+
rootFolder: string;
5556
ckbDebugger: {
5657
minVersion: string;
5758
};
59+
ckbTui: {
60+
version: string;
61+
};
5862
};
5963
}
6064

@@ -88,9 +92,13 @@ export const defaultSettings: Settings = {
8892
transactionsPath: path.resolve(dataPath, 'mainnet/transactions'),
8993
},
9094
tools: {
95+
rootFolder: path.resolve(dataPath, 'tools'),
9196
ckbDebugger: {
9297
minVersion: '0.200.0',
9398
},
99+
ckbTui: {
100+
version: 'v0.1.0',
101+
},
94102
},
95103
};
96104

src/cli.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { genSystemScriptsJsonFile } from './scripts/gen';
1717
import { CKBDebugger } from './tools/ckb-debugger';
1818
import { logger } from './util/logger';
1919
import { Network } from './type/base';
20+
import { status } from './cmd/status';
2021

2122
const version = require('../package.json').version;
2223
const description = require('../package.json').description;
@@ -154,6 +155,13 @@ program
154155
return CKBDebugger.runWithArgs(process.argv.slice(2));
155156
});
156157

158+
program
159+
.command('status')
160+
.description('Show ckb-tui status interface')
161+
.action(async () => {
162+
status();
163+
});
164+
157165
program
158166
.command('config <action> [item] [value]')
159167
.description('do a configuration action')

src/cmd/status.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { CKBTui } from '../tools/tui';
2+
3+
export async function status() {
4+
CKBTui.run();
5+
}

src/tools/tui.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { execSync } from 'child_process';
2+
import * as path from 'path';
3+
import * as fs from 'fs';
4+
import { readSettings } from '../cfg/setting';
5+
import { logger } from '../util/logger';
6+
7+
export class CKBTui {
8+
private static binaryPath: string | null = null;
9+
10+
private static getBinaryPath(): string {
11+
if (!this.binaryPath) {
12+
const settings = readSettings();
13+
const binDir = settings.tools.rootFolder;
14+
const version = settings.tools.ckbTui.version;
15+
this.binaryPath = path.join(binDir, 'ckb-tui');
16+
17+
if (!fs.existsSync(this.binaryPath)) {
18+
this.downloadBinary(version);
19+
}
20+
}
21+
return this.binaryPath;
22+
}
23+
24+
private static downloadBinary(version: string) {
25+
const platform = process.platform;
26+
const arch = process.arch;
27+
let assetName: string;
28+
29+
if (platform === 'darwin') {
30+
if (arch === 'arm64') {
31+
assetName = `ckb-tui-with-node-macos-aarch64.tar.gz`;
32+
} else {
33+
throw new Error(`Unsupported architecture for macOS: ${arch}`);
34+
}
35+
} else if (platform === 'linux') {
36+
if (arch === 'x64') {
37+
assetName = `ckb-tui-with-node-linux-amd64.tar.gz`;
38+
} else {
39+
throw new Error(`Unsupported architecture for Linux: ${arch}`);
40+
}
41+
} else if (platform === 'win32') {
42+
if (arch === 'x64') {
43+
assetName = `ckb-tui-with-node-windows-amd64.zip`;
44+
} else {
45+
throw new Error(`Unsupported architecture for Windows: ${arch}`);
46+
}
47+
} else {
48+
throw new Error(`Unsupported platform: ${platform}`);
49+
}
50+
51+
const downloadUrl = `https://github.com/Officeyutong/ckb-tui/releases/download/${version}/${assetName}`;
52+
const binDir = path.dirname(this.binaryPath!);
53+
const archivePath = path.join(binDir, assetName);
54+
55+
try {
56+
logger.info(`Downloading ckb-tui from ${downloadUrl}...`);
57+
execSync(`curl -L -o "${archivePath}" "${downloadUrl}"`, { stdio: 'inherit' });
58+
59+
logger.info('Extracting...');
60+
if (assetName.endsWith('.tar.gz')) {
61+
execSync(`tar -xzf "${archivePath}" -C "${binDir}"`, { stdio: 'inherit' });
62+
} else if (assetName.endsWith('.zip')) {
63+
execSync(`unzip "${archivePath}" -d "${binDir}"`, { stdio: 'inherit' });
64+
}
65+
66+
// Assume the binary is extracted as 'ckb-tui' or 'ckb-tui.exe'
67+
// todo: fix the bin name
68+
const extractedBinary = platform === 'win32' ? 'ckb-tui.exe' : 'ckb-tui-macos-amd64';
69+
const extractedPath = path.join(binDir, extractedBinary);
70+
if (fs.existsSync(extractedPath)) {
71+
fs.renameSync(extractedPath, this.binaryPath!);
72+
} else {
73+
// If in a subfolder, find it
74+
const files = fs.readdirSync(binDir);
75+
for (const file of files) {
76+
const filePath = path.join(binDir, file);
77+
if (fs.statSync(filePath).isDirectory()) {
78+
const candidate = path.join(filePath, extractedBinary);
79+
if (fs.existsSync(candidate)) {
80+
fs.renameSync(candidate, this.binaryPath!);
81+
break;
82+
}
83+
}
84+
}
85+
}
86+
87+
// Make executable on Unix
88+
if (platform !== 'win32') {
89+
execSync(`chmod +x "${this.binaryPath}"`);
90+
}
91+
92+
// Clean up archive
93+
fs.unlinkSync(archivePath);
94+
95+
logger.info('ckb-tui installed successfully.');
96+
} catch (error) {
97+
logger.error('Failed to download/install ckb-tui:', (error as Error).message);
98+
throw error;
99+
}
100+
}
101+
102+
static isInstalled(): boolean {
103+
try {
104+
const path = this.getBinaryPath();
105+
return fs.existsSync(path);
106+
} catch {
107+
return false;
108+
}
109+
}
110+
111+
static run(args: string[] = []) {
112+
const binaryPath = this.getBinaryPath();
113+
const command = `"${binaryPath}" ${args.join(' ')}`;
114+
execSync(command, { stdio: 'inherit' });
115+
}
116+
117+
static runWithArgs(args: string[]) {
118+
this.run(args);
119+
}
120+
}

0 commit comments

Comments
 (0)