feat(nx): improve the dev ergonomics of create-nx-workspace

This commit is contained in:
Victor Savkin 2019-07-26 19:09:45 -04:00
parent 6d6cbf8b0f
commit 6fd181f348
7 changed files with 122 additions and 39 deletions

View File

@ -11,6 +11,12 @@ ng generate ng-new ...
## Options ## Options
### appName
Type: `string`
Application name.
### commit ### commit
Default: `true` Default: `true`

View File

@ -11,6 +11,12 @@ ng generate tao-new ...
## Options ## Options
### appName
Type: `string`
Application name.
### commit ### commit
Default: `true` Default: `true`

View File

@ -40,7 +40,10 @@ const nxVersion = 'NX_VERSION';
const angularCliVersion = 'ANGULAR_CLI_VERSION'; const angularCliVersion = 'ANGULAR_CLI_VERSION';
const parsedArgs = yargsParser(process.argv, { const parsedArgs = yargsParser(process.argv, {
string: ['cli', 'preset'], string: ['cli', 'preset', 'appName'],
alias: {
appName: 'app-name'
},
boolean: ['help'] boolean: ['help']
}); });
@ -48,15 +51,18 @@ if (parsedArgs.help) {
showHelp(); showHelp();
process.exit(0); process.exit(0);
} }
validateInput(parsedArgs);
const packageManager = determinePackageManager(); const packageManager = determinePackageManager();
determinePreset(parsedArgs).then(preset => { determineWorkspaceName(parsedArgs).then(name => {
determinePreset(parsedArgs).then(preset => {
return determineAppName(preset, parsedArgs).then(appName => {
return determineCli(preset, parsedArgs).then(cli => { return determineCli(preset, parsedArgs).then(cli => {
const tmpDir = createSandbox(packageManager, cli); const tmpDir = createSandbox(packageManager, cli);
createApp(tmpDir, cli, parsedArgs, preset); createApp(tmpDir, cli, parsedArgs, name, preset, appName);
showNxWarning(); showNxWarning();
showCliWarning(preset, parsedArgs); showCliWarning(preset, parsedArgs);
}); });
});
});
}); });
function showHelp() { function showHelp() {
@ -73,6 +79,8 @@ function showHelp() {
.map(o => '"' + o.value + '"') .map(o => '"' + o.value + '"')
.join(', ')}) .join(', ')})
appName the name of the application created by some presets
cli CLI to power the Nx workspace (options: "nx", "angular") cli CLI to power the Nx workspace (options: "nx", "angular")
[new workspace options] any 'new workspace' options [new workspace options] any 'new workspace' options
@ -103,32 +111,46 @@ function determinePackageManager() {
return packageManager; return packageManager;
} }
function validateInput(parsedArgs: any) { function determineWorkspaceName(parsedArgs: any) {
const projectName = parsedArgs._[2]; const workspaceName = parsedArgs._[2];
if (!projectName) { if (workspaceName) {
return Promise.resolve(workspaceName);
} else {
return inquirer
.prompt([
{
name: 'WorkspaceName',
message: `Workspace name (e.g., org name) `,
type: 'string'
}
])
.then(a => {
if (!a.WorkspaceName) {
output.error({ output.error({
title: 'A project name is required when creating a new workspace', title: 'Invalid workspace name',
bodyLines: [ bodyLines: [`Workspace name cannot be empty`]
output.colors.gray('For example:'),
'',
`${output.colors.gray('>')} create-nx-workspace my-new-workspace`
]
}); });
process.exit(1); process.exit(1);
} }
return a.WorkspaceName;
});
}
return projectName; return workspaceName;
} }
function determinePreset(parsedArgs: any): Promise<string> { function determinePreset(parsedArgs: any): Promise<string> {
if (parsedArgs.preset) { if (parsedArgs.preset) {
if (presetOptions.map(o => o.value).indexOf(parsedArgs.preset) === -1) { if (presetOptions.map(o => o.value).indexOf(parsedArgs.preset) === -1) {
console.error( output.error({
`Invalid preset. It must be one of the following: ${presetOptions title: 'Invalid preset',
.map(o => '"' + o.value + '"') bodyLines: [
.join(', ')}.` `It must be one of the following:`,
); '',
...presetOptions.map(o => o.value)
]
});
process.exit(1); process.exit(1);
} else { } else {
return Promise.resolve(parsedArgs.preset); return Promise.resolve(parsedArgs.preset);
@ -148,6 +170,35 @@ function determinePreset(parsedArgs: any): Promise<string> {
} }
} }
function determineAppName(preset: string, parsedArgs: any): Promise<string> {
if (preset === 'empty') {
return Promise.resolve('');
}
if (parsedArgs.appName) {
return Promise.resolve(parsedArgs.appName);
} else {
return inquirer
.prompt([
{
name: 'AppName',
message: `Application name `,
type: 'string'
}
])
.then(a => {
if (!a.AppName) {
output.error({
title: 'Invalid name',
bodyLines: [`Name cannot be empty`]
});
process.exit(1);
}
return a.AppName;
});
}
}
function determineCli(preset: string, parsedArgs: any) { function determineCli(preset: string, parsedArgs: any) {
const angular = { const angular = {
package: '@angular/cli', package: '@angular/cli',
@ -163,9 +214,10 @@ function determineCli(preset: string, parsedArgs: any) {
if (parsedArgs.cli) { if (parsedArgs.cli) {
if (['nx', 'angular'].indexOf(parsedArgs.cli) === -1) { if (['nx', 'angular'].indexOf(parsedArgs.cli) === -1) {
console.error( output.error({
`Invalid cli. It must be one of the following: "nx", "angular".` title: 'Invalid cli',
); bodyLines: [`It must be one of the following:`, '', 'nx', 'angular']
});
process.exit(1); process.exit(1);
} }
return Promise.resolve(parsedArgs.cli === 'angular' ? angular : nx); return Promise.resolve(parsedArgs.cli === 'angular' ? angular : nx);
@ -231,16 +283,22 @@ function createApp(
tmpDir: string, tmpDir: string,
cli: { command: string }, cli: { command: string },
parsedArgs: any, parsedArgs: any,
preset: string name: string,
preset: string,
appName: string
) { ) {
// creating the app itself // creating the app itself
const args = process.argv const args = [
.slice(2) name,
...process.argv
.slice(parsedArgs._[2] ? 3 : 2)
.filter(a => !a.startsWith('--cli')) // not used by the new command .filter(a => !a.startsWith('--cli')) // not used by the new command
.map(a => `"${a}"`) .map(a => `"${a}"`)
.join(' '); ].join(' ');
const presetArg = parsedArgs.preset ? '' : ` --preset=${preset}`; const presetArg = parsedArgs.preset
? ''
: ` --preset=${preset} --appName=${appName}`;
console.log(`new ${args}${presetArg} --collection=@nrwl/workspace`); console.log(`new ${args}${presetArg} --collection=@nrwl/workspace`);
execSync( execSync(

View File

@ -117,6 +117,10 @@
} }
] ]
} }
},
"appName": {
"type": "string",
"description": "Application name."
} }
} }
} }

View File

@ -132,7 +132,7 @@ function connectFrontendAndApi(options: Schema) {
) )
]); ]);
const scope = options.npmScope ? options.npmScope : options.name; const scope = options.npmScope;
const style = options.style ? options.style : 'css'; const style = options.style ? options.style : 'css';
host.overwrite( host.overwrite(
`apps/${options.name}/src/app/app.component.ts`, `apps/${options.name}/src/app/app.component.ts`,

View File

@ -27,6 +27,7 @@ import { platform } from 'os';
export interface Schema { export interface Schema {
directory: string; directory: string;
name: string; name: string;
appName: string;
npmScope?: string; npmScope?: string;
skipInstall?: boolean; skipInstall?: boolean;
skipGit?: boolean; skipGit?: boolean;
@ -62,11 +63,15 @@ function createPresetTaskExecutor(cli: string, opts: Schema) {
const args = [ const args = [
`g`, `g`,
`@nrwl/workspace:preset`, `@nrwl/workspace:preset`,
`--name=${opts.name}`, `--name=${opts.appName}`,
opts.style ? `--style=${opts.style}` : null, opts.style ? `--style=${opts.style}` : null,
opts.npmScope ? `--npmScope=${opts.npmScope}` : null, opts.npmScope
? `--npmScope=${opts.npmScope}`
: `--npmScope=${opts.name}`,
opts.preset ? `--preset=${opts.preset}` : null opts.preset ? `--preset=${opts.preset}` : null
].filter(e => !!e); ].filter(e => !!e);
console.log('here', path.join(process.cwd(), opts.directory));
return new Observable(obs => { return new Observable(obs => {
spawn(executable, args, spawnOptions).on('close', (code: number) => { spawn(executable, args, spawnOptions).on('close', (code: number) => {
if (code === 0) { if (code === 0) {

View File

@ -117,6 +117,10 @@
} }
] ]
} }
},
"appName": {
"type": "string",
"description": "Application name."
} }
} }
} }