@kitlangton/ghui 0.3.3 → 0.4.1

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
@@ -8,13 +8,18 @@ Terminal UI for keeping up with your open GitHub pull requests across repositori
8
8
 
9
9
  ## Install
10
10
 
11
+ ```bash
12
+ brew install kitlangton/tap/ghui
13
+ ```
14
+
15
+ Or with npm:
16
+
11
17
  ```bash
12
18
  npm install -g @kitlangton/ghui
13
19
  ```
14
20
 
15
21
  Requirements:
16
22
 
17
- - Bun runtime installed
18
23
  - GitHub CLI installed and authenticated with `gh auth login`
19
24
 
20
25
  Run it from anywhere:
package/bin/ghui.js CHANGED
@@ -1,6 +1,26 @@
1
- #!/usr/bin/env bun
1
+ #!/usr/bin/env node
2
2
 
3
- const packageJson = await Bun.file(new URL("../package.json", import.meta.url)).json()
3
+ import childProcess from "node:child_process"
4
+ import fs from "node:fs"
5
+ import os from "node:os"
6
+ import path from "node:path"
7
+ import { createRequire } from "node:module"
8
+ import { fileURLToPath } from "node:url"
9
+
10
+ const __filename = fileURLToPath(import.meta.url)
11
+ const requireFromHere = createRequire(import.meta.url)
12
+
13
+ const packageJson = requireFromHere("../package.json")
14
+
15
+ const platformMap = {
16
+ darwin: "darwin",
17
+ linux: "linux",
18
+ }
19
+
20
+ const archMap = {
21
+ arm64: "arm64",
22
+ x64: "x64",
23
+ }
4
24
 
5
25
  const help = `ghui ${packageJson.version}
6
26
 
@@ -14,58 +34,90 @@ Usage:
14
34
  ghui -h, --help Show this help message
15
35
  `
16
36
 
17
- const args = Bun.argv.slice(2)
18
- const command = args[0]
19
- const commands = ["upgrade", "help", "version"]
20
-
21
- const editDistance = (a, b) => {
22
- const distances = Array.from({ length: a.length + 1 }, (_, i) => [i])
23
- for (let j = 1; j <= b.length; j++) distances[0][j] = j
24
-
25
- for (let i = 1; i <= a.length; i++) {
26
- for (let j = 1; j <= b.length; j++) {
27
- distances[i][j] = Math.min(
28
- distances[i - 1][j] + 1,
29
- distances[i][j - 1] + 1,
30
- distances[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1),
31
- )
32
- }
37
+ const run = (target, args = process.argv.slice(2)) => {
38
+ const result = childProcess.spawnSync(target, args, { stdio: "inherit" })
39
+ if (result.error) {
40
+ console.error(result.error.message)
41
+ process.exit(1)
33
42
  }
43
+ process.exit(typeof result.status === "number" ? result.status : 0)
44
+ }
34
45
 
35
- return distances[a.length][b.length]
46
+ if (process.env.GHUI_BIN_PATH) {
47
+ run(process.env.GHUI_BIN_PATH)
36
48
  }
37
49
 
38
- if (command === "-h" || command === "--help" || command === "help") {
50
+ if (process.argv[2] === "-h" || process.argv[2] === "--help" || process.argv[2] === "help") {
39
51
  console.log(help)
40
52
  process.exit(0)
41
53
  }
42
54
 
43
- if (command === "-v" || command === "--version" || command === "version") {
55
+ if (process.argv[2] === "-v" || process.argv[2] === "--version" || process.argv[2] === "version") {
44
56
  console.log(packageJson.version)
45
57
  process.exit(0)
46
58
  }
47
59
 
48
- if (command === "upgrade") {
49
- const proc = Bun.spawn({
50
- cmd: ["npm", "install", "-g", `${packageJson.name}@latest`],
51
- stdin: "inherit",
52
- stdout: "inherit",
53
- stderr: "inherit",
54
- })
55
- process.exit(await proc.exited)
60
+ if (process.argv[2] === "upgrade") {
61
+ const result = childProcess.spawnSync("npm", ["install", "-g", `${packageJson.name}@latest`], { stdio: "inherit" })
62
+ if (result.error) {
63
+ console.error(result.error.message)
64
+ process.exit(1)
65
+ }
66
+ process.exit(typeof result.status === "number" ? result.status : 0)
67
+ }
68
+
69
+ const scriptPath = fs.realpathSync(__filename)
70
+ const scriptDir = path.dirname(scriptPath)
71
+
72
+ const platform = platformMap[os.platform()]
73
+ const arch = archMap[os.arch()]
74
+
75
+ const isMusl = () => {
76
+ if (os.platform() !== "linux") return false
77
+ try {
78
+ if (fs.existsSync("/etc/alpine-release")) return true
79
+ } catch {}
80
+ try {
81
+ const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
82
+ return `${result.stdout ?? ""}${result.stderr ?? ""}`.toLowerCase().includes("musl")
83
+ } catch {
84
+ return false
85
+ }
56
86
  }
57
87
 
58
- if (command !== undefined) {
59
- const suggestion = commands.find((name) => editDistance(command, name) <= 2)
60
- console.error(`Unknown command: ${command}`)
61
- if (suggestion) console.error(`Did you mean: ghui ${suggestion}?`)
62
- console.error("Run `ghui --help` for usage.")
88
+ if (!platform || !arch) {
89
+ console.error(`Unsupported platform for ${packageJson.name}: ${os.platform()}-${os.arch()}`)
63
90
  process.exit(1)
64
91
  }
65
92
 
66
- const sourceEntry = new URL("../src/index.tsx", import.meta.url)
67
- if (await Bun.file(sourceEntry).exists()) {
68
- await import(sourceEntry.href)
69
- } else {
70
- await import("../dist/index.js")
93
+ if (platform === "linux" && isMusl()) {
94
+ console.error(`${packageJson.name} does not publish musl Linux binaries yet.`)
95
+ console.error("Use a glibc-based Linux distribution, Homebrew on Linux, or the source checkout with Bun.")
96
+ process.exit(1)
97
+ }
98
+
99
+ const packageName = `${packageJson.name}-${platform}-${arch}`
100
+
101
+ const resolveBinary = () => {
102
+ try {
103
+ const packageJsonPath = requireFromHere.resolve(`${packageName}/package.json`)
104
+ return path.join(path.dirname(packageJsonPath), "bin", "ghui")
105
+ } catch {
106
+ return null
107
+ }
108
+ }
109
+
110
+ const binaryPath = resolveBinary()
111
+
112
+ if (!binaryPath || !fs.existsSync(binaryPath)) {
113
+ const sourceEntry = path.join(scriptDir, "..", "src", "standalone.ts")
114
+ if (fs.existsSync(sourceEntry)) {
115
+ run("bun", [sourceEntry, ...process.argv.slice(2)])
116
+ }
117
+
118
+ console.error(`Could not find the ${packageName} binary package for this platform.`)
119
+ console.error(`Try reinstalling ${packageJson.name}, or install ${packageName} manually.`)
120
+ process.exit(1)
71
121
  }
122
+
123
+ run(binaryPath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitlangton/ghui",
3
- "version": "0.3.3",
3
+ "version": "0.4.1",
4
4
  "description": "Terminal UI for GitHub pull requests",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -16,60 +16,25 @@
16
16
  "github",
17
17
  "pull-requests",
18
18
  "terminal",
19
- "tui",
20
- "bun"
19
+ "tui"
21
20
  ],
21
+ "bin": {
22
+ "ghui": "bin/ghui.js"
23
+ },
22
24
  "files": [
23
25
  "bin",
24
- "dist",
25
26
  "README.md",
26
- ".env.example",
27
27
  "LICENSE"
28
28
  ],
29
+ "optionalDependencies": {
30
+ "@kitlangton/ghui-darwin-arm64": "0.4.1",
31
+ "@kitlangton/ghui-darwin-x64": "0.4.1",
32
+ "@kitlangton/ghui-linux-arm64": "0.4.1",
33
+ "@kitlangton/ghui-linux-x64": "0.4.1"
34
+ },
29
35
  "publishConfig": {
30
36
  "access": "public",
31
37
  "provenance": true,
32
38
  "registry": "https://registry.npmjs.org/"
33
- },
34
- "bin": {
35
- "ghui": "bin/ghui.js"
36
- },
37
- "scripts": {
38
- "build:cli": "bun run dev/build-cli.ts",
39
- "changeset": "npm exec --package @changesets/cli@2.31.0 -- changeset",
40
- "changeset:status": "npm exec --package @changesets/cli@2.31.0 -- changeset status",
41
- "changeset:version": "npm exec --package @changesets/cli@2.31.0 -- changeset version",
42
- "dev": "GHUI_MOTEL_PORT=${GHUI_MOTEL_PORT:-27686} bun --watch bin/ghui.js",
43
- "dev:logo": "bun --watch dev/loadingLogo.tsx",
44
- "start": "bun run src/index.tsx",
45
- "start:mock": "GHUI_MOCK_PR_COUNT=400 GHUI_MOCK_REPO_COUNT=4 bun run src/index.tsx",
46
- "test": "bun test test",
47
- "typecheck": "tsc --noEmit",
48
- "lint": "oxlint --tsconfig tsconfig.json src/ test/",
49
- "format": "oxfmt src/ test/ dev/",
50
- "format:check": "oxfmt --check src/ test/ dev/",
51
- "package:smoke": "bun run dev/package-smoke.ts",
52
- "prepack": "bun run build:cli"
53
- },
54
- "workspaces": [
55
- ".",
56
- "packages/*"
57
- ],
58
- "dependencies": {
59
- "@effect/atom-react": "4.0.0-beta.59",
60
- "@opentui/core": "0.2.1",
61
- "@opentui/react": "0.2.1",
62
- "effect": "4.0.0-beta.59",
63
- "react": "19.2.5",
64
- "scheduler": "0.27.0"
65
- },
66
- "devDependencies": {
67
- "@ghui/keymap": "workspace:*",
68
- "@effect/language-service": "0.85.1",
69
- "@types/bun": "1.3.12",
70
- "@types/react": "19.2.14",
71
- "oxfmt": "0.47.0",
72
- "oxlint": "1.62.0",
73
- "typescript": "6.0.2"
74
39
  }
75
40
  }
package/.env.example DELETED
@@ -1,6 +0,0 @@
1
- GHUI_AUTHOR=@me
2
- GHUI_PR_FETCH_LIMIT=200
3
-
4
- # Optional local observability. Motel's default local port is 27686.
5
- # GHUI_MOTEL_PORT=27686
6
- # GHUI_OTLP_ENDPOINT=http://127.0.0.1:27686