index.ts (3793B)
1 /** 2 * @license 3 * Copyright 2022 Google Inc. 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 import { 8 chain, 9 type Rule, 10 type SchematicContext, 11 type Tree, 12 } from '@angular-devkit/schematics'; 13 import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; 14 import {of} from 'rxjs'; 15 import {concatMap, map, scan} from 'rxjs/operators'; 16 17 import { 18 addCommonFiles as addCommonFilesHelper, 19 addFrameworkFiles, 20 getNgCommandName, 21 hasE2ETester, 22 } from '../utils/files.js'; 23 import {getApplicationProjects} from '../utils/json.js'; 24 import { 25 addPackageJsonDependencies, 26 addPackageJsonScripts, 27 getDependenciesFromOptions, 28 getPackageLatestNpmVersion, 29 DependencyType, 30 type NodePackage, 31 updateAngularJsonScripts, 32 } from '../utils/packages.js'; 33 import {TestRunner, type SchematicsOptions} from '../utils/types.js'; 34 35 const DEFAULT_PORT = 4200; 36 37 // You don't have to export the function as default. You can also have more than one rule 38 // factory per file. 39 export function ngAdd(options: SchematicsOptions): Rule { 40 return (tree: Tree, context: SchematicContext) => { 41 return chain([ 42 addDependencies(options), 43 addCommonFiles(options), 44 addOtherFiles(options), 45 updateScripts(), 46 updateAngularConfig(options), 47 ])(tree, context); 48 }; 49 } 50 51 function addDependencies(options: SchematicsOptions): Rule { 52 return (tree: Tree, context: SchematicContext) => { 53 context.logger.debug('Adding dependencies to "package.json"'); 54 const dependencies = getDependenciesFromOptions(options); 55 56 return of(...dependencies).pipe( 57 concatMap((packageName: string) => { 58 return getPackageLatestNpmVersion(packageName); 59 }), 60 scan((array, nodePackage) => { 61 array.push(nodePackage); 62 return array; 63 }, [] as NodePackage[]), 64 map(packages => { 65 context.logger.debug('Updating dependencies...'); 66 addPackageJsonDependencies(tree, packages, DependencyType.Dev); 67 context.addTask( 68 new NodePackageInstallTask({ 69 // Trigger Post-Install hooks to download the browser 70 allowScripts: true, 71 }), 72 ); 73 74 return tree; 75 }), 76 ); 77 }; 78 } 79 80 function updateScripts(): Rule { 81 return (tree: Tree, context: SchematicContext): Tree => { 82 context.logger.debug('Updating "package.json" scripts'); 83 const projects = getApplicationProjects(tree); 84 const projectsKeys = Object.keys(projects); 85 86 if (projectsKeys.length === 1) { 87 const name = getNgCommandName(projects); 88 const prefix = hasE2ETester(projects) ? `run ${projectsKeys[0]}:` : ''; 89 return addPackageJsonScripts(tree, [ 90 { 91 name, 92 script: `ng ${prefix}${name}`, 93 }, 94 ]); 95 } 96 return tree; 97 }; 98 } 99 100 function addCommonFiles(options: SchematicsOptions): Rule { 101 return (tree: Tree, context: SchematicContext) => { 102 context.logger.debug('Adding Puppeteer base files.'); 103 const projects = getApplicationProjects(tree); 104 105 return addCommonFilesHelper(projects, { 106 options: { 107 ...options, 108 port: DEFAULT_PORT, 109 ext: options.testRunner === TestRunner.Node ? 'test' : 'e2e', 110 }, 111 }); 112 }; 113 } 114 115 function addOtherFiles(options: SchematicsOptions): Rule { 116 return (tree: Tree, context: SchematicContext) => { 117 context.logger.debug('Adding Puppeteer additional files.'); 118 const projects = getApplicationProjects(tree); 119 120 return addFrameworkFiles(projects, { 121 options: { 122 ...options, 123 port: DEFAULT_PORT, 124 }, 125 }); 126 }; 127 } 128 129 function updateAngularConfig(options: SchematicsOptions): Rule { 130 return (tree: Tree, context: SchematicContext): Tree => { 131 context.logger.debug('Updating "angular.json".'); 132 133 return updateAngularJsonScripts(tree, options); 134 }; 135 }