@groma/scanner-react 0.2.0 → 0.2.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/README.md +1 -1
- package/dist/index.js +45 -27
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ bun plugins/scanners/react/build.ts
|
|
|
15
15
|
From the project being scanned:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
groma
|
|
18
|
+
groma plugin add /absolute/path/to/groma/plugins/scanners/react/dist/package
|
|
19
19
|
groma scanner check
|
|
20
20
|
groma scan
|
|
21
21
|
```
|
package/dist/index.js
CHANGED
|
@@ -252,13 +252,13 @@ function compare(...values) {
|
|
|
252
252
|
}
|
|
253
253
|
function uniqueBy(values, key, label) {
|
|
254
254
|
const seen = new Set;
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
const keyed = values.map((value) => ({ id: key(value), value }));
|
|
256
|
+
for (const { id } of keyed) {
|
|
257
257
|
if (seen.has(id))
|
|
258
258
|
throw new Error(`duplicate ${label}: ${id}`);
|
|
259
259
|
seen.add(id);
|
|
260
260
|
}
|
|
261
|
-
return
|
|
261
|
+
return keyed.sort((left, right) => left.id.localeCompare(right.id)).map((entry) => entry.value);
|
|
262
262
|
}
|
|
263
263
|
function createScanObservation(input) {
|
|
264
264
|
const roots = validateRoots(input.roots);
|
|
@@ -269,9 +269,7 @@ function createScanObservation(input) {
|
|
|
269
269
|
symbols: [...new Map(file.symbols.map((symbol) => [
|
|
270
270
|
compare(symbol.id, symbol.kind),
|
|
271
271
|
symbol
|
|
272
|
-
]))
|
|
273
|
-
return compare(left.id, left.kind).localeCompare(compare(right.id, right.kind));
|
|
274
|
-
})
|
|
272
|
+
]))].sort(([left], [right]) => left.localeCompare(right)).map(([, symbol]) => symbol)
|
|
275
273
|
})), (file) => file.file, "file path");
|
|
276
274
|
const filePaths = new Set(files.map((file) => file.file));
|
|
277
275
|
for (const file of files) {
|
|
@@ -282,8 +280,6 @@ function createScanObservation(input) {
|
|
|
282
280
|
throw new Error(`file references unknown root: ${root}`);
|
|
283
281
|
}
|
|
284
282
|
}
|
|
285
|
-
for (const diagnostic of input.diagnostics)
|
|
286
|
-
diagnosticLocation(diagnostic);
|
|
287
283
|
return {
|
|
288
284
|
schemaVersion: 1,
|
|
289
285
|
scanner: input.scanner,
|
|
@@ -293,14 +289,14 @@ function createScanObservation(input) {
|
|
|
293
289
|
...entryPoints(input.entryPoints, filePaths),
|
|
294
290
|
...operationEvidence(input, filePaths),
|
|
295
291
|
...httpEvidence(input.httpEndpoints, input.httpRequests, input.operations && new Set(input.operations.map((operation) => operation.id))),
|
|
296
|
-
diagnostics:
|
|
297
|
-
diagnosticKey(diagnostic),
|
|
298
|
-
diagnostic
|
|
299
|
-
])).values()].sort((left, right) => {
|
|
300
|
-
return diagnosticKey(left).localeCompare(diagnosticKey(right));
|
|
301
|
-
})
|
|
292
|
+
diagnostics: normalizeScanDiagnostics(input.diagnostics)
|
|
302
293
|
};
|
|
303
294
|
}
|
|
295
|
+
function normalizeScanDiagnostics(diagnostics) {
|
|
296
|
+
for (const diagnostic of diagnostics)
|
|
297
|
+
diagnosticLocation(diagnostic);
|
|
298
|
+
return [...new Map(diagnostics.map((diagnostic) => [diagnosticKey(diagnostic), diagnostic]))].sort(([left], [right]) => left.localeCompare(right)).map(([, diagnostic]) => diagnostic);
|
|
299
|
+
}
|
|
304
300
|
function entryPoints(input, paths) {
|
|
305
301
|
if (input === undefined)
|
|
306
302
|
return {};
|
|
@@ -409,10 +405,14 @@ function operationTokens(operation) {
|
|
|
409
405
|
const endLine = Number(operation.endLine);
|
|
410
406
|
if (endLine < startLine)
|
|
411
407
|
throw new Error("operation.endLine must be at or after startLine");
|
|
408
|
+
const tokens = array(operation.tokens, "operation.tokens");
|
|
409
|
+
tokens.forEach((token) => {
|
|
410
|
+
string(token, "operation.token");
|
|
411
|
+
});
|
|
412
412
|
return {
|
|
413
413
|
startLine,
|
|
414
414
|
endLine,
|
|
415
|
-
tokens
|
|
415
|
+
tokens
|
|
416
416
|
};
|
|
417
417
|
}
|
|
418
418
|
function validateOperationTokens(operation) {
|
|
@@ -603,20 +603,32 @@ function reachedFiles(entry, compiled, imports, packages, units) {
|
|
|
603
603
|
}
|
|
604
604
|
async function declaredEntries(root, declarations, packages, workspaces) {
|
|
605
605
|
const entries = [];
|
|
606
|
+
const diagnostics = [];
|
|
606
607
|
for (const file of declarations) {
|
|
607
608
|
const text = await readFile3(path4.join(root, file), "utf8");
|
|
608
609
|
const name = path4.posix.basename(file);
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
610
|
+
try {
|
|
611
|
+
if (name === "package.json") {
|
|
612
|
+
const manifest = JSON.parse(text);
|
|
613
|
+
entries.push(...declaredBins(file, manifest), ...declaredScripts(file, manifest.scripts));
|
|
614
|
+
} else if (name === "angular.json")
|
|
615
|
+
entries.push(...angularEntries(file, text));
|
|
616
|
+
else if (name === "project.json")
|
|
617
|
+
entries.push(...nxEntries(file, text, workspaces));
|
|
618
|
+
else if (file.endsWith(".html"))
|
|
619
|
+
entries.push(...browserEntries(file, text, packages));
|
|
620
|
+
} catch (error) {
|
|
621
|
+
if (!(error instanceof SyntaxError))
|
|
622
|
+
throw error;
|
|
623
|
+
diagnostics.push({
|
|
624
|
+
severity: "warning",
|
|
625
|
+
code: "JAVASCRIPT_MANIFEST_INVALID",
|
|
626
|
+
file,
|
|
627
|
+
message: `The file is not valid JSON; the entry points it declares are not read. ${error.message}`
|
|
628
|
+
});
|
|
629
|
+
}
|
|
618
630
|
}
|
|
619
|
-
return entries;
|
|
631
|
+
return { entries, diagnostics };
|
|
620
632
|
}
|
|
621
633
|
function sourced(entry, files, outputs = []) {
|
|
622
634
|
const file = sourceOf(entry.file, outputs, files);
|
|
@@ -630,7 +642,8 @@ async function withJavaScriptEntries(root, observation, inputs, files) {
|
|
|
630
642
|
const packages = new Set(inventory.filter((file) => path4.posix.basename(file) === "package.json").map((file) => path4.posix.dirname(file)));
|
|
631
643
|
const active = new Set(observation.files.map((file) => packageFor(file.file, packages)));
|
|
632
644
|
const declarations = inventory.filter((file) => path4.posix.basename(file) !== "nx.json" && active.has(packageFor(file, packages)));
|
|
633
|
-
const
|
|
645
|
+
const declared = await declaredEntries(root, declarations, packages, workspaces);
|
|
646
|
+
const entries = [...inputs.entries, ...declared.entries];
|
|
634
647
|
const inventoryFiles = [...observation.files];
|
|
635
648
|
const visible = new Set(inventoryFiles.map((file) => file.file));
|
|
636
649
|
const readable = new Set(files);
|
|
@@ -647,7 +660,12 @@ async function withJavaScriptEntries(root, observation, inputs, files) {
|
|
|
647
660
|
}
|
|
648
661
|
return [{ ...entry, files: [...new Set([entry.file, ...members.map((file) => file.file)])] }];
|
|
649
662
|
});
|
|
650
|
-
return createScanObservation({
|
|
663
|
+
return createScanObservation({
|
|
664
|
+
...observation,
|
|
665
|
+
files: inventoryFiles,
|
|
666
|
+
entryPoints,
|
|
667
|
+
diagnostics: [...observation.diagnostics, ...declared.diagnostics]
|
|
668
|
+
});
|
|
651
669
|
}
|
|
652
670
|
|
|
653
671
|
// plugins/scanners/entry-points/source.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groma/scanner-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Complementary React framework evidence; a dependency declaration does not verify runtime use.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"repository": {
|
|
54
54
|
"type": "git",
|
|
55
|
-
"url": "https://github.com/MrLesk/
|
|
55
|
+
"url": "https://github.com/MrLesk/groma.md.git"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|