nx
Version:
169 lines (168 loc) • 6.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.yargsInitCommand = void 0;
const shared_options_1 = require("../yargs-utils/shared-options");
const native_1 = require("../../native");
const ai_output_1 = require("./utils/ai-output");
const ab_testing_1 = require("../../utils/ab-testing");
const versions_1 = require("../../utils/versions");
const is_ci_1 = require("../../utils/is-ci");
const package_manager_1 = require("../../utils/package-manager");
exports.yargsInitCommand = {
command: 'init',
describe: 'Adds Nx to any type of workspace. It installs nx, creates an nx.json configuration file and optionally sets up remote caching. For more info, check https://nx.dev/recipes/adopting-nx.',
builder: async (yargs) => {
// Check for --help flag directly since async builder doesn't receive helpOrVersionSet reliably
const wantsHelp = process.argv.includes('--help') || process.argv.includes('-h');
if (wantsHelp) {
const y = await withInitOptions(yargs);
y.showHelp();
process.exit(0);
}
return withInitOptions(yargs);
},
handler: async (args) => {
// Node 24 has stricter readline behavior, and enquirer is not checking for closed state
// when invoking operations, thus you get an ERR_USE_AFTER_CLOSE error.
process.on('uncaughtException', (error) => {
if (error &&
typeof error === 'object' &&
'code' in error &&
error['code'] === 'ERR_USE_AFTER_CLOSE')
return;
throw error;
});
const aiAgent = (0, native_1.isAiAgent)();
(0, ab_testing_1.recordStat)({
command: 'init',
nxVersion: versions_1.nxVersion,
useCloud: false,
meta: {
type: 'start',
nodeVersion: process.versions.node,
os: process.platform,
packageManager: (0, package_manager_1.detectPackageManager)(),
aiAgent,
isCI: (0, is_ci_1.isCI)(),
},
});
try {
const useV2 = await isInitV2();
if (useV2) {
// v2 records its own complete event with richer context
await require('./init-v2').initHandler(args);
}
else {
await require('./init-v1').initHandler(args);
await (0, ab_testing_1.recordStat)({
command: 'init',
nxVersion: versions_1.nxVersion,
useCloud: false,
meta: {
type: 'complete',
nodeVersion: process.versions.node,
os: process.platform,
packageManager: (0, package_manager_1.detectPackageManager)(),
aiAgent,
isCI: (0, is_ci_1.isCI)(),
},
});
}
process.exit(0);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const errorCode = (0, ai_output_1.determineErrorCode)(error);
await (0, ab_testing_1.recordStat)({
command: 'init',
nxVersion: versions_1.nxVersion,
useCloud: false,
meta: {
type: 'error',
errorCode,
errorMessage: errorMessage.substring(0, 250),
aiAgent,
},
});
// Output structured error for AI agents
if (aiAgent) {
const errorLogPath = (0, ai_output_1.writeErrorLog)(error);
(0, ai_output_1.writeAiOutput)((0, ai_output_1.buildErrorResult)(errorMessage, errorCode, errorLogPath));
}
else {
// Ensure the cursor is always restored just in case the user has bailed during interactive prompts
// Skip for AI agents to avoid corrupting NDJSON output
process.stdout.write('\x1b[?25h');
}
process.exit(1);
}
},
};
async function isInitV2() {
return (process.env['NX_ADD_PLUGINS'] !== 'false' &&
(await Promise.resolve().then(() => require('../../config/nx-json'))).readNxJson().useInferencePlugins !==
false);
}
async function withInitOptions(yargs) {
const useV2 = await isInitV2();
if (useV2) {
return yargs
.option('nxCloud', {
type: 'boolean',
description: 'Set up distributed caching with Nx Cloud.',
})
.option('interactive', {
describe: 'When false disables interactive input prompts for options.',
type: 'boolean',
default: true,
})
.option('useDotNxInstallation', {
type: 'boolean',
description: 'Initialize an Nx workspace setup in the .nx directory of the current repository.',
default: false,
})
.option('aiAgents', {
type: 'array',
string: true,
description: 'List of AI agents to set up.',
choices: ['claude', 'codex', 'copilot', 'cursor', 'gemini', 'opencode'],
})
.option('plugins', {
type: 'string',
description: 'Plugins to install: "skip" for none, "all" for all detected, or comma-separated list (e.g., @nx/vite,@nx/jest).',
})
.option('cacheable', {
type: 'string',
description: 'Comma-separated list of cacheable operations (e.g., build,test,lint).',
coerce: shared_options_1.parseCSV,
});
}
else {
return yargs
.option('nxCloud', {
type: 'boolean',
description: 'Set up remote caching with Nx Cloud.',
})
.option('interactive', {
describe: 'When false disables interactive input prompts for options.',
type: 'boolean',
default: true,
})
.option('integrated', {
type: 'boolean',
description: 'Migrate to an Nx integrated layout workspace. Only for Angular CLI workspaces.',
default: false,
})
.option('useDotNxInstallation', {
type: 'boolean',
description: 'Initialize an Nx workspace setup in the .nx directory of the current repository.',
default: false,
})
.option('cacheable', {
type: 'string',
description: 'Comma-separated list of cacheable operations. Only used for internal testing.',
coerce: shared_options_1.parseCSV,
hidden: true,
});
}
}