angular-compat-matrix 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +406 -2
- package/dist/app.js +91 -0
- package/dist/build.js +167 -0
- package/dist/cleanup.js +117 -0
- package/dist/cli.js +262 -0
- package/dist/exec.js +166 -0
- package/dist/install.js +140 -0
- package/dist/library.js +200 -0
- package/dist/model.js +13 -0
- package/dist/partial.js +90 -0
- package/dist/peers.js +79 -0
- package/dist/progress.js +65 -0
- package/dist/registry.js +135 -0
- package/dist/report.js +280 -0
- package/dist/run.js +280 -0
- package/dist/scripts.js +73 -0
- package/dist/smoke.js +526 -0
- package/dist/tests.js +105 -0
- package/dist/tools.js +152 -0
- package/dist/versions.js +138 -0
- package/package.json +49 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nizamudeen S
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,407 @@
|
|
|
1
|
-
#
|
|
1
|
+
# angular-compat-matrix
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Which Angular versions does your published library really work with?
|
|
4
|
+
|
|
5
|
+
Run it with `npx angular-compat-matrix`, or install the package and run `ng-matrix`: both names start the same command.
|
|
6
|
+
|
|
7
|
+
ng-matrix builds and packs your Angular library, installs the tarball into a fresh app for each Angular major (created with that major's own CLI), builds it, and reports a compatibility matrix. It tests the exact package your users get, not your local source.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
$ npx angular-compat-matrix
|
|
11
|
+
|
|
12
|
+
my-dropdown@3.0.0 (compiled with Angular 21.2.0; highest minVersion 20.0.0)
|
|
13
|
+
|
|
14
|
+
peer range install partial AOT build strict types
|
|
15
|
+
Angular 19 ✓ ✓ ✗ — —
|
|
16
|
+
Angular 20 ✓ ✓ ✓ ✓ ✗
|
|
17
|
+
Angular 21 ✓ ✓ ✓ ✓ ✓
|
|
18
|
+
Angular 22 ✗ ✓ ✓ ✓ ✓
|
|
19
|
+
|
|
20
|
+
✗ 19: partial: Needs Angular 20.0.0 or later: highest minVersion 20.0.0, in
|
|
21
|
+
MyDropdownComponent. Build the library with the oldest Angular you support, or take
|
|
22
|
+
this version out of the peer range.
|
|
23
|
+
✗ 20: strict types: Fails with strictTemplates: true and skipLibCheck: false.
|
|
24
|
+
! 22: works, but peerDependencies doesn't allow it (@angular/core "^19.0.0 || ^20.0.0 ||
|
|
25
|
+
^21.0.0"). Widen the range to include it.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
Run it in your library's workspace: an Angular CLI workspace with a library project, or any folder with `ng-package.json`.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
# Check supported majors plus every major your peer range claims
|
|
36
|
+
npx angular-compat-matrix
|
|
37
|
+
|
|
38
|
+
# Check a specific range or list of majors
|
|
39
|
+
npx angular-compat-matrix --versions 18-22
|
|
40
|
+
npx angular-compat-matrix --versions 20,22
|
|
41
|
+
|
|
42
|
+
# Check one library in a workspace with several
|
|
43
|
+
npx angular-compat-matrix --project my-lib
|
|
44
|
+
|
|
45
|
+
# Check a published package from npm (no local build needed)
|
|
46
|
+
npx angular-compat-matrix --package primeng@19.0.0
|
|
47
|
+
|
|
48
|
+
# Generate Markdown for your README or GitHub Actions summary
|
|
49
|
+
npx angular-compat-matrix --format markdown
|
|
50
|
+
|
|
51
|
+
# Machine-readable JSON output for CI pipelines
|
|
52
|
+
npx angular-compat-matrix --json
|
|
53
|
+
|
|
54
|
+
# Verbose output (shows exact commands executed and full failure logs)
|
|
55
|
+
npx angular-compat-matrix --verbose
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## How to Read the Matrix
|
|
61
|
+
|
|
62
|
+
The matrix tests each Angular major in order. A failure on any step marks subsequent checks `—`, ensuring the first true incompatibility is reported clearly.
|
|
63
|
+
|
|
64
|
+
### Symbols
|
|
65
|
+
|
|
66
|
+
| Terminal | Markdown | Meaning |
|
|
67
|
+
| :---: | :---: | :--- |
|
|
68
|
+
| `✓` | `✅` | **Passed:** The check succeeded. |
|
|
69
|
+
| `✗` | `❌` | **Failed:** The check failed. |
|
|
70
|
+
| `✓?` | `✅*` | **Advisory pass:** Passed on `minVersion` alone, but because the library was compiled with a newer Angular major, `minVersion` has been historically unreliable. The build check decides compatibility. |
|
|
71
|
+
| `—` | `—` | **Not run:** Skipped because an earlier check failed. |
|
|
72
|
+
| `·` | `n/a` | **None:** Nothing to check (e.g. no `@angular/*` peer declared). |
|
|
73
|
+
| `!` | `⚠️` | **Setup error:** ng-matrix itself could not set up the app on this machine (e.g. disk full, network timeout). This is not a library failure. |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## What It Checks
|
|
78
|
+
|
|
79
|
+
| Check | What it asks | How it verifies |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| **Peer range** | Does your package claim this version? | Compares every declared `@angular/*` peer (e.g. `@angular/core`, `@angular/cdk`, `@angular/material`). Never stops other checks. |
|
|
82
|
+
| **Install** | Does it install cleanly without peer conflicts? | Installs the packed tarball into a fresh Angular app using your package manager (`npm` with `--legacy-peer-deps` + `npm ls`, or `pnpm` with `strictPeerDependencies: false`). For versions outside your peer range, expected peer conflicts are safely ignored. |
|
|
83
|
+
| **Partial** | Can this version's Angular linker load the compiled code? | Scans every `ɵɵngDeclare…` call in the published code for `minVersion`. A failure is absolute proof of incompatibility. |
|
|
84
|
+
| **AOT build** | Does a production app build with your library? | Runs `ng build --configuration production` (`strictTemplates: false`, `skipLibCheck: true`) on a smoke app using every public component, directive, pipe, service, and entry point. |
|
|
85
|
+
| **Strict types** | Do consumer templates type-check under strict settings? | Re-runs the build with `strictTemplates: true` and `skipLibCheck: false`. Catches template type errors and invalid typings. (Errors strictly inside third-party `node_modules/**/*.d.ts` are reported as warnings and do not fail the check). |
|
|
86
|
+
| **Tests** | Do your own unit tests pass on this version? | (Opt-in with `--tests`): Copies your workspace, swaps Angular dependencies to the target major, and executes your test command (`npm test` or `--test-command`). |
|
|
87
|
+
|
|
88
|
+
### The Generated Smoke App
|
|
89
|
+
|
|
90
|
+
When not using `--consumer`, ng-matrix inspects your package typings and generates a standalone smoke app:
|
|
91
|
+
- Imports all entry points exposed in your `package.json` `exports` map.
|
|
92
|
+
- Instantiates each component, directive, and pipe in its own isolated component.
|
|
93
|
+
- Supplies correctly-typed mock values for required `@Input()` fields.
|
|
94
|
+
- Uses attribute selectors bare (`<div myFlag>`) when they accept booleans or strings, matching real user patterns.
|
|
95
|
+
- Handles undeclared dependencies in secondary entry points: if a secondary entry point (e.g. `my-lib/chart`) fails because an undeclared extra (like `chart.js`) is missing, ng-matrix omits that entry point and warns you rather than failing the whole library. If the package's *main* entry point (`.`) imports an undeclared package, AOT fails immediately with a clear explanation.
|
|
96
|
+
|
|
97
|
+
If your library requires specialized providers, wrappers, or mock services, supply your own example app with `--consumer ./path-to-app`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Install-Script Safety Default & `--allow-scripts`
|
|
102
|
+
|
|
103
|
+
By default, ng-matrix **blocks arbitrary install scripts** (`preinstall`, `install`, `postinstall`) during `npm` and `pnpm` installations.
|
|
104
|
+
|
|
105
|
+
Only native build tools essential to the Angular toolchain are permitted to run:
|
|
106
|
+
- `esbuild`
|
|
107
|
+
- `@parcel/watcher`
|
|
108
|
+
- `lmdb`
|
|
109
|
+
- `@swc/core`
|
|
110
|
+
|
|
111
|
+
If your library or one of its dependencies requires an install script to compile native bindings, opt in explicitly:
|
|
112
|
+
```sh
|
|
113
|
+
npx angular-compat-matrix --allow-scripts
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If an installation or build fails while scripts were blocked, ng-matrix explicitly lists which packages were skipped in the output findings so you know whether `--allow-scripts` is needed.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Cache Management
|
|
121
|
+
|
|
122
|
+
ng-matrix caches npm registry metadata and downloaded tools (such as pinned pnpm binaries) to keep runs fast and enable `--offline` usage.
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
# View cache location, disk usage, and file count
|
|
126
|
+
ng-matrix cache
|
|
127
|
+
|
|
128
|
+
# Clear the cache entirely
|
|
129
|
+
ng-matrix cache clean
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Cache Locations by OS
|
|
133
|
+
|
|
134
|
+
- **Linux:** `$XDG_CACHE_HOME/ng-matrix` or `~/.cache/ng-matrix`
|
|
135
|
+
- **macOS:** `~/.cache/ng-matrix` (or `$XDG_CACHE_HOME/ng-matrix`)
|
|
136
|
+
- **Windows:** `%LOCALAPPDATA%\ng-matrix\Cache`
|
|
137
|
+
- **Custom Location:** Set the `NG_MATRIX_CACHE` environment variable to override the default on any OS.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Exit Codes
|
|
142
|
+
|
|
143
|
+
ng-matrix returns standard POSIX exit codes suitable for CI pipelines:
|
|
144
|
+
|
|
145
|
+
- **`0` (Success):** Every version claimed by the library's peer dependencies passed all checks. (If the library declares no `@angular/*` peer dependencies, 0 is returned if any checked version passes).
|
|
146
|
+
- **`1` (Broken Promise):** At least one Angular major claimed by your `peerDependencies` failed a check (install, partial, AOT, strict types, or tests).
|
|
147
|
+
- **`2` (Environment / Setup Error):** ng-matrix could not check a version due to machine or network failure (e.g. disk full ENOSPC, network down, step timeout, invalid CLI options).
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## In CI
|
|
152
|
+
|
|
153
|
+
### GitHub Actions
|
|
154
|
+
|
|
155
|
+
Add a step to your workflow to verify compatibility and post the matrix directly to your workflow run summary:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
name: Compatibility Matrix
|
|
159
|
+
|
|
160
|
+
on:
|
|
161
|
+
push:
|
|
162
|
+
branches: [main]
|
|
163
|
+
pull_request:
|
|
164
|
+
|
|
165
|
+
jobs:
|
|
166
|
+
compat:
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
steps:
|
|
169
|
+
- uses: actions/checkout@v4
|
|
170
|
+
- uses: actions/setup-node@v4
|
|
171
|
+
with:
|
|
172
|
+
node-version: 24
|
|
173
|
+
- run: npm ci
|
|
174
|
+
- name: Run Angular Compatibility Matrix
|
|
175
|
+
run: npx angular-compat-matrix --format markdown >> "$GITHUB_STEP_SUMMARY"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## JSON Output & Stable Schema Contract
|
|
181
|
+
|
|
182
|
+
When running with `--json` or `--format json`, ng-matrix outputs structured JSON with a fixed schema contract.
|
|
183
|
+
|
|
184
|
+
The top-level field `schemaVersion` is guaranteed. Any future additions or modifications to the JSON shape will increment `schemaVersion`.
|
|
185
|
+
|
|
186
|
+
### Schema Version 1 Specification
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"schemaVersion": 1,
|
|
191
|
+
"tool": {
|
|
192
|
+
"name": "angular-compat-matrix",
|
|
193
|
+
"version": "0.1.0"
|
|
194
|
+
},
|
|
195
|
+
"checkedAt": "2026-10-26T12:00:00.000Z",
|
|
196
|
+
"library": {
|
|
197
|
+
"name": "my-lib",
|
|
198
|
+
"version": "1.0.0",
|
|
199
|
+
"source": "package",
|
|
200
|
+
"compiledWith": "20.2.0",
|
|
201
|
+
"highestMinVersion": "20.0.0",
|
|
202
|
+
"highestMinVersionIn": "component (dist/my-lib.mjs)",
|
|
203
|
+
"declarations": 12
|
|
204
|
+
},
|
|
205
|
+
"packageManager": "npm",
|
|
206
|
+
"installScripts": "toolchain-only",
|
|
207
|
+
"node": "v24.19.0",
|
|
208
|
+
"versions": [
|
|
209
|
+
{
|
|
210
|
+
"major": 21,
|
|
211
|
+
"angularVersion": "21.2.0",
|
|
212
|
+
"supported": true,
|
|
213
|
+
"prerelease": false,
|
|
214
|
+
"claimed": true,
|
|
215
|
+
"peerMisses": [],
|
|
216
|
+
"checks": {
|
|
217
|
+
"peer": {
|
|
218
|
+
"status": "pass",
|
|
219
|
+
"message": "Claimed: @angular/core@^21.0.0.",
|
|
220
|
+
"errorLines": [],
|
|
221
|
+
"durationMs": 0
|
|
222
|
+
},
|
|
223
|
+
"install": {
|
|
224
|
+
"status": "pass",
|
|
225
|
+
"message": "Installed with npm.",
|
|
226
|
+
"errorLines": [],
|
|
227
|
+
"durationMs": 4200
|
|
228
|
+
},
|
|
229
|
+
"partial": {
|
|
230
|
+
"status": "pass",
|
|
231
|
+
"advisory": false,
|
|
232
|
+
"message": "minVersion is 20.0.0.",
|
|
233
|
+
"errorLines": [],
|
|
234
|
+
"durationMs": 12
|
|
235
|
+
},
|
|
236
|
+
"aot": {
|
|
237
|
+
"status": "pass",
|
|
238
|
+
"message": "Production build succeeded.",
|
|
239
|
+
"errorLines": [],
|
|
240
|
+
"durationMs": 6100
|
|
241
|
+
},
|
|
242
|
+
"strict": {
|
|
243
|
+
"status": "pass",
|
|
244
|
+
"message": "Builds with strictTemplates: true and skipLibCheck: false.",
|
|
245
|
+
"errorLines": [],
|
|
246
|
+
"durationMs": 5900
|
|
247
|
+
},
|
|
248
|
+
"tests": {
|
|
249
|
+
"status": "off",
|
|
250
|
+
"message": "Not requested (--tests).",
|
|
251
|
+
"errorLines": [],
|
|
252
|
+
"durationMs": 0
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"skippedInstallScripts": [],
|
|
256
|
+
"omittedEntryPoints": [],
|
|
257
|
+
"dtsErrors": false,
|
|
258
|
+
"durationMs": 16212
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
"findings": [
|
|
262
|
+
{
|
|
263
|
+
"level": "error",
|
|
264
|
+
"majors": [19],
|
|
265
|
+
"text": "AOT build: Production build failed."
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
"exitCode": 0
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### JSON Fields Reference
|
|
273
|
+
|
|
274
|
+
- **`schemaVersion`** (`number`): The JSON schema version (currently `1`).
|
|
275
|
+
- **`tool`** (`{ name: string, version: string }`): CLI name and version.
|
|
276
|
+
- **`checkedAt`** (`string`): ISO-8601 timestamp when the check was performed.
|
|
277
|
+
- **`library`** (`object`):
|
|
278
|
+
- `name`: Package name.
|
|
279
|
+
- `version`: Package version.
|
|
280
|
+
- `source`: How the package was acquired (`workspace`, `tarball`, or `package`).
|
|
281
|
+
- `compiledWith` (`string?`): The Angular version that built this library.
|
|
282
|
+
- `highestMinVersion` (`string?`): Highest `minVersion` found across declarations.
|
|
283
|
+
- `highestMinVersionIn` (`string?`): Component or declaration file with the highest `minVersion`.
|
|
284
|
+
- `declarations` (`number`): Count of Angular declarables detected.
|
|
285
|
+
- **`packageManager`** (`string`): `'npm'` or `'pnpm'`.
|
|
286
|
+
- **`installScripts`** (`'toolchain-only' | 'all'`): Whether `--allow-scripts` was active.
|
|
287
|
+
- **`node`** (`string`): Node.js runtime version.
|
|
288
|
+
- **`versions`** (`VersionReport[]`): Results per Angular major:
|
|
289
|
+
- `major`: Angular major version number.
|
|
290
|
+
- `angularVersion`: Resolved patch version checked.
|
|
291
|
+
- `supported`: Whether this major is currently within Angular's official 18-month support window.
|
|
292
|
+
- `prerelease`: Whether this major came from a pre-release tag (`next`).
|
|
293
|
+
- `claimed`: `true` if peer dependencies include this version, `false` if excluded, `null` if no Angular peers declared.
|
|
294
|
+
- `peerMisses`: Array of declared peers whose ranges excluded this major (`{ name, range, version }`).
|
|
295
|
+
- `checks`: Object mapping check names (`peer`, `install`, `partial`, `aot`, `strict`, `tests`) to check results:
|
|
296
|
+
- `status`: `'pass' | 'fail' | 'not-run' | 'off' | 'none'`.
|
|
297
|
+
- `message`: Summary message.
|
|
298
|
+
- `errorLines`: First relevant error lines extracted from build or install logs.
|
|
299
|
+
- `fullOutput` (`string?`): Full command stdout and stderr on failure (optional; present only when `--verbose` is used).
|
|
300
|
+
- `hint` (`string?`): Plain-language diagnostic hint.
|
|
301
|
+
- `durationMs`: Execution duration in milliseconds.
|
|
302
|
+
- `advisory` (`boolean?`): `true` when partial check passed only on `minVersion` despite being built with newer Angular.
|
|
303
|
+
- `setupError` (`string?`): Description if the run failed due to machine/environment reasons.
|
|
304
|
+
- `skippedInstallScripts` (`string[]?`): Packages whose install scripts were blocked.
|
|
305
|
+
- `omittedEntryPoints` (`{ entry: string, missingPackage: string }[]?`): Secondary entry points skipped due to undeclared dependencies.
|
|
306
|
+
- `dtsErrors` (`boolean?`): `true` if strict build had errors confined to `node_modules/**/*.d.ts`.
|
|
307
|
+
- `durationMs`: Total duration for checking this major.
|
|
308
|
+
- **`findings`** (`Finding[]`): Merged diagnostics across all checked versions:
|
|
309
|
+
- `level`: `'error' | 'warning' | 'note'`.
|
|
310
|
+
- `majors`: Array of major version numbers affected.
|
|
311
|
+
- `text`: Human-readable problem description and suggested resolution.
|
|
312
|
+
- `suggestedPeerDependencies` (`Record<string, string>?`): Recommended peer dependencies when none were declared.
|
|
313
|
+
- **`exitCode`** (`number`): `0`, `1`, or `2`.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Troubleshooting Real-World Issues
|
|
318
|
+
|
|
319
|
+
Here are the most common real-world incompatibilities identified across popular Angular packages and how to solve them:
|
|
320
|
+
|
|
321
|
+
### 1. Linker Crash on Older Angular (`Unsupported enum value` / `ɵɵFactoryTarget.Service`)
|
|
322
|
+
- **Symptom:** The library claims support for Angular 20 and 21, but on Angular 20 the linker crashes with `Unsupported enum value` or `Cannot create property 'message' on string`.
|
|
323
|
+
- **Cause:** The library was compiled with Angular 21 or 22. Newer Angular compilers emit bytecode constructs that older linkers do not recognize, even though `minVersion` was claimed as `12.0.0`.
|
|
324
|
+
- **Fix:** Compile your library with the **oldest** Angular major you support, or narrow your `peerDependencies` range to exclude older majors.
|
|
325
|
+
|
|
326
|
+
### 2. Secondary Entry Points with Undeclared Dependencies
|
|
327
|
+
- **Symptom:** A component in a secondary entry point (e.g. `primeng/chart` or `ng-zorro-antd/graph`) fails because `chart.js` or `dagre-d3-es` is not found.
|
|
328
|
+
- **Handling:** ng-matrix omits secondary entry points that fail exclusively because of undeclared packages and flags a warning finding. However, if your **main** entry point (`.`) imports an undeclared package, ng-matrix fails the AOT check because all consumers would experience build failures.
|
|
329
|
+
- **Fix:** Move undeclared packages into `peerDependencies` (or `dependencies` if required).
|
|
330
|
+
|
|
331
|
+
### 3. Library Typings Errors under `skipLibCheck: false`
|
|
332
|
+
- **Symptom:** Strict build fails with errors inside declaration files under `node_modules/**/*.d.ts`.
|
|
333
|
+
- **Handling:** When errors are confined strictly to third-party declaration files, ng-matrix marks the strict check as passed with an informational warning finding (`"library typings have errors with skipLibCheck: false"`). It does not fail the version or trigger an exit code 1.
|
|
334
|
+
- **Fix:** Keep your third-party typing dependencies aligned with target TypeScript versions.
|
|
335
|
+
|
|
336
|
+
### 4. Disk Full (ENOSPC)
|
|
337
|
+
- **Symptom:** Exit code 2 with `ENOSPC: no space left on device`.
|
|
338
|
+
- **Fix:** Clear temporary build folders and caches using `ng-matrix cache clean`, or point `NG_MATRIX_CACHE` and `TMPDIR`/`TEMP` to a drive with sufficient disk space.
|
|
339
|
+
|
|
340
|
+
> **Tip for library authors:** If your library accepts bare attributes like `<comp myFlag>`, give boolean inputs `@Input({ transform: booleanAttribute })` so consumers can write bare attributes under strict template checking (ng-matrix does not check this).
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Options Reference
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
Usage
|
|
348
|
+
npx angular-compat-matrix [options]
|
|
349
|
+
ng-matrix [options] (once installed)
|
|
350
|
+
ng-matrix cache (show cache location and size)
|
|
351
|
+
ng-matrix cache clean (delete the cache)
|
|
352
|
+
|
|
353
|
+
Options
|
|
354
|
+
--versions <list> Angular majors to check: 22, 18-22, 20,22. Default: supported
|
|
355
|
+
majors, claimed majors (from 17), and the newest
|
|
356
|
+
--next Also check whatever the `next` tag points to
|
|
357
|
+
--project <name> The library project, in a workspace with several
|
|
358
|
+
--consumer <dir> Build your own example app instead of a generated smoke app
|
|
359
|
+
--tests Also run the library's tests on each version (slow)
|
|
360
|
+
--test-command <cmd> The test command for --tests (default: <pm> test)
|
|
361
|
+
--format <format> terminal (default), markdown or json
|
|
362
|
+
--json Shorthand for --format json
|
|
363
|
+
--pm <npm|pnpm> Package manager for the apps (default: pnpm if lockfile present, else npm)
|
|
364
|
+
--build <cmd> Build the library with this command instead of the detected one
|
|
365
|
+
--skip-build Pack the existing build output as is
|
|
366
|
+
--tarball <file> Check this packed .tgz instead of building
|
|
367
|
+
--package <spec> Check a published package, e.g. some-lib@3.1.0
|
|
368
|
+
--concurrency <n> Versions checked at once (default: based on available memory)
|
|
369
|
+
--step-timeout <min> Maximum minutes any single step may take (default: 20)
|
|
370
|
+
--keep Keep the temporary apps after completion for debugging
|
|
371
|
+
--allow-scripts Permit all package install scripts to run (default: toolchain only)
|
|
372
|
+
--offline Use only cached registry answers and packages
|
|
373
|
+
--cwd <dir> The library's workspace (default: current directory)
|
|
374
|
+
--verbose Show commands run and full build/install output for failures
|
|
375
|
+
-h, --help Show help
|
|
376
|
+
-v, --version Show version
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Known Limitations & Roadmap
|
|
382
|
+
|
|
383
|
+
- **Supported Workspaces:** Angular CLI workspaces and standalone `ng-packagr` libraries.
|
|
384
|
+
- **Node.js:** Node 24.15 or later is recommended to cover all Angular majors from 17 through 22.
|
|
385
|
+
- **Planned:**
|
|
386
|
+
- `ng-matrix ci github`: Generates dedicated GitHub Actions workflows with matrix parallelism.
|
|
387
|
+
- First-class Nx workspace discovery and integration.
|
|
388
|
+
- Dedicated SSR (Server-Side Rendering) and `with-zone.js` validation columns.
|
|
389
|
+
- **Out of Scope:** Yarn and Bun (npm and pnpm cover package testing; JSON output makes custom wrappers simple), app migration tooling, and runtime browser testing.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Development
|
|
394
|
+
|
|
395
|
+
```sh
|
|
396
|
+
npm install
|
|
397
|
+
npm test # run all unit tests
|
|
398
|
+
npm run build # compile TypeScript
|
|
399
|
+
npm ci --prefix fixtures # install Angular fixture toolchain
|
|
400
|
+
node test/fixtures/run.ts # run fixture integration tests
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## License
|
|
406
|
+
|
|
407
|
+
MIT © 2026 Nizamudeen S
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { environmentProblem, errorLines, exec, quietEnv, stepTimeout } from "./exec.js";
|
|
4
|
+
import { binOf, ensureTool } from "./tools.js";
|
|
5
|
+
/** One flag set that works, without prompts, for every CLI from 17 to 22. */
|
|
6
|
+
export function newAppArgs(pm) {
|
|
7
|
+
return [
|
|
8
|
+
'new',
|
|
9
|
+
'smoke',
|
|
10
|
+
'--minimal',
|
|
11
|
+
'--skip-git',
|
|
12
|
+
'--skip-install',
|
|
13
|
+
'--defaults',
|
|
14
|
+
'--interactive=false',
|
|
15
|
+
'--ssr=false',
|
|
16
|
+
`--package-manager=${pm}`,
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
export async function generateApp(angular, pm, parentDir, cacheDir, offline) {
|
|
20
|
+
const cli = await ensureTool(cacheDir, '@angular/cli', angular.cliVersion, offline);
|
|
21
|
+
const result = await exec(process.execPath, [binOf(cli, 'ng'), ...newAppArgs(pm)], {
|
|
22
|
+
cwd: parentDir,
|
|
23
|
+
env: quietEnv({ CI: '1' }),
|
|
24
|
+
timeoutMs: stepTimeout(),
|
|
25
|
+
});
|
|
26
|
+
const appDir = join(parentDir, 'smoke');
|
|
27
|
+
if (result.code !== 0 || !existsSync(join(appDir, 'angular.json'))) {
|
|
28
|
+
const why = environmentProblem(result);
|
|
29
|
+
throw new Error(`ng new (Angular CLI ${angular.cliVersion}) failed${why ? `: ${why}` : ''}:\n${errorLines(result.output).join('\n')}`);
|
|
30
|
+
}
|
|
31
|
+
return appDir;
|
|
32
|
+
}
|
|
33
|
+
export function readJson(path) {
|
|
34
|
+
// Generated tsconfig files start with /* comments */; JSON.parse can't take them.
|
|
35
|
+
const text = readFileSync(path, 'utf8').replace(/^\s*\/\*[\s\S]*?\*\/\s*/gm, '').replace(/^\s*\/\/.*$/gm, '');
|
|
36
|
+
return JSON.parse(text);
|
|
37
|
+
}
|
|
38
|
+
export function writeJson(path, value) {
|
|
39
|
+
writeFileSync(path, JSON.stringify(value, null, 2) + '\n');
|
|
40
|
+
}
|
|
41
|
+
/** The app project in angular.json: the generated one, or the first application of a --consumer app. */
|
|
42
|
+
export function appProject(appDir) {
|
|
43
|
+
const workspace = readJson(join(appDir, 'angular.json'));
|
|
44
|
+
const entry = Object.entries(workspace.projects).find(([, p]) => (p.projectType ?? 'application') === 'application');
|
|
45
|
+
if (!entry)
|
|
46
|
+
throw new Error(`${appDir}/angular.json has no application project.`);
|
|
47
|
+
const [name, project] = entry;
|
|
48
|
+
const tsConfig = String(project.architect?.build?.options?.tsConfig ?? 'tsconfig.app.json');
|
|
49
|
+
return { name, tsConfig };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Points the build at ng-matrix's own tsconfig (and, for a generated app, its own main file),
|
|
53
|
+
* and removes the production budgets so a large component kit doesn't fail the build on size.
|
|
54
|
+
*/
|
|
55
|
+
export function configureBuild(appDir, mainFile) {
|
|
56
|
+
const path = join(appDir, 'angular.json');
|
|
57
|
+
const workspace = readJson(path);
|
|
58
|
+
const project = appProject(appDir);
|
|
59
|
+
const build = workspace.projects[project.name].architect.build;
|
|
60
|
+
build.options ??= {};
|
|
61
|
+
if (mainFile) {
|
|
62
|
+
// `browser` for the application builder (17+), `main` for the older webpack one.
|
|
63
|
+
if ('main' in build.options && !('browser' in build.options))
|
|
64
|
+
build.options.main = mainFile;
|
|
65
|
+
else
|
|
66
|
+
build.options.browser = mainFile;
|
|
67
|
+
}
|
|
68
|
+
build.options.tsConfig = 'tsconfig.ngm.json';
|
|
69
|
+
for (const configuration of Object.values(build.configurations ?? {})) {
|
|
70
|
+
if ('budgets' in configuration)
|
|
71
|
+
configuration.budgets = [];
|
|
72
|
+
}
|
|
73
|
+
writeJson(path, workspace);
|
|
74
|
+
return project;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Writes tsconfig.ngm.json extending the app's own tsconfig, with the template strictness set
|
|
78
|
+
* explicitly: Angular 17 to 21 apps write strictTemplates: true, and 22 makes it the default.
|
|
79
|
+
*/
|
|
80
|
+
export function writeTsconfig(appDir, baseTsConfig, mode, files) {
|
|
81
|
+
const config = {
|
|
82
|
+
extends: `./${baseTsConfig.replace(/^\.\//, '')}`,
|
|
83
|
+
compilerOptions: { skipLibCheck: mode.skipLibCheck },
|
|
84
|
+
angularCompilerOptions: { strictTemplates: mode.strictTemplates },
|
|
85
|
+
};
|
|
86
|
+
if (files) {
|
|
87
|
+
config.files = files;
|
|
88
|
+
config.include = [];
|
|
89
|
+
}
|
|
90
|
+
writeJson(join(appDir, 'tsconfig.ngm.json'), config);
|
|
91
|
+
}
|