ng-checkup 0.1.0 → 0.2.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.
- package/README.md +226 -60
- package/dist/checks/type-safety.js +18 -6
- package/dist/checks/type-safety.js.map +1 -1
- package/dist/cli.d.ts +45 -8
- package/dist/cli.js +158 -39
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +47 -0
- package/dist/config.js +93 -0
- package/dist/config.js.map +1 -0
- package/dist/files.d.ts +5 -1
- package/dist/files.js +10 -4
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +78 -0
- package/dist/init.js +220 -0
- package/dist/init.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/workspace.d.ts +6 -0
- package/dist/workspace.js +1 -0
- package/dist/workspace.js.map +1 -1
- package/package.json +10 -3
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.cjs +60 -0
- package/schematics/ng-add/schema.json +29 -0
package/README.md
CHANGED
|
@@ -1,108 +1,274 @@
|
|
|
1
1
|
# ng-checkup
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/ng-checkup) [](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml)
|
|
3
|
+
[](https://www.npmjs.com/package/ng-checkup) [](https://github.com/stefankuburovic/ng-checkup/actions/workflows/ci.yml) [](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
|
|
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
|
-
|
|
13
|
+

|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
[
|
|
23
|
-
[
|
|
24
|
-
[
|
|
25
|
-
[
|
|
26
|
-
[
|
|
27
|
-
[
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
- [What it checks](#what-it-checks)
|
|
25
|
+
- [Reports](#reports)
|
|
26
|
+
- [In CI](#in-ci)
|
|
27
|
+
- [Programmatic API](#programmatic-api)
|
|
28
|
+
- [What leaves your machine](#what-leaves-your-machine)
|
|
29
|
+
- [How it works](#how-it-works)
|
|
30
|
+
- [FAQ](#faq)
|
|
31
|
+
- [Roadmap](#roadmap)
|
|
32
|
+
- [Contributing](#contributing)
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
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.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. The summary in your terminal
|
|
40
|
+
npx ng-checkup
|
|
41
|
+
|
|
42
|
+
# 2. The full report as a page to share
|
|
43
|
+
npx ng-checkup --report checkup.html
|
|
44
|
+
|
|
45
|
+
# 3. Fail CI when an area turns poor
|
|
46
|
+
npx ng-checkup --fail-on poor
|
|
37
47
|
```
|
|
38
48
|
|
|
39
|
-
|
|
49
|
+
Install dependencies first (`npm install`) if you can: the deprecated-API check reads the installed Angular packages, and without them it is skipped.
|
|
50
|
+
|
|
51
|
+
## Set it up in a project
|
|
52
|
+
|
|
53
|
+
To keep the checkup in the project, with a script, a config file and a CI step:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ng add ng-checkup # Angular CLI: installs it and asks which CI to use
|
|
57
|
+
# or
|
|
58
|
+
npx ng-checkup init # any workspace, including Nx
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Both make the same changes and list what they changed:
|
|
62
|
+
|
|
63
|
+
| File | Change |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `package.json` | a `"checkup": "ng-checkup"` script, and `ng-checkup` in `devDependencies` (`init` only; `ng add` installs it itself) |
|
|
66
|
+
| `ng-checkup.config.json` | writes `checkup.html` on every run, and an empty `ignore` list |
|
|
67
|
+
| `.gitignore` | the generated reports, if the repository has a `.gitignore` |
|
|
68
|
+
| `.github/workflows/ng-checkup.yml` | runs on every pull request, fails on a poor area, uploads the reports (when `.github/` exists) |
|
|
69
|
+
| `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) |
|
|
70
|
+
|
|
71
|
+
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`.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx ng-checkup init --dry-run # show the changes, write nothing
|
|
75
|
+
npx ng-checkup init --ci gitlab # pick the CI instead of detecting it (github, gitlab, none)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
`ng-checkup.config.json` in the project root. Every key is optional, and every command-line flag overrides its key.
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"reports": ["checkup.html"],
|
|
85
|
+
"failOn": "poor",
|
|
86
|
+
"maxExamples": 5,
|
|
87
|
+
"offline": false,
|
|
88
|
+
"ignore": ["src/legacy", "**/generated", "apps/*/e2e"]
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| Key | Meaning | Flag |
|
|
93
|
+
| --- | --- | --- |
|
|
94
|
+
| `reports` | report files to write, relative to the config file | `--report` |
|
|
95
|
+
| `failOn` | exit with 1 when an area is `poor` (or `fair`) | `--fail-on` |
|
|
96
|
+
| `maxExamples` | example files listed per finding | `--max-examples` |
|
|
97
|
+
| `offline` | skip the npm lookup of the latest Angular version | `--offline` |
|
|
98
|
+
| `ignore` | paths left out of the analysis; a path matches everything below it, `*` stays within a folder, `**` crosses folders | |
|
|
99
|
+
|
|
100
|
+
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.
|
|
40
101
|
|
|
41
102
|
## What it checks
|
|
42
103
|
|
|
43
|
-
| Area |
|
|
104
|
+
| Area | It looks at | Poor when |
|
|
44
105
|
| --- | --- | --- |
|
|
45
|
-
| **Angular version & tooling** |
|
|
46
|
-
| **Deprecated APIs** |
|
|
47
|
-
| **Change detection** |
|
|
48
|
-
| **Components & templates** |
|
|
49
|
-
| **State management** |
|
|
50
|
-
| **Testing** | Karma / Jest / Vitest,
|
|
51
|
-
| **Type safety** | `strictNullChecks`, `strictTemplates`, `noImplicitAny`,
|
|
52
|
-
| **Circular dependencies** |
|
|
106
|
+
| [**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 |
|
|
107
|
+
| [**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 |
|
|
108
|
+
| [**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 |
|
|
109
|
+
| [**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% |
|
|
110
|
+
| [**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 |
|
|
111
|
+
| [**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 |
|
|
112
|
+
| [**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 |
|
|
113
|
+
| [**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 |
|
|
114
|
+
|
|
115
|
+
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
116
|
|
|
54
|
-
Defaults that changed between versions are applied per version: a component without `standalone` is standalone from Angular 19
|
|
117
|
+
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
118
|
|
|
56
119
|
## Reports
|
|
57
120
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
npx ng-checkup
|
|
121
|
+

|
|
122
|
+
|
|
123
|
+
| Command | Output |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| `npx ng-checkup` | summary and top five priorities in the terminal |
|
|
126
|
+
| `npx ng-checkup --verbose` | every finding with its files in the terminal |
|
|
127
|
+
| `npx ng-checkup --report checkup.html` | self-contained page: light and dark mode, prints cleanly to PDF, loads nothing from the network |
|
|
128
|
+
| `npx ng-checkup --report checkup.md` | Markdown for a pull request, an issue or a wiki |
|
|
129
|
+
| `npx ng-checkup --report checkup.json` | everything, machine-readable |
|
|
130
|
+
| `npx ng-checkup --json` | the JSON on stdout, for piping |
|
|
131
|
+
|
|
132
|
+
`--report` is repeatable, so one run can write all three files.
|
|
133
|
+
|
|
134
|
+
<details>
|
|
135
|
+
<summary>All options</summary>
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
Usage: ng-checkup [path] [options]
|
|
139
|
+
ng-checkup init [path] [init options]
|
|
140
|
+
|
|
141
|
+
Arguments:
|
|
142
|
+
path Repository root (default: current directory)
|
|
143
|
+
|
|
144
|
+
Options:
|
|
145
|
+
-r, --report <file> Write the full report; format from the extension:
|
|
146
|
+
.html, .md or .json. Repeatable.
|
|
147
|
+
--json Print the report as JSON to stdout instead of the summary
|
|
148
|
+
-v, --verbose Print every finding with its files
|
|
149
|
+
--fail-on <grade> Exit with code 1 if any area is graded <grade> or worse:
|
|
150
|
+
poor or fair (for CI)
|
|
151
|
+
--max-examples <n> Example files listed per finding (default 5)
|
|
152
|
+
--offline Do not look up the latest Angular version online
|
|
153
|
+
--config <file> Config file (default: ng-checkup.config.json in the root)
|
|
154
|
+
--no-color Plain output (also off when NO_COLOR is set or not a TTY)
|
|
155
|
+
-h, --help Show this help
|
|
156
|
+
--version Show the version
|
|
157
|
+
|
|
158
|
+
Init options (ng-checkup init):
|
|
159
|
+
--ci <provider> auto (default), github, gitlab or none
|
|
160
|
+
--dry-run Show what would change without writing anything
|
|
161
|
+
--force Replace an existing "checkup" script
|
|
63
162
|
```
|
|
64
163
|
|
|
65
|
-
|
|
164
|
+
Exit codes: `0` done, `1` `--fail-on` tripped, `2` usage error. Areas graded `info` never fail a run.
|
|
165
|
+
|
|
166
|
+
</details>
|
|
66
167
|
|
|
67
168
|
## In CI
|
|
68
169
|
|
|
69
|
-
|
|
70
|
-
|
|
170
|
+
`ng add ng-checkup` and `npx ng-checkup init` write this for you. By hand:
|
|
171
|
+
|
|
172
|
+
**GitHub Actions**
|
|
173
|
+
|
|
174
|
+
```yaml
|
|
175
|
+
- uses: actions/setup-node@v4
|
|
176
|
+
with:
|
|
177
|
+
node-version: 22
|
|
178
|
+
- run: npm ci
|
|
179
|
+
- run: npx ng-checkup --fail-on poor --report checkup.md --report checkup.html
|
|
180
|
+
- uses: actions/upload-artifact@v4
|
|
181
|
+
if: always()
|
|
182
|
+
with:
|
|
183
|
+
name: ng-checkup
|
|
184
|
+
path: checkup.*
|
|
71
185
|
```
|
|
72
186
|
|
|
73
|
-
|
|
187
|
+
**GitLab CI**
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
ng-checkup:
|
|
191
|
+
image: node:22
|
|
192
|
+
script:
|
|
193
|
+
- npm ci
|
|
194
|
+
- npx ng-checkup --fail-on poor --report checkup.md --report checkup.html
|
|
195
|
+
artifacts:
|
|
196
|
+
when: always
|
|
197
|
+
paths: [checkup.md, checkup.html]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Start with `--fail-on poor`. `--fail-on fair` is for codebases that are already in good shape and want to stay there.
|
|
201
|
+
|
|
202
|
+
## Programmatic API
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
import { writeFile } from 'node:fs/promises';
|
|
206
|
+
import { runCheckup, renderMarkdown, overallScore } from 'ng-checkup';
|
|
207
|
+
|
|
208
|
+
const report = await runCheckup('path/to/app', { offline: true });
|
|
209
|
+
|
|
210
|
+
console.log(overallScore(report)); // e.g. 45
|
|
211
|
+
for (const check of report.checks) {
|
|
212
|
+
console.log(check.id, check.grade, check.summary);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// The same Markdown the CLI writes, e.g. to post as a pull-request comment.
|
|
216
|
+
await writeFile('checkup.md', renderMarkdown(report));
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`runCheckup` never writes anything. `renderHtml`, `renderMarkdown`, `overallScore`, `topPriorities`, `loadConfig` and `planInit` (what `init` would change, without writing it) are exported too, along with the `Report`, `CheckResult`, `Finding` and `Grade` types. `Report` is also the schema of the JSON output.
|
|
74
220
|
|
|
75
221
|
## What leaves your machine
|
|
76
222
|
|
|
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
|
|
223
|
+
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
224
|
|
|
79
225
|
## How it works
|
|
80
226
|
|
|
81
|
-
- **Syntax only.** Every `.ts` file is parsed once with the TypeScript compiler API, without a type checker and without building
|
|
82
|
-
- **Deprecations come from your `node_modules`.**
|
|
83
|
-
- **Cycles are counted as groups.** A strongly connected component is one thing to untangle; counting individual cycles grows combinatorially
|
|
227
|
+
- **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.
|
|
228
|
+
- **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.
|
|
229
|
+
- **Cycles are counted as groups.** A strongly connected component is one thing to untangle; counting individual cycles grows combinatorially.
|
|
230
|
+
|
|
231
|
+
## FAQ
|
|
232
|
+
|
|
233
|
+
**Does it change my code?** No. It only reads. The fixes it suggests are Angular's own `ng generate` migrations, which you run yourself.
|
|
84
234
|
|
|
85
|
-
|
|
235
|
+
**Why is the deprecated-API check "info"?** Dependencies are not installed. Run `npm install` and run the checkup again.
|
|
86
236
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
237
|
+
**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.
|
|
238
|
+
|
|
239
|
+
**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.
|
|
240
|
+
|
|
241
|
+
**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.
|
|
242
|
+
|
|
243
|
+
**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
244
|
|
|
91
245
|
## Roadmap
|
|
92
246
|
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
247
|
+
- Baseline mode: fail CI only when a number gets worse, so legacy code can adopt it on day one
|
|
248
|
+
- Upgrade plan: the steps from your version to the latest, with the migrations each needs
|
|
249
|
+
- Per-project reports for Nx and multi-project workspaces
|
|
250
|
+
- Bundle size from the build's esbuild metafile
|
|
251
|
+
- SARIF output for GitHub code scanning
|
|
252
|
+
|
|
253
|
+
Ideas and bug reports are welcome in [issues](https://github.com/stefankuburovic/ng-checkup/issues).
|
|
97
254
|
|
|
98
|
-
##
|
|
255
|
+
## Contributing
|
|
99
256
|
|
|
100
257
|
```bash
|
|
258
|
+
git clone https://github.com/stefankuburovic/ng-checkup.git
|
|
259
|
+
cd ng-checkup
|
|
101
260
|
npm install
|
|
102
|
-
npm test
|
|
261
|
+
npm test # builds, then runs the Vitest suite against the fixture apps in test/fixtures
|
|
103
262
|
npm run typecheck
|
|
263
|
+
node dist/cli.js path/to/some/angular/app
|
|
104
264
|
```
|
|
105
265
|
|
|
266
|
+
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.
|
|
267
|
+
|
|
268
|
+
## Need help acting on the report?
|
|
269
|
+
|
|
270
|
+
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).
|
|
271
|
+
|
|
106
272
|
## License
|
|
107
273
|
|
|
108
274
|
MIT
|
|
@@ -20,9 +20,21 @@ export function typeSafetyCheck(context) {
|
|
|
20
20
|
const options = context.appCompilerOptions;
|
|
21
21
|
const angular = context.angularCompilerOptions;
|
|
22
22
|
const hasConfig = context.workspace.appTsconfig !== undefined;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
// What an absent flag means changed: `strict` is on by default from
|
|
24
|
+
// TypeScript 6, and `strictTemplates` from Angular 22 (17 to 21 default to
|
|
25
|
+
// false). A brand-new Angular 22 project sets neither and is fully strict,
|
|
26
|
+
// so reading only what the tsconfig says would grade it poor.
|
|
27
|
+
const typescriptMajor = context.workspace.typescriptMajor;
|
|
28
|
+
const angularMajor = context.workspace.angular.major;
|
|
29
|
+
const strictByDefault = typescriptMajor !== undefined && typescriptMajor >= 6;
|
|
30
|
+
const strictTemplatesByDefault = angularMajor !== undefined && angularMajor >= 22;
|
|
31
|
+
const strictNullChecks = options.strictNullChecks ?? options.strict ?? strictByDefault;
|
|
32
|
+
const noImplicitAny = options.noImplicitAny ?? options.strict ?? strictByDefault;
|
|
33
|
+
const explicitStrictTemplates = angular['strictTemplates'];
|
|
34
|
+
const strictTemplates = typeof explicitStrictTemplates === 'boolean' ? explicitStrictTemplates : strictTemplatesByDefault;
|
|
35
|
+
/** "default in TypeScript 6" when the value was not written down, so the reader knows where it came from. */
|
|
36
|
+
const source = (written, origin) => (written ? undefined : `default in ${origin}`);
|
|
37
|
+
const strictWritten = options.strict !== undefined;
|
|
26
38
|
const application = applicationFiles(context);
|
|
27
39
|
const linesOfCode = application.reduce((sum, file) => sum + file.linesOfCode, 0);
|
|
28
40
|
const anyCount = application.reduce((sum, file) => sum + file.anyLines.length, 0);
|
|
@@ -93,9 +105,9 @@ export function typeSafetyCheck(context) {
|
|
|
93
105
|
? `strictNullChecks ${on(strictNullChecks)}, strictTemplates ${on(strictTemplates)}, ${formatCount(anyCount)} explicit any.`
|
|
94
106
|
: 'No application tsconfig found.',
|
|
95
107
|
metrics: [
|
|
96
|
-
{ label: 'strictNullChecks', value: on(strictNullChecks) },
|
|
97
|
-
{ label: 'strictTemplates', value: on(strictTemplates) },
|
|
98
|
-
{ label: 'noImplicitAny', value: on(noImplicitAny) },
|
|
108
|
+
{ label: 'strictNullChecks', value: on(strictNullChecks), hint: source(options.strictNullChecks !== undefined || strictWritten, `TypeScript ${typescriptMajor ?? '?'}`) },
|
|
109
|
+
{ label: 'strictTemplates', value: on(strictTemplates), hint: source(typeof explicitStrictTemplates === 'boolean', `Angular ${angularMajor ?? '?'}`) },
|
|
110
|
+
{ label: 'noImplicitAny', value: on(noImplicitAny), hint: source(options.noImplicitAny !== undefined || strictWritten, `TypeScript ${typescriptMajor ?? '?'}`) },
|
|
99
111
|
{ label: 'Explicit any', value: formatCount(anyCount), hint: `${anyDensity.toFixed(1)} per 1 000 lines` },
|
|
100
112
|
{ label: 'Non-null assertions', value: formatCount(nonNull) },
|
|
101
113
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-safety.js","sourceRoot":"","sources":["../../src/checks/type-safety.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAwB,MAAM,cAAc,CAAC;AAE3F;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,WAAW,KAAK,SAAS,CAAC;IAE9D,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"type-safety.js","sourceRoot":"","sources":["../../src/checks/type-safety.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,23 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type CheckupConfig } from './config.js';
|
|
3
|
+
import { type CiChoice, type InitPlan } from './init.js';
|
|
2
4
|
import type { Report } from './types.js';
|
|
3
|
-
/** Parsed and validated
|
|
4
|
-
interface CliArguments {
|
|
5
|
+
/** Parsed and validated arguments of a checkup run, before the config file is applied. */
|
|
6
|
+
export interface CliArguments {
|
|
5
7
|
root: string;
|
|
8
|
+
/** Reports named on the command line, resolved against the working directory. Empty when none. */
|
|
6
9
|
reports: string[];
|
|
7
10
|
json: boolean;
|
|
8
11
|
verbose: boolean;
|
|
9
12
|
failOn?: 'fair' | 'poor';
|
|
10
|
-
|
|
13
|
+
/** Undefined when the flag was not given, so the config file can supply it. */
|
|
14
|
+
maxExamples?: number;
|
|
11
15
|
offline: boolean;
|
|
12
16
|
color: boolean;
|
|
17
|
+
config?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Parsed arguments of `ng-checkup init`. */
|
|
20
|
+
export interface InitArguments {
|
|
21
|
+
root: string;
|
|
22
|
+
ci: CiChoice;
|
|
23
|
+
dryRun: boolean;
|
|
24
|
+
force: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** What a run actually uses: the command line laid over the config file. */
|
|
27
|
+
export interface RunSettings {
|
|
28
|
+
reports: string[];
|
|
29
|
+
failOn?: 'fair' | 'poor';
|
|
30
|
+
maxExamples: number;
|
|
31
|
+
offline: boolean;
|
|
32
|
+
ignore?: string[];
|
|
13
33
|
}
|
|
14
34
|
/**
|
|
15
|
-
* Parses `argv` (without the node and script entries)
|
|
16
|
-
* whose message is meant for the user on anything invalid,
|
|
17
|
-
* prints with the hint to `--help`. Returns `'help'` or
|
|
18
|
-
* two flags so `main` can print and exit before doing
|
|
35
|
+
* Parses `argv` (without the node and script entries) of a checkup run.
|
|
36
|
+
* Throws an `Error` whose message is meant for the user on anything invalid,
|
|
37
|
+
* which `main` prints with the hint to `--help`. Returns `'help'` or
|
|
38
|
+
* `'version'` for those two flags so `main` can print and exit before doing
|
|
39
|
+
* any work.
|
|
19
40
|
*/
|
|
20
41
|
export declare function parseCliArguments(argv: string[], environment?: NodeJS.ProcessEnv, isTty?: boolean): CliArguments | 'help' | 'version';
|
|
42
|
+
/** Parses the arguments after `init`. Same error contract as `parseCliArguments`. */
|
|
43
|
+
export declare function parseInitArguments(argv: string[]): InitArguments | 'help';
|
|
44
|
+
/**
|
|
45
|
+
* Lays the command line over the config file: every flag that was given
|
|
46
|
+
* wins, the config fills the rest, and the built-in defaults come last.
|
|
47
|
+
* Config reports resolve against the config file's directory, command-line
|
|
48
|
+
* ones were already resolved against the working directory, which is what a
|
|
49
|
+
* user typing a path expects.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveSettings(args: CliArguments, config: CheckupConfig, configDirectory: string): RunSettings;
|
|
21
52
|
/** Renders a report in the format its file extension names. */
|
|
22
53
|
export declare function renderForFile(report: Report, path: string): string;
|
|
23
54
|
/**
|
|
@@ -25,4 +56,10 @@ export declare function renderForFile(report: Report, path: string): string;
|
|
|
25
56
|
* run: it means the area could not be measured, not that it is bad.
|
|
26
57
|
*/
|
|
27
58
|
export declare function shouldFail(report: Report, failOn: 'fair' | 'poor' | undefined): boolean;
|
|
28
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Runs `ng-checkup init`: plans against the real file system, then writes
|
|
61
|
+
* the changes unless `dryRun`. Returns the plan so the caller can print it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function runInit(args: InitArguments): InitPlan;
|
|
64
|
+
/** The text `ng-checkup init` prints: what changed, what was left alone, what to run next. */
|
|
65
|
+
export declare function describeInitPlan(plan: InitPlan, dryRun: boolean): string;
|