Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli): support multiple debug targets #3376

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-adults-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rnx-kit/cli": patch
---

Support multiple debug targets
90 changes: 74 additions & 16 deletions packages/cli/src/serve/keyboard.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,93 @@
import { info } from "@rnx-kit/console";
import type { MetroTerminal } from "@rnx-kit/metro-service";
import * as fs from "node:fs";
import type { Server } from "node:http";
import * as path from "node:path";
import readline from "node:readline";
import qrcode from "qrcode";
import type { DevServerMiddleware } from "./types";

type Options = {
type OpenDebuggerKeyboardHandler = {
handleOpenDebugger: () => Promise<void>;
maybeHandleTargetSelection: (key: string) => boolean;
dismiss: () => void;
};

type Params = {
devServerUrl: string;
help: () => void;
messageSocketEndpoint: DevServerMiddleware["messageSocketEndpoint"];
terminal: MetroTerminal["terminal"];
metroTerminal: MetroTerminal;
reactNativePath: string;
};

export function attachKeyHandlers({
function createOpenDebuggerKeyboardHandler({
devServerUrl,
help,
messageSocketEndpoint,
terminal,
}: Options) {
metroTerminal: { reporter },
reactNativePath,
}: Params): OpenDebuggerKeyboardHandler {
const resolvedPath = fs.lstatSync(reactNativePath).isSymbolicLink()
? path.resolve(
path.dirname(reactNativePath),
fs.readlinkSync(reactNativePath)
)
: reactNativePath;
try {
// Available starting with 0.76
const cliPlugin = require.resolve(
"@react-native/community-cli-plugin/package.json",
{ paths: [resolvedPath] }
);
const OpenDebuggerKeyboardHandler = require(
`${path.dirname(cliPlugin)}/dist/commands/start/OpenDebuggerKeyboardHandler`
);
return new OpenDebuggerKeyboardHandler({ devServerUrl, reporter });
} catch (_) {
return {
handleOpenDebugger: () => {
info("Opening debugger...");
fetch(devServerUrl + "/open-debugger", { method: "POST" });
return Promise.resolve();
},
maybeHandleTargetSelection: (_: string): boolean => false,
dismiss: () => undefined,
};
}
}

export function attachKeyHandlers(server: Server, params: Params) {
const openDebuggerKeyboardHandler = createOpenDebuggerKeyboardHandler(params);
const {
devServerUrl,
help,
messageSocketEndpoint,
metroTerminal: { terminal },
} = params;

process.on("SIGINT", () => {
openDebuggerKeyboardHandler.dismiss();
process.stdin.pause();
process.stdin.setRawMode(false);
info("Exiting...");
server.close();
server.closeAllConnections?.(); // This method was added in Node v18.2.0

// Even when we close all connections, clients may keep the server alive.
process.exit();
});

process.stdin.setRawMode(true);
process.stdin.on("keypress", (_key, data) => {
const { ctrl, name } = data;
if (openDebuggerKeyboardHandler.maybeHandleTargetSelection(name)) {
return;
}

if (ctrl === true) {
switch (name) {
case "c":
info("Exiting...");
process.exit();
break;
case "z":
process.emit("SIGTSTP", "SIGTSTP");
case "d":
process.emit("SIGINT");
break;
}
} else {
Expand All @@ -41,11 +101,9 @@ export function attachKeyHandlers({
help();
break;

case "j": {
info("Opening debugger...");
fetch(devServerUrl + "/open-debugger", { method: "POST" });
case "j":
openDebuggerKeyboardHandler.handleOpenDebugger();
break;
}

case "q": {
const url = `${devServerUrl}/index.bundle`;
Expand Down
11 changes: 10 additions & 1 deletion packages/cli/src/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,16 @@ export async function rnxStart(
// in interactive mode, listen for keyboard events from stdin and bind
// them to specific actions.
if (interactive) {
attachKeyHandlers({ devServerUrl, help, messageSocketEndpoint, terminal });
attachKeyHandlers(serverInstance, {
devServerUrl,
help,
messageSocketEndpoint,
metroTerminal: {
terminal,
reporter: terminalReporter,
},
reactNativePath: ctx.reactNativePath,
});
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/test-app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,7 @@ PODS:
- ReactTestApp-MSAL (4.0.0):
- MSAL
- ReactTestApp-Resources (1.0.0-dev)
- RNWWebStorage (0.3.0):
- RNWWebStorage (0.3.1):
- DoubleConversion
- glog
- RCT-Folly (= 2024.01.01.00)
Expand Down Expand Up @@ -1786,7 +1786,7 @@ SPEC CHECKSUMS:
ReactTestApp-DevSupport: 74676edd899013becce4eaecc5eabba1fc51e26e
ReactTestApp-MSAL: a7ac8e821fce95fc4e27cd91cf2a931b277ffef3
ReactTestApp-Resources: a4cc1f968cd26bdbd18ee0bfbd0ab8dd0ea90101
RNWWebStorage: 39af6c7aa24a9360372280338e0f5900630779a2
RNWWebStorage: 16ea67c1467a5b91c2859c490bec800f001adf78
RNXAuth: 7716515bc74149d226d798138f2d76af9f34427f
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63
Expand Down
Loading