nx/packages/create-nx-plugin/bin/create-nx-plugin.ts
Jason Jean 341f2951a8
feat(misc): add onboarding a/b testing (#27217)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

The onboarding message during `create-nx-workspace` is not ideal.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

We are A/b testing some options for the `create-nx-workspace` onboarding
message.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-07-30 19:33:38 -04:00

201 lines
5.6 KiB
JavaScript

#!/usr/bin/env node
import chalk = require('chalk');
import enquirer = require('enquirer');
import yargs = require('yargs');
import {
determineDefaultBase,
determineNxCloud,
determinePackageManager,
} from 'create-nx-workspace/src/internal-utils/prompts';
import {
withAllPrompts,
withGitOptions,
withNxCloud,
withOptions,
withPackageManager,
} from 'create-nx-workspace/src/internal-utils/yargs-options';
import { createWorkspace, CreateWorkspaceOptions } from 'create-nx-workspace';
import { output } from 'create-nx-workspace/src/utils/output';
import { NxCloud } from 'create-nx-workspace/src/utils/nx/nx-cloud';
import type { PackageManager } from 'create-nx-workspace/src/utils/package-manager';
import { showNxWarning } from 'create-nx-workspace/src/utils/nx/show-nx-warning';
import {
messages,
recordStat,
} from 'create-nx-workspace/src/utils/nx/ab-testing';
export const yargsDecorator = {
'Options:': `${chalk.green`Options`}:`,
'Examples:': `${chalk.green`Examples`}:`,
boolean: `${chalk.blue`boolean`}`,
count: `${chalk.blue`count`}`,
string: `${chalk.blue`string`}`,
array: `${chalk.blue`array`}`,
required: `${chalk.blue`required`}`,
'default:': `${chalk.blue`default`}:`,
'choices:': `${chalk.blue`choices`}:`,
'aliases:': `${chalk.blue`aliases`}:`,
};
const nxVersion = require('../package.json').version;
async function determinePluginName(
parsedArgs: CreateNxPluginArguments
): Promise<string> {
if (parsedArgs.pluginName) {
return parsedArgs.pluginName;
}
const results = await enquirer.prompt<{ pluginName: string }>([
{
name: 'pluginName',
message: `Plugin name `,
type: 'input',
validate: (s_1) => (s_1.length ? true : 'Plugin name cannot be empty'),
},
]);
return results.pluginName;
}
async function determineCreatePackageName(
parsedArgs: CreateNxPluginArguments
): Promise<string> {
if (parsedArgs.createPackageName) {
return parsedArgs.createPackageName;
}
const results = await enquirer.prompt<{ createPackageName: string }>([
{
name: 'createPackageName',
message: `Create a package which can be used by npx to create a new workspace (Leave blank to not create this package)`,
type: 'input',
},
]);
return results.createPackageName;
}
interface CreateNxPluginArguments {
pluginName: string;
createPackageName?: string;
packageManager: PackageManager;
allPrompts: boolean;
nxCloud: NxCloud;
}
export const commandsObject: yargs.Argv<CreateNxPluginArguments> = yargs
.wrap(yargs.terminalWidth())
.parserConfiguration({
'strip-dashed': true,
'dot-notation': true,
})
.command(
// this is the default and only command
'$0 [name] [options]',
'Create a new Nx plugin workspace',
(yargs) =>
withOptions(
yargs
.positional('pluginName', {
describe: chalk.dim`Plugin name`,
type: 'string',
alias: ['name'],
})
.option('createPackageName', {
describe: 'Name of the CLI package to create workspace with plugin',
type: 'string',
}),
withNxCloud,
withAllPrompts,
withPackageManager,
withGitOptions
),
async (argv: yargs.ArgumentsCamelCase<CreateNxPluginArguments>) => {
await main(argv).catch((error) => {
const { version } = require('../package.json');
output.error({
title: `Something went wrong! v${version}`,
});
throw error;
});
},
[normalizeArgsMiddleware]
)
.help('help', chalk.dim`Show help`)
.updateLocale(yargsDecorator)
.version(
'version',
chalk.dim`Show version`,
nxVersion
) as yargs.Argv<CreateNxPluginArguments>;
async function main(parsedArgs: yargs.Arguments<CreateNxPluginArguments>) {
const populatedArguments: CreateNxPluginArguments & CreateWorkspaceOptions = {
...parsedArgs,
name: parsedArgs.pluginName.includes('/')
? parsedArgs.pluginName.split('/')[1]
: parsedArgs.pluginName,
};
output.log({
title: `Creating an Nx v${nxVersion} plugin.`,
bodyLines: [
'To make sure the command works reliably in all environments, and that the preset is applied correctly,',
`Nx will run "${parsedArgs.packageManager} install" several times. Please wait.`,
],
});
const workspaceInfo = await createWorkspace(
`@nx/plugin@${nxVersion}`,
populatedArguments
);
showNxWarning(parsedArgs.pluginName);
await recordStat({
nxVersion,
command: 'create-nx-workspace',
useCloud: parsedArgs.nxCloud !== 'skip',
meta: [
messages.codeOfSelectedPromptMessage('setupCI'),
messages.codeOfSelectedPromptMessage('setupNxCloud'),
],
});
if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
console.log(workspaceInfo.nxCloudInfo);
}
}
/**
* This function is used to normalize the arguments passed to the command.
* It would:
* - normalize the preset.
* @param argv user arguments
*/
async function normalizeArgsMiddleware(
argv: yargs.Arguments<CreateNxPluginArguments>
): Promise<void> {
try {
const pluginName = await determinePluginName(argv);
const createPackageName = await determineCreatePackageName(argv);
const packageManager = await determinePackageManager(argv);
const defaultBase = await determineDefaultBase(argv);
const nxCloud = await determineNxCloud(argv);
Object.assign(argv, {
pluginName,
createPackageName,
nxCloud,
packageManager,
defaultBase,
} as Partial<CreateNxPluginArguments>);
} catch (e) {
console.error(e);
process.exit(1);
}
}
// Trigger Yargs
commandsObject.argv;