From dc6b6eaf6f8af0d2b3f31cea77dc9a63ff845e3c Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 2 Oct 2023 09:03:54 +0000 Subject: [PATCH] feat(@schematics/angular): add migration to replace usages of `@nguniversal/builders` This migration replaces usages of `@nguniversal/builders` with `@angular-devkit/build-angular`. --- .../migrations/migration-collection.json | 8 +- .../update-17/replace-nguniversal-builders.ts | 47 ++++++++ .../replace-nguniversal-builders_spec.ts | 111 ++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 packages/schematics/angular/migrations/update-17/replace-nguniversal-builders.ts create mode 100644 packages/schematics/angular/migrations/update-17/replace-nguniversal-builders_spec.ts diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json index 63001b445889..a354c9b0b682 100644 --- a/packages/schematics/angular/migrations/migration-collection.json +++ b/packages/schematics/angular/migrations/migration-collection.json @@ -1,3 +1,9 @@ { - "schematics": {} + "schematics": { + "replace-nguniversal-builders": { + "version": "17.0.0", + "factory": "./update-17/replace-nguniversal-builders", + "description": "Replace usages of '@nguniversal/builders' with '@angular-devkit/build-angular'." + } + } } diff --git a/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders.ts b/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders.ts new file mode 100644 index 000000000000..c150e8c27f44 --- /dev/null +++ b/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders.ts @@ -0,0 +1,47 @@ +/** + * @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.io/license + */ + +import { Rule, chain } from '@angular-devkit/schematics'; +import { removePackageJsonDependency } from '../../utility/dependencies'; +import { allTargetOptions, updateWorkspace } from '../../utility/workspace'; +import { ProjectType } from '../../utility/workspace-models'; + +export default function (): Rule { + return chain([ + updateWorkspace((workspace) => { + for (const [, project] of workspace.projects) { + if (project.extensions.projectType !== ProjectType.Application) { + // Only interested in application projects since these changes only effects application builders + continue; + } + + for (const [, target] of project.targets) { + if (target.builder === '@nguniversal/builders:ssr-dev-server') { + target.builder = '@angular-devkit/build-angular:ssr-dev-server'; + } else if (target.builder === '@nguniversal/builders:prerender') { + target.builder = '@angular-devkit/build-angular:prerender'; + for (const [, options] of allTargetOptions(target, false)) { + // Remove and replace builder options + if (options['guessRoutes'] !== undefined) { + options['discoverRoutes'] = options['guessRoutes']; + delete options['guessRoutes']; + } + + if (options['numProcesses'] !== undefined) { + delete options['numProcesses']; + } + } + } + } + } + }), + (host) => { + removePackageJsonDependency(host, '@nguniversal/builders'); + }, + ]); +} diff --git a/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders_spec.ts b/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders_spec.ts new file mode 100644 index 000000000000..ea46bd888fa9 --- /dev/null +++ b/packages/schematics/angular/migrations/update-17/replace-nguniversal-builders_spec.ts @@ -0,0 +1,111 @@ +/** + * @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.io/license + */ + +import { EmptyTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import { ProjectType, WorkspaceSchema } from '../../utility/workspace-models'; + +function createWorkSpaceConfig(tree: UnitTestTree) { + const angularConfig: WorkspaceSchema = { + version: 1, + projects: { + app: { + root: '/project/lib', + sourceRoot: '/project/app/src', + projectType: ProjectType.Application, + prefix: 'app', + architect: { + 'serve-ssr': { + builder: '@nguniversal/builders:ssr-dev-server', + options: { + browserTarget: 'appprerender:build', + serverTarget: 'appprerender:server', + }, + configurations: { + production: { + browserTarget: 'appprerender:build:production', + serverTarget: 'appprerender:server:production', + }, + }, + }, + prerender: { + builder: '@nguniversal/builders:prerender', + options: { + browserTarget: 'appprerender:build:production', + serverTarget: 'appprerender:server:production', + numProcesses: 1, + guessRoutes: false, + }, + }, + }, + }, + }, + }; + + tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2)); +} + +describe(`Migration to replace '@nguniversal/builders' with '@angular-devkit/build-angular'`, () => { + const schematicName = 'replace-nguniversal-builders'; + + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + createWorkSpaceConfig(tree); + tree.create( + '/package.json', + JSON.stringify( + { + devDependencies: { + '@nguniversal/builders': '0.0.0', + }, + }, + undefined, + 2, + ), + ); + }); + + it(`should remove '@nguniversal/builders' from devDependencies`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { devDependencies } = JSON.parse(newTree.readContent('/package.json')); + expect(devDependencies['@nguniversal/builders']).toBeUndefined(); + }); + + it(`should replace '@nguniversal/builders:ssr-dev-server' target`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { + projects: { app }, + } = JSON.parse(newTree.readContent('/angular.json')); + expect(app.architect['serve-ssr'].builder).toBe('@angular-devkit/build-angular:ssr-dev-server'); + }); + + it(`should replace '@nguniversal/builders:prerender' target`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { + projects: { app }, + } = JSON.parse(newTree.readContent('/angular.json')); + expect(app.architect['prerender'].builder).toBe('@angular-devkit/build-angular:prerender'); + }); + + it(`should replace old '@nguniversal/builders:prerender' options`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { + projects: { app }, + } = JSON.parse(newTree.readContent('/angular.json')); + const { guessRoutes, numProcesses, discoverRoutes } = app.architect['prerender'].options; + expect(guessRoutes).toBeUndefined(); + expect(discoverRoutes).toBeFalse(); + expect(numProcesses).toBeUndefined(); + }); +});