Skip to content

Commit

Permalink
feat(misc): make createWorkspace quiter by default
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Apr 11, 2023
1 parent c02ec9f commit 0fef698
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 186 deletions.
23 changes: 22 additions & 1 deletion packages/create-nx-workspace/bin/create-nx-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {
withOptions,
withPackageManager,
} from '../src/internal-utils/yargs-options';
import { DefaultLogHandler } from '../src/utils/log-handler';
import { showNxWarning } from '../src/utils/nx/show-nx-warning';
import { printNxCloudSuccessMessage } from '../src/utils/nx/nx-cloud';

interface Arguments extends CreateWorkspaceOptions {
preset: string;
Expand Down Expand Up @@ -129,7 +132,25 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
) as yargs.Argv<Arguments>;

async function main(parsedArgs: yargs.Arguments<Arguments>) {
await createWorkspace<Arguments>(parsedArgs.preset, parsedArgs);
output.log({
title: `Nx is creating your v${nxVersion} workspace.`,
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<Arguments>(
parsedArgs.preset,
parsedArgs,
new DefaultLogHandler()
);

showNxWarning(parsedArgs.name);

if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
printNxCloudSuccessMessage(workspaceInfo.nxCloudInfo);
}

if (isKnownPreset(parsedArgs.preset)) {
pointToTutorialAndCourse(parsedArgs.preset as Preset);
Expand Down
43 changes: 24 additions & 19 deletions packages/create-nx-workspace/src/create-empty-workspace.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import * as ora from 'ora';
import { join } from 'path';
import { CreateWorkspaceOptions } from './create-workspace-options';
import { execAndWait } from './utils/child-process-utils';
import { mapErrorToBodyLines } from './utils/error-utils';
import { output } from './utils/output';
import { ProgressLogHandler } from './utils/log-handler';
import {
getPackageManagerCommand,
getPackageManagerVersion,
Expand All @@ -24,7 +22,8 @@ export async function createEmptyWorkspace<T extends CreateWorkspaceOptions>(
tmpDir: string,
name: string,
packageManager: PackageManager,
options: T
options: T,
progressLogHandler?: ProgressLogHandler
): Promise<string> {
// Ensure to use packageManager for args
// if it's not already passed in from previous process
Expand Down Expand Up @@ -55,30 +54,36 @@ export async function createEmptyWorkspace<T extends CreateWorkspaceOptions>(
nxWorkspaceRoot = `\\"${nxWorkspaceRoot.slice(1, -1)}\\"`;
}
}
let workspaceSetupSpinner = ora(
`Creating your workspace in ${getFileName(name)}`
).start();
progressLogHandler?.eventStartHandler({
displayMessage: `Creating your workspace in ${getFileName(name)}`,
id: 'workspace-setup',
status: 'start',
});

try {
const fullCommand = `${pmc.exec} nx ${command} --nxWorkspaceRoot=${nxWorkspaceRoot}`;
await execAndWait(fullCommand, tmpDir);

workspaceSetupSpinner.succeed(
`Nx has successfully created the workspace: ${getFileName(name)}.`
);
progressLogHandler?.eventEndHandler({
displayMessage: `Nx has successfully created the workspace: ${getFileName(
name
)}`,
id: 'workspace-setup',
status: 'success',
});
} catch (e) {
workspaceSetupSpinner.fail();
if (e instanceof Error) {
output.error({
title: `Nx failed to create a workspace.`,
bodyLines: mapErrorToBodyLines(e),
if (progressLogHandler) {
progressLogHandler.eventEndHandler({
displayMessage: `Nx failed to create the workspace: ${getFileName(
name
)}`,
id: 'workspace-setup',
status: 'fail',
});
progressLogHandler.errorHandler(e);
} else {
console.error(e);
throw e;
}
process.exit(1);
} finally {
workspaceSetupSpinner.stop();
}
return join(workingDir, getFileName(name));
}
33 changes: 24 additions & 9 deletions packages/create-nx-workspace/src/create-preset.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { CreateWorkspaceOptions } from './create-workspace-options';
import { output } from './utils/output';
import {
getPackageManagerCommand,
getPackageManagerVersion,
PackageManager,
} from './utils/package-manager';
import { spawnAndWait } from './utils/child-process-utils';
import { unparse } from './utils/unparse';
import { ProgressLogHandler } from './utils/log-handler';

export async function createPreset<T extends CreateWorkspaceOptions>(
preset: string,
parsedArgs: T,
packageManager: PackageManager,
directory: string
directory: string,
progressLogHandler?: ProgressLogHandler
): Promise<void> {
const { skipGit, ci, commit, nxCloud, ...restArgs } = parsedArgs;

Expand Down Expand Up @@ -44,6 +45,13 @@ export async function createPreset<T extends CreateWorkspaceOptions>(
}
const command = `g ${preset}:preset ${args}`;

progressLogHandler?.eventStartHandler({
displayMessage: `Applying your preset: ${preset}`,
id: 'apply-preset',
status: 'start',
interactive: true,
});

try {
const [exec, ...args] = pmc.exec.split(' ');
args.push(
Expand All @@ -53,14 +61,21 @@ export async function createPreset<T extends CreateWorkspaceOptions>(
);
await spawnAndWait(exec, args, directory);

output.log({
title: `Successfully applied preset: ${preset}.`,
progressLogHandler?.eventEndHandler({
displayMessage: `Successfully applied preset: ${preset}.`,
id: 'apply-preset',
status: 'success',
});
} catch (e) {
output.error({
title: `Failed to apply preset: ${preset}`,
bodyLines: ['See above'],
});
process.exit(1);
if (progressLogHandler) {
progressLogHandler?.eventEndHandler({
displayMessage: `Failed to apply preset: ${preset}`,
id: 'apply-preset',
status: 'fail',
});
progressLogHandler?.errorHandler(e);
} else {
throw e;
}
}
}
38 changes: 22 additions & 16 deletions packages/create-nx-workspace/src/create-sandbox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { writeFileSync } from 'fs';
import { dirSync } from 'tmp';
import * as ora from 'ora';
import { join } from 'path';

import {
Expand All @@ -9,19 +8,24 @@ import {
PackageManager,
} from './utils/package-manager';
import { execAndWait } from './utils/child-process-utils';
import { output } from './utils/output';
import { nxVersion } from './utils/nx/nx-version';
import { mapErrorToBodyLines } from './utils/error-utils';
import { ProgressLogHandler } from './utils/log-handler';

/**
* Creates a temporary directory and installs Nx in it.
* @param packageManager package manager to use
* @returns directory where Nx is installed
*/
export async function createSandbox(packageManager: PackageManager) {
const installSpinner = ora(
`Installing dependencies with ${packageManager}`
).start();
export async function createSandbox(
packageManager: PackageManager,
progressLogHandler?: ProgressLogHandler
) {
progressLogHandler?.eventStartHandler({
displayMessage: `Installing dependencies with ${packageManager}`,
id: 'install-dependencies',
status: 'start',
});

const { install } = getPackageManagerCommand(packageManager);

Expand All @@ -41,20 +45,22 @@ export async function createSandbox(packageManager: PackageManager) {

await execAndWait(install, tmpDir);

installSpinner.succeed();
progressLogHandler?.eventEndHandler({
displayMessage: `Dependencies installed with ${packageManager}`,
id: 'install-dependencies',
status: 'success',
});
} catch (e) {
installSpinner.fail();
if (e instanceof Error) {
output.error({
title: `Nx failed to install dependencies`,
bodyLines: mapErrorToBodyLines(e),
if (progressLogHandler) {
progressLogHandler.eventEndHandler({
displayMessage: `Failed to install dependencies with ${packageManager}`,
id: 'install-dependencies',
status: 'fail',
});
progressLogHandler.errorHandler(e);
} else {
console.error(e);
throw e;
}
process.exit(1);
} finally {
installSpinner.stop();
}

return tmpDir;
Expand Down
54 changes: 21 additions & 33 deletions packages/create-nx-workspace/src/create-workspace.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { CreateWorkspaceOptions } from './create-workspace-options';
import { output } from './utils/output';
import { printNxCloudSuccessMessage, setupNxCloud } from './utils/nx/nx-cloud';
import { createSandbox } from './create-sandbox';
import { createEmptyWorkspace } from './create-empty-workspace';
Expand All @@ -11,11 +10,13 @@ import { initializeGitRepo } from './utils/git/git';
import { nxVersion } from './utils/nx/nx-version';
import { getThirdPartyPreset } from './utils/preset/get-third-party-preset';
import { mapErrorToBodyLines } from './utils/error-utils';
import { ProgressLogHandler } from './utils/log-handler';

export async function createWorkspace<T extends CreateWorkspaceOptions>(
preset: string,
options: T
) {
options: T,
logHandler?: ProgressLogHandler
): Promise<{ nxCloudInfo?: string }> {
const {
packageManager,
name,
Expand All @@ -26,30 +27,29 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
commit,
} = options;

output.log({
title: `Nx is creating your v${nxVersion} workspace.`,
bodyLines: [
'To make sure the command works reliably in all environments, and that the preset is applied correctly,',
`Nx will run "${options.packageManager} install" several times. Please wait.`,
],
});

const tmpDir = await createSandbox(packageManager);
const tmpDir = await createSandbox(packageManager, logHandler);

// nx new requires preset currently. We should probably make it optional.
const directory = await createEmptyWorkspace<T>(
tmpDir,
name,
packageManager,
{ ...options, preset }
{ ...options, preset },
logHandler
);

// If the preset is a third-party preset, we need to call createPreset to install it
// For first-party presets, it will created by createEmptyWorkspace instead.
// In createEmptyWorkspace, it will call `nx new` -> `@nrwl/workspace newGenerator` -> `@nrwl/workspace generatePreset`.
const thirdPartyPreset = await getThirdPartyPreset(preset);
if (thirdPartyPreset) {
await createPreset(thirdPartyPreset, options, packageManager, directory);
await createPreset(
thirdPartyPreset,
options,
packageManager,
directory,
logHandler
);
}

let nxCloudInstallRes;
Expand All @@ -61,28 +61,12 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
name,
ci,
packageManager,
nxCloud && nxCloudInstallRes?.code === 0
nxCloud && nxCloudInstallRes?.code === 0,
logHandler
);
}
if (!skipGit) {
try {
await initializeGitRepo(directory, { defaultBase, commit });
} catch (e) {
if (e instanceof Error) {
output.error({
title: 'Could not initialize git repository',
bodyLines: mapErrorToBodyLines(e),
});
} else {
console.error(e);
}
}
}

showNxWarning(name);

if (nxCloud && nxCloudInstallRes?.code === 0) {
printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
initializeGitRepo(directory, { defaultBase, commit }, logHandler);
}

await recordStat({
Expand All @@ -91,4 +75,8 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
useCloud: nxCloud,
meta: messages.codeOfSelectedPromptMessage('nxCloudCreation'),
});

return {
nxCloudInfo: nxCloudInstallRes?.stdout,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export function execAndWait(command: string, cwd: string) {
const logFile = join(cwd, 'error.log');
writeFileSync(logFile, `${stdout}\n${stderr}`);
const message = stderr && stderr.trim().length ? stderr : stdout;
rej(new CreateNxWorkspaceError(message, error.code, logFile));
rej(
new CreateNxWorkspaceError(message, { code: error.code, logFile })
);
} else {
res({ code: 0, stdout });
}
Expand Down
Loading

0 comments on commit 0fef698

Please sign in to comment.