ng-checkup 0.1.0 → 0.3.0

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 (49) hide show
  1. package/README.md +255 -59
  2. package/dist/baseline.d.ts +72 -0
  3. package/dist/baseline.js +82 -0
  4. package/dist/baseline.js.map +1 -0
  5. package/dist/checks/change-detection.js +5 -0
  6. package/dist/checks/change-detection.js.map +1 -1
  7. package/dist/checks/circular-deps.js +3 -0
  8. package/dist/checks/circular-deps.js.map +1 -1
  9. package/dist/checks/components.js +5 -0
  10. package/dist/checks/components.js.map +1 -1
  11. package/dist/checks/deprecated-apis.js +5 -0
  12. package/dist/checks/deprecated-apis.js.map +1 -1
  13. package/dist/checks/state.js +5 -0
  14. package/dist/checks/state.js.map +1 -1
  15. package/dist/checks/testing.js +3 -0
  16. package/dist/checks/testing.js.map +1 -1
  17. package/dist/checks/type-safety.js +26 -6
  18. package/dist/checks/type-safety.js.map +1 -1
  19. package/dist/checks/version.js +5 -0
  20. package/dist/checks/version.js.map +1 -1
  21. package/dist/cli.d.ts +69 -12
  22. package/dist/cli.js +246 -45
  23. package/dist/cli.js.map +1 -1
  24. package/dist/config.d.ts +49 -0
  25. package/dist/config.js +98 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/files.d.ts +5 -1
  28. package/dist/files.js +10 -4
  29. package/dist/files.js.map +1 -1
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.js +11 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/init.d.ts +92 -0
  34. package/dist/init.js +239 -0
  35. package/dist/init.js.map +1 -0
  36. package/dist/report/html.js +24 -0
  37. package/dist/report/html.js.map +1 -1
  38. package/dist/report/markdown.js +14 -0
  39. package/dist/report/markdown.js.map +1 -1
  40. package/dist/report/terminal.js +21 -0
  41. package/dist/report/terminal.js.map +1 -1
  42. package/dist/types.d.ts +23 -0
  43. package/dist/workspace.d.ts +6 -0
  44. package/dist/workspace.js +1 -0
  45. package/dist/workspace.js.map +1 -1
  46. package/package.json +10 -3
  47. package/schematics/collection.json +10 -0
  48. package/schematics/ng-add/index.cjs +65 -0
  49. package/schematics/ng-add/schema.json +29 -0
package/README.md CHANGED
@@ -1,108 +1,304 @@
1
1
  # ng-checkup
2
2
 
3
- [![npm](https://img.shields.io/npm/v/ng-checkup)](https://www.npmjs.com/package/ng-checkup) [![CI](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml/badge.svg)](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/ng-checkup)](https://www.npmjs.com/package/ng-checkup) [![CI](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml/badge.svg)](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/stefankuburovic/ng-checkup/blob/main/LICENSE)
4
4
 
5
- A one-minute modernization report for any Angular codebase.
5
+ **A one-minute modernization report for any Angular codebase.**
6
6
 
7
- Point it at a repository and it tells you how far the code is from current Angular, what will break on the next upgrade, and where the work is: version gap, deprecated APIs, zoneless readiness, standalone and signal adoption, test runner, type safety and circular dependencies. Each area gets a grade, every finding names the files, and the HTML report is a single self-contained page you can hand to a team lead or a client.
7
+ Point it at a repository and it tells you how far the code is from current Angular, what will break on the next upgrade, and where the work is. Eight areas get a grade, every finding names the files, and the HTML report is one self-contained page you can hand to your team lead.
8
8
 
9
9
  ```bash
10
10
  npx ng-checkup
11
- npx ng-checkup path/to/app --report checkup.html
12
11
  ```
13
12
 
14
- Needs Node 22 or newer.
13
+ ![ng-checkup in a terminal](https://raw.githubusercontent.com/stefankuburovic/ng-checkup/main/docs/terminal.png)
14
+
15
+ **[See a full example report →](https://stefankuburovic.github.io/ng-checkup/example.html)** (the Angular 12 version of the RealWorld example app)
16
+
17
+ ---
18
+
19
+ ## Contents
20
+
21
+ - [Quick start](#quick-start)
22
+ - [Set it up in a project](#set-it-up-in-a-project)
23
+ - [Configuration](#configuration)
24
+ - [Baseline: adopt it on legacy code](#baseline-adopt-it-on-legacy-code)
25
+ - [What it checks](#what-it-checks)
26
+ - [Reports](#reports)
27
+ - [In CI](#in-ci)
28
+ - [Programmatic API](#programmatic-api)
29
+ - [What leaves your machine](#what-leaves-your-machine)
30
+ - [How it works](#how-it-works)
31
+ - [FAQ](#faq)
32
+ - [Roadmap](#roadmap)
33
+ - [Contributing](#contributing)
34
+
35
+ ## Quick start
36
+
37
+ Run it in the root of an Angular CLI or Nx workspace. It needs Node 22 or newer and nothing else; your project does not have to build.
38
+
39
+ ```bash
40
+ # 1. The summary in your terminal
41
+ npx ng-checkup
42
+
43
+ # 2. The full report as a page to share
44
+ npx ng-checkup --report checkup.html
45
+
46
+ # 3. Record today's numbers, then fail CI only when one gets worse
47
+ npx ng-checkup baseline
48
+ npx ng-checkup --fail-on regression
49
+ ```
50
+
51
+ Install dependencies first (`npm install`) if you can: the deprecated-API check reads the installed Angular packages, and without them it is skipped.
52
+
53
+ ## Set it up in a project
54
+
55
+ To keep the checkup in the project, with a script, a config file and a CI step:
56
+
57
+ ```bash
58
+ ng add ng-checkup # Angular CLI: installs it and asks which CI to use
59
+ # or
60
+ npx ng-checkup init # any workspace, including Nx
61
+ ```
62
+
63
+ Both make the same changes and list what they changed:
64
+
65
+ | File | Change |
66
+ | --- | --- |
67
+ | `package.json` | a `"checkup": "ng-checkup"` script, and `ng-checkup` in `devDependencies` (`init` only; `ng add` installs it itself) |
68
+ | `ng-checkup.config.json` | writes `checkup.html` on every run, and an empty `ignore` list |
69
+ | `.gitignore` | the generated reports, if the repository has a `.gitignore` |
70
+ | `ng-checkup.baseline.json` | today's numbers, so CI fails only when one gets worse ([baseline](#baseline-adopt-it-on-legacy-code)) |
71
+ | `.github/workflows/ng-checkup.yml` | runs on every pull request with `--fail-on regression`, uploads the reports (when `.github/` exists) |
72
+ | `ng-checkup.gitlab-ci.yml` | the same as a GitLab job; add `include: [{ local: ng-checkup.gitlab-ci.yml }]` to your `.gitlab-ci.yml` (when that file exists) |
73
+
74
+ After that it is `npm run checkup` (or `pnpm checkup`, `yarn checkup`; the lockfile decides). Running either command again changes nothing. It never overwrites a file you wrote: an existing workflow or config is kept, and a different `checkup` script is kept unless you pass `--force`.
75
+
76
+ ```bash
77
+ npx ng-checkup init --dry-run # show the changes, write nothing
78
+ npx ng-checkup init --ci gitlab # pick the CI instead of detecting it (github, gitlab, none)
79
+ ```
80
+
81
+ ## Configuration
82
+
83
+ `ng-checkup.config.json` in the project root. Every key is optional, and every command-line flag overrides its key.
84
+
85
+ ```json
86
+ {
87
+ "reports": ["checkup.html"],
88
+ "failOn": "poor",
89
+ "maxExamples": 5,
90
+ "offline": false,
91
+ "ignore": ["src/legacy", "**/generated", "apps/*/e2e"]
92
+ }
93
+ ```
94
+
95
+ | Key | Meaning | Flag |
96
+ | --- | --- | --- |
97
+ | `reports` | report files to write, relative to the config file | `--report` |
98
+ | `failOn` | exit with 1 when an area is `poor` (or `fair`), or with `regression` when a measure is worse than the baseline | `--fail-on` |
99
+ | `maxExamples` | example files listed per finding | `--max-examples` |
100
+ | `offline` | skip the npm lookup of the latest Angular version | `--offline` |
101
+ | `ignore` | paths left out of the analysis; a path matches everything below it, `*` stays within a folder, `**` crosses folders | |
102
+ | `baseline` | the baseline file, relative to the config file (default `ng-checkup.baseline.json` in the root) | |
103
+
104
+ An unknown key or a wrong type stops the run with an error, so a typo cannot silently switch off a CI threshold. Use `--config path/to/file.json` for a file elsewhere.
105
+
106
+ ## Baseline: adopt it on legacy code
107
+
108
+ A ten-year-old Angular app will not pass `--fail-on poor` on day one, and a CI check that is red from the start gets switched off. The baseline fixes that: it records today's numbers, and CI fails only when one of them gets worse.
109
+
110
+ ```bash
111
+ npx ng-checkup baseline # writes ng-checkup.baseline.json; commit it
112
+ npx ng-checkup --fail-on regression # in CI: fails only on a number that went up
113
+ ```
15
114
 
16
115
  ```text
17
- ng-checkup 0.1.0 legacy-app · Angular CLI · Angular ^15.2.0
18
- 8 TypeScript files, 1 template, 50 lines of application code, analysed in 32 ms
19
-
20
- [POOR] Angular version & tooling Angular ^15.2.0, 7 majors behind 22.
21
- [INFO] Deprecated APIs Dependencies are not installed, so deprecations could not be read from the Angular packages.
22
- [FAIR] Change detection & zoneless readiness Runs on zone.js; 50% of 2 components use OnPush.
23
- [POOR] Components & templates 2 components: 0% standalone, 0% signal inputs, 0% built-in control flow.
24
- [FAIR] State management Classic NgRx in 2 files, 0 signal()/computed() calls, 0 signal-store files.
25
- [POOR] Testing Karma, 1 spec file, 25% of components and services with a spec.
26
- [POOR] Type safety strictNullChecks off, strictTemplates off, 2 explicit any.
27
- [FAIR] Circular dependencies 1 group of files importing each other in a loop, 2 files in total.
28
-
29
- Score 37/100 Average of the graded areas: good counts 100, fair 60, poor 20. Areas marked info are not counted.
30
-
31
- Top priorities
32
- 1. high Angular 15 is 7 majors behind 22 and out of support (Angular version & tooling)
33
- 2. high `@angular/flex-layout` is end of life (Angular version & tooling)
34
- 3. high Unit tests run on Karma, which is deprecated (Testing)
35
- 4. high End-to-end tests use Protractor, which is end of life (Testing)
36
- 5. high `strictNullChecks` is off (Type safety)
116
+ Baseline 2 worse
117
+ worse Type safety: Explicit any in application code 13 → 15
118
+ worse Type safety: Non-null assertions (x!) 0 → 1
37
119
  ```
38
120
 
39
- On a real 1 600-file Nx monorepo it finishes in under two seconds.
121
+ - **It records counts, not grades:** explicit `any`, `x!`, files in import cycles, components without OnPush or a spec, NgModule-declared components, deprecated API uses and [18 more](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#measures). Lower is better for every one.
122
+ - **It only goes down.** When numbers drop, the run says so; `npx ng-checkup baseline` locks the new numbers in. If a number went up, `baseline` refuses and lists it, so a regression cannot be waved through by re-running the command. `--force` accepts it, which is the moment someone has to explain why in review.
123
+ - **It is a plain, sorted JSON file**, so lowering a number is a one-line diff in a merge request.
124
+ - **The gap to the latest Angular is not in it.** That grows when Angular ships, not when the code gets worse.
125
+
126
+ `ng add ng-checkup` and `npx ng-checkup init` create the first baseline and set CI to `--fail-on regression` for you.
40
127
 
41
128
  ## What it checks
42
129
 
43
- | Area | What it looks at | Graded on |
130
+ | Area | It looks at | Poor when |
44
131
  | --- | --- | --- |
45
- | **Angular version & tooling** | Installed version against the latest on npm, mixed `@angular/*` majors, webpack vs. esbuild builder, end-of-life packages (`@angular/flex-layout`, Protractor, TSLint, …) | The 18-month support window: the newest three majors are supported |
46
- | **Deprecated APIs** | Every Angular and NgRx symbol the code imports that the **installed** packages tag `@deprecated`, plus `*ngIf` / `*ngFor` / `[ngSwitch]` in templates | `high` once a deprecation is two majors old, the earliest Angular may remove it |
47
- | **Change detection** | Zoneless or zone.js (zoneless is the default from Angular 21), OnPush coverage, `NgZone` usage, zone-only test helpers | Zoneless, or OnPush coverage as the readiness proxy |
48
- | **Components & templates** | Standalone vs. NgModule, signal inputs/outputs vs. decorators, built-in control flow, `@defer` | Average adoption, with the `ng generate` migration for each gap |
49
- | **State management** | Classic NgRx, NgRx signal store, Angular signals, `BehaviorSubject` services | Never `poor`: classic NgRx is supported, the check measures the distance to signals |
50
- | **Testing** | Karma / Jest / Vitest, spec files next to components and services, Protractor / Playwright / Cypress | Karma or Protractor, or no specs at all |
51
- | **Type safety** | `strictNullChecks`, `strictTemplates`, `noImplicitAny`, explicit `any` per 1 000 lines, `x!`, `@ts-ignore`, `$any()`, `UntypedForm*` | The two flags that let the most runtime errors through |
52
- | **Circular dependencies** | Import cycles between application files, through barrels and tsconfig `paths` | Groups of files in a loop, with one concrete loop to cut |
132
+ | [**Angular version & tooling**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#version) | installed vs. latest Angular, mixed `@angular/*` majors, webpack builder, end-of-life packages | three or more majors behind, i.e. out of support |
133
+ | [**Deprecated APIs**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#deprecated-apis) | every imported Angular/NgRx symbol your **installed** version tags `@deprecated`, plus `*ngIf` / `*ngFor` in templates | something deprecated two majors ago is still used |
134
+ | [**Change detection**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#change-detection) | zoneless or zone.js, OnPush coverage, `NgZone`, zone-only test helpers | zone.js with less than half the components on OnPush |
135
+ | [**Components & templates**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#components) | standalone, signal inputs and outputs, built-in control flow, `@defer` | average adoption below 40% |
136
+ | [**State management**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#state) | classic NgRx, NgRx signal store, signals, `BehaviorSubject` services | the removed `@Effect()` decorator |
137
+ | [**Testing**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#testing) | Karma / Jest / Vitest, specs next to components and services, Protractor / Playwright / Cypress | Karma, Protractor or no specs |
138
+ | [**Type safety**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#type-safety) | `strictNullChecks`, `strictTemplates`, `noImplicitAny`, `any`, `x!`, `@ts-ignore`, `$any()` | both `strictNullChecks` and `strictTemplates` off |
139
+ | [**Circular dependencies**](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md#circular-deps) | import cycles through relative paths, barrels and tsconfig `paths` | more than three groups or ten files in loops |
140
+
141
+ Each finding says why it matters and which `ng generate` migration fixes it. **[Every check, its grading and its fix →](https://github.com/stefankuburovic/ng-checkup/blob/main/docs/checks.md)**
53
142
 
54
- Defaults that changed between versions are applied per version: a component without `standalone` is standalone from Angular 19 and module-based before; one without `changeDetection` is OnPush from 22 and eager before.
143
+ Defaults that changed between versions are applied per version: a component without `standalone` is standalone from Angular 19, one without `changeDetection` is OnPush from 22, and an app without a zone provider is zoneless from 21.
55
144
 
56
145
  ## Reports
57
146
 
58
- ```bash
59
- npx ng-checkup --report checkup.html # self-contained page, light and dark, prints to PDF cleanly
60
- npx ng-checkup --report checkup.md # for a pull request or a wiki
61
- npx ng-checkup --report checkup.json # everything, machine-readable
62
- npx ng-checkup --verbose # every finding and file in the terminal
147
+ ![The HTML report](https://raw.githubusercontent.com/stefankuburovic/ng-checkup/main/docs/report.png)
148
+
149
+ | Command | Output |
150
+ | --- | --- |
151
+ | `npx ng-checkup` | summary and top five priorities in the terminal |
152
+ | `npx ng-checkup --verbose` | every finding with its files in the terminal |
153
+ | `npx ng-checkup --report checkup.html` | self-contained page: light and dark mode, prints cleanly to PDF, loads nothing from the network |
154
+ | `npx ng-checkup --report checkup.md` | Markdown for a pull request, an issue or a wiki |
155
+ | `npx ng-checkup --report checkup.json` | everything, machine-readable |
156
+ | `npx ng-checkup --json` | the JSON on stdout, for piping |
157
+
158
+ `--report` is repeatable, so one run can write all three files.
159
+
160
+ <details>
161
+ <summary>All options</summary>
162
+
163
+ ```text
164
+ Usage: ng-checkup [path] [options]
165
+ ng-checkup init [path] [init options]
166
+ ng-checkup baseline [path] [--force]
167
+
168
+ Arguments:
169
+ path Repository root (default: current directory)
170
+
171
+ Options:
172
+ -r, --report <file> Write the full report; format from the extension:
173
+ .html, .md or .json. Repeatable.
174
+ --json Print the report as JSON to stdout instead of the summary
175
+ -v, --verbose Print every finding with its files
176
+ --fail-on <grade> Exit with code 1 if any area is graded <grade> or worse
177
+ (poor or fair), or with regression if a measure is
178
+ worse than the baseline (for CI)
179
+ --max-examples <n> Example files listed per finding (default 5)
180
+ --offline Do not look up the latest Angular version online
181
+ --config <file> Config file (default: ng-checkup.config.json in the root)
182
+ --no-color Plain output (also off when NO_COLOR is set or not a TTY)
183
+ -h, --help Show this help
184
+ --version Show the version
185
+
186
+ Init options (ng-checkup init):
187
+ --ci <provider> auto (default), github, gitlab or none
188
+ --dry-run Show what would change without writing anything
189
+ --force Replace an existing "checkup" script
190
+
191
+ Baseline options (ng-checkup baseline):
192
+ --force Accept measures that went up since the last baseline
63
193
  ```
64
194
 
65
- `--report` is repeatable. The HTML page loads nothing from the network: no fonts, no scripts, no images.
195
+ Exit codes: `0` done, `1` `--fail-on` tripped, `2` usage error (including `--fail-on regression` without a baseline). Areas graded `info` never fail a run.
196
+
197
+ </details>
66
198
 
67
199
  ## In CI
68
200
 
69
- ```bash
70
- npx ng-checkup --fail-on poor --report checkup.md
201
+ `ng add ng-checkup` and `npx ng-checkup init` write this for you. By hand:
202
+
203
+ **GitHub Actions**
204
+
205
+ ```yaml
206
+ - uses: actions/setup-node@v4
207
+ with:
208
+ node-version: 22
209
+ - run: npm ci
210
+ - run: npx ng-checkup --fail-on regression --report checkup.md --report checkup.html
211
+ - uses: actions/upload-artifact@v4
212
+ if: always()
213
+ with:
214
+ name: ng-checkup
215
+ path: checkup.*
71
216
  ```
72
217
 
73
- Exits with `1` when any area is graded `poor` (or `fair` with `--fail-on fair`), `2` on a usage error, `0` otherwise. Areas graded `info`, the ones the tool could not measure, never fail a run.
218
+ **GitLab CI**
219
+
220
+ ```yaml
221
+ ng-checkup:
222
+ image: node:22
223
+ script:
224
+ - npm ci
225
+ - npx ng-checkup --fail-on regression --report checkup.md --report checkup.html
226
+ artifacts:
227
+ when: always
228
+ paths: [checkup.md, checkup.html]
229
+ ```
230
+
231
+ On an existing codebase, start with a [baseline](#baseline-adopt-it-on-legacy-code) and `--fail-on regression`. `--fail-on poor` and `--fail-on fair` are for codebases that are already in good shape and want to stay there.
232
+
233
+ ## Programmatic API
234
+
235
+ ```ts
236
+ import { writeFile } from 'node:fs/promises';
237
+ import { runCheckup, renderMarkdown, overallScore } from 'ng-checkup';
238
+
239
+ const report = await runCheckup('path/to/app', { offline: true });
240
+
241
+ console.log(overallScore(report)); // e.g. 45
242
+ for (const check of report.checks) {
243
+ console.log(check.id, check.grade, check.summary);
244
+ }
245
+
246
+ // The same Markdown the CLI writes, e.g. to post as a pull-request comment.
247
+ await writeFile('checkup.md', renderMarkdown(report));
248
+ ```
249
+
250
+ `runCheckup` never writes anything. `renderHtml`, `renderMarkdown`, `overallScore`, `topPriorities`, `loadConfig`, `planInit` (what `init` would change, without writing it) and the baseline functions (`createBaseline`, `compareWithBaseline`, `readBaseline`, `serializeBaseline`) are exported too, along with the `Report`, `CheckResult`, `Finding` and `Grade` types. `Report` is also the schema of the JSON output.
74
251
 
75
252
  ## What leaves your machine
76
253
 
77
- One request: the latest `@angular/core` version from the npm registry, with a three-second timeout. `--offline` skips it and compares against the newest major this release knows about, and the report says so. No source, no file names, no telemetry. The tool reads files and never writes anything except the reports you ask for.
254
+ One request: the latest `@angular/core` version from the npm registry, with a three-second timeout. `--offline` skips it and compares against the newest major this release knows, and the report says so. No source, no file names, no telemetry. The tool reads files and writes only the reports you ask for.
78
255
 
79
256
  ## How it works
80
257
 
81
- - **Syntax only.** Every `.ts` file is parsed once with the TypeScript compiler API, without a type checker and without building the project. That is what makes it fast and lets it run on a repository whose dependencies are not installed. Identifiers are matched through their imports, so a local helper called `signal` is not counted as Angular's.
82
- - **Deprecations come from your `node_modules`.** The tool reads the `@deprecated` tags in the installed `@angular/*` and `@ngrx/*` type definitions, following Angular's re-exports between its bundled `.d.ts` chunks, so the report always matches the version you actually run, with Angular's own wording. A function counts as deprecated only when every overload is.
83
- - **Cycles are counted as groups.** A strongly connected component is one thing to untangle; counting individual cycles grows combinatorially and produces numbers nobody can act on. `import type` and `import()` are ignored, since neither can cause an initialization-order crash.
258
+ - **Syntax only.** Every `.ts` file is parsed once with the TypeScript compiler API, without a type checker and without building your project. That is why it takes seconds on a large monorepo and works on a repository that does not compile. Identifiers are matched through their imports, so a local helper called `signal` is not counted as Angular's.
259
+ - **Deprecations come from your `node_modules`.** It reads the `@deprecated` tags in the installed `@angular/*` and `@ngrx/*` type definitions, following Angular's re-exports between its bundled `.d.ts` chunks, in both the current package layout and the older one. The report always matches the version you actually run, in Angular's own words.
260
+ - **Cycles are counted as groups.** A strongly connected component is one thing to untangle; counting individual cycles grows combinatorially.
261
+
262
+ ## FAQ
84
263
 
85
- ## Limitations
264
+ **Does it change my code?** No. It only reads. The fixes it suggests are Angular's own `ng generate` migrations, which you run yourself.
86
265
 
87
- - It is static analysis. "Has a spec next to it" is a proxy for coverage, not coverage.
88
- - A monorepo with several apps is reported as one codebase.
89
- - No bundle-size analysis yet.
266
+ **Why is the deprecated-API check "info"?** Dependencies are not installed. Run `npm install` and run the checkup again.
267
+
268
+ **My app is on Angular 12 and deprecated APIs are "good". Is that right?** Yes, for Angular 12: nothing that *Angular 12* deprecates is in use. Each upgrade step deprecates more, and the version check is where that gap shows.
269
+
270
+ **Is "with a spec" my test coverage?** No. It counts components and services with an `x.spec.ts` next to `x.ts`. It needs no test run, which is what keeps the tool fast and usable on a repository it has never seen.
271
+
272
+ **Does it support Nx?** Yes: it reads `project.json` targets and tsconfig `paths`. A workspace with several apps is reported as one codebase for now.
273
+
274
+ **Which Angular versions?** Angular 2 and newer (not AngularJS). Checks whose rules changed between versions (standalone, OnPush, zoneless defaults) apply the rules of the version you run.
90
275
 
91
276
  ## Roadmap
92
277
 
93
- - Bundle size and eager-chunk analysis from the build's `stats.json`
94
- - Per-project breakdown for Nx and multi-project CLI workspaces
95
- - An effort estimate per finding, in days
96
- - Ratchet mode: store a baseline and fail CI only when a number goes up
278
+ - Upgrade plan: the steps from your version to the latest, with the migrations each needs
279
+ - Per-project reports for Nx and multi-project workspaces
280
+ - Bundle size from the build's esbuild metafile
281
+ - SARIF output for GitHub code scanning
97
282
 
98
- ## Development
283
+ Ideas and bug reports are welcome in [issues](https://github.com/stefankuburovic/ng-checkup/issues).
284
+
285
+ ## Contributing
99
286
 
100
287
  ```bash
288
+ git clone https://github.com/stefankuburovic/ng-checkup.git
289
+ cd ng-checkup
101
290
  npm install
102
- npm test # builds, then runs the Vitest suite against the fixture apps in test/fixtures
291
+ npm test # builds, then runs the Vitest suite against the fixture apps in test/fixtures
103
292
  npm run typecheck
293
+ node dist/cli.js path/to/some/angular/app
104
294
  ```
105
295
 
296
+ Each check is one file in `src/checks/` and a pure function of the analysis context, so a new check is a new file plus a fixture that shows it.
297
+
298
+ ## Need help acting on the report?
299
+
300
+ I'm [Stefan Kuburovic](https://stefankuburovic.github.io/), and modernizing large Angular codebases is my job. If you'd rather have someone walk through the report with your team, or do the upgrade with you, have a look at the [Angular Health Check](https://stefankuburovic.github.io/#health-check).
301
+
106
302
  ## License
107
303
 
108
304
  MIT
@@ -0,0 +1,72 @@
1
+ import type { Report } from './types.js';
2
+ /** The file `ng-checkup baseline` writes and every run compares against, in the analysed root. */
3
+ export declare const BASELINE_FILE = "ng-checkup.baseline.json";
4
+ /**
5
+ * Recorded measures of one point in time.
6
+ *
7
+ * Kept deliberately flat (`"type-safety.explicit-any": 28`) and with sorted
8
+ * keys, because it is committed and reviewed: a merge request that lowers a
9
+ * number shows as a one-line diff, and one that raises it stands out.
10
+ */
11
+ export interface Baseline {
12
+ version: 1;
13
+ /** `ng-checkup <version>` that wrote it. */
14
+ tool: string;
15
+ /** Date of the last update, `YYYY-MM-DD`. */
16
+ updated: string;
17
+ /** `checkId.measureId` to its value. Lower is better for every one. */
18
+ measures: Record<string, number>;
19
+ }
20
+ /** One measure that moved against the baseline. */
21
+ export interface MeasureDelta {
22
+ /** `checkId.measureId`. */
23
+ key: string;
24
+ check: string;
25
+ label: string;
26
+ before: number;
27
+ after: number;
28
+ }
29
+ /** How a report compares with a baseline. Attached to `Report.baseline`. */
30
+ export interface BaselineComparison {
31
+ /** The baseline file, as given. */
32
+ path: string;
33
+ /** Measures that went up: what `--fail-on regression` fails on. */
34
+ regressions: MeasureDelta[];
35
+ /** Measures that went down: run `ng-checkup baseline` to lock them in. */
36
+ improvements: MeasureDelta[];
37
+ /** Measures the baseline does not know yet, e.g. from a newer ng-checkup. Never a failure. */
38
+ added: string[];
39
+ }
40
+ /** Every measure of a report under its baseline key, with its check's title for display. */
41
+ export declare function measuresOf(report: Report): Map<string, {
42
+ check: string;
43
+ label: string;
44
+ value: number;
45
+ }>;
46
+ /** A baseline of the report's current measures. */
47
+ export declare function createBaseline(report: Report, today?: string): Baseline;
48
+ /** The baseline as committed: two-space JSON with a final newline. */
49
+ export declare function serializeBaseline(baseline: Baseline): string;
50
+ /**
51
+ * Reads a baseline file. Undefined when it does not exist.
52
+ *
53
+ * @throws On malformed content. A broken baseline must stop a CI run rather
54
+ * than compare against nothing and pass.
55
+ */
56
+ export declare function readBaseline(path: string): Baseline | undefined;
57
+ /**
58
+ * Compares a report with a baseline. A measure the report has no value for
59
+ * (its check graded `info` this time) is skipped rather than counted as an
60
+ * improvement: it was not measured, not fixed.
61
+ */
62
+ export declare function compareWithBaseline(report: Report, baseline: Baseline, path: string): BaselineComparison;
63
+ /**
64
+ * The measures that would go up if `next` replaced `previous`. Updating a
65
+ * baseline may only lower numbers; raising one needs `--force`, which is the
66
+ * moment someone has to say why in review. Empty for a first baseline.
67
+ */
68
+ export declare function baselineIncreases(previous: Baseline | undefined, next: Baseline): Array<{
69
+ key: string;
70
+ before: number;
71
+ after: number;
72
+ }>;
@@ -0,0 +1,82 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ /** The file `ng-checkup baseline` writes and every run compares against, in the analysed root. */
3
+ export const BASELINE_FILE = 'ng-checkup.baseline.json';
4
+ /** Every measure of a report under its baseline key, with its check's title for display. */
5
+ export function measuresOf(report) {
6
+ const result = new Map();
7
+ for (const check of report.checks) {
8
+ for (const measure of check.measures ?? [])
9
+ result.set(`${check.id}.${measure.id}`, { check: check.title, label: measure.label, value: measure.value });
10
+ }
11
+ return result;
12
+ }
13
+ /** A baseline of the report's current measures. */
14
+ export function createBaseline(report, today = report.generatedAt.slice(0, 10)) {
15
+ const measures = {};
16
+ for (const [key, measure] of [...measuresOf(report)].sort(([left], [right]) => left.localeCompare(right)))
17
+ measures[key] = measure.value;
18
+ return { version: 1, tool: `${report.tool.name} ${report.tool.version}`, updated: today, measures };
19
+ }
20
+ /** The baseline as committed: two-space JSON with a final newline. */
21
+ export function serializeBaseline(baseline) {
22
+ return `${JSON.stringify(baseline, null, 2)}\n`;
23
+ }
24
+ /**
25
+ * Reads a baseline file. Undefined when it does not exist.
26
+ *
27
+ * @throws On malformed content. A broken baseline must stop a CI run rather
28
+ * than compare against nothing and pass.
29
+ */
30
+ export function readBaseline(path) {
31
+ if (!existsSync(path))
32
+ return undefined;
33
+ let raw;
34
+ try {
35
+ raw = JSON.parse(readFileSync(path, 'utf8'));
36
+ }
37
+ catch (error) {
38
+ throw new Error(`${path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
39
+ }
40
+ const record = (typeof raw === 'object' && raw !== null ? raw : {});
41
+ const measures = record['measures'];
42
+ if (record['version'] !== 1 || typeof measures !== 'object' || measures === null || Array.isArray(measures) || !Object.values(measures).every((value) => typeof value === 'number')) {
43
+ throw new Error(`${path} is not an ng-checkup baseline (expected version 1 and numeric measures). Recreate it with ng-checkup baseline --force.`);
44
+ }
45
+ return { version: 1, tool: String(record['tool'] ?? ''), updated: String(record['updated'] ?? ''), measures: measures };
46
+ }
47
+ /**
48
+ * Compares a report with a baseline. A measure the report has no value for
49
+ * (its check graded `info` this time) is skipped rather than counted as an
50
+ * improvement: it was not measured, not fixed.
51
+ */
52
+ export function compareWithBaseline(report, baseline, path) {
53
+ const regressions = [];
54
+ const improvements = [];
55
+ const added = [];
56
+ for (const [key, current] of measuresOf(report)) {
57
+ const before = baseline.measures[key];
58
+ if (before === undefined) {
59
+ added.push(key);
60
+ continue;
61
+ }
62
+ const delta = { key, check: current.check, label: current.label, before, after: current.value };
63
+ if (current.value > before)
64
+ regressions.push(delta);
65
+ else if (current.value < before)
66
+ improvements.push(delta);
67
+ }
68
+ return { path, regressions, improvements, added };
69
+ }
70
+ /**
71
+ * The measures that would go up if `next` replaced `previous`. Updating a
72
+ * baseline may only lower numbers; raising one needs `--force`, which is the
73
+ * moment someone has to say why in review. Empty for a first baseline.
74
+ */
75
+ export function baselineIncreases(previous, next) {
76
+ if (!previous)
77
+ return [];
78
+ return Object.entries(next.measures)
79
+ .filter(([key, value]) => previous.measures[key] !== undefined && value > previous.measures[key])
80
+ .map(([key, after]) => ({ key, before: previous.measures[key], after }));
81
+ }
82
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.js","sourceRoot":"","sources":["../src/baseline.ts"],"names":[],"mappings":"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"}
@@ -84,6 +84,11 @@ export function changeDetectionCheck(context) {
84
84
  { label: 'Zone test helpers', value: formatCount(zoneHelpers) },
85
85
  ],
86
86
  findings,
87
+ measures: [
88
+ { id: 'eager-components', label: 'Components with eager change detection', value: eager.length },
89
+ { id: 'ngzone-files', label: 'Files injecting NgZone', value: ngZoneFiles.length },
90
+ { id: 'zone-test-helpers', label: 'Zone-based test helper calls', value: zoneHelpers },
91
+ ],
87
92
  };
88
93
  }
89
94
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"change-detection.js","sourceRoot":"","sources":["../../src/checks/change-detection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"change-detection.js","sourceRoot":"","sources":["../../src/checks/change-detection.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,9 @@ export function circularDepsCheck(context) {
38
38
  { label: 'Largest tangle', value: formatCount(largest), hint: 'files' },
39
39
  ],
40
40
  findings,
41
+ measures: [
42
+ { id: 'files-in-cycles', label: 'Files in import cycles', value: filesInTangles },
43
+ ],
41
44
  };
42
45
  }
43
46
  //# sourceMappingURL=circular-deps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"circular-deps.js","sourceRoot":"","sources":["../../src/checks/circular-deps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"circular-deps.js","sourceRoot":"","sources":["../../src/checks/circular-deps.ts"],"names":[],"mappings":"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"}
@@ -85,6 +85,11 @@ export function componentsCheck(context) {
85
85
  summary: `${plural(components.length, 'component')}: ${standaloneShare}% standalone, ${inputs > 0 ? `${signalInputShare}% signal inputs` : 'no inputs'}, ${controlFlow > 0 ? `${controlFlowShare}% built-in control flow` : 'no control flow'}.`,
86
86
  metrics,
87
87
  findings,
88
+ measures: [
89
+ { id: 'module-components', label: 'Components declared in NgModules', value: moduleBased.length },
90
+ { id: 'decorator-inputs-outputs', label: '@Input() / @Output() decorators', value: decoratorInputs + decoratorOutputs },
91
+ { id: 'legacy-control-flow', label: '*ngIf / *ngFor / [ngSwitch] uses', value: totals.legacy },
92
+ ],
88
93
  };
89
94
  }
90
95
  /**