import { readFile } from 'node:fs/promises' import { resolve } from 'node:path' const root = resolve(new URL('..', import.meta.url).pathname) const inventory = JSON.parse(await readFile(resolve(root, 'config/freecad-source-inventory.json'), 'utf8')) const fail = (message) => { throw new Error(`FreeCAD source inventory: ${message}`) } if (inventory.schemaVersion !== 1) fail('unsupported schemaVersion.') if (inventory.baseline?.freecadVersion !== '1.1.1' || inventory.baseline?.commit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail('baseline mismatch.') if (inventory.moduleCount !== 34 || !Array.isArray(inventory.modules) || inventory.modules.length !== 34) fail('expected exactly 34 modules.') const names = new Set() for (const module of inventory.modules) { if (!module.name || names.has(module.name)) fail(`duplicate or empty module '${module.name}'.`) names.add(module.name) for (const field of ['sourcePath', 'cmakeOption', 'runtimeStatus']) if (typeof module[field] !== 'string' || !module[field]) fail(`${module.name}.${field} is missing.`) if (!Array.isArray(module.commandIds)) fail(`${module.name}.commandIds must be an array.`) if (module.commandIds.some((command) => typeof command !== 'string' || !command)) fail(`${module.name} has an invalid command ID.`) } const sourceRoot = process.env.FREECAD_SOURCE_DIR ? resolve(process.env.FREECAD_SOURCE_DIR) : resolve(root, inventory.baseline.sourcePath || '.cache/freecad/FreeCAD') const sourceMod = resolve(sourceRoot, 'src/Mod') let sourceAvailable = false try { const entries = await import('node:fs/promises').then(({ readdir }) => readdir(sourceMod, { withFileTypes: true })) const sourceNames = new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)) sourceAvailable = true if (sourceNames.size !== names.size || [...sourceNames].some((name) => !names.has(name))) fail('tracked inventory differs from the available source checkout.') } catch (error) { if (error?.code !== 'ENOENT') throw error } console.log(JSON.stringify({ status: 'source-inventory-pass', moduleCount: inventory.moduleCount, commandCount: inventory.modules.reduce((total, module) => total + module.commandIds.length, 0), sourceAvailable }, null, 2)) function joinRoot(path) { return resolve(root, path) }