结论:已新增ToolDbProcessPort合约、OPFS tool DB flat-file/transcript store和Node/WASM gates,baseline保持28/28/131/0且promotion继续锁定。
133 lines
3.3 KiB
JavaScript
133 lines
3.3 KiB
JavaScript
const ROOT = "linuxcnc";
|
|
|
|
function assertSegment(segment, label = "path segment") {
|
|
if (typeof segment !== "string" || segment.length === 0) {
|
|
throw new Error(`${label} must be a non-empty string.`);
|
|
}
|
|
if (
|
|
segment === "." ||
|
|
segment === ".." ||
|
|
segment.includes("/") ||
|
|
segment.includes("\\") ||
|
|
segment.includes("\0")
|
|
) {
|
|
throw new Error(`Invalid ${label}: ${segment}`);
|
|
}
|
|
return segment;
|
|
}
|
|
|
|
export function splitOpfsPath(path) {
|
|
if (typeof path !== "string" || path.length === 0) {
|
|
throw new Error("OPFS path must be a non-empty relative path.");
|
|
}
|
|
if (path.startsWith("/") || path.includes("//")) {
|
|
throw new Error(`Invalid OPFS path: ${path}`);
|
|
}
|
|
|
|
const parts = path.split("/");
|
|
if (parts.some((part) => part === "." || part === ".." || part === "")) {
|
|
throw new Error(`Invalid OPFS path: ${path}`);
|
|
}
|
|
return parts;
|
|
}
|
|
|
|
export function normalizeOpfsPath(path) {
|
|
return splitOpfsPath(path).join("/");
|
|
}
|
|
|
|
export function opfsPath(...segments) {
|
|
return segments.map((segment) => assertSegment(segment)).join("/");
|
|
}
|
|
|
|
export function machineRoot(machineId) {
|
|
return opfsPath(ROOT, "machines", assertSegment(machineId, "machine id"));
|
|
}
|
|
|
|
export function machineIniPath(machineId, filename = "machine.ini") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
assertSegment(filename, "INI filename"),
|
|
);
|
|
}
|
|
|
|
export function toolTablePath(machineId, filename = "tool.tbl") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
assertSegment(filename, "tool table filename"),
|
|
);
|
|
}
|
|
|
|
export function toolDbRootPath(machineId) {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
"tool-db",
|
|
);
|
|
}
|
|
|
|
export function toolDbFilePath(machineId, filename = "db_nonran_file") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
"tool-db",
|
|
assertSegment(filename, "tool DB filename"),
|
|
);
|
|
}
|
|
|
|
export function toolDbTranscriptPath(machineId, runId, filename = "transcript.json") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
"tool-db",
|
|
"transcripts",
|
|
assertSegment(runId, "tool DB run id"),
|
|
assertSegment(filename, "tool DB transcript filename"),
|
|
);
|
|
}
|
|
|
|
export function parameterFilePath(machineId, filename = "linuxcnc.var") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"machines",
|
|
assertSegment(machineId, "machine id"),
|
|
assertSegment(filename, "parameter filename"),
|
|
);
|
|
}
|
|
|
|
export function gcodeProgramPath(filename) {
|
|
return opfsPath(ROOT, "gcode", assertSegment(filename, "G-code filename"));
|
|
}
|
|
|
|
export function previewCachePath(cacheKey, filename = "preview.json") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"preview-cache",
|
|
assertSegment(cacheKey, "preview cache key"),
|
|
assertSegment(filename, "preview cache filename"),
|
|
);
|
|
}
|
|
|
|
export function sessionSnapshotPath(sessionId, filename = "snapshot.json") {
|
|
return opfsPath(
|
|
ROOT,
|
|
"sessions",
|
|
assertSegment(sessionId, "session id"),
|
|
assertSegment(filename, "session snapshot filename"),
|
|
);
|
|
}
|
|
|
|
export function defaultMachinePaths(machineId) {
|
|
return {
|
|
ini: machineIniPath(machineId),
|
|
toolTable: toolTablePath(machineId),
|
|
parameters: parameterFilePath(machineId),
|
|
};
|
|
}
|