filegrc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/bin/filegrc.js +8 -0
- package/model/index.js +13 -0
- package/model/v1.json +1378 -0
- package/package.json +29 -0
- package/src/agent.js +247 -0
- package/src/audit-preparation.js +906 -0
- package/src/build.js +27 -0
- package/src/cli.js +623 -0
- package/src/evidence-packet.js +1642 -0
- package/src/favicon.js +109 -0
- package/src/files.js +533 -0
- package/src/git.js +289 -0
- package/src/id.js +19 -0
- package/src/index.js +47 -0
- package/src/markdown.js +123 -0
- package/src/model-docs.js +119 -0
- package/src/mutation.js +15 -0
- package/src/obligations.js +595 -0
- package/src/paths.js +137 -0
- package/src/recurrence.js +89 -0
- package/src/resource-markdown.js +63 -0
- package/src/search.js +27 -0
- package/src/server.js +300 -0
- package/src/state.js +84 -0
- package/src/time.js +62 -0
- package/src/validate.js +496 -0
- package/src/web.js +2328 -0
- package/src/workspace.js +90 -0
package/src/workspace.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { join, relative, sep } from "node:path";
|
|
3
|
+
import { loadModel } from "../model/index.js";
|
|
4
|
+
import { resolveWorkspaceRoot } from "./paths.js";
|
|
5
|
+
|
|
6
|
+
export async function loadWorkspace(input = process.cwd()) {
|
|
7
|
+
const root = resolveWorkspaceRoot(input);
|
|
8
|
+
const dataRoot = join(root, "data");
|
|
9
|
+
const diagnostics = [];
|
|
10
|
+
const files = await collectJsonFiles(dataRoot);
|
|
11
|
+
const resources = [];
|
|
12
|
+
|
|
13
|
+
for (const path of files) {
|
|
14
|
+
const relativePath = relative(dataRoot, path).split(sep).join("/");
|
|
15
|
+
try {
|
|
16
|
+
const source = await readFile(path, "utf8");
|
|
17
|
+
const record = JSON.parse(source);
|
|
18
|
+
resources.push({ record, path, relativePath, source });
|
|
19
|
+
} catch (error) {
|
|
20
|
+
diagnostics.push({
|
|
21
|
+
severity: "error",
|
|
22
|
+
code: "invalid-json",
|
|
23
|
+
path: `data/${relativePath}`,
|
|
24
|
+
message: error.message
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const workspaceEntry = resources.find(({ record, relativePath }) => relativePath === "workspace.json" && record?.type === "workspace");
|
|
30
|
+
if (!workspaceEntry) {
|
|
31
|
+
diagnostics.push({
|
|
32
|
+
severity: "error",
|
|
33
|
+
code: "missing-workspace",
|
|
34
|
+
path: "data/workspace.json",
|
|
35
|
+
message: "The workspace record is missing."
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let model;
|
|
40
|
+
try {
|
|
41
|
+
model = loadModel(String(workspaceEntry?.record?.dataModelVersion ?? "1"));
|
|
42
|
+
} catch (error) {
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
severity: "error",
|
|
45
|
+
code: "unsupported-model",
|
|
46
|
+
path: "data/workspace.json",
|
|
47
|
+
message: error.message
|
|
48
|
+
});
|
|
49
|
+
model = loadModel("1");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
root,
|
|
54
|
+
dataRoot,
|
|
55
|
+
model,
|
|
56
|
+
workspace: workspaceEntry?.record ?? null,
|
|
57
|
+
entries: resources,
|
|
58
|
+
resources: resources.map(({ record }) => record),
|
|
59
|
+
diagnostics
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function indexResources(resources) {
|
|
64
|
+
const byId = new Map();
|
|
65
|
+
const byType = new Map();
|
|
66
|
+
for (const resource of resources) {
|
|
67
|
+
if (typeof resource?.id === "string") byId.set(resource.id, resource);
|
|
68
|
+
if (typeof resource?.type === "string") {
|
|
69
|
+
if (!byType.has(resource.type)) byType.set(resource.type, []);
|
|
70
|
+
byType.get(resource.type).push(resource);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { byId, byType };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function collectJsonFiles(directory, dataRoot = directory) {
|
|
77
|
+
const paths = [];
|
|
78
|
+
for (const item of await readdir(directory, { withFileTypes: true })) {
|
|
79
|
+
if (item.name.startsWith(".") || item.name === "content") continue;
|
|
80
|
+
const path = join(directory, item.name);
|
|
81
|
+
if (item.isDirectory()) paths.push(...await collectJsonFiles(path, dataRoot));
|
|
82
|
+
else if (item.isFile() && item.name.endsWith(".json") && !isEvidenceAttachment(path, dataRoot)) paths.push(path);
|
|
83
|
+
}
|
|
84
|
+
return paths.sort();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isEvidenceAttachment(path, dataRoot) {
|
|
88
|
+
const parts = relative(dataRoot, path).split(sep);
|
|
89
|
+
return parts[0] === "evidence" && parts.length > 2 && parts.at(-1) !== "evidence.json";
|
|
90
|
+
}
|