84 lines
4.2 KiB
JavaScript
84 lines
4.2 KiB
JavaScript
import { existsSync } from 'node:fs'
|
|
import { createServer } from 'node:http'
|
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
import { spawn } from 'node:child_process'
|
|
import { createChromeProfile, removeChromeProfile } from './chrome-profile.mjs'
|
|
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const waitForPort = (child) => new Promise((resolvePort, reject) => {
|
|
let output = ''
|
|
const timer = setTimeout(() => reject(new Error(`Vite did not announce a port: ${output.slice(-2000)}`)), 30_000)
|
|
const onData = (chunk) => {
|
|
output += String(chunk)
|
|
const match = output.match(/http:\/\/127\.0\.0\.1:(\d+)/)
|
|
if (match) { clearTimeout(timer); resolvePort(Number(match[1])) }
|
|
}
|
|
child.stdout.on('data', onData)
|
|
child.stderr.on('data', onData)
|
|
})
|
|
|
|
const vite = spawn('./nodew', ['node_modules/vite/bin/vite.js', '--host', '127.0.0.1'], { cwd: root, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
let vitePort
|
|
try { vitePort = await waitForPort(vite) } catch (error) { vite.kill('SIGTERM'); throw error }
|
|
let resolveReport
|
|
let rejectReport
|
|
const reportPromise = new Promise((resolveValue, rejectValue) => { resolveReport = resolveValue; rejectReport = rejectValue })
|
|
const server = createServer(async (request, response) => {
|
|
response.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
|
|
response.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
|
|
response.setHeader('Cross-Origin-Resource-Policy', 'same-origin')
|
|
if (request.method === 'POST' && request.url === '/__planegcs-report') {
|
|
let body = ''
|
|
request.setEncoding('utf8')
|
|
request.on('data', (chunk) => { body += chunk })
|
|
request.on('end', () => {
|
|
try { resolveReport(JSON.parse(body)); response.writeHead(204); response.end() }
|
|
catch (error) { rejectReport(error); response.writeHead(400); response.end(String(error)) }
|
|
})
|
|
return
|
|
}
|
|
if (request.url === '/planegcs-browser-harness.html') {
|
|
response.setHeader('content-type', 'text/html')
|
|
response.end(await readFile(resolve(root, 'public/planegcs-browser-harness.html')))
|
|
return
|
|
}
|
|
const pathname = decodeURIComponent((request.url || '/').split('?')[0])
|
|
if (pathname === '/native/planegcs/freecad-planegcs.js' || pathname === '/native/planegcs/freecad-planegcs.wasm') {
|
|
const file = resolve(root, `public${pathname}`)
|
|
if (!existsSync(file)) { response.writeHead(404); response.end('not found'); return }
|
|
response.setHeader('content-type', pathname.endsWith('.wasm') ? 'application/wasm' : 'text/javascript')
|
|
response.end(await readFile(file))
|
|
return
|
|
}
|
|
try {
|
|
const upstream = await fetch(`http://127.0.0.1:${vitePort}${request.url}`, { headers: { ...request.headers } })
|
|
response.writeHead(upstream.status, Object.fromEntries(upstream.headers.entries()))
|
|
response.end(Buffer.from(await upstream.arrayBuffer()))
|
|
} catch (error) {
|
|
response.writeHead(502)
|
|
response.end(String(error))
|
|
}
|
|
})
|
|
await new Promise((resolveServer) => server.listen(0, '127.0.0.1', resolveServer))
|
|
const port = server.address().port
|
|
const executable = process.env.CHROME_BIN || '/home/mes123456/.local/bin/google-chrome'
|
|
if (!existsSync(executable)) throw new Error(`Chrome executable not found: ${executable}`)
|
|
const chromeProfile = await createChromeProfile('planegcs')
|
|
const child = spawn(executable, ['--headless=new', '--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', `--user-data-dir=${chromeProfile}`, `http://127.0.0.1:${port}/planegcs-browser-harness.html?browser=chrome`], { cwd: root, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
let stderr = ''
|
|
child.stderr.on('data', (chunk) => { stderr += String(chunk) })
|
|
const timeout = setTimeout(() => rejectReport(new Error(`Chrome planegcs harness timed out. ${stderr.slice(-2000)}`)), 120_000)
|
|
try {
|
|
const report = await reportPromise
|
|
await writeFile(resolve(root, 'config/chrome-planegcs-verification.json'), `${JSON.stringify(report, null, 2)}\n`)
|
|
console.log(JSON.stringify(report, null, 2))
|
|
if (report.status !== 'pass') process.exitCode = 1
|
|
} finally {
|
|
clearTimeout(timeout)
|
|
child.kill('SIGTERM')
|
|
vite.kill('SIGTERM')
|
|
await new Promise((resolveClose) => server.close(resolveClose))
|
|
await removeChromeProfile(chromeProfile)
|
|
}
|