@wwkit/cft 1.0.1 → 1.0.2
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/package.json +4 -2
- package/scripts/postinstall.js +14 -0
- package/src/depchecker.js +33 -16
- package/src/installer.js +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wwkit/cft",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"author": "bluesliu <langcai163@163.com>",
|
|
5
5
|
"description": "Chrome for Testing (CFT) installer — download, extract, chmod, dep-check",
|
|
6
6
|
"type": "module",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"bin",
|
|
13
13
|
"src",
|
|
14
|
+
"scripts",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE"
|
|
16
17
|
],
|
|
@@ -35,12 +36,13 @@
|
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"extract-zip": "^2.0.1",
|
|
38
|
-
"@wwkit/shared": "1.0.
|
|
39
|
+
"@wwkit/shared": "1.0.2"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"jest": "^29.7.0"
|
|
42
43
|
},
|
|
43
44
|
"scripts": {
|
|
45
|
+
"postinstall": "node scripts/postinstall.js",
|
|
44
46
|
"start": "node bin/index.js",
|
|
45
47
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --no-cache tests/unit",
|
|
46
48
|
"test:all": "node --experimental-vm-modules node_modules/jest/bin/jest.js --no-cache tests/unit",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const bin = path.join(__dirname, '..', 'bin', 'index.js')
|
|
9
|
+
|
|
10
|
+
const result = spawnSync('node', [bin, 'install'], { stdio: 'inherit' })
|
|
11
|
+
if (result.status !== 0) {
|
|
12
|
+
console.error('cft: postinstall (cft install) failed')
|
|
13
|
+
process.exit(1)
|
|
14
|
+
}
|
package/src/depchecker.js
CHANGED
|
@@ -17,13 +17,13 @@ const APT_MAP = {
|
|
|
17
17
|
'libasound.so.2': 'libasound2t64',
|
|
18
18
|
'libpango-1.0.so.0': 'libpango-1.0-0',
|
|
19
19
|
'libcairo.so.2': 'libcairo2',
|
|
20
|
-
'libpangoft2-1.0.so.0': '
|
|
20
|
+
'libpangoft2-1.0.so.0': 'libpangoft2-1.0-0',
|
|
21
21
|
'libharfbuzz.so.0': 'libharfbuzz0b',
|
|
22
|
-
'
|
|
22
|
+
'libXss.so.1': 'libxss1',
|
|
23
23
|
'libatspi.so.0': 'libatspi2.0-0t64',
|
|
24
24
|
'libxcb.so.1': 'libxcb1',
|
|
25
|
-
'
|
|
26
|
-
'
|
|
25
|
+
'libX11.so.6': 'libx11-6',
|
|
26
|
+
'libXext.so.6': 'libxext6',
|
|
27
27
|
'libnssutil3.so': 'libnss3',
|
|
28
28
|
'libsmime3.so': 'libnss3',
|
|
29
29
|
'libnspr4.so': 'libnspr4',
|
|
@@ -32,7 +32,6 @@ const APT_MAP = {
|
|
|
32
32
|
'libxrender.so.1': 'libxrender1',
|
|
33
33
|
'libglib-2.0.so.0': 'libglib2.0-0',
|
|
34
34
|
'libgobject-2.0.so.0': 'libglib2.0-0',
|
|
35
|
-
'libpango-1.0-0.so.0': 'libpango-1.0-0',
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
const DNF_MAP = {
|
|
@@ -52,11 +51,11 @@ const DNF_MAP = {
|
|
|
52
51
|
'libcairo.so.2': 'cairo',
|
|
53
52
|
'libpangoft2-1.0.so.0': 'pango',
|
|
54
53
|
'libharfbuzz.so.0': 'harfbuzz',
|
|
55
|
-
'
|
|
54
|
+
'libXss.so.1': 'libXScrnSaver',
|
|
56
55
|
'libatspi.so.0': 'at-spi2-core',
|
|
57
56
|
'libxcb.so.1': 'libxcb',
|
|
58
|
-
'
|
|
59
|
-
'
|
|
57
|
+
'libX11.so.6': 'libX11',
|
|
58
|
+
'libXext.so.6': 'libXext',
|
|
60
59
|
'libnssutil3.so': 'nss',
|
|
61
60
|
'libsmime3.so': 'nss',
|
|
62
61
|
'libnspr4.so': 'nspr',
|
|
@@ -71,6 +70,8 @@ export function isSupported() {
|
|
|
71
70
|
return process.platform === 'linux'
|
|
72
71
|
}
|
|
73
72
|
|
|
73
|
+
export { APT_MAP, DNF_MAP }
|
|
74
|
+
|
|
74
75
|
export function check(binaryPath) {
|
|
75
76
|
if (!isSupported()) return []
|
|
76
77
|
if (!binaryPath || !fs.existsSync(binaryPath)) return []
|
|
@@ -81,7 +82,7 @@ export function check(binaryPath) {
|
|
|
81
82
|
}
|
|
82
83
|
let result
|
|
83
84
|
try {
|
|
84
|
-
result = execSync(`ldd "${binaryPath}"`, {
|
|
85
|
+
result = execSync(`ldd "${binaryPath}"`, { stdio: 'pipe', timeout: 20000 })
|
|
85
86
|
} catch {
|
|
86
87
|
return []
|
|
87
88
|
}
|
|
@@ -95,6 +96,9 @@ export function check(binaryPath) {
|
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
export function mapToPackages(libs, packageManager) {
|
|
99
|
+
if (packageManager !== 'apt' && packageManager !== 'dnf') {
|
|
100
|
+
return { packages: [], unknown: [...libs] }
|
|
101
|
+
}
|
|
98
102
|
const table = packageManager === 'apt' ? APT_MAP : DNF_MAP
|
|
99
103
|
const packages = []
|
|
100
104
|
const unknown = []
|
|
@@ -111,23 +115,36 @@ export function mapToPackages(libs, packageManager) {
|
|
|
111
115
|
return { packages, unknown }
|
|
112
116
|
}
|
|
113
117
|
|
|
114
|
-
export function
|
|
115
|
-
if (
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
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]
|
|
119
128
|
try {
|
|
120
|
-
|
|
129
|
+
execSync(cmd.join(' '), { stdio: 'pipe', timeout: 600000 })
|
|
121
130
|
return true
|
|
122
131
|
} catch {
|
|
123
132
|
return false
|
|
124
133
|
}
|
|
125
134
|
}
|
|
126
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
|
+
|
|
127
144
|
function detectPackageManager() {
|
|
128
145
|
try { execSync('which apt-get', { stdio: 'pipe' }); return 'apt' } catch {}
|
|
129
146
|
try { execSync('which dnf', { stdio: 'pipe' }); return 'dnf' } catch {}
|
|
130
|
-
return
|
|
147
|
+
return null
|
|
131
148
|
}
|
|
132
149
|
|
|
133
150
|
export { detectPackageManager }
|
package/src/installer.js
CHANGED
|
@@ -146,6 +146,10 @@ function checkSystemDeps(chromeExe, driverExe) {
|
|
|
146
146
|
if (!exePath || !fs.existsSync(exePath)) continue
|
|
147
147
|
const missing = checkDeps(exePath)
|
|
148
148
|
if (!missing.length) continue
|
|
149
|
+
if (!packageManager) {
|
|
150
|
+
log(`${label}: 缺少系统依赖 ${missing.join(', ')},未检测到 apt-get/dnf,请手动安装`)
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
149
153
|
const { packages, unknown } = mapToPackages(missing, packageManager)
|
|
150
154
|
if (packages.length) {
|
|
151
155
|
log(`${label}: 自动安装系统依赖 ${packages.join(', ')}`)
|
|
@@ -168,6 +172,10 @@ export async function install() {
|
|
|
168
172
|
throw new Error(`Unsupported OS: ${osType}`)
|
|
169
173
|
}
|
|
170
174
|
|
|
175
|
+
if (process.platform === 'linux' && process.arch !== 'x64') {
|
|
176
|
+
throw new Error(`Chrome for Testing 仅提供 linux64 (x86_64) 构建,不支持 linux-${process.arch}`)
|
|
177
|
+
}
|
|
178
|
+
|
|
171
179
|
const { installed, info } = checkInstalled(version, location, osType)
|
|
172
180
|
if (installed) {
|
|
173
181
|
log(`CFT ${version} 已安装,跳过`)
|