64 lines
5.2 KiB
JavaScript
64 lines
5.2 KiB
JavaScript
import { access, readFile, writeFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const sourceRoot = resolve(root, process.env.FREECAD_SOURCE_DIR || '.cache/freecad/FreeCAD')
|
|
const outputPath = resolve(root, process.env.FREECAD_ENTRYPOINT_INVENTORY || 'config/freecad-entrypoint-inventory.json')
|
|
const sourceInventory = JSON.parse(await readFile(resolve(root, 'config/freecad-source-inventory.json'), 'utf8'))
|
|
const exists = async (relativePath) => access(resolve(sourceRoot, relativePath)).then(() => true).catch(() => false)
|
|
|
|
const formats = [
|
|
['FCStd', 'project', ['App', 'Gui'], ['src/App/Document.cpp', 'src/Gui/Document.cpp'], 'native-parser', 'read-only'],
|
|
['BREP', 'geometry', ['Part'], ['src/Mod/Part/App/FeaturePartImportBrep.cpp'], 'occt-worker', 'experimental'],
|
|
['STEP', 'geometry', ['Part', 'Import'], ['src/Mod/Part/App/FeaturePartImportStep.cpp', 'src/Mod/Import/App/WriterStep.cpp'], 'occt-worker', 'experimental'],
|
|
['IGES', 'geometry', ['Part', 'Import'], ['src/Mod/Part/App/FeaturePartImportIges.cpp', 'src/Mod/Import/App/WriterIges.cpp'], 'occt-worker', 'experimental'],
|
|
['STL', 'mesh', ['Mesh', 'MeshPart'], ['src/Mod/Mesh/App/Importer.cpp', 'src/Mod/Mesh/App/Exporter.cpp'], 'worker-adapter', 'experimental'],
|
|
['OBJ', 'mesh', ['Mesh'], ['src/Mod/Mesh/App/Importer.cpp', 'src/Mod/Mesh/App/Exporter.cpp'], 'worker-adapter', 'experimental'],
|
|
['PLY', 'mesh', ['Mesh'], ['src/Mod/Mesh/App/Importer.cpp', 'src/Mod/Mesh/App/Exporter.cpp'], 'worker-adapter', 'experimental'],
|
|
['DXF', '2d', ['Draft', 'Import'], ['src/Mod/Draft/importDXF.py', 'src/Mod/Import/App/dxf/ImpExpDxf.cpp'], 'worker-adapter', 'read-only'],
|
|
['SVG', 'drawing', ['Draft', 'TechDraw'], ['src/Mod/Draft/importSVG.py', 'src/Mod/TechDraw/App/TechDrawExport.cpp'], 'sanitized-parser', 'read-only'],
|
|
['PDF', 'drawing', ['TechDraw'], ['src/Mod/TechDraw/App/TechDrawExport.cpp'], 'server-export', 'read-only'],
|
|
['IFC', 'bim', ['BIM'], ['src/Mod/BIM/importers/importIFC.py'], 'sandboxed-adapter', 'unsupported'],
|
|
['CSV', 'data', ['Spreadsheet'], ['src/Mod/Spreadsheet/App/SheetPyImp.cpp'], 'facade-parser', 'experimental'],
|
|
['GCODE', 'manufacturing', ['CAM'], ['src/Mod/CAM/PathCommands.py'], 'sandboxed-adapter', 'unsupported'],
|
|
['JT', 'geometry', ['JtReader'], ['src/Mod/JtReader/CMakeLists.txt'], 'proxy-resource', 'unsupported'],
|
|
['IDF', 'electronics', ['Idf'], ['src/Mod/Idf/Idf.py'], 'proxy-resource', 'unsupported'],
|
|
]
|
|
|
|
const entrypoints = [
|
|
['python-api', 'scripting', ['App', 'Gui'], ['src/App/ApplicationPy.cpp', 'src/Gui/ApplicationPy.cpp'], 'sandboxed-interpreter', 'unsupported'],
|
|
['macro-fcmacro', 'scripting', ['Gui'], ['src/Gui/CommandMacro.cpp'], 'blocked-resource', 'unsupported'],
|
|
['addon-package', 'extension', ['AddonManager'], ['src/Mod/AddonManager'], 'signed-catalog', 'unsupported'],
|
|
['preferences', 'configuration', ['App', 'Gui'], ['src/Base/Parameter.cpp', 'src/Gui/PreferencePages'], 'namespaced-settings', 'experimental'],
|
|
['clipboard', 'desktop', ['Gui'], ['src/Gui/MainWindow.cpp'], 'browser-clipboard-permission', 'unsupported'],
|
|
['print-job', 'desktop', ['Gui', 'TechDraw'], ['src/Gui/MainWindow.cpp', 'src/Mod/TechDraw/Gui/PagePrinter.cpp'], 'server-export', 'unsupported'],
|
|
]
|
|
|
|
const validateEvidence = async (items) => {
|
|
for (const item of items) for (const evidence of item[3]) if (!(await exists(evidence))) throw new Error(`Missing source evidence: ${evidence}`)
|
|
}
|
|
await validateEvidence(formats)
|
|
await validateEvidence(entrypoints)
|
|
|
|
const formatRecords = formats.map(([id, category, modules, sourceEvidence, webStrategy, compatibility]) => ({ id, category, modules, sourceEvidence, webStrategy, compatibility, roundTrip: compatibility === 'experimental', status: 'inventory-recorded' }))
|
|
const entrypointRecords = entrypoints.map(([id, category, modules, sourceEvidence, webStrategy, compatibility]) => ({ id, category, modules, sourceEvidence, webStrategy, compatibility, execution: false, status: 'inventory-recorded' }))
|
|
const coveredModules = new Set([...formatRecords, ...entrypointRecords].flatMap((entry) => entry.modules))
|
|
const moduleCoverage = sourceInventory.modules.map((module) => ({ name: module.name, sourcePath: module.sourcePath, coveredBy: [...formatRecords, ...entrypointRecords].filter((entry) => entry.modules.includes(module.name)).map((entry) => entry.id), status: coveredModules.has(module.name) ? 'entrypoint-covered' : 'scope-only' }))
|
|
|
|
const inventory = {
|
|
schemaVersion: 1,
|
|
baseline: { freecadVersion: '1.1.1', commit: '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' },
|
|
generatedBy: 'scripts/generate-freecad-entrypoint-inventory.mjs',
|
|
sourceInventory: 'config/freecad-source-inventory.json',
|
|
formats: formatRecords,
|
|
entrypoints: entrypointRecords,
|
|
moduleCoverage,
|
|
policy: {
|
|
unsupportedExecution: ['Python API', 'FCMacro', 'addon package', 'clipboard', 'print job'],
|
|
unknownOrUnlistedEntries: 'fail-inventory-check',
|
|
untrustedContent: 'never-execute',
|
|
},
|
|
}
|
|
await writeFile(outputPath, `${JSON.stringify(inventory, null, 2)}\n`, 'utf8')
|
|
console.log(JSON.stringify({ status: 'entrypoint-inventory-generated', output: outputPath, formatCount: formatRecords.length, entrypointCount: entrypointRecords.length, moduleCount: moduleCoverage.length }, null, 2))
|