@stevezhou/sisu 0.3.14 → 0.3.15
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 +1 -1
- package/package.json +3 -2
- package/scripts/ensure-cli-path.js +107 -0
- package/scripts/postinstall.js +7 -0
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ sisu login
|
|
|
13
13
|
sisu
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
`npm install -g` is a small JS package.
|
|
16
|
+
Postinstall links `sisu` into `~/.local/bin` (Debian/login PATH) and prints an `export PATH=...` line if this shell still cannot see the command. `npm install -g` is a small JS package. It also fetches the stamped SiSu TUI pager for **this package version** into `~/.sisu/bin` when a prebuilt exists. GitHub Release tags ship `darwin-arm64`, `linux-x64`, and `linux-arm64`. `darwin-x64` is opt-in (`workflow_dispatch` with `platforms` containing `darwin-x64`) and often missing; platforms without a binary, or a missing GitHub Release asset, keep the Node TUI.
|
|
17
17
|
|
|
18
18
|
Requires Node.js 20 or newer. `npx sisu` works without a global install.
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stevezhou/sisu",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "SiSu CLI — 思溯 / SiSu · 思有所溯",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://www.sisu.chat",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"NOTICE",
|
|
27
27
|
"third_party/grok-build",
|
|
28
28
|
"scripts/postinstall.js",
|
|
29
|
-
"scripts/install-pager.js"
|
|
29
|
+
"scripts/install-pager.js",
|
|
30
|
+
"scripts/ensure-cli-path.js"
|
|
30
31
|
],
|
|
31
32
|
"publishConfig": {
|
|
32
33
|
"access": "public"
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** After `npm i -g`, put `sisu` on a PATH users actually have.
|
|
3
|
+
* npm's global bin is often missing from Debian/login PATH.
|
|
4
|
+
*/
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const os = require('os')
|
|
7
|
+
const path = require('path')
|
|
8
|
+
|
|
9
|
+
function pathDirs(pathEnv = process.env.PATH || '') {
|
|
10
|
+
return pathEnv.split(path.delimiter).filter(Boolean)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function pathContains(dir, pathEnv = process.env.PATH || '') {
|
|
14
|
+
const target = path.resolve(dir)
|
|
15
|
+
return pathDirs(pathEnv).some((entry) => {
|
|
16
|
+
try {
|
|
17
|
+
return path.resolve(entry) === target
|
|
18
|
+
} catch {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function globalSisuBin(options = {}) {
|
|
25
|
+
const name = options.platform === 'win32' ? 'sisu.cmd' : 'sisu'
|
|
26
|
+
const prefix = options.prefix || process.env.npm_config_prefix || ''
|
|
27
|
+
const fromPrefix = prefix
|
|
28
|
+
? (options.platform === 'win32' ? path.join(prefix, name) : path.join(prefix, 'bin', name))
|
|
29
|
+
: ''
|
|
30
|
+
const fromLayout = path.resolve(
|
|
31
|
+
options.packageRoot || path.join(__dirname, '..'),
|
|
32
|
+
'..',
|
|
33
|
+
'..',
|
|
34
|
+
options.platform === 'win32' ? name : path.join('bin', name),
|
|
35
|
+
)
|
|
36
|
+
const exists = options.exists || ((file) => fs.existsSync(file))
|
|
37
|
+
for (const candidate of [fromPrefix, fromLayout]) {
|
|
38
|
+
if (candidate && exists(candidate)) return candidate
|
|
39
|
+
}
|
|
40
|
+
return fromPrefix || fromLayout
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function userLocalBin(home = os.homedir()) {
|
|
44
|
+
return path.join(home, '.local', 'bin')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function ensureUserShim(target, options = {}) {
|
|
48
|
+
if ((options.platform || process.platform) === 'win32') return null
|
|
49
|
+
if (!target) return null
|
|
50
|
+
const dir = userLocalBin(options.home || os.homedir())
|
|
51
|
+
const dest = path.join(dir, 'sisu')
|
|
52
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o755 })
|
|
53
|
+
try {
|
|
54
|
+
if (fs.lstatSync(dest)) fs.unlinkSync(dest)
|
|
55
|
+
} catch {
|
|
56
|
+
// missing
|
|
57
|
+
}
|
|
58
|
+
fs.symlinkSync(path.resolve(target), dest)
|
|
59
|
+
try {
|
|
60
|
+
fs.chmodSync(dest, 0o755)
|
|
61
|
+
} catch {
|
|
62
|
+
// symlink mode follows the target on most POSIX
|
|
63
|
+
}
|
|
64
|
+
return dest
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function pathHint(npmBin, localBin, pathEnv = process.env.PATH || '') {
|
|
68
|
+
const dirs = []
|
|
69
|
+
if (localBin && !pathContains(localBin, pathEnv)) dirs.push(localBin)
|
|
70
|
+
if (npmBin && !pathContains(npmBin, pathEnv)) dirs.push(npmBin)
|
|
71
|
+
if (!dirs.length) return ''
|
|
72
|
+
return `export PATH="${dirs.join(':')}:$PATH" && hash -r`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function installCliPath(options = {}) {
|
|
76
|
+
const writes = options.write || ((text) => process.stdout.write(text))
|
|
77
|
+
const platform = options.platform || process.platform
|
|
78
|
+
const bin = globalSisuBin(options)
|
|
79
|
+
const npmBinDir = bin ? path.dirname(bin) : ''
|
|
80
|
+
let shim = null
|
|
81
|
+
try {
|
|
82
|
+
shim = ensureUserShim(bin, options)
|
|
83
|
+
} catch (error) {
|
|
84
|
+
writes(`sisu: could not link ~/.local/bin/sisu (${error instanceof Error ? error.message : String(error)})\n`)
|
|
85
|
+
}
|
|
86
|
+
const localDir = shim ? path.dirname(shim) : userLocalBin(options.home)
|
|
87
|
+
const hint = pathHint(npmBinDir, localDir, options.pathEnv)
|
|
88
|
+
if (bin) writes(`sisu: command -> ${shim || bin}\n`)
|
|
89
|
+
if (hint) {
|
|
90
|
+
writes('sisu: if `sisu` is not found in this shell, run:\n')
|
|
91
|
+
writes(` ${hint}\n`)
|
|
92
|
+
}
|
|
93
|
+
return { bin, shim, hint }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = {
|
|
97
|
+
ensureUserShim,
|
|
98
|
+
globalSisuBin,
|
|
99
|
+
installCliPath,
|
|
100
|
+
pathContains,
|
|
101
|
+
pathHint,
|
|
102
|
+
userLocalBin,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (require.main === module) {
|
|
106
|
+
installCliPath()
|
|
107
|
+
}
|
package/scripts/postinstall.js
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
* Never fail `npm install` — Node TUI still works without the binary.
|
|
4
4
|
*/
|
|
5
5
|
const { installPager } = require('./install-pager')
|
|
6
|
+
const { installCliPath } = require('./ensure-cli-path')
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
installCliPath()
|
|
10
|
+
} catch (error) {
|
|
11
|
+
process.stdout.write(`sisu: path setup skipped (${error instanceof Error ? error.message : String(error)})\n`)
|
|
12
|
+
}
|
|
6
13
|
|
|
7
14
|
installPager().then(
|
|
8
15
|
(result) => {
|