UNPKG

@angular/cli

Version:
136 lines (135 loc) 6.6 kB
"use strict"; /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MODERNIZE_TOOL = void 0; exports.runModernization = runModernization; const zod_1 = require("zod"); const tool_registry_1 = require("./tool-registry"); const TRANSFORMATIONS = [ { name: 'control-flow-migration', description: 'Migrates from `*ngIf`, `*ngFor`, and `*ngSwitch` to the new `@if`, `@for`, and `@switch` block syntax in templates.', documentationUrl: 'https://angular.dev/reference/migrations/control-flow', }, { name: 'self-closing-tags-migration', description: 'Converts tags for elements with no content to be self-closing (e.g., `<app-foo></app-foo>` becomes `<app-foo />`).', documentationUrl: 'https://angular.dev/reference/migrations/self-closing-tags', }, { name: 'test-bed-get', description: 'Updates `TestBed.get` to the preferred and type-safe `TestBed.inject` in TypeScript test files.', documentationUrl: 'https://angular.dev/guide/testing/dependency-injection', }, { name: 'inject', description: 'Converts usages of constructor-based injection to the inject() function.', documentationUrl: 'https://angular.dev/reference/migrations/inject-function', }, { name: 'output-migration', description: 'Converts `@Output` declarations to the new functional `output()` syntax.', documentationUrl: 'https://angular.dev/reference/migrations/outputs', }, { name: 'signal-input-migration', description: 'Migrates `@Input` declarations to the new signal-based `input()` syntax.', documentationUrl: 'https://angular.dev/reference/migrations/signal-inputs', }, { name: 'signal-queries-migration', description: 'Migrates `@ViewChild` and `@ContentChild` queries to their signal-based `viewChild` and `contentChild` versions.', documentationUrl: 'https://angular.dev/reference/migrations/signal-queries', }, { name: 'standalone', description: 'Converts the application to use standalone components, directives, and pipes. This is a ' + 'three-step process. After each step, you should verify that your application builds and ' + 'runs correctly.', instructions: 'This migration requires running a cli schematic multiple times. Run the commands in the ' + 'order listed below, verifying that your code builds and runs between each step:\n\n' + '1. Run `ng g @angular/core:standalone` and select "Convert all components, directives and pipes to standalone"\n' + '2. Run `ng g @angular/core:standalone` and select "Remove unnecessary NgModule classes"\n' + '3. Run `ng g @angular/core:standalone` and select "Bootstrap the project using standalone APIs"', documentationUrl: 'https://angular.dev/reference/migrations/standalone', }, { name: 'zoneless', description: 'Migrates the application to be zoneless.', documentationUrl: 'https://angular.dev/guide/zoneless', }, ]; const modernizeInputSchema = zod_1.z.object({ // Casting to [string, ...string[]] since the enum definition requires a nonempty array. transformations: zod_1.z .array(zod_1.z.enum(TRANSFORMATIONS.map((t) => t.name))) .optional(), }); function generateInstructions(transformationNames) { if (transformationNames.length === 0) { return [ 'See https://angular.dev/best-practices for Angular best practices. ' + 'You can call this tool if you have specific transformation you want to run.', ]; } const instructions = []; const transformationsToRun = TRANSFORMATIONS.filter((t) => transformationNames?.includes(t.name)); for (const transformation of transformationsToRun) { let transformationInstructions = ''; if (transformation.instructions) { transformationInstructions = transformation.instructions; } else { // If no instructions are included, default to running a cli schematic with the transformation name. const command = `ng generate @angular/core:${transformation.name}`; transformationInstructions = `To run the ${transformation.name} migration, execute the following command: \`${command}\`.`; } if (transformation.documentationUrl) { transformationInstructions += `\nFor more information, see ${transformation.documentationUrl}.`; } instructions.push(transformationInstructions); } return instructions; } async function runModernization(input) { const structuredContent = { instructions: generateInstructions(input.transformations ?? []) }; return { content: [{ type: 'text', text: JSON.stringify(structuredContent) }], structuredContent, }; } exports.MODERNIZE_TOOL = (0, tool_registry_1.declareTool)({ name: 'modernize', title: 'Modernize Angular Code', description: '<Purpose>\n' + 'This tool modernizes Angular code by applying the latest best practices and syntax improvements, ' + 'ensuring it is idiomatic, readable, and maintainable.\n\n' + '</Purpose>\n' + '<Use Cases>\n' + '* After generating new code: Run this tool immediately after creating new Angular components, directives, ' + 'or services to ensure they adhere to modern standards.\n' + '* On existing code: Apply to existing TypeScript files (.ts) and Angular templates (.html) to update ' + 'them with the latest features, such as the new built-in control flow syntax.\n\n' + '* When the user asks for a specific transformation: When the transformation list is populated, ' + 'these specific ones will be ran on the inputs.\n' + '</Use Cases>\n' + '<Transformations>\n' + TRANSFORMATIONS.map((t) => `* ${t.name}: ${t.description}`).join('\n') + '\n</Transformations>\n', inputSchema: modernizeInputSchema.shape, outputSchema: { instructions: zod_1.z .array(zod_1.z.string()) .optional() .describe('A list of instructions on how to run the migrations.'), }, isLocalOnly: true, isReadOnly: true, factory: () => (input) => runModernization(input), });