ngcompass 0.1.5-beta → 0.1.8-beta

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 CHANGED
@@ -1,9 +1,152 @@
1
- Copyright (c) 2026 Sigkoudis Efthymios. All rights reserved.
1
+ Copyright (c) 2026 Sigkoudis Efthymios
2
2
 
3
- This software is provided free of charge for use in evaluating, testing, and analyzing Angular projects.
3
+ Required Notice: Copyright (c) 2026 Sigkoudis Efthymios
4
4
 
5
- You may download, install, and execute this software for both personal and commercial use.
5
+ # PolyForm Shield License 1.0.0
6
6
 
7
- You may not modify, reverse engineer, decompile, redistribute, repackage, sell, or sublicense this software, or any portion thereof, without explicit written permission from the author.
7
+ <https://polyformproject.org/licenses/shield/1.0.0>
8
8
 
9
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ ## Acceptance
10
+
11
+ To obtain any license under these terms, you must agree to them as both
12
+ strict obligations and conditions to all your licenses.
13
+
14
+ ## Copyright License
15
+
16
+ The licensor grants you a copyright license for the software to do
17
+ everything you might do with the software that would otherwise infringe
18
+ the licensor's copyright in it for any permitted purpose. However, you
19
+ may only distribute the software according to Distribution License and
20
+ make changes or new works based on the software according to Changes and
21
+ New Works License.
22
+
23
+ ## Distribution License
24
+
25
+ The licensor grants you an additional copyright license to distribute
26
+ copies of the software. Your license to distribute covers distributing
27
+ the software with changes and new works permitted by Changes and New
28
+ Works License.
29
+
30
+ ## Notices
31
+
32
+ You must ensure that anyone who gets a copy of any part of the software
33
+ from you also gets a copy of these terms or the URL for them above, as
34
+ well as copies of any plain-text lines beginning with `Required Notice:`
35
+ that the licensor provided with the software. For example:
36
+
37
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
38
+
39
+ ## Changes and New Works License
40
+
41
+ The licensor grants you an additional copyright license to make changes
42
+ and new works based on the software for any permitted purpose.
43
+
44
+ ## Patent License
45
+
46
+ The licensor grants you a patent license for the software that covers
47
+ patent claims the licensor can license, or becomes able to license, that
48
+ you would infringe by using the software.
49
+
50
+ ## Noncompete
51
+
52
+ Any purpose is a permitted purpose, except for providing any product
53
+ that competes with the software or any product the licensor or any of
54
+ its affiliates provides using the software.
55
+
56
+ ## Competition
57
+
58
+ Goods and services compete even when they provide functionality through
59
+ different kinds of interfaces or for different technical platforms.
60
+ Applications can compete with services, libraries with plugins,
61
+ frameworks with development tools, and so on, even if they're written in
62
+ different programming languages or for different computer architectures.
63
+ Goods and services compete even when provided free of charge. If you
64
+ market a product as a practical substitute for the software or another
65
+ product, it definitely competes.
66
+
67
+ ## New Products
68
+
69
+ If you are using the software to provide a product that does not
70
+ compete, but the licensor or any of its affiliates brings your product
71
+ into competition by providing a new version of the software or another
72
+ product using the software, you may continue using versions of the
73
+ software available under these terms beforehand to provide your
74
+ competing product, but not any later versions.
75
+
76
+ ## Discontinued Products
77
+
78
+ You may begin using the software to compete with a product or service
79
+ that the licensor or any of its affiliates has stopped providing, unless
80
+ the licensor includes a plain-text line beginning with `Licensor Line of
81
+ Business:` with the software that mentions that line of business. For
82
+ example:
83
+
84
+ > Licensor Line of Business: YoyodyneCMS Content Management System
85
+ > (http://example.com/cms)
86
+
87
+ ## Sales of Business
88
+
89
+ If the licensor or any of its affiliates sells a line of business
90
+ developing the software or using the software to provide a product, the
91
+ buyer can also enforce Noncompete for that product.
92
+
93
+ ## Fair Use
94
+
95
+ You may have "fair use" rights for the software under the law. These
96
+ terms do not limit them.
97
+
98
+ ## No Other Rights
99
+
100
+ These terms do not allow you to sublicense or transfer any of your
101
+ licenses to anyone else, or prevent the licensor from granting licenses
102
+ to anyone else. These terms do not imply any other licenses.
103
+
104
+ ## Patent Defense
105
+
106
+ If you make any written claim that the software infringes or contributes
107
+ to infringement of any patent, your patent license for the software
108
+ granted under these terms ends immediately. If your company makes such a
109
+ claim, your patent license ends immediately for work on behalf of your
110
+ company.
111
+
112
+ ## Violations
113
+
114
+ The first time you are notified in writing that you have violated any of
115
+ these terms, or done anything with the software not covered by your
116
+ licenses, your licenses can nonetheless continue if you come into full
117
+ compliance with these terms, and take practical steps to correct past
118
+ violations, within 32 days of receiving notice. Otherwise, all your
119
+ licenses end immediately.
120
+
121
+ ## No Liability
122
+
123
+ ***As far as the law allows, the software comes as is, without any
124
+ warranty or condition, and the licensor will not be liable to you for
125
+ any damages arising out of these terms or the use or nature of the
126
+ software, under any kind of legal claim.***
127
+
128
+ ## Definitions
129
+
130
+ The **licensor** is the individual or entity offering these terms, and
131
+ the **software** is the software the licensor makes available under
132
+ these terms.
133
+
134
+ A **product** can be a good or service, or a combination of them.
135
+
136
+ **You** refers to the individual or entity agreeing to these terms.
137
+
138
+ **Your company** is any legal entity, sole proprietorship, or other kind
139
+ of organization that you work for, plus all its affiliates.
140
+
141
+ **Affiliates** means the other organizations than an organization has
142
+ control over, is under the control of, or is under common control with.
143
+
144
+ **Control** means ownership of substantially all the assets of an
145
+ entity, or the power to direct its management and policies by vote,
146
+ contract, or otherwise. Control can be direct or indirect.
147
+
148
+ **Your licenses** are all the licenses granted to you for the software
149
+ under these terms.
150
+
151
+ **Use** means anything you do with the software requiring one of your
152
+ licenses.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  <a href="https://www.npmjs.com/package/ngcompass"><img src="https://img.shields.io/npm/v/ngcompass/beta?label=beta&color=ec4899&style=flat-square" alt="npm beta"></a>
6
6
  <img src="https://img.shields.io/badge/Angular-v15%2B-dd0031?style=flat-square" alt="Angular v15+">
7
7
  <img src="https://img.shields.io/badge/Node.js-20%2B-339933?style=flat-square" alt="Node.js 20+">
8
- <img src="https://img.shields.io/badge/license-MIT-6366f1?style=flat-square" alt="MIT License">
8
+ <img src="https://img.shields.io/badge/license-PolyForm%20Shield%201.0.0-6366f1?style=flat-square" alt="PolyForm Shield 1.0.0">
9
9
  </p>
10
10
  </div>
11
11
 
@@ -17,14 +17,14 @@ It is designed for teams that want a clearer view of Angular-specific risks: com
17
17
 
18
18
  ## Highlights
19
19
 
20
- | Area | What ngcompass helps find |
21
- |---|---|
22
- | Architecture | Circular dependencies, boundary violations, and fragile component relationships |
23
- | Performance | Missing `OnPush`, expensive template expressions, missing `trackBy`, and inefficient bindings |
24
- | SSR | Browser-only APIs in universal code, hydration risks, and render lifecycle pitfalls |
25
- | Security | Unsafe template bindings and sanitizer bypasses |
26
- | Reactivity | RxJS subscription issues, Signals misuse, and migration opportunities |
27
- | Code quality | Deprecated patterns, focused tests, and modern Angular API improvements |
20
+ | Area | What ngcompass helps find |
21
+ | ------------ | --------------------------------------------------------------------------------------------- |
22
+ | Architecture | Circular dependencies, boundary violations, and fragile component relationships |
23
+ | Performance | Missing `OnPush`, expensive template expressions, missing `trackBy`, and inefficient bindings |
24
+ | SSR | Browser-only APIs in universal code, hydration risks, and render lifecycle pitfalls |
25
+ | Security | Unsafe template bindings and sanitizer bypasses |
26
+ | Reactivity | RxJS subscription issues, Signals misuse, and migration opportunities |
27
+ | Code quality | Deprecated patterns, focused tests, and modern Angular API improvements |
28
28
 
29
29
  ## Installation
30
30
 
@@ -71,14 +71,14 @@ pnpm exec ngcompass analyze
71
71
 
72
72
  ## Output Formats
73
73
 
74
- | Command | Output |
75
- |---|---|
76
- | `ngcompass analyze` | Default terminal report |
77
- | `ngcompass analyze --format console --compact` | Compact one-line issue output |
78
- | `ngcompass analyze --format html --output report.html` | Self-contained HTML report |
79
- | `ngcompass analyze --format ui` | Interactive HTML report alias |
80
- | `ngcompass analyze --format json > results.json` | Machine-readable JSON |
81
- | `ngcompass analyze --format sarif > results.sarif` | SARIF for GitHub Code Scanning |
74
+ | Command | Output |
75
+ | ------------------------------------------------------ | ------------------------------ |
76
+ | `ngcompass analyze` | Default terminal report |
77
+ | `ngcompass analyze --format console --compact` | Compact one-line issue output |
78
+ | `ngcompass analyze --format html --output report.html` | Self-contained HTML report |
79
+ | `ngcompass analyze --format ui` | Interactive HTML report alias |
80
+ | `ngcompass analyze --format json > results.json` | Machine-readable JSON |
81
+ | `ngcompass analyze --format sarif > results.sarif` | SARIF for GitHub Code Scanning |
82
82
 
83
83
  ## Configuration
84
84
 
@@ -119,15 +119,15 @@ export default defineConfig({
119
119
 
120
120
  ### Presets
121
121
 
122
- | Preset | Purpose |
123
- |---|---|
124
- | `ngcompass:recommended` | Balanced default for most Angular projects |
125
- | `ngcompass:strict` | Stronger enforcement for mature codebases |
126
- | `ngcompass:performance` | Rendering and change-detection checks |
127
- | `ngcompass:reactivity` | Signals and RxJS correctness |
128
- | `ngcompass:security` | Security-focused Angular checks |
129
- | `ngcompass:ssr` | Server rendering and hydration safety |
130
- | `ngcompass:all` | Every built-in rule at its default severity |
122
+ | Preset | Purpose |
123
+ | ----------------------- | ------------------------------------------- |
124
+ | `ngcompass:recommended` | Balanced default for most Angular projects |
125
+ | `ngcompass:strict` | Stronger enforcement for mature codebases |
126
+ | `ngcompass:performance` | Rendering and change-detection checks |
127
+ | `ngcompass:reactivity` | Signals and RxJS correctness |
128
+ | `ngcompass:security` | Security-focused Angular checks |
129
+ | `ngcompass:ssr` | Server rendering and hydration safety |
130
+ | `ngcompass:all` | Every built-in rule at its default severity |
131
131
 
132
132
  Override individual rules in the same config:
133
133
 
@@ -143,32 +143,32 @@ export default defineConfig({
143
143
 
144
144
  ## Commands
145
145
 
146
- | Command | Description |
147
- |---|---|
148
- | `ngcompass init` | Create `ngcompass.config.ts` |
149
- | `ngcompass analyze` | Run analysis |
150
- | `ngcompass rules` | List available rules |
151
- | `ngcompass rules <name>` | Inspect one rule |
152
- | `ngcompass config health` | Validate configuration |
153
- | `ngcompass cache info` | Show cache status |
154
- | `ngcompass cache clear` | Clear cached analysis data |
155
- | `ngcompass cache path` | Print the cache directory |
146
+ | Command | Description |
147
+ | ------------------------- | ---------------------------- |
148
+ | `ngcompass init` | Create `ngcompass.config.ts` |
149
+ | `ngcompass analyze` | Run analysis |
150
+ | `ngcompass rules` | List available rules |
151
+ | `ngcompass rules <name>` | Inspect one rule |
152
+ | `ngcompass config health` | Validate configuration |
153
+ | `ngcompass cache info` | Show cache status |
154
+ | `ngcompass cache clear` | Clear cached analysis data |
155
+ | `ngcompass cache path` | Print the cache directory |
156
156
 
157
157
  ### Analyze Options
158
158
 
159
- | Option | Description |
160
- |---|---|
161
- | `--format <fmt>` | `console`, `json`, `sarif`, `html`, or `ui` |
162
- | `--output <path>` | Output path for HTML/UI reports |
163
- | `--compact` | Use compact issue output |
164
- | `-q, --quiet` | Show summary counts only |
165
- | `--no-recommendation` | Hide fix recommendations |
166
- | `--rule <id>` | Run one rule in isolation |
167
- | `--force` | Ignore cached results |
168
- | `-p, --profile <name>` | Run a named config profile |
169
- | `--mode <mode>` | Performance mode: `eco`, `balanced`, or `turbo` |
170
- | `--max-workers <n>` | Limit worker threads |
171
- | `--skip-type-check` | Skip rules that require TypeScript type checking |
159
+ | Option | Description |
160
+ | ---------------------- | ------------------------------------------------ |
161
+ | `--format <fmt>` | `console`, `json`, `sarif`, `html`, or `ui` |
162
+ | `--output <path>` | Output path for HTML/UI reports |
163
+ | `--compact` | Use compact issue output |
164
+ | `-q, --quiet` | Show summary counts only |
165
+ | `--no-recommendation` | Hide fix recommendations |
166
+ | `--rule <id>` | Run one rule in isolation |
167
+ | `--force` | Ignore cached results |
168
+ | `-p, --profile <name>` | Run a named config profile |
169
+ | `--mode <mode>` | Performance mode: `eco`, `balanced`, or `turbo` |
170
+ | `--max-workers <n>` | Limit worker threads |
171
+ | `--skip-type-check` | Skip rules that require TypeScript type checking |
172
172
 
173
173
  ## CI
174
174
 
@@ -196,19 +196,19 @@ ngcompass analyze --force
196
196
 
197
197
  ## Monorepo
198
198
 
199
- | Package | Responsibility |
200
- |---|---|
201
- | [`ngcompass`](packages/cli) | CLI entry point |
202
- | [`@ngcompass/config`](packages/config) | Config loading, validation, profiles, and health checks |
203
- | [`@ngcompass/scanner`](packages/scanner) | File discovery and filtering |
204
- | [`@ngcompass/rules`](packages/rules) | Built-in rules, presets, and rule registry |
205
- | [`@ngcompass/planner`](packages/planner) | Incremental execution planning |
206
- | [`@ngcompass/engine`](packages/engine) | Rule execution and analysis orchestration |
207
- | [`@ngcompass/ast`](packages/ast) | TypeScript, template, and style parsing helpers |
208
- | [`@ngcompass/cache`](packages/cache) | Memory and disk cache services |
209
- | [`@ngcompass/reporters`](packages/reporters) | Console, JSON, SARIF, and HTML reporters |
210
- | [`@ngcompass/common`](packages/common) | Shared types and utilities |
211
- | [`@ngcompass/site`](packages/site) | Documentation site |
199
+ | Package | Responsibility |
200
+ | -------------------------------------------- | ------------------------------------------------------- |
201
+ | [`ngcompass`](packages/cli) | CLI entry point |
202
+ | [`@ngcompass/config`](packages/config) | Config loading, validation, profiles, and health checks |
203
+ | [`@ngcompass/scanner`](packages/scanner) | File discovery and filtering |
204
+ | [`@ngcompass/rules`](packages/rules) | Built-in rules, presets, and rule registry |
205
+ | [`@ngcompass/planner`](packages/planner) | Incremental execution planning |
206
+ | [`@ngcompass/engine`](packages/engine) | Rule execution and analysis orchestration |
207
+ | [`@ngcompass/ast`](packages/ast) | TypeScript, template, and style parsing helpers |
208
+ | [`@ngcompass/cache`](packages/cache) | Memory and disk cache services |
209
+ | [`@ngcompass/reporters`](packages/reporters) | Console, JSON, SARIF, and HTML reporters |
210
+ | [`@ngcompass/common`](packages/common) | Shared types and utilities |
211
+ | [`@ngcompass/site`](packages/site) | Documentation site |
212
212
 
213
213
  ## Development
214
214
 
@@ -238,7 +238,3 @@ pnpm prerelease:check
238
238
  - Rule names, messages, and report layout may change before `1.0`.
239
239
  - Template analysis is best-effort for highly dynamic templates.
240
240
  - Validate ngcompass against your project before making it a required CI gate.
241
-
242
- ## License
243
-
244
- MIT. See [LICENSE](./LICENSE).
package/dist/cli.cjs CHANGED
@@ -1,22 +1,21 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var commander=require('commander'),reporters=require('@ngcompass/reporters'),config=require('@ngcompass/config'),L=require('path'),h=require('picocolors'),common=require('@ngcompass/common'),k=require('process'),cache=require('@ngcompass/cache'),rules=require('@ngcompass/rules'),engine=require('@ngcompass/engine'),planner=require('@ngcompass/planner'),scanner=require('@ngcompass/scanner');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var L__default=/*#__PURE__*/_interopDefault(L);var h__default=/*#__PURE__*/_interopDefault(h);var k__default=/*#__PURE__*/_interopDefault(k);var f=(t=1)=>{process.stdout.isTTY&&process.stdout.write("\x1B[?25h"),process.exit(t);};function ce(t,r){t.command("init").description("Create a starter ngcompass configuration in the current project").option("-f, --force","Overwrite an existing configuration file").option("--cwd <path>","Project directory where the configuration will be created",process.cwd()).action(async e=>{try{let o=await config.initConfig({cwd:e.cwd,force:e.force});await reporters.getConfigReporter().renderInitResult(o),o.success||o.alreadyExists||f();}catch(o){console.error(o instanceof Error?o.message:String(o)),f();}});}var le=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],j=class{stream;timer=null;frameIndex=0;message="";isTTY;constructor(r){this.stream=r,this.isTTY=!!r.isTTY;}start(r){this.message=r,this.frameIndex=0,this.isTTY?(this.stream.write("\x1B[?25l"),this.render(),this.timer=setInterval(()=>this.render(),80)):this.stream.write(`${h__default.default.cyan("\u276F")} ${h__default.default.dim(r)}
2
+ 'use strict';var commander=require('commander'),reporters=require('@ngcompass/reporters'),config=require('@ngcompass/config'),k=require('picocolors'),E=require('process'),cache=require('@ngcompass/cache'),N=require('path'),common=require('@ngcompass/common'),engine=require('@ngcompass/engine'),planner=require('@ngcompass/planner'),scanner=require('@ngcompass/scanner'),rules=require('@ngcompass/rules');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var k__default=/*#__PURE__*/_interopDefault(k);var E__default=/*#__PURE__*/_interopDefault(E);var N__default=/*#__PURE__*/_interopDefault(N);var $=()=>{process.stdout.isTTY&&process.stdout.write("\x1B[?25h");},f=(t=1)=>{$(),process.exit(t);},d=(t,r)=>{let e=r===void 0?"":`: ${r instanceof Error?r.message:String(r)}`;console.error(`${k__default.default.red(t)}${e}`);};function D(t,r){t.command("init").description("Create a starter ngcompass configuration in the current project").option("-f, --force","Overwrite an existing configuration file").option("--cwd <path>","Project directory where the configuration will be created",process.cwd()).action(async e=>{try{let n=await config.initConfig({cwd:e.cwd,force:e.force});await reporters.getConfigReporter().renderInitResult(n),n.success||n.alreadyExists||f();}catch(n){d("Error initializing configuration",n),f();}});}var M=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],R=class{stream;timer=null;frameIndex=0;message="";isTTY;constructor(r){this.stream=r,this.isTTY=!!r.isTTY;}start(r){this.message=r,this.frameIndex=0,this.isTTY?(this.stream.write("\x1B[?25l"),this.render(),this.timer=setInterval(()=>this.render(),80)):this.stream.write(`${k__default.default.cyan("\u276F")} ${k__default.default.dim(r)}
3
3
  `);}update(r){this.message=r,this.isTTY&&this.timer&&this.render();}writeLine(r){this.isTTY&&this.timer?(this.stream.write("\r\x1B[K"),this.stream.write(`${r}
4
4
  `),this.render()):this.stream.write(`${r}
5
- `);}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.isTTY&&(this.stream.write("\r\x1B[K"),this.stream.write("\x1B[?25h"));}render(){let r=h__default.default.cyan(le[this.frameIndex%le.length]);this.frameIndex++,this.stream.write(`\r\x1B[K${r} ${h__default.default.dim(this.message)}`);}};var we={eco:{typeAwareConcurrency:1,typeAwareFileConcurrency:1,typeAwareChunkSize:100,typeAwareIsolation:"auto",typeAwareChunkStrategy:"dependency"},balanced:{typeAwareConcurrency:2,typeAwareFileConcurrency:2,typeAwareChunkSize:300,typeAwareIsolation:"auto",typeAwareChunkStrategy:"simple"},turbo:{typeAwareConcurrency:2,typeAwareFileConcurrency:4,typeAwareChunkSize:500,typeAwareIsolation:"off",typeAwareChunkStrategy:"simple"}},pe=Object.keys(we),me=["auto","process","off"],de=["dependency","simple"];function z(t,r){if(t===void 0)return;let e=Number(t);if(!Number.isInteger(e)||e<1)throw Error(`${r} must be a positive integer.`);return e}function fe(t){return t==="ui"?"html":t??"console"}function D(t){return t<1e3?`${Math.max(0,Math.round(t))}ms`:`${(t/1e3).toFixed(1)}s`}function ge(t,r){return `${t.toLocaleString()} ${r}${t===1?"":"s"}`}function he(t,r,e){return `Running analysis in ${t} mode: ${r.toLocaleString()}/${e.toLocaleString()} checks complete...`}function ye(t,r){t.command("analyze").description("Analyze your project and report rule violations and architecture risks").option("-p, --profile <name>","Configuration profile to run").option("--force","Ignore cached results and re-run all checks").option("--format <fmt>","Reporter format: console | json | sarif | html | ui").option("--compact","Use compact, ESLint-style output").option("-q, --quiet","Show summary counts only, suppress violation details").option("--no-recommendation","Suppress fix recommendations from output").option("--output <path>","Output path for UI reports (default: ngcompass-report.html)").option("--rule <id>","Run only one rule (useful for debugging or focused checks)").option("--mode <mode>","Performance mode: eco | balanced | turbo (default: balanced)","balanced").option("--max-workers <n>","Cap the number of worker threads (lower = less memory, e.g. --max-workers 2)").addOption(new commander.Option("--type-aware-chunk-size <n>","Files per type-aware chunk").hideHelp()).addOption(new commander.Option("--type-aware-concurrency <n>","Concurrent type-aware chunks").hideHelp()).addOption(new commander.Option("--type-aware-file-concurrency <n>","Concurrent files per type-aware chunk").hideHelp()).addOption(new commander.Option("--type-aware-isolation <mode>","Type-aware isolation: auto | process | off").hideHelp()).addOption(new commander.Option("--type-aware-chunk-strategy <mode>","Type-aware chunk ordering: dependency | simple").hideHelp()).option("--skip-type-check","Skip rules that require the TypeScript type checker (fastest, lowest memory)").action(async e=>{let o=performance.now(),a=reporters.getReporter(fe(e.format),{compact:!!e.compact,outputPath:e.output,quiet:!!e.quiet,noRecommendation:e.recommendation===false}),n=r,i=0;try{var l;let p,R,A,K,V,J,Q,X=await He(e,r,a);if(!X){i=1;return}let{config:w}=X,Z=(p=we[(function(u){let C=u??"balanced";if(!pe.includes(C))throw Error(`Invalid performance mode "${C}". Expected one of: ${pe.join(", ")}.`);return C})(e.mode)],R=z(e.maxWorkers,"--max-workers"),A=z(e.typeAwareChunkSize,"--type-aware-chunk-size"),K=z(e.typeAwareConcurrency,"--type-aware-concurrency"),V=z(e.typeAwareFileConcurrency,"--type-aware-file-concurrency"),{maxWorkers:R??w.maxWorkers,typeAwareChunkSize:A??p.typeAwareChunkSize,typeAwareConcurrency:K??p.typeAwareConcurrency,typeAwareFileConcurrency:V??p.typeAwareFileConcurrency,typeAwareIsolation:(function(u){if(u!==void 0){if(!me.includes(u))throw Error(`Invalid --type-aware-isolation "${u}". Expected one of: ${me.join(", ")}.`);return u}})(e.typeAwareIsolation)??p.typeAwareIsolation,typeAwareChunkStrategy:(function(u){if(u!==void 0){if(!de.includes(u))throw Error(`Invalid --type-aware-chunk-strategy "${u}". Expected one of: ${de.join(", ")}.`);return u}})(e.typeAwareChunkStrategy)??p.typeAwareChunkStrategy});n=cache.createRuntimeCache(w,k__default.default.cwd());let T=(function(u,C){if(u)return fe(u);switch(C){case "json":return "json";case "sarif":return "sarif";case "html":return "html";default:return "console"}})(e.format,w.outputFormat);a=reporters.getReporter(T,{compact:!!e.compact,outputPath:e.output??w.outputPath,quiet:!!e.quiet,noRecommendation:e.recommendation===!1});let I=await qe(w,e,n,a);if(!I){i=1;return}let ee=await Ge(w,e,a);if(!ee){i=1;return}let y=await Ke(I,ee,n,e,a,w,Z.maxWorkers);if(!y){i=1;return}let Ee=T==="console"?k__default.default.stdout:k__default.default.stderr,F=new j(Ee),Se=y.tasks.length+(y.skippedTasks?.length??0),re=e.mode??"balanced";F.start(he(re,0,Se));let be=(function(u,C,oe){let P=new Map,v=new Map;for(let m of u.tasks){let s=m.filePath;typeof s=="string"&&s.length!==0&&(m.needsTypeChecker||m.needsProjectContext?v.set(s,(v.get(s)??0)+1):P.set(s,(P.get(s)??0)+1));}let _=new Map,Te=new Map,ne=new Set,O=new Set,B=(m,s)=>{let c=m.get(s.filePath),g=c?{taskCount:c.taskCount+s.taskCount,issueCount:c.issueCount+s.issueCount,errorCount:c.errorCount+s.errorCount,warningCount:c.warningCount+s.warningCount,duration:c.duration+s.duration}:{taskCount:s.taskCount,issueCount:s.issueCount,errorCount:s.errorCount,warningCount:s.warningCount,duration:s.duration};return m.set(s.filePath,g),g},Y=(m,s)=>{if(O.has(m))return;O.add(m);let c=L__default.default.relative(oe,m)||m,g=s.issueCount>0,d=g?h__default.default.red("\u276F"):h__default.default.green("\u276F"),x=g?h__default.default.red(D(s.duration)):h__default.default.green(D(s.duration));C(g?`${d} ${h__default.default.red(c)} ${x} ${h__default.default.red(ge(s.issueCount,"issue"))}`:`${d} ${h__default.default.dim(c)} ${x}`);};return m=>{let s=m.filePath;if(!O.has(s))if(m.typeAware===!1){let c=B(_,m),g=P.get(s)??c.taskCount;if(c.taskCount<g)return;v.has(s)?((d,x)=>{if(ne.has(d)||O.has(d))return;ne.add(d);let ae=L__default.default.relative(oe,d)||d,U=x.issueCount>0,ie=U?h__default.default.red("\u276F"):h__default.default.green("\u276F"),se=U?h__default.default.red(D(x.duration)):h__default.default.green(D(x.duration));C(U?`${ie} ${h__default.default.red(ae)} ${se} ${h__default.default.red(ge(x.issueCount,"issue"))}`:`${ie} ${h__default.default.dim(ae)} ${se}`);})(s,c):Y(s,c);}else if(m.typeAware===!0){let c=B(Te,m),g=v.get(s)??c.taskCount;if(c.taskCount<g)return;let d=_.get(s);Y(s,d?{taskCount:d.taskCount+c.taskCount,issueCount:d.issueCount+c.issueCount,errorCount:d.errorCount+c.errorCount,warningCount:d.warningCount+c.warningCount,duration:d.duration+c.duration}:c);}else {let c=(P.get(s)??0)+(v.get(s)??0),g=B(_,m);if(g.taskCount<(c||g.taskCount))return;Y(s,g);}}})(y,u=>F.writeLine(u),k__default.default.cwd()),$=await Ve(y,n,Z,e,a,I,w,(u,C)=>{F.update(he(re,u,C));},be);if(F.stop(),!$){i=1;return}let Re=performance.now()-o,te={scannedFiles:new Set([...y.tasks.map(u=>u.filePath),...(y.skippedTasks??[]).map(u=>u.filePath)]).size,discoveredFiles:I.length,totalFiles:$.stats.totalFiles,totalTasks:y.tasks.length+(y.skippedTasks?.length??0),cachedTasks:y.precomputedAnalysis?y.tasks.length:void 0,totalErrors:$.stats.totalErrors,totalWarnings:$.stats.totalWarnings,failOnSeverity:w.failOnSeverity,maxWarnings:w.maxWarnings,duration:Re};T==="console"&&a.summary(te),a.parseErrors($.parseErrors),a.report($.results),T!=="console"&&(a.step("\u276F Writing report..."),a.summary(te)),y.precomputedAnalysis||await Je($.results,n,e,a),l=$.stats,J=w.failOnSeverity??"error",Q=w.maxWarnings??10,(l.totalErrors>0||J==="warn"&&l.totalWarnings>0||l.totalWarnings>Q)&&(i=1);}catch(p){a.error(p),i=1;}finally{n&&n!==r&&await n.flush(),i!==0&&f(i);}});}async function He(t,r,e){let o=performance.now();e.step("\u276F Loading configuration...");let a=await config.resolveConfig({profile:t.profile,cache:r,cwd:k__default.default.cwd()});if(!a.report.valid){let i=a.report.issues.map(l=>{let p=l.path?.join(".")||"root";return `[${l.severity.toUpperCase()}] ${p}: ${l.message}`});return e.error(Error(["Configuration validation failed",...i].join(`
6
- `))),null}if(!a.config)return e.error(Error("No configuration found")),null;let n=a.config.plugins;if(n&&n.length>0){e.step(`\u276F Loading ${n.length} plugin(s)...`);let i=k__default.default.cwd();await config.loadPlugins(n,i,rules.getGlobalRegistry()),e.info(`Loaded ${n.length} plugin(s)`);}return e.debug(`Config resolve: ${(performance.now()-o).toFixed(2)}ms`),{config:a.config}}async function qe(t,r,e,o){let a=performance.now();o.step("\u276F Discovering files...");let n=await scanner.scan({rootDir:k__default.default.cwd(),include:t.include??[...common.DEFAULT_INCLUDE_PATTERNS],exclude:t.exclude??[],ignorePatterns:t.ignorePatterns,tsConfigPath:(function(i,l){if(!i?.project)return;let p=i.tsconfigRootDir?L__default.default.resolve(l,i.tsconfigRootDir):l;return L__default.default.resolve(p,i.project)})(t.parserOptions,k__default.default.cwd()),respectGitignore:true,debug:r.debug,cache:e});return n.ok?(o.info(`\u276F Found ${n.data.files.length} files in ${(performance.now()-a).toFixed(0)}ms`),o.debug(`File discovery: ${(performance.now()-a).toFixed(2)}ms`),n.data.files):(o.error(Error(`File discovery failed: ${n.error.message}`)),null)}async function Ge(t,r,e){let o=performance.now();e.step("\u276F Loading rules...");let a=t;r.rule&&(e.info(`Filtering analysis to single rule: ${r.rule}`),a={...t,rules:{[r.rule]:"error"},extends:[]});let n=await rules.resolveRules(a);if(!n.ok)return e.error(Error(`Rule resolution failed: ${n.error.message}`)),null;let i=rules.getEnabledRules(n.data.rules);return e.info(`\u276F Loaded ${i.size} active rules in ${(performance.now()-o).toFixed(0)}ms`),e.debug(`Rule resolution: ${(performance.now()-o).toFixed(2)}ms`),i}async function Ke(t,r,e,o,a,n,i){let l=performance.now();a.step("\u276F Planning analysis...");let p=await planner.buildExecutionPlan({files:t,rules:r,rootDir:k__default.default.cwd(),cache:e,debug:o.debug,incremental:o.force?{forceRerun:true}:void 0,workerCount:i,overrides:n.overrides});return p.ok?(p.data.precomputedAnalysis?a.info("\u276F Reused cached analysis plan"):a.info(`\u276F Prepared ${p.data.tasks.length.toLocaleString()} checks in ${(performance.now()-l).toFixed(0)}ms`),a.debug(`Plan build: ${(performance.now()-l).toFixed(2)}ms`),p.data):(a.error(Error(`Execution plan building failed: ${p.error.message}`)),null)}async function Ve(t,r,e,o,a,n,i,l,p){let R=performance.now();engine.configureRuleExecutor(rules.executeBatchedNewEngineRules,rules.isNewEngineRule);let A=await engine.runAnalysis(t,{rootDir:k__default.default.cwd(),cache:r,debug:o.debug,files:n,maxWorkers:e.maxWorkers,typeAwareChunkSize:e.typeAwareChunkSize,typeAwareConcurrency:e.typeAwareConcurrency,typeAwareFileConcurrency:e.typeAwareFileConcurrency,typeAwareIsolation:e.typeAwareIsolation,typeAwareChunkStrategy:e.typeAwareChunkStrategy,skipTypeCheck:o.skipTypeCheck,parserOptions:i?.parserOptions,onProgress:l,onFileProgress:p});return A.ok?(a.debug(`Execution: ${(performance.now()-R).toFixed(2)}ms`),A.data):(a.error(Error(`Analysis failed: ${A.error.message}`)),null)}async function Je(t,r,e,o){if(!r)return;let a=performance.now(),n=[];for(let i of t)i.taskId&&n.push([i.taskId,i]);n.length>0&&(await r.results.setMany(n),e.debug&&o.debug(`Saved ${n.length} results to cache (${(performance.now()-a).toFixed(2)}ms)`));}function Ce(t,r){t.command("config").description("Inspect and validate ngcompass configuration").command("health").description("Run semantic validation checks for the active configuration").option("-p, --profile <name>","Configuration profile to validate").action(async e=>{try{let o=await config.validateConfig({cache:e.cache?r:void 0,profile:e.profile});await reporters.getConfigReporter().renderHealthReport(o.report),o.report.valid||f();}catch(o){let a=o instanceof Error?o.message:String(o);console.error(`Error: ${a}`),f();}});}function $e(t,r){let e=t.command("cache").description("Inspect and manage analysis cache data");e.command("clear").description("Clear cached data for one cache type or all cache types").option("-p, --profile <name>","Configuration profile used to resolve cache settings").option("--type <type>","Cache type to clear: ast | config | results | all","all").action(async o=>{let a=reporters.getCacheReporter();k__default.default.stdout.write(h__default.default.dim(` \u203A Clearing cache...
7
- `));let n=o.type,i=["ast","config","results","all"];i.includes(n)||(console.error(h__default.default.red(`Invalid cache type: ${n}. Must be one of: ${i.join(", ")}`)),f());try{let l=await H(r,{profile:o.profile,allowDisabled:!0});n==="all"?await l.clear():await l.clearType(n),a.renderClearResult(n);}catch(l){console.error(h__default.default.red("Error clearing cache:"),l),f();}}),e.command("info").description("Show cache status, size, and usage details").option("-p, --profile <name>","Configuration profile used to resolve cache settings").action(async o=>{let a=reporters.getCacheReporter();try{let n=await H(r,{profile:o.profile,allowDisabled:!0}),i=await n.getInfo();a.renderCacheInfo(i);}catch(n){console.error(h__default.default.red("Error getting cache info:"),n),f();}}),e.command("path").description("Print the resolved cache directory path").option("-p, --profile <name>","Configuration profile used to resolve cache settings").action(async o=>{let a=await H(r,{profile:o.profile,allowDisabled:true});k__default.default.stdout.write(`${a.getCachePath()}
8
- `);});}async function H(t,r={}){let e=r.cwd??k__default.default.cwd();try{let o=await config.resolveConfig({profile:r.profile,cache:t,cwd:e});return !o.report.valid||!o.config?t:cache.createRuntimeCache(o.config,e,{allowDisabled:r.allowDisabled})??t}catch{return t}}function xe(t){t.command("rules [ruleName]").description("Browse available rules or inspect details for a specific rule").option("--preset <name>","Filter by preset: recommended, strict, performance, reactivity, or all").action((r,e)=>{e.preset&&!rules.isBuiltinPreset(e.preset)&&(console.error(h__default.default.red(`Unknown preset: "${e.preset}".`)),console.error(h__default.default.dim("Available presets: recommended, strict, all, performance, reactivity")),f());let o=rules.getRuleListEntries(),a=reporters.getRulesReporter({preset:e.preset});if(r){let n=o.find(i=>i.name===r);if(!n){console.error(h__default.default.red(`Rule "${r}" not found.`)),console.error(h__default.default.dim("Run `ngcompass rules` to list available rules.")),f();return}a.renderSingleRule(n);}else a.render(o);});}function Ae(t,r){ce(t),ye(t,r),Ce(t,r),$e(t,r),xe(t);}var b=()=>{process.stdout.isTTY&&process.stdout.write("\x1B[?25h");},ve=false,S=async(t,r)=>{if(!ve){if(ve=true,b(),t)try{let e=new Promise(o=>setTimeout(o,1e4).unref());await Promise.race([t.flush(),e]);}catch{}process.exit(r);}};async function cr(){let t=new commander.Command;t.name("ngcompass").description("Static analysis and architecture insights for Angular codebases.").version(common.PACKAGE_VERSION,"-V, --version","Display ngcompass version").option("--debug","Enable detailed debug logs across all modules").addHelpText("after",`
5
+ `);}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.isTTY&&(this.stream.write("\r\x1B[K"),this.stream.write("\x1B[?25h"));}render(){let r=k__default.default.cyan(M[this.frameIndex%M.length]);this.frameIndex++,this.stream.write(`\r\x1B[K${r} ${k__default.default.dim(this.message)}`);}};var we={eco:{typeAwareConcurrency:1,typeAwareFileConcurrency:1,typeAwareChunkSize:100,typeAwareIsolation:"auto",typeAwareChunkStrategy:"dependency"},balanced:{typeAwareConcurrency:1,typeAwareFileConcurrency:1,typeAwareChunkSize:150,typeAwareIsolation:"auto",typeAwareChunkStrategy:"dependency"},turbo:{typeAwareConcurrency:2,typeAwareFileConcurrency:4,typeAwareChunkSize:500,typeAwareIsolation:"off",typeAwareChunkStrategy:"simple"}},j=["eco","balanced","turbo"],Ce=new Set(j);function xe(t,r){if(t===void 0)return;let e=Number(t);if(!Number.isInteger(e)||e<1)throw Error(`${r} must be a positive integer.`);return e}function _(t,r){let e=we[(function(n){let o=n??"balanced";if(!Ce.has(o))throw Error(`Invalid performance mode "${o}". Expected one of: ${j.join(", ")}.`);return o})(t.mode)];return {maxWorkers:xe(t.maxWorkers,"--max-workers")??r.maxWorkers,typeAwareChunkSize:e.typeAwareChunkSize,typeAwareConcurrency:e.typeAwareConcurrency,typeAwareFileConcurrency:e.typeAwareFileConcurrency,typeAwareIsolation:e.typeAwareIsolation,typeAwareChunkStrategy:e.typeAwareChunkStrategy}}function F(t){return t==="ui"?"html":t??"console"}function U(t,r){if(t)return F(t);switch(r){case "json":return "json";case "sarif":return "sarif";case "html":return "html";default:return "console"}}function B(t,r){let e=t.failOnSeverity??"error",n=t.maxWarnings??10;return r.totalErrors>0||e==="warn"&&r.totalWarnings>0||r.totalWarnings>n}function Y(t,r){if(!t?.project)return;let e=t.tsconfigRootDir?N__default.default.resolve(r,t.tsconfigRootDir):r;return N__default.default.resolve(e,t.project)}function q(t){return t instanceof Error?t:Error(String(t))}function G(t){return t.mode??"balanced"}function T(t,r,e){return `Running analysis in ${t} mode: ${r.toLocaleString()}/${e.toLocaleString()} checks complete...`}async function H(t,r,e){let n=performance.now();e.step("\u276F Loading configuration...");let o=await config.resolveConfig({profile:t.profile,cache:r,cwd:E__default.default.cwd()});if(!o.report.valid){let i=o.report.issues.map(u=>{let s=u.path?.join(".")||"root";return `[${u.severity.toUpperCase()}] ${s}: ${u.message}`});return e.error(Error(["Configuration validation failed",...i].join(`
6
+ `))),null}if(!o.config)return e.error(Error("No configuration found")),null;let a=o.config.plugins;if(a&&a.length>0){e.step(`\u276F Loading ${a.length} plugin(s)...`);let i=E__default.default.cwd();await config.loadPlugins(a,i,rules.getGlobalRegistry()),e.info(`Loaded ${a.length} plugin(s)`);}return e.debug(`Config resolve: ${(performance.now()-n).toFixed(2)}ms`),{config:o.config}}async function K(t,r,e,n){let o=performance.now();n.step("\u276F Discovering files...");let a=await scanner.scan({rootDir:E__default.default.cwd(),include:t.include??[...common.DEFAULT_INCLUDE_PATTERNS],exclude:t.exclude??[],ignorePatterns:t.ignorePatterns,tsConfigPath:Y(t.parserOptions,E__default.default.cwd()),respectGitignore:true,debug:r.debug,cache:e});return a.ok?(n.info(`\u276F Found ${a.data.files.length} files in ${(performance.now()-o).toFixed(0)}ms`),n.debug(`File discovery: ${(performance.now()-o).toFixed(2)}ms`),a.data.files):(n.error(Error(`File discovery failed: ${a.error.message}`)),null)}async function V(t,r,e){let n=performance.now();e.step("\u276F Loading rules...");let o=t;r.rule&&(e.info(`Filtering analysis to single rule: ${r.rule}`),o={...t,rules:{[r.rule]:"error"},extends:[]});let a=await rules.resolveRules(o,E__default.default.cwd());if(!a.ok)return e.error(Error(`Rule resolution failed: ${a.error.message}`)),null;let i=rules.getEnabledRules(a.data.rules);return e.info(`\u276F Loaded ${i.size} active rules in ${(performance.now()-n).toFixed(0)}ms`),e.debug(`Rule resolution: ${(performance.now()-n).toFixed(2)}ms`),i}async function Z(t,r,e,n,o,a,i){let u=performance.now();o.step("\u276F Planning analysis...");let s=await planner.buildExecutionPlan({files:t,rules:r,rootDir:E__default.default.cwd(),cache:e,debug:n.debug,incremental:n.force?{forceRerun:true}:void 0,workerCount:i,overrides:a.overrides});return s.ok?(s.data.precomputedAnalysis?o.info("\u276F Reused cached analysis plan"):o.info(`\u276F Prepared ${s.data.tasks.length.toLocaleString()} checks in ${(performance.now()-u).toFixed(0)}ms`),o.debug(`Plan build: ${(performance.now()-u).toFixed(2)}ms`),s.data):(o.error(Error(`Execution plan building failed: ${s.error.message}`)),null)}async function J(t,r,e,n,o,a,i,u,s){let C=performance.now();engine.configureRuleExecutor(rules.executeBatchedNewEngineRules,rules.isNewEngineRule);let p=await engine.runAnalysis(t,{rootDir:E__default.default.cwd(),cache:r,debug:n.debug,files:a,maxWorkers:e.maxWorkers,typeAwareChunkSize:e.typeAwareChunkSize,typeAwareConcurrency:e.typeAwareConcurrency,typeAwareFileConcurrency:e.typeAwareFileConcurrency,typeAwareIsolation:e.typeAwareIsolation,typeAwareChunkStrategy:e.typeAwareChunkStrategy,skipTypeCheck:n.skipTypeCheck,parserOptions:i?.parserOptions,onProgress:u,onFileProgress:s});return p.ok?(o.debug(`Execution: ${(performance.now()-C).toFixed(2)}ms`),p.data):(o.error(Error(`Analysis failed: ${p.error.message}`)),null)}async function Q(t,r,e,n){if(!r)return;let o=performance.now(),a=[];for(let i of t)i.taskId&&a.push([i.taskId,i]);a.length>0&&(await r.results.setMany(a),e.debug&&n.debug(`Saved ${a.length} results to cache (${(performance.now()-o).toFixed(2)}ms)`));}var We={taskCount:0,issueCount:0,errorCount:0,warningCount:0,duration:0};function ee(t,r){let e=new Map;for(let n of t.tasks){let o=n.filePath;typeof o=="string"&&o.length!==0&&(n.needsTypeChecker||n.needsProjectContext)===r&&e.set(o,(e.get(o)??0)+1);}return e}function I(t,r){let e=t??We;return {taskCount:e.taskCount+r.taskCount,issueCount:e.issueCount+r.issueCount,errorCount:e.errorCount+r.errorCount,warningCount:e.warningCount+r.warningCount,duration:e.duration+r.duration}}function re(t,r,e){let n=ee(t,false),o=ee(t,true),a=new Map,i=new Map,u=new Set,s=new Set,C=(p,c,g)=>{if(s.has(p))return;let m=g?s:u;m.has(p)||(m.add(p),r((function(y,l){let w=l.issueCount>0,v=w?k__default.default.red("\u276F"):k__default.default.green("\u276F"),A=w?k__default.default.red(common.formatDuration(l.duration)):k__default.default.green(common.formatDuration(l.duration));if(w){let h=`${l.issueCount.toLocaleString()} ${common.pluralise(l.issueCount,"issue")}`;return `${v} ${k__default.default.red(y)} ${A} ${k__default.default.red(h)}`}return `${v} ${k__default.default.dim(y)} ${A}`})(N__default.default.relative(e,p)||p,c)));};return p=>{let c=p.filePath;if(s.has(c))return;if(p.typeAware===false){let l=I(a.get(c),p);a.set(c,l);let w=n.get(c)??l.taskCount;if(l.taskCount<w)return;C(c,l,!o.has(c));return}if(p.typeAware===true){var g;let l=I(i.get(c),p);i.set(c,l);let w=o.get(c)??l.taskCount;if(l.taskCount<w)return;C(c,(g=a.get(c),g?{taskCount:g.taskCount+l.taskCount,issueCount:g.issueCount+l.issueCount,errorCount:g.errorCount+l.errorCount,warningCount:g.warningCount+l.warningCount,duration:g.duration+l.duration}:l),true);return}let m=(n.get(c)??0)+(o.get(c)??0),y=I(a.get(c),p);a.set(c,y),y.taskCount<(m||y.taskCount)||C(c,y,true);}}function oe(t,r){t.command("analyze").description("Analyze your project and report rule violations and architecture risks").option("-p, --profile <name>","Configuration profile to run").option("--force","Ignore cached results and re-run all checks").option("--format <fmt>","Reporter format: console | json | sarif | html | ui").option("--compact","Use compact, ESLint-style output").option("-q, --quiet","Show summary counts only, suppress violation details").option("--no-recommendation","Suppress fix recommendations from output").option("--output <path>","Output path for UI reports (default: ngcompass-report.html)").option("--rule <id>","Run only one rule (useful for debugging or focused checks)").option("--mode <mode>","Performance mode: eco | balanced | turbo (default: balanced)","balanced").option("--max-workers <n>","Cap the number of worker threads (lower = less memory, e.g. --max-workers 2)").option("--skip-type-check","Skip rules that require the TypeScript type checker (fastest, lowest memory)").action(async e=>{let n=performance.now(),o=reporters.getReporter(F(e.format),{compact:!!e.compact,outputPath:e.output,quiet:!!e.quiet,noRecommendation:e.recommendation===false}),a=r,i=0;try{let u=await H(e,r,o);if(!u){i=1;return}let{config:s}=u,C=_(e,s);a=cache.createRuntimeCache(s,E__default.default.cwd());let p=U(e.format,s.outputFormat);o=reporters.getReporter(p,{compact:!!e.compact,outputPath:e.output??s.outputPath,quiet:!!e.quiet,noRecommendation:e.recommendation===!1});let c=await K(s,e,a,o);if(!c){i=1;return}let g=await V(s,e,o);if(!g){i=1;return}let m=await Z(c,g,a,e,o,s,C.maxWorkers);if(!m){i=1;return}let y=p==="console"?E__default.default.stdout:E__default.default.stderr,l=new R(y),w=m.tasks.length+(m.skippedTasks?.length??0),v=G(e);l.start(T(v,0,w));let A=re(m,x=>l.writeLine(x),E__default.default.cwd()),h=await J(m,a,C,e,o,c,s,(x,fe)=>{l.update(T(v,x,fe));},A);if(l.stop(),!h){i=1;return}let de=performance.now()-n,O={scannedFiles:new Set([...m.tasks.map(x=>x.filePath),...(m.skippedTasks??[]).map(x=>x.filePath)]).size,discoveredFiles:c.length,totalFiles:h.stats.totalFiles,totalTasks:m.tasks.length+(m.skippedTasks?.length??0),cachedTasks:m.precomputedAnalysis?m.tasks.length:void 0,totalErrors:h.stats.totalErrors,totalWarnings:h.stats.totalWarnings,failOnSeverity:s.failOnSeverity,maxWarnings:s.maxWarnings,duration:de};p==="console"&&o.summary(O),o.parseErrors(h.parseErrors),o.report(h.results),p!=="console"&&(o.step("\u276F Writing report..."),o.summary(O)),m.precomputedAnalysis||await Q(h.results,a,e,o),B(s,h.stats)&&(i=1);}catch(u){o.error(q(u)),i=1;}finally{a&&a!==r&&await a.flush(),i!==0&&f(i);}});}function ne(t,r){t.command("config").description("Inspect and validate ngcompass configuration").command("health").description("Run semantic validation checks for the active configuration").option("-p, --profile <name>","Configuration profile to validate").action(async e=>{try{let n=await config.validateConfig({cwd:E__default.default.cwd(),cache:e.cache?r:void 0,profile:e.profile});await reporters.getConfigReporter().renderHealthReport(n.report),n.report.valid||f();}catch(n){d("Error",n),f();}});}var ie=["ast","config","results","all"],Be=new Set(ie);function se(t,r){let e=t.command("cache").description("Inspect and manage analysis cache data");e.command("clear").description("Clear cached data for one cache type or all cache types").option("-p, --profile <name>","Configuration profile used to resolve cache settings").option("--type <type>","Cache type to clear: ast | config | results | all","all").action(async n=>{var o;let a,i=(a=o=n.type,Be.has(a)?o:(d(`Invalid cache type: ${o}. Must be one of: ${ie.join(", ")}`),f())),u=reporters.getCacheReporter();E__default.default.stdout.write(k__default.default.dim(` \u203A Clearing cache...
7
+ `));try{let s=await z(r,{profile:n.profile,allowDisabled:!0});i==="all"?await s.clear():await s.clearType(i),u.renderClearResult(i);}catch(s){d("Error clearing cache",s),f();}}),e.command("info").description("Show cache status, size, and usage details").option("-p, --profile <name>","Configuration profile used to resolve cache settings").action(async n=>{let o=reporters.getCacheReporter();try{let a=await z(r,{profile:n.profile,allowDisabled:!0}),i=await a.getInfo();o.renderCacheInfo(i);}catch(a){d("Error getting cache info",a),f();}}),e.command("path").description("Print the resolved cache directory path").option("-p, --profile <name>","Configuration profile used to resolve cache settings").action(async n=>{let o=await z(r,{profile:n.profile,allowDisabled:true});E__default.default.stdout.write(`${o.getCachePath()}
8
+ `);});}async function z(t,r={}){let e=r.cwd??E__default.default.cwd();try{let n=await config.resolveConfig({profile:r.profile,cache:t,cwd:e});return !n.report.valid||!n.config?t:cache.createRuntimeCache(n.config,e,{allowDisabled:r.allowDisabled})??t}catch(n){return d("Unable to resolve cache configuration; using default cache",n),t}}function ce(t){t.command("rules [ruleName]").description("Browse available rules or inspect details for a specific rule").option("--preset <name>","Filter by preset: recommended, strict, performance, reactivity, or all").action((r,e)=>{e.preset&&!rules.isBuiltinPreset(e.preset)&&(d(`Unknown preset: "${e.preset}".`),process.stderr.write(k__default.default.dim(`Available presets: recommended, strict, all, performance, reactivity
9
+ `)),f());let n=rules.getRuleListEntries(),o=reporters.getRulesReporter({preset:e.preset});if(r){let a=n.find(i=>i.name===r);if(!a){d(`Rule "${r}" not found.`),process.stderr.write(k__default.default.dim("Run `ngcompass rules` to list available rules.\n")),f();return}o.renderSingleRule(a);}else o.render(n);});}function pe(t,r){D(t),oe(t,r),ne(t,r),se(t,r),ce(t);}var ue=false,P=async(t,r)=>{if(!ue){if(ue=true,$(),t)try{let e=new Promise(n=>setTimeout(n,1e4).unref());await Promise.race([t.flush(),e]);}catch(e){d("[ngcompass] Cache flush failed during shutdown",e);}process.exit(r);}},me=(t,r,e)=>{d(`[ngcompass] ${r}`,e),P(t,1);},Je=async t=>{let{default:r}=await import('picocolors'),e=process.cwd();process.stdout.write(`
10
+ ${r.dim(">")} ${r.dim(`ngcompass@${common.PACKAGE_VERSION}`)} ${r.dim(t)} ${r.dim(e)}
11
+ ${r.dim(">")} ${r.dim("ngcompass")} ${r.dim("run")}
12
+
13
+ ${r.bgCyan(r.white(r.bold(` ${t.toUpperCase()} `)))} ${r.cyan(common.PACKAGE_VERSION)} ${r.dim(e)}
14
+
15
+ `);};async function Qe(){let t=new commander.Command;t.name("ngcompass").description("Static analysis and architecture insights for Angular codebases.").version(common.PACKAGE_VERSION,"-V, --version","Display ngcompass version").option("--debug","Enable detailed debug logs across all modules").addHelpText("after",`
9
16
  Examples:
10
17
  $ ngcompass init
11
18
  $ ngcompass analyze --profile strict
12
19
  $ ngcompass cache info
13
- `).hook("preAction",async(e,o)=>{e.opts().debug&&common.enableDebug("debug","all");let a=o.opts();if(a.format!=="json"&&a.format!=="sarif"&&a.format!=="html"&&a.format!=="ui"){let{default:n}=await import('picocolors'),i=o.parent,l=i&&i.name()!=="ngcompass"?i.name():o.name(),p=process.cwd();process.stdout.write(`
14
- ${n.dim(">")} ${n.dim(`ngcompass@${common.PACKAGE_VERSION}`)} ${n.dim(l)} ${n.dim(p)}
15
- ${n.dim(">")} ${n.dim("ngcompass")} ${n.dim("run")}
16
-
17
- ${n.bgCyan(n.white(n.bold(` ${l.toUpperCase()} `)))} ${n.cyan(common.PACKAGE_VERSION)} ${n.dim(p)}
18
-
19
- `);}});let r=cache.createCacheContext();process.on("SIGINT",()=>{S(r,130);}),process.on("SIGTERM",()=>{S(r,143);}),process.on("uncaughtException",e=>{b(),console.error(`
20
- [ngcompass] Unexpected error: ${e.message}`),S(r,1);}),process.on("unhandledRejection",e=>{b();let o=e instanceof Error?e.message:String(e);console.error(`
21
- [ngcompass] Unhandled promise rejection: ${o}`),S(r,1);});try{if(rules.registerAllBuiltinRules(),Ae(t,r),!process.argv.slice(2).length)return void t.outputHelp();await t.parseAsync(process.argv),await r.flush(),process.exit(0);}catch(e){b();let o=e instanceof Error?e.message:String(e);console.error(`[ngcompass] Fatal error: ${o}`),await S(r,1);}}cr().catch(t=>{b();let r=t instanceof Error?t.message:String(t);console.error(`[ngcompass] Fatal error: ${r}`),process.exit(1);});exports.run=cr;//# sourceMappingURL=cli.cjs.map
20
+ `).hook("preAction",async(e,n)=>{let o;if(e.opts().debug&&common.enableDebug("debug","all"),(o=n.opts().format)!=="json"&&o!=="sarif"&&o!=="html"&&o!=="ui"){let a=n.parent,i=a&&a.name()!=="ngcompass"?a.name():n.name();await Je(i);}});let r=cache.createCacheContext();process.on("SIGINT",()=>{P(r,130);}),process.on("SIGTERM",()=>{P(r,143);}),process.on("uncaughtException",e=>{me(r,"Unexpected error",e);}),process.on("unhandledRejection",e=>{me(r,"Unhandled promise rejection",e);});try{if(rules.registerAllBuiltinRules(),pe(t,r),!process.argv.slice(2).length)return void t.outputHelp();await t.parseAsync(process.argv),await r.flush(),process.exit(0);}catch(e){d("[ngcompass] Fatal error",e),await P(r,1);}}Qe().catch(t=>{d("[ngcompass] Fatal error",t),$(),process.exit(1);});exports.run=Qe;//# sourceMappingURL=cli.cjs.map
22
21
  //# sourceMappingURL=cli.cjs.map