Skip to content

Commit 740326b

Browse files
committed
fix: 修复了free-eye读取config.json的错误
1 parent be77d9e commit 740326b

10 files changed

Lines changed: 141 additions & 85 deletions

File tree

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable format/prettier */
12
# dev-sidecar
23

34
开发者边车,命名取自service-mesh的service-sidecar,意为为开发者打辅助的边车工具(以下简称ds)
@@ -446,7 +447,7 @@ node_modules/.pnpm/phantomjs-prebuilt@2.1.16/node_modules/phantomjs-prebuilt: Ru
446447

447448
2. `electron: Running postinstall script...` 卡死
448449

449-
形如以下情况下卡死,请耐心等待。**不要删除node_modules后重新安装**
450+
形如以下情况下卡死,请耐心等待。**不推荐在删除node_modules后重新安装**
450451

451452
```shell
452453
> pnpm i
@@ -533,6 +534,66 @@ pnpm run electron:build:termux
533534
- `os-network-fallback.cjs` 会在 `uv_interface_addresses` 权限受限时返回回环接口,避免 node-ipc 崩溃。
534535
- 若仍需沙箱,只能在支持 setuid 的环境或 root 下运行。
535536

537+
6. `ModuleNotFoundError: No module named 'distutils'` 错误
538+
539+
形如以下情况下报错:
540+
541+
```shell
542+
> pnpm i
543+
Scope: all 5 workspace projects
544+
Lockfile is up to date, resolution step is skipped
545+
Already up to date
546+
547+
devDependencies:
548+
+ @antfu/eslint-config 3.16.0
549+
+ eslint 9.39.1
550+
+ eslint-plugin-format 0.1.3
551+
552+
packages/gui postinstall$ electron-builder install-app-deps
553+
│ • electron-builder version=25.1.8
554+
│ • executing @electron/rebuild electronVersion=29.4.6 arch=x64 buildFromSource=false appDir=./
555+
│ • installing native dependencies arch=x64
556+
│ • preparing moduleName=@parcel/watcher arch=x64
557+
│ ⨯ (node:158832) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() …
558+
│ (Use `node --trace-deprecation ...` to show where the warning was created)
559+
│ (node:158832) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to se…
560+
│ Traceback (most recent call last):
561+
│ File "[dev-sidecar项目目录]\node_modules\.pnpm\node-gyp@9.4.1\node_modules\node-gyp\gyp\gyp_…
562+
│ import gyp # noqa: E402
563+
│ ^^^^^^^^^^
564+
│ File "[dev-sidecar项目目录]\node_modules\.pnpm\node-gyp@9.4.1\node_modules\node-gyp\gyp\pyli…
565+
│ import gyp.input
566+
│ File "[dev-sidecar项目目录]\node_modules\.pnpm\node-gyp@9.4.1\node_modules\node-gyp\gyp\pyli…
567+
│ from distutils.version import StrictVersion
568+
│ ModuleNotFoundError: No module named 'distutils'
569+
│ Error: `gyp` failed with exit code: 1
570+
│ at ChildProcess.onCpExit ([dev-sidecar项目目录]\node_modules\.pnpm\node-gyp@9.4.1\node_mod…
571+
│ at ChildProcess.emit (node:events:508:28)
572+
│ at ChildProcess._handle.onexit (node:internal/child_process:294:12)
573+
│ ⨯ node-gyp failed to rebuild '[dev-sidecar项目目录]\node_modules\.pnpm\@parcel+watcher@2.5.0…
574+
│ at ChildProcess.<anonymous> ([dev-sidecar项目目录]\node_modules\.pnpm\@electron+rebuild@3.…
575+
│ at ChildProcess.emit (node:events:508:28)
576+
│ at ChildProcess._handle.onexit (node:internal/child_process:294:12)
577+
└─ Failed in 3.8s at [dev-sidecar项目目录]\packages\gui
578+
 ELIFECYCLE  Command failed with exit code 1.
579+
```
580+
581+
distutils 是构建和安装 Python 模块的标准工具,但在 Python 3.10 被弃用,在 Python 3.12 被移除。显然,node-gyp 仍然依赖 distutils 来编译本地模块。
582+
583+
推荐使用第三方的 setuptools 来替代 distutils。一般而言,请执行下面的命令安装 setuptools:(这至少在Python 3.12上有效)
584+
585+
```shell
586+
pip install setuptools
587+
```
588+
589+
如果你使用其他软件管理Python环境,请自行查找对应工具的pip等价命令,如使用uv时,应当执行:
590+
591+
```shell
592+
uv venv . # 创建虚拟环境
593+
.venv\Scripts\activate # 激活虚拟环境,视具体shell类型,需要使用不同的activate脚本
594+
uv pip install setuptools
595+
```
596+
536597
### 8.5、提交pr
537598
538599
如果你想将你的修改贡献出来,请提交pr

packages/core/src/config-api.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import fs from 'node:fs';
2-
import jsonApi from '@docmirror/mitmproxy/src/json.js';
3-
import lodash from 'lodash';
4-
import request from 'request';
5-
import defConfig from './config/index.js';
6-
import mergeApi from './merge.js';
7-
import Shell from './shell.js';
8-
import log from './utils/util.log.core.js';
9-
import configLoader from './config/local-config-loader.js';
1+
import fs from 'node:fs'
2+
import jsonApi from '@docmirror/mitmproxy/src/json.js'
3+
import lodash from 'lodash'
4+
import request from 'request'
5+
import defConfig from './config/index.js'
6+
import mergeApi from './merge.js'
7+
import Shell from './shell'
8+
import log from './utils/util.log.core.js'
9+
import configLoader from './config/local-config-loader.js'
1010

1111
let configTarget = lodash.cloneDeep(defConfig)
1212

@@ -297,4 +297,4 @@ const configApi = {
297297
},
298298
}
299299

300-
export default configApi;
300+
export default configApi

packages/core/src/config/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import path from 'node:path';
2-
import configLoader from './local-config-loader.js';
1+
/* eslint-disable style/no-tabs */
2+
import path from 'node:path'
3+
import configLoader from './local-config-loader.js'
34

45
function getRootCaCertPath () {
56
return path.join(configLoader.getUserBasePath(), '/dev-sidecar.ca.crt')
@@ -1288,4 +1289,4 @@ const defaultConfig = {
12881289
// 从本地文件中加载配置
12891290
defaultConfig.configFromFiles = configLoader.getConfigFromFiles(configLoader.getUserConfig(), defaultConfig)
12901291

1291-
export default defaultConfig;
1292+
export default defaultConfig

packages/core/src/expose.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import lodash from 'lodash';
2-
import config from './config-api.js';
3-
import event from './event.js';
4-
import modules from './modules.js';
5-
import shell from './shell.js';
6-
import status from './status.js';
7-
import log from './utils/util.log.core.js';
1+
import lodash from 'lodash'
2+
import config from './config-api.js'
3+
import event from './event.js'
4+
import modules from './modules'
5+
import shell from './shell.js'
6+
import status from './status.js'
7+
import log from './utils/util.log.core.js'
88

99
const context = {
1010
config,
@@ -141,4 +141,4 @@ const api = {
141141
export default {
142142
status,
143143
api,
144-
};
144+
}

packages/core/src/modules/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export default {
22
server: require('./server.js'),
33
proxy: require('./proxy.js'),
44
plugin: require('./plugin.js'),
5-
};
5+
}

packages/core/src/modules/plugin/free-eye/client.js

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
1-
import fs from 'node:fs';
2-
import { createRequire } from 'node:module';
3-
import path from 'node:path';
4-
import utils from './utils.js';
1+
import fs from 'node:fs'
2+
import { createRequire } from 'node:module'
3+
import path from 'node:path'
4+
import utils from './utils.js'
55

66
const printHeader = (utils && utils.printHeader) || (utils && utils.default && utils.default.printHeader)
77

8+
// 简化说明:
9+
// - 本文件为 FreeEye 插件的客户端运行器(用于加载插件的 tests 并顺序执行)。
10+
// - 为了降低运行时复杂度,我们将插件根定为本文件所在目录(`PLUGIN_ROOT = __dirname`),
11+
// 不再向上遍历查找配置文件或插件目录。这样实现假定项目中该文件位置稳定。
12+
// - 配置加载采用同步的 `require` 风格(通过 `createRequire` 创建的 `pluginRequire`),
13+
// 以便在 CommonJS 环境或混合模块环境中更可靠地加载 `config.js`(`module.exports` 或 `export default`)。
14+
// 如果你的 `config.js` 是严格 ESM-only(例如使用 `export` 且包含顶级 `await`),
15+
// 需要改回基于动态 `import()` 的实现。
816
const TEST_PACKAGE_DIR = 'checkpoints'
9-
const PLUGIN_RELATIVE_PATH = path.join('packages', 'core', 'src', 'modules', 'plugin', 'free-eye')
1017

11-
function locatePluginRoot () {
12-
const localConfig = path.join(__dirname, 'config.json')
13-
if (fs.existsSync(localConfig)) {
14-
return __dirname
15-
}
16-
17-
let current = __dirname
18-
for (let i = 0; i < 8; i += 1) {
19-
const candidate = path.join(current, PLUGIN_RELATIVE_PATH)
20-
if (fs.existsSync(path.join(candidate, 'config.json'))) {
21-
return candidate
22-
}
23-
const parent = path.dirname(current)
24-
if (parent === current) {
25-
break
26-
}
27-
current = parent
28-
}
29-
return __dirname
30-
}
31-
32-
const PLUGIN_ROOT = locatePluginRoot()
18+
// 插件根目录(简化为当前目录)
19+
const PLUGIN_ROOT = __dirname
20+
// 用于在插件目录上下文中同步加载模块(config、tests 等)
3321
const pluginRequire = createRequire(path.join(PLUGIN_ROOT, 'index.js'))
3422

3523
function resolveTestsDir (customDir) {
@@ -55,7 +43,11 @@ async function loadAllTests (globalConfig, testsDir) {
5543
for (const file of files) {
5644
const modulePath = path.join(resolvedDir, file)
5745

46+
// 使用 pluginRequire 同步加载测试模块。这样做的好处:
47+
// - 保持加载行为一致(在 CommonJS / 混合项目中更可靠)
48+
// - 避免动态 import 带来的 URL 转换与异步模块解析复杂性
5849
const module = pluginRequire(modulePath)
50+
// 测试模块可以导出 `getClientTests`(命名导出或 default 导出中的方法)
5951
const getClientTests = module.getClientTests || (module.default && module.default.getClientTests)
6052
if (typeof getClientTests === 'function') {
6153
for (const testCls of getClientTests()) {
@@ -70,6 +62,8 @@ async function loadAllTests (globalConfig, testsDir) {
7062

7163
function getNextTest (todoTests, doneTests) {
7264
for (const testCls of todoTests) {
65+
// 检查此测试类的前置依赖(prereqs)是否全部完成。
66+
// 如果全部满足,则返回该测试类作为下一要执行的任务。
7367
let allPrereqsDone = true
7468
for (const testTag of testCls.getPrereqs()) {
7569
if (!doneTests.includes(testTag)) {
@@ -86,31 +80,30 @@ function getNextTest (todoTests, doneTests) {
8680

8781
async function runTests (options = {}) {
8882
const { configPath, testsDir } = options
89-
const preferredConfigPath = configPath && configPath.length > 0
90-
? (path.isAbsolute(configPath) ? configPath : path.join(PLUGIN_ROOT, configPath))
91-
: null
92-
const fallbackConfigPath = path.join(PLUGIN_ROOT, 'config.json')
93-
94-
const configCandidates = Array.from(new Set([preferredConfigPath, fallbackConfigPath].filter(Boolean)))
95-
96-
let globalConfig
97-
let lastError
98-
for (const candidatePath of configCandidates) {
99-
try {
100-
if (!fs.existsSync(candidatePath)) {
101-
lastError = new Error(`Config file not found: ${candidatePath}`)
102-
continue
103-
}
104-
const configData = fs.readFileSync(candidatePath, 'utf8')
105-
globalConfig = JSON.parse(configData)
106-
break
107-
} catch (error) {
108-
lastError = new Error(`Error reading config file (${candidatePath}): ${error.message}`)
83+
// 配置文件解析规则(简化):
84+
// - 如果传入了 `configPath`,则优先使用它(相对路径相对于插件根)。
85+
// - 否则使用插件根下的 `config.js`。
86+
// - 使用 `pluginRequire` 同步加载配置模块;接受 `module.exports` 或 `export default` 两种形式。
87+
let preferredConfigPath = path.join(PLUGIN_ROOT, 'config.js')
88+
if (configPath && configPath.length > 0) {
89+
if (path.isAbsolute(configPath)) {
90+
preferredConfigPath = configPath
91+
} else {
92+
preferredConfigPath = path.join(PLUGIN_ROOT, configPath)
10993
}
11094
}
11195

112-
if (!globalConfig) {
113-
throw lastError || new Error('Unable to load FreeEye config.')
96+
if (!fs.existsSync(preferredConfigPath)) {
97+
throw new Error(`Config file not found: ${preferredConfigPath}`)
98+
}
99+
100+
let globalConfig
101+
try {
102+
// 这里期望 config.js 导出一个对象,包含如 mainConfig.server.plugin.free_eye 的合并结果或默认设置
103+
const mod = pluginRequire(preferredConfigPath)
104+
globalConfig = mod && (mod.default || mod)
105+
} catch (err) {
106+
throw new Error(`Error loading config (${preferredConfigPath}): ${err.message}`)
114107
}
115108

116109
const globalResults = {}
@@ -165,4 +158,4 @@ if (require.main === module) {
165158
})
166159
}
167160

168-
export default { runTests };
161+
export default { runTests }

packages/core/src/modules/plugin/free-eye/config.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import mainConfig from '../../../config.js';
1+
import mainConfig from '../../../config'
22

33
export default {
44
name: '网络检测',
@@ -14,5 +14,6 @@ export default {
1414
defaultTimeout: 3,
1515
},
1616
// 复用主配置里的 free_eye 默认值,避免重复维护两份配置
17-
...mainConfig.plugin.free_eye,
18-
};
17+
// TODO: 此处config并未读取到用户自定义配置
18+
...mainConfig.server.plugin.free_eye,
19+
}

packages/core/src/modules/plugin/free-eye/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import fs from 'node:fs';
2-
import path from 'node:path';
3-
import clientModule from './client.js';
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import clientModule from './client.js'
44

5-
const runTests = (clientModule && (clientModule.runTests || (clientModule.default && clientModule.default.runTests)))
6-
import freeEyeConfig from './config.js';
5+
const runTests = (clientModule && clientModule.runTests)
6+
import freeEyeConfig from './config.js'
77

88
const PLUGIN_STATUS_KEY = 'plugin.free_eye'
99

@@ -158,4 +158,4 @@ export default {
158158
result: null,
159159
},
160160
plugin: FreeEyePlugin,
161-
};
161+
}

packages/core/src/modules/plugin/free-eye/template.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { performance } from 'node:perf_hooks';
1+
import { performance } from 'node:perf_hooks'
22

33
class TestThread {
44
/**
@@ -140,4 +140,4 @@ export default {
140140
TestThread,
141141
TestGroup,
142142
getClientTests,
143-
};
143+
}

packages/core/src/modules/plugin/free-eye/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ export default {
7676
printHeader,
7777
getResultIcon,
7878
getCensorsString,
79-
};
79+
}

0 commit comments

Comments
 (0)