nx 23.2.0-beta.4 → 23.2.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/nx.js +1 -0
- package/dist/src/command-line/affected/affected.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +2 -2
- package/dist/src/command-line/init/init-v2.js +2 -2
- package/dist/src/command-line/migrate/agentic/definitions.js +2 -2
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +15 -19
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +19 -31
- package/dist/src/command-line/migrate/agentic/handoff.d.ts +4 -6
- package/dist/src/command-line/migrate/agentic/handoff.js +9 -8
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.d.ts +7 -12
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.js +7 -0
- package/dist/src/command-line/migrate/agentic/run-step.d.ts +10 -0
- package/dist/src/command-line/migrate/agentic/select.d.ts +10 -2
- package/dist/src/command-line/migrate/agentic/select.js +10 -2
- package/dist/src/command-line/migrate/agentic/types.d.ts +17 -3
- package/dist/src/command-line/migrate/agentic/types.js +26 -0
- package/dist/src/command-line/migrate/command-object.d.ts +3 -0
- package/dist/src/command-line/migrate/command-object.js +6 -1
- package/dist/src/command-line/migrate/execute-migration.d.ts +14 -9
- package/dist/src/command-line/migrate/execute-migration.js +82 -18
- package/dist/src/command-line/migrate/migrate-analytics.d.ts +7 -0
- package/dist/src/command-line/migrate/migrate-analytics.js +14 -0
- package/dist/src/command-line/migrate/migrate-commits.d.ts +32 -8
- package/dist/src/command-line/migrate/migrate-commits.js +77 -9
- package/dist/src/command-line/migrate/migrate-config.d.ts +11 -12
- package/dist/src/command-line/migrate/migrate-config.js +14 -14
- package/dist/src/command-line/migrate/migrate-output.d.ts +45 -7
- package/dist/src/command-line/migrate/migrate-output.js +52 -8
- package/dist/src/command-line/migrate/migrate-ui-api.d.ts +2 -1
- package/dist/src/command-line/migrate/migrate-ui-api.js +16 -7
- package/dist/src/command-line/migrate/migrate.d.ts +17 -68
- package/dist/src/command-line/migrate/migrate.js +411 -229
- package/dist/src/command-line/migrate/migration-shape.d.ts +8 -0
- package/dist/src/command-line/migrate/run/index.d.ts +2 -0
- package/dist/src/command-line/migrate/run/index.js +5 -0
- package/dist/src/command-line/migrate/run/util.d.ts +1 -0
- package/dist/src/command-line/migrate/run/util.js +16 -0
- package/dist/src/command-line/migrate/run/worker.d.ts +15 -0
- package/dist/src/command-line/migrate/run/worker.js +419 -0
- package/dist/src/command-line/migrate/run-migration-process.js +6 -5
- package/dist/src/command-line/migrate/sort-migrations.d.ts +16 -0
- package/dist/src/command-line/migrate/sort-migrations.js +32 -0
- package/dist/src/command-line/migrate/version-skew-guard.d.ts +58 -0
- package/dist/src/command-line/migrate/version-skew-guard.js +155 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/command-object.d.ts +2 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/command-object.js +16 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/start-nx-agents.d.ts +4 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/start-nx-agents.js +13 -0
- package/dist/src/command-line/nx-commands.js +26 -24
- package/dist/src/command-line/release/changelog.js +5 -0
- package/dist/src/command-line/release/utils/git.js +1 -1
- package/dist/src/command-line/release/utils/release-graph.d.ts +1 -0
- package/dist/src/command-line/release/utils/release-graph.js +15 -3
- package/dist/src/command-line/release/version/version-actions.d.ts +8 -0
- package/dist/src/command-line/release/version/version-actions.js +8 -0
- package/dist/src/command-line/release/version.js +9 -5
- package/dist/src/command-line/reset/reset.js +6 -1
- package/dist/src/command-line/run/run-one.js +1 -0
- package/dist/src/command-line/run-many/run-many.js +1 -0
- package/dist/src/config/misc-interfaces.d.ts +19 -7
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +45 -1
- package/dist/src/daemon/client/client.js +128 -32
- package/dist/src/daemon/client/daemon-socket-messenger.js +4 -0
- package/dist/src/daemon/message-types/daemon-message.d.ts +32 -0
- package/dist/src/daemon/message-types/daemon-message.js +25 -0
- package/dist/src/daemon/server/latest-nx.js +5 -2
- package/dist/src/daemon/server/server.js +22 -0
- package/dist/src/daemon/server/shutdown-utils.d.ts +5 -0
- package/dist/src/daemon/server/shutdown-utils.js +11 -4
- package/dist/src/daemon/socket-utils.d.ts +1 -0
- package/dist/src/daemon/socket-utils.js +24 -3
- package/dist/src/daemon/tmp-dir.d.ts +43 -3
- package/dist/src/daemon/tmp-dir.js +437 -15
- package/dist/src/devkit-internals.d.ts +92 -3
- package/dist/src/devkit-internals.js +189 -5
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.d.ts +5 -0
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +9 -2
- package/dist/src/generators/tree.d.ts +4 -2
- package/dist/src/native/index.d.ts +10 -0
- package/dist/src/native/index.js +71 -28
- package/dist/src/native/native-bindings.js +1 -0
- package/dist/src/native/native-file-cache-location.d.ts +17 -1
- package/dist/src/native/native-file-cache-location.js +86 -12
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/utilities/get-cloud-options.js +5 -2
- package/dist/src/nx-cloud/utilities/onboarding.js +5 -2
- package/dist/src/nx-cloud/utilities/url-shorten.d.ts +1 -4
- package/dist/src/nx-cloud/utilities/url-shorten.js +9 -8
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +14 -8
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +2 -0
- package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.js +2 -2
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +5 -2
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +18 -1
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +16 -3
- package/dist/src/project-graph/plugins/isolation/messaging.js +3 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +58 -8
- package/dist/src/project-graph/project-graph.js +20 -0
- package/dist/src/tasks-runner/life-cycles/performance-report.d.ts +12 -0
- package/dist/src/tasks-runner/life-cycles/performance-report.js +62 -3
- package/dist/src/tasks-runner/run-command.js +4 -0
- package/dist/src/utils/assert-workspace-validity.js +7 -2
- package/dist/src/utils/child-process.d.ts +31 -1
- package/dist/src/utils/child-process.js +103 -0
- package/dist/src/utils/ignore.d.ts +128 -1
- package/dist/src/utils/ignore.js +182 -12
- package/dist/src/utils/nx-tmp-dir.d.ts +18 -0
- package/dist/src/utils/nx-tmp-dir.js +40 -0
- package/dist/src/utils/owned-private-dir.d.ts +132 -0
- package/dist/src/utils/owned-private-dir.js +323 -0
- package/dist/src/utils/shell-quoting.d.ts +15 -0
- package/dist/src/utils/shell-quoting.js +35 -0
- package/dist/src/utils/wait-for-socket-connection.d.ts +11 -0
- package/dist/src/utils/wait-for-socket-connection.js +14 -8
- package/package.json +12 -12
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MEANINGFUL_OVERHEAD = exports.MIN_RECOMMENDATION_RUN_DURATION = void 0;
|
|
4
|
+
exports.prefetchRemoteCacheOnboardingUrl = prefetchRemoteCacheOnboardingUrl;
|
|
4
5
|
exports.recommendationToPayloadString = recommendationToPayloadString;
|
|
5
6
|
exports.buildRecommendations = buildRecommendations;
|
|
6
7
|
exports.formatReport = formatReport;
|
|
@@ -8,14 +9,72 @@ exports.formatReportMarkdown = formatReportMarkdown;
|
|
|
8
9
|
exports.buildExitSummaryPayload = buildExitSummaryPayload;
|
|
9
10
|
const native_1 = require("../../native");
|
|
10
11
|
const terminal_link_1 = require("../../utils/terminal-link");
|
|
12
|
+
const nx_cloud_utils_1 = require("../../utils/nx-cloud-utils");
|
|
13
|
+
const url_shorten_1 = require("../../nx-cloud/utilities/url-shorten");
|
|
14
|
+
const get_cloud_options_1 = require("../../nx-cloud/utilities/get-cloud-options");
|
|
15
|
+
const git_utils_1 = require("../../utils/git-utils");
|
|
16
|
+
const logger_1 = require("../../utils/logger");
|
|
11
17
|
const NX_AGENTS_URL = 'https://nx.dev/ci/features/distribute-task-execution';
|
|
12
|
-
|
|
18
|
+
// Fallback for the remote-cache CTA when the short onboarding URL can't be
|
|
19
|
+
// fetched: the generic Cloud get-started page (still drives to onboarding).
|
|
20
|
+
const NX_CLOUD_GET_STARTED_URL = 'https://cloud.nx.app/get-started';
|
|
13
21
|
const NX_PERFORMANCE_URL = 'https://nx.dev/docs/concepts/ci-concepts/parallelization-distribution';
|
|
14
22
|
/** utm tag attributing report clicks back to it; the content names the CTA clicked. */
|
|
15
23
|
const utm = (content) => `?utm_source=nx-cli&utm_medium=cli&utm_campaign=performance-report&utm_content=${content}`;
|
|
16
24
|
const NX_PERFORMANCE_LINK = `${NX_PERFORMANCE_URL}${utm('parallelization')}`;
|
|
17
25
|
const NX_AGENTS_LINK = `${NX_AGENTS_URL}${utm('nx-agents')}`;
|
|
18
|
-
const NX_REMOTE_CACHE_LINK = `${
|
|
26
|
+
const NX_REMOTE_CACHE_LINK = `${NX_CLOUD_GET_STARTED_URL}${utm('remote-cache')}`;
|
|
27
|
+
// Defaults to the get-started link; a disconnected workspace gets a short Nx
|
|
28
|
+
// Cloud onboarding URL instead (see prefetchRemoteCacheOnboardingUrl).
|
|
29
|
+
let remoteCacheLink = NX_REMOTE_CACHE_LINK;
|
|
30
|
+
// Give up on the short URL after this long so a slow/hung Cloud API never
|
|
31
|
+
// lingers past the exit report. Covers two sequential round trips (features
|
|
32
|
+
// GET, onboarding POST); the 30s CTA floor leaves room. Timing out also aborts
|
|
33
|
+
// the request - Promise.race alone would leave the socket holding the event
|
|
34
|
+
// loop open, which strands programmatic callers that never process.exit.
|
|
35
|
+
const ONBOARDING_URL_TIMEOUT = 5000;
|
|
36
|
+
/**
|
|
37
|
+
* Point the remote-cache CTA at a short Nx Cloud onboarding URL for a
|
|
38
|
+
* disconnected GitHub workspace - the VCS flow where Cloud opens the nx.json PR.
|
|
39
|
+
* Non-GitHub remotes keep the get-started link (handles every provider) and skip
|
|
40
|
+
* the network entirely. Runs in CI too - terminal + job summary.
|
|
41
|
+
*
|
|
42
|
+
* Best-effort: the get-started link stays on failure/timeout. Fired at run start;
|
|
43
|
+
* the CTA needs a >30s run (MIN_RECOMMENDATION_RUN_DURATION), so the fetch
|
|
44
|
+
* always resolves first.
|
|
45
|
+
*/
|
|
46
|
+
async function prefetchRemoteCacheOnboardingUrl(nxJson) {
|
|
47
|
+
if ((0, nx_cloud_utils_1.isNxCloudDisabled)(nxJson) || (0, nx_cloud_utils_1.isNxCloudUsed)(nxJson)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if ((0, git_utils_1.getVcsRemoteInfo)()?.domain !== 'github.com') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const abortController = new AbortController();
|
|
54
|
+
try {
|
|
55
|
+
const url = await Promise.race([
|
|
56
|
+
(0, url_shorten_1.createNxCloudOnboardingURL)('nx-cli-perf-report', undefined, undefined, false, false, undefined, abortController.signal),
|
|
57
|
+
new Promise((resolve) => {
|
|
58
|
+
// unref so the pending timer never keeps the CLI alive on its own.
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
abortController.abort();
|
|
61
|
+
resolve(null);
|
|
62
|
+
}, ONBOARDING_URL_TIMEOUT).unref();
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
65
|
+
// createNxCloudOnboardingURL never throws - on an unreachable API it returns a
|
|
66
|
+
// paste-a-token URL (accessToken=undefined). Only accept a real short link.
|
|
67
|
+
if (url?.startsWith(`${(0, get_cloud_options_1.getCloudUrl)()}/connect/`)) {
|
|
68
|
+
remoteCacheLink = url;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
logger_1.logger.verbose(`Keeping the get-started remote-cache link (${url === null ? 'onboarding URL timed out' : `got: ${url}`})`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
logger_1.logger.verbose(`Keeping the get-started remote-cache link: ${e}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
19
78
|
/**
|
|
20
79
|
* Whole-phrase CTA: the whole sentence is the link. The Rust TUI popup keeps no
|
|
21
80
|
* copy of this string; it gets the phrase + href from the exit payload's `links`.
|
|
@@ -176,7 +235,7 @@ const RECOMMENDATIONS = [
|
|
|
176
235
|
c.cacheableCount > 0 &&
|
|
177
236
|
!c.remoteCacheEnabled &&
|
|
178
237
|
c.cacheHits / c.cacheableCount <= LOW_CACHE_HIT_RATE,
|
|
179
|
-
build: () => [phraseLink(NX_REMOTE_CACHE_CTA,
|
|
238
|
+
build: () => [phraseLink(NX_REMOTE_CACHE_CTA, remoteCacheLink), `.`],
|
|
180
239
|
},
|
|
181
240
|
{
|
|
182
241
|
// Cache skipped: drop the flag to restore unchanged tasks instantly.
|
|
@@ -39,6 +39,7 @@ const store_run_information_life_cycle_1 = require("./life-cycles/store-run-info
|
|
|
39
39
|
const task_history_life_cycle_1 = require("./life-cycles/task-history-life-cycle");
|
|
40
40
|
const task_profiling_life_cycle_1 = require("./life-cycles/task-profiling-life-cycle");
|
|
41
41
|
const performance_life_cycle_1 = require("./life-cycles/performance-life-cycle");
|
|
42
|
+
const performance_report_1 = require("./life-cycles/performance-report");
|
|
42
43
|
const task_results_life_cycle_1 = require("./life-cycles/task-results-life-cycle");
|
|
43
44
|
const task_telemetry_life_cycle_1 = require("./life-cycles/task-telemetry-life-cycle");
|
|
44
45
|
const task_timings_life_cycle_1 = require("./life-cycles/task-timings-life-cycle");
|
|
@@ -80,6 +81,9 @@ async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, pr
|
|
|
80
81
|
if (tasks.length === 1 && !is_tui_enabled_1.ORIGINAL_TUI_ENV_VALUE) {
|
|
81
82
|
process.env.NX_TUI = 'false';
|
|
82
83
|
}
|
|
84
|
+
// Kick off in the background so the URL is ready by the exit report. A brief
|
|
85
|
+
// sync preamble (git remote + axios load) runs here; the network call does not.
|
|
86
|
+
(0, performance_report_1.prefetchRemoteCacheOnboardingUrl)(nxJson);
|
|
83
87
|
if ((0, is_tui_enabled_1.isTuiEnabled)()) {
|
|
84
88
|
const interceptedNxCloudLogs = [];
|
|
85
89
|
// Resolve where the Nx Cloud client bundle actually loads from so the
|
|
@@ -3,7 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.assertWorkspaceValidity = assertWorkspaceValidity;
|
|
4
4
|
const find_matching_projects_1 = require("./find-matching-projects");
|
|
5
5
|
const output_1 = require("./output");
|
|
6
|
-
|
|
6
|
+
// Import from the defining module, not the devkit-internals barrel: this file
|
|
7
|
+
// is on the project-graph construction path, and the barrel now eagerly
|
|
8
|
+
// re-exports the project-graph modules, which would create a require cycle back
|
|
9
|
+
// through build-project-graph. (Release modules cross the barrel as erased
|
|
10
|
+
// types only — see the note in packages/devkit/internal.ts.)
|
|
11
|
+
const error_types_1 = require("../project-graph/error-types");
|
|
7
12
|
function assertWorkspaceValidity(projects, nxJson) {
|
|
8
13
|
const projectNames = Object.keys(projects);
|
|
9
14
|
const projectGraphNodes = projectNames.reduce((graph, project) => {
|
|
@@ -65,7 +70,7 @@ function assertWorkspaceValidity(projects, nxJson) {
|
|
|
65
70
|
})
|
|
66
71
|
.join('\n\n');
|
|
67
72
|
}
|
|
68
|
-
throw new
|
|
73
|
+
throw new error_types_1.WorkspaceValidityError(message);
|
|
69
74
|
}
|
|
70
75
|
function detectAndSetInvalidProjectGlobValues(map, sourceName, desiredImplicitDeps, projectConfigurations, projects) {
|
|
71
76
|
const invalidProjectsOrGlobs = desiredImplicitDeps.filter((implicit) => {
|
|
@@ -1,7 +1,37 @@
|
|
|
1
|
-
import { type ExecOptions, type ExecSyncOptions } from 'child_process';
|
|
1
|
+
import { type ExecOptions, type ExecSyncOptions, type SpawnSyncOptions } from 'child_process';
|
|
2
2
|
import { PackageManagerCommands } from './package-manager';
|
|
3
3
|
import { ChildProcess } from '../native';
|
|
4
4
|
export declare function getRunNxBaseCommand(packageManagerCommand?: PackageManagerCommands, cwd?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Locate an nx entry point to spawn for the workspace at `root`, so a caller
|
|
7
|
+
* can run it directly instead of going through a shell. `findInstalledNxBin`
|
|
8
|
+
* decides which one.
|
|
9
|
+
*
|
|
10
|
+
* Null means nothing may be spawned directly, leaving the caller to fall back
|
|
11
|
+
* to `getRunNxBaseCommand`. Null is therefore always safe: it costs the
|
|
12
|
+
* argument fidelity a direct spawn buys, never the ability to run.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getNxBin(root?: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* The entry point the nx installed directly under `dir` names, with no ascent
|
|
17
|
+
* to `dir`'s ancestors. For an installation that declares nx itself, such as
|
|
18
|
+
* the temp CLI `nx migrate` builds, an ancestor's nx is never the right answer.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readInstalledNxBin(dir: string): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Run a nx command, passing the arguments through as an argv array.
|
|
23
|
+
*
|
|
24
|
+
* When `getNxBin` names an entry point, the child is spawned directly with no
|
|
25
|
+
* shell in between, so every argument reaches the child exactly as provided:
|
|
26
|
+
* shell metacharacters (`(`, `%`, `^`, spaces, quotes) are data, not syntax.
|
|
27
|
+
* Otherwise falls back to the package-manager + shell path, where every
|
|
28
|
+
* argument goes through `quoteShellArg` and the Windows limits it documents
|
|
29
|
+
* apply.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runNxArgvSync(argv: string[], options?: SpawnSyncOptions & {
|
|
32
|
+
cwd?: string;
|
|
33
|
+
nxBin?: string;
|
|
34
|
+
}): void;
|
|
5
35
|
export declare function runNxSync(cmd: string, options?: ExecSyncOptions & {
|
|
6
36
|
cwd?: string;
|
|
7
37
|
packageManagerCommand?: PackageManagerCommands;
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PseudoTtyProcess = void 0;
|
|
4
4
|
exports.getRunNxBaseCommand = getRunNxBaseCommand;
|
|
5
|
+
exports.getNxBin = getNxBin;
|
|
6
|
+
exports.readInstalledNxBin = readInstalledNxBin;
|
|
7
|
+
exports.runNxArgvSync = runNxArgvSync;
|
|
5
8
|
exports.runNxSync = runNxSync;
|
|
6
9
|
exports.runNxAsync = runNxAsync;
|
|
7
10
|
const child_process_1 = require("child_process");
|
|
@@ -10,9 +13,14 @@ const path_1 = require("path");
|
|
|
10
13
|
const package_manager_1 = require("./package-manager");
|
|
11
14
|
const workspace_root_1 = require("./workspace-root");
|
|
12
15
|
const exit_codes_1 = require("./exit-codes");
|
|
16
|
+
const fileutils_1 = require("./fileutils");
|
|
17
|
+
const shell_quoting_1 = require("./shell-quoting");
|
|
13
18
|
function getRunNxBaseCommand(packageManagerCommand, cwd = process.cwd()) {
|
|
14
19
|
if ((0, fs_1.existsSync)((0, path_1.join)(workspace_root_1.workspaceRoot, 'package.json'))) {
|
|
15
20
|
if (!packageManagerCommand) {
|
|
21
|
+
// `readLocalNxVersion` (command-line/migrate/migrate.ts) mirrors this
|
|
22
|
+
// selector to predict which nx a spawn will run, for the workspaces
|
|
23
|
+
// `getNxBin` declines to resolve; keep the two in sync.
|
|
16
24
|
const pm = (0, package_manager_1.detectPackageManager)(workspace_root_1.workspaceRoot);
|
|
17
25
|
packageManagerCommand = (0, package_manager_1.getPackageManagerCommand)(pm, workspace_root_1.workspaceRoot);
|
|
18
26
|
}
|
|
@@ -28,6 +36,101 @@ function getRunNxBaseCommand(packageManagerCommand, cwd = process.cwd()) {
|
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Locate an nx entry point to spawn for the workspace at `root`, so a caller
|
|
41
|
+
* can run it directly instead of going through a shell. `findInstalledNxBin`
|
|
42
|
+
* decides which one.
|
|
43
|
+
*
|
|
44
|
+
* Null means nothing may be spawned directly, leaving the caller to fall back
|
|
45
|
+
* to `getRunNxBaseCommand`. Null is therefore always safe: it costs the
|
|
46
|
+
* argument fidelity a direct spawn buys, never the ability to run.
|
|
47
|
+
*/
|
|
48
|
+
function getNxBin(root = workspace_root_1.workspaceRoot) {
|
|
49
|
+
// A workspace with no root package.json runs nx through the `./nx` wrapper,
|
|
50
|
+
// which reinstalls `.nx/installation` whenever it drifts from nx.json's
|
|
51
|
+
// `installation.version`. Spawning the resolved entry point would skip that
|
|
52
|
+
// sync, and a migration is precisely when the version changes.
|
|
53
|
+
if (!(0, fs_1.existsSync)((0, path_1.join)(root, 'package.json'))) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return findInstalledNxBin(root);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The entry point the nx installed directly under `dir` names, with no ascent
|
|
60
|
+
* to `dir`'s ancestors. For an installation that declares nx itself, such as
|
|
61
|
+
* the temp CLI `nx migrate` builds, an ancestor's nx is never the right answer.
|
|
62
|
+
*/
|
|
63
|
+
function readInstalledNxBin(dir) {
|
|
64
|
+
const packageDir = (0, path_1.join)(dir, 'node_modules', 'nx');
|
|
65
|
+
const manifest = (0, path_1.join)(packageDir, 'package.json');
|
|
66
|
+
if (!(0, fs_1.existsSync)(manifest)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
let bin;
|
|
70
|
+
try {
|
|
71
|
+
({ bin } = (0, fileutils_1.readJsonFile)(manifest));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
// npm accepts both the single-entry shorthand and the map form.
|
|
77
|
+
const entry = typeof bin === 'string' ? bin : bin?.nx;
|
|
78
|
+
return typeof entry === 'string' ? (0, path_1.join)(packageDir, entry) : null;
|
|
79
|
+
}
|
|
80
|
+
// Ascend to the nearest installed nx and take the entry point its `bin` field
|
|
81
|
+
// names, which is the file a package manager links into `node_modules/.bin`.
|
|
82
|
+
// Deliberately npx-shaped: npx and bun ascend unconditionally while pnpm and
|
|
83
|
+
// yarn stop at an outer workspace, so this can name an nx those two would
|
|
84
|
+
// decline to run.
|
|
85
|
+
//
|
|
86
|
+
// Deliberately not a resolver. Resolvers answer from NODE_PATH once their
|
|
87
|
+
// explicit paths miss, and `nxCliPath` (command-line/migrate/migrate.ts) points
|
|
88
|
+
// NODE_PATH at the temp installation before spawning it; they also answer
|
|
89
|
+
// through package self-reference, which hands back the running nx whatever
|
|
90
|
+
// `paths` they are given. Either one lets the temp installation hand off to
|
|
91
|
+
// itself, which for `--run-migrations` re-enters the same hand-off and respawns
|
|
92
|
+
// without end.
|
|
93
|
+
function findInstalledNxBin(root) {
|
|
94
|
+
for (let dir = root;; dir = (0, path_1.dirname)(dir)) {
|
|
95
|
+
// The nearest install wins, so an unusable manifest there ends the search
|
|
96
|
+
// rather than deferring to an ancestor.
|
|
97
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(dir, 'node_modules', 'nx', 'package.json'))) {
|
|
98
|
+
return readInstalledNxBin(dir);
|
|
99
|
+
}
|
|
100
|
+
if (dir === (0, path_1.dirname)(dir)) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Run a nx command, passing the arguments through as an argv array.
|
|
107
|
+
*
|
|
108
|
+
* When `getNxBin` names an entry point, the child is spawned directly with no
|
|
109
|
+
* shell in between, so every argument reaches the child exactly as provided:
|
|
110
|
+
* shell metacharacters (`(`, `%`, `^`, spaces, quotes) are data, not syntax.
|
|
111
|
+
* Otherwise falls back to the package-manager + shell path, where every
|
|
112
|
+
* argument goes through `quoteShellArg` and the Windows limits it documents
|
|
113
|
+
* apply.
|
|
114
|
+
*/
|
|
115
|
+
function runNxArgvSync(argv, options) {
|
|
116
|
+
let { nxBin, ...spawnOptions } = options ?? {};
|
|
117
|
+
spawnOptions.cwd ??= process.cwd();
|
|
118
|
+
spawnOptions.windowsHide ??= true;
|
|
119
|
+
nxBin ??= getNxBin((0, workspace_root_1.workspaceRootInner)(spawnOptions.cwd, null) ?? workspace_root_1.workspaceRoot);
|
|
120
|
+
if (!nxBin) {
|
|
121
|
+
runNxSync(argv.map(shell_quoting_1.quoteShellArg).join(' '), spawnOptions);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const result = (0, child_process_1.spawnSync)(process.execPath, [nxBin, ...argv], spawnOptions);
|
|
125
|
+
if (result.error) {
|
|
126
|
+
throw result.error;
|
|
127
|
+
}
|
|
128
|
+
if (result.status !== 0) {
|
|
129
|
+
const error = new Error(`Command failed: nx ${argv.join(' ')} (exit code ${result.status})`);
|
|
130
|
+
error.status = result.status ?? 1;
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
31
134
|
function runNxSync(cmd, options) {
|
|
32
135
|
let { packageManagerCommand, ...execSyncOptions } = options ?? {};
|
|
33
136
|
execSyncOptions.cwd ??= process.cwd();
|
|
@@ -1,7 +1,134 @@
|
|
|
1
1
|
import ignore = require('ignore');
|
|
2
2
|
import { Tree } from '../generators/tree';
|
|
3
3
|
export declare function getIgnoreObject(root?: string): ReturnType<typeof ignore>;
|
|
4
|
-
|
|
4
|
+
/** One directory's ignore files, and the directory its patterns are rooted at. */
|
|
5
|
+
export type ScopedIgnoreMatcher = {
|
|
6
|
+
/** Workspace-relative POSIX directory, `''` for the workspace root. */
|
|
7
|
+
dir: string;
|
|
8
|
+
/** How they relate is decided at build time - see `merge`. */
|
|
9
|
+
matchers: ReturnType<typeof ignore>[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the ignore files that apply to a directory: its own and every one
|
|
13
|
+
* above it, up to the workspace root.
|
|
14
|
+
*
|
|
15
|
+
* Ignore files cascade - a `.gitignore` covers its own directory and below, and
|
|
16
|
+
* its patterns are relative to *itself*, not to the workspace root. Reading only
|
|
17
|
+
* the root file, which is what `getIgnoreObject` does, silently misses every
|
|
18
|
+
* nested one.
|
|
19
|
+
*
|
|
20
|
+
* A directory's answer is its own files plus its parent's, so every directory on
|
|
21
|
+
* the way up is memoized rather than only the one asked for: sibling leaves
|
|
22
|
+
* share the whole trunk, and a later walk stops at the first directory already
|
|
23
|
+
* known.
|
|
24
|
+
*
|
|
25
|
+
* `read` decides where the files come from - `tree.read` for a generator, disk
|
|
26
|
+
* for a caller with no tree - and returns an empty string or null when there is
|
|
27
|
+
* no such file. Paths handed to it are workspace-relative POSIX.
|
|
28
|
+
*
|
|
29
|
+
* `merge` decides how the files *within one directory* relate, and the two
|
|
30
|
+
* consumers genuinely need different rules:
|
|
31
|
+
*
|
|
32
|
+
* - `false` is prettier's: one matcher per file, any of them excluding wins, and
|
|
33
|
+
* a negation counts only if none excluded. `createIsIgnoredFunction` builds an
|
|
34
|
+
* ignorer per `--ignore-path` and ORs them, so a `!x` in `.prettierignore`
|
|
35
|
+
* cannot re-include an `x` that `.gitignore` excluded.
|
|
36
|
+
* - `true` is git's and the native walker's: all files in one matcher, so
|
|
37
|
+
* `.nxignore`'s `!x` removes `.gitignore`'s exclusion of `x` outright. It has
|
|
38
|
+
* to be a merge rather than a precedence check between separate matchers,
|
|
39
|
+
* because a lone `!x` in its own matcher reports an opinion on `x/` but *none*
|
|
40
|
+
* on `x/a.ts` (measured), so the exclusion would still reach the children.
|
|
41
|
+
* The merge only removes the exclusion within that one directory - a negation
|
|
42
|
+
* in a nested file still loses to an ancestor's exclusion.
|
|
43
|
+
*
|
|
44
|
+
* When `merge` is true, `filenames` order matters: they go into one matcher in
|
|
45
|
+
* order and the last matching pattern decides, so list them lowest-authority
|
|
46
|
+
* first.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createIgnoreChainResolver(read: (path: string) => string | null | undefined, filenames: string[], merge: boolean): (dir: string) => ScopedIgnoreMatcher[];
|
|
49
|
+
/**
|
|
50
|
+
* True when the file is ignored, resolving the chain nearest file first.
|
|
51
|
+
*
|
|
52
|
+
* Each matcher is tested against the path relative to its own directory, which
|
|
53
|
+
* is what makes a nested pattern like `/build` mean that directory's `build`
|
|
54
|
+
* rather than the workspace's.
|
|
55
|
+
*
|
|
56
|
+
* Nearest directory with an *opinion* wins, not the first match: a nested
|
|
57
|
+
* `!keep.log` must override the root's `*.log`, which is git's rule for files.
|
|
58
|
+
* A nested negation of a *directory* does not reach its children - see the
|
|
59
|
+
* `merge` note on `createIgnoreChainResolver`.
|
|
60
|
+
*
|
|
61
|
+
* How the files of one directory relate is decided when the chain is built - see
|
|
62
|
+
* that same note. Here they are simply the entry's matchers: any one excluding
|
|
63
|
+
* wins, and a negation counts only if none excluded.
|
|
64
|
+
*
|
|
65
|
+
* Two preconditions, both satisfied by a pruning walk and neither enforced:
|
|
66
|
+
*
|
|
67
|
+
* - `filePath` is workspace-relative POSIX and must sit under every `dir` in the
|
|
68
|
+
* chain, which holds when the chain came from that file's own directory.
|
|
69
|
+
* - No ancestor directory of `filePath` may itself be ignored. git refuses to
|
|
70
|
+
* re-include a file inside an excluded directory, and this does not implement
|
|
71
|
+
* that rule: asked directly about `dist/keep.ts` with a root `dist/` and a
|
|
72
|
+
* nested `dist/.gitignore` holding `!keep.ts`, it answers "not ignored" where
|
|
73
|
+
* git says ignored (measured). `visitNotIgnoredFiles` never asks, because it
|
|
74
|
+
* prunes `dist/` before descending - which is what makes its answers match
|
|
75
|
+
* git, and why that pruning is load-bearing for correctness rather than speed.
|
|
76
|
+
*/
|
|
77
|
+
export declare function isIgnoredByChain(chain: ScopedIgnoreMatcher[], filePath: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Directories that should never be walked, whatever the workspace's own ignore
|
|
80
|
+
* files say - `node_modules`, `.git`, the nx caches.
|
|
81
|
+
*
|
|
82
|
+
* The list comes from the native walker rather than a second copy here, so a
|
|
83
|
+
* filesystem walk and a tree walk cannot drift apart.
|
|
84
|
+
*
|
|
85
|
+
* Checked ahead of the cascading chain rather than folded into it: these are not
|
|
86
|
+
* re-includable, and as ordinary patterns a nested negation could resurrect
|
|
87
|
+
* `node_modules`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function isAlwaysIgnored(path: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* The chain bound to a tree, as predicates over workspace-relative POSIX paths.
|
|
92
|
+
*
|
|
93
|
+
* Files and directories are asked separately because the answers differ: a
|
|
94
|
+
* pattern is only directory-only if it ends in a slash, and `ignore` will not
|
|
95
|
+
* match `dist/` against the path `dist`. Callers must not have to know that, so
|
|
96
|
+
* the slash is appended inside and never leaves this module.
|
|
97
|
+
*/
|
|
98
|
+
export type TreeIgnoreChecker = {
|
|
99
|
+
isIgnoredFile: (path: string) => boolean;
|
|
100
|
+
isIgnoredDirectory: (path: string) => boolean;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* What git ignores, which is also what the native walker ignores.
|
|
104
|
+
*
|
|
105
|
+
* `.nxignore` outranks `.gitignore` - `walker.rs` registers it with
|
|
106
|
+
* `add_custom_ignore_filename` - which a merge with `.nxignore` last reproduces.
|
|
107
|
+
* git itself does not read it.
|
|
108
|
+
*
|
|
109
|
+
* Reads from the tree rather than disk because a generator can create or amend
|
|
110
|
+
* an ignore file in the same run, which would leave the on-disk copy stale.
|
|
111
|
+
*/
|
|
112
|
+
export declare function createGitIgnoreChecker(tree: Tree): TreeIgnoreChecker;
|
|
113
|
+
/**
|
|
114
|
+
* What prettier ignores: the workspace root only, and one ignorer per
|
|
115
|
+
* `--ignore-path` ORed rather than merged (both measured), so a `!` in
|
|
116
|
+
* `.prettierignore` cannot re-include what `.gitignore` excluded. That is the
|
|
117
|
+
* CLI `nx format:check` shells out to.
|
|
118
|
+
*
|
|
119
|
+
* Not an exact match for that command: `isAlwaysIgnored` is wider than
|
|
120
|
+
* prettier's built-ins, and `format.ts` filters its own patterns through
|
|
121
|
+
* `.nxignore`, which this does not read.
|
|
122
|
+
*
|
|
123
|
+
* Reads from the tree rather than disk, as above.
|
|
124
|
+
*/
|
|
125
|
+
export declare function createPrettierIgnoreChecker(tree: Tree): TreeIgnoreChecker;
|
|
126
|
+
/**
|
|
127
|
+
* `path.dirname` for the workspace-relative POSIX paths the chain is keyed by,
|
|
128
|
+
* except that the workspace root is `''` rather than `.` - that is the key
|
|
129
|
+
* `createIgnoreChainResolver` terminates on.
|
|
130
|
+
*/
|
|
131
|
+
export declare function posixDirname(relativePath: string): string;
|
|
5
132
|
/**
|
|
6
133
|
* Adds an entry to a .gitignore file if it's not already covered by existing patterns.
|
|
7
134
|
* Creates the file if it doesn't exist.
|
package/dist/src/utils/ignore.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getIgnoreObject = getIgnoreObject;
|
|
4
|
-
exports.
|
|
4
|
+
exports.createIgnoreChainResolver = createIgnoreChainResolver;
|
|
5
|
+
exports.isIgnoredByChain = isIgnoredByChain;
|
|
6
|
+
exports.isAlwaysIgnored = isAlwaysIgnored;
|
|
7
|
+
exports.createGitIgnoreChecker = createGitIgnoreChecker;
|
|
8
|
+
exports.createPrettierIgnoreChecker = createPrettierIgnoreChecker;
|
|
9
|
+
exports.posixDirname = posixDirname;
|
|
5
10
|
exports.addEntryToGitIgnore = addEntryToGitIgnore;
|
|
6
11
|
const ignore = require("ignore");
|
|
12
|
+
const index_1 = require("../native/index");
|
|
7
13
|
const fileutils_1 = require("./fileutils");
|
|
8
14
|
const workspace_root_1 = require("./workspace-root");
|
|
9
15
|
function getIgnoreObject(root = workspace_root_1.workspaceRoot) {
|
|
@@ -12,18 +18,182 @@ function getIgnoreObject(root = workspace_root_1.workspaceRoot) {
|
|
|
12
18
|
ig.add((0, fileutils_1.readFileIfExisting)(`${root}/.nxignore`));
|
|
13
19
|
return ig;
|
|
14
20
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the ignore files that apply to a directory: its own and every one
|
|
23
|
+
* above it, up to the workspace root.
|
|
24
|
+
*
|
|
25
|
+
* Ignore files cascade - a `.gitignore` covers its own directory and below, and
|
|
26
|
+
* its patterns are relative to *itself*, not to the workspace root. Reading only
|
|
27
|
+
* the root file, which is what `getIgnoreObject` does, silently misses every
|
|
28
|
+
* nested one.
|
|
29
|
+
*
|
|
30
|
+
* A directory's answer is its own files plus its parent's, so every directory on
|
|
31
|
+
* the way up is memoized rather than only the one asked for: sibling leaves
|
|
32
|
+
* share the whole trunk, and a later walk stops at the first directory already
|
|
33
|
+
* known.
|
|
34
|
+
*
|
|
35
|
+
* `read` decides where the files come from - `tree.read` for a generator, disk
|
|
36
|
+
* for a caller with no tree - and returns an empty string or null when there is
|
|
37
|
+
* no such file. Paths handed to it are workspace-relative POSIX.
|
|
38
|
+
*
|
|
39
|
+
* `merge` decides how the files *within one directory* relate, and the two
|
|
40
|
+
* consumers genuinely need different rules:
|
|
41
|
+
*
|
|
42
|
+
* - `false` is prettier's: one matcher per file, any of them excluding wins, and
|
|
43
|
+
* a negation counts only if none excluded. `createIsIgnoredFunction` builds an
|
|
44
|
+
* ignorer per `--ignore-path` and ORs them, so a `!x` in `.prettierignore`
|
|
45
|
+
* cannot re-include an `x` that `.gitignore` excluded.
|
|
46
|
+
* - `true` is git's and the native walker's: all files in one matcher, so
|
|
47
|
+
* `.nxignore`'s `!x` removes `.gitignore`'s exclusion of `x` outright. It has
|
|
48
|
+
* to be a merge rather than a precedence check between separate matchers,
|
|
49
|
+
* because a lone `!x` in its own matcher reports an opinion on `x/` but *none*
|
|
50
|
+
* on `x/a.ts` (measured), so the exclusion would still reach the children.
|
|
51
|
+
* The merge only removes the exclusion within that one directory - a negation
|
|
52
|
+
* in a nested file still loses to an ancestor's exclusion.
|
|
53
|
+
*
|
|
54
|
+
* When `merge` is true, `filenames` order matters: they go into one matcher in
|
|
55
|
+
* order and the last matching pattern decides, so list them lowest-authority
|
|
56
|
+
* first.
|
|
57
|
+
*/
|
|
58
|
+
function createIgnoreChainResolver(read, filenames, merge) {
|
|
59
|
+
const cache = new Map();
|
|
60
|
+
const resolve = (dir) => {
|
|
61
|
+
const cached = cache.get(dir);
|
|
62
|
+
if (cached) {
|
|
63
|
+
return cached;
|
|
64
|
+
}
|
|
65
|
+
const contents = filenames
|
|
66
|
+
.map((name) => read(dir ? `${dir}/${name}` : name))
|
|
67
|
+
.filter((c) => !!c);
|
|
68
|
+
const matchers = merge
|
|
69
|
+
? contents.length > 0
|
|
70
|
+
? [contents.reduce((m, c) => m.add(c), ignore())]
|
|
71
|
+
: []
|
|
72
|
+
: contents.map((c) => ignore().add(c));
|
|
73
|
+
const inherited = dir === '' ? [] : resolve(posixDirname(dir));
|
|
74
|
+
const chain = matchers.length > 0 ? [{ dir, matchers }, ...inherited] : inherited;
|
|
75
|
+
cache.set(dir, chain);
|
|
76
|
+
return chain;
|
|
77
|
+
};
|
|
78
|
+
return resolve;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* True when the file is ignored, resolving the chain nearest file first.
|
|
82
|
+
*
|
|
83
|
+
* Each matcher is tested against the path relative to its own directory, which
|
|
84
|
+
* is what makes a nested pattern like `/build` mean that directory's `build`
|
|
85
|
+
* rather than the workspace's.
|
|
86
|
+
*
|
|
87
|
+
* Nearest directory with an *opinion* wins, not the first match: a nested
|
|
88
|
+
* `!keep.log` must override the root's `*.log`, which is git's rule for files.
|
|
89
|
+
* A nested negation of a *directory* does not reach its children - see the
|
|
90
|
+
* `merge` note on `createIgnoreChainResolver`.
|
|
91
|
+
*
|
|
92
|
+
* How the files of one directory relate is decided when the chain is built - see
|
|
93
|
+
* that same note. Here they are simply the entry's matchers: any one excluding
|
|
94
|
+
* wins, and a negation counts only if none excluded.
|
|
95
|
+
*
|
|
96
|
+
* Two preconditions, both satisfied by a pruning walk and neither enforced:
|
|
97
|
+
*
|
|
98
|
+
* - `filePath` is workspace-relative POSIX and must sit under every `dir` in the
|
|
99
|
+
* chain, which holds when the chain came from that file's own directory.
|
|
100
|
+
* - No ancestor directory of `filePath` may itself be ignored. git refuses to
|
|
101
|
+
* re-include a file inside an excluded directory, and this does not implement
|
|
102
|
+
* that rule: asked directly about `dist/keep.ts` with a root `dist/` and a
|
|
103
|
+
* nested `dist/.gitignore` holding `!keep.ts`, it answers "not ignored" where
|
|
104
|
+
* git says ignored (measured). `visitNotIgnoredFiles` never asks, because it
|
|
105
|
+
* prunes `dist/` before descending - which is what makes its answers match
|
|
106
|
+
* git, and why that pruning is load-bearing for correctness rather than speed.
|
|
107
|
+
*/
|
|
108
|
+
function isIgnoredByChain(chain, filePath) {
|
|
109
|
+
for (const { dir, matchers } of chain) {
|
|
110
|
+
const relative = dir === '' ? filePath : filePath.slice(dir.length + 1);
|
|
111
|
+
let unignored = false;
|
|
112
|
+
for (const matcher of matchers) {
|
|
113
|
+
const result = matcher.test(relative);
|
|
114
|
+
if (result.ignored) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
unignored ||= result.unignored;
|
|
118
|
+
}
|
|
119
|
+
if (unignored) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
25
122
|
}
|
|
26
|
-
return
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
let alwaysIgnored;
|
|
126
|
+
/**
|
|
127
|
+
* Directories that should never be walked, whatever the workspace's own ignore
|
|
128
|
+
* files say - `node_modules`, `.git`, the nx caches.
|
|
129
|
+
*
|
|
130
|
+
* The list comes from the native walker rather than a second copy here, so a
|
|
131
|
+
* filesystem walk and a tree walk cannot drift apart.
|
|
132
|
+
*
|
|
133
|
+
* Checked ahead of the cascading chain rather than folded into it: these are not
|
|
134
|
+
* re-includable, and as ordinary patterns a nested negation could resurrect
|
|
135
|
+
* `node_modules`.
|
|
136
|
+
*/
|
|
137
|
+
function isAlwaysIgnored(path) {
|
|
138
|
+
alwaysIgnored ??= ignore().add((0, index_1.getHardcodedIgnorePatterns)());
|
|
139
|
+
return alwaysIgnored.ignores(path);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* What git ignores, which is also what the native walker ignores.
|
|
143
|
+
*
|
|
144
|
+
* `.nxignore` outranks `.gitignore` - `walker.rs` registers it with
|
|
145
|
+
* `add_custom_ignore_filename` - which a merge with `.nxignore` last reproduces.
|
|
146
|
+
* git itself does not read it.
|
|
147
|
+
*
|
|
148
|
+
* Reads from the tree rather than disk because a generator can create or amend
|
|
149
|
+
* an ignore file in the same run, which would leave the on-disk copy stale.
|
|
150
|
+
*/
|
|
151
|
+
function createGitIgnoreChecker(tree) {
|
|
152
|
+
return createTreeIgnoreChecker(tree, {
|
|
153
|
+
filenames: ['.gitignore', '.nxignore'],
|
|
154
|
+
cascade: true,
|
|
155
|
+
merge: true,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* What prettier ignores: the workspace root only, and one ignorer per
|
|
160
|
+
* `--ignore-path` ORed rather than merged (both measured), so a `!` in
|
|
161
|
+
* `.prettierignore` cannot re-include what `.gitignore` excluded. That is the
|
|
162
|
+
* CLI `nx format:check` shells out to.
|
|
163
|
+
*
|
|
164
|
+
* Not an exact match for that command: `isAlwaysIgnored` is wider than
|
|
165
|
+
* prettier's built-ins, and `format.ts` filters its own patterns through
|
|
166
|
+
* `.nxignore`, which this does not read.
|
|
167
|
+
*
|
|
168
|
+
* Reads from the tree rather than disk, as above.
|
|
169
|
+
*/
|
|
170
|
+
function createPrettierIgnoreChecker(tree) {
|
|
171
|
+
return createTreeIgnoreChecker(tree, {
|
|
172
|
+
filenames: ['.gitignore', '.prettierignore'],
|
|
173
|
+
cascade: false,
|
|
174
|
+
merge: false,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function createTreeIgnoreChecker(tree, { filenames, cascade, merge }) {
|
|
178
|
+
const resolve = createIgnoreChainResolver((path) => tree.read(path, 'utf-8'), filenames, merge);
|
|
179
|
+
// `probe` may carry a trailing slash; `path` never does. The chain is keyed by
|
|
180
|
+
// real directories, and `posixDirname('dist/')` is `'dist'` rather than the
|
|
181
|
+
// parent, so the lookup always uses the slash-less form.
|
|
182
|
+
const check = (path, probe) => isAlwaysIgnored(probe) ||
|
|
183
|
+
isIgnoredByChain(resolve(cascade ? posixDirname(path) : ''), probe);
|
|
184
|
+
return {
|
|
185
|
+
isIgnoredFile: (path) => check(path, path),
|
|
186
|
+
isIgnoredDirectory: (path) => check(path, `${path}/`),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* `path.dirname` for the workspace-relative POSIX paths the chain is keyed by,
|
|
191
|
+
* except that the workspace root is `''` rather than `.` - that is the key
|
|
192
|
+
* `createIgnoreChainResolver` terminates on.
|
|
193
|
+
*/
|
|
194
|
+
function posixDirname(relativePath) {
|
|
195
|
+
const separator = relativePath.lastIndexOf('/');
|
|
196
|
+
return separator === -1 ? '' : relativePath.slice(0, separator);
|
|
27
197
|
}
|
|
28
198
|
/**
|
|
29
199
|
* Adds an entry to a .gitignore file if it's not already covered by existing patterns.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable root for Nx runtime artifacts that need an OS tmp location. On POSIX a
|
|
3
|
+
* literal `/tmp`, not `os.tmpdir()`, which honours `$TMPDIR` — per-user on
|
|
4
|
+
* macOS, rewritten by sandboxes, stripped from the daemon env, so client and
|
|
5
|
+
* daemon would disagree. Windows has no `/tmp`, and `%TMP%` is already per-user
|
|
6
|
+
* and stable, so it keeps `os.tmpdir()`.
|
|
7
|
+
*
|
|
8
|
+
* Consumed by the native binding loader, so keep this file limited to local
|
|
9
|
+
* helpers that themselves use Node builtins only.
|
|
10
|
+
*/
|
|
11
|
+
export declare const NX_TMP_DIR: string;
|
|
12
|
+
/**
|
|
13
|
+
* Owner-only runtime root for the current user. No user segment on Windows —
|
|
14
|
+
* `%TMP%` is already per-account, and the segment would only cost path length.
|
|
15
|
+
*/
|
|
16
|
+
export declare const NX_USER_TMP_DIR: string;
|
|
17
|
+
/** Runtime root under the user's home, used when the shared container cannot be established. */
|
|
18
|
+
export declare const NX_HOME_TMP_DIR: string;
|