Skip to content

Commit

Permalink
feat(misc): support interactive prompts for custom presets
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz committed Dec 19, 2022
1 parent b94c7e5 commit f6c0a43
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 31 deletions.
88 changes: 86 additions & 2 deletions packages/create-nx-workspace/bin/create-nx-workspace.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec } from 'child_process';
import { exec, spawn } from 'child_process';
import { writeFileSync } from 'fs';
import * as enquirer from 'enquirer';
import * as path from 'path';
Expand Down Expand Up @@ -251,6 +251,10 @@ async function main(parsedArgs: yargs.Arguments<Arguments>) {
}
);

if (!isKnownPreset(parsedArgs.preset)) {
await createPreset(parsedArgs, packageManager as PackageManager, directory);
}

let nxCloudInstallRes;
if (nxCloud) {
nxCloudInstallRes = await setupNxCloud(
Expand Down Expand Up @@ -879,7 +883,6 @@ async function createSandbox(packageManager: PackageManager) {

return tmpDir;
}

async function createApp(
tmpDir: string,
name: string,
Expand Down Expand Up @@ -939,6 +942,66 @@ async function createApp(
return join(workingDir, getFileName(name));
}

async function createPreset(
parsedArgs: yargs.Arguments<Arguments>,
packageManager: PackageManager,
directory: string
): Promise<void> {
const {
_,
cli,
skipGit,
ci,
commit,
allPrompts,
nxCloud,
preset,
...restArgs
} = parsedArgs;

const args = unparse(restArgs).join(' ');

const pmc = getPackageManagerCommand(packageManager);

const workingDir = process.cwd().replace(/\\/g, '/');
let nxWorkspaceRoot = `"${workingDir}"`;

// If path contains spaces there is a problem in Windows for npm@6.
// In this case we have to escape the wrapping quotes.
if (
process.platform === 'win32' &&
/\s/.test(nxWorkspaceRoot) &&
packageManager === 'npm'
) {
const pmVersion = +getPackageManagerVersion(packageManager).split('.')[0];
if (pmVersion < 7) {
nxWorkspaceRoot = `\\"${nxWorkspaceRoot.slice(1, -1)}\\"`;
}
}

const command = `g ${preset}:preset ${args}`;

try {
const [exec, ...args] = pmc.exec.split(' ');
args.push(
'nx',
`--nxWorkspaceRoot=${nxWorkspaceRoot}`,
...command.split(' ')
);
await spawnAndWait(exec, args, directory);

output.log({
title: `Successfully applied preset: ${preset}.`,
});
} catch (e) {
output.error({
title: `Failed to apply preset: ${preset}`,
bodyLines: ['See above'],
});
process.exit(1);
}
}

async function setupNxCloud(name: string, packageManager: PackageManager) {
const nxCloudSpinner = ora(`Setting up NxCloud`).start();
try {
Expand Down Expand Up @@ -1045,6 +1108,27 @@ function execAndWait(command: string, cwd: string) {
});
}

/**
* Use spawn only for interactive shells
*/
function spawnAndWait(command: string, args: string[], cwd: string) {
return new Promise((res, rej) => {
const childProcess = spawn(command, args, {
cwd,
stdio: 'inherit',
env: { ...process.env, NX_DAEMON: 'false' },
});

childProcess.on('exit', (code) => {
if (code !== 0) {
rej({ code: code });
} else {
res({ code: 0 });
}
});
});
}

function pointToTutorialAndCourse(preset: Preset) {
const title = `First time using Nx? Check out this interactive Nx tutorial.`;
switch (preset) {
Expand Down
33 changes: 5 additions & 28 deletions packages/workspace/src/generators/new/generate-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getNpmPackageVersion } from '../utils/get-npm-package-version';
import { NormalizedSchema } from './new';
import { join } from 'path';
import * as yargsParser from 'yargs-parser';
import { spawn } from 'child_process';
import { spawn, SpawnOptions } from 'child_process';

export function addPresetDependencies(host: Tree, options: NormalizedSchema) {
if (
Expand Down Expand Up @@ -39,8 +39,8 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
interactive: true,
},
});
const spawnOptions = {
stdio: [process.stdin, process.stdout, process.stderr],
const spawnOptions: SpawnOptions = {
stdio: 'inherit',
shell: true,
cwd: join(host.root, opts.directory),
};
Expand All @@ -60,11 +60,8 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
});

function getPresetArgs(options: NormalizedSchema) {
if (Object.values(Preset).some((val) => val === options.preset)) {
// supported presets
return getDefaultArgs(options);
}
return getThirdPartyPresetArgs();
// supported presets
return getDefaultArgs(options);
}

function getDefaultArgs(opts: NormalizedSchema) {
Expand All @@ -80,26 +77,6 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
parsedArgs.interactive ? '--interactive=true' : '--interactive=false',
].filter((e) => !!e);
}

function getThirdPartyPresetArgs() {
const thirdPartyPkgArgs = Object.entries(opts).reduce(
(acc, [key, value]) => {
if (value === true) {
acc.push(`--${key}`);
} else if (value === false) {
acc.push(`--no-${key}`);
// nxWorkspaceRoot breaks CLI if incorrectly set, so need to exclude it.
// TODO(jack): Should read in the preset schema and only pass the options specified.
} else if (key !== 'nxWorkspaceRoot') {
// string, number (don't handle arrays or nested objects)
acc.push(`--${key}=${value}`);
}
return acc;
},
[]
);
return [`g`, `${opts.preset}:preset`, ...thirdPartyPkgArgs];
}
}

function getPresetDependencies(preset: string, version?: string) {
Expand Down
8 changes: 7 additions & 1 deletion packages/workspace/src/generators/new/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ export async function newGenerator(host: Tree, options: Schema) {
await generateWorkspaceFiles(host, { ...options, nxCloud: undefined } as any);

addPresetDependencies(host, options);
const isCustomPreset = !Object.values(Preset).includes(options.preset as any);
addCloudDependencies(host, options);

await formatFiles(host);

return async () => {
installPackagesTask(host, false, options.directory, options.packageManager);
if (options.preset !== Preset.NPM && options.preset !== Preset.Core) {
// TODO: move all of these into create-nx-workspace
if (
options.preset !== Preset.NPM &&
options.preset !== Preset.Core &&
!isCustomPreset
) {
await generatePreset(host, options);
}
};
Expand Down

0 comments on commit f6c0a43

Please sign in to comment.