mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-25 00:31:36 +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": {
|
||||
"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."
|
||||
}
|
||||
}
|
||||
"schematics": {}
|
||||
}
|
||||
|
@ -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