@groma/scanner-angular 0.1.0 → 0.1.1
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 +11 -1
- package/dist/index.js +98 -12
- package/package.json +2 -5
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ declarations. Consumers do not run a package build or installation script.
|
|
|
26
26
|
The prototype package name is not a public publication commitment.
|
|
27
27
|
|
|
28
28
|
Prepare the application's ordinary dependencies using its package manager.
|
|
29
|
-
The scanner reads
|
|
29
|
+
The scanner reads each selected project's `tsconfig.json`, its configured source entry points,
|
|
30
30
|
and the Angular resources reachable from that program. It does not install
|
|
31
31
|
dependencies, compile application output, or run application code.
|
|
32
32
|
|
|
@@ -88,3 +88,13 @@ Independent fixture tests load the built package and cover concrete callback
|
|
|
88
88
|
endpoints, complementary TypeScript evidence, curated ownership, HTML-triggered
|
|
89
89
|
rescan, and failure preservation. See [validation](validation.md) for the
|
|
90
90
|
real-project result and remaining release gates.
|
|
91
|
+
|
|
92
|
+
## Nested projects
|
|
93
|
+
|
|
94
|
+
Run Groma from the repository root. The scanner finds package declarations in
|
|
95
|
+
tracked and unignored files, including nested apps and libraries. Dependencies,
|
|
96
|
+
dev dependencies, peer dependencies and optional dependencies identify framework
|
|
97
|
+
projects. Each compiler uses that project's configuration and installed dependencies;
|
|
98
|
+
imported source in sibling repository libraries keeps its original source path.
|
|
99
|
+
Readiness checks all selected projects. A project error fails the complete scan.
|
|
100
|
+
Source and nested package/configuration changes use the shared scanner watch flow.
|
package/dist/index.js
CHANGED
|
@@ -170600,8 +170600,8 @@ var require_semver2 = __commonJS(function(exports, module) {
|
|
|
170600
170600
|
});
|
|
170601
170601
|
|
|
170602
170602
|
// plugins/scanners/angular/src/scan.ts
|
|
170603
|
-
import { existsSync, readFileSync } from "fs";
|
|
170604
|
-
import
|
|
170603
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
170604
|
+
import path3 from "path";
|
|
170605
170605
|
|
|
170606
170606
|
// node_modules/@angular/compiler/fesm2022/compiler.mjs
|
|
170607
170607
|
var _SELECTOR_REGEXP = new RegExp("(\\:not\\()|" + "(([\\.\\#]?)[-\\w]+)|" + `(?:\\[([-.\\w*\\\\$]+)(?:=(["']?)([^\\]"']*)\\5)?\\])|` + "(\\))|" + "(\\s*,\\s*)", "g");
|
|
@@ -226672,8 +226672,82 @@ function sourcePosition(position) {
|
|
|
226672
226672
|
|
|
226673
226673
|
// plugins/scanners/angular/src/scan.ts
|
|
226674
226674
|
var import_typescript114 = __toESM(require_typescript(), 1);
|
|
226675
|
+
|
|
226676
|
+
// plugins/scanners/projects.ts
|
|
226677
|
+
import { execFile } from "child_process";
|
|
226678
|
+
import { existsSync } from "fs";
|
|
226679
|
+
import { readFile } from "fs/promises";
|
|
226680
|
+
import path2 from "path";
|
|
226681
|
+
import { promisify } from "util";
|
|
226682
|
+
var execute = promisify(execFile);
|
|
226683
|
+
var excluded = new Set([
|
|
226684
|
+
".git",
|
|
226685
|
+
"node_modules",
|
|
226686
|
+
"vendor",
|
|
226687
|
+
"target",
|
|
226688
|
+
"dist",
|
|
226689
|
+
"build",
|
|
226690
|
+
"bin",
|
|
226691
|
+
"obj",
|
|
226692
|
+
".gradle",
|
|
226693
|
+
".angular",
|
|
226694
|
+
"coverage",
|
|
226695
|
+
"generated",
|
|
226696
|
+
"groma",
|
|
226697
|
+
".groma"
|
|
226698
|
+
]);
|
|
226699
|
+
async function projectFiles(root, matches) {
|
|
226700
|
+
const { stdout } = await execute("git", ["-C", root, "ls-files", "-z", "--cached", "--others", "--exclude-standard"], { maxBuffer: 64 * 1024 * 1024 });
|
|
226701
|
+
return [...new Set(stdout.split("\x00").filter((file) => file && matches(file) && !file.split("/").some((part) => excluded.has(part)) && existsSync(path2.join(root, file))))].sort();
|
|
226702
|
+
}
|
|
226703
|
+
function hasDependency(manifest, dependency) {
|
|
226704
|
+
return ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"].some((section) => typeof manifest[section]?.[dependency] === "string");
|
|
226705
|
+
}
|
|
226706
|
+
async function frameworkProjects(root, dependency) {
|
|
226707
|
+
const projects = [];
|
|
226708
|
+
for (const file of await projectFiles(root, (file) => path2.posix.basename(file) === "package.json")) {
|
|
226709
|
+
const manifest = JSON.parse(await readFile(path2.join(root, file), "utf8"));
|
|
226710
|
+
if (hasDependency(manifest, dependency))
|
|
226711
|
+
projects.push(path2.dirname(path2.join(root, file)));
|
|
226712
|
+
}
|
|
226713
|
+
return projects;
|
|
226714
|
+
}
|
|
226715
|
+
|
|
226716
|
+
// plugins/scanners/observations.ts
|
|
226717
|
+
function combineObservations(parts) {
|
|
226718
|
+
if (!parts.length)
|
|
226719
|
+
return;
|
|
226720
|
+
const roots = [];
|
|
226721
|
+
const files = new Map;
|
|
226722
|
+
const operations = [];
|
|
226723
|
+
const invocations = [];
|
|
226724
|
+
const diagnostics = [];
|
|
226725
|
+
for (const { key, observation } of parts) {
|
|
226726
|
+
const id = (value) => JSON.stringify([key, value]);
|
|
226727
|
+
roots.push(...observation.roots.map((root) => ({ ...root, id: id(root.id), ...root.parent ? { parent: id(root.parent) } : {} })));
|
|
226728
|
+
for (const source of observation.files) {
|
|
226729
|
+
const combined = files.get(source.file) ?? { file: source.file, roots: [], symbols: [] };
|
|
226730
|
+
combined.roots.push(...source.roots.map(id));
|
|
226731
|
+
combined.symbols.push(...source.symbols.map((symbol) => ({ ...symbol, id: id(symbol.id) })));
|
|
226732
|
+
files.set(source.file, combined);
|
|
226733
|
+
}
|
|
226734
|
+
operations.push(...(observation.operations ?? []).map((operation) => ({ ...operation, id: id(operation.id) })));
|
|
226735
|
+
invocations.push(...(observation.invocations ?? []).map((call) => ({ ...call, source: id(call.source), targets: call.targets.map(id) })));
|
|
226736
|
+
diagnostics.push(...observation.diagnostics);
|
|
226737
|
+
}
|
|
226738
|
+
return createScanObservation({
|
|
226739
|
+
scanner: parts[0].observation.scanner,
|
|
226740
|
+
roots,
|
|
226741
|
+
files: [...files.values()],
|
|
226742
|
+
operations,
|
|
226743
|
+
invocations,
|
|
226744
|
+
diagnostics
|
|
226745
|
+
});
|
|
226746
|
+
}
|
|
226747
|
+
|
|
226748
|
+
// plugins/scanners/angular/src/scan.ts
|
|
226675
226749
|
function relative4(root, file) {
|
|
226676
|
-
return
|
|
226750
|
+
return path3.relative(root, file).split(path3.sep).join("/");
|
|
226677
226751
|
}
|
|
226678
226752
|
function owned(root, source) {
|
|
226679
226753
|
return !source.isDeclarationFile && !relative4(root, source.fileName).startsWith("../") && !source.fileName.includes("/node_modules/") && !source.fileName.endsWith(".ngtypecheck.ts");
|
|
@@ -226796,14 +226870,14 @@ class Evidence {
|
|
|
226796
226870
|
}
|
|
226797
226871
|
}
|
|
226798
226872
|
function angularProject(root) {
|
|
226799
|
-
const manifestPath =
|
|
226800
|
-
if (!
|
|
226873
|
+
const manifestPath = path3.join(root, "package.json");
|
|
226874
|
+
if (!existsSync2(manifestPath))
|
|
226801
226875
|
return;
|
|
226802
226876
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
226803
|
-
if (!manifest
|
|
226877
|
+
if (!hasDependency(manifest, "@angular/core"))
|
|
226804
226878
|
return;
|
|
226805
226879
|
try {
|
|
226806
|
-
const config = readConfiguration(
|
|
226880
|
+
const config = readConfiguration(path3.join(root, "tsconfig.json"));
|
|
226807
226881
|
failDiagnostics(config.errors);
|
|
226808
226882
|
const options = { ...config.options, noEmit: true, _enableTemplateTypeChecker: true };
|
|
226809
226883
|
const ng = new NgtscProgram(config.rootNames, options, createCompilerHost({ options }));
|
|
@@ -226817,11 +226891,23 @@ function angularProject(root) {
|
|
|
226817
226891
|
}
|
|
226818
226892
|
}
|
|
226819
226893
|
async function checkAngularReadiness(root) {
|
|
226820
|
-
|
|
226821
|
-
|
|
226894
|
+
const projects = await frameworkProjects(root, "@angular/core");
|
|
226895
|
+
if (!projects.length)
|
|
226896
|
+
throw new Error("ANGULAR_PROJECT_REQUIRED: No Angular project declaration was found.");
|
|
226897
|
+
for (const project of projects)
|
|
226898
|
+
angularProject(project);
|
|
226822
226899
|
}
|
|
226823
226900
|
async function scanAngular(root) {
|
|
226824
|
-
const
|
|
226901
|
+
const parts = [];
|
|
226902
|
+
for (const project of await frameworkProjects(root, "@angular/core")) {
|
|
226903
|
+
const observation = await scanAngularProject(project, root);
|
|
226904
|
+
if (observation)
|
|
226905
|
+
parts.push({ key: relative4(root, project), observation });
|
|
226906
|
+
}
|
|
226907
|
+
return combineObservations(parts);
|
|
226908
|
+
}
|
|
226909
|
+
async function scanAngularProject(projectRoot, root) {
|
|
226910
|
+
const project = angularProject(projectRoot);
|
|
226825
226911
|
if (!project)
|
|
226826
226912
|
return;
|
|
226827
226913
|
const { manifest, ng } = project;
|
|
@@ -226850,7 +226936,7 @@ async function scanAngular(root) {
|
|
|
226850
226936
|
})), ...[...evidence.templates].map((file) => ({ file, symbols: [] }))];
|
|
226851
226937
|
return createScanObservation({
|
|
226852
226938
|
scanner: { id: "angular", technology: "typescript/angular", engine: "@angular/compiler-cli", engineVersion: VERSION2.full },
|
|
226853
|
-
roots: [{ id: "angular-project", kind: "package", name: manifest.name, file: "package.json" }],
|
|
226939
|
+
roots: [{ id: "angular-project", kind: "package", name: manifest.name, file: relative4(root, path3.join(projectRoot, "package.json")) }],
|
|
226854
226940
|
files: files.map((file) => ({ ...file, roots: ["angular-project"] })),
|
|
226855
226941
|
operations: [...evidence.operations.values()],
|
|
226856
226942
|
invocations: evidence.invocations,
|
|
@@ -226861,7 +226947,7 @@ async function scanAngular(root) {
|
|
|
226861
226947
|
// plugins/scanners/angular/src/index.ts
|
|
226862
226948
|
var src_default = {
|
|
226863
226949
|
id: "angular",
|
|
226864
|
-
watch: { include: ["**/*.ts", "**/*.html", "tsconfig
|
|
226950
|
+
watch: { include: ["**/*.ts", "**/*.html", "**/tsconfig*.json", "**/package.json"], exclude: [] },
|
|
226865
226951
|
checkReadiness: checkAngularReadiness,
|
|
226866
226952
|
scan: scanAngular
|
|
226867
226953
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groma/scanner-angular",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Complementary Angular framework evidence with its own compatible TypeScript tooling.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -25,10 +25,7 @@
|
|
|
25
25
|
}
|
|
26
26
|
],
|
|
27
27
|
"compatibility": {
|
|
28
|
-
"groma": "^0.3.0"
|
|
29
|
-
"technologyVersions": {
|
|
30
|
-
"angular": "21.2.19"
|
|
31
|
-
}
|
|
28
|
+
"groma": "^0.3.0"
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
}
|