mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-31 16:33:34 +08:00
fix(desktop): make electron:dev launcher work on Windows
`new URL('..', import.meta.url).pathname` yields a leading-slash path like
/E:/... on Windows, so Bun.spawn failed with ENOENT. Resolve desktopRoot via
fileURLToPath, start Vite through its Node API instead of spawning `bun run
dev`, and resolve the Electron binary directly per platform.
Recovered from the discarded wip/capabilities snapshot (cb1208c9) as a
standalone fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f70fa017ef
commit
0f22792861
@ -1,5 +1,6 @@
|
|||||||
|
import path from 'node:path'
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { createElectronDevEnv, DEFAULT_RENDERER_URL, mergeNoProxy } from './electron-dev'
|
import { createElectronDevEnv, DEFAULT_RENDERER_URL, mergeNoProxy, resolveElectronExecutable } from './electron-dev'
|
||||||
|
|
||||||
describe('desktop dev launcher environment', () => {
|
describe('desktop dev launcher environment', () => {
|
||||||
it('uses localhost and bypasses proxies for local renderer startup', () => {
|
it('uses localhost and bypasses proxies for local renderer startup', () => {
|
||||||
@ -27,4 +28,8 @@ describe('desktop dev launcher environment', () => {
|
|||||||
it('deduplicates no_proxy entries', () => {
|
it('deduplicates no_proxy entries', () => {
|
||||||
expect(mergeNoProxy('localhost,127.0.0.1')).toBe('localhost,127.0.0.1,::1')
|
expect(mergeNoProxy('localhost,127.0.0.1')).toBe('localhost,127.0.0.1,::1')
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
it('resolves Electron directly instead of shelling through bunx', () => {
|
||||||
|
expect(resolveElectronExecutable(path.resolve(import.meta.dirname, '..'), 'win32')).toMatch(/electron\.exe$/)
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -1,3 +1,9 @@
|
|||||||
|
import { spawn } from 'node:child_process'
|
||||||
|
import { existsSync } from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { createServer, type ViteDevServer } from 'vite'
|
||||||
|
|
||||||
export const DEFAULT_RENDERER_URL = 'http://localhost:1420'
|
export const DEFAULT_RENDERER_URL = 'http://localhost:1420'
|
||||||
export const LOCAL_NO_PROXY_ENTRIES = ['localhost', '127.0.0.1', '::1']
|
export const LOCAL_NO_PROXY_ENTRIES = ['localhost', '127.0.0.1', '::1']
|
||||||
|
|
||||||
@ -23,6 +29,20 @@ export function createElectronDevEnv(env: NodeJS.ProcessEnv = process.env) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveElectronExecutable(desktopRoot: string, platform = process.platform) {
|
||||||
|
const candidates = platform === 'win32'
|
||||||
|
? [path.join(desktopRoot, 'node_modules', 'electron', 'dist', 'electron.exe')]
|
||||||
|
: platform === 'darwin'
|
||||||
|
? [path.join(desktopRoot, 'node_modules', 'electron', 'dist', 'Electron.app', 'Contents', 'MacOS', 'Electron')]
|
||||||
|
: [path.join(desktopRoot, 'node_modules', 'electron', 'dist', 'electron')]
|
||||||
|
|
||||||
|
const electronPath = candidates.find(candidate => existsSync(candidate))
|
||||||
|
if (!electronPath) {
|
||||||
|
throw new Error(`Electron executable not found under ${path.join(desktopRoot, 'node_modules', 'electron', 'dist')}. Run "cd desktop && bun install" first.`)
|
||||||
|
}
|
||||||
|
return electronPath
|
||||||
|
}
|
||||||
|
|
||||||
async function waitForRenderer(rendererUrl: string) {
|
async function waitForRenderer(rendererUrl: string) {
|
||||||
const deadline = Date.now() + 30_000
|
const deadline = Date.now() + 30_000
|
||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
@ -36,47 +56,57 @@ async function waitForRenderer(rendererUrl: string) {
|
|||||||
throw new Error(`Timed out waiting for Vite renderer at ${rendererUrl}`)
|
throw new Error(`Timed out waiting for Vite renderer at ${rendererUrl}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function startVite(desktopRoot: string) {
|
||||||
|
const server = await createServer({
|
||||||
|
root: desktopRoot,
|
||||||
|
configFile: path.join(desktopRoot, 'vite.config.ts'),
|
||||||
|
})
|
||||||
|
await server.listen()
|
||||||
|
server.printUrls()
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
async function closeVite(server: ViteDevServer) {
|
||||||
|
await server.close().catch(() => undefined)
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const desktopRoot = new URL('..', import.meta.url).pathname
|
const desktopRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||||
const childEnv = createElectronDevEnv()
|
const childEnv = createElectronDevEnv()
|
||||||
const rendererUrl = childEnv.ELECTRON_RENDERER_URL
|
const rendererUrl = childEnv.ELECTRON_RENDERER_URL
|
||||||
process.env.NO_PROXY = childEnv.NO_PROXY
|
process.env.NO_PROXY = childEnv.NO_PROXY
|
||||||
process.env.no_proxy = childEnv.no_proxy
|
process.env.no_proxy = childEnv.no_proxy
|
||||||
|
|
||||||
const vite = Bun.spawn(['bun', 'run', 'dev'], {
|
const vite = await startVite(desktopRoot)
|
||||||
cwd: desktopRoot,
|
|
||||||
env: childEnv,
|
|
||||||
stdout: 'inherit',
|
|
||||||
stderr: 'inherit',
|
|
||||||
})
|
|
||||||
|
|
||||||
function stopVite() {
|
async function stopVite() {
|
||||||
vite.kill()
|
await closeVite(vite)
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
stopVite()
|
void stopVite().finally(() => process.exit(130))
|
||||||
process.exit(130)
|
|
||||||
})
|
})
|
||||||
process.on('SIGTERM', () => {
|
process.on('SIGTERM', () => {
|
||||||
stopVite()
|
void stopVite().finally(() => process.exit(143))
|
||||||
process.exit(143)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await waitForRenderer(rendererUrl)
|
await waitForRenderer(rendererUrl)
|
||||||
|
|
||||||
const electron = Bun.spawn(['bunx', 'electron', './electron-dist/main.cjs'], {
|
const electron = spawn(resolveElectronExecutable(desktopRoot), ['./electron-dist/main.cjs'], {
|
||||||
cwd: desktopRoot,
|
cwd: desktopRoot,
|
||||||
env: childEnv,
|
env: childEnv,
|
||||||
stdout: 'inherit',
|
stdio: 'inherit',
|
||||||
stderr: 'inherit',
|
windowsHide: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const exitCode = await electron.exited
|
const exitCode = await new Promise<number>((resolve, reject) => {
|
||||||
stopVite()
|
electron.once('error', reject)
|
||||||
|
electron.once('exit', code => resolve(code ?? 0))
|
||||||
|
})
|
||||||
|
await stopVite()
|
||||||
process.exit(exitCode)
|
process.exit(exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.main) {
|
if (import.meta.main) {
|
||||||
await main()
|
await main()
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user