nx
Version:
136 lines (135 loc) • 4.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureAnalyticsPreferenceSet = ensureAnalyticsPreferenceSet;
exports.promptForAnalyticsPreference = promptForAnalyticsPreference;
exports.generateWorkspaceId = generateWorkspaceId;
const crypto_1 = require("crypto");
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const enquirer_1 = require("enquirer");
const path_1 = require("path");
const output_1 = require("./output");
const is_ci_1 = require("./is-ci");
const nx_json_1 = require("../config/nx-json");
const fileutils_1 = require("./fileutils");
const write_formatted_json_file_1 = require("./write-formatted-json-file");
const workspace_root_1 = require("./workspace-root");
/**
* Prompts for analytics preference if not already set in nx.json, persists the
* answer so later commands don't re-ask, and returns it for telemetry. Returns
* 'unset' when not prompted (CI / non-interactive / no nx.json). `nx init`
* passes its own root + interactive flag; the default call (bin/nx.ts) derives
* interactive from the TTY.
*/
async function ensureAnalyticsPreferenceSet(root = workspace_root_1.workspaceRoot, interactive = !!(process.stdin.isTTY && process.stdout.isTTY)) {
if (!interactive || (0, is_ci_1.isCI)()) {
return 'unset';
}
// Only prompt inside a workspace that has nx.json — avoid creating
// nx.json in arbitrary directories (e.g. when running cloud commands
// outside a workspace).
if (!(0, fs_1.existsSync)((0, path_1.join)(root, 'nx.json'))) {
return 'unset';
}
const nxJson = (0, nx_json_1.readNxJson)(root);
// Already chosen (true = enabled, false = disabled) — report it.
if (typeof nxJson?.analytics === 'boolean') {
return nxJson.analytics ? 'yes' : 'no';
}
const enabled = await promptForAnalyticsPreference();
await saveAnalyticsPreference(root, enabled);
return enabled ? 'yes' : 'no';
}
async function promptForAnalyticsPreference() {
try {
output_1.output.log({
title: 'Help improve Nx by sharing usage data',
bodyLines: [
'Nx collects usage analytics to help improve the developer experience.',
'No project-specific information is collected.',
'Learn more: https://cloud.nx.app/privacy',
],
});
const { enableAnalytics } = await (0, enquirer_1.prompt)({
type: 'confirm',
name: 'enableAnalytics',
message: 'Share usage data with the Nx team?',
initial: true,
});
return enableAnalytics;
}
catch {
// User cancelled - default to false
return false;
}
}
async function saveAnalyticsPreference(root, enabled) {
try {
const nxJsonPath = (0, path_1.join)(root, 'nx.json');
const nxJson = (0, fileutils_1.readJsonFile)(nxJsonPath);
nxJson.analytics = enabled;
await (0, write_formatted_json_file_1.writeFormattedJsonFile)(nxJsonPath, nxJson);
if (enabled) {
output_1.output.success({ title: 'Thank you for helping improve Nx!' });
}
else {
output_1.output.log({
title: 'Analytics disabled.',
bodyLines: [
'You can change this anytime by setting "analytics" in nx.json.',
],
});
}
}
catch {
// Silently fail - don't block user's command
}
}
/**
* Generates a deterministic workspace ID.
* Priority: nxCloudId > git remote URL (hashed).
* Returns null if neither is available (no telemetry).
*/
function generateWorkspaceId(cwd) {
const root = cwd ?? workspace_root_1.workspaceRoot;
// Use nxCloudId if available — most stable identifier
const nxJson = (0, nx_json_1.readNxJson)(root);
const nxCloudId = nxJson?.nxCloudId ?? nxJson?.nxCloudAccessToken;
if (nxCloudId) {
return nxCloudId;
}
// Fall back to git remote URL hash
try {
const remoteUrl = (0, child_process_1.execSync)('git remote get-url origin', {
stdio: 'pipe',
cwd: root,
windowsHide: true,
})
.toString()
.trim();
if (remoteUrl) {
return (0, crypto_1.createHash)('sha256').update(remoteUrl).digest('hex').slice(0, 32);
}
}
catch {
// No git remote available
}
// Fall back to first commit SHA — already a hash
try {
const firstCommit = (0, child_process_1.execSync)('git rev-list --max-parents=0 HEAD', {
stdio: 'pipe',
cwd: root,
windowsHide: true,
})
.toString()
.trim()
.split('\n')[0];
if (firstCommit) {
return firstCommit;
}
}
catch {
// Not a git repo
}
return null;
}