mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-25 16:57:51 +08:00
refactor(@schematics/angular): remove migrations for version 14
This migrations are no longer needed as multiple versions update is not allowed.
This commit is contained in:
parent
4de9045de8
commit
71ff22cc0c
@ -1,34 +1,3 @@
|
|||||||
{
|
{
|
||||||
"schematics": {
|
"schematics": {}
|
||||||
"update-angular-packages-version-prefix": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/angular-packages-version-prefix",
|
|
||||||
"description": "Update Angular packages 'dependencies' and 'devDependencies' version prefix to '^' instead of '~'."
|
|
||||||
},
|
|
||||||
"update-tsconfig-target": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/update-tsconfig-target",
|
|
||||||
"description": "Update TypeScript compilation target to 'ES2020'."
|
|
||||||
},
|
|
||||||
"remove-show-circular-dependencies-option": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/remove-show-circular-dependencies-option",
|
|
||||||
"description": "Remove 'showCircularDependencies' option from browser and server builders."
|
|
||||||
},
|
|
||||||
"remove-default-project-option": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/remove-default-project-option",
|
|
||||||
"description": "Remove 'defaultProject' option from workspace configuration. The project to use will be determined from the current working directory."
|
|
||||||
},
|
|
||||||
"replace-default-collection-option": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/replace-default-collection-option",
|
|
||||||
"description": "Replace 'defaultCollection' option in workspace configuration with 'schematicCollections'."
|
|
||||||
},
|
|
||||||
"update-libraries-secondary-entrypoints": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"factory": "./update-14/update-libraries-secondary-entrypoints",
|
|
||||||
"description": "Remove 'package.json' files from library projects secondary entrypoints."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 } from '@angular-devkit/schematics';
|
|
||||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
|
||||||
import { NodeDependencyType } from '../../utility/dependencies';
|
|
||||||
import { JSONFile } from '../../utility/json-file';
|
|
||||||
|
|
||||||
const PACKAGES_REGEXP = /^@(?:angular|nguniversal|schematics|angular-devkit)\/|^ng-packagr$/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migrations updates Angular packages 'dependencies' and 'devDependencies' version prefix to '^' instead of '~'.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* **Before**
|
|
||||||
* ```json
|
|
||||||
* dependencies: {
|
|
||||||
* "@angular/animations": "~13.1.0",
|
|
||||||
* "@angular/common": "~13.1.0"
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* **After**
|
|
||||||
* ```json
|
|
||||||
* dependencies: {
|
|
||||||
* "@angular/animations": "^13.1.0",
|
|
||||||
* "@angular/common": "^13.1.0"
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export default function (): Rule {
|
|
||||||
return (tree, context) => {
|
|
||||||
const json = new JSONFile(tree, '/package.json');
|
|
||||||
updateVersionPrefixToTilde(json, NodeDependencyType.Default);
|
|
||||||
updateVersionPrefixToTilde(json, NodeDependencyType.Dev);
|
|
||||||
|
|
||||||
context.addTask(new NodePackageInstallTask());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateVersionPrefixToTilde(json: JSONFile, dependencyType: NodeDependencyType): void {
|
|
||||||
const dependencyTypePath = [dependencyType];
|
|
||||||
const dependencies = json.get(dependencyTypePath);
|
|
||||||
|
|
||||||
if (!dependencies || typeof dependencies !== 'object') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedDependencies = new Map<string, string>();
|
|
||||||
for (const [name, version] of Object.entries(dependencies)) {
|
|
||||||
if (typeof version === 'string' && version.charAt(0) === '~' && PACKAGES_REGEXP.test(name)) {
|
|
||||||
updatedDependencies.set(name, `^${version.substring(1)}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedDependencies.size) {
|
|
||||||
json.modify(dependencyTypePath, {
|
|
||||||
...dependencies,
|
|
||||||
...Object.fromEntries(updatedDependencies),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,153 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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';
|
|
||||||
|
|
||||||
describe('Migration to update Angular packages version prefix to `^` instead of `~`', () => {
|
|
||||||
const packageJsonPath = '/package.json';
|
|
||||||
const schematicName = 'update-angular-packages-version-prefix';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should replace Angular packages versioned with '~' to '^'`, async () => {
|
|
||||||
tree.create(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify({
|
|
||||||
dependencies: {
|
|
||||||
'@angular/animations': '~13.1.0',
|
|
||||||
'@angular/common': '~13.1.0',
|
|
||||||
'@angular/compiler': '~13.1.0',
|
|
||||||
'@angular/core': '~13.1.0',
|
|
||||||
'@angular/forms': '~13.1.0',
|
|
||||||
'@angular/platform-browser': '~13.1.0',
|
|
||||||
'@angular/platform-browser-dynamic': '~13.1.0',
|
|
||||||
'@angular/router': '~13.1.0',
|
|
||||||
'@nguniversal/commom': '^13.1.0',
|
|
||||||
'rxjs': '~7.4.0',
|
|
||||||
'tslib': '^2.3.0',
|
|
||||||
'zone.js': '~0.11.4',
|
|
||||||
},
|
|
||||||
devDependencies: {
|
|
||||||
'@angular-devkit/build-angular': '~13.1.3',
|
|
||||||
'@angular/cli': '~13.1.3',
|
|
||||||
'@angular/compiler-cli': '~13.1.0',
|
|
||||||
'@angular/localize': '^13.1.3',
|
|
||||||
'@types/jasmine': '~3.10.0',
|
|
||||||
'@types/node': '^14.15.0',
|
|
||||||
'jasmine-core': '~3.10.0',
|
|
||||||
'karma': '~6.3.0',
|
|
||||||
'karma-chrome-launcher': '~3.1.0',
|
|
||||||
'karma-coverage': '~2.1.0',
|
|
||||||
'karma-jasmine': '~4.0.0',
|
|
||||||
'karma-jasmine-html-reporter': '~1.7.0',
|
|
||||||
'ng-packagr': '~13.1.3',
|
|
||||||
'typescript': '~4.5.2',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const pkg = JSON.parse(newTree.readContent(packageJsonPath));
|
|
||||||
|
|
||||||
expect(pkg['dependencies']).toEqual({
|
|
||||||
'@angular/animations': '^13.1.0',
|
|
||||||
'@angular/common': '^13.1.0',
|
|
||||||
'@angular/compiler': '^13.1.0',
|
|
||||||
'@angular/core': '^13.1.0',
|
|
||||||
'@angular/forms': '^13.1.0',
|
|
||||||
'@angular/platform-browser': '^13.1.0',
|
|
||||||
'@angular/platform-browser-dynamic': '^13.1.0',
|
|
||||||
'@angular/router': '^13.1.0',
|
|
||||||
'@nguniversal/commom': '^13.1.0',
|
|
||||||
'rxjs': '~7.4.0',
|
|
||||||
'tslib': '^2.3.0',
|
|
||||||
'zone.js': '~0.11.4',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(pkg['devDependencies']).toEqual({
|
|
||||||
'@angular-devkit/build-angular': '^13.1.3',
|
|
||||||
'@angular/cli': '^13.1.3',
|
|
||||||
'@angular/compiler-cli': '^13.1.0',
|
|
||||||
'@angular/localize': '^13.1.3',
|
|
||||||
'@types/jasmine': '~3.10.0',
|
|
||||||
'@types/node': '^14.15.0',
|
|
||||||
'jasmine-core': '~3.10.0',
|
|
||||||
'karma': '~6.3.0',
|
|
||||||
'karma-chrome-launcher': '~3.1.0',
|
|
||||||
'karma-coverage': '~2.1.0',
|
|
||||||
'karma-jasmine': '~4.0.0',
|
|
||||||
'karma-jasmine-html-reporter': '~1.7.0',
|
|
||||||
'ng-packagr': '^13.1.3',
|
|
||||||
'typescript': '~4.5.2',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not replace pinned Angular packages versions', async () => {
|
|
||||||
tree.create(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify({
|
|
||||||
dependencies: {
|
|
||||||
'@angular/animations': '13.1.0',
|
|
||||||
'@angular/core': '~13.1.0',
|
|
||||||
},
|
|
||||||
devDependencies: {
|
|
||||||
'@angular-devkit/build-angular': '13.1.3',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const pkg = JSON.parse(newTree.readContent(packageJsonPath));
|
|
||||||
|
|
||||||
expect(pkg['dependencies']['@angular/animations']).toBe('13.1.0');
|
|
||||||
expect(pkg['dependencies']['@angular/core']).toBe('^13.1.0');
|
|
||||||
expect(pkg['devDependencies']['@angular-devkit/build-angular']).toBe('13.1.3');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not error when `dependencies` is missing', async () => {
|
|
||||||
tree.create(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify({
|
|
||||||
devDependencies: {
|
|
||||||
'@angular-devkit/build-angular': '~13.1.3',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const pkg = JSON.parse(newTree.readContent(packageJsonPath));
|
|
||||||
|
|
||||||
expect(pkg['dependencies']).toBeUndefined();
|
|
||||||
expect(pkg['devDependencies']['@angular-devkit/build-angular']).toBe('^13.1.3');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not error when `devDependencies` is missing', async () => {
|
|
||||||
tree.create(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify({
|
|
||||||
dependencies: {
|
|
||||||
'@angular-devkit/build-angular': '~13.1.3',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const pkg = JSON.parse(newTree.readContent(packageJsonPath));
|
|
||||||
|
|
||||||
expect(pkg['dependencies']['@angular-devkit/build-angular']).toBe('^13.1.3');
|
|
||||||
expect(pkg['devDependencies']).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,17 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 } from '@angular-devkit/schematics';
|
|
||||||
import { updateWorkspace } from '../../utility/workspace';
|
|
||||||
|
|
||||||
/** Migration to remove 'defaultProject' option from angular.json. */
|
|
||||||
export default function (): Rule {
|
|
||||||
return updateWorkspace((workspace) => {
|
|
||||||
delete workspace.extensions['defaultProject'];
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { WorkspaceSchema } from '../../utility/workspace-models';
|
|
||||||
|
|
||||||
describe(`Migration to remove 'defaultProject' option.`, () => {
|
|
||||||
const schematicName = 'remove-default-project-option';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should remove 'defaultProject'`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {},
|
|
||||||
defaultProject: 'foo',
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { defaultProject } = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(defaultProject).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not error when 'defaultProject' is not defined`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { defaultProject } = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(defaultProject).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 } from '@angular-devkit/schematics';
|
|
||||||
import { allTargetOptions, updateWorkspace } from '../../utility/workspace';
|
|
||||||
|
|
||||||
/** Migration to remove 'showCircularDependencies' option from browser and server builders. */
|
|
||||||
export default function (): Rule {
|
|
||||||
return updateWorkspace((workspace) => {
|
|
||||||
for (const project of workspace.projects.values()) {
|
|
||||||
for (const target of project.targets.values()) {
|
|
||||||
if (
|
|
||||||
target.builder === '@angular-devkit/build-angular:server' ||
|
|
||||||
target.builder === '@angular-devkit/build-angular:browser'
|
|
||||||
) {
|
|
||||||
for (const [, options] of allTargetOptions(target)) {
|
|
||||||
delete options.showCircularDependencies;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { JsonObject } from '@angular-devkit/core';
|
|
||||||
import { EmptyTree } from '@angular-devkit/schematics';
|
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
|
||||||
import {
|
|
||||||
BuilderTarget,
|
|
||||||
Builders,
|
|
||||||
ProjectType,
|
|
||||||
WorkspaceSchema,
|
|
||||||
} from '../../utility/workspace-models';
|
|
||||||
|
|
||||||
function getBuildTarget(tree: UnitTestTree): BuilderTarget<Builders.Browser, JsonObject> {
|
|
||||||
return JSON.parse(tree.readContent('/angular.json')).projects.app.architect.build;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWorkSpaceConfig(tree: UnitTestTree) {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {
|
|
||||||
app: {
|
|
||||||
root: '',
|
|
||||||
sourceRoot: 'src',
|
|
||||||
projectType: ProjectType.Application,
|
|
||||||
prefix: 'app',
|
|
||||||
architect: {
|
|
||||||
build: {
|
|
||||||
builder: Builders.Browser,
|
|
||||||
options: {
|
|
||||||
extractCss: false,
|
|
||||||
showCircularDependencies: true,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
} as any,
|
|
||||||
configurations: {
|
|
||||||
one: {
|
|
||||||
showCircularDependencies: false,
|
|
||||||
aot: true,
|
|
||||||
},
|
|
||||||
two: {
|
|
||||||
showCircularDependencies: false,
|
|
||||||
aot: true,
|
|
||||||
},
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
} as any,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
describe(`Migration to remove 'showCircularDependencies' option.`, () => {
|
|
||||||
const schematicName = 'remove-show-circular-dependencies-option';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
createWorkSpaceConfig(tree);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should remove 'showCircularDependencies'`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { options, configurations } = getBuildTarget(newTree);
|
|
||||||
|
|
||||||
expect(options.showCircularDependencies).toBeUndefined();
|
|
||||||
expect(configurations).toBeDefined();
|
|
||||||
expect(configurations?.one.showCircularDependencies).toBeUndefined();
|
|
||||||
expect(configurations?.two.showCircularDependencies).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { JsonValue, isJsonObject } from '@angular-devkit/core';
|
|
||||||
import { Rule } from '@angular-devkit/schematics';
|
|
||||||
import { updateWorkspace } from '../../utility/workspace';
|
|
||||||
|
|
||||||
/** Migration to replace 'defaultCollection' option in angular.json. */
|
|
||||||
export default function (): Rule {
|
|
||||||
return updateWorkspace((workspace) => {
|
|
||||||
// workspace level
|
|
||||||
replaceDefaultCollection(workspace.extensions['cli']);
|
|
||||||
|
|
||||||
// Project level
|
|
||||||
for (const project of workspace.projects.values()) {
|
|
||||||
replaceDefaultCollection(project.extensions['cli']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceDefaultCollection(cliExtension: JsonValue | undefined): void {
|
|
||||||
if (cliExtension && isJsonObject(cliExtension) && cliExtension['defaultCollection']) {
|
|
||||||
// If `schematicsCollection` defined `defaultCollection` is ignored hence no need to warn.
|
|
||||||
if (!cliExtension['schematicCollections']) {
|
|
||||||
cliExtension['schematicCollections'] = [cliExtension['defaultCollection']];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete cliExtension['defaultCollection'];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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';
|
|
||||||
|
|
||||||
describe(`Migration to replace 'defaultCollection' option.`, () => {
|
|
||||||
const schematicName = 'replace-default-collection-option';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should replace 'defaultCollection' with 'schematicCollections' at the root level`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {},
|
|
||||||
cli: {
|
|
||||||
defaultCollection: 'foo',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { cli } = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(cli.defaultCollection).toBeUndefined();
|
|
||||||
expect(cli.schematicCollections).toEqual(['foo']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not error when 'cli' is not defined`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { cli } = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(cli).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should replace 'defaultCollection' with 'schematicCollections' at the project level`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
cli: {
|
|
||||||
defaultCollection: 'foo',
|
|
||||||
},
|
|
||||||
projects: {
|
|
||||||
test: {
|
|
||||||
sourceRoot: '',
|
|
||||||
root: '',
|
|
||||||
prefix: '',
|
|
||||||
projectType: ProjectType.Application,
|
|
||||||
cli: {
|
|
||||||
defaultCollection: 'bar',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const {
|
|
||||||
projects: { test },
|
|
||||||
} = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(test.cli.defaultCollection).toBeUndefined();
|
|
||||||
expect(test.cli.schematicCollections).toEqual(['bar']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not replace 'defaultCollection' with 'schematicCollections', when it is already defined`, async () => {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {},
|
|
||||||
cli: {
|
|
||||||
defaultCollection: 'foo',
|
|
||||||
schematicCollections: ['bar'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { cli } = JSON.parse(newTree.readContent('/angular.json'));
|
|
||||||
|
|
||||||
expect(cli.defaultCollection).toBeUndefined();
|
|
||||||
expect(cli.schematicCollections).toEqual(['bar']);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { dirname, isJsonObject, join, normalize } from '@angular-devkit/core';
|
|
||||||
import { DirEntry, Rule } from '@angular-devkit/schematics';
|
|
||||||
import { getWorkspace } from '../../utility/workspace';
|
|
||||||
|
|
||||||
function* visitPackageJsonFiles(
|
|
||||||
directory: DirEntry,
|
|
||||||
includedInLookup = false,
|
|
||||||
): IterableIterator<string> {
|
|
||||||
if (includedInLookup) {
|
|
||||||
for (const path of directory.subfiles) {
|
|
||||||
if (path !== 'package.json') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield join(directory.path, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const path of directory.subdirs) {
|
|
||||||
if (path === 'node_modules' || path.startsWith('.')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield* visitPackageJsonFiles(directory.dir(path), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Migration to remove secondary entrypoints 'package.json' files and migrate ng-packagr configurations. */
|
|
||||||
export default function (): Rule {
|
|
||||||
return async (tree) => {
|
|
||||||
const workspace = await getWorkspace(tree);
|
|
||||||
|
|
||||||
for (const project of workspace.projects.values()) {
|
|
||||||
if (
|
|
||||||
project.extensions['projectType'] !== 'library' ||
|
|
||||||
![...project.targets.values()].some(
|
|
||||||
({ builder }) => builder === '@angular-devkit/build-angular:ng-packagr',
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// Project is not a library or doesn't use ng-packagr, skip.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const path of visitPackageJsonFiles(tree.getDir(project.root))) {
|
|
||||||
const json = tree.readJson(path);
|
|
||||||
if (isJsonObject(json) && json['ngPackage']) {
|
|
||||||
// Migrate ng-packagr config to an ng-packagr config file.
|
|
||||||
const configFilePath = join(dirname(normalize(path)), 'ng-package.json');
|
|
||||||
tree.create(configFilePath, JSON.stringify(json['ngPackage'], undefined, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete package.json as it is no longer needed in APF 14.
|
|
||||||
tree.delete(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
|
|
||||||
|
|
||||||
function createFileStructure(tree: UnitTestTree) {
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {
|
|
||||||
foo: {
|
|
||||||
root: 'projects/foo',
|
|
||||||
sourceRoot: 'projects/foo/src',
|
|
||||||
projectType: ProjectType.Library,
|
|
||||||
prefix: 'lib',
|
|
||||||
architect: {
|
|
||||||
build: {
|
|
||||||
builder: Builders.NgPackagr,
|
|
||||||
options: {
|
|
||||||
project: '',
|
|
||||||
tsConfig: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
bar: {
|
|
||||||
root: 'projects/bar',
|
|
||||||
sourceRoot: 'projects/bar/src',
|
|
||||||
projectType: ProjectType.Library,
|
|
||||||
prefix: 'lib',
|
|
||||||
architect: {
|
|
||||||
test: {
|
|
||||||
builder: Builders.Karma,
|
|
||||||
options: {
|
|
||||||
karmaConfig: '',
|
|
||||||
tsConfig: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
|
|
||||||
|
|
||||||
// Library foo
|
|
||||||
tree.create('/projects/foo/package.json', JSON.stringify({ version: '0.0.0' }, undefined, 2));
|
|
||||||
// Library foo/secondary
|
|
||||||
tree.create(
|
|
||||||
'/projects/foo/secondary/package.json',
|
|
||||||
JSON.stringify(
|
|
||||||
{ version: '0.0.0', ngPackage: { lib: { entryFile: 'src/public-api.ts' } } },
|
|
||||||
undefined,
|
|
||||||
2,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Library bar
|
|
||||||
tree.create('/projects/bar/package.json', JSON.stringify({ version: '0.0.0' }, undefined, 2));
|
|
||||||
// Library bar/secondary
|
|
||||||
tree.create(
|
|
||||||
'/projects/bar/secondary/package.json',
|
|
||||||
JSON.stringify({ version: '0.0.0' }, undefined, 2),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe(`Migration to update Angular libraries secondary entrypoints.`, () => {
|
|
||||||
const schematicName = 'update-libraries-secondary-entrypoints';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
createFileStructure(tree);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(`when library has '@angular-devkit/build-angular:ng-packagr' as a builder`, () => {
|
|
||||||
it(`should not delete 'package.json' of primary entry-point`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
|
|
||||||
expect(newTree.exists('/projects/foo/package.json')).toBeTrue();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should delete 'package.json' of secondary entry-point`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
expect(newTree.exists('/projects/foo/secondary/package.json')).toBeFalse();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should move ng-packagr configuration from 'package.json' to 'ng-package.json'`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
expect(newTree.readJson('projects/foo/secondary/ng-package.json')).toEqual({
|
|
||||||
lib: { entryFile: 'src/public-api.ts' },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(`when library doesn't have '@angular-devkit/build-angular:ng-packagr' as a builder`, () => {
|
|
||||||
it(`should not delete 'package.json' of primary entry-point`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
expect(newTree.exists('/projects/bar/package.json')).toBeTrue();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not delete 'package.json' of secondary entry-point`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
expect(newTree.exists('/projects/bar/package.json')).toBeTrue();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not create ng-packagr configuration`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
expect(newTree.exists('projects/bar/secondary/ng-package.json')).toBeFalse();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 } from '@angular-devkit/schematics';
|
|
||||||
import { JSONFile } from '../../utility/json-file';
|
|
||||||
import { getWorkspace } from '../../utility/workspace';
|
|
||||||
import { Builders } from '../../utility/workspace-models';
|
|
||||||
|
|
||||||
/** Migration to update tsconfig compilation target option to es2020. */
|
|
||||||
export default function (): Rule {
|
|
||||||
return async (host) => {
|
|
||||||
/** Builders for which the migration will run. */
|
|
||||||
const supportedBuilders = [Builders.Karma, Builders.NgPackagr, Builders.Browser];
|
|
||||||
|
|
||||||
/** Compilation targets values that should not be amended. */
|
|
||||||
const skipTargets = ['es2020', 'es2021', 'es2022', 'esnext'];
|
|
||||||
|
|
||||||
const uniqueTsConfigs = new Set(['/tsconfig.json']);
|
|
||||||
|
|
||||||
// Find all tsconfig files which are refereced by the builders.
|
|
||||||
const workspace = await getWorkspace(host);
|
|
||||||
for (const project of workspace.projects.values()) {
|
|
||||||
for (const target of project.targets.values()) {
|
|
||||||
if (!supportedBuilders.includes(target.builder as Builders)) {
|
|
||||||
// Unknown builder.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all other known CLI builders that use a tsconfig.
|
|
||||||
const allOptions = [target.options ?? {}, ...Object.values(target.configurations ?? {})];
|
|
||||||
for (const opt of allOptions) {
|
|
||||||
if (typeof opt?.tsConfig === 'string') {
|
|
||||||
uniqueTsConfigs.add(opt.tsConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify tsconfig files
|
|
||||||
const targetJsonPath = ['compilerOptions', 'target'];
|
|
||||||
for (const tsConfigPath of uniqueTsConfigs) {
|
|
||||||
const json = new JSONFile(host, tsConfigPath);
|
|
||||||
const target = json.get(targetJsonPath);
|
|
||||||
|
|
||||||
// Update compilation target when it's current set lower than es2020.
|
|
||||||
if (typeof target === 'string' && !skipTargets.includes(target.toLowerCase())) {
|
|
||||||
json.modify(targetJsonPath, 'es2020');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,127 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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 { parse as parseJson } from 'jsonc-parser';
|
|
||||||
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
|
|
||||||
|
|
||||||
describe('Migration to update target compiler options', () => {
|
|
||||||
const schematicName = 'update-tsconfig-target';
|
|
||||||
const schematicRunner = new SchematicTestRunner(
|
|
||||||
'migrations',
|
|
||||||
require.resolve('../migration-collection.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
function createJsonFile(tree: UnitTestTree, filePath: string, content: {}) {
|
|
||||||
tree.create(filePath, JSON.stringify(content, undefined, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
function readJsonFile(tree: UnitTestTree, filePath: string): any {
|
|
||||||
return parseJson(tree.readContent(filePath).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new EmptyTree());
|
|
||||||
|
|
||||||
// Workspace configuration
|
|
||||||
const angularConfig: WorkspaceSchema = {
|
|
||||||
version: 1,
|
|
||||||
projects: {
|
|
||||||
app: {
|
|
||||||
root: '',
|
|
||||||
sourceRoot: 'src',
|
|
||||||
projectType: ProjectType.Application,
|
|
||||||
prefix: 'app',
|
|
||||||
architect: {
|
|
||||||
build: {
|
|
||||||
builder: Builders.Browser,
|
|
||||||
options: {
|
|
||||||
tsConfig: 'src/tsconfig.app.json',
|
|
||||||
main: '',
|
|
||||||
polyfills: '',
|
|
||||||
},
|
|
||||||
configurations: {
|
|
||||||
production: {
|
|
||||||
tsConfig: 'src/tsconfig.app.prod.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
test: {
|
|
||||||
builder: Builders.Karma,
|
|
||||||
options: {
|
|
||||||
karmaConfig: '',
|
|
||||||
tsConfig: 'src/tsconfig.spec.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
builder: Builders.Server,
|
|
||||||
options: {
|
|
||||||
tsConfig: 'src/tsconfig.server.json',
|
|
||||||
outputPath: '',
|
|
||||||
main: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
createJsonFile(tree, 'angular.json', angularConfig);
|
|
||||||
|
|
||||||
// Create tsconfigs
|
|
||||||
const compilerOptions = { target: 'es5', module: 'esnext' };
|
|
||||||
|
|
||||||
// Workspace
|
|
||||||
createJsonFile(tree, 'tsconfig.json', { compilerOptions });
|
|
||||||
|
|
||||||
// Application
|
|
||||||
createJsonFile(tree, 'src/tsconfig.app.json', { compilerOptions });
|
|
||||||
createJsonFile(tree, 'src/tsconfig.app.prod.json', { compilerOptions });
|
|
||||||
createJsonFile(tree, 'src/tsconfig.spec.json', { compilerOptions });
|
|
||||||
|
|
||||||
// Server
|
|
||||||
createJsonFile(tree, 'src/tsconfig.server.json', { compilerOptions });
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should update target in workspace 'tsconfig.json'`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { target } = readJsonFile(newTree, 'tsconfig.json').compilerOptions;
|
|
||||||
expect(target).toBe('es2020');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should update target in 'tsconfig.json' which is referenced in option`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { target } = readJsonFile(newTree, 'src/tsconfig.spec.json').compilerOptions;
|
|
||||||
expect(target).toBe('es2020');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should update target in 'tsconfig.json' which is referenced in a configuration`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { target } = readJsonFile(newTree, 'src/tsconfig.app.prod.json').compilerOptions;
|
|
||||||
expect(target).toBe('es2020');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should not update target in 'tsconfig.server.json'`, async () => {
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { target } = readJsonFile(newTree, 'src/tsconfig.server.json').compilerOptions;
|
|
||||||
expect(target).toBe('es5');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not update target if it is greater than es2020', async () => {
|
|
||||||
const tsConfigPath = 'src/tsconfig.app.json';
|
|
||||||
tree.delete(tsConfigPath);
|
|
||||||
createJsonFile(tree, tsConfigPath, { compilerOptions: { target: 'es2021' } });
|
|
||||||
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
|
|
||||||
const { target } = readJsonFile(newTree, tsConfigPath).compilerOptions;
|
|
||||||
expect(target).toBe('es2021');
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user