@wwkit/sshproxy 1.0.23 → 1.0.25

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/bin/index.js CHANGED
@@ -1,10 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { execSync } from 'node:child_process'
4
- import { readFileSync } from 'node:fs'
4
+ import { existsSync, readFileSync } from 'node:fs'
5
+ import { parseFlags } from '@wwkit/shared'
5
6
  import { ProxyManager } from '../src/ProxyManager.js'
6
7
  import { SshCommands } from '../src/SshCommands.js'
7
- import { clientAddr, loadConfig } from '../src/config.js'
8
+ import { clientAddr, loadConfig, getConfigPath, mergeBuiltinConfig } from '../src/config.js'
9
+
10
+ // Lazy-init: if user config doesn't exist (postinstall skipped), create it now
11
+ if (!existsSync(getConfigPath())) {
12
+ if (mergeBuiltinConfig()) {
13
+ console.log(`sshproxy: config initialized at ${getConfigPath()}`)
14
+ }
15
+ }
8
16
 
9
17
  const pkgVersion = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version
10
18
 
@@ -39,6 +47,8 @@ async function main() {
39
47
  console.log(pkgVersion)
40
48
  return
41
49
  case 'help':
50
+ case '-h':
51
+ case '--help':
42
52
  default:
43
53
  printHelp()
44
54
  }
@@ -50,26 +60,6 @@ function printResult(result) {
50
60
  if (result.ok === false) process.exitCode = 1
51
61
  }
52
62
 
53
- function parseOptions(tokens, flagDefs) {
54
- const options = {}
55
- const positional = []
56
- for (let i = 0; i < tokens.length; i++) {
57
- const t = tokens[i]
58
- const flag = flagDefs.find((f) => f.flag === t || (f.short && f.short === t))
59
- if (flag) {
60
- if (flag.boolean) {
61
- options[flag.name] = true
62
- } else {
63
- options[flag.name] = tokens[i + 1]
64
- i++
65
- }
66
- } else {
67
- positional.push(t)
68
- }
69
- }
70
- return { options, positional }
71
- }
72
-
73
63
  async function handleSsh(rest) {
74
64
  const sub = rest[0] ?? 'help'
75
65
  const commands = new SshCommands()
@@ -81,28 +71,23 @@ async function handleSsh(rest) {
81
71
  await commands.exec(rest.slice(1))
82
72
  break
83
73
  case 'upload': {
84
- const { options, positional } = parseOptions(rest.slice(1), [
85
- { flag: '-x', name: 'extract', boolean: true },
86
- { flag: '--rm', name: 'rm', boolean: true },
87
- ])
88
- await commands.upload(positional[0], positional[1], options)
74
+ const { flags, positional } = parseFlags(rest.slice(1), { booleans: ['extract', 'rm'] })
75
+ await commands.upload(positional[0], positional[1], { extract: flags.extract === 'true', rm: flags.rm === 'true' })
89
76
  break
90
77
  }
91
78
  case 'download': {
92
- const { options, positional } = parseOptions(rest.slice(1), [
93
- { flag: '-x', name: 'extract', boolean: true },
94
- { flag: '--rm', name: 'rm', boolean: true },
95
- ])
96
- await commands.download(positional[0], positional[1], options)
79
+ const { flags, positional } = parseFlags(rest.slice(1), { booleans: ['extract', 'rm'] })
80
+ await commands.download(positional[0], positional[1], { extract: flags.extract === 'true', rm: flags.rm === 'true' })
97
81
  break
98
82
  }
99
83
  case 'rsync': {
100
- const { options, positional } = parseOptions(rest.slice(1), [
101
- { flag: '-r', name: 'remote' },
102
- { flag: '-d', name: 'delete', boolean: true },
103
- { flag: '-n', name: 'dryRun', boolean: true },
104
- { flag: '-t', name: 'timeout' },
105
- ])
84
+ const { flags, positional } = parseFlags(rest.slice(1))
85
+ const options = {
86
+ remote: flags.remote && flags.remote !== 'true' ? flags.remote : undefined,
87
+ delete: flags.delete === 'true',
88
+ dryRun: flags['dry-run'] === 'true',
89
+ timeout: flags.timeout && flags.timeout !== 'true' ? flags.timeout : undefined,
90
+ }
106
91
  await commands.rsync(positional[0], options)
107
92
  break
108
93
  }
@@ -110,20 +95,19 @@ async function handleSsh(rest) {
110
95
  await commands.root()
111
96
  break
112
97
  case 'login': {
113
- const { options } = parseOptions(rest.slice(1), [
114
- { flag: '-f', name: 'force', boolean: true },
115
- ])
116
- await commands.login(options)
98
+ const { flags } = parseFlags(rest.slice(1), { booleans: ['f', 'force'] })
99
+ await commands.login({ force: flags.force === 'true' || flags.f === 'true' })
117
100
  break
118
101
  }
119
102
  case 'open':
120
103
  await commands.open()
121
104
  break
122
105
  case 'services': {
123
- const { options } = parseOptions(rest.slice(1), [
124
- { flag: '-a', name: 'all', boolean: true },
125
- { flag: '-f', name: 'find' },
126
- ])
106
+ const { flags } = parseFlags(rest.slice(1))
107
+ const options = {
108
+ all: flags.all === 'true' || flags.a === 'true',
109
+ find: flags.find && flags.find !== 'true' ? flags.find : undefined,
110
+ }
127
111
  await commands.services(options)
128
112
  break
129
113
  }
@@ -134,6 +118,8 @@ async function handleSsh(rest) {
134
118
  commands.config()
135
119
  break
136
120
  case 'help':
121
+ case '-h':
122
+ case '--help':
137
123
  default:
138
124
  printSshHelp()
139
125
  }
@@ -146,23 +132,23 @@ function printSshHelp() {
146
132
  sshproxy ssh connect 测试 SSH 连接
147
133
  sshproxy ssh exec <命令> 执行远程命令
148
134
  sshproxy ssh upload <本地> <远程> [选项] 上传文件到远程
149
- -x, --extract 上传后自动解压(zip/rar)
135
+ --extract 上传后自动解压(zip/rar)
150
136
  --rm 解压后删除压缩包
151
137
  sshproxy ssh download <远程> <本地> [选项] 从远程下载文件
152
- -x, --extract 下载后自动解压(zip/rar)
138
+ --extract 下载后自动解压(zip/rar)
153
139
  --rm 解压后删除压缩包
154
140
  sshproxy ssh rsync <本地目录> [选项] 通过 rsync 同步目录到远程
155
- -r, --remote <目录> 远程目标目录(默认 /htdocs)
156
- -d, --delete 镜像同步(删除远程多余文件)
157
- -n, --dry-run 试运行(只显示将传输的文件)
158
- -t, --timeout <秒> 连接超时(默认 30)
141
+ --remote <目录> 远程目标目录(默认 /htdocs)
142
+ --delete 镜像同步(删除远程多余文件)
143
+ --dry-run 试运行(只显示将传输的文件)
144
+ --timeout <秒> 连接超时(默认 30)
159
145
  sshproxy ssh root 显示远程主目录($HOME)
160
146
  sshproxy ssh login [选项] 安装本地公钥到远程实现免密登录
161
147
  -f, --force 强制覆盖 authorized_keys
162
148
  sshproxy ssh open 打开终端窗口并建立 SSH 连接
163
149
  sshproxy ssh services [选项] 列出远程服务器运行中的服务
164
150
  -a, --all 列出所有服务(不仅运行中)
165
- -f, --find <名称> 按名称筛选服务
151
+ --find <名称> 按名称筛选服务
166
152
  sshproxy ssh port <端口> 查看指定端口上的监听进程
167
153
  sshproxy ssh config 显示 SSH 配置
168
154
  sshproxy ssh help 显示本帮助
@@ -171,13 +157,13 @@ function printSshHelp() {
171
157
  sshproxy ssh exec ls -la /root
172
158
  sshproxy ssh upload ./config.py /root/config.py
173
159
  sshproxy ssh download /root/log/app.log ./app.log
174
- sshproxy ssh upload ./app.zip /root/app.zip -x --rm
175
- sshproxy ssh download /root/backup.zip ./backup.zip -x
160
+ sshproxy ssh upload ./app.zip /root/app.zip --extract --rm
161
+ sshproxy ssh download /root/backup.zip ./backup.zip --extract
176
162
  sshproxy ssh rsync ./webwork/
177
- sshproxy ssh rsync ./webwork/ -r /htdocs -d
178
- sshproxy ssh rsync ./webwork/ -r /htdocs -n
163
+ sshproxy ssh rsync ./webwork/ --remote /htdocs --delete
164
+ sshproxy ssh rsync ./webwork/ --remote /htdocs --dry-run
179
165
  sshproxy ssh services
180
- sshproxy ssh services -f nginx
166
+ sshproxy ssh services --find nginx
181
167
  sshproxy ssh port 80
182
168
  sshproxy ssh login
183
169
  sshproxy ssh open
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wwkit/sshproxy",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "author": "bluesliu <langcai163@163.com>",
5
5
  "description": "SOCKS5 proxy manager (client SSH tunnel / server remote), CLI + web UI",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  "dotenv": "^16.4.5",
38
38
  "json5": "^2.2.3",
39
39
  "ssh2": "^1.16.0",
40
- "@wwkit/shared": "1.0.23"
40
+ "@wwkit/shared": "1.0.26"
41
41
  },
42
42
  "devDependencies": {
43
43
  "jest": "^29.7.0"
package/src/config.js CHANGED
@@ -40,6 +40,14 @@ export function loadConfig() {
40
40
  return _loader.getConfig()
41
41
  }
42
42
 
43
+ /**
44
+ * 合并内置配置到用户配置文件(追加缺失 key,不覆盖已有值)
45
+ * @returns {boolean} 是否写入了文件
46
+ */
47
+ export function mergeBuiltinConfig() {
48
+ return _loader.mergeBuiltinConfig()
49
+ }
50
+
43
51
  // ============================================================
44
52
  // 静态配置(系统内置常量,存于 src/contains.json5,用户不可改)
45
53
  // ============================================================