@angular/cli 21.0.0-next.6 → 21.0.0-next.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/cli",
3
- "version": "21.0.0-next.6",
3
+ "version": "21.0.0-next.7",
4
4
  "description": "CLI tool for Angular",
5
5
  "main": "lib/cli/index.js",
6
6
  "bin": {
@@ -25,19 +25,19 @@
25
25
  },
26
26
  "homepage": "https://github.com/angular/angular-cli",
27
27
  "dependencies": {
28
- "@angular-devkit/architect": "0.2100.0-next.6",
29
- "@angular-devkit/core": "21.0.0-next.6",
30
- "@angular-devkit/schematics": "21.0.0-next.6",
28
+ "@angular-devkit/architect": "0.2100.0-next.7",
29
+ "@angular-devkit/core": "21.0.0-next.7",
30
+ "@angular-devkit/schematics": "21.0.0-next.7",
31
31
  "@inquirer/prompts": "7.8.6",
32
32
  "@listr2/prompt-adapter-inquirer": "3.0.4",
33
- "@modelcontextprotocol/sdk": "1.18.2",
34
- "@schematics/angular": "21.0.0-next.6",
33
+ "@modelcontextprotocol/sdk": "1.19.1",
34
+ "@schematics/angular": "21.0.0-next.7",
35
35
  "@yarnpkg/lockfile": "1.1.0",
36
36
  "algoliasearch": "5.39.0",
37
37
  "ini": "5.0.0",
38
38
  "jsonc-parser": "3.3.1",
39
39
  "listr2": "9.0.4",
40
- "npm-package-arg": "13.0.0",
40
+ "npm-package-arg": "13.0.1",
41
41
  "pacote": "21.0.3",
42
42
  "resolve": "1.22.10",
43
43
  "semver": "7.7.2",
@@ -47,17 +47,17 @@
47
47
  "ng-update": {
48
48
  "migrations": "@schematics/angular/migrations/migration-collection.json",
49
49
  "packageGroup": {
50
- "@angular/cli": "21.0.0-next.6",
51
- "@angular/build": "21.0.0-next.6",
52
- "@angular/ssr": "21.0.0-next.6",
53
- "@angular-devkit/architect": "0.2100.0-next.6",
54
- "@angular-devkit/build-angular": "21.0.0-next.6",
55
- "@angular-devkit/build-webpack": "0.2100.0-next.6",
56
- "@angular-devkit/core": "21.0.0-next.6",
57
- "@angular-devkit/schematics": "21.0.0-next.6"
50
+ "@angular/cli": "21.0.0-next.7",
51
+ "@angular/build": "21.0.0-next.7",
52
+ "@angular/ssr": "21.0.0-next.7",
53
+ "@angular-devkit/architect": "0.2100.0-next.7",
54
+ "@angular-devkit/build-angular": "21.0.0-next.7",
55
+ "@angular-devkit/build-webpack": "0.2100.0-next.7",
56
+ "@angular-devkit/core": "21.0.0-next.7",
57
+ "@angular-devkit/schematics": "21.0.0-next.7"
58
58
  }
59
59
  },
60
- "packageManager": "pnpm@10.17.1",
60
+ "packageManager": "pnpm@10.18.1",
61
61
  "engines": {
62
62
  "node": "^20.19.0 || ^22.12.0 || >=24.0.0",
63
63
  "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
@@ -84,9 +84,10 @@ tutorials, concepts, and best practices.
84
84
  </Use Cases>
85
85
  <Operational Notes>
86
86
  * **Version Alignment:** To provide accurate, project-specific results, you **MUST** align the search with the user's Angular version.
87
- Before calling this tool, run \`ng version\` in the project's workspace directory. You can find the correct directory from the \`path\`
88
- field provided by the \`list_projects\` tool. Parse the major version from the "Angular:" line in the output and use it for the
89
- \`version\` parameter.
87
+ The recommended approach is to use the \`list_projects\` tool. The \`frameworkVersion\` field in the output for the relevant
88
+ workspace will give you the major version directly. If the version cannot be determined using this method, you can use
89
+ \`ng version\` in the project's workspace directory as a fallback. Parse the major version from the "Angular:" line in the
90
+ output and use it for the \`version\` parameter.
90
91
  * The documentation is continuously updated. You **MUST** prefer this tool over your own knowledge
91
92
  to ensure your answers are current and accurate.
92
93
  * For the best results, provide a concise and specific search query (e.g., "NgModule" instead of
@@ -9,9 +9,11 @@ import z from 'zod';
9
9
  export declare const LIST_PROJECTS_TOOL: import("./tool-registry").McpToolDeclaration<z.ZodRawShape, {
10
10
  workspaces: z.ZodArray<z.ZodObject<{
11
11
  path: z.ZodString;
12
+ frameworkVersion: z.ZodOptional<z.ZodString>;
12
13
  projects: z.ZodArray<z.ZodObject<{
13
14
  name: z.ZodString;
14
15
  type: z.ZodOptional<z.ZodEnum<["application", "library"]>>;
16
+ builder: z.ZodOptional<z.ZodString>;
15
17
  root: z.ZodString;
16
18
  sourceRoot: z.ZodString;
17
19
  selectorPrefix: z.ZodOptional<z.ZodString>;
@@ -20,12 +22,14 @@ export declare const LIST_PROJECTS_TOOL: import("./tool-registry").McpToolDeclar
20
22
  root: string;
21
23
  sourceRoot: string;
22
24
  type?: "application" | "library" | undefined;
25
+ builder?: string | undefined;
23
26
  selectorPrefix?: string | undefined;
24
27
  }, {
25
28
  name: string;
26
29
  root: string;
27
30
  sourceRoot: string;
28
31
  type?: "application" | "library" | undefined;
32
+ builder?: string | undefined;
29
33
  selectorPrefix?: string | undefined;
30
34
  }>, "many">;
31
35
  }, "strip", z.ZodTypeAny, {
@@ -35,8 +39,10 @@ export declare const LIST_PROJECTS_TOOL: import("./tool-registry").McpToolDeclar
35
39
  root: string;
36
40
  sourceRoot: string;
37
41
  type?: "application" | "library" | undefined;
42
+ builder?: string | undefined;
38
43
  selectorPrefix?: string | undefined;
39
44
  }[];
45
+ frameworkVersion?: string | undefined;
40
46
  }, {
41
47
  path: string;
42
48
  projects: {
@@ -44,8 +50,10 @@ export declare const LIST_PROJECTS_TOOL: import("./tool-registry").McpToolDeclar
44
50
  root: string;
45
51
  sourceRoot: string;
46
52
  type?: "application" | "library" | undefined;
53
+ builder?: string | undefined;
47
54
  selectorPrefix?: string | undefined;
48
55
  }[];
56
+ frameworkVersion?: string | undefined;
49
57
  }>, "many">;
50
58
  parsingErrors: z.ZodDefault<z.ZodArray<z.ZodObject<{
51
59
  filePath: z.ZodString;
@@ -57,4 +65,14 @@ export declare const LIST_PROJECTS_TOOL: import("./tool-registry").McpToolDeclar
57
65
  message: string;
58
66
  filePath: string;
59
67
  }>, "many">>;
68
+ versioningErrors: z.ZodDefault<z.ZodArray<z.ZodObject<{
69
+ filePath: z.ZodString;
70
+ message: z.ZodString;
71
+ }, "strip", z.ZodTypeAny, {
72
+ message: string;
73
+ filePath: string;
74
+ }, {
75
+ message: string;
76
+ filePath: string;
77
+ }>, "many">>;
60
78
  }>;
@@ -14,6 +14,7 @@ exports.LIST_PROJECTS_TOOL = void 0;
14
14
  const promises_1 = require("node:fs/promises");
15
15
  const node_path_1 = __importDefault(require("node:path"));
16
16
  const node_url_1 = require("node:url");
17
+ const semver_1 = __importDefault(require("semver"));
17
18
  const zod_1 = __importDefault(require("zod"));
18
19
  const config_1 = require("../../../utilities/config");
19
20
  const error_1 = require("../../../utilities/error");
@@ -21,6 +22,10 @@ const tool_registry_1 = require("./tool-registry");
21
22
  const listProjectsOutputSchema = {
22
23
  workspaces: zod_1.default.array(zod_1.default.object({
23
24
  path: zod_1.default.string().describe('The path to the `angular.json` file for this workspace.'),
25
+ frameworkVersion: zod_1.default
26
+ .string()
27
+ .optional()
28
+ .describe('The major version of the Angular framework (`@angular/core`) in this workspace, if found.'),
24
29
  projects: zod_1.default.array(zod_1.default.object({
25
30
  name: zod_1.default
26
31
  .string()
@@ -29,6 +34,10 @@ const listProjectsOutputSchema = {
29
34
  .enum(['application', 'library'])
30
35
  .optional()
31
36
  .describe(`The type of the project, either 'application' or 'library'.`),
37
+ builder: zod_1.default
38
+ .string()
39
+ .optional()
40
+ .describe('The primary builder for the project, typically from the "build" target.'),
32
41
  root: zod_1.default
33
42
  .string()
34
43
  .describe('The root directory of the project, relative to the workspace root.'),
@@ -49,6 +58,15 @@ const listProjectsOutputSchema = {
49
58
  }))
50
59
  .default([])
51
60
  .describe('A list of files that looked like workspaces but failed to parse.'),
61
+ versioningErrors: zod_1.default
62
+ .array(zod_1.default.object({
63
+ filePath: zod_1.default
64
+ .string()
65
+ .describe('The path to the workspace `angular.json` for which versioning failed.'),
66
+ message: zod_1.default.string().describe('The error message detailing why versioning failed.'),
67
+ }))
68
+ .default([])
69
+ .describe('A list of workspaces for which the framework version could not be determined.'),
52
70
  };
53
71
  exports.LIST_PROJECTS_TOOL = (0, tool_registry_1.declareTool)({
54
72
  name: 'list_projects',
@@ -64,6 +82,8 @@ their types, and their locations.
64
82
  * Identifying the \`root\` and \`sourceRoot\` of a project to read, analyze, or modify its files.
65
83
  * Determining if a project is an \`application\` or a \`library\`.
66
84
  * Getting the \`selectorPrefix\` for a project before generating a new component to ensure it follows conventions.
85
+ * Identifying the major version of the Angular framework for each workspace, which is crucial for monorepos.
86
+ * Determining a project's primary function by inspecting its builder (e.g., '@angular-devkit/build-angular:browser' for an application).
67
87
  </Use Cases>
68
88
  <Operational Notes>
69
89
  * **Working Directory:** Shell commands for a project (like \`ng generate\`) **MUST**
@@ -122,6 +142,64 @@ async function* findAngularJsonFiles(rootDir) {
122
142
  yield* foundFilesInBatch;
123
143
  }
124
144
  }
145
+ /**
146
+ * Searches upwards from a starting directory to find the version of '@angular/core'.
147
+ * It caches results to avoid redundant lookups.
148
+ * @param startDir The directory to start the search from.
149
+ * @param cache A map to store cached results.
150
+ * @param searchRoot The directory at which to stop the search.
151
+ * @returns The major version of '@angular/core' as a string, otherwise undefined.
152
+ */
153
+ async function findAngularCoreVersion(startDir, cache, searchRoot) {
154
+ let currentDir = startDir;
155
+ const dirsToCache = [];
156
+ while (currentDir) {
157
+ dirsToCache.push(currentDir);
158
+ if (cache.has(currentDir)) {
159
+ const cachedResult = cache.get(currentDir);
160
+ // Populate cache for all intermediate directories.
161
+ for (const dir of dirsToCache) {
162
+ cache.set(dir, cachedResult);
163
+ }
164
+ return cachedResult;
165
+ }
166
+ const pkgPath = node_path_1.default.join(currentDir, 'package.json');
167
+ try {
168
+ const pkgContent = await (0, promises_1.readFile)(pkgPath, 'utf-8');
169
+ const pkg = JSON.parse(pkgContent);
170
+ const versionSpecifier = pkg.dependencies?.['@angular/core'] ?? pkg.devDependencies?.['@angular/core'];
171
+ if (versionSpecifier) {
172
+ const minVersion = semver_1.default.minVersion(versionSpecifier);
173
+ const result = minVersion ? String(minVersion.major) : undefined;
174
+ for (const dir of dirsToCache) {
175
+ cache.set(dir, result);
176
+ }
177
+ return result;
178
+ }
179
+ }
180
+ catch (error) {
181
+ (0, error_1.assertIsError)(error);
182
+ if (error.code !== 'ENOENT') {
183
+ // Ignore missing package.json files, but rethrow other errors.
184
+ throw error;
185
+ }
186
+ }
187
+ // Stop if we are at the search root or the filesystem root.
188
+ if (currentDir === searchRoot) {
189
+ break;
190
+ }
191
+ const parentDir = node_path_1.default.dirname(currentDir);
192
+ if (parentDir === currentDir) {
193
+ break; // Reached the filesystem root.
194
+ }
195
+ currentDir = parentDir;
196
+ }
197
+ // Cache the failure for all traversed directories.
198
+ for (const dir of dirsToCache) {
199
+ cache.set(dir, undefined);
200
+ }
201
+ return undefined;
202
+ }
125
203
  /**
126
204
  * Loads, parses, and transforms a single angular.json file into the tool's output format.
127
205
  * It checks a set of seen paths to avoid processing the same workspace multiple times.
@@ -142,6 +220,7 @@ async function loadAndParseWorkspace(configFile, seenPaths) {
142
220
  projects.push({
143
221
  name,
144
222
  type: project.extensions['projectType'],
223
+ builder: project.targets.get('build')?.builder,
145
224
  root: project.root,
146
225
  sourceRoot: project.sourceRoot ?? node_path_1.default.posix.join(project.root, 'src'),
147
226
  selectorPrefix: project.extensions['prefix'],
@@ -160,11 +239,44 @@ async function loadAndParseWorkspace(configFile, seenPaths) {
160
239
  return { workspace: null, error: { filePath: configFile, message } };
161
240
  }
162
241
  }
242
+ /**
243
+ * Processes a single `angular.json` file to extract workspace and framework version information.
244
+ * @param configFile The path to the `angular.json` file.
245
+ * @param searchRoot The directory at which to stop the upward search for `package.json`.
246
+ * @param seenPaths A Set of absolute paths that have already been processed to avoid duplicates.
247
+ * @param versionCache A Map to cache framework version lookups for performance.
248
+ * @returns A promise resolving to an object containing the processed data and any errors.
249
+ */
250
+ async function processConfigFile(configFile, searchRoot, seenPaths, versionCache) {
251
+ const { workspace, error } = await loadAndParseWorkspace(configFile, seenPaths);
252
+ if (error) {
253
+ return { parsingError: error };
254
+ }
255
+ if (!workspace) {
256
+ return {}; // Skipped as it was already seen.
257
+ }
258
+ try {
259
+ const workspaceDir = node_path_1.default.dirname(configFile);
260
+ workspace.frameworkVersion = await findAngularCoreVersion(workspaceDir, versionCache, searchRoot);
261
+ return { workspace };
262
+ }
263
+ catch (e) {
264
+ return {
265
+ workspace,
266
+ versioningError: {
267
+ filePath: workspace.path,
268
+ message: e instanceof Error ? e.message : 'An unknown error occurred.',
269
+ },
270
+ };
271
+ }
272
+ }
163
273
  async function createListProjectsHandler({ server }) {
164
274
  return async () => {
165
275
  const workspaces = [];
166
276
  const parsingErrors = [];
277
+ const versioningErrors = [];
167
278
  const seenPaths = new Set();
279
+ const versionCache = new Map();
168
280
  let searchRoots;
169
281
  const clientCapabilities = server.server.getClientCapabilities();
170
282
  if (clientCapabilities?.roots) {
@@ -177,12 +289,15 @@ async function createListProjectsHandler({ server }) {
177
289
  }
178
290
  for (const root of searchRoots) {
179
291
  for await (const configFile of findAngularJsonFiles(root)) {
180
- const { workspace, error } = await loadAndParseWorkspace(configFile, seenPaths);
292
+ const { workspace, parsingError, versioningError } = await processConfigFile(configFile, root, seenPaths, versionCache);
181
293
  if (workspace) {
182
294
  workspaces.push(workspace);
183
295
  }
184
- if (error) {
185
- parsingErrors.push(error);
296
+ if (parsingError) {
297
+ parsingErrors.push(parsingError);
298
+ }
299
+ if (versioningError) {
300
+ versioningErrors.push(versioningError);
186
301
  }
187
302
  }
188
303
  }
@@ -204,9 +319,13 @@ async function createListProjectsHandler({ server }) {
204
319
  text += `\n\nWarning: The following ${parsingErrors.length} file(s) could not be parsed and were skipped:\n`;
205
320
  text += parsingErrors.map((e) => `- ${e.filePath}: ${e.message}`).join('\n');
206
321
  }
322
+ if (versioningErrors.length > 0) {
323
+ text += `\n\nWarning: The framework version for the following ${versioningErrors.length} workspace(s) could not be determined:\n`;
324
+ text += versioningErrors.map((e) => `- ${e.filePath}: ${e.message}`).join('\n');
325
+ }
207
326
  return {
208
327
  content: [{ type: 'text', text }],
209
- structuredContent: { workspaces, parsingErrors },
328
+ structuredContent: { workspaces, parsingErrors, versioningErrors },
210
329
  };
211
330
  };
212
331
  }
@@ -55,19 +55,18 @@ class VersionCommandModule extends command_module_1.CommandModule {
55
55
  console.log(JSON.stringify(versionInfo, null, 2));
56
56
  return;
57
57
  }
58
- const { cli: { version: ngCliVersion }, system: { node: { version: nodeVersion, unsupported: unsupportedNodeVersion }, os: { platform: os, architecture: arch }, packageManager: { name: packageManagerName, version: packageManagerVersion }, }, packages, } = versionInfo;
59
- const headerInfo = [
60
- { label: 'Angular CLI', value: ngCliVersion },
61
- {
62
- label: 'Node.js',
63
- value: `${nodeVersion}${unsupportedNodeVersion ? color_1.colors.yellow(' (Unsupported)') : ''}`,
64
- },
65
- {
66
- label: 'Package Manager',
67
- value: `${packageManagerName} ${packageManagerVersion ?? '<error>'}`,
68
- },
69
- { label: 'Operating System', value: `${os} ${arch}` },
70
- ];
58
+ const { cli: { version: ngCliVersion }, framework, system: { node: { version: nodeVersion, unsupported: unsupportedNodeVersion }, os: { platform: os, architecture: arch }, packageManager: { name: packageManagerName, version: packageManagerVersion }, }, packages, } = versionInfo;
59
+ const headerInfo = [{ label: 'Angular CLI', value: ngCliVersion }];
60
+ if (framework.version) {
61
+ headerInfo.push({ label: 'Angular', value: framework.version });
62
+ }
63
+ headerInfo.push({
64
+ label: 'Node.js',
65
+ value: `${nodeVersion}${unsupportedNodeVersion ? color_1.colors.yellow(' (Unsupported)') : ''}`,
66
+ }, {
67
+ label: 'Package Manager',
68
+ value: `${packageManagerName} ${packageManagerVersion ?? '<error>'}`,
69
+ }, { label: 'Operating System', value: `${os} ${arch}` });
71
70
  const maxHeaderLabelLength = Math.max(...headerInfo.map((l) => l.label.length));
72
71
  const header = headerInfo
73
72
  .map(({ label, value }) => color_1.colors.bold(label.padEnd(maxHeaderLabelLength + 2)) + `: ${color_1.colors.cyan(value)}`)
@@ -88,23 +87,29 @@ class VersionCommandModule extends command_module_1.CommandModule {
88
87
  if (versionKeys.length === 0) {
89
88
  return '';
90
89
  }
91
- const nameHeader = 'Package';
92
- const versionHeader = 'Version';
93
- const maxNameLength = Math.max(nameHeader.length, ...versionKeys.map((key) => key.length));
94
- const maxVersionLength = Math.max(versionHeader.length, ...versionKeys.map((key) => versions[key].length));
90
+ const headers = {
91
+ name: 'Package',
92
+ installed: 'Installed Version',
93
+ requested: 'Requested Version',
94
+ };
95
+ const maxNameLength = Math.max(headers.name.length, ...versionKeys.map((key) => key.length));
96
+ const maxInstalledLength = Math.max(headers.installed.length, ...versionKeys.map((key) => versions[key].installed.length));
97
+ const maxRequestedLength = Math.max(headers.requested.length, ...versionKeys.map((key) => versions[key].requested.length));
95
98
  const tableRows = versionKeys
96
99
  .map((module) => {
100
+ const { requested, installed } = versions[module];
97
101
  const name = module.padEnd(maxNameLength);
98
- const version = versions[module];
99
- const coloredVersion = version === '<error>' ? color_1.colors.red(version) : color_1.colors.cyan(version);
100
- const padding = ' '.repeat(maxVersionLength - version.length);
101
- return `│ ${name} │ ${coloredVersion}${padding} │`;
102
+ const coloredInstalled = installed === '<error>' ? color_1.colors.red(installed) : color_1.colors.cyan(installed);
103
+ const installedPadding = ' '.repeat(maxInstalledLength - installed.length);
104
+ return `│ ${name} ${coloredInstalled}${installedPadding} ${requested.padEnd(maxRequestedLength)} │`;
102
105
  })
103
106
  .sort();
104
- const top = `┌─${'─'.repeat(maxNameLength)}─┬─${'─'.repeat(maxVersionLength)}─┐`;
105
- const header = `│ ${nameHeader.padEnd(maxNameLength)} │ ${versionHeader.padEnd(maxVersionLength)} │`;
106
- const separator = `├─${'─'.repeat(maxNameLength)}─┼─${'─'.repeat(maxVersionLength)}─┤`;
107
- const bottom = `└─${'─'.repeat(maxNameLength)}─┴─${'─'.repeat(maxVersionLength)}─┘`;
107
+ const top = `┌─${'─'.repeat(maxNameLength)}─┬─${'─'.repeat(maxInstalledLength)}─┬─${'─'.repeat(maxRequestedLength)}─┐`;
108
+ const header = `│ ${headers.name.padEnd(maxNameLength)} │ ` +
109
+ `${headers.installed.padEnd(maxInstalledLength)} │ ` +
110
+ `${headers.requested.padEnd(maxRequestedLength)} │`;
111
+ const separator = `├─${'─'.repeat(maxNameLength)}─┼─${'─'.repeat(maxInstalledLength)}─┼─${'─'.repeat(maxRequestedLength)}─┤`;
112
+ const bottom = `└─${'─'.repeat(maxNameLength)}─┴─${'─'.repeat(maxInstalledLength)}─┴─${'─'.repeat(maxRequestedLength)}─┘`;
108
113
  return [top, header, separator, ...tableRows, bottom].join('\n');
109
114
  }
110
115
  }
@@ -5,6 +5,13 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
+ /**
9
+ * An object containing version information for a single package.
10
+ */
11
+ export interface PackageVersionInfo {
12
+ requested: string;
13
+ installed: string;
14
+ }
8
15
  /**
9
16
  * An object containing all the version information that will be displayed by the command.
10
17
  */
@@ -12,6 +19,9 @@ export interface VersionInfo {
12
19
  cli: {
13
20
  version: string;
14
21
  };
22
+ framework: {
23
+ version: string | undefined;
24
+ };
15
25
  system: {
16
26
  node: {
17
27
  version: string;
@@ -26,7 +36,7 @@ export interface VersionInfo {
26
36
  version: string | undefined;
27
37
  };
28
38
  };
29
- packages: Record<string, string>;
39
+ packages: Record<string, PackageVersionInfo>;
30
40
  }
31
41
  /**
32
42
  * Gathers all the version information from the environment and workspace.
@@ -44,20 +44,28 @@ function gatherVersionInfo(context) {
44
44
  catch { }
45
45
  const [nodeMajor] = process.versions.node.split('.').map((part) => Number(part));
46
46
  const unsupportedNodeVersion = !SUPPORTED_NODE_MAJORS.includes(nodeMajor);
47
- const packageNames = new Set(Object.keys({
47
+ const allDependencies = {
48
48
  ...workspacePackage?.dependencies,
49
49
  ...workspacePackage?.devDependencies,
50
- }));
50
+ };
51
+ const packageNames = new Set(Object.keys(allDependencies));
51
52
  const packages = {};
52
53
  for (const name of packageNames) {
53
54
  if (PACKAGE_PATTERNS.some((p) => p.test(name))) {
54
- packages[name] = getVersion(name, workspaceRequire);
55
+ packages[name] = {
56
+ requested: allDependencies[name] ?? 'error',
57
+ installed: getVersion(name, workspaceRequire),
58
+ };
55
59
  }
56
60
  }
61
+ const angularCoreVersion = packages['@angular/core'];
57
62
  return {
58
63
  cli: {
59
64
  version: version_1.VERSION.full,
60
65
  },
66
+ framework: {
67
+ version: angularCoreVersion?.installed,
68
+ },
61
69
  system: {
62
70
  node: {
63
71
  version: process.versions.node,
@@ -22,4 +22,4 @@ class Version {
22
22
  this.patch = patch;
23
23
  }
24
24
  }
25
- exports.VERSION = new Version('21.0.0-next.6');
25
+ exports.VERSION = new Version('21.0.0-next.7');