@angular/cli 22.0.0-next.7 → 22.0.0-next.8
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/bin/ng.js +2 -2
- package/lib/config/schema.json +5 -0
- package/lib/config/workspace-schema.d.ts +4 -0
- package/package.json +16 -16
- package/src/commands/mcp/devserver.js +1 -1
- package/src/commands/mcp/devserver.js.map +1 -1
- package/src/commands/mcp/host.d.ts +8 -12
- package/src/commands/mcp/host.js +96 -11
- package/src/commands/mcp/host.js.map +1 -1
- package/src/commands/mcp/mcp-server.d.ts +0 -20
- package/src/commands/mcp/mcp-server.js +38 -9
- package/src/commands/mcp/mcp-server.js.map +1 -1
- package/src/commands/mcp/tools/build.js +2 -1
- package/src/commands/mcp/tools/build.js.map +1 -1
- package/src/commands/mcp/tools/devserver/devserver-start.js +1 -0
- package/src/commands/mcp/tools/devserver/devserver-start.js.map +1 -1
- package/src/commands/mcp/tools/devserver/devserver-stop.js +1 -0
- package/src/commands/mcp/tools/devserver/devserver-stop.js.map +1 -1
- package/src/commands/mcp/tools/devserver/devserver-wait-for-build.js +1 -0
- package/src/commands/mcp/tools/devserver/devserver-wait-for-build.js.map +1 -1
- package/src/commands/mcp/tools/e2e.js +2 -1
- package/src/commands/mcp/tools/e2e.js.map +1 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.d.ts +2 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.js +2 -2
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.js.map +1 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.d.ts +3 -2
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.js +8 -8
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.js.map +1 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.d.ts +2 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.js +2 -3
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.js.map +1 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.d.ts +2 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js +21 -21
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js.map +1 -1
- package/src/commands/mcp/tools/test.js +1 -1
- package/src/commands/mcp/tools/test.js.map +1 -1
- package/src/commands/mcp/workspace-utils.d.ts +2 -1
- package/src/commands/mcp/workspace-utils.js +43 -1
- package/src/commands/mcp/workspace-utils.js.map +1 -1
- package/src/package-managers/parsers.d.ts +0 -5
- package/src/package-managers/parsers.js +43 -1
- package/src/package-managers/parsers.js.map +1 -1
- package/src/utilities/node-version.js +1 -1
- package/src/utilities/version.js +1 -1
- package/src/commands/mcp/tools/modernize.d.ts +0 -43
- package/src/commands/mcp/tools/modernize.js +0 -165
- package/src/commands/mcp/tools/modernize.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["e2e.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAyBH,
|
|
1
|
+
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["e2e.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAyBH,wBA6CC;AApED,6BAAwB;AAExB,sDAA+D;AAC/D,oCAA8E;AAC9E,wDAAgE;AAChE,mDAA4F;AAE5F,MAAM,eAAe,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAGvD,MAAM,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IAClC,GAAG,2CAA0B;CAC9B,CAAC,CAAC;AAIH,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACzD,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;CAC5E,CAAC,CAAC;AAII,KAAK,UAAU,MAAM,CAAC,KAAmB,EAAE,IAAU,EAAE,OAAuB;IACnF,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,MAAM,IAAA,4CAA0B,EAAC;QACjF,IAAI;QACJ,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,kBAAkB,EAAE,KAAK,CAAC,SAAS;QACnC,gBAAgB,EAAE,KAAK,CAAC,OAAO;QAC/B,YAAY,EAAE,OAAO,CAAC,SAAS;KAChC,CAAC,CAAC;IAEH,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;QAC7B,+EAA+E;QAC/E,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC1D,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtC,OAAO,IAAA,qCAA6B,EAAC;oBACnC,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE;wBACJ,yCAAyC,WAAW,8BAA8B;4BAChF,uDAAuD;4BACvD,gDAAgD;qBACnD;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAElC,IAAI,MAAM,GAAc,SAAS,CAAC;IAClC,IAAI,IAAc,CAAC;IAEnB,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,SAAS,CAAC;QACnB,IAAI,GAAG,IAAA,2BAAmB,EAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,iBAAiB,GAAkB;QACvC,MAAM;QACN,IAAI;KACL,CAAC;IAEF,OAAO,IAAA,qCAA6B,EAAC,iBAAiB,CAAC,CAAC;AAC1D,CAAC;AAEY,QAAA,QAAQ,GAGjB,IAAA,2BAAW,EAAC;IACd,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,UAAU;IACjB,WAAW,EAAE;;;;;;;;;;;;CAYd;IACC,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,kBAAkB,CAAC,KAAK;IACrC,YAAY,EAAE,mBAAmB,CAAC,KAAK;IACvC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;CACtE,CAAC,CAAC"}
|
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol';
|
|
9
9
|
import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types';
|
|
10
10
|
import type { SourceFile } from 'typescript';
|
|
11
|
+
import type { Host } from '../../host';
|
|
11
12
|
import type { MigrationResponse } from './types';
|
|
12
|
-
export declare function migrateSingleFile(sourceFile: SourceFile, extras: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<MigrationResponse | null>;
|
|
13
|
+
export declare function migrateSingleFile(sourceFile: SourceFile, host: Host, extras: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<MigrationResponse | null>;
|
|
@@ -14,11 +14,11 @@ const prompts_1 = require("./prompts");
|
|
|
14
14
|
const send_debug_message_1 = require("./send-debug-message");
|
|
15
15
|
const ts_utils_1 = require("./ts-utils");
|
|
16
16
|
const supportedStrategies = new Set(['OnPush', 'Default', 'Eager']);
|
|
17
|
-
async function migrateSingleFile(sourceFile, extras) {
|
|
17
|
+
async function migrateSingleFile(sourceFile, host, extras) {
|
|
18
18
|
const testBedSpecifier = await (0, ts_utils_1.getImportSpecifier)(sourceFile, '@angular/core/testing', 'TestBed');
|
|
19
19
|
const isTestFile = sourceFile.fileName.endsWith('.spec.ts') || !!testBedSpecifier;
|
|
20
20
|
if (isTestFile) {
|
|
21
|
-
return (0, migrate_test_file_1.migrateTestFile)(sourceFile);
|
|
21
|
+
return (0, migrate_test_file_1.migrateTestFile)(sourceFile, host);
|
|
22
22
|
}
|
|
23
23
|
const unsupportedZoneUseResponse = await (0, analyze_for_unsupported_zone_uses_1.analyzeForUnsupportedZoneUses)(sourceFile);
|
|
24
24
|
if (unsupportedZoneUseResponse) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-single-file.js","sourceRoot":"","sources":["migrate-single-file.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"migrate-single-file.js","sourceRoot":"","sources":["migrate-single-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { SourceFile } from 'typescript';
|
|
9
|
+
import { type Host } from '../../host';
|
|
9
10
|
import { MigrationResponse } from './types';
|
|
10
|
-
export declare function migrateTestFile(sourceFile: SourceFile): Promise<MigrationResponse | null>;
|
|
11
|
-
export declare function searchForGlobalZoneless(startPath: string): Promise<boolean>;
|
|
11
|
+
export declare function migrateTestFile(sourceFile: SourceFile, host: Host): Promise<MigrationResponse | null>;
|
|
12
|
+
export declare function searchForGlobalZoneless(startPath: string, host: Host): Promise<boolean>;
|
|
@@ -9,15 +9,14 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.migrateTestFile = migrateTestFile;
|
|
11
11
|
exports.searchForGlobalZoneless = searchForGlobalZoneless;
|
|
12
|
-
const
|
|
13
|
-
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
14
13
|
const workspace_utils_1 = require("../../workspace-utils");
|
|
15
14
|
const prompts_1 = require("./prompts");
|
|
16
15
|
const ts_utils_1 = require("./ts-utils");
|
|
17
|
-
async function migrateTestFile(sourceFile) {
|
|
16
|
+
async function migrateTestFile(sourceFile, host) {
|
|
18
17
|
const ts = await (0, ts_utils_1.loadTypescript)();
|
|
19
18
|
// Check if tests use zoneless either by default through `initTestEnvironment` or by explicitly calling `provideZonelessChangeDetection`.
|
|
20
|
-
let testsUseZonelessChangeDetection = await searchForGlobalZoneless(sourceFile.fileName);
|
|
19
|
+
let testsUseZonelessChangeDetection = await searchForGlobalZoneless(sourceFile.fileName, host);
|
|
21
20
|
if (!testsUseZonelessChangeDetection) {
|
|
22
21
|
ts.forEachChild(sourceFile, function visit(node) {
|
|
23
22
|
if (ts.isCallExpression(node) &&
|
|
@@ -35,17 +34,18 @@ async function migrateTestFile(sourceFile) {
|
|
|
35
34
|
// At this point, tests are using zoneless, so we look for any explicit uses of `provideZoneChangeDetection` that need to be fixed.
|
|
36
35
|
return (0, prompts_1.createFixResponseForZoneTests)(sourceFile);
|
|
37
36
|
}
|
|
38
|
-
async function searchForGlobalZoneless(startPath) {
|
|
39
|
-
const angularJsonDir = (0, workspace_utils_1.findAngularJsonDir)(startPath);
|
|
37
|
+
async function searchForGlobalZoneless(startPath, host) {
|
|
38
|
+
const angularJsonDir = (0, workspace_utils_1.findAngularJsonDir)(startPath, host);
|
|
40
39
|
if (!angularJsonDir) {
|
|
41
40
|
// Cannot determine project root, fallback to original behavior or assume false.
|
|
42
41
|
// For now, let's assume no global setup if angular.json is not found.
|
|
43
42
|
return false;
|
|
44
43
|
}
|
|
45
44
|
try {
|
|
46
|
-
const files = (
|
|
45
|
+
const files = host.glob('**/*.ts', { cwd: angularJsonDir });
|
|
47
46
|
for await (const file of files) {
|
|
48
|
-
const
|
|
47
|
+
const fullPath = (0, node_path_1.join)(file.parentPath, file.name);
|
|
48
|
+
const content = await host.readFile(fullPath, 'utf-8');
|
|
49
49
|
if (content.includes('initTestEnvironment') &&
|
|
50
50
|
content.includes('provideZonelessChangeDetection')) {
|
|
51
51
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-test-file.js","sourceRoot":"","sources":["migrate-test-file.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"migrate-test-file.js","sourceRoot":"","sources":["migrate-test-file.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAUH,0CA4BC;AAED,0DAyBC;AA/DD,yCAAiC;AAGjC,2DAA2D;AAC3D,uCAAoG;AACpG,yCAA4C;AAGrC,KAAK,UAAU,eAAe,CACnC,UAAsB,EACtB,IAAU;IAEV,MAAM,EAAE,GAAG,MAAM,IAAA,yBAAc,GAAE,CAAC;IAClC,yIAAyI;IACzI,IAAI,+BAA+B,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC/F,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACrC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,KAAK,CAAC,IAAI;YAC7C,IACE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;gBACzB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,gCAAgC,EACxE,CAAC;gBACD,+BAA+B,GAAG,IAAI,CAAC;gBAEvC,OAAO;YACT,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACrC,sEAAsE;QACtE,OAAO,IAAA,kDAAwC,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvE,CAAC;IAED,mIAAmI;IACnI,OAAO,IAAA,uCAA6B,EAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAEM,KAAK,UAAU,uBAAuB,CAAC,SAAiB,EAAE,IAAU;IACzE,MAAM,cAAc,GAAG,IAAA,oCAAkB,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,gFAAgF;QAChF,sEAAsE;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC;QAC5D,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,IAAA,gBAAI,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACvD,IACE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;gBACvC,OAAO,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAClD,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type ts from 'typescript';
|
|
9
|
+
import type { Host } from '../../host';
|
|
9
10
|
export declare function loadTypescript(): Promise<typeof ts>;
|
|
10
11
|
/**
|
|
11
12
|
* Gets a top-level import specifier with a specific name that is imported from a particular module.
|
|
@@ -32,4 +33,4 @@ export declare function getImportSpecifier(sourceFile: ts.SourceFile, moduleName
|
|
|
32
33
|
*/
|
|
33
34
|
export declare function findImportSpecifier(nodes: ts.NodeArray<ts.ImportSpecifier>, specifierName: string): ts.ImportSpecifier | undefined;
|
|
34
35
|
/** Creates a TypeScript source file from a file path. */
|
|
35
|
-
export declare function createSourceFile(file: string): Promise<ts.SourceFile>;
|
|
36
|
+
export declare function createSourceFile(file: string, host: Host): Promise<ts.SourceFile>;
|
|
@@ -44,7 +44,6 @@ exports.loadTypescript = loadTypescript;
|
|
|
44
44
|
exports.getImportSpecifier = getImportSpecifier;
|
|
45
45
|
exports.findImportSpecifier = findImportSpecifier;
|
|
46
46
|
exports.createSourceFile = createSourceFile;
|
|
47
|
-
const node_fs_1 = require("node:fs");
|
|
48
47
|
let typescriptModule;
|
|
49
48
|
async function loadTypescript() {
|
|
50
49
|
return (typescriptModule ??= await Promise.resolve().then(() => __importStar(require('typescript'))));
|
|
@@ -128,8 +127,8 @@ function findImportSpecifier(nodes, specifierName) {
|
|
|
128
127
|
});
|
|
129
128
|
}
|
|
130
129
|
/** Creates a TypeScript source file from a file path. */
|
|
131
|
-
async function createSourceFile(file) {
|
|
132
|
-
const content =
|
|
130
|
+
async function createSourceFile(file, host) {
|
|
131
|
+
const content = await host.readFile(file, 'utf8');
|
|
133
132
|
const ts = await loadTypescript();
|
|
134
133
|
return ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true);
|
|
135
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-utils.js","sourceRoot":"","sources":["ts-utils.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,wCAEC;AAmBD,gDAQC;AAgED,kDASC;AAGD,4CAMC;
|
|
1
|
+
{"version":3,"file":"ts-utils.js","sourceRoot":"","sources":["ts-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol';
|
|
9
9
|
import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types';
|
|
10
10
|
import { z } from 'zod';
|
|
11
|
+
import type { Host } from '../../host';
|
|
11
12
|
export declare const ZONELESS_MIGRATION_TOOL: import("../tool-registry").McpToolDeclaration<{
|
|
12
13
|
fileOrDirPath: z.ZodString;
|
|
13
14
|
}, Readonly<{
|
|
14
15
|
[k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
15
16
|
}>>;
|
|
16
|
-
export declare function registerZonelessMigrationTool(fileOrDirPath: string, extras: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<import("./types").MigrationResponse>;
|
|
17
|
+
export declare function registerZonelessMigrationTool(fileOrDirPath: string, host: Host, extras: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<import("./types").MigrationResponse>;
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.ZONELESS_MIGRATION_TOOL = void 0;
|
|
11
11
|
exports.registerZonelessMigrationTool = registerZonelessMigrationTool;
|
|
12
|
-
const
|
|
13
|
-
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
14
13
|
const zod_1 = require("zod");
|
|
15
14
|
const tool_registry_1 = require("../tool-registry");
|
|
16
15
|
const analyze_for_unsupported_zone_uses_1 = require("./analyze-for-unsupported-zone-uses");
|
|
@@ -43,8 +42,8 @@ most important action to take in the migration journey.
|
|
|
43
42
|
* **Iterative Process:** The migration process is iterative. You must call this tool repeatedly,
|
|
44
43
|
applying the suggested fix after each call, until the tool indicates that no more actions are
|
|
45
44
|
needed.
|
|
46
|
-
* **Relationship to
|
|
47
|
-
migration. For other migrations (like signal inputs), you should
|
|
45
|
+
* **Relationship to other migrations:** This tool is the specialized starting point for the zoneless/OnPush
|
|
46
|
+
migration. For other migrations (like signal inputs), you should run the corresponding schematics first,
|
|
48
47
|
as the zoneless migration may depend on them as prerequisites.
|
|
49
48
|
* **Input:** The tool can operate on either a single file or an entire directory. Provide the
|
|
50
49
|
absolute path.
|
|
@@ -57,13 +56,13 @@ most important action to take in the migration journey.
|
|
|
57
56
|
.describe('The absolute path of the directory or file with the component(s), directive(s), or service(s) to migrate.' +
|
|
58
57
|
' The contents are read with fs.readFileSync.'),
|
|
59
58
|
},
|
|
60
|
-
factory: () => ({ fileOrDirPath }, requestHandlerExtra) => registerZonelessMigrationTool(fileOrDirPath, requestHandlerExtra),
|
|
59
|
+
factory: ({ host }) => ({ fileOrDirPath }, requestHandlerExtra) => registerZonelessMigrationTool(fileOrDirPath, host, requestHandlerExtra),
|
|
61
60
|
});
|
|
62
|
-
async function registerZonelessMigrationTool(fileOrDirPath, extras) {
|
|
61
|
+
async function registerZonelessMigrationTool(fileOrDirPath, host, extras) {
|
|
63
62
|
let filesWithComponents, componentTestFiles, zoneFiles, categorizationErrors;
|
|
64
63
|
try {
|
|
65
64
|
({ filesWithComponents, componentTestFiles, zoneFiles, categorizationErrors } =
|
|
66
|
-
await discoverAndCategorizeFiles(fileOrDirPath, extras));
|
|
65
|
+
await discoverAndCategorizeFiles(fileOrDirPath, host, extras));
|
|
67
66
|
}
|
|
68
67
|
catch (e) {
|
|
69
68
|
return (0, prompts_1.createResponse)(`Error: Could not access the specified path. Please ensure the following path is correct ` +
|
|
@@ -82,14 +81,14 @@ async function registerZonelessMigrationTool(fileOrDirPath, extras) {
|
|
|
82
81
|
? await rankComponentFilesForMigration(extras, Array.from(filesWithComponents))
|
|
83
82
|
: Array.from(filesWithComponents);
|
|
84
83
|
for (const file of rankedFiles) {
|
|
85
|
-
const result = await (0, migrate_single_file_1.migrateSingleFile)(file, extras);
|
|
84
|
+
const result = await (0, migrate_single_file_1.migrateSingleFile)(file, host, extras);
|
|
86
85
|
if (result !== null) {
|
|
87
86
|
return result;
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
for (const file of componentTestFiles) {
|
|
92
|
-
const result = await (0, migrate_test_file_1.migrateTestFile)(file);
|
|
91
|
+
const result = await (0, migrate_test_file_1.migrateTestFile)(file, host);
|
|
93
92
|
if (result !== null) {
|
|
94
93
|
return result;
|
|
95
94
|
}
|
|
@@ -101,7 +100,7 @@ async function registerZonelessMigrationTool(fileOrDirPath, extras) {
|
|
|
101
100
|
}
|
|
102
101
|
return (0, prompts_1.createTestDebuggingGuideForNonActionableInput)(fileOrDirPath);
|
|
103
102
|
}
|
|
104
|
-
async function discoverAndCategorizeFiles(fileOrDirPath, extras) {
|
|
103
|
+
async function discoverAndCategorizeFiles(fileOrDirPath, host, extras) {
|
|
105
104
|
const filePaths = [];
|
|
106
105
|
const componentTestFiles = new Set();
|
|
107
106
|
const filesWithComponents = new Set();
|
|
@@ -109,20 +108,21 @@ async function discoverAndCategorizeFiles(fileOrDirPath, extras) {
|
|
|
109
108
|
const categorizationErrors = [];
|
|
110
109
|
let isDirectory;
|
|
111
110
|
try {
|
|
112
|
-
isDirectory = (
|
|
111
|
+
isDirectory = (await host.stat(fileOrDirPath)).isDirectory();
|
|
113
112
|
}
|
|
114
113
|
catch (e) {
|
|
115
114
|
// Re-throw to be handled by the main function as a user input error
|
|
116
115
|
throw new Error(`Failed to access path: ${fileOrDirPath}`, { cause: e });
|
|
117
116
|
}
|
|
118
117
|
if (isDirectory) {
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
const files = host.glob('**/*.ts', { cwd: fileOrDirPath });
|
|
119
|
+
for await (const file of files) {
|
|
120
|
+
filePaths.push((0, node_path_1.join)(file.parentPath, file.name));
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
else {
|
|
124
124
|
filePaths.push(fileOrDirPath);
|
|
125
|
-
const maybeTestFile = await getTestFilePath(fileOrDirPath);
|
|
125
|
+
const maybeTestFile = await getTestFilePath(fileOrDirPath, host);
|
|
126
126
|
if (maybeTestFile) {
|
|
127
127
|
// Eagerly add the test file path for categorization.
|
|
128
128
|
filePaths.push(maybeTestFile);
|
|
@@ -133,8 +133,8 @@ async function discoverAndCategorizeFiles(fileOrDirPath, extras) {
|
|
|
133
133
|
while (filesToProcess.length > 0) {
|
|
134
134
|
const batch = filesToProcess.splice(0, CONCURRENCY_LIMIT);
|
|
135
135
|
const results = await Promise.allSettled(batch.map(async (filePath) => {
|
|
136
|
-
const sourceFile = await (0, ts_utils_1.createSourceFile)(filePath);
|
|
137
|
-
await categorizeFile(sourceFile, extras, {
|
|
136
|
+
const sourceFile = await (0, ts_utils_1.createSourceFile)(filePath, host);
|
|
137
|
+
await categorizeFile(sourceFile, host, extras, {
|
|
138
138
|
filesWithComponents,
|
|
139
139
|
componentTestFiles,
|
|
140
140
|
zoneFiles,
|
|
@@ -151,7 +151,7 @@ async function discoverAndCategorizeFiles(fileOrDirPath, extras) {
|
|
|
151
151
|
}
|
|
152
152
|
return { filesWithComponents, componentTestFiles, zoneFiles, categorizationErrors };
|
|
153
153
|
}
|
|
154
|
-
async function categorizeFile(sourceFile, extras, categorizedFiles) {
|
|
154
|
+
async function categorizeFile(sourceFile, host, extras, categorizedFiles) {
|
|
155
155
|
const { filesWithComponents, componentTestFiles, zoneFiles } = categorizedFiles;
|
|
156
156
|
const content = sourceFile.getFullText();
|
|
157
157
|
const componentSpecifier = await (0, ts_utils_1.getImportSpecifier)(sourceFile, '@angular/core', 'Component');
|
|
@@ -167,9 +167,9 @@ async function categorizeFile(sourceFile, extras, categorizedFiles) {
|
|
|
167
167
|
else {
|
|
168
168
|
(0, send_debug_message_1.sendDebugMessage)(`Component file already has change detection strategy: ${sourceFile.fileName}. Skipping migration.`, extras);
|
|
169
169
|
}
|
|
170
|
-
const testFilePath = await getTestFilePath(sourceFile.fileName);
|
|
170
|
+
const testFilePath = await getTestFilePath(sourceFile.fileName, host);
|
|
171
171
|
if (testFilePath) {
|
|
172
|
-
componentTestFiles.add(await (0, ts_utils_1.createSourceFile)(testFilePath));
|
|
172
|
+
componentTestFiles.add(await (0, ts_utils_1.createSourceFile)(testFilePath, host));
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
else if (zoneSpecifier) {
|
|
@@ -213,9 +213,9 @@ async function rankComponentFilesForMigration({ sendRequest }, componentFiles) {
|
|
|
213
213
|
catch { }
|
|
214
214
|
return componentFiles; // Fallback to original order if the response fails
|
|
215
215
|
}
|
|
216
|
-
async function getTestFilePath(filePath) {
|
|
216
|
+
async function getTestFilePath(filePath, host) {
|
|
217
217
|
const testFilePath = filePath.replace(/\.ts$/, '.spec.ts');
|
|
218
|
-
if (
|
|
218
|
+
if (host.existsSync(testFilePath)) {
|
|
219
219
|
return testFilePath;
|
|
220
220
|
}
|
|
221
221
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zoneless-migration.js","sourceRoot":"","sources":["zoneless-migration.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AA8DH,
|
|
1
|
+
{"version":3,"file":"zoneless-migration.js","sourceRoot":"","sources":["zoneless-migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,7 +49,7 @@ async function runTest(input, context) {
|
|
|
49
49
|
let status = 'success';
|
|
50
50
|
let logs;
|
|
51
51
|
try {
|
|
52
|
-
logs = (await context.host.
|
|
52
|
+
logs = (await context.host.executeNgCommand(args, { cwd: workspacePath })).logs;
|
|
53
53
|
}
|
|
54
54
|
catch (e) {
|
|
55
55
|
status = 'failure';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["test.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAiCH,0BAwCC;AAvED,6BAAwB;AACxB,sDAA+D;AAC/D,oCAA8E;AAC9E,wDAAgE;AAChE,mDAA4F;AAE5F,MAAM,gBAAgB,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAGxD,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,GAAG,2CAA0B;IAC7B,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;CAClF,CAAC,CAAC;AAIH,MAAM,oBAAoB,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAC3D,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;CAC7E,CAAC,CAAC;AAIH,SAAS,uBAAuB,CAC9B,UAAkF;IAElF,OAAO,CACL,UAAU,EAAE,OAAO,KAAK,0BAA0B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,KAAK,OAAO,CACjG,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,OAAO,CAAC,KAAoB,EAAE,OAAuB;IACzE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,MAAM,IAAA,4CAA0B,EAAC;QACjF,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,kBAAkB,EAAE,KAAK,CAAC,SAAS;QACnC,gBAAgB,EAAE,KAAK,CAAC,OAAO;QAC/B,YAAY,EAAE,OAAO,CAAC,SAAS;KAChC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEnC,IAAI,uBAAuB,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACtF,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,4FAA4F;QAC5F,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAE9B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,MAAM,GAAe,SAAS,CAAC;IACnC,IAAI,IAAc,CAAC;IAEnB,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["test.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAiCH,0BAwCC;AAvED,6BAAwB;AACxB,sDAA+D;AAC/D,oCAA8E;AAC9E,wDAAgE;AAChE,mDAA4F;AAE5F,MAAM,gBAAgB,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAGxD,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,GAAG,2CAA0B;IAC7B,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;CAClF,CAAC,CAAC;AAIH,MAAM,oBAAoB,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAC3D,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;CAC7E,CAAC,CAAC;AAIH,SAAS,uBAAuB,CAC9B,UAAkF;IAElF,OAAO,CACL,UAAU,EAAE,OAAO,KAAK,0BAA0B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,KAAK,OAAO,CACjG,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,OAAO,CAAC,KAAoB,EAAE,OAAuB;IACzE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,MAAM,IAAA,4CAA0B,EAAC;QACjF,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,kBAAkB,EAAE,KAAK,CAAC,SAAS;QACnC,gBAAgB,EAAE,KAAK,CAAC,OAAO;QAC/B,YAAY,EAAE,OAAO,CAAC,SAAS;KAChC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEnC,IAAI,uBAAuB,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACtF,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,4FAA4F;QAC5F,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAE9B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,MAAM,GAAe,SAAS,CAAC;IACnC,IAAI,IAAc,CAAC;IAEnB,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,SAAS,CAAC;QACnB,IAAI,GAAG,IAAA,2BAAmB,EAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,iBAAiB,GAAmB;QACxC,MAAM;QACN,IAAI;KACL,CAAC;IAEF,OAAO,IAAA,qCAA6B,EAAC,iBAAiB,CAAC,CAAC;AAC1D,CAAC;AAEY,QAAA,SAAS,GAGlB,IAAA,2BAAW,EAAC;IACd,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,WAAW;IAClB,WAAW,EAAE;;;;;;;;;;;;;;CAcd;IACC,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,mBAAmB,CAAC,KAAK;IACtC,YAAY,EAAE,oBAAoB,CAAC,KAAK;IACxC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC;CACzD,CAAC,CAAC"}
|
|
@@ -41,8 +41,9 @@ export declare function getDefaultProjectName(workspace: AngularWorkspace | unde
|
|
|
41
41
|
* current directory as the workspace.
|
|
42
42
|
* If `projectNameInput` is absent, uses the default project in the workspace.
|
|
43
43
|
*/
|
|
44
|
-
export declare function resolveWorkspaceAndProject({ host, workspacePathInput, projectNameInput, mcpWorkspace, }: {
|
|
44
|
+
export declare function resolveWorkspaceAndProject({ host, server, workspacePathInput, projectNameInput, mcpWorkspace, }: {
|
|
45
45
|
host: Host;
|
|
46
|
+
server?: McpToolContext['server'];
|
|
46
47
|
workspacePathInput?: string;
|
|
47
48
|
projectNameInput?: string;
|
|
48
49
|
mcpWorkspace?: AngularWorkspace;
|
|
@@ -11,7 +11,9 @@ exports.findAngularJsonDir = findAngularJsonDir;
|
|
|
11
11
|
exports.getProject = getProject;
|
|
12
12
|
exports.getDefaultProjectName = getDefaultProjectName;
|
|
13
13
|
exports.resolveWorkspaceAndProject = resolveWorkspaceAndProject;
|
|
14
|
+
const node_fs_1 = require("node:fs");
|
|
14
15
|
const node_path_1 = require("node:path");
|
|
16
|
+
const node_url_1 = require("node:url");
|
|
15
17
|
const config_1 = require("../../utilities/config");
|
|
16
18
|
const host_1 = require("./host");
|
|
17
19
|
/**
|
|
@@ -71,6 +73,36 @@ function getDefaultProjectName(workspace) {
|
|
|
71
73
|
}
|
|
72
74
|
return undefined;
|
|
73
75
|
}
|
|
76
|
+
function isWithinAllowedRoot(root, targetPath) {
|
|
77
|
+
const rel = (0, node_path_1.relative)(root, targetPath);
|
|
78
|
+
return !rel.startsWith('..') && !(0, node_path_1.isAbsolute)(rel);
|
|
79
|
+
}
|
|
80
|
+
async function getAllowedWorkspaceRoots(server) {
|
|
81
|
+
let roots;
|
|
82
|
+
const clientCapabilities = server.server.getClientCapabilities();
|
|
83
|
+
if (clientCapabilities?.roots) {
|
|
84
|
+
const { roots: clientRoots } = await server.server.listRoots();
|
|
85
|
+
roots = clientRoots?.map((root) => (0, node_url_1.fileURLToPath)(root.uri)) ?? [];
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
roots = [process.cwd()];
|
|
89
|
+
}
|
|
90
|
+
return roots
|
|
91
|
+
.map((root) => {
|
|
92
|
+
try {
|
|
93
|
+
return (0, node_fs_1.realpathSync)(root);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
.filter((root) => root !== null);
|
|
100
|
+
}
|
|
101
|
+
async function isAllowedWorkspacePath(server, workspacePath) {
|
|
102
|
+
const allowedRoots = await getAllowedWorkspaceRoots(server);
|
|
103
|
+
const resolvedWorkspacePath = (0, node_fs_1.realpathSync)(workspacePath);
|
|
104
|
+
return allowedRoots.some((root) => isWithinAllowedRoot(root, resolvedWorkspacePath));
|
|
105
|
+
}
|
|
74
106
|
/**
|
|
75
107
|
* Resolves workspace and project for tools to operate on.
|
|
76
108
|
*
|
|
@@ -78,7 +110,7 @@ function getDefaultProjectName(workspace) {
|
|
|
78
110
|
* current directory as the workspace.
|
|
79
111
|
* If `projectNameInput` is absent, uses the default project in the workspace.
|
|
80
112
|
*/
|
|
81
|
-
async function resolveWorkspaceAndProject({ host, workspacePathInput, projectNameInput, mcpWorkspace, }) {
|
|
113
|
+
async function resolveWorkspaceAndProject({ host, server, workspacePathInput, projectNameInput, mcpWorkspace, }) {
|
|
82
114
|
let workspacePath;
|
|
83
115
|
let workspace;
|
|
84
116
|
if (workspacePathInput) {
|
|
@@ -90,6 +122,12 @@ async function resolveWorkspaceAndProject({ host, workspacePathInput, projectNam
|
|
|
90
122
|
throw new Error(`No angular.json found at ${workspacePathInput}. ` +
|
|
91
123
|
"You can use 'list_projects' to find available workspaces.");
|
|
92
124
|
}
|
|
125
|
+
if (server) {
|
|
126
|
+
if (!(await isAllowedWorkspacePath(server, workspacePathInput))) {
|
|
127
|
+
throw new Error(`Workspace path is outside the allowed MCP roots: ${workspacePathInput}. ` +
|
|
128
|
+
"You can use 'list_projects' to find available workspaces.");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
93
131
|
workspacePath = workspacePathInput;
|
|
94
132
|
const configPath = (0, node_path_1.join)(workspacePath, 'angular.json');
|
|
95
133
|
try {
|
|
@@ -109,6 +147,10 @@ async function resolveWorkspaceAndProject({ host, workspacePathInput, projectNam
|
|
|
109
147
|
throw new Error('Could not find an Angular workspace (angular.json) in the current directory. ' +
|
|
110
148
|
"You can use 'list_projects' to find available workspaces.");
|
|
111
149
|
}
|
|
150
|
+
if (server && !(await isAllowedWorkspacePath(server, found))) {
|
|
151
|
+
throw new Error(`The current directory resolves to a workspace outside the allowed MCP roots: ${found}. ` +
|
|
152
|
+
"You can use 'list_projects' to find available workspaces.");
|
|
153
|
+
}
|
|
112
154
|
workspacePath = found;
|
|
113
155
|
const configPath = (0, node_path_1.join)(workspacePath, 'angular.json');
|
|
114
156
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-utils.js","sourceRoot":"","sources":["workspace-utils.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"workspace-utils.js","sourceRoot":"","sources":["workspace-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,11 +5,6 @@
|
|
|
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
|
-
* @fileoverview This file contains the parser functions that are used to
|
|
10
|
-
* interpret the output of various package manager commands. Separating these
|
|
11
|
-
* into their own file improves modularity and allows for focused testing.
|
|
12
|
-
*/
|
|
13
8
|
import { ErrorInfo } from './error';
|
|
14
9
|
import { Logger } from './logger';
|
|
15
10
|
import { PackageManifest, PackageMetadata } from './package-metadata';
|
|
@@ -17,6 +17,12 @@ exports.parseNpmLikeError = parseNpmLikeError;
|
|
|
17
17
|
exports.parseYarnClassicError = parseYarnClassicError;
|
|
18
18
|
exports.parseBunDependencies = parseBunDependencies;
|
|
19
19
|
exports.parseYarnModernDependencies = parseYarnModernDependencies;
|
|
20
|
+
/**
|
|
21
|
+
* @fileoverview This file contains the parser functions that are used to
|
|
22
|
+
* interpret the output of various package manager commands. Separating these
|
|
23
|
+
* into their own file improves modularity and allows for focused testing.
|
|
24
|
+
*/
|
|
25
|
+
const semver_1 = require("semver");
|
|
20
26
|
const MAX_LOG_LENGTH = 1024;
|
|
21
27
|
function logStdout(stdout, logger) {
|
|
22
28
|
if (!logger) {
|
|
@@ -172,6 +178,15 @@ function parseYarnClassicDependencies(stdout, logger) {
|
|
|
172
178
|
logger?.debug(` Found ${dependencies.size} dependencies.`);
|
|
173
179
|
return dependencies;
|
|
174
180
|
}
|
|
181
|
+
function isValidManifest(obj) {
|
|
182
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const record = obj;
|
|
186
|
+
const name = record.name;
|
|
187
|
+
const version = record.version;
|
|
188
|
+
return typeof name === 'string' && typeof version === 'string' && (0, semver_1.valid)(version) !== null;
|
|
189
|
+
}
|
|
175
190
|
/**
|
|
176
191
|
* Parses the output of `npm view` or a compatible command to get a package manifest.
|
|
177
192
|
* @param stdout The standard output of the command.
|
|
@@ -186,7 +201,30 @@ function parseNpmLikeManifest(stdout, logger) {
|
|
|
186
201
|
return null;
|
|
187
202
|
}
|
|
188
203
|
const result = JSON.parse(stdout);
|
|
189
|
-
|
|
204
|
+
// npm view returns an array of manifests if the query matches multiple versions
|
|
205
|
+
// (e.g. when using a version range). We find the highest version to ensure
|
|
206
|
+
// we get the latest relevant manifest, even if the output is not sorted.
|
|
207
|
+
if (Array.isArray(result)) {
|
|
208
|
+
let maxManifest = null;
|
|
209
|
+
for (const manifest of result) {
|
|
210
|
+
if (!isValidManifest(manifest)) {
|
|
211
|
+
logger?.debug(' Skipping invalid manifest in array (missing name, version, or invalid SemVer).');
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (!maxManifest || (0, semver_1.compare)(manifest.version, maxManifest.version) > 0) {
|
|
215
|
+
maxManifest = manifest;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!maxManifest) {
|
|
219
|
+
logger?.debug(' No valid manifests found in the array.');
|
|
220
|
+
}
|
|
221
|
+
return maxManifest;
|
|
222
|
+
}
|
|
223
|
+
if (!isValidManifest(result)) {
|
|
224
|
+
logger?.debug(' Parsed JSON is not a valid manifest (missing name, version, or invalid SemVer).');
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
190
228
|
}
|
|
191
229
|
/**
|
|
192
230
|
* Parses the output of `npm view` or a compatible command to get package metadata.
|
|
@@ -247,6 +285,10 @@ function parseYarnClassicManifest(stdout, logger) {
|
|
|
247
285
|
Object.keys(manifest['ng-add']).length === 0) {
|
|
248
286
|
manifest['ng-add'].save ??= false;
|
|
249
287
|
}
|
|
288
|
+
if (!isValidManifest(manifest)) {
|
|
289
|
+
logger?.debug(' Parsed JSON is not a valid manifest (missing name, version, or invalid SemVer).');
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
250
292
|
return manifest;
|
|
251
293
|
}
|
|
252
294
|
/**
|