@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.
Files changed (3) hide show
  1. package/README.md +11 -1
  2. package/dist/index.js +98 -12
  3. 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 the root `tsconfig.json`, its configured source entry points,
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 path2 from "path";
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 path2.relative(root, file).split(path2.sep).join("/");
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 = path2.join(root, "package.json");
226800
- if (!existsSync(manifestPath))
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.dependencies?.["@angular/core"] && !manifest.devDependencies?.["@angular/core"])
226877
+ if (!hasDependency(manifest, "@angular/core"))
226804
226878
  return;
226805
226879
  try {
226806
- const config = readConfiguration(path2.join(root, "tsconfig.json"));
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
- if (!angularProject(root))
226821
- throw new Error("ANGULAR_PROJECT_REQUIRED: Select a project with @angular/core in its root package.json, or disable the angular scanner.");
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 project = angularProject(root);
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.json", "package.json"], exclude: [] },
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.0",
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
  }