From 7b00b920aa1524bc9a8739951cf97b26fee94ca1 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Sun, 7 Jul 2019 18:49:26 -0400 Subject: [PATCH] feat(nx): delegate to cli when command is not recognized --- docs/api-workspace/npmscripts/update-check.md | 79 --------- docs/api-workspace/npmscripts/update-skip.md | 79 --------- docs/api-workspace/npmscripts/update.md | 79 --------- ...{lint-files.md => workspace-lint-files.md} | 4 +- e2e/schematics/command-line.test.ts | 2 +- e2e/schematics/delegate-to-cli.test.ts | 23 +++ e2e/schematics/ng-add.test.ts | 3 +- packages/workspace/migrations.json | 5 + .../workspace/src/command-line/nx-commands.ts | 36 ++-- packages/workspace/src/command-line/nx.ts | 15 +- packages/workspace/src/command-line/update.ts | 161 ------------------ .../migrations/update-8.3.0/rename-lint.ts | 19 +++ .../workspace/src/schematics/ng-add/ng-add.ts | 3 +- .../workspace/files/package.json__tmpl__ | 3 +- packages/workspace/src/utils/app-root.ts | 19 +++ scripts/e2e-rerun.sh | 0 16 files changed, 109 insertions(+), 421 deletions(-) delete mode 100644 docs/api-workspace/npmscripts/update-check.md delete mode 100644 docs/api-workspace/npmscripts/update-skip.md delete mode 100644 docs/api-workspace/npmscripts/update.md rename docs/api-workspace/npmscripts/{lint-files.md => workspace-lint-files.md} (93%) create mode 100644 e2e/schematics/delegate-to-cli.test.ts delete mode 100644 packages/workspace/src/command-line/update.ts create mode 100644 packages/workspace/src/migrations/update-8.3.0/rename-lint.ts mode change 100644 => 100755 scripts/e2e-rerun.sh diff --git a/docs/api-workspace/npmscripts/update-check.md b/docs/api-workspace/npmscripts/update-check.md deleted file mode 100644 index bc16fe2010988..0000000000000 --- a/docs/api-workspace/npmscripts/update-check.md +++ /dev/null @@ -1,79 +0,0 @@ -# update:check - -Check for workspace updates - -## Usage - -```bash -update:check -``` - -## Options - -### all - -All projects - -### apps-and-libs - -### base - -Base of the current branch (usually master) - -### exclude - -Default: `` - -Exclude certain projects from being processed - -### file - -output file (e.g. --file=.vis/output.json) - -### files - -A list of files delimited by commas - -### head - -Latest commit of the current branch (usually HEAD) - -### help - -Show help - -### maxParallel - -Default: `3` - -Max number of parallel processes - -### only-failed - -Default: `false` - -Isolate projects which previously failed - -### parallel - -Default: `false` - -Parallelize the command - -### quiet - -### uncommitted - -Uncommitted changes - -### untracked - -Untracked changes - -### verbose - -Print additional error stack trace on failure - -### version - -Show version number diff --git a/docs/api-workspace/npmscripts/update-skip.md b/docs/api-workspace/npmscripts/update-skip.md deleted file mode 100644 index 9545dced26aa4..0000000000000 --- a/docs/api-workspace/npmscripts/update-skip.md +++ /dev/null @@ -1,79 +0,0 @@ -# update:skip - -Skip workspace updates - -## Usage - -```bash -update:skip -``` - -## Options - -### all - -All projects - -### apps-and-libs - -### base - -Base of the current branch (usually master) - -### exclude - -Default: `` - -Exclude certain projects from being processed - -### file - -output file (e.g. --file=.vis/output.json) - -### files - -A list of files delimited by commas - -### head - -Latest commit of the current branch (usually HEAD) - -### help - -Show help - -### maxParallel - -Default: `3` - -Max number of parallel processes - -### only-failed - -Default: `false` - -Isolate projects which previously failed - -### parallel - -Default: `false` - -Parallelize the command - -### quiet - -### uncommitted - -Uncommitted changes - -### untracked - -Untracked changes - -### verbose - -Print additional error stack trace on failure - -### version - -Show version number diff --git a/docs/api-workspace/npmscripts/update.md b/docs/api-workspace/npmscripts/update.md deleted file mode 100644 index 80193ff493edc..0000000000000 --- a/docs/api-workspace/npmscripts/update.md +++ /dev/null @@ -1,79 +0,0 @@ -# update - -Update workspace - -## Usage - -```bash -update -``` - -## Options - -### all - -All projects - -### apps-and-libs - -### base - -Base of the current branch (usually master) - -### exclude - -Default: `` - -Exclude certain projects from being processed - -### file - -output file (e.g. --file=.vis/output.json) - -### files - -A list of files delimited by commas - -### head - -Latest commit of the current branch (usually HEAD) - -### help - -Show help - -### maxParallel - -Default: `3` - -Max number of parallel processes - -### only-failed - -Default: `false` - -Isolate projects which previously failed - -### parallel - -Default: `false` - -Parallelize the command - -### quiet - -### uncommitted - -Uncommitted changes - -### untracked - -Untracked changes - -### verbose - -Print additional error stack trace on failure - -### version - -Show version number diff --git a/docs/api-workspace/npmscripts/lint-files.md b/docs/api-workspace/npmscripts/workspace-lint-files.md similarity index 93% rename from docs/api-workspace/npmscripts/lint-files.md rename to docs/api-workspace/npmscripts/workspace-lint-files.md index bde0488e2c52e..44cf887c1e721 100644 --- a/docs/api-workspace/npmscripts/lint-files.md +++ b/docs/api-workspace/npmscripts/workspace-lint-files.md @@ -1,11 +1,11 @@ -# lint [files..] +# workspace-lint [files..] Lint workspace or list of files ## Usage ```bash -lint [files..] +workspace-lint [files..] ``` ## Options diff --git a/e2e/schematics/command-line.test.ts b/e2e/schematics/command-line.test.ts index 839db23471a31..f0839aef4a355 100644 --- a/e2e/schematics/command-line.test.ts +++ b/e2e/schematics/command-line.test.ts @@ -73,7 +73,7 @@ describe('Command line', () => { runCLI(`generate @nrwl/angular:app ${appBefore}`); runCommand(`mv apps/${appBefore} apps/${appAfter}`); - const stdout = runCommand('./node_modules/.bin/nx lint'); + const stdout = runCommand('./node_modules/.bin/nx workspace-lint'); expect(stdout).toContain( `Cannot find project '${appBefore}' in 'apps/${appBefore}'` ); diff --git a/e2e/schematics/delegate-to-cli.test.ts b/e2e/schematics/delegate-to-cli.test.ts new file mode 100644 index 0000000000000..12c62ff8edd85 --- /dev/null +++ b/e2e/schematics/delegate-to-cli.test.ts @@ -0,0 +1,23 @@ +import { ensureProject, uniq, runCommand, checkFilesExist } from '../utils'; + +describe('Delegate to CLI', () => { + it('should delegate to the Angular CLI all non-standard commands', async () => { + ensureProject(); + + const appName = uniq('app'); + runCommand(`npm run nx -- g app ${appName}`); + runCommand(`npm run nx -- build ${appName}`); + + checkFilesExist( + `dist/apps/${appName}/index.html`, + `dist/apps/${appName}/polyfills-es2015.js`, + `dist/apps/${appName}/runtime-es2015.js`, + `dist/apps/${appName}/main-es2015.js`, + `dist/apps/${appName}/styles-es2015.js`, + `dist/apps/${appName}/polyfills-es5.js`, + `dist/apps/${appName}/runtime-es5.js`, + `dist/apps/${appName}/main-es5.js`, + `dist/apps/${appName}/styles-es5.js` + ); + }, 120000); +}); diff --git a/e2e/schematics/ng-add.test.ts b/e2e/schematics/ng-add.test.ts index 61c1c3c0ad376..c10ff261f3512 100644 --- a/e2e/schematics/ng-add.test.ts +++ b/e2e/schematics/ng-add.test.ts @@ -71,10 +71,11 @@ describe('Nrwl Convert to Nx Workspace', () => { expect(updatedPackageJson.description).toEqual('some description'); expect(updatedPackageJson.scripts).toEqual({ ng: 'ng', + nx: 'nx', start: 'ng serve', build: 'ng build', test: 'ng test', - lint: 'nx lint && ng lint', + lint: 'nx workspace-lint && ng lint', e2e: 'ng e2e', 'affected:apps': 'nx affected:apps', 'affected:libs': 'nx affected:libs', diff --git a/packages/workspace/migrations.json b/packages/workspace/migrations.json index 328d608559dcd..0ba81713c63b0 100644 --- a/packages/workspace/migrations.json +++ b/packages/workspace/migrations.json @@ -4,6 +4,11 @@ "version": "8.2.0-beta.1", "description": "Add exclusions to lint config", "factory": "./src/migrations/update-8-2-0/update-8-2-0" + }, + "rename-lint-into-workspace-lint": { + "version": "8.3.0-beta.1", + "description": "Rename 'nx lint' into 'nx workspace-lint' to avoid confusion", + "factory": "./src/migrations/update-8-3-0/rename-lint" } } } diff --git a/packages/workspace/src/command-line/nx-commands.ts b/packages/workspace/src/command-line/nx-commands.ts index c8ef8177a285a..cbf1a0f63ba38 100644 --- a/packages/workspace/src/command-line/nx-commands.ts +++ b/packages/workspace/src/command-line/nx-commands.ts @@ -3,13 +3,31 @@ import * as yargs from 'yargs'; import { affected } from './affected'; import { format } from './format'; -import { update } from './update'; import { lint } from './lint'; import { workspaceSchematic } from './workspace-schematic'; import { generateGraph, OutputType } from './dep-graph'; const noop = (yargs: yargs.Argv): yargs.Argv => yargs; +export const supportedNxCommands = [ + 'affected', + 'affected:apps', + 'affected:libs', + 'affected:build', + 'affected:test', + 'affected:e2e', + 'affected:dep-graph', + 'affected:lint', + 'dep-graph', + 'format', + 'format:check', + 'format:write', + 'workspace-schematic', + 'workspace-lint', + '--help', + '--version' +]; + /** * Exposing the Yargs commands object so the documentation generator can * parse it. The CLI will consume it and call the `.argv` to bootstrapped @@ -114,15 +132,12 @@ export const commandsObject = yargs args => format('write', args) ) .alias('format:write', 'format') - .command('lint [files..]', 'Lint workspace or list of files', noop, _ => - lint() - ) - .command('update:check', 'Check for workspace updates', noop, _ => - update(['check']) + .command( + 'workspace-lint [files..]', + 'Lint workspace or list of files', + noop, + _ => lint() ) - .command('update:skip', 'Skip workspace updates', noop, _ => update(['skip'])) - .command('update', 'Update workspace', noop, _ => update([])) - .alias('update', 'migrates') // TODO: Remove after 1.0 .command( 'workspace-schematic [name]', 'Runs a workspace schematic from the tools/schematics directory', @@ -147,8 +162,7 @@ export const commandsObject = yargs ) .help('help') .version() - .option('quiet', { type: 'boolean', hidden: true }) - .demandCommand(); + .option('quiet', { type: 'boolean', hidden: true }); function withFormatOptions(yargs: yargs.Argv): yargs.Argv { return withAffectedOptions(yargs).option('apps-and-libs', { diff --git a/packages/workspace/src/command-line/nx.ts b/packages/workspace/src/command-line/nx.ts index 6744a0dda2edc..94f47de4c2efb 100644 --- a/packages/workspace/src/command-line/nx.ts +++ b/packages/workspace/src/command-line/nx.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node -import { commandsObject } from '@nrwl/workspace'; +import { commandsObject, supportedNxCommands } from './nx-commands'; +import { closestCli } from '../utils/app-root'; export interface GlobalNxArgs { help?: boolean; @@ -7,8 +8,10 @@ export interface GlobalNxArgs { quiet?: boolean; } -/** - * The commandsObject is a Yargs object declared in `nx-commands.ts`, - * It is exposed and bootstrapped here to provide CLI features. - */ -commandsObject.argv; // .argv bootstraps the CLI creation; +if (supportedNxCommands.includes(process.argv[2])) { + // The commandsObject is a Yargs object declared in `nx-commands.ts`, + // It is exposed and bootstrapped here to provide CLI features. + commandsObject.argv; // .argv bootstraps the CLI creation; +} else { + require(closestCli(__dirname)); +} diff --git a/packages/workspace/src/command-line/update.ts b/packages/workspace/src/command-line/update.ts deleted file mode 100644 index dbaca34a9dc6e..0000000000000 --- a/packages/workspace/src/command-line/update.ts +++ /dev/null @@ -1,161 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { stripIndents } from '@angular-devkit/core/src/utils/literals'; - -import { updateJsonFile, readCliConfigFile } from '../utils/fileutils'; - -type Migration = { description: string; run(): void }; -type MigrationName = { name: string; migration: Migration }; - -export function update(args: string[]) { - const allMigrations = readAllMigrations(); - const latestMigration = readLatestMigration(); - const migrationsToRun = calculateMigrationsToRun( - allMigrations, - latestMigration - ); - - const command = args[0]; - switch (command) { - case 'check': - check(latestMigration, migrationsToRun); - break; - - case 'skip': - skip(latestMigration, migrationsToRun); - break; - - default: - run(latestMigration, migrationsToRun); - break; - } -} - -function readAllMigrations() { - return fs - .readdirSync(path.join(__dirname, '/../../migrations/legacy-migrations')) - .filter(f => f.endsWith('.js') && !f.endsWith('.d.js')) - .map(file => ({ - migration: require(`../../migrations/legacy-migrations/${file}`).default, - name: path.parse(file).name - })); -} - -function readLatestMigration(): string { - if (!fs.existsSync('.angular-cli.json') && fs.existsSync('angular.json')) { - return 'ANGULAR CLI 6'; - } - const angularCli = readCliConfigFile(); - return angularCli.project.latestMigration; -} - -function calculateMigrationsToRun( - migrations: MigrationName[], - latestMigration: string -) { - if (latestMigration === 'ANGULAR CLI 6') { - console.error(stripIndents` - Nx update is now deprecated. - Please use "ng update @nrwl/workspace" instead. - `); - process.exit(1); - } - const startingWith = latestMigration - ? migrations.findIndex(item => item.name === latestMigration) + 1 - : 0; - return migrations.slice(startingWith); -} - -function skip(latestMigration: string, migrations: MigrationName[]): void { - if (migrations.length === 0) { - process.exit(0); - } - - updateLatestMigration(migrations); - - console.log('The following migrations have been skipped:'); - migrations.forEach(m => { - console.log(`- ${m.name}`); - }); - - const target = migrations[migrations.length - 1].name; - console.log( - `The latestMigration property in .angular-cli.json has been set to "${target}".` - ); -} - -function check(latestMigration: string, migrations: MigrationName[]): void { - if (migrations.length === 0) { - process.exit(0); - } - - console.log( - '-----------------------------------------------------------------------------' - ); - console.log( - '-------------------------------IMPORTANT!!!----------------------------------' - ); - console.log( - '-----------------------------------------------------------------------------' - ); - console.log('Run "npm run update" to run the following migrations:'); - migrations.forEach(m => { - console.log(`- ${m.name}`); - console.log(m.migration.description); - console.log( - '-----------------------------------------------------------------------------' - ); - }); - - const target = migrations[migrations.length - 1].name; - console.log( - `Or run "npm run update:skip" to set the latestMigration property` - ); - console.log(`in .angular-cli.json to: "${target}".`); -} - -function run(latestMigration: string, migrations: MigrationName[]): void { - if (migrations.length === 0) { - console.log('No migrations to run'); - process.exit(0); - } - - migrations.forEach(m => { - try { - console.log(`Running ${m.name}`); - console.log(m.migration.description); - m.migration.run(); - console.log( - '-----------------------------------------------------------------------------' - ); - } catch (e) { - console.error(`Migration ${m.name} failed`); - console.error(e); - console.error(`Please run 'git checkout .'`); - process.exit(1); - } - }); - - updateLatestMigration(migrations); - - console.log(`The following migrations have been run:`); - migrations.forEach(m => { - console.log(`- ${m.name}`); - }); - - const target = migrations[migrations.length - 1].name; - console.log( - `The latestMigration property in .angular-cli.json has been set to "${target}".` - ); -} - -function updateLatestMigration(migrations: MigrationName[]): void { - try { - // we must reread .angular-cli.json because some of the migrations could have modified it - updateJsonFile('.angular-cli.json', angularCliJson => { - angularCliJson.project.latestMigration = - migrations[migrations.length - 1].name; - }); - } catch (e) {} -} diff --git a/packages/workspace/src/migrations/update-8.3.0/rename-lint.ts b/packages/workspace/src/migrations/update-8.3.0/rename-lint.ts new file mode 100644 index 0000000000000..56d601ed276a6 --- /dev/null +++ b/packages/workspace/src/migrations/update-8.3.0/rename-lint.ts @@ -0,0 +1,19 @@ +import { updateJsonInTree } from '../../utils/ast-utils'; + +const updateLint = updateJsonInTree('package.json', json => { + if ( + json.scripts && + json.scripts.lint && + json.scripts.lint.indexOf('nx lint') > -1 + ) { + json.scripts.lint = json.scripts.lint.replace( + 'nx lint', + 'nx workspace-lint' + ); + } + return json; +}); + +export default function() { + return updateLint; +} diff --git a/packages/workspace/src/schematics/ng-add/ng-add.ts b/packages/workspace/src/schematics/ng-add/ng-add.ts index a5a847da809e2..00428a67f1578 100755 --- a/packages/workspace/src/schematics/ng-add/ng-add.ts +++ b/packages/workspace/src/schematics/ng-add/ng-add.ts @@ -38,6 +38,7 @@ function updatePackageJson() { packageJson.scripts = packageJson.scripts || {}; packageJson.scripts = { ...packageJson.scripts, + nx: 'nx', 'affected:apps': 'nx affected:apps', 'affected:libs': 'nx affected:libs', 'affected:build': 'nx affected:build', @@ -51,7 +52,7 @@ function updatePackageJson() { 'format:check': 'nx format:check', update: 'ng update @nrwl/workspace', 'update:check': 'ng update', - lint: 'nx lint && ng lint', + lint: 'nx workspace-lint && ng lint', 'dep-graph': 'nx dep-graph', 'workspace-schematic': 'nx workspace-schematic', help: 'nx help' diff --git a/packages/workspace/src/schematics/workspace/files/package.json__tmpl__ b/packages/workspace/src/schematics/workspace/files/package.json__tmpl__ index ea4815d331e98..5697c93694bb2 100644 --- a/packages/workspace/src/schematics/workspace/files/package.json__tmpl__ +++ b/packages/workspace/src/schematics/workspace/files/package.json__tmpl__ @@ -4,10 +4,11 @@ "license": "MIT", "scripts": { "ng": "ng", + "nx": "nx", "start": "ng serve", "build": "ng build", "test": "ng test", - "lint": "nx lint && ng lint", + "lint": "nx workspace-lint && ng lint", "e2e": "ng e2e", "affected:apps": "nx affected:apps", "affected:libs": "nx affected:libs", diff --git a/packages/workspace/src/utils/app-root.ts b/packages/workspace/src/utils/app-root.ts index e51f8677849ee..15eef8471f985 100644 --- a/packages/workspace/src/utils/app-root.ts +++ b/packages/workspace/src/utils/app-root.ts @@ -11,3 +11,22 @@ function pathInner(dir: string): string { return pathInner(path.dirname(dir)); } } + +export function closestCli(dir: string): string { + if (path.dirname(dir) === dir) { + throw new Error(`Cannot find the Angular CLI to invoke the command`); + } + const cliPath = path.join( + dir, + 'node_modules', + '@angular', + 'cli', + 'lib', + 'init.js' + ); + if (fileExists(cliPath)) { + return cliPath; + } else { + return closestCli(path.dirname(dir)); + } +} diff --git a/scripts/e2e-rerun.sh b/scripts/e2e-rerun.sh old mode 100644 new mode 100755