@wwkit/opm 1.0.14 → 1.0.16
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 +33 -8
- package/docs/managers/apt.md +0 -1
- package/docs/managers/brew.md +0 -4
- package/docs/managers/bun.md +0 -2
- package/docs/managers/composer.md +0 -4
- package/docs/managers/dnf.md +0 -1
- package/docs/managers/npm.md +0 -4
- package/docs/managers/pip.md +0 -4
- package/docs/opm.html +8 -21
- package/docs/test/linux-environment-test-report.md +0 -1
- package/package.json +13 -4
- package/src/binaries/base.js +1 -1
- package/src/cli/groups/env.js +451 -0
- package/src/cli/groups/package.js +30 -10
- package/src/cli/groups/ping.js +60 -20
- package/src/cli/index.js +3 -1
- package/src/index.js +2 -1
- package/src/managers/apt.js +0 -17
- package/src/managers/base.js +0 -15
- package/src/managers/brew.js +1 -32
- package/src/managers/bun.js +7 -58
- package/src/managers/composer.js +1 -16
- package/src/managers/dnf.js +0 -17
- package/src/managers/npm.js +0 -20
- package/src/managers/pip.js +1 -22
- package/src/managers/proc.js +7 -1
- package/src/managers/runtime.js +0 -4
- package/src/managers/winget.js +0 -14
- package/src/managers/http.js +0 -432
package/src/cli/groups/ping.js
CHANGED
|
@@ -18,6 +18,9 @@ import { getActiveProxy, getActiveRegistry, getConfig } from '../../config.js'
|
|
|
18
18
|
|
|
19
19
|
const shell = new Shell()
|
|
20
20
|
|
|
21
|
+
// 跨平台 null device(curl -o 丢弃输出体)
|
|
22
|
+
const NULL_DEV = process.platform === 'win32' ? 'NUL' : '/dev/null'
|
|
23
|
+
|
|
21
24
|
/**
|
|
22
25
|
* 从 URL 或 deb 行中提取主机名和端口(用于 ping 目标)
|
|
23
26
|
* @param {string} url
|
|
@@ -47,8 +50,9 @@ function isUrl(addr) {
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
// HTTP 状态码 → 可达性判断:2xx/3xx 视为可达,allowlist 中的状态码
|
|
50
|
-
// 虽非成功响应但证明服务器已响应(如 404
|
|
51
|
-
|
|
53
|
+
// 虽非成功响应但证明服务器已响应(如 404 表示主机/代理存活,
|
|
54
|
+
// 429 表示临时限流,服务器实际存活)
|
|
55
|
+
const REACHABLE_ALLOWLIST = [404, 429]
|
|
52
56
|
|
|
53
57
|
function httpReachable(httpCode) {
|
|
54
58
|
return (httpCode >= 200 && httpCode < 400) || REACHABLE_ALLOWLIST.includes(httpCode)
|
|
@@ -85,7 +89,16 @@ function checkByPing(host, count) {
|
|
|
85
89
|
? ['-n', String(count), '-w', '2000', host]
|
|
86
90
|
: ['-c', String(count), '-W', '2', host]
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
let child
|
|
93
|
+
try {
|
|
94
|
+
child = spawn('ping', args, { stdio: ['pipe', 'pipe', 'pipe'], shell: true })
|
|
95
|
+
} catch {
|
|
96
|
+
resolve({
|
|
97
|
+
reachable: false, sent: count, received: 0, loss: count,
|
|
98
|
+
lossPercent: 100, rttMin: '', rttAvg: '', rttMax: '', raw: 'ping command failed to execute',
|
|
99
|
+
})
|
|
100
|
+
return
|
|
101
|
+
}
|
|
89
102
|
let stdout = ''
|
|
90
103
|
let stderr = ''
|
|
91
104
|
child.stdout.on('data', (d) => { stdout += d })
|
|
@@ -154,10 +167,19 @@ function checkByPing(host, count) {
|
|
|
154
167
|
*/
|
|
155
168
|
function checkByCurl(url, proxy) {
|
|
156
169
|
return new Promise((resolve) => {
|
|
157
|
-
const args = ['-k', '-L', '-s', '-o',
|
|
170
|
+
const args = ['-k', '-L', '-s', '-o', NULL_DEV, '-w', '%{http_code} %{time_total}', '--connect-timeout', '2', '--max-time', '5']
|
|
158
171
|
if (proxy) args.push('-x', proxy)
|
|
159
172
|
args.push(url)
|
|
160
|
-
|
|
173
|
+
let child
|
|
174
|
+
try {
|
|
175
|
+
child = spawn('curl', args, { stdio: ['pipe', 'pipe', 'pipe'], shell: true })
|
|
176
|
+
} catch {
|
|
177
|
+
resolve({
|
|
178
|
+
reachable: false, sent: 1, received: 0, loss: 1,
|
|
179
|
+
lossPercent: 100, rttMin: '', rttAvg: '', rttMax: '', raw: 'curl failed to execute',
|
|
180
|
+
})
|
|
181
|
+
return
|
|
182
|
+
}
|
|
161
183
|
let stdout = ''
|
|
162
184
|
let stderr = ''
|
|
163
185
|
child.stdout.on('data', (d) => { stdout += d })
|
|
@@ -204,7 +226,16 @@ function checkByWget(url, proxy) {
|
|
|
204
226
|
args.push('-e', `use_proxy=yes`, '-e', `https_proxy=${proxy}`, '-e', `http_proxy=${proxy}`)
|
|
205
227
|
}
|
|
206
228
|
args.push(url)
|
|
207
|
-
|
|
229
|
+
let child
|
|
230
|
+
try {
|
|
231
|
+
child = spawn('wget', args, { stdio: ['pipe', 'pipe', 'pipe'], shell: true })
|
|
232
|
+
} catch {
|
|
233
|
+
resolve({
|
|
234
|
+
reachable: false, sent: 1, received: 0, loss: 1,
|
|
235
|
+
lossPercent: 100, rttMin: '', rttAvg: '', rttMax: '', raw: 'wget failed to execute',
|
|
236
|
+
})
|
|
237
|
+
return
|
|
238
|
+
}
|
|
208
239
|
let stdout = ''
|
|
209
240
|
let stderr = ''
|
|
210
241
|
child.stdout.on('data', (d) => { stdout += d })
|
|
@@ -271,7 +302,7 @@ async function checkReachability(address, tool, count, proxy) {
|
|
|
271
302
|
return { reachable: false, sent: 0, received: 0, loss: 0, lossPercent: 0, rttMin: '', rttAvg: '', rttMax: '', raw: 'No tool available' }
|
|
272
303
|
}
|
|
273
304
|
|
|
274
|
-
export { checkReachability, extractHostPort }
|
|
305
|
+
export { checkReachability, extractHostPort, httpReachable }
|
|
275
306
|
|
|
276
307
|
export class PingGroup {
|
|
277
308
|
constructor() {
|
|
@@ -298,12 +329,9 @@ export class PingGroup {
|
|
|
298
329
|
const n = (isNaN(count) || count < 1) ? 4 : count
|
|
299
330
|
const detail = !!(parsed.flags.d || parsed.flags.detail)
|
|
300
331
|
|
|
301
|
-
let proxy = ''
|
|
302
|
-
if ('
|
|
303
|
-
|
|
304
|
-
if (raw === 'true') raw = ''
|
|
305
|
-
proxy = raw || getActiveProxy()
|
|
306
|
-
}
|
|
332
|
+
let proxy = parsed.flags.proxy || parsed.flags.p || ''
|
|
333
|
+
if (proxy === 'true') proxy = ''
|
|
334
|
+
if (!proxy) proxy = getActiveProxy()
|
|
307
335
|
|
|
308
336
|
if (target === 'proxy') {
|
|
309
337
|
return this._pingProxy(n, detail, tool)
|
|
@@ -318,7 +346,8 @@ export class PingGroup {
|
|
|
318
346
|
}
|
|
319
347
|
|
|
320
348
|
if (proxy) {
|
|
321
|
-
const
|
|
349
|
+
const testUrl = isUrl(target) ? target : undefined
|
|
350
|
+
const usable = await this._checkProxyUsable(proxy, tool, n, testUrl)
|
|
322
351
|
if (!usable.ok) {
|
|
323
352
|
console.error(`[opm] Proxy not usable: ${usable.reason}`)
|
|
324
353
|
process.exit(1)
|
|
@@ -331,12 +360,16 @@ export class PingGroup {
|
|
|
331
360
|
}
|
|
332
361
|
|
|
333
362
|
/**
|
|
334
|
-
*
|
|
363
|
+
* 检查代理是否可用:通过代理访问指定 URL 测试
|
|
364
|
+
* @param {string} proxyUrl - 代理地址
|
|
365
|
+
* @param {string} tool - 检测工具
|
|
366
|
+
* @param {number} count - ping 包数量
|
|
367
|
+
* @param {string} [testUrl] - 测试 URL(默认 npm active registry)
|
|
335
368
|
* @returns {{ ok: boolean, reason: string }}
|
|
336
369
|
*/
|
|
337
|
-
async _checkProxyUsable(proxyUrl, tool, count) {
|
|
338
|
-
const
|
|
339
|
-
const result = await checkReachability(
|
|
370
|
+
async _checkProxyUsable(proxyUrl, tool, count, testUrl) {
|
|
371
|
+
const url = testUrl || getActiveRegistry('npm')
|
|
372
|
+
const result = await checkReachability(url, tool, count, proxyUrl)
|
|
340
373
|
if (result.proxyAuthRequired) {
|
|
341
374
|
return { ok: false, reason: 'authentication required (HTTP 407)' }
|
|
342
375
|
}
|
|
@@ -376,7 +409,13 @@ export class PingGroup {
|
|
|
376
409
|
const tools = getRegistryTools()
|
|
377
410
|
|
|
378
411
|
if (proxy) {
|
|
379
|
-
|
|
412
|
+
// 用首个可用 registry URL 作为代理可用性测试目标(而非硬编码 npm)
|
|
413
|
+
let testUrl = ''
|
|
414
|
+
for (const t of tools) {
|
|
415
|
+
const u = getActiveRegistry(t)
|
|
416
|
+
if (u) { testUrl = u; break }
|
|
417
|
+
}
|
|
418
|
+
const usable = await this._checkProxyUsable(proxy, tool, 1, testUrl)
|
|
380
419
|
if (!usable.ok) {
|
|
381
420
|
console.error(`[opm] Proxy not usable: ${usable.reason}`)
|
|
382
421
|
process.exit(1)
|
|
@@ -459,7 +498,8 @@ Actions:
|
|
|
459
498
|
|
|
460
499
|
Options:
|
|
461
500
|
-c, --count <n> Number of packets to send (ping only; default: 4)
|
|
462
|
-
-p, --proxy <url>
|
|
501
|
+
-p, --proxy <url> Proxy address for the check (overrides config proxy.active;
|
|
502
|
+
routes curl/wget requests through the proxy and pre-validates usability)
|
|
463
503
|
-d, --detail Output full JSON details (default: compact [{tool, address, proxy, reachable}])
|
|
464
504
|
-h, --help Show this help
|
|
465
505
|
|
package/src/cli/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { EnsureGroup } from './groups/ensure.js'
|
|
|
21
21
|
import { PingGroup } from './groups/ping.js'
|
|
22
22
|
import { ProcGroup } from './groups/proc.js'
|
|
23
23
|
import { OverlayGroup } from './groups/overlay.js'
|
|
24
|
+
import { EnvGroup } from './groups/env.js'
|
|
24
25
|
import { FtpGroup } from '../tools/ftp/index.js'
|
|
25
26
|
import { GitGroup } from '../tools/git/index.js'
|
|
26
27
|
import { ShareGroup } from '../tools/share/index.js'
|
|
@@ -66,6 +67,7 @@ const GROUPS = {
|
|
|
66
67
|
ping: new PingGroup(),
|
|
67
68
|
proc: new ProcGroup(),
|
|
68
69
|
overlay: new OverlayGroup(),
|
|
70
|
+
env: new EnvGroup(),
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
class CLI {
|
|
@@ -130,7 +132,7 @@ ${groupLines}
|
|
|
130
132
|
|
|
131
133
|
Options:
|
|
132
134
|
-g, --global Global operation (npm: global node_modules; pip: system Python)
|
|
133
|
-
-p, --proxy <url> Proxy address (search/info/versions/
|
|
135
|
+
-p, --proxy <url> Proxy address (search/info/versions/install/upgrade)
|
|
134
136
|
-h, --help Show help
|
|
135
137
|
|
|
136
138
|
Run "opm <command> help" for command details.
|
package/src/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export { DockerGroup } from './cli/groups/docker.js'
|
|
|
23
23
|
export { PingGroup } from './cli/groups/ping.js'
|
|
24
24
|
export { ProcGroup } from './cli/groups/proc.js'
|
|
25
25
|
export { OverlayGroup } from './cli/groups/overlay.js'
|
|
26
|
+
export { EnvGroup, parseEnvBlocks, parseRegOutput, isValidEnvKey } from './cli/groups/env.js'
|
|
26
27
|
export { FtpGroup } from './tools/ftp/index.js'
|
|
27
28
|
export { GitGroup } from './tools/git/index.js'
|
|
28
29
|
export { ShareGroup } from './tools/share/index.js'
|
|
@@ -62,7 +63,7 @@ export {
|
|
|
62
63
|
} from './presets.js'
|
|
63
64
|
export { PROXY_PRESETS } from './proxy-presets.js'
|
|
64
65
|
export { output } from './formatter.js'
|
|
65
|
-
export { downloadToFile, fetchText } from '
|
|
66
|
+
export { downloadToFile, fetchText } from '@wwkit/shared'
|
|
66
67
|
export {
|
|
67
68
|
getConfig, getSection, copyBuiltinConfig, getActiveRegistry, setActiveRegistry,
|
|
68
69
|
getUserConfigDir, getUserConfigFile, getActiveProxy,
|
package/src/managers/apt.js
CHANGED
|
@@ -326,23 +326,6 @@ export class AptManager extends PackageManager {
|
|
|
326
326
|
return { name, versions, registry }
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
async listOutdated(opts = {}) {
|
|
330
|
-
const out = this._exec(['list', '--upgradable', ...this._proxyArgs(opts.proxy)], { allowNonZero: true })
|
|
331
|
-
const items = []
|
|
332
|
-
for (const line of this._parseLines(out)) {
|
|
333
|
-
const m = line.match(/^(\S+?)\/(\S+)\s+(\S+)\s+(\S+)\s+\[(.*?)\]$/)
|
|
334
|
-
if (m) {
|
|
335
|
-
const from = m[5].match(/upgradable from:\s*(\S+)/)
|
|
336
|
-
items.push({
|
|
337
|
-
name: m[1],
|
|
338
|
-
current: from ? from[1] : '',
|
|
339
|
-
latest: m[3]
|
|
340
|
-
})
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return items
|
|
344
|
-
}
|
|
345
|
-
|
|
346
329
|
async install(name, version, opts = {}) {
|
|
347
330
|
const spec = version ? `${name}=${version}` : name
|
|
348
331
|
const args = ['get', 'install', '-y', spec, ...this._proxyArgs(opts.proxy)]
|
package/src/managers/base.js
CHANGED
|
@@ -30,12 +30,6 @@
|
|
|
30
30
|
* @typedef {Object} InstalledItem
|
|
31
31
|
* @property {string} name - 包名
|
|
32
32
|
* @property {string} version - 版本
|
|
33
|
-
*
|
|
34
|
-
* @typedef {Object} OutdatedItem
|
|
35
|
-
* @property {string} name - 包名
|
|
36
|
-
* @property {string} current - 当前版本
|
|
37
|
-
* @property {string} [wanted] - 期望版本
|
|
38
|
-
* @property {string} latest - 最新版本
|
|
39
33
|
*/
|
|
40
34
|
export class PackageManager {
|
|
41
35
|
constructor() {
|
|
@@ -132,15 +126,6 @@ export class PackageManager {
|
|
|
132
126
|
throw new Error(`${this.name}: listInstalled not implemented`)
|
|
133
127
|
}
|
|
134
128
|
|
|
135
|
-
/**
|
|
136
|
-
* 列出过期包
|
|
137
|
-
* @param {{ global?: boolean, proxy?: string }} [opts] - 选项
|
|
138
|
-
* @returns {Promise<OutdatedItem[]>}
|
|
139
|
-
*/
|
|
140
|
-
async listOutdated(opts) {
|
|
141
|
-
throw new Error(`${this.name}: listOutdated not implemented`)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
129
|
/**
|
|
145
130
|
* 安装包
|
|
146
131
|
* @param {string} name - 包名
|
package/src/managers/brew.js
CHANGED
|
@@ -166,6 +166,7 @@ export class BrewManager extends PackageManager {
|
|
|
166
166
|
_execInherit(args, opts = {}) {
|
|
167
167
|
const result = spawnSync(this._brewBin(), args, {
|
|
168
168
|
stdio: 'inherit',
|
|
169
|
+
shell: true,
|
|
169
170
|
env: this._buildEnv(opts.proxy),
|
|
170
171
|
})
|
|
171
172
|
if (result.error) {
|
|
@@ -213,33 +214,6 @@ export class BrewManager extends PackageManager {
|
|
|
213
214
|
return items
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
/**
|
|
217
|
-
* 解析 brew outdated --json=v2 输出为过期项数组(formulae + casks)
|
|
218
|
-
* @param {string} text
|
|
219
|
-
* @returns {{ name: string, current: string, latest: string }[]}
|
|
220
|
-
* @private
|
|
221
|
-
*/
|
|
222
|
-
_parseOutdatedJson(text) {
|
|
223
|
-
let data
|
|
224
|
-
try {
|
|
225
|
-
data = JSON.parse(text)
|
|
226
|
-
} catch {
|
|
227
|
-
return []
|
|
228
|
-
}
|
|
229
|
-
const items = []
|
|
230
|
-
for (const group of ['formulae', 'casks']) {
|
|
231
|
-
const list = Array.isArray(data[group]) ? data[group] : []
|
|
232
|
-
for (const item of list) {
|
|
233
|
-
items.push({
|
|
234
|
-
name: item.name,
|
|
235
|
-
current: (Array.isArray(item.installed_versions) ? item.installed_versions : []).join(', '),
|
|
236
|
-
latest: item.current_version || '',
|
|
237
|
-
})
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return items
|
|
241
|
-
}
|
|
242
|
-
|
|
243
217
|
async getVersion() {
|
|
244
218
|
try {
|
|
245
219
|
const out = this._exec(['--version'], { allowNonZero: true })
|
|
@@ -340,11 +314,6 @@ export class BrewManager extends PackageManager {
|
|
|
340
314
|
return { name, versions, registry }
|
|
341
315
|
}
|
|
342
316
|
|
|
343
|
-
async listOutdated(opts = {}) {
|
|
344
|
-
const out = this._exec(['outdated', '--json=v2'], { allowNonZero: true, proxy: opts.proxy })
|
|
345
|
-
return this._parseOutdatedJson(out)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
317
|
async install(name, version, opts = {}) {
|
|
349
318
|
if (!isHomebrewInstalled()) {
|
|
350
319
|
console.log('[opm] Homebrew not installed, auto-installing...')
|
package/src/managers/bun.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* bun 包管理器实现
|
|
3
3
|
*
|
|
4
4
|
* Bun 是全栈 JS 工具链(runtime + 包管理器 + 打包器)。
|
|
5
|
-
* 包管理命令通过 bun CLI
|
|
5
|
+
* 包管理命令通过 bun CLI 实现,源查询通过共享 fetchText 查 npm registry。
|
|
6
6
|
* 镜像通过 BUN_CONFIG_REGISTRY 环境变量传递给 bun 命令。
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -11,6 +11,7 @@ import fs from 'node:fs'
|
|
|
11
11
|
import os from 'node:os'
|
|
12
12
|
import path from 'node:path'
|
|
13
13
|
import { PackageManager } from './base.js'
|
|
14
|
+
import { fetchText } from '@wwkit/shared'
|
|
14
15
|
import { getActiveRegistry, setActiveRegistry } from '../config.js'
|
|
15
16
|
|
|
16
17
|
export class BunManager extends PackageManager {
|
|
@@ -108,52 +109,24 @@ export class BunManager extends PackageManager {
|
|
|
108
109
|
|
|
109
110
|
/**
|
|
110
111
|
* 通过 HTTP 查询 npm registry 获取包元数据
|
|
112
|
+
* 使用共享 fetchText(支持 HTTP/SOCKS5 代理隧道,与 pip/composer 一致)
|
|
111
113
|
* @param {string} pkgName
|
|
112
114
|
* @param {{ proxy?: string }} [opts]
|
|
113
115
|
* @returns {Promise<object|null>}
|
|
114
116
|
* @private
|
|
115
117
|
*/
|
|
116
118
|
async _fetchRegistryMetadata(pkgName, opts = {}) {
|
|
117
|
-
const registry = getActiveRegistry('bun').replace(/\/$/, '')
|
|
119
|
+
const registry = (getActiveRegistry('bun') || 'https://registry.npmjs.org').replace(/\/$/, '')
|
|
118
120
|
const url = `${registry}/${encodeURIComponent(pkgName).replace('%40', '@')}`
|
|
119
121
|
try {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const proxyAgent = opts.proxy ? await this._getProxyAgent(opts.proxy) : null
|
|
124
|
-
return new Promise((resolve) => {
|
|
125
|
-
const req = client.get(url, { agent: proxyAgent }, (res) => {
|
|
126
|
-
let data = ''
|
|
127
|
-
res.on('data', (chunk) => (data += chunk))
|
|
128
|
-
res.on('end', () => {
|
|
129
|
-
try {
|
|
130
|
-
resolve(JSON.parse(data))
|
|
131
|
-
} catch {
|
|
132
|
-
resolve(null)
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
})
|
|
136
|
-
req.on('error', () => resolve(null))
|
|
137
|
-
req.setTimeout(15000, () => {
|
|
138
|
-
req.destroy()
|
|
139
|
-
resolve(null)
|
|
140
|
-
})
|
|
141
|
-
})
|
|
122
|
+
const text = await fetchText(url, { proxy: opts.proxy })
|
|
123
|
+
if (!text) return null
|
|
124
|
+
return JSON.parse(text)
|
|
142
125
|
} catch {
|
|
143
126
|
return null
|
|
144
127
|
}
|
|
145
128
|
}
|
|
146
129
|
|
|
147
|
-
/**
|
|
148
|
-
* 获取 proxy agent(简化实现,仅支持 http proxy)
|
|
149
|
-
* @param {string} proxy
|
|
150
|
-
* @returns {Promise<undefined>}
|
|
151
|
-
* @private
|
|
152
|
-
*/
|
|
153
|
-
async _getProxyAgent(proxy) {
|
|
154
|
-
return undefined
|
|
155
|
-
}
|
|
156
|
-
|
|
157
130
|
async getVersion() {
|
|
158
131
|
try {
|
|
159
132
|
const version = this._exec(['--version'], { allowNonZero: true }).trim()
|
|
@@ -269,30 +242,6 @@ export class BunManager extends PackageManager {
|
|
|
269
242
|
return { name, versions, registry }
|
|
270
243
|
}
|
|
271
244
|
|
|
272
|
-
async listOutdated(opts = {}) {
|
|
273
|
-
const args = ['outdated']
|
|
274
|
-
if (opts.global) args.push('-g')
|
|
275
|
-
try {
|
|
276
|
-
const out = this._exec(args, { allowNonZero: true, proxy: opts.proxy })
|
|
277
|
-
const items = []
|
|
278
|
-
const lines = out.split('\n')
|
|
279
|
-
for (const line of lines) {
|
|
280
|
-
const parts = line.trim().split(/\s+/)
|
|
281
|
-
if (parts.length >= 3 && parts[0] !== 'package' && parts[0] !== 'name') {
|
|
282
|
-
items.push({
|
|
283
|
-
name: parts[0],
|
|
284
|
-
current: parts[1] || 'unknown',
|
|
285
|
-
wanted: parts[1] || '',
|
|
286
|
-
latest: parts[2] || 'unknown',
|
|
287
|
-
})
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return items
|
|
291
|
-
} catch {
|
|
292
|
-
return []
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
245
|
async install(name, version, opts = {}) {
|
|
297
246
|
const spec = version ? `${name}@${version}` : name
|
|
298
247
|
const args = ['add', spec]
|
package/src/managers/composer.js
CHANGED
|
@@ -14,7 +14,7 @@ import fs from 'node:fs'
|
|
|
14
14
|
import os from 'node:os'
|
|
15
15
|
import path from 'node:path'
|
|
16
16
|
import { PackageManager } from './base.js'
|
|
17
|
-
import { fetchText } from '
|
|
17
|
+
import { fetchText } from '@wwkit/shared'
|
|
18
18
|
import { getActiveRegistry, setActiveRegistry } from '../config.js'
|
|
19
19
|
|
|
20
20
|
export class ComposerManager extends PackageManager {
|
|
@@ -298,21 +298,6 @@ export class ComposerManager extends PackageManager {
|
|
|
298
298
|
return { name, versions, registry }
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
async listOutdated(opts = {}) {
|
|
302
|
-
const out = this._exec(['outdated', '--format=json'], { allowNonZero: true, proxy: opts.proxy })
|
|
303
|
-
try {
|
|
304
|
-
const data = JSON.parse(out)
|
|
305
|
-
const installed = Array.isArray(data.installed) ? data.installed : []
|
|
306
|
-
return installed.map((item) => ({
|
|
307
|
-
name: item.name,
|
|
308
|
-
current: item.version || '',
|
|
309
|
-
latest: item.latest || '',
|
|
310
|
-
}))
|
|
311
|
-
} catch {
|
|
312
|
-
return []
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
301
|
async install(name, version, opts = {}) {
|
|
317
302
|
const spec = version ? `${name}:${version}` : name
|
|
318
303
|
this._execInherit(['require', spec, '--no-interaction'], { proxy: opts.proxy })
|
package/src/managers/dnf.js
CHANGED
|
@@ -319,23 +319,6 @@ export class DnfManager extends PackageManager {
|
|
|
319
319
|
return { name, versions, registry }
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
async listOutdated(opts = {}) {
|
|
323
|
-
const args = ['list', '--upgrades', ...this._proxyArgs(opts.proxy)]
|
|
324
|
-
const out = this._exec(args, { allowNonZero: true })
|
|
325
|
-
const items = []
|
|
326
|
-
for (const line of this._parseLines(out)) {
|
|
327
|
-
const parts = line.split(/\s+/)
|
|
328
|
-
if (parts.length >= 3 && parts[1].includes('-')) {
|
|
329
|
-
items.push({
|
|
330
|
-
name: parts[0].replace(ARCH_SUFFIX, ''),
|
|
331
|
-
current: parts[1],
|
|
332
|
-
latest: parts[2]
|
|
333
|
-
})
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return items
|
|
337
|
-
}
|
|
338
|
-
|
|
339
322
|
async install(name, version, opts = {}) {
|
|
340
323
|
const spec = version ? `${name}-${version}` : name
|
|
341
324
|
const args = ['install', '-y', spec, ...this._proxyArgs(opts.proxy)]
|
package/src/managers/npm.js
CHANGED
|
@@ -422,26 +422,6 @@ export class NpmManager extends PackageManager {
|
|
|
422
422
|
return { name, versions: [], registry }
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
async listOutdated(opts = {}) {
|
|
426
|
-
try {
|
|
427
|
-
const args = ['outdated']
|
|
428
|
-
if (opts.global) args.push('-g')
|
|
429
|
-
args.push(...this._proxyArgs(opts.proxy))
|
|
430
|
-
args.push(...this._registryArgs())
|
|
431
|
-
const data = this._execJson(args)
|
|
432
|
-
if (!data) return []
|
|
433
|
-
const items = Object.entries(data).map(([name, info]) => ({
|
|
434
|
-
name,
|
|
435
|
-
current: info.current || 'missing',
|
|
436
|
-
wanted: info.wanted || '',
|
|
437
|
-
latest: info.latest || ''
|
|
438
|
-
}))
|
|
439
|
-
return items
|
|
440
|
-
} catch (err) {
|
|
441
|
-
throw new Error(`npm outdated failed: ${err.message}`)
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
425
|
/**
|
|
446
426
|
* 查询 npm 主版本号(缓存),用于判断是否支持 --allow-scripts(npm >= 11)
|
|
447
427
|
* @returns {number}
|
package/src/managers/pip.js
CHANGED
|
@@ -9,7 +9,7 @@ import { execSync, spawnSync } from 'node:child_process'
|
|
|
9
9
|
import path from 'node:path'
|
|
10
10
|
import { URL } from 'node:url'
|
|
11
11
|
import { PackageManager } from './base.js'
|
|
12
|
-
import { fetchText } from '
|
|
12
|
+
import { fetchText } from '@wwkit/shared'
|
|
13
13
|
import { getActiveRegistry, setActiveRegistry } from '../config.js'
|
|
14
14
|
|
|
15
15
|
export class PipManager extends PackageManager {
|
|
@@ -511,27 +511,6 @@ export class PipManager extends PackageManager {
|
|
|
511
511
|
return { name, versions: [], registry }
|
|
512
512
|
}
|
|
513
513
|
|
|
514
|
-
async listOutdated(opts = {}) {
|
|
515
|
-
try {
|
|
516
|
-
const args = ['list', '--outdated', '--format=json']
|
|
517
|
-
if (opts.proxy) args.push('--proxy', opts.proxy)
|
|
518
|
-
const jsonOut = this._execPip(args, { ...opts, allowNonZero: true })
|
|
519
|
-
const parsed = JSON.parse(jsonOut)
|
|
520
|
-
if (!Array.isArray(parsed)) return []
|
|
521
|
-
return parsed.map((item) => ({
|
|
522
|
-
name: item.name || '',
|
|
523
|
-
current: item.version || '',
|
|
524
|
-
latest: item.latest_version || '',
|
|
525
|
-
...(opts.global ? { global: true } : {})
|
|
526
|
-
}))
|
|
527
|
-
} catch (err) {
|
|
528
|
-
if (err.message.includes('No packages') || err.message.includes('No broken')) {
|
|
529
|
-
return []
|
|
530
|
-
}
|
|
531
|
-
throw new Error(`pip list --outdated failed: ${err.message}`)
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
514
|
async install(name, version, opts = {}) {
|
|
536
515
|
const spec = version ? `${name}==${version}` : name
|
|
537
516
|
const args = ['install', spec]
|
package/src/managers/proc.js
CHANGED
|
@@ -52,7 +52,13 @@ export async function getPortMap() {
|
|
|
52
52
|
const args = shell.isWindows ? ['-ano'] : ['-tlnp']
|
|
53
53
|
|
|
54
54
|
return new Promise((resolve) => {
|
|
55
|
-
|
|
55
|
+
let child
|
|
56
|
+
try {
|
|
57
|
+
child = spawn(fallback, args, { stdio: ['pipe', 'pipe', 'pipe'], shell: true })
|
|
58
|
+
} catch {
|
|
59
|
+
resolve(map)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
56
62
|
let stdout = ''
|
|
57
63
|
child.stdout.on('data', (d) => { stdout += d })
|
|
58
64
|
child.on('close', () => {
|
package/src/managers/runtime.js
CHANGED
|
@@ -237,10 +237,6 @@ export class RuntimeManager extends PackageManager {
|
|
|
237
237
|
return this._parseInstalled(out)
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
async listOutdated(opts = {}) {
|
|
241
|
-
return []
|
|
242
|
-
}
|
|
243
|
-
|
|
244
240
|
async install(name, version, opts = {}) {
|
|
245
241
|
if (!version) {
|
|
246
242
|
throw new Error(this.cfg.installUsage)
|
package/src/managers/winget.js
CHANGED
|
@@ -221,20 +221,6 @@ export class WingetManager extends PackageManager {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
async listOutdated(opts = {}) {
|
|
225
|
-
const out = this._exec(
|
|
226
|
-
['list', '--upgrade-available', '--accept-source-agreements', '--disable-interactivity'],
|
|
227
|
-
{ allowNonZero: true }
|
|
228
|
-
)
|
|
229
|
-
return this._parseTable(out).map((r) => ({
|
|
230
|
-
name: r.Name || r.Id,
|
|
231
|
-
id: r.Id,
|
|
232
|
-
current: r.Version || '',
|
|
233
|
-
latest: r.Available || '',
|
|
234
|
-
source: r.Source || '',
|
|
235
|
-
}))
|
|
236
|
-
}
|
|
237
|
-
|
|
238
224
|
async install(name, version, opts = {}) {
|
|
239
225
|
const args = ['install', name, '--accept-package-agreements', '--accept-source-agreements']
|
|
240
226
|
if (version) args.push('--version', version)
|