mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-28 09:12:08 +08:00
Delegate service and core installation to Service IPC so replacement uses one elevation. Share fallback occupancy checks and retain the execution guard until the Sidecar exits. Track missing approved cores and start refusals as unavailable, and show when no core is running. Build matching service tools from the local IPC dependency and pass both core executables through the Dev installer.
100 lines
2.6 KiB
JavaScript
100 lines
2.6 KiB
JavaScript
import { execFileSync, spawn } from 'node:child_process'
|
|
import { access } from 'node:fs/promises'
|
|
import { dirname, join, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
export const developmentServiceDirectoryEnvironment =
|
|
'CLASH_VERGE_DEV_SERVICE_DIR'
|
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
const serviceRepository = resolve(
|
|
repositoryRoot,
|
|
'..',
|
|
'clash-verge-service-ipc',
|
|
)
|
|
const serviceManifest = join(serviceRepository, 'Cargo.toml')
|
|
export const developmentServiceWatchPaths = [
|
|
'src',
|
|
'resources',
|
|
'Cargo.toml',
|
|
'Cargo.lock',
|
|
].map((name) => join(serviceRepository, name))
|
|
|
|
function executable(name, platform) {
|
|
return join(
|
|
serviceRepository,
|
|
'target',
|
|
'debug',
|
|
platform === 'win32' ? `${name}.exe` : name,
|
|
)
|
|
}
|
|
|
|
function run(command, args, options = {}) {
|
|
return new Promise((resolvePromise, reject) => {
|
|
const child = spawn(command, args, {
|
|
env: options.env ?? process.env,
|
|
stdio: options.stdio ?? 'inherit',
|
|
windowsHide: true,
|
|
})
|
|
child.once('error', reject)
|
|
child.once('exit', (code, signal) => {
|
|
if (code === 0) {
|
|
resolvePromise()
|
|
return
|
|
}
|
|
const error = new Error(
|
|
`${command} failed with ${signal ? `signal ${signal}` : `exit code ${code}`}`,
|
|
)
|
|
error.exitCode = code
|
|
reject(error)
|
|
})
|
|
})
|
|
}
|
|
|
|
export async function prepareDevelopmentService({
|
|
platform = process.platform,
|
|
} = {}) {
|
|
await access(serviceManifest)
|
|
await run('cargo', [
|
|
'build',
|
|
'--manifest-path',
|
|
serviceManifest,
|
|
'--features',
|
|
'standalone,client,development-channel',
|
|
'--bins',
|
|
])
|
|
|
|
const service = executable('clash-verge-service', platform)
|
|
await access(service)
|
|
return dirname(service)
|
|
}
|
|
|
|
export async function ensureDevelopmentService({
|
|
platform = process.platform,
|
|
} = {}) {
|
|
const serviceDirectory = await prepareDevelopmentService({ platform })
|
|
const extension = platform === 'win32' ? '.exe' : ''
|
|
const installer = join(
|
|
serviceDirectory,
|
|
`clash-verge-service-install${extension}`,
|
|
)
|
|
const host = execFileSync('rustc', ['-vV'], { encoding: 'utf8' }).match(
|
|
/^host: (.+)$/m,
|
|
)?.[1]
|
|
if (!host) throw new Error('rustc did not report its host target')
|
|
const args = ['--prepare-install', '--ensure']
|
|
for (const name of ['verge-mihomo', 'verge-mihomo-alpha']) {
|
|
args.push(
|
|
'--core',
|
|
`${name}${extension}`,
|
|
join(
|
|
repositoryRoot,
|
|
'src-tauri',
|
|
'sidecar',
|
|
`${name}-${host}${extension}`,
|
|
),
|
|
)
|
|
}
|
|
await run(installer, args)
|
|
return serviceDirectory
|
|
}
|