feat(misc): expose nx init command flags (#16287)

This commit is contained in:
Leosvel Pérez Espinosa 2023-04-19 18:32:51 +01:00 committed by GitHub
parent 5d7ad348e0
commit 6677a9c932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 141 additions and 143 deletions

View File

@ -30,7 +30,9 @@ describe('nx init (Angular CLI)', () => {
it('should successfully convert an Angular CLI workspace to an Nx standalone workspace', () => { it('should successfully convert an Angular CLI workspace to an Nx standalone workspace', () => {
const output = runCommand( const output = runCommand(
`${pmc.runUninstalledPackage} nx@${getPublishedVersion()} init -y` `${
pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init --no-interactive`
); );
expect(output).toContain('🎉 Done!'); expect(output).toContain('🎉 Done!');
@ -64,7 +66,7 @@ describe('nx init (Angular CLI)', () => {
const output = runCommand( const output = runCommand(
`${ `${
pmc.runUninstalledPackage pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init -y --integrated` } nx@${getPublishedVersion()} init --integrated --no-interactive`
); );
expect(output).toContain('🎉 Done!'); expect(output).toContain('🎉 Done!');

View File

@ -40,7 +40,7 @@ describe('nx init (Monorepo)', () => {
const output = runCommand( const output = runCommand(
`${ `${
pmc.runUninstalledPackage pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init -y --cacheable=build` } nx@${getPublishedVersion()} init --cacheable=build --no-interactive`
); );
expect(output).toContain('🎉 Done!'); expect(output).toContain('🎉 Done!');

View File

@ -34,7 +34,7 @@ describe('nx init (for NestCLI)', () => {
const output = execSync( const output = execSync(
`${ `${
pmc.runUninstalledPackage pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init -y --cacheable=format`, } nx@${getPublishedVersion()} init --cacheable=format --no-interactive`,
{ {
cwd: projectRoot, cwd: projectRoot,
encoding: 'utf-8', encoding: 'utf-8',

View File

@ -32,7 +32,7 @@ describe('nx init (NPM repo)', () => {
const output = runCommand( const output = runCommand(
`${ `${
pmc.runUninstalledPackage pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init -y --cacheable=echo` } nx@${getPublishedVersion()} init --cacheable=echo --no-interactive`
); );
console.log(output); console.log(output);
expect(output).toContain('Enabled computation caching'); expect(output).toContain('Enabled computation caching');
@ -61,7 +61,7 @@ describe('nx init (NPM repo)', () => {
runCommand( runCommand(
`${ `${
pmc.runUninstalledPackage pmc.runUninstalledPackage
} nx@${getPublishedVersion()} init -y --cacheable=compound` } nx@${getPublishedVersion()} init --cacheable=compound --no-interactive`
); );
const output = runCommand('npm run compound TEST'); const output = runCommand('npm run compound TEST');

View File

@ -14,7 +14,13 @@ import { directoryExists, readJsonFile } from '../utils/fileutils';
import { PackageJson } from '../utils/package-json'; import { PackageJson } from '../utils/package-json';
export interface InitArgs { export interface InitArgs {
addE2e: boolean;
force: boolean;
integrated: boolean; integrated: boolean;
interactive: boolean;
vite: boolean;
nxCloud?: boolean;
cacheable?: string[];
} }
export async function initHandler(options: InitArgs) { export async function initHandler(options: InitArgs) {
@ -40,15 +46,15 @@ export async function initHandler(options: InitArgs) {
} else if (existsSync('package.json')) { } else if (existsSync('package.json')) {
const packageJson: PackageJson = readJsonFile('package.json'); const packageJson: PackageJson = readJsonFile('package.json');
if (existsSync('angular.json')) { if (existsSync('angular.json')) {
await addNxToAngularCliRepo(options.integrated); await addNxToAngularCliRepo(options);
} else if (isCRA(packageJson)) { } else if (isCRA(packageJson)) {
await addNxToCraRepo(options.integrated); await addNxToCraRepo(options);
} else if (isNestCLI(packageJson)) { } else if (isNestCLI(packageJson)) {
await addNxToNest(packageJson); await addNxToNest(options, packageJson);
} else if (isMonorepo(packageJson)) { } else if (isMonorepo(packageJson)) {
await addNxToMonorepo(); await addNxToMonorepo(options);
} else { } else {
await addNxToNpmRepo(); await addNxToNpmRepo(options);
} }
} else { } else {
const useDotNxFolder = await prompt<{ useDotNxFolder: string }>([ const useDotNxFolder = await prompt<{ useDotNxFolder: string }>([

View File

@ -2,14 +2,12 @@ import * as chalk from 'chalk';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import * as path from 'path'; import * as path from 'path';
import * as yargs from 'yargs'; import * as yargs from 'yargs';
import { nxVersion } from '../utils/versions';
import { examples } from './examples';
import { workspaceRoot } from '../utils/workspace-root';
import { getPackageManagerCommand } from '../utils/package-manager';
import { writeJsonFile } from '../utils/fileutils';
import { WatchArguments } from './watch';
import { runNxSync } from '../utils/child-process'; import { runNxSync } from '../utils/child-process';
import { stripIndents } from '../utils/strip-indents'; import { writeJsonFile } from '../utils/fileutils';
import { getPackageManagerCommand } from '../utils/package-manager';
import { workspaceRoot } from '../utils/workspace-root';
import { examples } from './examples';
import { WatchArguments } from './watch';
// Ensure that the output takes up the available width of the terminal. // Ensure that the output takes up the available width of the terminal.
yargs.wrap(yargs.terminalWidth()); yargs.wrap(yargs.terminalWidth());
@ -305,7 +303,7 @@ export const commandsObject = yargs
command: 'init', command: 'init',
describe: describe:
'Adds Nx to any type of workspace. It installs nx, creates an nx.json configuration file and optionally sets up distributed caching. For more info, check https://nx.dev/recipes/adopting-nx.', 'Adds Nx to any type of workspace. It installs nx, creates an nx.json configuration file and optionally sets up distributed caching. For more info, check https://nx.dev/recipes/adopting-nx.',
builder: (yargs) => withIntegratedOption(yargs), builder: (yargs) => withInitOptions(yargs),
handler: async (args: any) => { handler: async (args: any) => {
await (await import('./init')).initHandler(args); await (await import('./init')).initHandler(args);
process.exit(0); process.exit(0);
@ -1122,14 +1120,54 @@ function withListOptions(yargs) {
}); });
} }
function withIntegratedOption(yargs) { function withInitOptions(yargs: yargs.Argv) {
return yargs.option('integrated', { // TODO(leo): make them visible in docs/help once the feature is released in Nx 16
type: 'boolean', return yargs
description: .options('nxCloud', {
'Migrate to an Nx integrated layout workspace. Only for CRA and Angular projects.', type: 'boolean',
// TODO(leo): keep it hidden until feature is released description: 'Set up distributed caching with Nx Cloud.',
hidden: true, hidden: true,
}); })
.option('interactive', {
describe: 'When false disables interactive input prompts for options.',
type: 'boolean',
default: true,
hidden: true,
})
.option('integrated', {
type: 'boolean',
description:
'Migrate to an Nx integrated layout workspace. Only for Angular CLI workspaces and CRA projects.',
default: false,
hidden: true,
})
.option('addE2e', {
describe:
'Set up Cypress E2E tests in integrated workspaces. Only for CRA projects.',
type: 'boolean',
default: false,
hidden: true,
})
.option('force', {
describe:
'Force the migration to continue and ignore custom webpack setup or uncommitted changes. Only for CRA projects.',
type: 'boolean',
default: false,
hidden: true,
})
.options('vite', {
type: 'boolean',
description: 'Use Vite as the bundler. Only for CRA projects.',
default: true,
hidden: true,
})
.options('cacheable', {
type: 'string',
description:
'Comma-separated list of cacheable operations. Only used for internal testing.',
coerce: parseCSV,
hidden: true,
});
} }
function runMigration() { function runMigration() {

View File

@ -2,7 +2,7 @@ import { prompt } from 'enquirer';
import { readdirSync, readFileSync, statSync } from 'fs'; import { readdirSync, readFileSync, statSync } from 'fs';
import ignore from 'ignore'; import ignore from 'ignore';
import { join, relative } from 'path'; import { join, relative } from 'path';
import * as yargsParser from 'yargs-parser'; import { InitArgs } from '../command-line/init';
import { readJsonFile } from '../utils/fileutils'; import { readJsonFile } from '../utils/fileutils';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { getPackageManagerCommand } from '../utils/package-manager'; import { getPackageManagerCommand } from '../utils/package-manager';
@ -15,15 +15,9 @@ import {
runInstall, runInstall,
} from './utils'; } from './utils';
const parsedArgs = yargsParser(process.argv, { type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'>;
boolean: ['yes'],
string: ['cacheable'], // only used for testing
alias: {
yes: ['y'],
},
});
export async function addNxToMonorepo() { export async function addNxToMonorepo(options: Options) {
const repoRoot = process.cwd(); const repoRoot = process.cwd();
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
@ -36,7 +30,7 @@ export async function addNxToMonorepo() {
let scriptOutputs = {} as { [script: string]: string }; let scriptOutputs = {} as { [script: string]: string };
let useNxCloud: boolean; let useNxCloud: boolean;
if (parsedArgs.yes !== true && scripts.length > 0) { if (options.interactive && scripts.length > 0) {
output.log({ output.log({
title: title:
'🧑‍🔧 Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration', '🧑‍🔧 Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration',
@ -78,13 +72,13 @@ export async function addNxToMonorepo() {
)[scriptName]; )[scriptName];
} }
useNxCloud = await askAboutNxCloud(); useNxCloud = options.nxCloud ?? (await askAboutNxCloud());
} else { } else {
targetDefaults = []; targetDefaults = [];
cacheableOperations = parsedArgs.cacheable cacheableOperations = options.cacheable ?? [];
? parsedArgs.cacheable.split(',') useNxCloud =
: []; options.nxCloud ??
useNxCloud = false; (options.interactive ? await askAboutNxCloud() : false);
} }
createNxJsonFile( createNxJsonFile(

View File

@ -1,10 +1,13 @@
import { unlinkSync, writeFileSync } from 'fs-extra';
import * as yargsParser from 'yargs-parser';
import * as enquirer from 'enquirer'; import * as enquirer from 'enquirer';
import { unlinkSync, writeFileSync } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import { InitArgs } from '../command-line/init';
import { NrwlJsPluginConfig, NxJsonConfiguration } from '../config/nx-json';
import { ProjectConfiguration } from '../config/workspace-json-project-json';
import { fileExists, readJsonFile, writeJsonFile } from '../utils/fileutils';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { PackageJson } from '../utils/package-json'; import { PackageJson } from '../utils/package-json';
import { fileExists, readJsonFile, writeJsonFile } from '../utils/fileutils'; import { getPackageManagerCommand } from '../utils/package-manager';
import { import {
addDepsToPackageJson, addDepsToPackageJson,
askAboutNxCloud, askAboutNxCloud,
@ -14,20 +17,11 @@ import {
printFinalMessage, printFinalMessage,
runInstall, runInstall,
} from './utils'; } from './utils';
import { getPackageManagerCommand } from '../utils/package-manager';
import { ProjectConfiguration } from '../config/workspace-json-project-json';
import { NrwlJsPluginConfig, NxJsonConfiguration } from '../config/nx-json';
type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'>;
type NestCLIConfiguration = any; type NestCLIConfiguration = any;
const parsedArgs = yargsParser(process.argv, {
boolean: ['yes'],
string: ['cacheable'], // only used for testing
alias: {
yes: ['y'],
},
});
export async function addNxToNest(packageJson: PackageJson) { export async function addNxToNest(options: Options, packageJson: PackageJson) {
const repoRoot = process.cwd(); const repoRoot = process.cwd();
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
@ -69,7 +63,7 @@ export async function addNxToNest(packageJson: PackageJson) {
let scriptOutputs = {}; let scriptOutputs = {};
let useNxCloud: boolean; let useNxCloud: boolean;
if (parsedArgs.yes !== true) { if (options.interactive) {
output.log({ output.log({
title: title:
'🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration', '🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
@ -98,12 +92,10 @@ export async function addNxToNest(packageJson: PackageJson) {
)[scriptName]; )[scriptName];
} }
useNxCloud = await askAboutNxCloud(); useNxCloud = options.nxCloud ?? (await askAboutNxCloud());
} else { } else {
cacheableOperations = parsedArgs.cacheable cacheableOperations = options.cacheable ?? [];
? parsedArgs.cacheable.split(',') useNxCloud = options.nxCloud ?? false;
: [];
useNxCloud = false;
} }
createNxJsonFile( createNxJsonFile(

View File

@ -1,5 +1,5 @@
import * as enquirer from 'enquirer'; import * as enquirer from 'enquirer';
import * as yargsParser from 'yargs-parser'; import { InitArgs } from '../command-line/init';
import { readJsonFile } from '../utils/fileutils'; import { readJsonFile } from '../utils/fileutils';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { getPackageManagerCommand } from '../utils/package-manager'; import { getPackageManagerCommand } from '../utils/package-manager';
@ -13,15 +13,9 @@ import {
runInstall, runInstall,
} from './utils'; } from './utils';
const parsedArgs = yargsParser(process.argv, { type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'>;
boolean: ['yes'],
string: ['cacheable'], // only used for testing
alias: {
yes: ['y'],
},
});
export async function addNxToNpmRepo() { export async function addNxToNpmRepo(options: Options) {
const repoRoot = process.cwd(); const repoRoot = process.cwd();
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
@ -35,7 +29,7 @@ export async function addNxToNpmRepo() {
(s) => !s.startsWith('pre') && !s.startsWith('post') (s) => !s.startsWith('pre') && !s.startsWith('post')
); );
if (parsedArgs.yes !== true) { if (options.interactive) {
output.log({ output.log({
title: title:
'🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration', '🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
@ -66,12 +60,10 @@ export async function addNxToNpmRepo() {
)[scriptName]; )[scriptName];
} }
useNxCloud = await askAboutNxCloud(); useNxCloud = options.nxCloud ?? (await askAboutNxCloud());
} else { } else {
cacheableOperations = parsedArgs.cacheable cacheableOperations = options.cacheable ?? [];
? parsedArgs.cacheable.split(',') useNxCloud = options.nxCloud ?? false;
: [];
useNxCloud = false;
} }
createNxJsonFile(repoRoot, [], cacheableOperations, {}); createNxJsonFile(repoRoot, [], cacheableOperations, {});

View File

@ -14,8 +14,7 @@ import {
import { setupIntegratedWorkspace } from './integrated-workspace'; import { setupIntegratedWorkspace } from './integrated-workspace';
import { getLegacyMigrationFunctionIfApplicable } from './legacy-angular-versions'; import { getLegacyMigrationFunctionIfApplicable } from './legacy-angular-versions';
import { setupStandaloneWorkspace } from './standalone-workspace'; import { setupStandaloneWorkspace } from './standalone-workspace';
import type { AngularJsonConfig } from './types'; import type { AngularJsonConfig, Options } from './types';
import yargsParser = require('yargs-parser');
const defaultCacheableOperations: string[] = [ const defaultCacheableOperations: string[] = [
'build', 'build',
@ -23,25 +22,17 @@ const defaultCacheableOperations: string[] = [
'test', 'test',
'lint', 'lint',
]; ];
const parsedArgs = yargsParser(process.argv, {
boolean: ['yes'],
string: ['cacheable'], // only used for testing
alias: {
yes: ['y'],
},
});
let repoRoot: string; let repoRoot: string;
let workspaceTargets: string[]; let workspaceTargets: string[];
export async function addNxToAngularCliRepo(integrated: boolean) { export async function addNxToAngularCliRepo(options: Options) {
repoRoot = process.cwd(); repoRoot = process.cwd();
output.log({ title: '🧐 Checking versions compatibility' }); output.log({ title: '🧐 Checking versions compatibility' });
const legacyMigrationFn = await getLegacyMigrationFunctionIfApplicable( const legacyMigrationFn = await getLegacyMigrationFunctionIfApplicable(
repoRoot, repoRoot,
integrated, options
parsedArgs.yes !== true
); );
if (legacyMigrationFn) { if (legacyMigrationFn) {
output.log({ title: '💽 Running migration for a legacy Angular version' }); output.log({ title: '💽 Running migration for a legacy Angular version' });
@ -55,16 +46,17 @@ export async function addNxToAngularCliRepo(integrated: boolean) {
}); });
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
const cacheableOperations = !integrated const cacheableOperations = !options.integrated
? await collectCacheableOperations() ? await collectCacheableOperations(options)
: []; : [];
const useNxCloud = parsedArgs.yes !== true ? await askAboutNxCloud() : false; const useNxCloud =
options.nxCloud ?? (options.interactive ? await askAboutNxCloud() : false);
output.log({ title: '📦 Installing dependencies' }); output.log({ title: '📦 Installing dependencies' });
installDependencies(useNxCloud); installDependencies(useNxCloud);
output.log({ title: '📝 Setting up workspace' }); output.log({ title: '📝 Setting up workspace' });
await setupWorkspace(cacheableOperations, integrated); await setupWorkspace(cacheableOperations, options.integrated);
if (useNxCloud) { if (useNxCloud) {
output.log({ title: '🛠️ Setting up Nx Cloud' }); output.log({ title: '🛠️ Setting up Nx Cloud' });
@ -79,7 +71,7 @@ export async function addNxToAngularCliRepo(integrated: boolean) {
}); });
} }
async function collectCacheableOperations(): Promise<string[]> { async function collectCacheableOperations(options: Options): Promise<string[]> {
let cacheableOperations: string[]; let cacheableOperations: string[];
workspaceTargets = getWorkspaceTargets(); workspaceTargets = getWorkspaceTargets();
@ -87,7 +79,7 @@ async function collectCacheableOperations(): Promise<string[]> {
(t) => workspaceTargets.includes(t) (t) => workspaceTargets.includes(t)
); );
if (parsedArgs.yes !== true) { if (options.interactive) {
output.log({ output.log({
title: title:
'🧑‍🔧 Please answer the following questions about the targets found in your angular.json in order to generate task runner configuration', '🧑‍🔧 Please answer the following questions about the targets found in your angular.json in order to generate task runner configuration',
@ -107,9 +99,8 @@ async function collectCacheableOperations(): Promise<string[]> {
])) as any ])) as any
).cacheableOperations; ).cacheableOperations;
} else { } else {
cacheableOperations = parsedArgs.cacheable cacheableOperations =
? parsedArgs.cacheable.split(',') options.cacheable ?? defaultCacheableTargetsInWorkspace;
: defaultCacheableTargetsInWorkspace;
} }
return cacheableOperations; return cacheableOperations;

View File

@ -12,6 +12,7 @@ import {
resolvePackageVersionUsingRegistry, resolvePackageVersionUsingRegistry,
} from '../../utils/package-manager'; } from '../../utils/package-manager';
import { askAboutNxCloud, initCloud, printFinalMessage } from '../utils'; import { askAboutNxCloud, initCloud, printFinalMessage } from '../utils';
import type { Options } from './types';
// map of Angular major versions to Nx versions to use for legacy `nx init` migrations, // map of Angular major versions to Nx versions to use for legacy `nx init` migrations,
// key is major Angular version and value is Nx version to use // key is major Angular version and value is Nx version to use
@ -23,8 +24,7 @@ const versionWithConsolidatedPackages = '13.9.0';
export async function getLegacyMigrationFunctionIfApplicable( export async function getLegacyMigrationFunctionIfApplicable(
repoRoot: string, repoRoot: string,
isIntegratedMigration: boolean, options: Options
interactive: boolean
): Promise<() => Promise<void> | null> { ): Promise<() => Promise<void> | null> {
const angularVersion = const angularVersion =
readModulePackageJson('@angular/core').packageJson.version; readModulePackageJson('@angular/core').packageJson.version;
@ -44,7 +44,7 @@ export async function getLegacyMigrationFunctionIfApplicable(
pkgName, pkgName,
`^${majorAngularVersion}.0.0` `^${majorAngularVersion}.0.0`
); );
const preserveAngularCliLayoutFlag = !isIntegratedMigration const preserveAngularCliLayoutFlag = !options.integrated
? '--preserveAngularCLILayout' ? '--preserveAngularCLILayout'
: '--preserveAngularCLILayout=false'; : '--preserveAngularCLILayout=false';
legacyMigrationCommand = `ng g ${pkgName}:ng-add ${preserveAngularCliLayoutFlag}`; legacyMigrationCommand = `ng g ${pkgName}:ng-add ${preserveAngularCliLayoutFlag}`;
@ -52,7 +52,7 @@ export async function getLegacyMigrationFunctionIfApplicable(
// for v13, the migration was in @nrwl/angular:ng-add // for v13, the migration was in @nrwl/angular:ng-add
pkgName = '@nrwl/angular'; pkgName = '@nrwl/angular';
pkgVersion = await resolvePackageVersion(pkgName, '~14.1.0'); pkgVersion = await resolvePackageVersion(pkgName, '~14.1.0');
const preserveAngularCliLayoutFlag = !isIntegratedMigration const preserveAngularCliLayoutFlag = !options.integrated
? '--preserve-angular-cli-layout' ? '--preserve-angular-cli-layout'
: '--preserve-angular-cli-layout=false'; : '--preserve-angular-cli-layout=false';
legacyMigrationCommand = `ng g ${pkgName}:ng-add ${preserveAngularCliLayoutFlag}`; legacyMigrationCommand = `ng g ${pkgName}:ng-add ${preserveAngularCliLayoutFlag}`;
@ -70,7 +70,9 @@ export async function getLegacyMigrationFunctionIfApplicable(
return async () => { return async () => {
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
const useNxCloud = interactive ? await askAboutNxCloud() : false; const useNxCloud =
options.nxCloud ??
(options.interactive ? await askAboutNxCloud() : false);
output.log({ title: '📦 Installing dependencies' }); output.log({ title: '📦 Installing dependencies' });
const pmc = getPackageManagerCommand(); const pmc = getPackageManagerCommand();

View File

@ -1,5 +1,11 @@
import { InitArgs } from '../../command-line/init';
import type { TargetConfiguration } from '../../config/workspace-json-project-json'; import type { TargetConfiguration } from '../../config/workspace-json-project-json';
export type Options = Pick<
InitArgs,
'nxCloud' | 'integrated' | 'interactive' | 'cacheable'
>;
export type AngularJsonConfigTargetConfiguration = Exclude< export type AngularJsonConfigTargetConfiguration = Exclude<
TargetConfiguration, TargetConfiguration,
'command' | 'executor' | 'outputs' | 'dependsOn' | 'inputs' 'command' | 'executor' | 'outputs' | 'dependsOn' | 'inputs'

View File

@ -1,13 +1,13 @@
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { copySync, moveSync, readdirSync, removeSync } from 'fs-extra'; import { copySync, moveSync, readdirSync, removeSync } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import * as yargsParser from 'yargs-parser'; import { InitArgs } from '../../command-line/init';
import { fileExists, readJsonFile } from '../../utils/fileutils'; import { fileExists, readJsonFile } from '../../utils/fileutils';
import { output } from '../../utils/output'; import { output } from '../../utils/output';
import { import {
PackageManagerCommands,
detectPackageManager, detectPackageManager,
getPackageManagerCommand, getPackageManagerCommand,
PackageManagerCommands,
} from '../../utils/package-manager'; } from '../../utils/package-manager';
import { askAboutNxCloud, printFinalMessage } from '../utils'; import { askAboutNxCloud, printFinalMessage } from '../utils';
import { checkForCustomWebpackSetup } from './check-for-custom-webpack-setup'; import { checkForCustomWebpackSetup } from './check-for-custom-webpack-setup';
@ -21,16 +21,9 @@ import { writeCracoConfig } from './write-craco-config';
import { writeViteConfig } from './write-vite-config'; import { writeViteConfig } from './write-vite-config';
import { writeViteIndexHtml } from './write-vite-index-html'; import { writeViteIndexHtml } from './write-vite-index-html';
export interface Options { type Options = InitArgs;
force: boolean;
e2e: boolean;
nxCloud: boolean;
vite: boolean;
integrated: boolean;
interactive: boolean;
}
interface NormalizedOptions extends Options { type NormalizedOptions = Options & {
packageManager: string; packageManager: string;
pmc: PackageManagerCommands; pmc: PackageManagerCommands;
appIsJs: boolean; appIsJs: boolean;
@ -39,31 +32,17 @@ interface NormalizedOptions extends Options {
npxYesFlagNeeded: boolean; npxYesFlagNeeded: boolean;
isVite: boolean; isVite: boolean;
isStandalone: boolean; isStandalone: boolean;
} };
const parsedArgs = yargsParser(process.argv, { export async function addNxToCraRepo(options: Options) {
boolean: ['force', 'e2e', 'nxCloud', 'vite', 'interactive'], if (!options.force) {
default: {
interactive: true,
vite: true,
},
configuration: {
'strip-dashed': true,
},
});
export async function addNxToCraRepo(integrated: boolean) {
if (!parsedArgs.force) {
checkForUncommittedChanges(); checkForUncommittedChanges();
checkForCustomWebpackSetup(); checkForCustomWebpackSetup();
} }
output.log({ title: '🐳 Nx initialization' }); output.log({ title: '🐳 Nx initialization' });
const normalizedOptions = await normalizeOptions( const normalizedOptions = await normalizeOptions(options);
parsedArgs as unknown as Options,
integrated
);
await reorgnizeWorkspaceStructure(normalizedOptions); await reorgnizeWorkspaceStructure(normalizedOptions);
} }
@ -90,10 +69,7 @@ function installDependencies(options: NormalizedOptions) {
}); });
} }
async function normalizeOptions( async function normalizeOptions(options: Options): Promise<NormalizedOptions> {
options: Options,
integrated: boolean
): Promise<NormalizedOptions> {
const packageManager = detectPackageManager(); const packageManager = detectPackageManager();
const pmc = getPackageManagerCommand(packageManager); const pmc = getPackageManagerCommand(packageManager);
@ -110,14 +86,14 @@ async function normalizeOptions(
// Should remove this check 04/2023 once Node 14 & npm 6 reach EOL // Should remove this check 04/2023 once Node 14 & npm 6 reach EOL
const npxYesFlagNeeded = !npmVersion.startsWith('6'); // npm 7 added -y flag to npx const npxYesFlagNeeded = !npmVersion.startsWith('6'); // npm 7 added -y flag to npx
const isVite = options.vite; const isVite = options.vite;
const isStandalone = !integrated; const isStandalone = !options.integrated;
options.nxCloud =
options.interactive && options.nxCloud === undefined const nxCloud =
? await askAboutNxCloud() options.nxCloud ?? (options.interactive ? await askAboutNxCloud() : false);
: options.nxCloud ?? false;
return { return {
...options, ...options,
nxCloud,
packageManager, packageManager,
pmc, pmc,
appIsJs, appIsJs,
@ -126,7 +102,6 @@ async function normalizeOptions(
npxYesFlagNeeded, npxYesFlagNeeded,
isVite, isVite,
isStandalone, isStandalone,
integrated,
}; };
} }
@ -312,7 +287,7 @@ function cleanUpUnusedFilesAndAddConfigFiles(options: NormalizedOptions) {
setupTsConfig(options.reactAppName, options.isStandalone); setupTsConfig(options.reactAppName, options.isStandalone);
if (options.e2e && !options.isStandalone) { if (options.addE2e && !options.isStandalone) {
output.log({ title: '📃 Setup e2e tests' }); output.log({ title: '📃 Setup e2e tests' });
setupE2eProject(options.reactAppName); setupE2eProject(options.reactAppName);
} else { } else {