jbs-client 0.0.1 → 0.0.5
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 +9 -56
- package/bin/jbs-client.js +71 -0
- package/package.json +16 -16
- package/.github/workflows/release.yml +0 -54
- package/build.ts +0 -162
- package/bun.lock +0 -234
- package/scripts/npm/README.md +0 -14
- package/scripts/npm/bin/jbs-client +0 -70
- package/src/app.tsx +0 -239
- package/src/components/action-menu.tsx +0 -28
- package/src/components/log-panel.tsx +0 -31
- package/src/components/param-form.tsx +0 -73
- package/src/components.test.tsx +0 -36
- package/src/index.tsx +0 -19
- package/src/protocol.test.ts +0 -40
- package/src/protocol.ts +0 -201
- package/src/state.test.ts +0 -31
- package/src/state.ts +0 -77
- package/src/types.ts +0 -34
- package/src/ws.ts +0 -63
- package/tsconfig.json +0 -15
- /package/{scripts/npm/postinstall.mjs → postinstall.mjs} +0 -0
package/README.md
CHANGED
|
@@ -1,61 +1,14 @@
|
|
|
1
1
|
# jbs-client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Prebuilt OpenTUI CLI distribution package.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package is intended to be published together with platform-specific packages:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- `jbs-client-windows-x64`
|
|
8
|
+
- `jbs-client-windows-arm64`
|
|
9
|
+
- `jbs-client-linux-x64`
|
|
10
|
+
- `jbs-client-linux-arm64`
|
|
11
|
+
- `jbs-client-darwin-x64`
|
|
12
|
+
- `jbs-client-darwin-arm64`
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
npm i -g jbs-client
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Run
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
jbs-client
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
By default, the client connects to:
|
|
20
|
-
|
|
21
|
-
```text
|
|
22
|
-
ws://localhost:18000
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Options
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
jbs-client --host localhost --ws_port 18000 --connect true
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Supported startup parameters:
|
|
32
|
-
|
|
33
|
-
- `--host <host>`: WebSocket host, default is `localhost`
|
|
34
|
-
- `--ws_port <port>`: WebSocket port, default is `18000`
|
|
35
|
-
- `--connect <true|false>`: whether to connect to the backend on startup, default is `true`
|
|
36
|
-
|
|
37
|
-
Examples:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
jbs-client --host 192.168.1.10 --ws_port 18000
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
jbs-client --connect false
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
When `--connect false` is used, the UI starts without opening the backend WebSocket connection. You can edit the WebSocket URL inside the TUI and reconnect manually.
|
|
48
|
-
|
|
49
|
-
## Keyboard
|
|
50
|
-
|
|
51
|
-
- `Ctrl+C`: exit the client
|
|
52
|
-
- `Tab` / `Shift+Tab`: switch focus
|
|
53
|
-
- `Up` / `Down`: change selected action in the menu
|
|
54
|
-
- `Enter`: open an action or submit the current form
|
|
55
|
-
- `Esc`: return from the form view to the main menu
|
|
56
|
-
|
|
57
|
-
## Release Build
|
|
58
|
-
|
|
59
|
-
This repository publishes prebuilt binaries through GitHub Releases and npm wrapper packages.
|
|
60
|
-
|
|
61
|
-
Pushing a tag like `v0.0.1` triggers the release workflow, builds all supported platforms, zips each platform binary, and uploads them to the corresponding GitHub Release.
|
|
14
|
+
Publish the platform packages first, then publish the root `jbs-client` wrapper package.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const childProcess = require("child_process");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
|
|
8
|
+
function run(target) {
|
|
9
|
+
const result = childProcess.spawnSync(target, process.argv.slice(2), {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
shell: false,
|
|
12
|
+
});
|
|
13
|
+
if (result.error) {
|
|
14
|
+
console.error(result.error.message);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
process.exit(typeof result.status === "number" ? result.status : 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const envPath = process.env.JBS_CLIENT_BIN_PATH;
|
|
21
|
+
if (envPath) {
|
|
22
|
+
run(envPath);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const scriptPath = fs.realpathSync(__filename);
|
|
26
|
+
const scriptDir = path.dirname(scriptPath);
|
|
27
|
+
const cached = path.join(scriptDir, ".jbs-client");
|
|
28
|
+
if (fs.existsSync(cached)) {
|
|
29
|
+
run(cached);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const platformMap = {
|
|
33
|
+
darwin: "darwin",
|
|
34
|
+
linux: "linux",
|
|
35
|
+
win32: "windows",
|
|
36
|
+
};
|
|
37
|
+
const archMap = {
|
|
38
|
+
x64: "x64",
|
|
39
|
+
arm64: "arm64",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const platform = platformMap[os.platform()] || os.platform();
|
|
43
|
+
const arch = archMap[os.arch()] || os.arch();
|
|
44
|
+
const packageName = `jbs-client-${platform}-${arch}`;
|
|
45
|
+
const binaryName = platform === "windows" ? "jbs-client.exe" : "jbs-client";
|
|
46
|
+
|
|
47
|
+
function findBinary(startDir) {
|
|
48
|
+
let current = startDir;
|
|
49
|
+
for (;;) {
|
|
50
|
+
const modules = path.join(current, "node_modules");
|
|
51
|
+
if (fs.existsSync(modules)) {
|
|
52
|
+
const candidate = path.join(modules, packageName, "bin", binaryName);
|
|
53
|
+
if (fs.existsSync(candidate)) {
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const parent = path.dirname(current);
|
|
58
|
+
if (parent === current) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
current = parent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const resolved = findBinary(scriptDir);
|
|
66
|
+
if (!resolved) {
|
|
67
|
+
console.error(`Unable to find installed binary package "${packageName}".`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
run(resolved);
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jbs-client",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"build": "bun run build.ts",
|
|
10
|
-
"build:npm": "bun run build.ts"
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "JBS Client terminal UI powered by OpenTUI",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/sunwu51/jbs-client-opentui.git"
|
|
11
9
|
},
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"react": "^19.2.0"
|
|
10
|
+
"bin": "./bin/jbs-client.js",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"postinstall": "node ./postinstall.mjs"
|
|
16
13
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
14
|
+
"optionalDependencies": {
|
|
15
|
+
"jbs-client-windows-x64": "0.0.5",
|
|
16
|
+
"jbs-client-windows-arm64": "0.0.5",
|
|
17
|
+
"jbs-client-linux-x64": "0.0.5",
|
|
18
|
+
"jbs-client-linux-arm64": "0.0.5",
|
|
19
|
+
"jbs-client-darwin-x64": "0.0.5",
|
|
20
|
+
"jbs-client-darwin-arm64": "0.0.5"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- "v*"
|
|
7
|
-
|
|
8
|
-
permissions:
|
|
9
|
-
contents: write
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
release:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
- name: Checkout
|
|
17
|
-
uses: actions/checkout@v4
|
|
18
|
-
|
|
19
|
-
- name: Setup Bun
|
|
20
|
-
uses: oven-sh/setup-bun@v2
|
|
21
|
-
with:
|
|
22
|
-
bun-version: latest
|
|
23
|
-
|
|
24
|
-
- name: Install Dependencies
|
|
25
|
-
run: bun install
|
|
26
|
-
|
|
27
|
-
- name: Build Packages
|
|
28
|
-
run: bun run build
|
|
29
|
-
|
|
30
|
-
- name: Prepare Release Assets
|
|
31
|
-
shell: bash
|
|
32
|
-
run: |
|
|
33
|
-
set -euo pipefail
|
|
34
|
-
mkdir -p release-assets
|
|
35
|
-
|
|
36
|
-
while IFS= read -r dir; do
|
|
37
|
-
name="$(basename "$dir")"
|
|
38
|
-
if [ "$name" = "jbs-client" ]; then
|
|
39
|
-
continue
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
(
|
|
43
|
-
cd "$dir/bin"
|
|
44
|
-
zip -r "../../../release-assets/${name}.zip" .
|
|
45
|
-
)
|
|
46
|
-
done < <(find dist/npm -mindepth 1 -maxdepth 1 -type d | sort)
|
|
47
|
-
|
|
48
|
-
ls -lah release-assets
|
|
49
|
-
|
|
50
|
-
- name: Upload Release Assets
|
|
51
|
-
uses: softprops/action-gh-release@v2
|
|
52
|
-
with:
|
|
53
|
-
files: release-assets/*.zip
|
|
54
|
-
generate_release_notes: true
|
package/build.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { cp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import { basename, join, resolve } from "node:path";
|
|
3
|
-
import { $ } from "bun";
|
|
4
|
-
import packageJson from "./package.json" with { type: "json" };
|
|
5
|
-
|
|
6
|
-
const entrypoint = "./src/index.tsx";
|
|
7
|
-
const outdir = "dist";
|
|
8
|
-
const npmOutdir = join(outdir, "npm");
|
|
9
|
-
const rootPackageName = "jbs-client";
|
|
10
|
-
const templateDir = "scripts/npm";
|
|
11
|
-
const projectRoot = resolve(".");
|
|
12
|
-
|
|
13
|
-
const targets = [
|
|
14
|
-
{ target: "bun-windows-x64", os: "win32", cpu: "x64" },
|
|
15
|
-
{ target: "bun-windows-arm64", os: "win32", cpu: "arm64" },
|
|
16
|
-
{ target: "bun-linux-x64", os: "linux", cpu: "x64" },
|
|
17
|
-
{ target: "bun-linux-arm64", os: "linux", cpu: "arm64" },
|
|
18
|
-
{ target: "bun-darwin-x64", os: "darwin", cpu: "x64" },
|
|
19
|
-
{ target: "bun-darwin-arm64", os: "darwin", cpu: "arm64" }
|
|
20
|
-
] satisfies Array<{
|
|
21
|
-
target: Bun.Build.CompileTarget;
|
|
22
|
-
os: "win32" | "linux" | "darwin";
|
|
23
|
-
cpu: "x64" | "arm64";
|
|
24
|
-
}>;
|
|
25
|
-
|
|
26
|
-
function platformLabel(os: string) {
|
|
27
|
-
return os === "win32" ? "windows" : os;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function binaryName(os: string) {
|
|
31
|
-
return os === "win32" ? `${rootPackageName}.exe` : rootPackageName;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function packageNameForTarget(os: string, cpu: string) {
|
|
35
|
-
return `${rootPackageName}-${platformLabel(os)}-${cpu}`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function createRootPackageJson() {
|
|
39
|
-
const optionalDependencies = Object.fromEntries(
|
|
40
|
-
targets.map((item) => [packageNameForTarget(item.os, item.cpu), packageJson.version])
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
name: rootPackageName,
|
|
45
|
-
version: packageJson.version,
|
|
46
|
-
description: "JBS Client terminal UI powered by OpenTUI",
|
|
47
|
-
license: "UNLICENSED",
|
|
48
|
-
bin: {
|
|
49
|
-
[rootPackageName]: "./bin/jbs-client"
|
|
50
|
-
},
|
|
51
|
-
scripts: {
|
|
52
|
-
postinstall: "node ./postinstall.mjs"
|
|
53
|
-
},
|
|
54
|
-
optionalDependencies
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function createPlatformPackageJson(name: string, os: string, cpu: string, bin: string) {
|
|
59
|
-
return {
|
|
60
|
-
name,
|
|
61
|
-
version: packageJson.version,
|
|
62
|
-
description: "Prebuilt binary for JBS Client OpenTUI",
|
|
63
|
-
license: "UNLICENSED",
|
|
64
|
-
os: [os],
|
|
65
|
-
cpu: [cpu],
|
|
66
|
-
preferUnplugged: true,
|
|
67
|
-
bin: {
|
|
68
|
-
[rootPackageName]: `./bin/${bin}`
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async function installCrossPlatformNativeDependencies() {
|
|
74
|
-
if (process.env.SKIP_CROSS_PLATFORM_INSTALL === "1") {
|
|
75
|
-
console.log("Skipping cross-platform native dependency install");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const opentuiCoreVersion = packageJson.dependencies["@opentui/core"];
|
|
80
|
-
|
|
81
|
-
if (!opentuiCoreVersion) {
|
|
82
|
-
throw new Error("Missing @opentui/core dependency");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
console.log(`Installing cross-platform OpenTUI native packages (${opentuiCoreVersion})`);
|
|
86
|
-
try {
|
|
87
|
-
await $`bun install --os="*" --cpu="*" ${`@opentui/core@${opentuiCoreVersion}`}`.cwd(projectRoot);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
throw new Error(
|
|
90
|
-
`Failed to install cross-platform OpenTUI packages. Run 'bun install --os="*" --cpu="*" @opentui/core@${opentuiCoreVersion}' manually or set SKIP_CROSS_PLATFORM_INSTALL=1 if dependencies are already present.`,
|
|
91
|
-
{ cause: error }
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async function copyTemplates() {
|
|
97
|
-
const rootPublishDir = join(npmOutdir, rootPackageName);
|
|
98
|
-
await mkdir(join(rootPublishDir, "bin"), { recursive: true });
|
|
99
|
-
await cp(join(templateDir, "bin", "jbs-client"), join(rootPublishDir, "bin", "jbs-client"));
|
|
100
|
-
await cp(join(templateDir, "postinstall.mjs"), join(rootPublishDir, "postinstall.mjs"));
|
|
101
|
-
await cp(join(templateDir, "README.md"), join(rootPublishDir, "README.md"));
|
|
102
|
-
await writeFile(join(rootPublishDir, "package.json"), `${JSON.stringify(createRootPackageJson(), null, 2)}\n`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function buildTarget(item: (typeof targets)[number]) {
|
|
106
|
-
const packageName = packageNameForTarget(item.os, item.cpu);
|
|
107
|
-
const packageDir = join(npmOutdir, packageName);
|
|
108
|
-
const binDir = join(packageDir, "bin");
|
|
109
|
-
const outputFile = join(binDir, binaryName(item.os));
|
|
110
|
-
|
|
111
|
-
console.log(`Building ${item.target} -> ${outputFile}`);
|
|
112
|
-
await mkdir(binDir, { recursive: true });
|
|
113
|
-
|
|
114
|
-
const result = await Bun.build({
|
|
115
|
-
entrypoints: [entrypoint],
|
|
116
|
-
root: projectRoot,
|
|
117
|
-
target: "bun",
|
|
118
|
-
minify: true,
|
|
119
|
-
tsconfig: "./tsconfig.json",
|
|
120
|
-
compile: {
|
|
121
|
-
autoloadBunfig: false,
|
|
122
|
-
autoloadDotenv: false,
|
|
123
|
-
autoloadPackageJson: false,
|
|
124
|
-
autoloadTsconfig: false,
|
|
125
|
-
target: item.target,
|
|
126
|
-
outfile: outputFile
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
if (!result.success) {
|
|
131
|
-
for (const log of result.logs) {
|
|
132
|
-
console.error(log);
|
|
133
|
-
}
|
|
134
|
-
throw new Error(`Build failed for ${item.target}`);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
await writeFile(
|
|
138
|
-
join(packageDir, "package.json"),
|
|
139
|
-
`${JSON.stringify(createPlatformPackageJson(packageName, item.os, item.cpu, basename(outputFile)), null, 2)}\n`
|
|
140
|
-
);
|
|
141
|
-
await cp(join(templateDir, "README.md"), join(packageDir, "README.md"));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async function main() {
|
|
145
|
-
await installCrossPlatformNativeDependencies();
|
|
146
|
-
await rm(resolve(outdir), { recursive: true, force: true });
|
|
147
|
-
await mkdir(npmOutdir, { recursive: true });
|
|
148
|
-
|
|
149
|
-
await copyTemplates();
|
|
150
|
-
|
|
151
|
-
for (const target of targets) {
|
|
152
|
-
await buildTarget(target);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
console.log(`Publish root package from ${join(npmOutdir, rootPackageName)}`);
|
|
156
|
-
console.log("Publish platform packages first, then publish the root wrapper package.");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
void main().catch((error) => {
|
|
160
|
-
console.error(error);
|
|
161
|
-
process.exit(1);
|
|
162
|
-
});
|