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 CHANGED
@@ -1,61 +1,14 @@
1
1
  # jbs-client
2
2
 
3
- `jbs-client` is the CLI client for [JVMByteSwapTool](https://github.com/sunwu51/JVMByteSwapTool).
3
+ Prebuilt OpenTUI CLI distribution package.
4
4
 
5
- It is built with OpenTUI and connects to the JVMByteSwapTool WebSocket service by default.
5
+ This package is intended to be published together with platform-specific packages:
6
6
 
7
- ## Install
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
- ```bash
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.1",
4
- "type": "module",
5
- "scripts": {
6
- "start": "bun run src/index.tsx",
7
- "dev": "bun --watch run src/index.tsx",
8
- "test": "bun test",
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
- "dependencies": {
13
- "@opentui/core": "0.1.97",
14
- "@opentui/react": "^0.1.97",
15
- "react": "^19.2.0"
10
+ "bin": "./bin/jbs-client.js",
11
+ "scripts": {
12
+ "postinstall": "node ./postinstall.mjs"
16
13
  },
17
- "devDependencies": {
18
- "@types/bun": "^1.2.20",
19
- "@types/react": "^19.1.11",
20
- "typescript": "^5.9.2"
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
- });