#!/usr/bin/env node import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { execFileSync } from "node:child_process"; const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), ".."); const sourceRoot = path.join(root, "freecad-source"); const docsRoot = path.join(root, "docs"); const sourceRevision = execFileSync("git", ["-C", sourceRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim(); const files = [ "src/Mod/Cloud/CMakeLists.txt", "src/Mod/Cloud/App/CMakeLists.txt", "src/Mod/Cloud/App/AppCloud.cpp", "src/Mod/Cloud/App/AppCloud.h", "src/Mod/Cloud/Init.py", "src/Mod/Cloud/InitGui.py", "src/Mod/Cloud/Gui/CMakeLists.txt", "src/Mod/Cloud/Gui/AppCloudGui.cpp", "src/Mod/Cloud/Gui/Command.cpp", ]; const text = (file) => fs.readFileSync(path.join(sourceRoot, file), "utf8"); const lineOf = (file, pattern) => { const lines = text(file).split(/\r?\n/); const index = lines.findIndex((line) => line.includes(pattern)); if (index < 0) throw new Error(`pattern not found: ${file}:${pattern}`); return index + 1; }; const sourceRef = (file, pattern) => ({ file, line: lineOf(file, pattern) }); const inputs = Object.fromEntries(files.map((file) => [ file, crypto.createHash("sha256").update(text(file)).digest("hex"), ])); const report = { schema: "freecad-web-p6-cloud-source-boundary/v1", task_id: "FW-P6-CLD-A", module: "Cloud", result: "pass_probe_only", sourceRevision, cmake: { target: "Cloud", kind: "shared_library", appTarget: "Cloud", scriptsTarget: "CloudScripts", buildCondition: "Cloud App is always added; Gui, InitGui.py and CloudGui are gated by BUILD_GUI", entries: [ sourceRef("src/Mod/Cloud/CMakeLists.txt", "add_subdirectory(App)"), sourceRef("src/Mod/Cloud/CMakeLists.txt", "if(BUILD_GUI)"), sourceRef("src/Mod/Cloud/App/CMakeLists.txt", "add_library(Cloud SHARED"), sourceRef("src/Mod/Cloud/Gui/CMakeLists.txt", "add_library(CloudGui SHARED"), ], }, dependencies: { required: ["FreeCADApp", "OpenSSL", "CURL", "XercesC", "Boost", "ZLIB"], cmake: [ sourceRef("src/Mod/Cloud/CMakeLists.txt", "find_package(OpenSSL REQUIRED)"), sourceRef("src/Mod/Cloud/CMakeLists.txt", "find_package(CURL REQUIRED)"), sourceRef("src/Mod/Cloud/App/CMakeLists.txt", "FreeCADApp"), sourceRef("src/Mod/Cloud/App/CMakeLists.txt", "${XercesC_LIBRARIES}"), ], network: ["libcurl", "OpenSSL"], }, registration: { pythonModule: "Cloud", entry: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "PyMOD_INIT_FUNC(Cloud)"), moduleClass: sourceRef("src/Mod/Cloud/App/AppCloud.h", "class Module: public Py::ExtensionModule"), guiModule: sourceRef("src/Mod/Cloud/Gui/AppCloudGui.cpp", "PyMOD_INIT_FUNC(CloudGui)"), }, actions: { "create/recompute": { applicable: false, reason: "Cloud exposes service configuration and document transfer; no Cloud-specific parametric object is registered.", entries: [ sourceRef("src/Mod/Cloud/App/AppCloud.h", "class Module: public Py::ExtensionModule"), sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "Py::Object Cloud::Module::sCloudURL"), ], }, "inspect/source-inventory": { entry: sourceRef("src/Mod/Cloud/Init.py", "FreeCAD init script of the Cloud module"), registration: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "PyMOD_INIT_FUNC(Cloud)"), readOnly: true, }, "python-api": { entry: sourceRef("src/Mod/Cloud/App/AppCloud.h", "\"URL\""), methods: ["URL", "TokenAuth", "TokenSecret", "TCPPort", "Save", "Restore", "ProtocolVersion", "Region"], implementation: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "Py::Object Cloud::Module::sCloudSave"), }, "save/reopen": { applicable: false, reason: "Cloud persistence is remote S3-style transfer through Cloud Save/Restore, not a local FCStd save/reopen action.", save: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "bool Cloud::Module::cloudSave"), restore: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "bool Cloud::Module::cloudRestore"), persistence: sourceRef("src/Mod/Cloud/App/AppCloud.cpp", "void Cloud::CloudWriter::writeFiles"), }, }, gui: { condition: "BUILD_GUI", workbench: sourceRef("src/Mod/Cloud/InitGui.py", "class CloudWorkbench"), extension: sourceRef("src/Mod/Cloud/Gui/AppCloudGui.cpp", "PyMOD_INIT_FUNC(CloudGui)"), command: sourceRef("src/Mod/Cloud/Gui/Command.cpp", "DEF_STD_CMD(CmdCloudTest)"), excludedFromHeadless: ["FreeCADGui", "PySide", "CloudGui"], }, boundaries: [ "This is a source probe only; no Cloud runtime, network, browser, or persistence claim is made.", "Cloud Save/Restore requires configured remote service credentials and is outside the headless source probe.", "No Cloud-specific parametric object type was found in the inspected module sources.", ], inputs, }; fs.mkdirSync(path.join(docsRoot, "p6"), { recursive: true }); fs.writeFileSync(path.join(docsRoot, "p6/cloud-source-boundary.json"), `${JSON.stringify(report, null, 2)}\n`); fs.writeFileSync(path.join(docsRoot, "freecad-p6-cloud-a-rg.log"), [ `result=${report.result}`, `sourceRevision=${sourceRevision}`, `files=${files.length}`, `target=${report.cmake.target}`, `guiCondition=${report.cmake.buildCondition}`, `dependencies=${report.dependencies.required.join(",")}`, ].join("\n") + "\n"); console.log(JSON.stringify({ result: report.result, module: report.module, files: files.length, target: report.cmake.target }));