import { spawnSync } from 'node:child_process' import { existsSync } from 'node:fs' import { writeFile } from 'node:fs/promises' import { resolve } from 'node:path' const root = resolve(new URL('..', import.meta.url).pathname) const executable = process.env.FREECAD_CMD || resolve(root, '.cache/freecad/install-desktop/bin/FreeCADCmd') const pythonPath = resolve(root, '.cache/freecad/sysroot/usr/lib/python3/dist-packages') const script = resolve(root, 'scripts/freecad-composite-history-elementmap-oracle.py') const outputPath = resolve(root, 'config/freecad-composite-history-elementmap-oracle.json') if (!existsSync(executable)) throw new Error(`FreeCAD composite oracle executable is missing: ${executable}`) const execution = spawnSync(executable, ['--python-path', pythonPath, script], { cwd: root, encoding: 'utf8', timeout: 180_000, maxBuffer: 80 * 1024 * 1024, env: { ...process.env, PYTHONPATH: `${pythonPath}${process.env.PYTHONPATH ? `:${process.env.PYTHONPATH}` : ''}`, LD_LIBRARY_PATH: `${resolve(root, '.cache/freecad/sysroot/usr/lib/x86_64-linux-gnu')}${process.env.LD_LIBRARY_PATH ? `:${process.env.LD_LIBRARY_PATH}` : ''}`, MATPLOTLIBRC: resolve(root, '.cache/freecad/sysroot/etc/matplotlibrc'), MPLBACKEND: 'Agg', }, }) const output = `${execution.stdout || ''}\n${execution.stderr || ''}` const marker = 'FREECAD_COMPOSITE_HISTORY_ELEMENTMAP_RESULT=' const markerIndex = output.indexOf(marker) const payload = markerIndex >= 0 ? output.slice(markerIndex + marker.length).match(/\{.*\}/s)?.[0] : undefined if (execution.error || execution.status !== 0 || !payload) throw new Error(`FreeCAD composite history oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`) const report = JSON.parse(payload) await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`) console.log(JSON.stringify(report, null, 2))