diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts index ba7cb3c7e8..4ae8bcd8fd 100644 --- a/packages/schematics/angular/app-shell/index.ts +++ b/packages/schematics/angular/app-shell/index.ts @@ -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 { diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts index ee56ba51b6..50636c7b11 100644 --- a/packages/schematics/angular/app-shell/index_spec.ts +++ b/packages/schematics/angular/app-shell/index_spec.ts @@ -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'); diff --git a/packages/schematics/angular/service-worker/index.ts b/packages/schematics/angular/service-worker/index.ts index 795637a7b1..4b571008a4 100644 --- a/packages/schematics/angular/service-worker/index.ts +++ b/packages/schematics/angular/service-worker/index.ts @@ -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}`); diff --git a/packages/schematics/angular/service-worker/index_spec.ts b/packages/schematics/angular/service-worker/index_spec.ts index fae453d353..e6a6de9ffd 100644 --- a/packages/schematics/angular/service-worker/index_spec.ts +++ b/packages/schematics/angular/service-worker/index_spec.ts @@ -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); }); diff --git a/packages/schematics/angular/universal/index.ts b/packages/schematics/angular/universal/index.ts index 2f02522ce8..f3a94daea5 100644 --- a/packages/schematics/angular/universal/index.ts +++ b/packages/schematics/angular/universal/index.ts @@ -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' : ''); diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts index 565cbdeca0..262aa04882 100644 --- a/packages/schematics/angular/universal/index_spec.ts +++ b/packages/schematics/angular/universal/index_spec.ts @@ -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'); diff --git a/packages/schematics/angular/utility/project-targets.ts b/packages/schematics/angular/utility/project-targets.ts new file mode 100644 index 0000000000..330093d367 --- /dev/null +++ b/packages/schematics/angular/utility/project-targets.ts @@ -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; +}