@yolkai/nx-workspace
Version:
261 lines (259 loc) • 10.8 kB
JavaScript
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const os_1 = require("os");
const yargs = require("yargs");
const versions_1 = require("../utils/versions");
const dep_graph_1 = require("./dep-graph");
const format_1 = require("./format");
const lint_1 = require("./lint");
const list_1 = require("./list");
const report_1 = require("./report");
const workspace_schematic_1 = require("./workspace-schematic");
const affected_1 = require("./affected");
const run_many_1 = require("./run-many");
const noop = (yargs) => yargs;
exports.supportedNxCommands = [
'affected',
'affected:apps',
'affected:libs',
'affected:build',
'affected:test',
'affected:e2e',
'affected:dep-graph',
'affected:lint',
'print-affected',
'dep-graph',
'format',
'format:check',
'format:write',
'workspace-schematic',
'workspace-lint',
'migrate',
'report',
'run-many',
'list',
'help',
'--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
* the CLI. These command declarations needs to be in a different file
* from the `.argv` call, so the object and it's relative scripts can
* be executed correctly.
*/
exports.commandsObject = yargs
.usage('Extensible Dev Tools for Monorepos')
.command('run [project][:target][:configuration] [options, ...]', `
Run a target for a project
(e.g., nx run myapp:serve:production).
You can also use the infix notation to run a target:
(e.g., nx serve myapp --configuration=production)
`)
.command('generate [schematic-collection:][schematic] [options, ...]', `
Generate code
(e.g., nx generate @yolkai/nx-web:app myapp).
`)
.command('affected', 'Run task for affected projects', yargs => withAffectedOptions(withParallel(withTarget(yargs))), args => affected_1.affected('affected', Object.assign({}, args)))
.command('run-many', 'Run task for multiple projects', yargs => withRunManyOptions(withParallel(withTarget(yargs))), args => run_many_1.runMany(Object.assign({}, args)))
.command('affected:apps', 'Print applications affected by changes', withAffectedOptions, args => affected_1.affected('apps', Object.assign({}, args)))
.command('affected:libs', 'Print libraries affected by changes', withAffectedOptions, args => affected_1.affected('libs', Object.assign({}, args)))
.command('affected:build', 'Build applications and publishable libraries affected by changes', yargs => withAffectedOptions(withParallel(yargs)), args => affected_1.affected('affected', Object.assign({}, args, { target: 'build' })))
.command('affected:test', 'Test projects affected by changes', yargs => withAffectedOptions(withParallel(yargs)), args => affected_1.affected('affected', Object.assign({}, args, { target: 'test' })))
.command('affected:e2e', 'Run e2e tests for the applications affected by changes', yargs => withAffectedOptions(withParallel(yargs)), args => affected_1.affected('affected', Object.assign({}, args, { target: 'e2e' })))
.command('affected:dep-graph', 'Graph dependencies affected by changes', yargs => withAffectedOptions(withDepGraphOptions(yargs)), args => affected_1.affected('dep-graph', Object.assign({}, args)))
.command('print-affected', 'Graph execution plan', yargs => withAffectedOptions(withPrintAffectedOptions(yargs)), args => affected_1.affected('print-affected', Object.assign({}, args)))
.command('affected:lint', 'Lint projects affected by changes', yargs => withAffectedOptions(withParallel(yargs)), args => affected_1.affected('affected', Object.assign({}, args, { target: 'lint' })))
.command('dep-graph', 'Graph dependencies within workspace', yargs => withDepGraphOptions(yargs), args => dep_graph_1.generateGraph(args, []))
.command('format:check', 'Check for un-formatted files', withFormatOptions, args => format_1.format('check', args))
.command('format:write', 'Overwrite un-formatted files', withFormatOptions, args => format_1.format('write', args))
.alias('format:write', 'format')
.command('workspace-lint [files..]', 'Lint workspace or list of files', noop, _ => lint_1.workspaceLint())
.command('workspace-schematic [name]', 'Runs a workspace schematic from the tools/schematics directory', yargs => {
yargs.option('list-schematics', {
describe: 'List the available workspace-schematics',
type: 'boolean'
});
/**
* Don't require `name` if only listing available
* schematics
*/
if (yargs.argv.listSchematics !== true) {
yargs.demandOption(['name']).positional('name', {
type: 'string',
describe: 'The name of your schematic`'
});
}
return yargs;
}, () => workspace_schematic_1.workspaceSchematic(process.argv.slice(3)))
.command('migrate', `Creates a migrations file or runs migrations from the migrations file.
- Migrate packages and create migrations.json (e.g., nx migrate @yolkai/nx-workspace@latest)
- Run migrations (e.g., nx migrate --run-migrations=migrations.json)
`, yargs => yargs, () => {
const executable = os_1.platform() === 'win32'
? `.\\node_modules\\.bin\\tao`
: `./node_modules/.bin/tao`;
child_process_1.execSync(`${executable} migrate ${process.argv.slice(3).join(' ')}`, {
stdio: ['inherit', 'inherit', 'inherit']
});
})
.command(report_1.report)
.command(list_1.list)
.help('help')
.version(versions_1.nxVersion)
.option('quiet', { type: 'boolean', hidden: true });
function withFormatOptions(yargs) {
return withAffectedOptions(yargs).option('apps-and-libs', {
type: 'boolean'
});
}
function withPrintAffectedOptions(yargs) {
return yargs.option('select', { type: 'string' });
}
function withAffectedOptions(yargs) {
return yargs
.option('files', {
describe: 'Change the way Nx is calculating the affected command by providing directly changed files, list of files delimited by commas',
type: 'array',
requiresArg: true,
coerce: parseCSV
})
.option('uncommitted', { describe: 'Uncommitted changes' })
.option('untracked', { describe: 'Untracked changes' })
.option('all', { describe: 'All projects' })
.option('base', {
describe: 'Base of the current branch (usually master)',
type: 'string',
requiresArg: true
})
.option('head', {
describe: 'Latest commit of the current branch (usually HEAD)',
type: 'string',
requiresArg: true
})
.group(['base'], 'Run command using --base=[SHA1] (affected by the committed, uncommitted and untracked changes):')
.group(['base', 'head'], 'or using --base=[SHA1] --head=[SHA2] (affected by the committed changes):')
.group(['files', 'uncommitted', 'untracked'], 'or using:')
.implies('head', 'base')
.nargs('uncommitted', 0)
.nargs('untracked', 0)
.nargs('all', 0)
.option('exclude', {
describe: 'Exclude certain projects from being processed',
type: 'array',
coerce: parseCSV,
default: []
})
.options('runner', {
describe: 'This is the name of the tasks runner configured in nx.json',
type: 'string'
})
.options('configuration', {
describe: 'This is the configuration to use when performing tasks on projects',
type: 'string'
})
.options('only-failed', {
describe: 'Isolate projects which previously failed',
type: 'boolean',
default: false
})
.option('verbose', {
describe: 'Print additional error stack trace on failure'
})
.option('plain', {
describe: 'Produces a plain output for affected:apps and affected:libs'
})
.conflicts({
files: ['uncommitted', 'untracked', 'base', 'head', 'all'],
untracked: ['uncommitted', 'files', 'base', 'head', 'all'],
uncommitted: ['files', 'untracked', 'base', 'head', 'all'],
all: ['files', 'untracked', 'uncommitted', 'base', 'head']
});
}
function withRunManyOptions(yargs) {
return yargs
.option('projects', {
describe: 'Projects to run (comma delimited)',
type: 'string'
})
.option('all', { describe: 'All projects' })
.nargs('all', 0)
.check(({ all, projects }) => {
if ((all && projects) || (!all && !projects))
throw new Error('You must provide either --all or --projects');
return true;
})
.options('runner', {
describe: 'This is the name of the tasks runner configured in nx.json',
type: 'string'
})
.options('configuration', {
describe: 'This is the configuration to use when performing tasks on projects',
type: 'string'
})
.options('with-deps', {
describe: 'Include dependencies of specified projects when computing what to run',
type: 'boolean',
default: false
})
.options('only-failed', {
describe: 'Isolate projects which previously failed',
type: 'boolean',
default: false
})
.option('verbose', {
describe: 'Print additional error stack trace on failure'
})
.conflicts({
all: 'projects'
});
}
function withDepGraphOptions(yargs) {
return yargs
.option('file', {
describe: 'output file (e.g. --file=output.json)',
type: 'string'
})
.option('filter', {
describe: 'Use to limit the dependency graph to only show specific projects, list of projects delimited by commas.',
type: 'array',
coerce: parseCSV
})
.option('exclude', {
describe: 'List of projects delimited by commas to exclude from the dependency graph.',
type: 'array',
coerce: parseCSV
});
}
function parseCSV(args) {
return args
.map(arg => arg.split(','))
.reduce((acc, value) => {
return [...acc, ...value];
}, []);
}
function withParallel(yargs) {
return yargs
.option('parallel', {
describe: 'Parallelize the command',
type: 'boolean',
default: false
})
.option('maxParallel', {
describe: 'Max number of parallel processes',
type: 'number',
default: 3
});
}
function withTarget(yargs) {
return yargs.option('target', {
describe: 'Task to run for affected projects',
type: 'string',
requiresArg: true,
demandOption: true,
global: false
});
}