@wwkit/cft 1.0.27 → 1.0.29

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/src/depchecker.js CHANGED
@@ -1,176 +1,176 @@
1
- import { execSync } from 'node:child_process'
2
- import fs from 'node:fs'
3
- import process from 'node:process'
4
-
5
- const APT_MAP = {
6
- 'libnss3.so': 'libnss3',
7
- 'libatk-1.0.so.0': 'libatk1.0-0t64',
8
- 'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0t64',
9
- 'libcups.so.2': 'libcups2t64',
10
- 'libdrm.so.2': 'libdrm2',
11
- 'libgbm.so.1': 'libgbm1',
12
- 'libxkbcommon.so.0': 'libxkbcommon0',
13
- 'libXcomposite.so.1': 'libxcomposite1',
14
- 'libXdamage.so.1': 'libxdamage1',
15
- 'libXfixes.so.3': 'libxfixes3',
16
- 'libXrandr.so.2': 'libxrandr2',
17
- 'libasound.so.2': 'libasound2t64',
18
- 'libpango-1.0.so.0': 'libpango-1.0-0',
19
- 'libcairo.so.2': 'libcairo2',
20
- 'libpangoft2-1.0.so.0': 'libpangoft2-1.0-0',
21
- 'libharfbuzz.so.0': 'libharfbuzz0b',
22
- 'libXss.so.1': 'libxss1',
23
- 'libatspi.so.0': 'libatspi2.0-0t64',
24
- 'libxcb.so.1': 'libxcb1',
25
- 'libX11.so.6': 'libx11-6',
26
- 'libXext.so.6': 'libxext6',
27
- 'libnssutil3.so': 'libnss3',
28
- 'libsmime3.so': 'libnss3',
29
- 'libnspr4.so': 'libnspr4',
30
- 'libdbus-1.so.3': 'libdbus-1-3',
31
- 'libexpat.so.1': 'libexpat1',
32
- 'libxrender.so.1': 'libxrender1',
33
- 'libglib-2.0.so.0': 'libglib2.0-0',
34
- 'libgobject-2.0.so.0': 'libglib2.0-0',
35
- }
36
-
37
- const DNF_MAP = {
38
- 'libnss3.so': 'nss',
39
- 'libatk-1.0.so.0': 'atk',
40
- 'libatk-bridge-2.0.so.0': 'at-spi2-atk',
41
- 'libcups.so.2': 'libcups',
42
- 'libdrm.so.2': 'libdrm',
43
- 'libgbm.so.1': 'mesa-libgbm',
44
- 'libxkbcommon.so.0': 'libxkbcommon',
45
- 'libXcomposite.so.1': 'libXcomposite',
46
- 'libXdamage.so.1': 'libXdamage',
47
- 'libXfixes.so.3': 'libXfixes',
48
- 'libXrandr.so.2': 'libXrandr',
49
- 'libasound.so.2': 'alsa-lib',
50
- 'libpango-1.0.so.0': 'pango',
51
- 'libcairo.so.2': 'cairo',
52
- 'libpangoft2-1.0.so.0': 'pango',
53
- 'libharfbuzz.so.0': 'harfbuzz',
54
- 'libXss.so.1': 'libXScrnSaver',
55
- 'libatspi.so.0': 'at-spi2-core',
56
- 'libxcb.so.1': 'libxcb',
57
- 'libX11.so.6': 'libX11',
58
- 'libXext.so.6': 'libXext',
59
- 'libnssutil3.so': 'nss',
60
- 'libsmime3.so': 'nss',
61
- 'libnspr4.so': 'nspr',
62
- 'libdbus-1.so.3': 'dbus-libs',
63
- 'libexpat.so.1': 'expat',
64
- 'libxrender.so.1': 'libXrender',
65
- 'libglib-2.0.so.0': 'glib2',
66
- 'libgobject-2.0.so.0': 'glib2',
67
- }
68
-
69
- export function isSupported() {
70
- return process.platform === 'linux'
71
- }
72
-
73
- export { APT_MAP, DNF_MAP }
74
-
75
- export function check(binaryPath) {
76
- if (!isSupported()) return []
77
- if (!binaryPath || !fs.existsSync(binaryPath)) return []
78
- try {
79
- execSync('which ldd', { stdio: 'pipe' })
80
- } catch {
81
- return []
82
- }
83
- let result
84
- try {
85
- result = execSync(`ldd "${binaryPath}"`, { stdio: 'pipe', timeout: 20000 })
86
- } catch {
87
- return []
88
- }
89
- const stdout = result.stdout?.toString() || ''
90
- const missing = []
91
- for (const line of stdout.split('\n')) {
92
- const m = line.match(/^\s*(\S+)\s+=>\s+not found/)
93
- if (m) missing.push(m[1])
94
- }
95
- return missing
96
- }
97
-
98
- export function mapToPackages(libs, packageManager) {
99
- if (packageManager !== 'apt' && packageManager !== 'dnf') {
100
- return { packages: [], unknown: [...libs] }
101
- }
102
- const table = packageManager === 'apt' ? APT_MAP : DNF_MAP
103
- const packages = []
104
- const unknown = []
105
- const seen = new Set()
106
- for (const lib of libs) {
107
- const pkg = table[lib]
108
- if (pkg && !seen.has(pkg)) {
109
- seen.add(pkg)
110
- packages.push(pkg)
111
- } else if (!pkg) {
112
- unknown.push(lib)
113
- }
114
- }
115
- return { packages, unknown }
116
- }
117
-
118
- export function fallbackPackages(packages, packageManager) {
119
- if (packageManager !== 'apt') return []
120
- const fb = packages.map((p) => p.replace(/t64$/, ''))
121
- return fb.some((p, i) => p !== packages[i]) ? fb : []
122
- }
123
-
124
- function runInstall(packages, packageManager) {
125
- const tool = packageManager === 'apt' ? 'apt-get' : 'dnf'
126
- const args = [tool, 'install', '-y', ...packages]
127
- const cmd = process.getuid && process.getuid() === 0 ? args : ['sudo', ...args]
128
- try {
129
- execSync(cmd.join(' '), { stdio: 'pipe', timeout: 600000 })
130
- return true
131
- } catch {
132
- return false
133
- }
134
- }
135
-
136
- export function install(packages, packageManager) {
137
- if (!packages.length) return true
138
- if (packageManager !== 'apt' && packageManager !== 'dnf') return false
139
- if (runInstall(packages, packageManager)) return true
140
- const fb = fallbackPackages(packages, packageManager)
141
- return fb.length ? runInstall(fb, packageManager) : false
142
- }
143
-
144
- function detectPackageManager() {
145
- try { execSync('which apt-get', { stdio: 'pipe' }); return 'apt' } catch {}
146
- try { execSync('which dnf', { stdio: 'pipe' }); return 'dnf' } catch {}
147
- return null
148
- }
149
-
150
- export { detectPackageManager }
151
-
152
- export function verify(binaryPath) {
153
- if (!isSupported()) {
154
- return { missing: [], packages: [], unknown: [], ok: true }
155
- }
156
- const packageManager = detectPackageManager()
157
- const missing = check(binaryPath)
158
- const result = { missing, packages: [], unknown: [], ok: !missing.length }
159
- if (!missing.length) return result
160
-
161
- const { packages, unknown } = mapToPackages(missing, packageManager)
162
- result.packages = packages
163
- result.unknown = unknown
164
-
165
- if (packages.length) {
166
- if (install(packages, packageManager)) {
167
- const stillMissing = check(binaryPath)
168
- result.ok = !stillMissing.length
169
- } else {
170
- result.ok = false
171
- }
172
- } else {
173
- result.ok = false
174
- }
175
- return result
1
+ import { execSync } from 'node:child_process'
2
+ import fs from 'node:fs'
3
+ import process from 'node:process'
4
+
5
+ const APT_MAP = {
6
+ 'libnss3.so': 'libnss3',
7
+ 'libatk-1.0.so.0': 'libatk1.0-0t64',
8
+ 'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0t64',
9
+ 'libcups.so.2': 'libcups2t64',
10
+ 'libdrm.so.2': 'libdrm2',
11
+ 'libgbm.so.1': 'libgbm1',
12
+ 'libxkbcommon.so.0': 'libxkbcommon0',
13
+ 'libXcomposite.so.1': 'libxcomposite1',
14
+ 'libXdamage.so.1': 'libxdamage1',
15
+ 'libXfixes.so.3': 'libxfixes3',
16
+ 'libXrandr.so.2': 'libxrandr2',
17
+ 'libasound.so.2': 'libasound2t64',
18
+ 'libpango-1.0.so.0': 'libpango-1.0-0',
19
+ 'libcairo.so.2': 'libcairo2',
20
+ 'libpangoft2-1.0.so.0': 'libpangoft2-1.0-0',
21
+ 'libharfbuzz.so.0': 'libharfbuzz0b',
22
+ 'libXss.so.1': 'libxss1',
23
+ 'libatspi.so.0': 'libatspi2.0-0t64',
24
+ 'libxcb.so.1': 'libxcb1',
25
+ 'libX11.so.6': 'libx11-6',
26
+ 'libXext.so.6': 'libxext6',
27
+ 'libnssutil3.so': 'libnss3',
28
+ 'libsmime3.so': 'libnss3',
29
+ 'libnspr4.so': 'libnspr4',
30
+ 'libdbus-1.so.3': 'libdbus-1-3',
31
+ 'libexpat.so.1': 'libexpat1',
32
+ 'libxrender.so.1': 'libxrender1',
33
+ 'libglib-2.0.so.0': 'libglib2.0-0',
34
+ 'libgobject-2.0.so.0': 'libglib2.0-0',
35
+ }
36
+
37
+ const DNF_MAP = {
38
+ 'libnss3.so': 'nss',
39
+ 'libatk-1.0.so.0': 'atk',
40
+ 'libatk-bridge-2.0.so.0': 'at-spi2-atk',
41
+ 'libcups.so.2': 'libcups',
42
+ 'libdrm.so.2': 'libdrm',
43
+ 'libgbm.so.1': 'mesa-libgbm',
44
+ 'libxkbcommon.so.0': 'libxkbcommon',
45
+ 'libXcomposite.so.1': 'libXcomposite',
46
+ 'libXdamage.so.1': 'libXdamage',
47
+ 'libXfixes.so.3': 'libXfixes',
48
+ 'libXrandr.so.2': 'libXrandr',
49
+ 'libasound.so.2': 'alsa-lib',
50
+ 'libpango-1.0.so.0': 'pango',
51
+ 'libcairo.so.2': 'cairo',
52
+ 'libpangoft2-1.0.so.0': 'pango',
53
+ 'libharfbuzz.so.0': 'harfbuzz',
54
+ 'libXss.so.1': 'libXScrnSaver',
55
+ 'libatspi.so.0': 'at-spi2-core',
56
+ 'libxcb.so.1': 'libxcb',
57
+ 'libX11.so.6': 'libX11',
58
+ 'libXext.so.6': 'libXext',
59
+ 'libnssutil3.so': 'nss',
60
+ 'libsmime3.so': 'nss',
61
+ 'libnspr4.so': 'nspr',
62
+ 'libdbus-1.so.3': 'dbus-libs',
63
+ 'libexpat.so.1': 'expat',
64
+ 'libxrender.so.1': 'libXrender',
65
+ 'libglib-2.0.so.0': 'glib2',
66
+ 'libgobject-2.0.so.0': 'glib2',
67
+ }
68
+
69
+ export function isSupported() {
70
+ return process.platform === 'linux'
71
+ }
72
+
73
+ export { APT_MAP, DNF_MAP }
74
+
75
+ export function check(binaryPath) {
76
+ if (!isSupported()) return []
77
+ if (!binaryPath || !fs.existsSync(binaryPath)) return []
78
+ try {
79
+ execSync('which ldd', { stdio: 'pipe' })
80
+ } catch {
81
+ return []
82
+ }
83
+ let result
84
+ try {
85
+ result = execSync(`ldd "${binaryPath}"`, { stdio: 'pipe', timeout: 20000 })
86
+ } catch {
87
+ return []
88
+ }
89
+ const stdout = result.stdout?.toString() || ''
90
+ const missing = []
91
+ for (const line of stdout.split('\n')) {
92
+ const m = line.match(/^\s*(\S+)\s+=>\s+not found/)
93
+ if (m) missing.push(m[1])
94
+ }
95
+ return missing
96
+ }
97
+
98
+ export function mapToPackages(libs, packageManager) {
99
+ if (packageManager !== 'apt' && packageManager !== 'dnf') {
100
+ return { packages: [], unknown: [...libs] }
101
+ }
102
+ const table = packageManager === 'apt' ? APT_MAP : DNF_MAP
103
+ const packages = []
104
+ const unknown = []
105
+ const seen = new Set()
106
+ for (const lib of libs) {
107
+ const pkg = table[lib]
108
+ if (pkg && !seen.has(pkg)) {
109
+ seen.add(pkg)
110
+ packages.push(pkg)
111
+ } else if (!pkg) {
112
+ unknown.push(lib)
113
+ }
114
+ }
115
+ return { packages, unknown }
116
+ }
117
+
118
+ export function fallbackPackages(packages, packageManager) {
119
+ if (packageManager !== 'apt') return []
120
+ const fb = packages.map((p) => p.replace(/t64$/, ''))
121
+ return fb.some((p, i) => p !== packages[i]) ? fb : []
122
+ }
123
+
124
+ function runInstall(packages, packageManager) {
125
+ const tool = packageManager === 'apt' ? 'apt-get' : 'dnf'
126
+ const args = [tool, 'install', '-y', ...packages]
127
+ const cmd = process.getuid && process.getuid() === 0 ? args : ['sudo', ...args]
128
+ try {
129
+ execSync(cmd.join(' '), { stdio: 'pipe', timeout: 600000 })
130
+ return true
131
+ } catch {
132
+ return false
133
+ }
134
+ }
135
+
136
+ export function install(packages, packageManager) {
137
+ if (!packages.length) return true
138
+ if (packageManager !== 'apt' && packageManager !== 'dnf') return false
139
+ if (runInstall(packages, packageManager)) return true
140
+ const fb = fallbackPackages(packages, packageManager)
141
+ return fb.length ? runInstall(fb, packageManager) : false
142
+ }
143
+
144
+ function detectPackageManager() {
145
+ try { execSync('which apt-get', { stdio: 'pipe' }); return 'apt' } catch {}
146
+ try { execSync('which dnf', { stdio: 'pipe' }); return 'dnf' } catch {}
147
+ return null
148
+ }
149
+
150
+ export { detectPackageManager }
151
+
152
+ export function verify(binaryPath) {
153
+ if (!isSupported()) {
154
+ return { missing: [], packages: [], unknown: [], ok: true }
155
+ }
156
+ const packageManager = detectPackageManager()
157
+ const missing = check(binaryPath)
158
+ const result = { missing, packages: [], unknown: [], ok: !missing.length }
159
+ if (!missing.length) return result
160
+
161
+ const { packages, unknown } = mapToPackages(missing, packageManager)
162
+ result.packages = packages
163
+ result.unknown = unknown
164
+
165
+ if (packages.length) {
166
+ if (install(packages, packageManager)) {
167
+ const stillMissing = check(binaryPath)
168
+ result.ok = !stillMissing.length
169
+ } else {
170
+ result.ok = false
171
+ }
172
+ } else {
173
+ result.ok = false
174
+ }
175
+ return result
176
176
  }
package/src/env.js CHANGED
@@ -1,84 +1,84 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
- import process from 'node:process'
4
-
5
- import { Shell } from '@wwkit/shared'
6
-
7
- import { getLocation } from './config.js'
8
- import { getOs } from './platform.js'
9
-
10
- const CFT_ENV_VARS = [
11
- 'SELENIUM_CFT_DIR',
12
- 'SELENIUM_CFT_CHROME_DIR',
13
- 'SELENIUM_CFT_DRIVER_DIR',
14
- ]
15
-
16
- /**
17
- * 计算 cft 期望写入的环境变量值(与 postinstall 逻辑一致)。
18
- */
19
- function expectedValues() {
20
- const installDir = getLocation()
21
- const osType = getOs()
22
- return {
23
- SELENIUM_CFT_DIR: installDir,
24
- SELENIUM_CFT_CHROME_DIR: path.join(installDir, `chrome-${osType}`),
25
- SELENIUM_CFT_DRIVER_DIR: path.join(installDir, `chromedriver-${osType}`),
26
- }
27
- }
28
-
29
- /**
30
- * 从 shell profile 文件中提取 cft 实际写入的环境变量值。
31
- * 遍历 Shell.getProfiles() 返回的所有 profile,解析 wwkit marker 块。
32
- */
33
- function profileValues() {
34
- const shell = new Shell()
35
- const result = {}
36
- for (const { path: profilePath } of shell.getProfiles()) {
37
- let content = ''
38
- try {
39
- content = fs.readFileSync(profilePath, 'utf8')
40
- } catch {
41
- continue
42
- }
43
- for (const name of CFT_ENV_VARS) {
44
- if (result[name]) continue
45
- const beginMarker = `# >>> wwkit ${name} >>>`
46
- const endMarker = `# <<< wwkit ${name} <<<`
47
- const beginIdx = content.indexOf(beginMarker)
48
- if (beginIdx === -1) continue
49
- const endIdx = content.indexOf(endMarker, beginIdx)
50
- if (endIdx === -1) continue
51
- const block = content.slice(beginIdx, endIdx)
52
- // 提取引号内的值(兼容 export NAME="val" 与 fish set -gx NAME "val")
53
- const m = block.match(/"([^"]*)"/)
54
- if (m) {
55
- result[name] = { value: m[1], profile: profilePath }
56
- }
57
- }
58
- }
59
- return result
60
- }
61
-
62
- /**
63
- * 显示 cft 创建的全局环境变量:期望值、profile 实际写入值、当前 shell 值。
64
- */
65
- export function showEnv() {
66
- const expected = expectedValues()
67
- const profVals = profileValues()
68
- console.log('cft 管理的环境变量(由 postinstall 写入 shell profile):\n')
69
- for (const name of CFT_ENV_VARS) {
70
- const exp = expected[name]
71
- const prof = profVals[name]
72
- const env = process.env[name] || ''
73
- console.log(` ${name}`)
74
- console.log(` 期望值: ${exp}`)
75
- if (prof) {
76
- console.log(` profile 写入: ${prof.value}`)
77
- console.log(` ← ${prof.profile}`)
78
- } else {
79
- console.log(` profile 写入: (未写入,请运行 cft install 或重新安装包)`)
80
- }
81
- console.log(` 当前 shell: ${env || '(未设置 — 请重新打开终端或 source 你的 profile)'}`)
82
- console.log()
83
- }
84
- }
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import process from 'node:process'
4
+
5
+ import { Shell } from '@wwkit/shared'
6
+
7
+ import { getLocation } from './config.js'
8
+ import { getOs } from './platform.js'
9
+
10
+ const CFT_ENV_VARS = [
11
+ 'SELENIUM_CFT_DIR',
12
+ 'SELENIUM_CFT_CHROME_DIR',
13
+ 'SELENIUM_CFT_DRIVER_DIR',
14
+ ]
15
+
16
+ /**
17
+ * 计算 cft 期望写入的环境变量值(与 postinstall 逻辑一致)。
18
+ */
19
+ function expectedValues() {
20
+ const installDir = getLocation()
21
+ const osType = getOs()
22
+ return {
23
+ SELENIUM_CFT_DIR: installDir,
24
+ SELENIUM_CFT_CHROME_DIR: path.join(installDir, `chrome-${osType}`),
25
+ SELENIUM_CFT_DRIVER_DIR: path.join(installDir, `chromedriver-${osType}`),
26
+ }
27
+ }
28
+
29
+ /**
30
+ * 从 shell profile 文件中提取 cft 实际写入的环境变量值。
31
+ * 遍历 Shell.getProfiles() 返回的所有 profile,解析 wwkit marker 块。
32
+ */
33
+ function profileValues() {
34
+ const shell = new Shell()
35
+ const result = {}
36
+ for (const { path: profilePath } of shell.getProfiles()) {
37
+ let content = ''
38
+ try {
39
+ content = fs.readFileSync(profilePath, 'utf8')
40
+ } catch {
41
+ continue
42
+ }
43
+ for (const name of CFT_ENV_VARS) {
44
+ if (result[name]) continue
45
+ const beginMarker = `# >>> wwkit ${name} >>>`
46
+ const endMarker = `# <<< wwkit ${name} <<<`
47
+ const beginIdx = content.indexOf(beginMarker)
48
+ if (beginIdx === -1) continue
49
+ const endIdx = content.indexOf(endMarker, beginIdx)
50
+ if (endIdx === -1) continue
51
+ const block = content.slice(beginIdx, endIdx)
52
+ // 提取引号内的值(兼容 export NAME="val" 与 fish set -gx NAME "val")
53
+ const m = block.match(/"([^"]*)"/)
54
+ if (m) {
55
+ result[name] = { value: m[1], profile: profilePath }
56
+ }
57
+ }
58
+ }
59
+ return result
60
+ }
61
+
62
+ /**
63
+ * 显示 cft 创建的全局环境变量:期望值、profile 实际写入值、当前 shell 值。
64
+ */
65
+ export function showEnv() {
66
+ const expected = expectedValues()
67
+ const profVals = profileValues()
68
+ console.log('cft 管理的环境变量(由 postinstall 写入 shell profile):\n')
69
+ for (const name of CFT_ENV_VARS) {
70
+ const exp = expected[name]
71
+ const prof = profVals[name]
72
+ const env = process.env[name] || ''
73
+ console.log(` ${name}`)
74
+ console.log(` 期望值: ${exp}`)
75
+ if (prof) {
76
+ console.log(` profile 写入: ${prof.value}`)
77
+ console.log(` ← ${prof.profile}`)
78
+ } else {
79
+ console.log(` profile 写入: (未写入,请运行 cft install 或重新安装包)`)
80
+ }
81
+ console.log(` 当前 shell: ${env || '(未设置 — 请重新打开终端或 source 你的 profile)'}`)
82
+ console.log()
83
+ }
84
+ }