mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(angular): support multi-app for ng-add schematic (#20768)
* chore(angular): Add missing argument type information. * chore(angular): Add missing semicolon. * fix(angular): Properly detect the Angular project name for multi-app repositories. * fix(angular): Fix generated angular.json when using ng-add in multi-app repositories. * chore(angular): Improve reported warnings when using ng-add with invalid workspace configuration.
This commit is contained in:
@@ -2,7 +2,7 @@ import { join, Path } from '@angular-devkit/core';
|
||||
import { apply, chain, mergeWith, move, Rule, SchematicContext, SchematicsException, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||
import { addModuleImportToRootModule } from './../utils/ast';
|
||||
import { addArchitectBuilder, addStyle, getWorkspace, addAsset, WorkspaceProject, WorkspaceSchema } from './../utils/config';
|
||||
import { addArchitectBuilder, addAsset, addStyle, getDefaultAngularAppName, getWorkspace, WorkspaceProject, WorkspaceSchema } from './../utils/config';
|
||||
import { addPackageToPackageJson } from './../utils/package';
|
||||
import { Schema as IonAddOptions } from './schema';
|
||||
|
||||
@@ -37,7 +37,7 @@ function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicStyles(projectSourceRoot: Path): Rule {
|
||||
function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
|
||||
return (host: Tree) => {
|
||||
const ionicStyles = [
|
||||
'node_modules/@ionic/angular/css/normalize.css',
|
||||
@@ -51,27 +51,27 @@ function addIonicStyles(projectSourceRoot: Path): Rule {
|
||||
'node_modules/@ionic/angular/css/flex-utils.css',
|
||||
`${projectSourceRoot}/theme/variables.css`
|
||||
].forEach(entry => {
|
||||
addStyle(host, entry);
|
||||
addStyle(host, projectName, entry);
|
||||
});
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicons(): Rule {
|
||||
function addIonicons(projectName: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const ioniconsGlob = {
|
||||
glob: '**/*.svg',
|
||||
input: 'node_modules/ionicons/dist/ionicons/svg',
|
||||
output: './svg'
|
||||
};
|
||||
addAsset(host, ioniconsGlob);
|
||||
addAsset(host, projectName, ioniconsGlob);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicBuilder(projectName: string): Rule {
|
||||
return (host: Tree) => {
|
||||
addArchitectBuilder(host, 'ionic-cordova-serve', {
|
||||
addArchitectBuilder(host, projectName, 'ionic-cordova-serve', {
|
||||
builder: '@ionic/angular-toolkit:cordova-serve',
|
||||
options: {
|
||||
cordovaBuildTarget: `${projectName}:ionic-cordova-build`,
|
||||
@@ -84,7 +84,7 @@ function addIonicBuilder(projectName: string): Rule {
|
||||
}
|
||||
}
|
||||
});
|
||||
addArchitectBuilder(host, 'ionic-cordova-build', {
|
||||
addArchitectBuilder(host, projectName, 'ionic-cordova-build', {
|
||||
builder: '@ionic/angular-toolkit:cordova-build',
|
||||
options: {
|
||||
browserTarget: `${projectName}:build`
|
||||
@@ -109,7 +109,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
return (host: Tree) => {
|
||||
const workspace: WorkspaceSchema = getWorkspace(host);
|
||||
if (!options.project) {
|
||||
options.project = Object.keys(workspace.projects)[0];
|
||||
options.project = getDefaultAngularAppName(workspace);
|
||||
}
|
||||
const project: WorkspaceProject = workspace.projects[options.project];
|
||||
if (project.projectType !== 'application') {
|
||||
@@ -128,8 +128,8 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
addIonicAngularToolkitToPackageJson(),
|
||||
addIonicAngularModuleToAppModule(sourcePath),
|
||||
addIonicBuilder(options.project),
|
||||
addIonicStyles(sourcePath),
|
||||
addIonicons(),
|
||||
addIonicStyles(options.project, sourcePath),
|
||||
addIonicons(options.project),
|
||||
mergeWith(rootTemplateSource),
|
||||
// install freshly added dependencies
|
||||
installNodeDeps()
|
||||
|
||||
@@ -27,7 +27,7 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile {
|
||||
*/
|
||||
export function addModuleImportToRootModule(
|
||||
host: Tree,
|
||||
projectSourceRoot,
|
||||
projectSourceRoot: string,
|
||||
moduleName: string,
|
||||
importSrc: string
|
||||
) {
|
||||
|
||||
@@ -21,7 +21,7 @@ function isAngularBrowserProject(projectConfig: any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getAngularAppName(config: any): string | null {
|
||||
export function getDefaultAngularAppName(config: any): string {
|
||||
const projects = config.projects;
|
||||
const projectNames = Object.keys(projects);
|
||||
|
||||
@@ -32,60 +32,48 @@ export function getAngularAppName(config: any): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return projectNames[0];
|
||||
}
|
||||
|
||||
export function getAngularAppConfig(config: any): any | null {
|
||||
const projects = config.projects;
|
||||
const projectNames = Object.keys(projects);
|
||||
|
||||
for (const projectName of projectNames) {
|
||||
const projectConfig = projects[projectName];
|
||||
if (isAngularBrowserProject(projectConfig)) {
|
||||
return projectConfig;
|
||||
}
|
||||
export function getAngularAppConfig(config: any, projectName: string): any | never {
|
||||
if (!config.projects.hasOwnProperty(projectName)) {
|
||||
throw new SchematicsException(`Could not find project: ${projectName}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
const projectConfig = config.projects[projectName];
|
||||
if (isAngularBrowserProject(projectConfig)) {
|
||||
return projectConfig;
|
||||
}
|
||||
|
||||
export function addStyle(host: Tree, stylePath: string) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect.build.options.styles.push({
|
||||
input: stylePath
|
||||
});
|
||||
|
||||
writeConfig(host, config);
|
||||
if (config.projectType !== 'application') {
|
||||
throw new SchematicsException(`Invalid projectType for ${projectName}: ${config.projectType}`);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
const buildConfig = projectConfig.architect.build;
|
||||
throw new SchematicsException(`Invalid builder for ${projectName}: ${buildConfig.builder}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function addAsset(host: Tree, asset: string | {glob: string; input: string; output: string}) {
|
||||
export function addStyle(host: Tree, projectName: string, stylePath: string) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect.build.options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
}
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.styles.push({
|
||||
input: stylePath
|
||||
});
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export function addArchitectBuilder(host: Tree, builderName: string, builderOpts: any){
|
||||
export function addAsset(host: Tree, projectName: string, asset: string | {glob: string; input: string; output: string}) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect[builderName] = builderOpts
|
||||
writeConfig(host, config);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
}
|
||||
export function addArchitectBuilder(host: Tree, projectName: string, builderName: string, builderOpts: any): void | never {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect[builderName] = builderOpts;
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export type WorkspaceSchema = experimental.workspace.WorkspaceSchema;
|
||||
|
||||
Reference in New Issue
Block a user