create-nx-workspace
Version:
257 lines (256 loc) • 8.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.messages = exports.PromptMessages = exports.NxCloudChoices = void 0;
exports.getFlowVariant = getFlowVariant;
exports.recordStat = recordStat;
const node_child_process_1 = require("node:child_process");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const node_os_1 = require("node:os");
const is_ci_1 = require("../ci/is-ci");
// TODO(jack): Remove flow variant logic after A/B testing is complete
const FLOW_VARIANT_CACHE_FILE = (0, node_path_1.join)((0, node_os_1.tmpdir)(), 'nx-cnw-flow-variant');
const FLOW_VARIANT_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; // 1 week
// In-memory cache to ensure consistency within a single run
let flowVariantCache = null;
function readCachedFlowVariant() {
try {
if (!(0, node_fs_1.existsSync)(FLOW_VARIANT_CACHE_FILE))
return null;
const stats = (0, node_fs_1.statSync)(FLOW_VARIANT_CACHE_FILE);
if (Date.now() - stats.mtimeMs > FLOW_VARIANT_EXPIRY_MS)
return null;
const value = (0, node_fs_1.readFileSync)(FLOW_VARIANT_CACHE_FILE, 'utf-8').trim();
return value === '0' || value === '1' ? value : null;
}
catch {
return null;
}
}
function writeCachedFlowVariant(variant) {
try {
(0, node_fs_1.writeFileSync)(FLOW_VARIANT_CACHE_FILE, variant, 'utf-8');
}
catch {
// Ignore write errors
}
}
/**
* Internal function to determine and cache the flow variant.
*/
function getFlowVariantInternal() {
if (flowVariantCache)
return flowVariantCache;
const variant = process.env.NX_CNW_FLOW_VARIANT ??
readCachedFlowVariant() ??
(Math.random() < 0.5 ? '0' : '1');
flowVariantCache = variant;
// Only write to cache if we randomly assigned a variant and no cache exists yet
// This ensures the cache expiry is based on original creation time, not last access
if (!process.env.NX_CNW_FLOW_VARIANT &&
!(0, node_fs_1.existsSync)(FLOW_VARIANT_CACHE_FILE)) {
writeCachedFlowVariant(variant);
}
return variant;
}
/**
* Returns the flow variant for tracking (0 = preset, 1 = template).
*/
function getFlowVariant() {
if (process.env.NX_GENERATE_DOCS_PROCESS === 'true') {
return '0';
}
return flowVariantCache ?? getFlowVariantInternal();
}
exports.NxCloudChoices = [
'github',
'gitlab',
'azure',
'bitbucket-pipelines',
'circleci',
'skip',
'yes', // Deprecated but still handled
];
const messageOptions = {
/**
* These messages are for setting up CI as part of create-nx-workspace and nx init
*/
setupCI: [
{
code: 'which-ci-provider',
message: `Which CI provider would you like to use?`,
initial: 0,
choices: [
{ value: 'github', name: 'GitHub Actions' },
{ value: 'gitlab', name: 'Gitlab' },
{ value: 'azure', name: 'Azure DevOps' },
{ value: 'bitbucket-pipelines', name: 'BitBucket Pipelines' },
{ value: 'circleci', name: 'Circle CI' },
{ value: 'skip', name: '\nDo it later' },
],
footer: '\nSelf-healing CI, remote caching, and task distribution are provided by Nx Cloud: https://nx.dev/nx-cloud',
fallback: { value: 'skip', key: 'setupNxCloud' },
completionMessage: 'ci-setup',
},
],
/**
* These messages are a fallback for setting up CI as well as when migrating major versions
*/
setupNxCloud: [
{
code: 'enable-caching2',
message: `Would you like remote caching to make your build faster?`,
initial: 0,
choices: [
{ value: 'yes', name: 'Yes' },
{
value: 'skip',
name: 'No - I would not like remote caching',
},
],
footer: '\nRead more about remote caching at https://nx.dev/ci/features/remote-cache',
hint: `\n(can be disabled any time).`,
fallback: undefined,
completionMessage: 'cache-setup',
},
],
/**
* Simplified Cloud prompt for template flow
*/
setupNxCloudV2: [
//{
// code: 'cloud-v2-remote-cache-visit',
// message: 'Enable remote caching with Nx Cloud?',
// initial: 0,
// choices: [
// { value: 'yes', name: 'Yes' },
// { value: 'skip', name: 'Skip' },
// ],
// footer:
// '\nRemote caching makes your builds faster for development and in CI: https://nx.dev/ci/features/remote-cache',
// fallback: undefined,
// completionMessage: 'cache-setup',
//},
//{
// code: 'cloud-v2-fast-ci-visit',
// message: 'Speed up CI and reduce compute costs with Nx Cloud?',
// initial: 0,
// choices: [
// { value: 'yes', name: 'Yes' },
// { value: 'skip', name: 'Skip' },
// ],
// footer:
// '\n70% faster CI, 60% less compute, Automatically fix broken PRs: https://nx.dev/nx-cloud',
// fallback: undefined,
// completionMessage: 'ci-setup',
//},
//{
// code: 'cloud-v2-green-prs-visit',
// message: 'Get to green PRs faster with Nx Cloud?',
// initial: 0,
// choices: [
// { value: 'yes', name: 'Yes' },
// { value: 'skip', name: 'Skip' },
// ],
// footer:
// '\nAutomatically fix broken PRs, 70% faster CI: https://nx.dev/nx-cloud',
// fallback: undefined,
// completionMessage: 'ci-setup',
//},
{
code: 'cloud-v2-full-platform-visit',
message: 'Try the full Nx platform?',
initial: 0,
choices: [
{ value: 'yes', name: 'Yes' },
{ value: 'skip', name: 'Skip' },
],
footer: '\nAutomatically fix broken PRs, 70% faster CI: https://nx.dev/nx-cloud',
fallback: undefined,
completionMessage: 'platform-setup',
},
],
};
class PromptMessages {
constructor() {
this.selectedMessages = {};
}
getPrompt(key) {
if (this.selectedMessages[key] === undefined) {
if (process.env.NX_GENERATE_DOCS_PROCESS === 'true') {
this.selectedMessages[key] = 0;
}
else {
this.selectedMessages[key] = Math.floor(Math.random() * messageOptions[key].length);
}
}
return messageOptions[key][this.selectedMessages[key]];
}
codeOfSelectedPromptMessage(key) {
const selected = this.selectedMessages[key];
if (selected === undefined) {
return '';
}
return messageOptions[key][selected].code;
}
completionMessageOfSelectedPrompt(key) {
const selected = this.selectedMessages[key];
if (selected === undefined) {
return 'ci-setup';
}
else {
return messageOptions[key][selected].completionMessage;
}
}
}
exports.PromptMessages = PromptMessages;
exports.messages = new PromptMessages();
function getCloudUrl() {
const url = process.env.NX_CLOUD_API || process.env.NRWL_API || 'https://cloud.nx.app';
// Remove trailing slash if present
return url[url.length - 1] === '/' ? url.slice(0, -1) : url;
}
/**
* We are incrementing a counter to track how often create-nx-workspace is used in CI
* vs dev environments. No personal information is collected.
*/
async function recordStat(opts) {
try {
if (!shouldRecordStats()) {
return;
}
const axios = require('axios');
await (axios['default'] ?? axios)
.create({
baseURL: getCloudUrl(),
timeout: 400,
})
.post('/nx-cloud/stats', {
command: opts.command,
isCI: (0, is_ci_1.isCI)(),
useCloud: opts.useCloud,
meta: JSON.stringify({ nxVersion: opts.nxVersion, ...opts.meta }),
});
}
catch (e) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.error(e);
}
}
}
function shouldRecordStats() {
try {
// Use npm to check registry - this works regardless of which package manager invoked us
const stdout = (0, node_child_process_1.execSync)('npm config get registry', {
encoding: 'utf-8',
windowsHide: false,
});
const url = new URL(stdout.trim());
// don't record stats when testing locally
return url.hostname !== 'localhost';
}
catch {
// fallback to true if we can't detect the registry
return true;
}
}