|
| 1 | +/** |
| 2 | + * @license |
| 3 | + * Copyright Google LLC All Rights Reserved. |
| 4 | + * |
| 5 | + * Use of this source code is governed by an MIT-style license that can be |
| 6 | + * found in the LICENSE file at https://angular.io/license |
| 7 | + */ |
| 8 | + |
| 9 | +import { |
| 10 | + Rule, |
| 11 | + SchematicsException, |
| 12 | + chain, |
| 13 | + externalSchematic, |
| 14 | +} from '@angular-devkit/schematics'; |
| 15 | +import {getWorkspace} from '@schematics/angular/utility/workspace'; |
| 16 | +import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; |
| 17 | +import {Builders} from '@schematics/angular/utility/workspace-models'; |
| 18 | +import {normalize, join} from '@angular-devkit/core'; |
| 19 | +import {Schema as UniversalOptions} from '@schematics/angular/universal/schema'; |
| 20 | + |
| 21 | +export function version9UpdateRule(collectionPath: string): Rule { |
| 22 | + return async host => { |
| 23 | + return chain([ |
| 24 | + backupPackageScriptsRule(), |
| 25 | + updateProjectsStructureRule(collectionPath), |
| 26 | + (tree, context) => { |
| 27 | + const packageChanges = tree.actions.some(a => a.path.endsWith('/package.json')); |
| 28 | + if (context && packageChanges) { |
| 29 | + context.addTask(new NodePackageInstallTask()); |
| 30 | + } |
| 31 | + }, |
| 32 | + ]); |
| 33 | + }; |
| 34 | +} |
| 35 | + |
| 36 | +function backupPackageScriptsRule(): Rule { |
| 37 | + return tree => { |
| 38 | + // Remove old scripts in 'package.json' |
| 39 | + const pkgPath = '/package.json'; |
| 40 | + const buffer = tree.read(pkgPath); |
| 41 | + if (!buffer) { |
| 42 | + throw new SchematicsException('Could not find package.json'); |
| 43 | + } |
| 44 | + |
| 45 | + const pkg = JSON.parse(buffer.toString()); |
| 46 | + const scripts = pkg.scripts; |
| 47 | + if (!scripts) { |
| 48 | + return; |
| 49 | + } |
| 50 | + |
| 51 | + // Backup script targets |
| 52 | + [ |
| 53 | + 'compile:server', |
| 54 | + 'build:ssr', |
| 55 | + 'serve:ssr', |
| 56 | + 'build:client-and-server-bundles', |
| 57 | + ].forEach(key => { |
| 58 | + const keyBackup = `${key}_bak`; |
| 59 | + const scriptValue = scripts[key]; |
| 60 | + // Check if script target exists and it has not been already backed up |
| 61 | + if (scriptValue && !scripts[keyBackup]) { |
| 62 | + scripts[keyBackup] = scriptValue; |
| 63 | + scripts[key] = undefined; |
| 64 | + } |
| 65 | + }); |
| 66 | + |
| 67 | + tree.overwrite(pkgPath, JSON.stringify(pkg, null, 2)); |
| 68 | + }; |
| 69 | +} |
| 70 | + |
| 71 | +function updateProjectsStructureRule(collectionPath: string): Rule { |
| 72 | + return async tree => { |
| 73 | + const workspace = await getWorkspace(tree); |
| 74 | + const installRules: Rule[] = []; |
| 75 | + |
| 76 | + for (const [projectName, projectDefinition] of workspace.projects) { |
| 77 | + const serverTarget = projectDefinition.targets.get('server'); |
| 78 | + if (!serverTarget || serverTarget.builder !== Builders.Server) { |
| 79 | + // Only process those targets which have a known builder for the CLI |
| 80 | + continue; |
| 81 | + } |
| 82 | + |
| 83 | + const root = normalize(projectDefinition.root); |
| 84 | + |
| 85 | + // Backup old files |
| 86 | + [ |
| 87 | + 'server.ts', |
| 88 | + 'webpack.server.config.js', |
| 89 | + ] |
| 90 | + .map(f => join(root, f)) |
| 91 | + .filter(f => tree.exists(f)) |
| 92 | + .forEach(f => tree.rename(f, `${f}.bak`)); |
| 93 | + |
| 94 | + const installOptions: UniversalOptions = { |
| 95 | + clientProject: projectName, |
| 96 | + // Skip install, so we only do one for the entire workspace at the end. |
| 97 | + skipInstall: true, |
| 98 | + }; |
| 99 | + |
| 100 | + if (!collectionPath) { |
| 101 | + continue; |
| 102 | + } |
| 103 | + // Run the install schematic again so that we re-create the entire stucture. |
| 104 | + installRules.push(externalSchematic(collectionPath, 'ng-add', installOptions)); |
| 105 | + } |
| 106 | + |
| 107 | + return chain(installRules); |
| 108 | + }; |
| 109 | +} |
0 commit comments