ng-checkup 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +83 -9
  2. package/dist/bundle.d.ts +58 -0
  3. package/dist/bundle.js +189 -0
  4. package/dist/bundle.js.map +1 -0
  5. package/dist/cache.d.ts +41 -0
  6. package/dist/cache.js +36 -0
  7. package/dist/cache.js.map +1 -0
  8. package/dist/checks/architecture.d.ts +21 -0
  9. package/dist/checks/architecture.js +108 -0
  10. package/dist/checks/architecture.js.map +1 -0
  11. package/dist/checks/bundle.d.ts +24 -0
  12. package/dist/checks/bundle.js +112 -0
  13. package/dist/checks/bundle.js.map +1 -0
  14. package/dist/checks/context.d.ts +13 -0
  15. package/dist/checks/context.js.map +1 -1
  16. package/dist/checks/dependencies.d.ts +18 -0
  17. package/dist/checks/dependencies.js +89 -0
  18. package/dist/checks/dependencies.js.map +1 -0
  19. package/dist/checks/deprecated-apis.js +23 -3
  20. package/dist/checks/deprecated-apis.js.map +1 -1
  21. package/dist/checks/security.d.ts +17 -0
  22. package/dist/checks/security.js +87 -0
  23. package/dist/checks/security.js.map +1 -0
  24. package/dist/checks/version.d.ts +11 -0
  25. package/dist/checks/version.js +1 -1
  26. package/dist/checks/version.js.map +1 -1
  27. package/dist/cli.d.ts +10 -0
  28. package/dist/cli.js +102 -14
  29. package/dist/cli.js.map +1 -1
  30. package/dist/compatibility.d.ts +43 -0
  31. package/dist/compatibility.js +135 -0
  32. package/dist/compatibility.js.map +1 -0
  33. package/dist/config.d.ts +2 -0
  34. package/dist/config.js +4 -2
  35. package/dist/config.js.map +1 -1
  36. package/dist/deprecations.js +21 -8
  37. package/dist/deprecations.js.map +1 -1
  38. package/dist/graph.d.ts +20 -0
  39. package/dist/graph.js +30 -0
  40. package/dist/graph.js.map +1 -1
  41. package/dist/index.d.ts +13 -4
  42. package/dist/index.js +137 -14
  43. package/dist/index.js.map +1 -1
  44. package/dist/plan.d.ts +2 -1
  45. package/dist/plan.js +37 -1
  46. package/dist/plan.js.map +1 -1
  47. package/dist/report/html.js +32 -1
  48. package/dist/report/html.js.map +1 -1
  49. package/dist/report/markdown.js +11 -1
  50. package/dist/report/markdown.js.map +1 -1
  51. package/dist/report/sarif.d.ts +20 -0
  52. package/dist/report/sarif.js +83 -0
  53. package/dist/report/sarif.js.map +1 -0
  54. package/dist/report/summary.d.ts +11 -2
  55. package/dist/report/summary.js +12 -0
  56. package/dist/report/summary.js.map +1 -1
  57. package/dist/report/terminal.js +20 -1
  58. package/dist/report/terminal.js.map +1 -1
  59. package/dist/scan.d.ts +43 -0
  60. package/dist/scan.js +60 -0
  61. package/dist/scan.js.map +1 -1
  62. package/dist/types.d.ts +33 -0
  63. package/dist/watch.d.ts +47 -0
  64. package/dist/watch.js +107 -0
  65. package/dist/watch.js.map +1 -0
  66. package/dist/workspace.d.ts +41 -0
  67. package/dist/workspace.js +86 -3
  68. package/dist/workspace.js.map +1 -1
  69. package/package.json +1 -1
@@ -0,0 +1,108 @@
1
+ import { applicationFiles, formatCount, percent, plural } from './context.js';
2
+ /** Lines of code from which a file is listed as large. */
3
+ const LARGE_FILE = 500;
4
+ /** Lines of code from which a file counts against the grade. */
5
+ const VERY_LARGE_FILE = 1000;
6
+ /**
7
+ * How the code is put together: lazy loading, oversized files, and the
8
+ * dependency-injection and guard style.
9
+ *
10
+ * Graded only on what makes an app slower to load or harder to change:
11
+ * routes that load everything up front, and files past a thousand lines,
12
+ * where every change touches code nobody fully reads any more. Constructor
13
+ * injection and class-based guards are reported but never grade, because
14
+ * they are a matter of style that works fine; `inject()` and functional
15
+ * guards are the current default and what the Angular migrations produce,
16
+ * which is all the findings say.
17
+ *
18
+ * Routes are recognised syntactically (object literals with `path` and
19
+ * `component` or `loadComponent`/`loadChildren`), so routes built by a
20
+ * helper function are not seen. A `component:` route inside a lazily loaded
21
+ * module is lazy, and is counted so: only files statically reachable from
22
+ * `main.ts` hold eager routes (`AnalysisContext.eagerFiles`).
23
+ */
24
+ export function architectureCheck(context) {
25
+ const files = applicationFiles(context);
26
+ // A `component:` route counts as eager only in a file loaded at startup: in
27
+ // a module that is itself behind `loadChildren`, it loads with that module.
28
+ const loadedAtStartup = (path) => context.eagerFiles === undefined || context.eagerFiles.has(path);
29
+ const eager = files.filter((file) => loadedAtStartup(file.path)).flatMap((file) => file.routes.eager.map((line) => ({ path: file.path, line })));
30
+ const lazy = files.flatMap((file) => [...file.routes.lazy, ...(loadedAtStartup(file.path) ? [] : file.routes.eager)].map((line) => ({ path: file.path, line })));
31
+ const routes = eager.length + lazy.length;
32
+ const large = files.filter((file) => file.linesOfCode >= LARGE_FILE).sort((left, right) => right.linesOfCode - left.linesOfCode);
33
+ const veryLarge = large.filter((file) => file.linesOfCode >= VERY_LARGE_FILE);
34
+ const constructorInjections = files.flatMap((file) => file.constructorInjections.map((entry) => ({ ...entry, path: file.path })));
35
+ const classGuards = files.flatMap((file) => file.classGuards.map((entry) => ({ ...entry, path: file.path })));
36
+ const injectCalls = files.reduce((sum, file) => sum + (file.calls.get('@angular/core#inject')?.length ?? 0), 0);
37
+ const max = context.maxExamples;
38
+ const findings = [];
39
+ if (eager.length > 0 && eager.length >= lazy.length && routes >= 5) {
40
+ findings.push({
41
+ severity: lazy.length === 0 ? 'high' : 'medium',
42
+ message: lazy.length === 0 ? `All ${plural(routes, 'route')} load eagerly` : `${plural(eager.length, 'route')} of ${formatCount(routes)} load eagerly`,
43
+ detail: 'A route with `component:` puts its whole screen in the initial bundle, downloaded before the first page shows. `loadComponent: () => import(...)` (or `loadChildren` for a group) loads it when the user navigates there; the route config is the only change.',
44
+ files: eager.slice(0, max),
45
+ count: eager.length,
46
+ });
47
+ }
48
+ if (large.length > 0) {
49
+ findings.push({
50
+ severity: veryLarge.length > 0 ? 'medium' : 'low',
51
+ message: `${plural(large.length, 'file')} over ${formatCount(LARGE_FILE)} lines${veryLarge.length > 0 ? `, ${formatCount(veryLarge.length)} over ${formatCount(VERY_LARGE_FILE)}` : ''}`,
52
+ detail: `The largest: ${large
53
+ .slice(0, 3)
54
+ .map((file) => `${file.path.split('/').pop()} (${formatCount(file.linesOfCode)})`)
55
+ .join(', ')}. Files this size usually hold several responsibilities; they are where changes collide and where a refactor pays back first.`,
56
+ files: large.slice(0, max).map((file) => ({ path: file.path })),
57
+ count: large.length,
58
+ });
59
+ }
60
+ if (classGuards.length > 0) {
61
+ findings.push({
62
+ severity: 'low',
63
+ message: `${plural(classGuards.length, 'class-based guard or interceptor', 'class-based guards and interceptors')}`,
64
+ detail: `${[...new Set(classGuards.map((entry) => entry.kind))].join(', ')}. Functional guards (\`CanActivateFn\`, \`ResolveFn\`) and interceptors (\`HttpInterceptorFn\` with \`withInterceptors\`) are the current style: a function with \`inject()\` inside, no class, no provider. Class interceptors also need \`withInterceptorsFromDi()\` to keep working with \`provideHttpClient\`.`,
65
+ files: classGuards.slice(0, max).map((entry) => ({ path: entry.path, line: entry.line })),
66
+ count: classGuards.length,
67
+ });
68
+ }
69
+ if (constructorInjections.length > 0) {
70
+ findings.push({
71
+ severity: 'low',
72
+ message: `${plural(constructorInjections.length, 'class injects', 'classes inject')} through the constructor`,
73
+ detail: `\`inject()\` is the current default (${plural(injectCalls, 'call')} already in the code). It works in field initialisers and functions, and it is what signal-based code expects. \`ng generate @angular/core:inject\` migrates constructors automatically.`,
74
+ files: constructorInjections.slice(0, max).map((entry) => ({ path: entry.path, line: entry.line })),
75
+ count: constructorInjections.length,
76
+ });
77
+ }
78
+ const lazyShare = percent(lazy.length, routes);
79
+ const grade = files.length === 0
80
+ ? 'info'
81
+ : (lazy.length === 0 && eager.length >= 10) || veryLarge.length >= 3
82
+ ? 'poor'
83
+ : (routes >= 5 && eager.length > lazy.length) || veryLarge.length > 0
84
+ ? 'fair'
85
+ : 'good';
86
+ return {
87
+ id: 'architecture',
88
+ title: 'Architecture',
89
+ grade,
90
+ summary: files.length === 0
91
+ ? 'No application code to check.'
92
+ : `${routes === 0 ? 'No routes found' : `${lazyShare}% of ${plural(routes, 'route')} lazy`}, ${plural(large.length, 'file')} over ${formatCount(LARGE_FILE)} lines, ${plural(constructorInjections.length, 'class', 'classes')} with constructor injection.`,
93
+ metrics: [
94
+ { label: 'Lazy routes', value: `${lazyShare}%`, hint: `${formatCount(lazy.length)} of ${formatCount(routes)}` },
95
+ { label: 'Large files', value: formatCount(large.length), hint: `over ${formatCount(LARGE_FILE)} lines` },
96
+ { label: 'Constructor injection', value: formatCount(constructorInjections.length), hint: `classes; ${formatCount(injectCalls)} inject() calls` },
97
+ { label: 'Class guards', value: formatCount(classGuards.length), hint: 'and interceptors' },
98
+ ],
99
+ findings,
100
+ measures: [
101
+ { id: 'eager-routes', label: 'Eagerly loaded routes', value: eager.length },
102
+ { id: 'very-large-files', label: `Files over ${VERY_LARGE_FILE} lines`, value: veryLarge.length },
103
+ { id: 'constructor-injection', label: 'Classes with constructor injection', value: constructorInjections.length },
104
+ { id: 'class-guards', label: 'Class-based guards and interceptors', value: classGuards.length },
105
+ ],
106
+ };
107
+ }
108
+ //# sourceMappingURL=architecture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architecture.js","sourceRoot":"","sources":["../../src/checks/architecture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { CheckResult } from '../types.js';
2
+ import { type AnalysisContext } from './context.js';
3
+ /**
4
+ * The size of what the browser loads before the app starts, from the stats
5
+ * file of the last `ng build --stats-json`, against the build's `initial`
6
+ * budget.
7
+ *
8
+ * It reads a build, it does not run one: building takes minutes and needs a
9
+ * working toolchain, while every other check takes seconds on a repository
10
+ * that may not even compile. Without a stats file it grades `info` and says
11
+ * how to get one. The file's date is in the summary, because a stats file
12
+ * from last month describes last month's bundle.
13
+ *
14
+ * There is no baseline measure here, on purpose: a bundle grows with every
15
+ * feature, so "may only go down" would fail CI on ordinary work. The budget
16
+ * is the limit, and the build already enforces it; this check explains what
17
+ * fills it.
18
+ */
19
+ export declare function bundleCheck(context: AnalysisContext): CheckResult;
20
+ /**
21
+ * Bytes in decimal units, as the size table of `ng build` prints them
22
+ * (112063 bytes is "112.1 kB"), so a number here can be found in the build log.
23
+ */
24
+ export declare function formatBytes(bytes: number): string;
@@ -0,0 +1,112 @@
1
+ import { formatCount, plural } from './context.js';
2
+ /**
3
+ * The size of what the browser loads before the app starts, from the stats
4
+ * file of the last `ng build --stats-json`, against the build's `initial`
5
+ * budget.
6
+ *
7
+ * It reads a build, it does not run one: building takes minutes and needs a
8
+ * working toolchain, while every other check takes seconds on a repository
9
+ * that may not even compile. Without a stats file it grades `info` and says
10
+ * how to get one. The file's date is in the summary, because a stats file
11
+ * from last month describes last month's bundle.
12
+ *
13
+ * There is no baseline measure here, on purpose: a bundle grows with every
14
+ * feature, so "may only go down" would fail CI on ordinary work. The budget
15
+ * is the limit, and the build already enforces it; this check explains what
16
+ * fills it.
17
+ */
18
+ export function bundleCheck(context) {
19
+ const id = 'bundle';
20
+ const title = 'Bundle size';
21
+ const { bundles } = context;
22
+ if (bundles.length === 0) {
23
+ return {
24
+ id,
25
+ title,
26
+ grade: 'info',
27
+ summary: 'No build stats found, so the bundle size is not part of this report.',
28
+ metrics: [],
29
+ findings: [{ severity: 'info', message: 'Run `ng build --stats-json` (or `nx build <app> --stats-json`) and re-run to include the bundle size' }],
30
+ };
31
+ }
32
+ const graded = bundles.map((bundle) => ({ bundle, grade: gradeOf(bundle) }));
33
+ const worst = [...graded].sort((left, right) => rank(right.grade) - rank(left.grade) || right.bundle.initialBytes - left.bundle.initialBytes)[0];
34
+ const largest = worst.bundle;
35
+ const findings = [];
36
+ for (const { bundle, grade } of graded) {
37
+ const name = bundles.length > 1 ? ` of ${bundle.project}` : '';
38
+ const top = bundle.initialByPackage.slice(0, 5).map((entry) => `${entry.name} ${formatBytes(entry.bytes)}`).join(', ');
39
+ if (grade !== 'good') {
40
+ const limit = grade === 'poor' ? bundle.budget.error : bundle.budget.warning;
41
+ findings.push({
42
+ severity: grade === 'poor' ? 'high' : 'medium',
43
+ message: `The initial bundle${name} is ${formatBytes(bundle.initialBytes)}, over its ${grade === 'poor' ? 'error' : 'warning'} budget of ${formatBudget(limit)}`,
44
+ detail: `Everything in it is downloaded, parsed and run before the first screen.${top ? ` Largest parts: ${top}.` : ''} Lazy routes (\`loadComponent\`, \`loadChildren\`) and \`@defer\` move code out of it; a large package used on one screen is the usual first candidate.`,
45
+ files: [{ path: bundle.file }],
46
+ });
47
+ }
48
+ else if (top) {
49
+ findings.push({ severity: 'info', message: `Largest parts of the initial bundle${name}: ${top}`, files: [{ path: bundle.file }] });
50
+ }
51
+ if (bundle.lazyChunks === 0 && bundle.initialBytes > 250 * 1000) {
52
+ findings.push({
53
+ severity: 'low',
54
+ message: `Nothing${name} is loaded lazily`,
55
+ detail: 'The whole app ships in the initial bundle. Lazy routes split it per screen at no cost to the code that stays eager.',
56
+ files: [{ path: bundle.file }],
57
+ });
58
+ }
59
+ }
60
+ const builtAt = bundles.map((bundle) => bundle.builtAt).sort()[0].slice(0, 10);
61
+ const summary = bundles.length === 1
62
+ ? `Initial bundle ${formatBytes(largest.initialBytes)} of a ${formatBudget(largest.budget.warning)} budget, ${plural(largest.lazyChunks, 'lazy chunk')} (build of ${builtAt}).`
63
+ : `${bundles.length} apps measured; ${worst.grade === 'good' ? 'largest' : 'worst'} initial bundle ${formatBytes(largest.initialBytes)} (${largest.project}) of a ${formatBudget(largest.budget.warning)} budget (builds from ${builtAt}).`;
64
+ return {
65
+ id,
66
+ title,
67
+ grade: worst.grade,
68
+ summary,
69
+ metrics: [
70
+ { label: 'Initial bundle', value: formatBytes(largest.initialBytes), hint: `budget ${formatBudget(largest.budget.warning)}${bundles.length > 1 ? `, ${largest.project}` : ''}` },
71
+ { label: 'Lazy chunks', value: formatCount(largest.lazyChunks), hint: formatBytes(largest.lazyBytes) },
72
+ { label: 'Largest lazy chunk', value: largest.largestLazy ? formatBytes(largest.largestLazy.bytes) : '-' },
73
+ { label: 'Largest package', value: largest.initialByPackage.find((entry) => entry.name !== '(your code)')?.name ?? '-', hint: 'in the initial bundle' },
74
+ ],
75
+ findings,
76
+ };
77
+ }
78
+ /** Good under the warning budget, fair under the error budget, poor above it. A missing limit never trips. */
79
+ function gradeOf(bundle) {
80
+ if (bundle.budget.error !== undefined && bundle.initialBytes > bundle.budget.error)
81
+ return 'poor';
82
+ if (bundle.budget.warning !== undefined && bundle.initialBytes > bundle.budget.warning)
83
+ return 'fair';
84
+ return 'good';
85
+ }
86
+ /** Order for picking the worst bundle. */
87
+ function rank(grade) {
88
+ return { info: 0, good: 1, fair: 2, poor: 3 }[grade];
89
+ }
90
+ /**
91
+ * Bytes in decimal units, as the size table of `ng build` prints them
92
+ * (112063 bytes is "112.1 kB"), so a number here can be found in the build log.
93
+ */
94
+ export function formatBytes(bytes) {
95
+ if (bytes < 1000)
96
+ return `${bytes} bytes`;
97
+ if (bytes < 1000 * 1000)
98
+ return `${(bytes / 1000).toFixed(1)} kB`;
99
+ return `${(bytes / 1000 / 1000).toFixed(2)} MB`;
100
+ }
101
+ /**
102
+ * A budget in binary units, the way `angular.json` declares it: Angular reads
103
+ * "500kB" as 500 × 1024 bytes, so it is printed back as "500 kB", not "512.0 kB".
104
+ */
105
+ function formatBudget(bytes) {
106
+ if (bytes === undefined)
107
+ return 'no';
108
+ if (bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0)
109
+ return `${bytes / 1024 / 1024} MB`;
110
+ return `${Math.round(bytes / 1024)} kB`;
111
+ }
112
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/checks/bundle.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
+ import type { BundleStats } from '../bundle.js';
1
2
  import type ts from 'typescript';
3
+ import type { PackageCompatibility } from '../compatibility.js';
2
4
  import type { DeprecationIndex } from '../deprecations.js';
3
5
  import type { DependencyTangle } from '../graph.js';
4
6
  import type { SourceFileFacts, TemplateFact } from '../scan.js';
@@ -18,6 +20,17 @@ export interface AnalysisContext {
18
20
  /** Empty when dependencies are not installed. */
19
21
  deprecations: DeprecationIndex;
20
22
  tangles: DependencyTangle[];
23
+ /**
24
+ * Report paths of the files loaded at startup: statically reachable from an
25
+ * application entry (`main.ts`). Undefined when no build target names an
26
+ * entry that was analysed, in which case nothing can be said about what
27
+ * loads lazily.
28
+ */
29
+ eagerFiles?: Set<string>;
30
+ /** Stats of the last `ng build --stats-json` per application. Empty when there is none. */
31
+ bundles: BundleStats[];
32
+ /** Installed third-party packages that depend on Angular. Empty without node_modules. */
33
+ compatibility: PackageCompatibility[];
21
34
  /** Newest Angular major, and whether it came from the registry or the tool's bundled fallback. */
22
35
  latestAngular: {
23
36
  major: number;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/checks/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/checks/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { CheckResult } from '../types.js';
2
+ import { type AnalysisContext } from './context.js';
3
+ /**
4
+ * Third-party packages that depend on Angular, and whether they hold the
5
+ * project back.
6
+ *
7
+ * A library pinned to an old Angular is the most common reason an upgrade
8
+ * stalls halfway: `ng update` refuses, or worse, succeeds with
9
+ * `--force` and the library fails at runtime. This check reads every
10
+ * installed package's `@angular/core` peer range, so it covers any UI kit,
11
+ * state library or utility without a list of known names.
12
+ *
13
+ * Graded `poor` when something is already broken (a package that does not
14
+ * accept the Angular in use) or when, per the registry, no release of a
15
+ * package supports the latest Angular yet; `fair` when packages block the
16
+ * upgrade but have newer releases, or are deprecated on npm.
17
+ */
18
+ export declare function dependenciesCheck(context: AnalysisContext): CheckResult;
@@ -0,0 +1,89 @@
1
+ import { highestSupported } from '../compatibility.js';
2
+ import { formatCount, plural, verb } from './context.js';
3
+ /**
4
+ * Third-party packages that depend on Angular, and whether they hold the
5
+ * project back.
6
+ *
7
+ * A library pinned to an old Angular is the most common reason an upgrade
8
+ * stalls halfway: `ng update` refuses, or worse, succeeds with
9
+ * `--force` and the library fails at runtime. This check reads every
10
+ * installed package's `@angular/core` peer range, so it covers any UI kit,
11
+ * state library or utility without a list of known names.
12
+ *
13
+ * Graded `poor` when something is already broken (a package that does not
14
+ * accept the Angular in use) or when, per the registry, no release of a
15
+ * package supports the latest Angular yet; `fair` when packages block the
16
+ * upgrade but have newer releases, or are deprecated on npm.
17
+ */
18
+ export function dependenciesCheck(context) {
19
+ const { workspace, compatibility } = context;
20
+ const current = workspace.angular.major;
21
+ const target = context.latestAngular.major;
22
+ const id = 'dependencies';
23
+ const title = 'Third-party compatibility';
24
+ if (!workspace.hasNodeModules || current === undefined) {
25
+ return {
26
+ id,
27
+ title,
28
+ grade: 'info',
29
+ summary: current === undefined ? 'No Angular dependency to check against.' : 'Dependencies are not installed, so the packages that depend on Angular could not be read.',
30
+ metrics: [],
31
+ findings: current === undefined ? [] : [{ severity: 'info', message: 'Run `npm install` (or your package manager) and re-run for this check' }],
32
+ };
33
+ }
34
+ const majors = Array.from({ length: target - current + 1 }, (_, index) => current + index);
35
+ const mismatched = compatibility.filter((entry) => !entry.supportsCurrent);
36
+ const blocking = compatibility.filter((entry) => entry.supportsCurrent && entry.blocksAt !== undefined);
37
+ const deprecated = compatibility.filter((entry) => entry.deprecated);
38
+ const dead = blocking.filter((entry) => entry.releaseFor?.[target] === null);
39
+ const findings = [];
40
+ for (const entry of mismatched) {
41
+ findings.push({
42
+ severity: 'high',
43
+ message: `\`${entry.name}\` ${entry.installed} does not accept Angular ${current}`,
44
+ detail: `It declares \`@angular/core\` ${entry.angularRange}, so it was installed with --force, --legacy-peer-deps or an override, and it may fail at runtime in ways no build catches.${releaseHint(entry, current)}${entry.releaseFor?.[current] === null ? ` No release accepts Angular ${current} yet (latest ${entry.latest ?? 'unknown'}).` : ''}`,
45
+ });
46
+ }
47
+ for (const entry of blocking) {
48
+ const upTo = highestSupported(entry.angularRange, majors);
49
+ const noRelease = entry.releaseFor?.[target] === null;
50
+ findings.push({
51
+ severity: noRelease ? 'high' : 'medium',
52
+ message: `\`${entry.name}\` ${entry.installed} supports Angular up to ${upTo ?? current}: it blocks the step to ${entry.blocksAt}`,
53
+ detail: `It declares \`@angular/core\` ${entry.angularRange}.${releaseHint(entry, entry.blocksAt)}${noRelease ? ` No release supports Angular ${target} yet (latest ${entry.latest ?? 'unknown'}): plan to replace it, or to stop at the last major it supports.` : ''}`,
54
+ });
55
+ }
56
+ for (const entry of deprecated) {
57
+ findings.push({ severity: 'medium', message: `\`${entry.name}\` is deprecated on npm`, detail: entry.deprecated });
58
+ }
59
+ if (blocking.length > 0 && blocking.every((entry) => entry.releaseFor === undefined)) {
60
+ findings.push({ severity: 'info', message: 'Run without --offline to find the releases that support newer Angular versions' });
61
+ }
62
+ const grade = mismatched.length > 0 || dead.length > 0 ? 'poor' : blocking.length > 0 || deprecated.length > 0 ? 'fair' : 'good';
63
+ return {
64
+ id,
65
+ title,
66
+ grade,
67
+ summary: compatibility.length === 0
68
+ ? 'No third-party package depends on Angular.'
69
+ : `${plural(compatibility.length, 'package')} ${verb(compatibility.length, 'depends', 'depend')} on Angular: ${formatCount(blocking.length)} blocking the upgrade to ${target}, ${formatCount(mismatched.length)} not accepting the current version.`,
70
+ metrics: [
71
+ { label: 'Depend on Angular', value: formatCount(compatibility.length), hint: 'third-party packages' },
72
+ { label: 'Block the upgrade', value: formatCount(blocking.length), hint: `to Angular ${target}` },
73
+ { label: 'Peer mismatches', value: formatCount(mismatched.length), hint: `with Angular ${current}` },
74
+ { label: 'Deprecated on npm', value: formatCount(deprecated.length) },
75
+ ],
76
+ findings,
77
+ // Only what the code controls: blocking packages depend on when Angular ships, so they are not a measure.
78
+ measures: [
79
+ { id: 'peer-mismatches', label: 'Packages that do not accept the installed Angular', value: mismatched.length },
80
+ { id: 'deprecated-packages', label: 'Packages deprecated on npm', value: deprecated.length },
81
+ ],
82
+ };
83
+ }
84
+ /** " Version 5.1.0 supports Angular 14." when the registry found one, else an empty string. */
85
+ function releaseHint(entry, major) {
86
+ const release = entry.releaseFor?.[major];
87
+ return release ? ` Version ${release.version} supports Angular ${major}.` : '';
88
+ }
89
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/checks/dependencies.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { isSpecFile } from '../files.js';
2
+ import { majorOf, readInstalledVersion } from '../workspace.js';
2
3
  import { formatCount, plural } from './context.js';
3
4
  /**
4
5
  * Deprecated Angular and NgRx APIs the code uses, as the installed packages
@@ -59,11 +60,16 @@ export function deprecatedApisCheck(context) {
59
60
  }
60
61
  }
61
62
  const current = workspace.angular.major;
62
- const isOverdue = (info) => current !== undefined && info.since !== undefined && current - Number.parseInt(info.since, 10) >= 2;
63
+ /**
64
+ * Overdue means deprecated two or more Angular majors ago. Only Angular's and
65
+ * NgRx's version numbers follow Angular majors; RxJS has its own ("7.0"), and
66
+ * comparing that with Angular 22 would call every RxJS deprecation overdue.
67
+ */
68
+ const isOverdue = (info, module) => (module === undefined || module.startsWith('@angular/') || module.startsWith('@ngrx/')) && current !== undefined && info.since !== undefined && current - Number.parseInt(info.since, 10) >= 2;
63
69
  const sorted = [...usages.values()];
64
- const groups = groupByDeprecation(sorted).sort((left, right) => Number(isOverdue(right.info)) - Number(isOverdue(left.info)) || right.refs.length - left.refs.length);
70
+ const groups = groupByDeprecation(sorted).sort((left, right) => Number(isOverdue(right.info, right.module)) - Number(isOverdue(left.info, left.module)) || right.refs.length - left.refs.length);
65
71
  const findings = groups.map((group) => ({
66
- severity: isOverdue(group.info) ? 'high' : 'medium',
72
+ severity: isOverdue(group.info, group.module) ? 'high' : 'medium',
67
73
  message: `${group.names.map((name) => `\`${name}\``).join(', ')} from ${group.module}, used in ${plural(group.refs.length, 'file')}${testShare(group.refs)}`,
68
74
  detail: describe(group.info),
69
75
  files: group.refs.slice(0, context.maxExamples),
@@ -79,6 +85,19 @@ export function deprecatedApisCheck(context) {
79
85
  count: legacyTemplates.length,
80
86
  });
81
87
  }
88
+ // `.toPromise()`: deprecated in RxJS 7 and removed in 8, so it only counts from 7 on.
89
+ const rxjsMajor = majorOf(readInstalledVersion(workspace.root, 'rxjs') ?? workspace.dependencies['rxjs']);
90
+ const toPromiseFiles = context.sources.filter((file) => file.toPromiseLines.length > 0);
91
+ const toPromiseCalls = toPromiseFiles.reduce((sum, file) => sum + file.toPromiseLines.length, 0);
92
+ if (rxjsMajor !== undefined && rxjsMajor >= 7 && toPromiseCalls > 0) {
93
+ findings.push({
94
+ severity: 'medium',
95
+ message: `${plural(toPromiseCalls, '`.toPromise()` call')} in ${plural(toPromiseFiles.length, 'file')}`,
96
+ detail: 'Deprecated in RxJS 7 and removed in RxJS 8. `firstValueFrom(source$)` or `lastValueFrom(source$)` replace it; pick by whether the code wants the first value or waits for completion.',
97
+ files: toPromiseFiles.slice(0, context.maxExamples).map((file) => ({ path: file.path, line: file.toPromiseLines[0] })),
98
+ count: toPromiseFiles.length,
99
+ });
100
+ }
82
101
  const affectedFiles = new Set(sorted.flatMap((usage) => usage.refs.map((ref) => ref.path)));
83
102
  const grade = findings.length === 0 ? 'good' : findings.some((finding) => finding.severity === 'high') ? 'poor' : 'fair';
84
103
  return {
@@ -99,6 +118,7 @@ export function deprecatedApisCheck(context) {
99
118
  measures: [
100
119
  { id: 'deprecated-usages', label: 'Deprecated API uses (symbol × file)', value: sorted.reduce((sum, usage) => sum + usage.refs.length, 0) },
101
120
  { id: 'legacy-template-directives', label: '*ngIf / *ngFor / [ngSwitch] uses', value: legacyUses },
121
+ { id: 'to-promise-calls', label: '.toPromise() calls', value: rxjsMajor !== undefined && rxjsMajor >= 7 ? toPromiseCalls : 0 },
102
122
  ],
103
123
  };
104
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"deprecated-apis.js","sourceRoot":"","sources":["../../src/checks/deprecated-apis.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deprecated-apis.js","sourceRoot":"","sources":["../../src/checks/deprecated-apis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CheckResult } from '../types.js';
2
+ import { type AnalysisContext } from './context.js';
3
+ /**
4
+ * The places where the code steps around Angular's built-in XSS protection.
5
+ *
6
+ * Angular sanitizes every value bound into the DOM, so an Angular app is safe
7
+ * from cross-site scripting by default; the holes are the escape hatches.
8
+ * This check counts them, it does not judge them: a `bypassSecurityTrustHtml`
9
+ * on a constant is fine, the same call on a user's comment is an XSS. That
10
+ * is why bypasses only make the area `fair` (each needs a look), while HTML
11
+ * written straight into the DOM, or a string run as code, makes it `poor`:
12
+ * those skip the sanitizer for every value, not one reviewed value.
13
+ *
14
+ * Found by name in the syntax tree, without types, like the rest of the tool:
15
+ * `x.innerHTML = …` counts whatever `x` is. Spec files are left out.
16
+ */
17
+ export declare function securityCheck(context: AnalysisContext): CheckResult;