mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-15 01:54:04 +08:00
fix(@schematics/angular): support updating projects that use the targets property
This commit is contained in:
parent
307160806c
commit
38fda3ea60
@ -5,7 +5,7 @@
|
||||
* 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, dirname, join, normalize } from '@angular-devkit/core';
|
||||
import { JsonObject, dirname, experimental, join, normalize } from '@angular-devkit/core';
|
||||
import {
|
||||
Rule,
|
||||
SchematicContext,
|
||||
@ -15,10 +15,6 @@ import {
|
||||
schematic,
|
||||
} from '@angular-devkit/schematics';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
WorkspaceProject,
|
||||
WorkspaceTool,
|
||||
} from '../../../angular_devkit/core/src/workspace/workspace-schema';
|
||||
import { Schema as ComponentOptions } from '../component/schema';
|
||||
import {
|
||||
addImportToModule,
|
||||
@ -32,6 +28,7 @@ import {
|
||||
import { InsertChange } from '../utility/change';
|
||||
import { getWorkspace, getWorkspacePath } from '../utility/config';
|
||||
import { getAppModulePath } from '../utility/ng-ast-utils';
|
||||
import { getProjectTargets } from '../utility/project-targets';
|
||||
import { Schema as AppShellOptions } from './schema';
|
||||
|
||||
|
||||
@ -54,7 +51,9 @@ function getSourceFile(host: Tree, path: string): ts.SourceFile {
|
||||
}
|
||||
|
||||
function getServerModulePath(
|
||||
host: Tree, project: WorkspaceProject, architect: WorkspaceTool,
|
||||
host: Tree,
|
||||
project: experimental.workspace.WorkspaceProject,
|
||||
architect: experimental.workspace.WorkspaceTool,
|
||||
): string | null {
|
||||
const mainPath = architect.server.options.main;
|
||||
const mainSource = getSourceFile(host, mainPath);
|
||||
@ -102,11 +101,12 @@ function getComponentTemplate(host: Tree, compPath: string, tmplInfo: TemplateIn
|
||||
return template;
|
||||
}
|
||||
|
||||
function getBootstrapComponentPath(host: Tree, project: WorkspaceProject): string {
|
||||
if (!project.architect) {
|
||||
throw new Error('Project architect not found.');
|
||||
}
|
||||
const mainPath = project.architect.build.options.main;
|
||||
function getBootstrapComponentPath(
|
||||
host: Tree,
|
||||
project: experimental.workspace.WorkspaceProject,
|
||||
): string {
|
||||
const projectTargets = getProjectTargets(project);
|
||||
const mainPath = projectTargets.build.options.main;
|
||||
const modulePath = getAppModulePath(host, mainPath);
|
||||
const moduleSource = getSourceFile(host, modulePath);
|
||||
|
||||
@ -202,10 +202,8 @@ function addAppShellConfigToWorkspace(options: AppShellOptions): Rule {
|
||||
throw new SchematicsException(`Client app ${options.clientProject} not found.`);
|
||||
}
|
||||
const clientProject = workspace.projects[options.clientProject];
|
||||
if (!clientProject.architect) {
|
||||
throw new Error('Client project architect not found.');
|
||||
}
|
||||
clientProject.architect['app-shell'] = appShellTarget;
|
||||
const projectTargets = getProjectTargets(clientProject);
|
||||
projectTargets['app-shell'] = appShellTarget;
|
||||
|
||||
host.overwrite(workspacePath, JSON.stringify(workspace, null, 2));
|
||||
|
||||
@ -317,7 +315,9 @@ function addShellComponent(options: AppShellOptions): Rule {
|
||||
return schematic('component', componentOptions);
|
||||
}
|
||||
|
||||
function getClientProject(host: Tree, options: AppShellOptions): WorkspaceProject {
|
||||
function getClientProject(
|
||||
host: Tree, options: AppShellOptions,
|
||||
): experimental.workspace.WorkspaceProject {
|
||||
const workspace = getWorkspace(host);
|
||||
const clientProject = workspace.projects[options.clientProject];
|
||||
if (!clientProject) {
|
||||
@ -327,14 +327,13 @@ function getClientProject(host: Tree, options: AppShellOptions): WorkspaceProjec
|
||||
return clientProject;
|
||||
}
|
||||
|
||||
function getClientArchitect(host: Tree, options: AppShellOptions): WorkspaceTool {
|
||||
const clientArchitect = getClientProject(host, options).architect;
|
||||
function getClientArchitect(
|
||||
host: Tree, options: AppShellOptions,
|
||||
): experimental.workspace.WorkspaceTool {
|
||||
const clientProject = getClientProject(host, options);
|
||||
const projectTargets = getProjectTargets(clientProject);
|
||||
|
||||
if (!clientArchitect) {
|
||||
throw new Error('Client project architect not found.');
|
||||
}
|
||||
|
||||
return clientArchitect;
|
||||
return projectTargets;
|
||||
}
|
||||
|
||||
export default function (options: AppShellOptions): Rule {
|
||||
|
@ -65,7 +65,7 @@ describe('App Shell Schematic', () => {
|
||||
const filePath = '/angular.json';
|
||||
const content = tree.readContent(filePath);
|
||||
const workspace = JSON.parse(content);
|
||||
const target = workspace.projects.bar.architect['app-shell'];
|
||||
const target = workspace.projects.bar.targets['app-shell'];
|
||||
expect(target.options.browserTarget).toEqual('bar:build');
|
||||
expect(target.options.serverTarget).toEqual('bar:server');
|
||||
expect(target.options.route).toEqual('shell');
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
} from '../utility/config';
|
||||
import { addPackageJsonDependency, getPackageJsonDependency } from '../utility/dependencies';
|
||||
import { getAppModulePath } from '../utility/ng-ast-utils';
|
||||
import { getProjectTargets } from '../utility/project-targets';
|
||||
import { Schema as ServiceWorkerOptions } from './schema';
|
||||
|
||||
function updateConfigFile(options: ServiceWorkerOptions): Rule {
|
||||
@ -43,20 +44,18 @@ function updateConfigFile(options: ServiceWorkerOptions): Rule {
|
||||
throw new Error(`Project is not defined in this workspace.`);
|
||||
}
|
||||
|
||||
if (!project.architect) {
|
||||
throw new Error(`Architect is not defined for this project.`);
|
||||
}
|
||||
const projectTargets = getProjectTargets(project);
|
||||
|
||||
if (!project.architect[options.target]) {
|
||||
if (!projectTargets[options.target]) {
|
||||
throw new Error(`Target is not defined for this project.`);
|
||||
}
|
||||
|
||||
let applyTo = project.architect[options.target].options;
|
||||
let applyTo = projectTargets[options.target].options;
|
||||
|
||||
if (options.configuration &&
|
||||
project.architect[options.target].configurations &&
|
||||
project.architect[options.target].configurations[options.configuration]) {
|
||||
applyTo = project.architect[options.target].configurations[options.configuration];
|
||||
projectTargets[options.target].configurations &&
|
||||
projectTargets[options.target].configurations[options.configuration]) {
|
||||
applyTo = projectTargets[options.target].configurations[options.configuration];
|
||||
}
|
||||
|
||||
applyTo.serviceWorker = true;
|
||||
@ -92,10 +91,8 @@ function updateAppModule(options: ServiceWorkerOptions): Rule {
|
||||
// find app module
|
||||
const workspace = getWorkspace(host);
|
||||
const project = workspace.projects[options.project as string];
|
||||
if (!project.architect) {
|
||||
throw new Error('Project architect not found.');
|
||||
}
|
||||
const mainPath = project.architect.build.options.main;
|
||||
const projectTargets = getProjectTargets(project);
|
||||
const mainPath = projectTargets.build.options.main;
|
||||
const modulePath = getAppModulePath(host, mainPath);
|
||||
context.logger.debug(`module path: ${modulePath}`);
|
||||
|
||||
|
@ -50,7 +50,7 @@ describe('Service Worker Schematic', () => {
|
||||
const tree = schematicRunner.runSchematic('service-worker', defaultOptions, appTree);
|
||||
const configText = tree.readContent('/angular.json');
|
||||
const config = JSON.parse(configText);
|
||||
const swFlag = config.projects.bar.architect.build.configurations.production.serviceWorker;
|
||||
const swFlag = config.projects.bar.targets.build.configurations.production.serviceWorker;
|
||||
expect(swFlag).toEqual(true);
|
||||
});
|
||||
|
||||
@ -59,7 +59,7 @@ describe('Service Worker Schematic', () => {
|
||||
const tree = schematicRunner.runSchematic('service-worker', options, appTree);
|
||||
const configText = tree.readContent('/angular.json');
|
||||
const config = JSON.parse(configText);
|
||||
const swFlag = config.projects.bar.architect.build.options.serviceWorker;
|
||||
const swFlag = config.projects.bar.targets.build.options.serviceWorker;
|
||||
expect(swFlag).toEqual(true);
|
||||
});
|
||||
|
||||
|
@ -36,6 +36,7 @@ import { InsertChange } from '../utility/change';
|
||||
import { getWorkspace } from '../utility/config';
|
||||
import { addPackageJsonDependency, getPackageJsonDependency } from '../utility/dependencies';
|
||||
import { findBootstrapModuleCall, findBootstrapModulePath } from '../utility/ng-ast-utils';
|
||||
import { getProjectTargets } from '../utility/project-targets';
|
||||
import { Schema as UniversalOptions } from './schema';
|
||||
|
||||
|
||||
@ -57,17 +58,14 @@ function getClientProject(
|
||||
return clientProject;
|
||||
}
|
||||
|
||||
function getClientArchitect(
|
||||
function getClientTargets(
|
||||
host: Tree,
|
||||
options: UniversalOptions,
|
||||
): experimental.workspace.WorkspaceTool {
|
||||
const clientArchitect = getClientProject(host, options).architect;
|
||||
const clientProject = getClientProject(host, options);
|
||||
const projectTargets = getProjectTargets(clientProject);
|
||||
|
||||
if (!clientArchitect) {
|
||||
throw new Error('Client project architect not found.');
|
||||
}
|
||||
|
||||
return clientArchitect;
|
||||
return projectTargets;
|
||||
}
|
||||
|
||||
function updateConfigFile(options: UniversalOptions, tsConfigDirectory: Path): Rule {
|
||||
@ -78,9 +76,7 @@ function updateConfigFile(options: UniversalOptions, tsConfigDirectory: Path): R
|
||||
}
|
||||
|
||||
const clientProject = workspace.projects[options.clientProject];
|
||||
if (!clientProject.architect) {
|
||||
throw new Error('Client project architect not found.');
|
||||
}
|
||||
const projectTargets = getProjectTargets(clientProject);
|
||||
|
||||
const builderOptions: JsonObject = {
|
||||
outputPath: `dist/${options.clientProject}-server`,
|
||||
@ -91,7 +87,7 @@ function updateConfigFile(options: UniversalOptions, tsConfigDirectory: Path): R
|
||||
builder: '@angular-devkit/build-angular:server',
|
||||
options: builderOptions,
|
||||
};
|
||||
clientProject.architect.server = serverTarget;
|
||||
projectTargets.server = serverTarget;
|
||||
|
||||
const workspacePath = getWorkspacePath(host);
|
||||
|
||||
@ -122,8 +118,8 @@ function findBrowserModuleImport(host: Tree, modulePath: string): ts.Node {
|
||||
|
||||
function wrapBootstrapCall(options: UniversalOptions): Rule {
|
||||
return (host: Tree) => {
|
||||
const clientArchitect = getClientArchitect(host, options);
|
||||
const mainPath = normalize('/' + clientArchitect.build.options.main);
|
||||
const clientTargets = getClientTargets(host, options);
|
||||
const mainPath = normalize('/' + clientTargets.build.options.main);
|
||||
let bootstrapCall: ts.Node | null = findBootstrapModuleCall(host, mainPath);
|
||||
if (bootstrapCall === null) {
|
||||
throw new SchematicsException('Bootstrap module not found.');
|
||||
@ -151,8 +147,8 @@ function wrapBootstrapCall(options: UniversalOptions): Rule {
|
||||
function addServerTransition(options: UniversalOptions): Rule {
|
||||
return (host: Tree) => {
|
||||
const clientProject = getClientProject(host, options);
|
||||
const clientArchitect = getClientArchitect(host, options);
|
||||
const mainPath = normalize('/' + clientArchitect.build.options.main);
|
||||
const clientTargets = getClientTargets(host, options);
|
||||
const mainPath = normalize('/' + clientTargets.build.options.main);
|
||||
|
||||
const bootstrapModuleRelativePath = findBootstrapModulePath(host, mainPath);
|
||||
const bootstrapModulePath = normalize(
|
||||
@ -187,8 +183,8 @@ function addDependencies(): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
function getTsConfigOutDir(host: Tree, architect: experimental.workspace.WorkspaceTool): string {
|
||||
const tsConfigPath = architect.build.options.tsConfig;
|
||||
function getTsConfigOutDir(host: Tree, targets: experimental.workspace.WorkspaceTool): string {
|
||||
const tsConfigPath = targets.build.options.tsConfig;
|
||||
const tsConfigBuffer = host.read(tsConfigPath);
|
||||
if (!tsConfigBuffer) {
|
||||
throw new SchematicsException(`Could not read ${tsConfigPath}`);
|
||||
@ -211,9 +207,9 @@ export default function (options: UniversalOptions): Rule {
|
||||
if (clientProject.projectType !== 'application') {
|
||||
throw new SchematicsException(`Universal requires a project type of "application".`);
|
||||
}
|
||||
const clientArchitect = getClientArchitect(host, options);
|
||||
const outDir = getTsConfigOutDir(host, clientArchitect);
|
||||
const tsConfigExtends = basename(clientArchitect.build.options.tsConfig);
|
||||
const clientTargets = getClientTargets(host, options);
|
||||
const outDir = getTsConfigOutDir(host, clientTargets);
|
||||
const tsConfigExtends = basename(clientTargets.build.options.tsConfig);
|
||||
const rootInSrc = clientProject.root === '';
|
||||
const tsConfigDirectory = join(normalize(clientProject.root), rootInSrc ? 'src' : '');
|
||||
|
||||
|
@ -88,7 +88,7 @@ describe('Universal Schematic', () => {
|
||||
},
|
||||
});
|
||||
const angularConfig = JSON.parse(tree.readContent('angular.json'));
|
||||
expect(angularConfig.projects.workspace.architect.server.options.tsConfig)
|
||||
expect(angularConfig.projects.workspace.targets.server.options.tsConfig)
|
||||
.toEqual('src/tsconfig.server.json');
|
||||
});
|
||||
|
||||
@ -108,7 +108,7 @@ describe('Universal Schematic', () => {
|
||||
},
|
||||
});
|
||||
const angularConfig = JSON.parse(tree.readContent('angular.json'));
|
||||
expect(angularConfig.projects.bar.architect.server.options.tsConfig)
|
||||
expect(angularConfig.projects.bar.targets.server.options.tsConfig)
|
||||
.toEqual('projects/bar/tsconfig.server.json');
|
||||
});
|
||||
|
||||
@ -124,10 +124,10 @@ describe('Universal Schematic', () => {
|
||||
const filePath = '/angular.json';
|
||||
const contents = tree.readContent(filePath);
|
||||
const config = JSON.parse(contents.toString());
|
||||
const arch = config.projects.bar.architect;
|
||||
expect(arch.server).toBeDefined();
|
||||
expect(arch.server.builder).toBeDefined();
|
||||
const opts = arch.server.options;
|
||||
const targets = config.projects.bar.targets;
|
||||
expect(targets.server).toBeDefined();
|
||||
expect(targets.server.builder).toBeDefined();
|
||||
const opts = targets.server.options;
|
||||
expect(opts.outputPath).toEqual('dist/bar-server');
|
||||
expect(opts.main).toEqual('projects/bar/src/main.server.ts');
|
||||
expect(opts.tsConfig).toEqual('projects/bar/tsconfig.server.json');
|
||||
|
20
packages/schematics/angular/utility/project-targets.ts
Normal file
20
packages/schematics/angular/utility/project-targets.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. 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 { experimental } from '@angular-devkit/core';
|
||||
|
||||
export function getProjectTargets(
|
||||
project: experimental.workspace.WorkspaceProject,
|
||||
): experimental.workspace.WorkspaceTool {
|
||||
const projectTargets = project.targets || project.architect;
|
||||
if (!projectTargets) {
|
||||
throw new Error('Project architect not found.');
|
||||
}
|
||||
|
||||
return projectTargets;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user