filegrc 0.13.0 → 0.13.2
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/package.json +4 -2
- package/src/collection-review.js +28 -8
- package/src/files.js +13 -5
- package/src/git.js +2032 -759
- package/src/server.js +154 -68
- package/src/state.js +30 -5
- package/src/validate.js +51 -13
- package/src/web.js +154 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "filegrc",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "Zero-dependency Git-native GRC engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test": "node ../../scripts/run-filegrc-tests.mjs",
|
|
25
|
-
"test:
|
|
25
|
+
"test:unit": "node ../../scripts/run-filegrc-tests.mjs --tier unit",
|
|
26
|
+
"test:integration": "node ../../scripts/run-filegrc-tests.mjs --tier integration",
|
|
27
|
+
"test:fast": "npm run test:unit",
|
|
26
28
|
"test:full": "npm test"
|
|
27
29
|
},
|
|
28
30
|
"engines": {
|
package/src/collection-review.js
CHANGED
|
@@ -102,17 +102,37 @@ export async function scaffoldCollectionReview(input = process.cwd(), options =
|
|
|
102
102
|
const resourceType = requiredType(loaded, options.resourceType);
|
|
103
103
|
const assessment = assessCollectionReview(loaded, resourceType, { programId: program.id });
|
|
104
104
|
const allowedDecisions = assessment.configuration.decisions || ["complete"];
|
|
105
|
+
const now = options.now ? new Date(options.now) : new Date();
|
|
106
|
+
if (Number.isNaN(now.getTime())) throw new Error("A valid Collection Review time is required.");
|
|
107
|
+
const priorReview = assessment.review;
|
|
108
|
+
const v4 = modelSupports(loaded.model, "program-scope");
|
|
109
|
+
const priorAuthoritativeSourceId = priorReview?.authoritativeComponentId || priorReview?.authoritativeSystemId || null;
|
|
110
|
+
const priorAuthoritativeSourceActive = priorReview?.decision !== "externally-managed" || loaded.resources.some((record) => (
|
|
111
|
+
record.type === (v4 ? "component" : "system")
|
|
112
|
+
&& record.id === priorAuthoritativeSourceId
|
|
113
|
+
&& record.status === "active"
|
|
114
|
+
));
|
|
115
|
+
const priorDecisionStillValid = allowedDecisions.includes(priorReview?.decision)
|
|
116
|
+
&& priorAuthoritativeSourceActive
|
|
117
|
+
&& (assessment.records.length
|
|
118
|
+
? priorReview.decision !== "zero-population"
|
|
119
|
+
: priorReview.decision !== "complete");
|
|
120
|
+
const preservedAuthoritativeSourceId = priorDecisionStillValid && priorReview.decision === "externally-managed"
|
|
121
|
+
? priorAuthoritativeSourceId
|
|
122
|
+
: null;
|
|
105
123
|
return {
|
|
106
124
|
resourceType,
|
|
107
|
-
decision: assessment.records.length
|
|
125
|
+
decision: priorDecisionStillValid ? priorReview.decision : (assessment.records.length
|
|
108
126
|
? "complete"
|
|
109
|
-
: allowedDecisions.includes("zero-population") ? "zero-population" : null,
|
|
110
|
-
rationale: null,
|
|
111
|
-
reviewedByIds: [],
|
|
112
|
-
reviewedOn:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
: allowedDecisions.includes("zero-population") ? "zero-population" : null),
|
|
128
|
+
rationale: priorReview?.rationale || null,
|
|
129
|
+
reviewedByIds: [...(priorReview?.reviewedByIds || [])],
|
|
130
|
+
reviewedOn: priorReview?.reviewedOn
|
|
131
|
+
? currentCalendarDate(loaded.workspace.timezone, now)
|
|
132
|
+
: null,
|
|
133
|
+
...(v4
|
|
134
|
+
? { authoritativeComponentId: preservedAuthoritativeSourceId }
|
|
135
|
+
: { authoritativeSystemId: preservedAuthoritativeSourceId })
|
|
116
136
|
};
|
|
117
137
|
}
|
|
118
138
|
|
package/src/files.js
CHANGED
|
@@ -965,14 +965,22 @@ async function updateContentUnlocked(input, dataRelativePath, source, options) {
|
|
|
965
965
|
const path = resolveDataPath(loaded.root, dataRelativePath);
|
|
966
966
|
const previous = await readFile(path, "utf8");
|
|
967
967
|
assertRevision(previous, options.expectedRevision, "The Markdown file");
|
|
968
|
-
const
|
|
968
|
+
const deferValidation = workspaceValidationDeferred();
|
|
969
|
+
const before = deferValidation ? null : await validateWorkspace(loaded);
|
|
969
970
|
const nextSource = source.endsWith("\n") ? source : `${source}\n`;
|
|
970
971
|
await writeTextAtomic(path, nextSource);
|
|
971
972
|
try {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
973
|
+
if (!deferValidation) {
|
|
974
|
+
const result = await validateWorkspace(loaded.root);
|
|
975
|
+
const introduced = newErrors(result, before);
|
|
976
|
+
if (introduced.length) throw new Error(formatWriteFailure(introduced, dataRelativePath));
|
|
977
|
+
}
|
|
978
|
+
return {
|
|
979
|
+
path,
|
|
980
|
+
dataRelativePath,
|
|
981
|
+
source: nextSource,
|
|
982
|
+
revision: contentRevision(nextSource)
|
|
983
|
+
};
|
|
976
984
|
} catch (error) {
|
|
977
985
|
await writeTextAtomic(path, previous);
|
|
978
986
|
throw error;
|