订阅副本改成 type: file 后,认亲靠 path 而不是 url,脚本里解构已不存在的 url 字段会拿到 undefined;术语表补上 0007 引入的专属组、链式代理、入口组、 订阅副本四个词条,并移除已被取代的筛选组。
50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
/**
|
||
* 验证「每路一个专属代理组」和链式代理生成的配置内核真的接受。
|
||
*
|
||
* 单元测试只能证明字符串拼对了,证明不了内核认。这里走一遍真实的写回路径,
|
||
* 产物交给 mihomo -t 校验。特别要看的是订阅副本上的 dialer-proxy 引用能不能过
|
||
* `validateDialerProxies`(内核源码 config/utils.go:148-176)。
|
||
*
|
||
* 用法:bun run scripts/verify-chain.ts <源配置> <输出路径>
|
||
*/
|
||
import { readFileSync, writeFileSync } from 'node:fs'
|
||
import { openDocument } from '../vendor/config-editor/index.ts'
|
||
import type { ConfigObject } from '../vendor/config-editor/index.ts'
|
||
import { rewriteYaml } from '../server/config-store.ts'
|
||
import { applySetup, pruneGenerated } from '../shared/inbound-groups.ts'
|
||
|
||
const [src, out] = process.argv.slice(2)
|
||
if (!src || !out) {
|
||
console.error('用法:bun run scripts/verify-chain.ts <源配置> <输出路径>')
|
||
process.exit(1)
|
||
}
|
||
|
||
const source = readFileSync(src, 'utf8')
|
||
const data = JSON.parse(JSON.stringify(openDocument(source).data)) as ConfigObject
|
||
|
||
// 模拟界面上的三个动作:新增两路入站,一路直连,一路开链式代理并把入口筛到某一条线
|
||
data.listeners = [
|
||
{ name: '容器A', type: 'mixed', port: 17895 },
|
||
{ name: '容器B', type: 'mixed', port: 17896 },
|
||
]
|
||
|
||
let next = applySetup(data, '容器A', {
|
||
proxy: { sources: ['subs'], filter: null },
|
||
chain: null,
|
||
})
|
||
next = applySetup(next, '容器B', {
|
||
proxy: { sources: ['subs'], filter: null },
|
||
chain: { sources: ['subs'], filter: '(?i)DMIT' },
|
||
})
|
||
|
||
writeFileSync(out, rewriteYaml(source, pruneGenerated(next)), 'utf8')
|
||
|
||
console.log('生成的策略组:')
|
||
console.log(JSON.stringify(next['proxy-groups'], null, 2))
|
||
// 副本是 type: file,makeChainProvider 已去掉 url,整条回显没有泄露订阅地址的风险
|
||
console.log('\n生成的订阅副本:')
|
||
for (const [name, entry] of Object.entries(next['proxy-providers'] as ConfigObject)) {
|
||
if (!name.startsWith('patchbay:')) continue
|
||
console.log(name, JSON.stringify(entry))
|
||
}
|