Skip to content

Commit

Permalink
fix(core): custom generators help should print relevant information
Browse files Browse the repository at this point in the history
  • Loading branch information
meeroslav committed Sep 27, 2022
1 parent 24cb3cd commit dda74ec
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 18 deletions.
12 changes: 11 additions & 1 deletion e2e/nx-misc/src/workspace.test.ts
Expand Up @@ -192,6 +192,9 @@ describe('Workspace Tests', () => {
type: 'boolean',
description: 'skip changes to tsconfig',
};
json.properties['inlineprop'] = json.properties['name'];
delete json.properties['name'];

updateFile(
`tools/generators/${custom}/schema.json`,
JSON.stringify(json)
Expand All @@ -202,10 +205,17 @@ describe('Workspace Tests', () => {
`tools/generators/${custom}/index.ts`,
indexFile.replace(
'name: schema.name',
'name: schema.name, directory: schema.directory, skipTsConfig: schema.skipTsConfig'
'inlineprop: schema.inlineprop, directory: schema.directory, skipTsConfig: schema.skipTsConfig'
)
);

const helpOutput = runCLI(`workspace-generator ${custom} --help`);
expect(helpOutput).toContain(
`nx workspace-generator ${custom} [inlineprop] [options]`
);
expect(helpOutput).toContain(`--directory`);
expect(helpOutput).toContain(`--skipTsConfig`);

const workspace = uniq('workspace');
const dryRunOutput = runCLI(
`workspace-generator ${custom} ${workspace} --no-interactive --directory=dir --skipTsConfig=true -d`
Expand Down
128 changes: 111 additions & 17 deletions packages/nx/src/command-line/nx-commands.ts
Expand Up @@ -256,7 +256,7 @@ export const commandsObject = yargs
aliases: ['workspace-schematic [name]'],
builder: async (yargs) =>
linkToNxDevAndExamples(
await withWorkspaceGeneratorOptions(yargs),
await withWorkspaceGeneratorOptions(yargs, process.argv.slice(3)),
'workspace-generator'
),
handler: async () => {
Expand Down Expand Up @@ -763,24 +763,118 @@ function withRunOneOptions(yargs: yargs.Argv) {
}
}

async function withWorkspaceGeneratorOptions(yargs: yargs.Argv) {
yargs
.option('list-generators', {
describe: 'List the available workspace-generators',
type: 'boolean',
})
.positional('name', {
type: 'string',
describe: 'The name of your generator',
});
type WorkspaceGeneratorProperties = {
[name: string]:
| {
type: yargs.Options['type'];
description?: string;
default?: any;
enum?: yargs.Options['type'][];
}
| {
type: yargs.PositionalOptionsType;
description?: string;
default?: any;
enum?: yargs.PositionalOptionsType[];
$default: {
$source: 'argv';
index: number;
};
};
};

function isPositionalProperty(
property: WorkspaceGeneratorProperties[keyof WorkspaceGeneratorProperties]
): property is { type: yargs.PositionalOptionsType } {
return property['$default']?.['$source'] === 'argv';
}

async function withWorkspaceGeneratorOptions(
yargs: yargs.Argv,
args: string[]
) {
// filter out only positional arguments
args = args.filter((a) => !a.startsWith('-'));
if (args.length) {
// this is an actual workspace generator
return withCustomGeneratorOptions(yargs, args[0]);
} else {
yargs
.option('list-generators', {
describe: 'List the available workspace-generators',
type: 'boolean',
})
.positional('name', {
type: 'string',
describe: 'The name of your generator',
});
/**
* Don't require `name` if only listing available
* schematics
*/
if ((await yargs.argv).listGenerators !== true) {
yargs.demandOption('name');
}
return yargs;
}
}

async function withCustomGeneratorOptions(
yargs: yargs.Argv,
generatorName: string
) {
const schema = (
await import('./workspace-generators')
).workspaceGeneratorSchema(generatorName);
const options = [];
const positionals = [];

Object.entries(schema.properties as WorkspaceGeneratorProperties).forEach(
([name, prop]) => {
options.push({
name,
definition: {
describe: prop.description,
type: prop.type,
default: prop.default,
choices: prop.enum,
},
});
if (isPositionalProperty(prop)) {
positionals.push({
name,
definition: {
describe: prop.description,
type: prop.type,
choices: prop.enum,
},
});
}
}
);

/**
* Don't require `name` if only listing available
* schematics
*/
if ((await yargs.argv).listGenerators !== true) {
yargs.demandOption('name');
let command = generatorName;
positionals.forEach(({ name }) => {
command += ` [${name}]`;
});
if (options.length) {
command += ' [options]';
}

yargs.wrap(yargs.terminalWidth()).command(
// this is the default and only command
command,
schema.description || '',
(yargs) => {
options.forEach(({ name, definition }) => {
yargs.option(name, definition);
});
positionals.forEach(({ name, definition }) => {
yargs.positional(name, definition);
});
}
);

return yargs;
}

Expand Down
11 changes: 11 additions & 0 deletions packages/nx/src/command-line/workspace-generators.ts
Expand Up @@ -40,6 +40,17 @@ export async function workspaceGenerators(args: string[]) {
}
}

export function workspaceGeneratorSchema(name: string) {
const schemaFile = path.join(generatorsDir, name, 'schema.json');

if (fileExists(schemaFile)) {
return readJsonFile(schemaFile);
} else {
logger.error(`Cannot find schema for ${name}. Does the generator exist?`);
process.exit(1);
}
}

// compile tools
function compileTools() {
const toolsOutDir = getToolsOutDir();
Expand Down

0 comments on commit dda74ec

Please sign in to comment.