@wwkit/cft 1.0.30 → 1.0.31
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/LICENSE +20 -20
- package/README.md +67 -67
- package/bin/index.js +74 -74
- package/package.json +3 -3
- package/scripts/postinstall.js +49 -49
- package/src/config.js +54 -54
- package/src/config.json5 +4 -4
- package/src/depchecker.js +175 -175
- package/src/env.js +84 -84
- package/src/exefinder.js +109 -109
- package/src/index.js +3 -3
- package/src/installer.js +368 -368
- package/src/platform.js +31 -31
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
|
+
}
|