1*5234fe38SCedric van Puttendeclare module 'metro-inspector-proxy/src/Device' {
2*5234fe38SCedric van Putten  import { Device } from 'metro-inspector-proxy';
3*5234fe38SCedric van Putten  export = Device;
4*5234fe38SCedric van Putten}
5*5234fe38SCedric van Putten
633643b60SEvan Bacondeclare module 'metro-inspector-proxy' {
7*5234fe38SCedric van Putten  import WS from 'ws';
8*5234fe38SCedric van Putten  import type { Server as HttpsServer } from 'https';
9*5234fe38SCedric van Putten  import type {
10*5234fe38SCedric van Putten    IncomingMessage as HttpRequest,
11*5234fe38SCedric van Putten    ServerResponse as HttpResponse,
12*5234fe38SCedric van Putten    Server as HttpServer,
13*5234fe38SCedric van Putten  } from 'http';
14*5234fe38SCedric van Putten
15*5234fe38SCedric van Putten  type Middleware = (error?: Error) => any;
16*5234fe38SCedric van Putten
17*5234fe38SCedric van Putten  /**
18*5234fe38SCedric van Putten   * Page information received from the device. New page is created for
19*5234fe38SCedric van Putten   * each new instance of VM and can appear when user reloads React Native
20*5234fe38SCedric van Putten   * application.
21*5234fe38SCedric van Putten   */
22*5234fe38SCedric van Putten  type Page = {
23*5234fe38SCedric van Putten    id: string;
24*5234fe38SCedric van Putten    title: string;
25*5234fe38SCedric van Putten    vm: string;
26*5234fe38SCedric van Putten    app: string;
27*5234fe38SCedric van Putten
28*5234fe38SCedric van Putten    // Allow objects too
29*5234fe38SCedric van Putten    [key: string]: string;
30*5234fe38SCedric van Putten  };
31*5234fe38SCedric van Putten
32*5234fe38SCedric van Putten  type DebuggerInfo = {
33*5234fe38SCedric van Putten    // Debugger web socket connection
34*5234fe38SCedric van Putten    socket: WS;
35*5234fe38SCedric van Putten    // If we replaced address (like '10.0.2.2') to localhost we need to store original
36*5234fe38SCedric van Putten    // address because Chrome uses URL or urlRegex params (instead of scriptId) to set breakpoints.
37*5234fe38SCedric van Putten    originalSourceURLAddress?: string;
38*5234fe38SCedric van Putten    prependedFilePrefix: boolean;
39*5234fe38SCedric van Putten    pageId: string;
40*5234fe38SCedric van Putten
41*5234fe38SCedric van Putten    // Allow objects too
42*5234fe38SCedric van Putten    [key: string]: string;
43*5234fe38SCedric van Putten  };
44*5234fe38SCedric van Putten
45*5234fe38SCedric van Putten  type PageDescription = any;
46*5234fe38SCedric van Putten
47*5234fe38SCedric van Putten  function runInspectorProxy(port: number, projectRoot: string): void;
48*5234fe38SCedric van Putten
49*5234fe38SCedric van Putten  class InspectorProxy {
50*5234fe38SCedric van Putten    /** Root of the project used for relative to absolute source path conversion. */
51*5234fe38SCedric van Putten    _projectRoot: string;
52*5234fe38SCedric van Putten    /** Maps device ID to Device instance. */
53*5234fe38SCedric van Putten    _devices: Map<number, Device>;
54*5234fe38SCedric van Putten    /** Internal counter for device IDs -- just gets incremented for each new device. */
55*5234fe38SCedric van Putten    _deviceCounter: number = 0;
56*5234fe38SCedric van Putten
57*5234fe38SCedric van Putten    /**
58*5234fe38SCedric van Putten     * We store server's address with port (like '127.0.0.1:8081') to be able to build URLs
59*5234fe38SCedric van Putten     * (devtoolsFrontendUrl and webSocketDebuggerUrl) for page descriptions. These URLs are used
60*5234fe38SCedric van Putten     * by debugger to know where to connect.
61*5234fe38SCedric van Putten     */
62*5234fe38SCedric van Putten    _serverAddressWithPort: string = '';
63*5234fe38SCedric van Putten
6433643b60SEvan Bacon    constructor(projectRoot: string);
65*5234fe38SCedric van Putten
66*5234fe38SCedric van Putten    /**
67*5234fe38SCedric van Putten     * Process HTTP request sent to server. We only respond to 2 HTTP requests:
68*5234fe38SCedric van Putten     * 1. /json/version returns Chrome debugger protocol version that we use
69*5234fe38SCedric van Putten     * 2. /json and /json/list returns list of page descriptions (list of inspectable apps).
70*5234fe38SCedric van Putten     * This list is combined from all the connected devices.
71*5234fe38SCedric van Putten     */
72*5234fe38SCedric van Putten    processRequest(req: HttpRequest, res: HttpResponse, next: Middleware): void;
73*5234fe38SCedric van Putten
74*5234fe38SCedric van Putten    /** Adds websocket listeners to the provided HTTP/HTTPS server. */
75*5234fe38SCedric van Putten    createWebSocketListeners(server: HttpServer | HttpsServer): Record<string, WS.Server>;
76*5234fe38SCedric van Putten
77*5234fe38SCedric van Putten    /** Converts page information received from device into PageDescription object that is sent to debugger. */
78*5234fe38SCedric van Putten    _buildPageDescription(deviceId: number, device: Device, page: Page): PageDescription;
79*5234fe38SCedric van Putten
80*5234fe38SCedric van Putten    /**
81*5234fe38SCedric van Putten     * Sends object as response to HTTP request.
82*5234fe38SCedric van Putten     * Just serializes object using JSON and sets required headers.
83*5234fe38SCedric van Putten     */
84*5234fe38SCedric van Putten    _sendJsonResponse(response: ServerResponse, object: any): void;
85*5234fe38SCedric van Putten
86*5234fe38SCedric van Putten    /**
87*5234fe38SCedric van Putten     * Adds websocket handler for device connections.
88*5234fe38SCedric van Putten     * Device connects to /inspector/device and passes device and app names as
89*5234fe38SCedric van Putten     * HTTP GET params.
90*5234fe38SCedric van Putten     * For each new websocket connection we parse device and app names and create
91*5234fe38SCedric van Putten     * new instance of Device class.
92*5234fe38SCedric van Putten     */
93*5234fe38SCedric van Putten    _createDeviceConnectionWSServer(): WS.Server;
94*5234fe38SCedric van Putten
95*5234fe38SCedric van Putten    /**
96*5234fe38SCedric van Putten     * Returns websocket handler for debugger connections.
97*5234fe38SCedric van Putten     * Debugger connects to webSocketDebuggerUrl that we return as part of page description
98*5234fe38SCedric van Putten     * in /json response.
99*5234fe38SCedric van Putten     * When debugger connects we try to parse device and page IDs from the query and pass
100*5234fe38SCedric van Putten     * websocket object to corresponding Device instance.
101*5234fe38SCedric van Putten     */
102*5234fe38SCedric van Putten    _createDebuggerConnectionWSServer(): WS.Server;
103*5234fe38SCedric van Putten  }
104*5234fe38SCedric van Putten
105*5234fe38SCedric van Putten  class Device {
106*5234fe38SCedric van Putten    /** ID of the device. */
107*5234fe38SCedric van Putten    _id: number;
108*5234fe38SCedric van Putten    /** Name of the device. */
109*5234fe38SCedric van Putten    _name: string;
110*5234fe38SCedric van Putten    /** Package name of the app. */
111*5234fe38SCedric van Putten    _app: string;
112*5234fe38SCedric van Putten    /** Stores socket connection between Inspector Proxy and device. */
113*5234fe38SCedric van Putten    _deviceSocket: WS;
114*5234fe38SCedric van Putten    /** Stores last list of device's pages. */
115*5234fe38SCedric van Putten    _pages: Page[];
116*5234fe38SCedric van Putten    /** Stores information about currently connected debugger (if any). */
117*5234fe38SCedric van Putten    _debuggerConnection: DebuggerInfo | null = null;
118*5234fe38SCedric van Putten    /** Whether we are in the middle of a reload in the REACT_NATIVE_RELOADABLE_PAGE. */
119*5234fe38SCedric van Putten    _isReloading: boolean = false;
120*5234fe38SCedric van Putten    /** The previous "GetPages" message, for deduplication in debug logs. */
121*5234fe38SCedric van Putten    _lastGetPagesMessage: string = '';
122*5234fe38SCedric van Putten    /** Mapping built from scriptParsed events and used to fetch file content in `Debugger.getScriptSource`. */
123*5234fe38SCedric van Putten    _scriptIdToSourcePathMapping: Map<string, string>;
124*5234fe38SCedric van Putten    /** Root of the project used for relative to absolute source path conversion. */
125*5234fe38SCedric van Putten    _projectRoot: string;
126*5234fe38SCedric van Putten
127*5234fe38SCedric van Putten    /**
128*5234fe38SCedric van Putten     * Last known Page ID of the React Native page.
129*5234fe38SCedric van Putten     * This is used by debugger connections that don't have PageID specified
130*5234fe38SCedric van Putten     * (and will interact with the latest React Native page).
131*5234fe38SCedric van Putten     */
132*5234fe38SCedric van Putten    _lastConnectedReactNativePage: Page | null = null;
133*5234fe38SCedric van Putten
134*5234fe38SCedric van Putten    constructor(id: number, name: string, app: string, socket: WS, projectRoot: string);
135*5234fe38SCedric van Putten
136*5234fe38SCedric van Putten    getName(): string;
137*5234fe38SCedric van Putten    getPagesList(): Page[];
138*5234fe38SCedric van Putten
139*5234fe38SCedric van Putten    /**
140*5234fe38SCedric van Putten     * Handles new debugger connection to this device:
141*5234fe38SCedric van Putten     * 1. Sends connect event to device
142*5234fe38SCedric van Putten     * 2. Forwards all messages from the debugger to device as wrappedEvent
143*5234fe38SCedric van Putten     * 3. Sends disconnect event to device when debugger connection socket closes.
144*5234fe38SCedric van Putten     */
145*5234fe38SCedric van Putten    handleDebuggerConnection(socket: WS, pageId: string): void;
146*5234fe38SCedric van Putten
147*5234fe38SCedric van Putten    /**
148*5234fe38SCedric van Putten     * Handles messages received from device:
149*5234fe38SCedric van Putten     * 1. For getPages responses updates local _pages list.
150*5234fe38SCedric van Putten     * 2. All other messages are forwarded to debugger as wrappedEvent.
151*5234fe38SCedric van Putten     *
152*5234fe38SCedric van Putten     * In the future more logic will be added to this method for modifying
153*5234fe38SCedric van Putten     * some of the messages (like updating messages with source maps and file locations).
154*5234fe38SCedric van Putten     */
155*5234fe38SCedric van Putten    _handleMessageFromDevice(message: MessageFromDevice): void;
156*5234fe38SCedric van Putten
157*5234fe38SCedric van Putten    /** Sends single message to device. */
158*5234fe38SCedric van Putten    _sendMessageToDevice(message: MessageToDevice): void;
159*5234fe38SCedric van Putten
160*5234fe38SCedric van Putten    /** Sends 'getPages' request to device every PAGES_POLLING_INTERVAL milliseconds.*/
161*5234fe38SCedric van Putten    _setPagesPolling(): void;
162*5234fe38SCedric van Putten
163*5234fe38SCedric van Putten    /** Allows to make changes in incoming message from device. */
164*5234fe38SCedric van Putten    _processMessageFromDevice(
165*5234fe38SCedric van Putten      payload: { method: string; params: { sourceMapURL: string; url: string } },
166*5234fe38SCedric van Putten      debuggerInfo: DebuggerInfo
167*5234fe38SCedric van Putten    ): void;
168*5234fe38SCedric van Putten
169*5234fe38SCedric van Putten    /** Allows to make changes in incoming messages from debugger. */
170*5234fe38SCedric van Putten    _interceptMessageFromDebugger(
171*5234fe38SCedric van Putten      request: DebuggerRequest,
172*5234fe38SCedric van Putten      debuggerInfo: DebuggerInfo,
173*5234fe38SCedric van Putten      socket: WS
174*5234fe38SCedric van Putten    ): DebuggerResponse | null;
175*5234fe38SCedric van Putten
176*5234fe38SCedric van Putten    // _newReactNativePage
177*5234fe38SCedric van Putten    // _processDebuggerSetBreakpointByUrl
178*5234fe38SCedric van Putten    // _processDebuggerGetScriptSource
179*5234fe38SCedric van Putten    // _mapToDevicePageId
18033643b60SEvan Bacon  }
18133643b60SEvan Bacon}
182