Source code
Revision control
Copy as Markdown
Other Tools
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import {
chain,
type Rule,
type SchematicContext,
type Tree,
} from '@angular-devkit/schematics';
import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks';
import {of} from 'rxjs';
import {concatMap, map, scan} from 'rxjs/operators';
import {
addCommonFiles as addCommonFilesHelper,
addFrameworkFiles,
getNgCommandName,
hasE2ETester,
} from '../utils/files.js';
import {getApplicationProjects} from '../utils/json.js';
import {
addPackageJsonDependencies,
addPackageJsonScripts,
getDependenciesFromOptions,
getPackageLatestNpmVersion,
DependencyType,
type NodePackage,
updateAngularJsonScripts,
} from '../utils/packages.js';
import {TestRunner, type SchematicsOptions} from '../utils/types.js';
const DEFAULT_PORT = 4200;
// You don't have to export the function as default. You can also have more than one rule
// factory per file.
export function ngAdd(options: SchematicsOptions): Rule {
return (tree: Tree, context: SchematicContext) => {
return chain([
addDependencies(options),
addCommonFiles(options),
addOtherFiles(options),
updateScripts(),
updateAngularConfig(options),
])(tree, context);
};
}
function addDependencies(options: SchematicsOptions): Rule {
return (tree: Tree, context: SchematicContext) => {
context.logger.debug('Adding dependencies to "package.json"');
const dependencies = getDependenciesFromOptions(options);
return of(...dependencies).pipe(
concatMap((packageName: string) => {
return getPackageLatestNpmVersion(packageName);
}),
scan((array, nodePackage) => {
array.push(nodePackage);
return array;
}, [] as NodePackage[]),
map(packages => {
context.logger.debug('Updating dependencies...');
addPackageJsonDependencies(tree, packages, DependencyType.Dev);
context.addTask(
new NodePackageInstallTask({
// Trigger Post-Install hooks to download the browser
allowScripts: true,
})
);
return tree;
})
);
};
}
function updateScripts(): Rule {
return (tree: Tree, context: SchematicContext): Tree => {
context.logger.debug('Updating "package.json" scripts');
const projects = getApplicationProjects(tree);
const projectsKeys = Object.keys(projects);
if (projectsKeys.length === 1) {
const name = getNgCommandName(projects);
const prefix = hasE2ETester(projects) ? `run ${projectsKeys[0]}:` : '';
return addPackageJsonScripts(tree, [
{
name,
script: `ng ${prefix}${name}`,
},
]);
}
return tree;
};
}
function addCommonFiles(options: SchematicsOptions): Rule {
return (tree: Tree, context: SchematicContext) => {
context.logger.debug('Adding Puppeteer base files.');
const projects = getApplicationProjects(tree);
return addCommonFilesHelper(projects, {
options: {
...options,
port: DEFAULT_PORT,
ext: options.testRunner === TestRunner.Node ? 'test' : 'e2e',
},
});
};
}
function addOtherFiles(options: SchematicsOptions): Rule {
return (tree: Tree, context: SchematicContext) => {
context.logger.debug('Adding Puppeteer additional files.');
const projects = getApplicationProjects(tree);
return addFrameworkFiles(projects, {
options: {
...options,
port: DEFAULT_PORT,
},
});
};
}
function updateAngularConfig(options: SchematicsOptions): Rule {
return (tree: Tree, context: SchematicContext): Tree => {
context.logger.debug('Updating "angular.json".');
return updateAngularJsonScripts(tree, options);
};
}