Skip to content

Commit

Permalink
fix(schematics): compatibility with Angular CLI 6.2.0 (#2131)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsuanxyz authored and vthinkxie committed Sep 13, 2018
1 parent 3c6215f commit ac428db
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 28 deletions.
37 changes: 18 additions & 19 deletions schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getAppModulePath } from '../utils/devkit-utils/ng-ast-utils';
import { insertImport } from '../utils/devkit-utils/route-utils';
import { zorroVersion } from '../utils/lib-versions';
import { addPackageToPackageJson } from '../utils/package';
import { getProjectTargetOptions } from '../utils/project-targets';
import { Schema } from './schema';

const ADD_CONFIG = {
Expand Down Expand Up @@ -45,7 +46,7 @@ function addI18n(options: Schema): (host: Tree) => Tree {
return function (host: Tree): Tree {
const workspace = getWorkspace(host);
const project = getProjectFromWorkspace(workspace, options.project);
const modulePath = getAppModulePath(host, project.architect.build.options.main);
const modulePath = getAppModulePath(host, getProjectTargetOptions(project, 'build').main);
const moduleSource = getSourceFile(host, modulePath);
const locale = options.i18n;
const localePrefix = locale.split('_')[0];
Expand Down Expand Up @@ -206,11 +207,11 @@ function insertCustomTheme(project: Project, host: Tree, workspace: Workspace):
host.create(themePath, createCustomTheme());
}

if (project.architect) {
addStyleToTarget(project.architect.build, host, workspace, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
addStyleToTarget(project.architect.test, host, workspace, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
if ((project as any).targets || project.architect) {
addStyleToTarget('build', host, workspace, project, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
addStyleToTarget('test', host, workspace, project, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
} else {
throw new SchematicsException(`${project.name} does not have an architect configuration`);
throw new SchematicsException(`${project.name} does not have an architect or targets configuration`);
}
}

Expand All @@ -234,37 +235,35 @@ function installNodeDeps(): (host: Tree, context: SchematicContext) => void {
function insertCompiledTheme(project: Project, host: Tree, workspace: Workspace): void {
const themePath = ADD_CONFIG.COMPILED_THEME_PATH;

if (project.architect) {
addStyleToTarget(project.architect.build, host, workspace, themePath);
addStyleToTarget(project.architect.test, host, workspace, themePath);
if ((project as any).targets || project.architect) {
addStyleToTarget('build', host, workspace, project, themePath);
addStyleToTarget('test', host, workspace, project, themePath);
} else {
throw new SchematicsException(`${project.name} does not have an architect configuration`);
throw new SchematicsException(`${project.name} does not have an architect or targets configuration`);
}
}

/** Adds a style entry to the given target. */
function addStyleToTarget(target: any, host: Tree, workspace: Workspace, asset: string, exclude: string = ''): void {
function addStyleToTarget(targetName: string, host: Tree, workspace: Workspace, project: Project, asset: string, exclude: string = ''): void {
const styleEntry = asset;

const targetOptions = getProjectTargetOptions(project, targetName);
// We can't assume that any of these properties are defined, so safely add them as we go
// if necessary.
if (!target.options) {
target.options = { styles: [ styleEntry ] };
} else if (!target.options.styles) {
target.options.styles = [ styleEntry ];
if (!targetOptions.styles) {
targetOptions.styles = [ styleEntry ];
} else {
const existingStyles = target.options.styles.map(s => typeof s === 'string' ? s : s.input);
const existingStyles = targetOptions.styles.map(s => typeof s === 'string' ? s : s.input);
const hasGivenTheme = existingStyles.find(s => s.includes(asset));

if (exclude) {
const removeIndex = target.options.styles.indexOf(exclude);
const removeIndex = targetOptions.styles.indexOf(exclude);
if (removeIndex >= 0) {
target.options.styles.splice(removeIndex, 1);
targetOptions.styles.splice(removeIndex, 1);
}
}

if (!hasGivenTheme) {
target.options.styles.splice(0, 0, styleEntry);
targetOptions.styles.splice(0, 0, styleEntry);
}
}

Expand Down
21 changes: 12 additions & 9 deletions schematics/utils/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import {SchematicsException, Tree} from '@angular-devkit/schematics';
import * as ts from 'typescript';
import {addImportToModule} from './devkit-utils/ast-utils';
import {InsertChange} from './devkit-utils/change';
import {Project, getWorkspace} from './devkit-utils/config';
import { Project, getWorkspace, Workspace } from './devkit-utils/config';
import {findBootstrapModulePath, getAppModulePath} from './devkit-utils/ng-ast-utils';
import {ModuleOptions, findModuleFromOptions as internalFindModule} from './devkit-utils/find-module';
import { getProjectMainFile } from './project-main-file'
import { getProjectTargetOptions } from './project-targets'


/** Reads file given path and returns TypeScript source file. */
Expand All @@ -19,8 +21,9 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile {
}

/** Import and add module to root app module. */
export function addModuleImportToRootModule(host: Tree, moduleName: string, src: string, project: Project) {
const modulePath = getAppModulePath(host, project.architect.build.options.main);
export function addModuleImportToRootModule(host: Tree, moduleName: string, src: string,
project: Workspace | any) {
const modulePath = getAppModulePath(host, getProjectMainFile(project));
addModuleImportToModule(host, modulePath, moduleName, src);
}

Expand Down Expand Up @@ -53,21 +56,21 @@ export function addModuleImportToModule(

/** Gets the app index.html file */
export function getIndexHtmlPath(host: Tree, project: Project): string {
const buildTarget = project.architect.build.options;
const buildOptions = getProjectTargetOptions(project, 'build');

if (buildTarget.index && buildTarget.index.endsWith('index.html')) {
return buildTarget.index;
if (buildOptions.index && buildOptions.index.endsWith('index.html')) {
return buildOptions.index;
}

throw new SchematicsException('No index.html file was found.');
}

/** Get the root stylesheet file. */
export function getStylesPath(host: Tree, project: Project): string {
const buildTarget = project.architect['build'];
const buildOptions = getProjectTargetOptions(project, 'build');

if (buildTarget.options && buildTarget.options.styles && buildTarget.options.styles.length) {
const styles = buildTarget.options.styles.map(s => typeof s === 'string' ? s : s.input);
if (buildOptions && buildOptions.styles && buildOptions.styles.length) {
const styles = buildOptions.styles.map(s => typeof s === 'string' ? s : s.input);

// First, see if any of the assets is called "styles.(le|sc|c)ss", which is the default
// "main" style sheet.
Expand Down
23 changes: 23 additions & 0 deletions schematics/utils/project-main-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @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 { SchematicsException } from '@angular-devkit/schematics';
import { Workspace } from './devkit-utils/config';
import { getProjectTargetOptions } from './project-targets';

/** Looks for the main TypeScript file in the given project and returns its path. */
export function getProjectMainFile(project: Workspace): string {
const buildOptions = getProjectTargetOptions(project, 'build');

if (!buildOptions.main) {
throw new SchematicsException(`Could not find the project main file inside of the ` +
`workspace config (${(project as any).sourceRoot})`);
}

return buildOptions.main;
}
31 changes: 31 additions & 0 deletions schematics/utils/project-targets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @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 { Project } from './devkit-utils/config';

/** Resolves the architect options for the build target of the given project. */
export function getProjectTargetOptions(project: Project | any, buildTarget: string) {
if (project.targets &&
project.targets[buildTarget] &&
project.targets[buildTarget].options) {

return project.targets[buildTarget].options;
}

// TODO(devversion): consider removing this architect check if the CLI completely switched
// over to `targets`, and the `architect` support has been removed.
// See: https://github.com/angular/angular-cli/commit/307160806cb48c95ecb8982854f452303801ac9f
if (project.architect &&
project.architect[buildTarget] &&
project.architect[buildTarget].options) {

return project.architect[buildTarget].options;
}

throw new Error(`Cannot determine project target configuration for: ${buildTarget}.`);
}

0 comments on commit ac428db

Please sign in to comment.