Skip to content

Commit 32c7e25

Browse files
committed
Reapply "feat(core): make console daemon check backgroundable and pull… (#33578)
This reverts commit 626fb08.
1 parent 6a24e9c commit 32c7e25

File tree

9 files changed

+474
-28
lines changed

9 files changed

+474
-28
lines changed

packages/nx/bin/init-local.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { performance } from 'perf_hooks';
33
import { commandsObject } from '../src/command-line/nx-commands';
44
import { WorkspaceTypeAndRoot } from '../src/utils/find-workspace-root';
55
import { stripIndents } from '../src/utils/strip-indents';
6-
import { ensureNxConsoleInstalled } from '../src/utils/nx-console-prompt';
6+
import { daemonClient } from '../src/daemon/client/client';
7+
import { prompt } from 'enquirer';
8+
import { output } from '../src/utils/output';
79

810
/**
911
* Nx is being run inside a workspace.
@@ -33,7 +35,7 @@ export async function initLocal(workspace: WorkspaceTypeAndRoot) {
3335

3436
// Ensure NxConsole is installed if the user has it configured.
3537
try {
36-
await ensureNxConsoleInstalled();
38+
await ensureNxConsoleInstalledViaDaemon();
3739
} catch {}
3840

3941
const command = process.argv[2];
@@ -121,6 +123,51 @@ function shouldDelegateToAngularCLI() {
121123
return commands.indexOf(command) > -1;
122124
}
123125

126+
async function ensureNxConsoleInstalledViaDaemon(): Promise<void> {
127+
// Only proceed if daemon is available
128+
if (!daemonClient.enabled()) {
129+
return;
130+
}
131+
132+
// Get status from daemon
133+
const status = await daemonClient.getNxConsoleStatus();
134+
135+
// If we should prompt the user
136+
if (status.shouldPrompt && process.stdout.isTTY) {
137+
output.log({
138+
title: "Install Nx's official editor extension to:",
139+
bodyLines: [
140+
'- Enable your AI assistant to do more by understanding your workspace',
141+
'- Add IntelliSense for Nx configuration files',
142+
'- Explore your workspace visually',
143+
],
144+
});
145+
146+
try {
147+
const { shouldInstallNxConsole } = await prompt<{
148+
shouldInstallNxConsole: boolean;
149+
}>({
150+
type: 'confirm',
151+
name: 'shouldInstallNxConsole',
152+
message: 'Install Nx Console? (you can uninstall anytime)',
153+
initial: true,
154+
});
155+
156+
// Set preference and install if user said yes
157+
const result = await daemonClient.setNxConsolePreferenceAndInstall(
158+
shouldInstallNxConsole
159+
);
160+
161+
if (result.installed) {
162+
output.log({ title: 'Successfully installed Nx Console!' });
163+
}
164+
} catch (error) {
165+
// User cancelled or error occurred, save preference as false
166+
await daemonClient.setNxConsolePreferenceAndInstall(false);
167+
}
168+
}
169+
}
170+
124171
function handleAngularCLIFallbacks(workspace: WorkspaceTypeAndRoot) {
125172
if (process.argv[2] === 'update' && process.env.FORCE_NG_UPDATE != 'true') {
126173
console.log(

packages/nx/src/daemon/client/client.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ import {
9696
PRE_TASKS_EXECUTION,
9797
} from '../message-types/run-tasks-execution-hooks';
9898
import { REGISTER_PROJECT_GRAPH_LISTENER } from '../message-types/register-project-graph-listener';
99+
import {
100+
GET_NX_CONSOLE_STATUS,
101+
type HandleGetNxConsoleStatusMessage,
102+
type HandleSetNxConsolePreferenceAndInstallMessage,
103+
type NxConsoleStatusResponse,
104+
SET_NX_CONSOLE_PREFERENCE_AND_INSTALL,
105+
type SetNxConsolePreferenceAndInstallResponse,
106+
} from '../message-types/nx-console';
99107
import { deserialize } from 'node:v8';
100108
import { isJsonMessage } from '../../utils/consume-messages-from-socket';
101109
import { isV8SerializerEnabled } from '../is-v8-serializer-enabled';
@@ -564,6 +572,23 @@ export class DaemonClient {
564572
return this.sendToDaemonViaQueue(message);
565573
}
566574

575+
getNxConsoleStatus(): Promise<NxConsoleStatusResponse> {
576+
const message: HandleGetNxConsoleStatusMessage = {
577+
type: GET_NX_CONSOLE_STATUS,
578+
};
579+
return this.sendToDaemonViaQueue(message);
580+
}
581+
582+
setNxConsolePreferenceAndInstall(
583+
preference: boolean
584+
): Promise<SetNxConsolePreferenceAndInstallResponse> {
585+
const message: HandleSetNxConsolePreferenceAndInstallMessage = {
586+
type: SET_NX_CONSOLE_PREFERENCE_AND_INSTALL,
587+
preference,
588+
};
589+
return this.sendToDaemonViaQueue(message);
590+
}
591+
567592
async isServerAvailable(): Promise<boolean> {
568593
return new Promise((resolve) => {
569594
try {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export const GET_NX_CONSOLE_STATUS = 'GET_NX_CONSOLE_STATUS' as const;
2+
export const SET_NX_CONSOLE_PREFERENCE_AND_INSTALL =
3+
'SET_NX_CONSOLE_PREFERENCE_AND_INSTALL' as const;
4+
5+
export type HandleGetNxConsoleStatusMessage = {
6+
type: typeof GET_NX_CONSOLE_STATUS;
7+
};
8+
9+
export type NxConsoleStatusResponse = {
10+
shouldPrompt: boolean;
11+
};
12+
13+
export type HandleSetNxConsolePreferenceAndInstallMessage = {
14+
type: typeof SET_NX_CONSOLE_PREFERENCE_AND_INSTALL;
15+
preference: boolean;
16+
};
17+
18+
export type SetNxConsolePreferenceAndInstallResponse = {
19+
installed: boolean;
20+
};
21+
22+
export function isHandleGetNxConsoleStatusMessage(
23+
message: unknown
24+
): message is HandleGetNxConsoleStatusMessage {
25+
return (
26+
typeof message === 'object' &&
27+
message !== null &&
28+
'type' in message &&
29+
message['type'] === GET_NX_CONSOLE_STATUS
30+
);
31+
}
32+
33+
export function isHandleSetNxConsolePreferenceAndInstallMessage(
34+
message: unknown
35+
): message is HandleSetNxConsolePreferenceAndInstallMessage {
36+
return (
37+
typeof message === 'object' &&
38+
message !== null &&
39+
'type' in message &&
40+
message['type'] === SET_NX_CONSOLE_PREFERENCE_AND_INSTALL
41+
);
42+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type {
2+
NxConsoleStatusResponse,
3+
SetNxConsolePreferenceAndInstallResponse,
4+
} from '../message-types/nx-console';
5+
import type { HandlerResult } from './server';
6+
import {
7+
getNxConsoleStatus,
8+
handleNxConsolePreferenceAndInstall,
9+
} from './nx-console-operations';
10+
11+
// Module-level state for caching
12+
let cachedShouldPrompt: boolean | null = null;
13+
let isComputing = false;
14+
15+
export async function handleGetNxConsoleStatus(): Promise<HandlerResult> {
16+
// Return cached result if available
17+
if (cachedShouldPrompt !== null) {
18+
const response: NxConsoleStatusResponse = {
19+
shouldPrompt: cachedShouldPrompt,
20+
};
21+
return {
22+
response,
23+
description: 'handleGetNxConsoleStatus',
24+
};
25+
}
26+
27+
// Kick off background computation if not already running
28+
if (!isComputing) {
29+
isComputing = true;
30+
getNxConsoleStatus()
31+
.then((result) => {
32+
cachedShouldPrompt = result;
33+
isComputing = false;
34+
})
35+
.catch(() => {
36+
cachedShouldPrompt = null;
37+
isComputing = false;
38+
});
39+
}
40+
41+
// Return false for shouldPrompt if cache not ready (main process will noop)
42+
const response: NxConsoleStatusResponse = {
43+
shouldPrompt: false,
44+
};
45+
46+
return {
47+
response,
48+
description: 'handleGetNxConsoleStatus',
49+
};
50+
}
51+
52+
export async function handleSetNxConsolePreferenceAndInstall(
53+
preference: boolean
54+
): Promise<HandlerResult> {
55+
// Immediately update cache - we know the answer now!
56+
// User answered the prompt, so we won't prompt again
57+
cachedShouldPrompt = false;
58+
59+
const result = await handleNxConsolePreferenceAndInstall({ preference });
60+
61+
const response: SetNxConsolePreferenceAndInstallResponse = {
62+
installed: result.installed,
63+
};
64+
65+
return {
66+
response,
67+
description: 'handleSetNxConsolePreferenceAndInstall',
68+
};
69+
}

0 commit comments

Comments
 (0)