feat(misc): nx init should work on non-monorepo projects
This commit is contained in:
parent
90f2791303
commit
661bea436a
@ -2,6 +2,7 @@ import {
|
|||||||
cleanupProject,
|
cleanupProject,
|
||||||
createNonNxProjectDirectory,
|
createNonNxProjectDirectory,
|
||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
|
getPublishedVersion,
|
||||||
getSelectedPackageManager,
|
getSelectedPackageManager,
|
||||||
renameFile,
|
renameFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
@ -16,8 +17,8 @@ describe('nx init', () => {
|
|||||||
|
|
||||||
afterEach(() => cleanupProject());
|
afterEach(() => cleanupProject());
|
||||||
|
|
||||||
it('should work', () => {
|
it('should work in a monorepo', () => {
|
||||||
createNonNxProjectDirectory();
|
createNonNxProjectDirectory('monorepo', true);
|
||||||
updateFile(
|
updateFile(
|
||||||
'packages/package/package.json',
|
'packages/package/package.json',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@ -30,7 +31,9 @@ describe('nx init', () => {
|
|||||||
|
|
||||||
runCommand(pmc.install);
|
runCommand(pmc.install);
|
||||||
|
|
||||||
const output = runCommand(`${pmc.runUninstalledPackage} nx init -y`);
|
const output = runCommand(
|
||||||
|
`${pmc.runUninstalledPackage} nx@${getPublishedVersion()} init -y`
|
||||||
|
);
|
||||||
expect(output).toContain('Enabled computation caching');
|
expect(output).toContain('Enabled computation caching');
|
||||||
|
|
||||||
expect(runCLI('run package:echo')).toContain('123');
|
expect(runCLI('run package:echo')).toContain('123');
|
||||||
@ -38,4 +41,32 @@ describe('nx init', () => {
|
|||||||
|
|
||||||
expect(runCLI('run package:echo')).toContain('123');
|
expect(runCLI('run package:echo')).toContain('123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work in a regular npm repo ttt', () => {
|
||||||
|
createNonNxProjectDirectory('regular-repo', false);
|
||||||
|
updateFile(
|
||||||
|
'package.json',
|
||||||
|
JSON.stringify({
|
||||||
|
name: 'package',
|
||||||
|
scripts: {
|
||||||
|
echo: 'echo 123',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
runCommand(pmc.install);
|
||||||
|
|
||||||
|
const output = runCommand(
|
||||||
|
`${
|
||||||
|
pmc.runUninstalledPackage
|
||||||
|
} nx@${getPublishedVersion()} init -y --cacheable=echo`
|
||||||
|
);
|
||||||
|
console.log(output);
|
||||||
|
expect(output).toContain('Enabled computation caching');
|
||||||
|
|
||||||
|
expect(runCLI('echo')).toContain('123');
|
||||||
|
renameFile('nx.json', 'nx.json.old');
|
||||||
|
|
||||||
|
expect(runCLI('echo')).toContain('123');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -136,14 +136,17 @@ export function readProjectConfig(projectName: string): ProjectConfiguration {
|
|||||||
return readJson(path);
|
return readJson(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNonNxProjectDirectory(name = uniq('proj')) {
|
export function createNonNxProjectDirectory(
|
||||||
|
name = uniq('proj'),
|
||||||
|
addWorkspaces = true
|
||||||
|
) {
|
||||||
projName = name;
|
projName = name;
|
||||||
ensureDirSync(tmpProjPath());
|
ensureDirSync(tmpProjPath());
|
||||||
createFile(
|
createFile(
|
||||||
'package.json',
|
'package.json',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
name,
|
name,
|
||||||
workspaces: ['packages/*'],
|
workspaces: addWorkspaces ? ['packages/*'] : undefined,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,20 @@
|
|||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { execSync } from 'child_process';
|
|
||||||
import * as enquirer from 'enquirer';
|
import * as enquirer from 'enquirer';
|
||||||
import { joinPathFragments } from 'nx/src/utils/path';
|
import { joinPathFragments } from 'nx/src/utils/path';
|
||||||
import {
|
import { getPackageManagerCommand } from 'nx/src/utils/package-manager';
|
||||||
getPackageManagerCommand,
|
|
||||||
PackageManagerCommands,
|
|
||||||
} from 'nx/src/utils/package-manager';
|
|
||||||
import { output } from 'nx/src/utils/output';
|
import { output } from 'nx/src/utils/output';
|
||||||
import { readJsonFile, writeJsonFile } from 'nx/src/utils/fileutils';
|
import { readJsonFile } from 'nx/src/utils/fileutils';
|
||||||
import ignore from 'ignore';
|
import ignore from 'ignore';
|
||||||
import * as yargsParser from 'yargs-parser';
|
import * as yargsParser from 'yargs-parser';
|
||||||
|
import {
|
||||||
|
askAboutNxCloud,
|
||||||
|
createNxJsonFile,
|
||||||
|
initCloud,
|
||||||
|
runInstall,
|
||||||
|
addDepsToPackageJson,
|
||||||
|
} from 'nx/src/nx-init/utils';
|
||||||
|
|
||||||
const parsedArgs = yargsParser(process.argv, {
|
const parsedArgs = yargsParser(process.argv, {
|
||||||
boolean: ['yes'],
|
boolean: ['yes'],
|
||||||
@ -38,13 +41,12 @@ async function addNxToMonorepo() {
|
|||||||
|
|
||||||
output.log({ title: `🐳 Nx initialization` });
|
output.log({ title: `🐳 Nx initialization` });
|
||||||
|
|
||||||
const pmc = getPackageManagerCommand();
|
|
||||||
const packageJsonFiles = allProjectPackageJsonFiles(repoRoot);
|
const packageJsonFiles = allProjectPackageJsonFiles(repoRoot);
|
||||||
const scripts = combineAllScriptNames(repoRoot, packageJsonFiles);
|
const scripts = combineAllScriptNames(repoRoot, packageJsonFiles);
|
||||||
|
|
||||||
let targetDefaults: string[];
|
let targetDefaults: string[];
|
||||||
let cacheableOperations: string[];
|
let cacheableOperations: string[];
|
||||||
let scriptOutputs = {};
|
let scriptOutputs = {} as { [script: string]: string };
|
||||||
let useCloud: boolean;
|
let useCloud: boolean;
|
||||||
|
|
||||||
if (parsedArgs.yes !== true) {
|
if (parsedArgs.yes !== true) {
|
||||||
@ -57,8 +59,7 @@ async function addNxToMonorepo() {
|
|||||||
{
|
{
|
||||||
type: 'multiselect',
|
type: 'multiselect',
|
||||||
name: 'targetDefaults',
|
name: 'targetDefaults',
|
||||||
message:
|
message: `Which scripts need to be run in order? (e.g. before building a project, dependent projects must be built.)`,
|
||||||
'Which of the following scripts need to be run in deterministic/topological order?',
|
|
||||||
choices: scripts,
|
choices: scripts,
|
||||||
},
|
},
|
||||||
])) as any
|
])) as any
|
||||||
@ -70,7 +71,7 @@ async function addNxToMonorepo() {
|
|||||||
type: 'multiselect',
|
type: 'multiselect',
|
||||||
name: 'cacheableOperations',
|
name: 'cacheableOperations',
|
||||||
message:
|
message:
|
||||||
'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
|
'Which scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
|
||||||
choices: scripts,
|
choices: scripts,
|
||||||
},
|
},
|
||||||
])) as any
|
])) as any
|
||||||
@ -78,13 +79,15 @@ async function addNxToMonorepo() {
|
|||||||
|
|
||||||
for (const scriptName of cacheableOperations) {
|
for (const scriptName of cacheableOperations) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
scriptOutputs[scriptName] = await enquirer.prompt([
|
scriptOutputs[scriptName] = (
|
||||||
|
await enquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: scriptName,
|
name: scriptName,
|
||||||
message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path relative to a project root (e.g. dist, lib, build, coverage)`,
|
message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path relative to a project root (e.g. dist, lib, build, coverage)`,
|
||||||
},
|
},
|
||||||
]);
|
])
|
||||||
|
)[scriptName];
|
||||||
}
|
}
|
||||||
|
|
||||||
useCloud = await askAboutNxCloud();
|
useCloud = await askAboutNxCloud();
|
||||||
@ -98,42 +101,20 @@ async function addNxToMonorepo() {
|
|||||||
repoRoot,
|
repoRoot,
|
||||||
targetDefaults,
|
targetDefaults,
|
||||||
cacheableOperations,
|
cacheableOperations,
|
||||||
scriptOutputs
|
scriptOutputs,
|
||||||
|
undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
addDepsToPackageJson(repoRoot, useCloud);
|
addDepsToPackageJson(repoRoot, useCloud);
|
||||||
|
|
||||||
output.log({ title: `📦 Installing dependencies` });
|
output.log({ title: `📦 Installing dependencies` });
|
||||||
runInstall(repoRoot, pmc);
|
runInstall(repoRoot);
|
||||||
|
|
||||||
if (useCloud) {
|
if (useCloud) {
|
||||||
initCloud(repoRoot, pmc);
|
initCloud(repoRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
printFinalMessage(pmc);
|
printFinalMessage();
|
||||||
}
|
|
||||||
|
|
||||||
function askAboutNxCloud() {
|
|
||||||
return enquirer
|
|
||||||
.prompt([
|
|
||||||
{
|
|
||||||
name: 'NxCloud',
|
|
||||||
message: `Enable distributed caching to make your CI faster`,
|
|
||||||
type: 'autocomplete',
|
|
||||||
choices: [
|
|
||||||
{
|
|
||||||
name: 'Yes',
|
|
||||||
hint: 'I want faster builds',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'No',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
initial: 'Yes' as any,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// scanning package.json files
|
// scanning package.json files
|
||||||
@ -198,102 +179,8 @@ function combineAllScriptNames(
|
|||||||
return [...res];
|
return [...res];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNxJsonFile(
|
function printFinalMessage() {
|
||||||
repoRoot: string,
|
const pmc = getPackageManagerCommand();
|
||||||
targetDefaults: string[],
|
|
||||||
cacheableOperations: string[],
|
|
||||||
scriptOutputs: { [name: string]: string }
|
|
||||||
) {
|
|
||||||
const nxJsonPath = joinPathFragments(repoRoot, 'nx.json');
|
|
||||||
let nxJson = {} as any;
|
|
||||||
try {
|
|
||||||
nxJson = readJsonFile(nxJsonPath);
|
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
nxJson.tasksRunnerOptions ||= {};
|
|
||||||
nxJson.tasksRunnerOptions.default ||= {};
|
|
||||||
nxJson.tasksRunnerOptions.default.runner ||= 'nx/tasks-runners/default';
|
|
||||||
nxJson.tasksRunnerOptions.default.options ||= {};
|
|
||||||
nxJson.tasksRunnerOptions.default.options.cacheableOperations =
|
|
||||||
cacheableOperations;
|
|
||||||
nxJson.targetDefaults ||= {};
|
|
||||||
for (const scriptName of targetDefaults) {
|
|
||||||
nxJson.targetDefaults[scriptName] ||= {};
|
|
||||||
nxJson.targetDefaults[scriptName] = { dependsOn: [`^${scriptName}`] };
|
|
||||||
}
|
|
||||||
for (const [scriptName, scriptAnswerData] of Object.entries(scriptOutputs)) {
|
|
||||||
if (!scriptAnswerData[scriptName]) {
|
|
||||||
// eslint-disable-next-line no-continue
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nxJson.targetDefaults[scriptName] ||= {};
|
|
||||||
nxJson.targetDefaults[scriptName].outputs = [
|
|
||||||
`{projectRoot}/${scriptAnswerData[scriptName]}`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
nxJson.defaultBase = deduceDefaultBase();
|
|
||||||
writeJsonFile(nxJsonPath, nxJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deduceDefaultBase() {
|
|
||||||
try {
|
|
||||||
execSync(`git rev-parse --verify main`, {
|
|
||||||
stdio: ['ignore', 'ignore', 'ignore'],
|
|
||||||
});
|
|
||||||
return 'main';
|
|
||||||
} catch {
|
|
||||||
try {
|
|
||||||
execSync(`git rev-parse --verify dev`, {
|
|
||||||
stdio: ['ignore', 'ignore', 'ignore'],
|
|
||||||
});
|
|
||||||
return 'dev';
|
|
||||||
} catch {
|
|
||||||
try {
|
|
||||||
execSync(`git rev-parse --verify develop`, {
|
|
||||||
stdio: ['ignore', 'ignore', 'ignore'],
|
|
||||||
});
|
|
||||||
return 'develop';
|
|
||||||
} catch {
|
|
||||||
try {
|
|
||||||
execSync(`git rev-parse --verify next`, {
|
|
||||||
stdio: ['ignore', 'ignore', 'ignore'],
|
|
||||||
});
|
|
||||||
return 'next';
|
|
||||||
} catch {
|
|
||||||
return 'master';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add dependencies
|
|
||||||
function addDepsToPackageJson(repoRoot: string, useCloud: boolean) {
|
|
||||||
const json = readJsonFile(joinPathFragments(repoRoot, `package.json`));
|
|
||||||
if (!json.devDependencies) json.devDependencies = {};
|
|
||||||
json.devDependencies['nx'] = require('../package.json').version;
|
|
||||||
if (useCloud) {
|
|
||||||
json.devDependencies['@nrwl/nx-cloud'] = 'latest';
|
|
||||||
}
|
|
||||||
writeJsonFile(`package.json`, json);
|
|
||||||
}
|
|
||||||
|
|
||||||
function runInstall(repoRoot: string, pmc: PackageManagerCommands) {
|
|
||||||
execSync(pmc.install, { stdio: [0, 1, 2], cwd: repoRoot });
|
|
||||||
}
|
|
||||||
|
|
||||||
function initCloud(repoRoot: string, pmc: PackageManagerCommands) {
|
|
||||||
execSync(
|
|
||||||
`${pmc.exec} nx g @nrwl/nx-cloud:init --installationSource=add-nx-to-monorepo`,
|
|
||||||
{
|
|
||||||
stdio: [0, 1, 2],
|
|
||||||
cwd: repoRoot,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printFinalMessage(pmc: PackageManagerCommands) {
|
|
||||||
output.success({
|
output.success({
|
||||||
title: `🎉 Done!`,
|
title: `🎉 Done!`,
|
||||||
bodyLines: [
|
bodyLines: [
|
||||||
|
|||||||
@ -1,15 +1,34 @@
|
|||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
|
import { readJsonFile } from '../utils/fileutils';
|
||||||
|
import { addNxToNpmRepo } from '../nx-init/add-nx-to-npm-repo';
|
||||||
|
|
||||||
export function initHandler() {
|
export async function initHandler() {
|
||||||
const args = process.argv.slice(2).join(' ');
|
const args = process.argv.slice(2).join(' ');
|
||||||
if (existsSync('package.json')) {
|
if (existsSync('package.json')) {
|
||||||
|
if (isMonorepo()) {
|
||||||
|
// TODO: vsavkin remove add-nx-to-monorepo
|
||||||
execSync(`npx --yes add-nx-to-monorepo@latest ${args}`, {
|
execSync(`npx --yes add-nx-to-monorepo@latest ${args}`, {
|
||||||
stdio: [0, 1, 2],
|
stdio: [0, 1, 2],
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await addNxToNpmRepo();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
execSync(`npx --yes create-nx-workspace@latest ${args}`, {
|
execSync(`npx --yes create-nx-workspace@latest ${args}`, {
|
||||||
stdio: [0, 1, 2],
|
stdio: [0, 1, 2],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMonorepo() {
|
||||||
|
const packageJson = readJsonFile('package.json');
|
||||||
|
if (!!packageJson.workspaces) return true;
|
||||||
|
|
||||||
|
if (existsSync('pnpm-workspace.yaml') || existsSync('pnpm-workspace.yml'))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (existsSync('lerna.json')) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -161,7 +161,7 @@ export function calculateDefaultProjectName(
|
|||||||
workspaceConfiguration: ProjectsConfigurations & NxJsonConfiguration
|
workspaceConfiguration: ProjectsConfigurations & NxJsonConfiguration
|
||||||
) {
|
) {
|
||||||
let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1];
|
let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1];
|
||||||
if (relativeCwd) {
|
|
||||||
relativeCwd = relativeCwd.startsWith('/')
|
relativeCwd = relativeCwd.startsWith('/')
|
||||||
? relativeCwd.substring(1)
|
? relativeCwd.substring(1)
|
||||||
: relativeCwd;
|
: relativeCwd;
|
||||||
@ -170,12 +170,12 @@ export function calculateDefaultProjectName(
|
|||||||
const projectRoot = workspaceConfiguration.projects[p].root;
|
const projectRoot = workspaceConfiguration.projects[p].root;
|
||||||
return (
|
return (
|
||||||
relativeCwd == projectRoot ||
|
relativeCwd == projectRoot ||
|
||||||
|
(relativeCwd == '' && projectRoot == '.') ||
|
||||||
relativeCwd.startsWith(`${projectRoot}/`)
|
relativeCwd.startsWith(`${projectRoot}/`)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (matchingProject) return matchingProject;
|
if (matchingProject) return matchingProject;
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
(workspaceConfiguration.cli as { defaultProjectName: string })
|
(workspaceConfiguration.cli as { defaultProjectName: string })
|
||||||
?.defaultProjectName || workspaceConfiguration.defaultProject
|
?.defaultProjectName || workspaceConfiguration.defaultProject
|
||||||
|
|||||||
122
packages/nx/src/nx-init/add-nx-to-npm-repo.ts
Normal file
122
packages/nx/src/nx-init/add-nx-to-npm-repo.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { output } from '../utils/output';
|
||||||
|
import { getPackageManagerCommand } from '../utils/package-manager';
|
||||||
|
import * as yargsParser from 'yargs-parser';
|
||||||
|
import * as enquirer from 'enquirer';
|
||||||
|
import { readJsonFile, writeJsonFile } from '../utils/fileutils';
|
||||||
|
import {
|
||||||
|
addDepsToPackageJson,
|
||||||
|
askAboutNxCloud,
|
||||||
|
createNxJsonFile,
|
||||||
|
initCloud,
|
||||||
|
runInstall,
|
||||||
|
} from './utils';
|
||||||
|
import { joinPathFragments } from 'nx/src/utils/path';
|
||||||
|
|
||||||
|
const parsedArgs = yargsParser(process.argv, {
|
||||||
|
boolean: ['yes'],
|
||||||
|
string: ['cacheable'], // only used for testing
|
||||||
|
alias: {
|
||||||
|
yes: ['y'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function addNxToNpmRepo() {
|
||||||
|
const repoRoot = process.cwd();
|
||||||
|
|
||||||
|
output.log({ title: `🐳 Nx initialization` });
|
||||||
|
|
||||||
|
let cacheableOperations: string[];
|
||||||
|
let scriptOutputs = {};
|
||||||
|
let useCloud: boolean;
|
||||||
|
|
||||||
|
const packageJson = readJsonFile('package.json');
|
||||||
|
const scripts = Object.keys(packageJson.scripts).filter(
|
||||||
|
(s) => !s.startsWith('pre') && !s.startsWith('post')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (parsedArgs.yes !== true) {
|
||||||
|
output.log({
|
||||||
|
title: `🧑🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration`,
|
||||||
|
});
|
||||||
|
|
||||||
|
cacheableOperations = (
|
||||||
|
(await enquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'multiselect',
|
||||||
|
name: 'cacheableOperations',
|
||||||
|
message:
|
||||||
|
'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
|
||||||
|
choices: scripts,
|
||||||
|
},
|
||||||
|
])) as any
|
||||||
|
).cacheableOperations;
|
||||||
|
|
||||||
|
for (const scriptName of cacheableOperations) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
scriptOutputs[scriptName] = (
|
||||||
|
await enquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: scriptName,
|
||||||
|
message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path (e.g. dist, lib, build, coverage)`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)[scriptName];
|
||||||
|
}
|
||||||
|
|
||||||
|
useCloud = await askAboutNxCloud();
|
||||||
|
} else {
|
||||||
|
cacheableOperations = parsedArgs.cacheable
|
||||||
|
? parsedArgs.cacheable.split(',')
|
||||||
|
: [];
|
||||||
|
useCloud = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
createNxJsonFile(repoRoot, [], cacheableOperations, {}, packageJson.name);
|
||||||
|
|
||||||
|
addDepsToPackageJson(repoRoot, useCloud);
|
||||||
|
markRootPackageJsonAsNxProject(repoRoot, cacheableOperations, scriptOutputs);
|
||||||
|
|
||||||
|
output.log({ title: `📦 Installing dependencies` });
|
||||||
|
|
||||||
|
runInstall(repoRoot);
|
||||||
|
|
||||||
|
if (useCloud) {
|
||||||
|
initCloud(repoRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
printFinalMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function printFinalMessage() {
|
||||||
|
output.success({
|
||||||
|
title: `🎉 Done!`,
|
||||||
|
bodyLines: [
|
||||||
|
`- Enabled computation caching!`,
|
||||||
|
`- Learn more at https://nx.dev/recipes/adopting-nx/adding-to-monorepo`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function markRootPackageJsonAsNxProject(
|
||||||
|
repoRoot: string,
|
||||||
|
cacheableScripts: string[],
|
||||||
|
scriptOutputs: { [script: string]: string }
|
||||||
|
) {
|
||||||
|
const json = readJsonFile(joinPathFragments(repoRoot, `package.json`));
|
||||||
|
json.nx = { includeScripts: cacheableScripts };
|
||||||
|
for (let script of Object.keys(scriptOutputs)) {
|
||||||
|
if (scriptOutputs[script]) {
|
||||||
|
json.nx.targets ||= {};
|
||||||
|
json.nx.targets[script] = {
|
||||||
|
outputs: [`{projectRoot}/${scriptOutputs[script]}`],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let script of cacheableScripts) {
|
||||||
|
if (json.scripts[script]) {
|
||||||
|
json.scripts[script] = `nx exec -- ${json.scripts[script]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeJsonFile(`package.json`, json);
|
||||||
|
}
|
||||||
130
packages/nx/src/nx-init/utils.ts
Normal file
130
packages/nx/src/nx-init/utils.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { joinPathFragments } from '../utils/path';
|
||||||
|
import { readJsonFile, writeJsonFile } from '../utils/fileutils';
|
||||||
|
import * as enquirer from 'enquirer';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
import { getPackageManagerCommand } from '../utils/package-manager';
|
||||||
|
|
||||||
|
export function askAboutNxCloud() {
|
||||||
|
return enquirer
|
||||||
|
.prompt([
|
||||||
|
{
|
||||||
|
name: 'NxCloud',
|
||||||
|
message: `Enable distributed caching to make your CI faster`,
|
||||||
|
type: 'autocomplete',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Yes',
|
||||||
|
hint: 'I want faster builds',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'No',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
initial: 'Yes' as any,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createNxJsonFile(
|
||||||
|
repoRoot: string,
|
||||||
|
targetDefaults: string[],
|
||||||
|
cacheableOperations: string[],
|
||||||
|
scriptOutputs: { [name: string]: string },
|
||||||
|
defaultProject: string | undefined
|
||||||
|
) {
|
||||||
|
const nxJsonPath = joinPathFragments(repoRoot, 'nx.json');
|
||||||
|
let nxJson = {} as any;
|
||||||
|
try {
|
||||||
|
nxJson = readJsonFile(nxJsonPath);
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
nxJson.tasksRunnerOptions ||= {};
|
||||||
|
nxJson.tasksRunnerOptions.default ||= {};
|
||||||
|
nxJson.tasksRunnerOptions.default.runner ||= 'nx/tasks-runners/default';
|
||||||
|
nxJson.tasksRunnerOptions.default.options ||= {};
|
||||||
|
nxJson.tasksRunnerOptions.default.options.cacheableOperations =
|
||||||
|
cacheableOperations;
|
||||||
|
|
||||||
|
if (targetDefaults.length > 0) {
|
||||||
|
nxJson.targetDefaults ||= {};
|
||||||
|
for (const scriptName of targetDefaults) {
|
||||||
|
nxJson.targetDefaults[scriptName] ||= {};
|
||||||
|
nxJson.targetDefaults[scriptName] = { dependsOn: [`^${scriptName}`] };
|
||||||
|
}
|
||||||
|
for (const [scriptName, output] of Object.entries(scriptOutputs)) {
|
||||||
|
if (!output) {
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nxJson.targetDefaults[scriptName] ||= {};
|
||||||
|
nxJson.targetDefaults[scriptName].outputs = [`{projectRoot}/${output}`];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nxJson.defaultBase = deduceDefaultBase();
|
||||||
|
if (defaultProject) {
|
||||||
|
nxJson.defaultProject = defaultProject;
|
||||||
|
}
|
||||||
|
writeJsonFile(nxJsonPath, nxJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deduceDefaultBase() {
|
||||||
|
try {
|
||||||
|
execSync(`git rev-parse --verify main`, {
|
||||||
|
stdio: ['ignore', 'ignore', 'ignore'],
|
||||||
|
});
|
||||||
|
return 'main';
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
execSync(`git rev-parse --verify dev`, {
|
||||||
|
stdio: ['ignore', 'ignore', 'ignore'],
|
||||||
|
});
|
||||||
|
return 'dev';
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
execSync(`git rev-parse --verify develop`, {
|
||||||
|
stdio: ['ignore', 'ignore', 'ignore'],
|
||||||
|
});
|
||||||
|
return 'develop';
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
execSync(`git rev-parse --verify next`, {
|
||||||
|
stdio: ['ignore', 'ignore', 'ignore'],
|
||||||
|
});
|
||||||
|
return 'next';
|
||||||
|
} catch {
|
||||||
|
return 'master';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addDepsToPackageJson(repoRoot: string, useCloud: boolean) {
|
||||||
|
const path = joinPathFragments(repoRoot, `package.json`);
|
||||||
|
const json = readJsonFile(path);
|
||||||
|
if (!json.devDependencies) json.devDependencies = {};
|
||||||
|
json.devDependencies['nx'] = require('../../package.json').version;
|
||||||
|
if (useCloud) {
|
||||||
|
json.devDependencies['@nrwl/nx-cloud'] = 'latest';
|
||||||
|
}
|
||||||
|
writeJsonFile(path, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runInstall(repoRoot: string) {
|
||||||
|
const pmc = getPackageManagerCommand();
|
||||||
|
execSync(pmc.install, { stdio: [0, 1, 2], cwd: repoRoot });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initCloud(repoRoot: string) {
|
||||||
|
const pmc = getPackageManagerCommand();
|
||||||
|
execSync(
|
||||||
|
`${pmc.exec} nx g @nrwl/nx-cloud:init --installationSource=add-nx-to-monorepo`,
|
||||||
|
{
|
||||||
|
stdio: [0, 1, 2],
|
||||||
|
cwd: repoRoot,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user