@wwkit/opm 1.0.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.
Files changed (62) hide show
  1. package/README.md +381 -0
  2. package/bin/index.js +9 -0
  3. package/docs/managers/apt.md +45 -0
  4. package/docs/managers/brew.md +92 -0
  5. package/docs/managers/bun.md +50 -0
  6. package/docs/managers/cft.md +57 -0
  7. package/docs/managers/composer.md +96 -0
  8. package/docs/managers/config.md +32 -0
  9. package/docs/managers/dnf.md +46 -0
  10. package/docs/managers/node.md +49 -0
  11. package/docs/managers/npm.md +100 -0
  12. package/docs/managers/nvm.md +34 -0
  13. package/docs/managers/php.md +48 -0
  14. package/docs/managers/phpenv.md +34 -0
  15. package/docs/managers/pip.md +98 -0
  16. package/docs/managers/python.md +53 -0
  17. package/docs/managers/uv.md +27 -0
  18. package/docs/opm.html +570 -0
  19. package/docs/packages/opencode.md +41 -0
  20. package/package.json +51 -0
  21. package/scripts/postinstall.js +7 -0
  22. package/src/binaries/base.js +508 -0
  23. package/src/binaries/cft/index.js +35 -0
  24. package/src/binaries/depchecker.js +172 -0
  25. package/src/binaries/exefinder.js +110 -0
  26. package/src/binaries/platform.js +17 -0
  27. package/src/cli/doc.js +335 -0
  28. package/src/cli/groups/config.js +78 -0
  29. package/src/cli/groups/ensure.js +96 -0
  30. package/src/cli/groups/homebrew.js +73 -0
  31. package/src/cli/groups/nvm.js +73 -0
  32. package/src/cli/groups/package.js +514 -0
  33. package/src/cli/groups/phpenv.js +89 -0
  34. package/src/cli/groups/uv.js +73 -0
  35. package/src/cli/groups/version-manager.js +186 -0
  36. package/src/cli/helpers/args.js +49 -0
  37. package/src/cli/index.js +129 -0
  38. package/src/config.js +133 -0
  39. package/src/config.json5 +158 -0
  40. package/src/formatter.js +13 -0
  41. package/src/harnesses/base.js +205 -0
  42. package/src/harnesses/opencode/clear.js +239 -0
  43. package/src/harnesses/opencode/db.js +39 -0
  44. package/src/harnesses/opencode/index.js +46 -0
  45. package/src/harnesses/opencode/sqlite.js +200 -0
  46. package/src/index.js +46 -0
  47. package/src/managers/apt.js +377 -0
  48. package/src/managers/base.js +167 -0
  49. package/src/managers/brew.js +374 -0
  50. package/src/managers/bun.js +342 -0
  51. package/src/managers/composer.js +280 -0
  52. package/src/managers/dnf.js +370 -0
  53. package/src/managers/http.js +432 -0
  54. package/src/managers/node.js +150 -0
  55. package/src/managers/npm.js +473 -0
  56. package/src/managers/php.js +157 -0
  57. package/src/managers/pip.js +555 -0
  58. package/src/managers/python.js +180 -0
  59. package/src/managers/runtime.js +309 -0
  60. package/src/managers/winget.js +268 -0
  61. package/src/presets.js +24 -0
  62. package/src/proxy-presets.js +12 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 配置命令组
3
+ *
4
+ * 显示合并后的 opm 配置文件(内置默认 + 用户 ~/.config/opm/config.json5)。
5
+ * 可用段名由 getConfig() 动态生成(top-level 段 + 含 registry 的 `.registry` 子段),
6
+ * 新增配置段无需改动本文件。
7
+ */
8
+
9
+ import { parseFlags } from '../helpers/args.js'
10
+ import { getConfig, getSection } from '../../config.js'
11
+ import { output } from '../../formatter.js'
12
+
13
+ /**
14
+ * 由配置动态生成可用段名列表
15
+ * @param {object} config
16
+ * @returns {string[]}
17
+ */
18
+ function sectionNames(config) {
19
+ const names = []
20
+ for (const key of Object.keys(config)) {
21
+ names.push(key)
22
+ if (config[key] && typeof config[key] === 'object' && config[key].registry) {
23
+ names.push(`${key}.registry`)
24
+ }
25
+ }
26
+ return names
27
+ }
28
+
29
+ export class ConfigGroup {
30
+ constructor() {
31
+ this.name = 'config'
32
+ this.desc = 'Show merged config (proxy + all registry sections)'
33
+ }
34
+
35
+ async run(argv) {
36
+ const parsed = parseFlags(argv)
37
+
38
+ const config = await getConfig()
39
+ const section = parsed.positional.join('.')
40
+ const result = getSection(config, section)
41
+ if (result === undefined) {
42
+ console.error(`Unknown config section: ${section || '(empty)'}`)
43
+ console.error(`Available sections: ${sectionNames(config).join(', ')}`)
44
+ process.exit(1)
45
+ }
46
+ output(result)
47
+ }
48
+
49
+ printHelp() {
50
+ const sectionLines = sectionNames(getConfig())
51
+ .map((s) => {
52
+ const desc = s === 'proxy'
53
+ ? 'Show proxy presets + active (empty = no proxy)'
54
+ : (s.endsWith('.registry')
55
+ ? `Show ${s.slice(0, -9)} registry presets + active`
56
+ : `Show ${s} section`)
57
+ return ` ${s.padEnd(30)} ${desc}`
58
+ })
59
+ .join('\n')
60
+
61
+ console.log(`
62
+ Usage: opm config [section] [options]
63
+
64
+ Sections:
65
+ ${sectionLines}
66
+
67
+ Config file: ~/.config/opm/config.json5 (merged with builtin defaults)
68
+
69
+ Options:
70
+ -h, --help Show help
71
+
72
+ Examples:
73
+ opm config
74
+ opm config proxy
75
+ opm config npm.registry
76
+ `)
77
+ }
78
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * ensure 命令组 — 确保运行时已安装(组合现有命令)
3
+ *
4
+ * opm ensure <node|php|python> [version]
5
+ *
6
+ * 逻辑:
7
+ * 1. 检查当前是否已满足(已安装,且若指定 version 则该版本已安装)
8
+ * 2. 不满足则安装(自动安装版本管理器 + 安装版本)
9
+ */
10
+
11
+ import { parseFlags } from '../helpers/args.js'
12
+ import { NodeManager } from '../../managers/node.js'
13
+ import { PhpManager } from '../../managers/php.js'
14
+ import { PythonManager } from '../../managers/python.js'
15
+ import { getActiveProxy } from '../../config.js'
16
+ import { output } from '../../formatter.js'
17
+
18
+ const RUNTIMES = {
19
+ node: () => new NodeManager(),
20
+ php: () => new PhpManager(),
21
+ python: () => new PythonManager(),
22
+ }
23
+
24
+ export class EnsureGroup {
25
+ constructor() {
26
+ this.name = 'ensure'
27
+ this.desc = 'Ensure a runtime is installed (node/php/python)'
28
+ }
29
+
30
+ async run(argv) {
31
+ const parsed = parseFlags(argv)
32
+ const [runtime, version] = parsed.positional
33
+
34
+ if (!runtime || runtime === '-h' || runtime === '--help' || runtime === 'help' || !RUNTIMES[runtime]) {
35
+ if (runtime && runtime !== '-h' && runtime !== '--help' && runtime !== 'help') {
36
+ console.error(`Unknown runtime: ${runtime}`)
37
+ }
38
+ this.printHelp()
39
+ process.exit(runtime && RUNTIMES[runtime] === undefined ? 1 : 0)
40
+ }
41
+
42
+ let proxy = parsed.flags.proxy || parsed.flags.p || ''
43
+ if (proxy === 'true') proxy = ''
44
+ if (!proxy) proxy = getActiveProxy()
45
+
46
+ const manager = RUNTIMES[runtime]()
47
+
48
+ let satisfied = false
49
+ let currentVersion = ''
50
+
51
+ if (version) {
52
+ const result = await manager.isInstalled(version)
53
+ satisfied = result.installed
54
+ if (satisfied) currentVersion = result.version || version
55
+ } else {
56
+ const result = await manager.getVersion()
57
+ satisfied = result.installed
58
+ currentVersion = result.version || ''
59
+ }
60
+
61
+ if (satisfied) {
62
+ output({ name: runtime, version: currentVersion, ensured: true, satisfied: true })
63
+ return
64
+ }
65
+
66
+ const installVersion = version || (manager.getDefaultVersion ? manager.getDefaultVersion() : '')
67
+ if (!installVersion) {
68
+ console.error(`No version specified and no defaultVersion configured for ${runtime}`)
69
+ process.exit(1)
70
+ }
71
+
72
+ await manager.install(runtime, installVersion, { proxy })
73
+ output({ name: runtime, version: installVersion, ensured: true, satisfied: false, action: 'installed' })
74
+ }
75
+
76
+ printHelp() {
77
+ console.log(`
78
+ Usage: opm ensure <runtime> [version] [options]
79
+
80
+ Runtimes:
81
+ node Ensure Node.js is installed
82
+ php Ensure PHP is installed
83
+ python Ensure Python is installed
84
+
85
+ Options:
86
+ -p, --proxy <url> Proxy address (for install)
87
+ -h, --help Show this help
88
+
89
+ Examples:
90
+ opm ensure node Ensure node is installed (uses defaultVersion from config)
91
+ opm ensure node 22 Ensure node 22 is installed
92
+ opm ensure python 3.12 Ensure python 3.12 is installed
93
+ opm ensure php 8.3 Ensure php 8.3 is installed
94
+ `)
95
+ }
96
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * homebrew 命令组 — 管理 Homebrew(brew)自身
3
+ *
4
+ * Homebrew 无独立版本管理器,通过官方 shell 脚本安装/卸载。
5
+ * 安装方式:curl 管道执行 install.sh(与 uv 同模式);
6
+ * upgrade = brew update;uninstall = curl 管道执行 uninstall.sh。
7
+ * brew 自身无镜像源(包镜像走 opm brew registry),故无 registry action。
8
+ * 仅支持 macOS / Linux,Windows 不支持。
9
+ */
10
+
11
+ import { execSync } from 'node:child_process'
12
+ import fs from 'node:fs'
13
+ import { ToolManagerGroup } from './version-manager.js'
14
+ import { getBrewBin, isHomebrewInstalled, installHomebrew } from '../../managers/brew.js'
15
+
16
+ const BREW_UNINSTALL_URL = 'https://raw.githubusercontent.com/Homebrew/uninstall/HEAD/uninstall.sh'
17
+
18
+ /**
19
+ * 获取 brew 安装根目录
20
+ * @returns {string}
21
+ */
22
+ function getBrewRoot() {
23
+ const bin = getBrewBin()
24
+ if (bin === 'brew') return ''
25
+ return bin.replace(/\/bin\/brew$/, '')
26
+ }
27
+
28
+ export class HomebrewGroup extends ToolManagerGroup {
29
+ constructor() {
30
+ super({
31
+ name: 'homebrew',
32
+ desc: 'Homebrew manager (install/upgrade/uninstall brew itself)',
33
+ hasRegistry: false,
34
+ isInstalled: () => isHomebrewInstalled(),
35
+ getPath: () => getBrewRoot(),
36
+ versionCmd: () => `${getBrewBin()} --version`,
37
+ parseVersion: (out) => {
38
+ const m = out.trim().match(/^Homebrew\s+(\S+)/)
39
+ return m ? m[1] : out.trim()
40
+ },
41
+ install: () => installHomebrew(),
42
+ upgrade: () => {
43
+ execSync(`${getBrewBin()} update`, { stdio: 'inherit' })
44
+ return { action: 'upgraded' }
45
+ },
46
+ uninstall: () => {
47
+ if (process.platform === 'win32') {
48
+ throw new Error('Homebrew is not supported on Windows')
49
+ }
50
+ execSync(`curl -fsSL "${BREW_UNINSTALL_URL}" | bash`, { stdio: 'inherit', shell: true })
51
+ return { action: 'uninstalled' }
52
+ },
53
+ usage: 'opm homebrew <action> [options]',
54
+ actions: [
55
+ ['version', 'Show Homebrew version'],
56
+ ['installed', 'Check if Homebrew is installed'],
57
+ ['install', 'Install Homebrew (curl installer from GitHub)'],
58
+ ['upgrade', 'Update Homebrew (brew update)'],
59
+ ['uninstall', 'Remove Homebrew (curl uninstaller from GitHub)'],
60
+ ['dir', 'Show Homebrew install directory'],
61
+ ['help', 'Show this help'],
62
+ ],
63
+ examples: [
64
+ 'opm homebrew version',
65
+ 'opm homebrew installed',
66
+ 'opm homebrew install',
67
+ 'opm homebrew upgrade',
68
+ 'opm homebrew dir',
69
+ 'opm homebrew uninstall',
70
+ ],
71
+ })
72
+ }
73
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * nvm 命令组 — 管理 nvm 自身
3
+ *
4
+ * nvm 是 shell function,通过 git clone 安装;
5
+ * install = git clone + 写 shell profile;upgrade = git pull;uninstall = rm -rf ~/.nvm。
6
+ * registry 是 nvm 的 git 镜像地址(official / gitee)。
7
+ */
8
+
9
+ import { execSync } from 'node:child_process'
10
+ import fs from 'node:fs'
11
+ import path from 'node:path'
12
+ import os from 'node:os'
13
+ import { ToolManagerGroup } from './version-manager.js'
14
+ import { Shell } from '@wwkit/shared'
15
+ import { getActiveRegistry } from '../../config.js'
16
+ import { installNvm } from '../../managers/node.js'
17
+
18
+ const shell = new Shell()
19
+
20
+ /**
21
+ * 获取 nvm 目录
22
+ * @returns {string}
23
+ */
24
+ function getNvmDir() {
25
+ return process.env.NVM_DIR || path.join(os.homedir(), '.nvm')
26
+ }
27
+
28
+ export class NvmGroup extends ToolManagerGroup {
29
+ constructor() {
30
+ super({
31
+ name: 'nvm',
32
+ desc: 'nvm version manager (manage nvm itself)',
33
+ needsBash: true,
34
+ isInstalled: () => fs.existsSync(path.join(getNvmDir(), 'nvm.sh')),
35
+ getPath: () => getNvmDir(),
36
+ versionCmd: () => `source "${path.join(getNvmDir(), 'nvm.sh')}" && nvm --version`,
37
+ parseVersion: (out) => out.trim(),
38
+ install: () => installNvm(),
39
+ upgrade: () => {
40
+ execSync(`cd "${getNvmDir()}" && git remote set-url origin "${getActiveRegistry('nvm')}" && git pull --tags`, {
41
+ stdio: 'inherit',
42
+ shell: shell.resolveBash(),
43
+ })
44
+ return { action: 'upgraded' }
45
+ },
46
+ uninstall: () => {
47
+ fs.rmSync(getNvmDir(), { recursive: true, force: true })
48
+ return { action: 'uninstalled', hint: 'Remove NVM_DIR/source line from shell profile manually' }
49
+ },
50
+ usage: 'opm nvm <action> [args] [options]',
51
+ actions: [
52
+ ['version', 'Show nvm version'],
53
+ ['installed', 'Check if nvm is installed'],
54
+ ['registry', 'Show active nvm git mirror (from opm config)'],
55
+ ['registry set <url|preset>', 'Set active nvm git mirror (writes opm config)'],
56
+ ['registry presets', 'List available mirror presets'],
57
+ ['install', 'Install nvm (git clone + shell profile setup)'],
58
+ ['upgrade', 'Update nvm (git pull)'],
59
+ ['uninstall', 'Remove nvm (~/.nvm)'],
60
+ ['dir', 'Show nvm install directory'],
61
+ ['help', 'Show this help'],
62
+ ],
63
+ examples: [
64
+ 'opm nvm version',
65
+ 'opm nvm installed',
66
+ 'opm nvm registry set gitee',
67
+ 'opm nvm install',
68
+ 'opm nvm upgrade',
69
+ 'opm nvm dir',
70
+ ],
71
+ })
72
+ }
73
+ }