@rnx-kit/cli 0.9.55 → 0.10.0

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/src/start.ts CHANGED
@@ -6,13 +6,15 @@ import {
6
6
  startServer,
7
7
  } from "@rnx-kit/metro-service";
8
8
  import chalk from "chalk";
9
- import type { Reporter, ReportableEvent } from "metro";
10
- import type Server from "metro/src/Server";
9
+ import type { ReportableEvent, Reporter } from "metro";
11
10
  import type { Middleware } from "metro-config";
11
+ import type Server from "metro/src/Server";
12
+ import os from "os";
12
13
  import path from "path";
14
+ import qrcode from "qrcode";
13
15
  import readline from "readline";
14
- import { getKitServerConfig } from "./serve/kit-config";
15
16
  import { customizeMetroConfig } from "./metro-config";
17
+ import { getKitServerConfig } from "./serve/kit-config";
16
18
  import type { TypeScriptValidationOptions } from "./types";
17
19
 
18
20
  export type CLIStartOptions = {
@@ -85,17 +87,16 @@ export async function rnxStart(
85
87
  reportEventDelegate(event);
86
88
  }
87
89
  if (interactive && event.type === "dep_graph_loading") {
88
- terminal.log("To reload the app press '" + chalk.cyanBright("r") + "'");
89
- terminal.log(
90
- "To open developer menu press '" + chalk.cyanBright("d") + "'"
91
- );
92
- terminal.log(
93
- "To quit, press '" +
94
- chalk.cyanBright("control") +
95
- "-" +
96
- chalk.cyanBright("c") +
97
- "'"
98
- );
90
+ const dim = chalk.dim;
91
+ const press = dim(" › Press ");
92
+ [
93
+ ["r", "reload the app"],
94
+ ["d", "open developer menu"],
95
+ ["a", "show bundler address QR code"],
96
+ ["ctrl-c", "quit"],
97
+ ].forEach(([key, description]) => {
98
+ terminal.log(press + key + dim(` to ${description}.`));
99
+ });
99
100
  }
100
101
  },
101
102
  };
@@ -199,14 +200,31 @@ export async function rnxStart(
199
200
  process.emit("SIGTSTP", "SIGTSTP");
200
201
  break;
201
202
  }
202
- } else if (name === "r") {
203
- terminal.log(chalk.green("Reloading app..."));
204
- messageSocket.broadcast("reload", undefined);
205
- } else if (name === "d") {
206
- terminal.log(chalk.green("Opening developer menu..."));
207
- messageSocket.broadcast("devMenu", undefined);
208
203
  } else {
209
- terminal.log(chalk.grey(_key));
204
+ switch (name) {
205
+ case "a": {
206
+ const protocol = cliOptions.https ? "https" : "http";
207
+ const host = cliOptions.host || os.hostname();
208
+ const port = metroConfig.server.port;
209
+ const url = `${protocol}://${host}:${port}/index.bundle`;
210
+ qrcode.toString(url, { type: "terminal" }, (_err, qr) => {
211
+ terminal.log("");
212
+ terminal.log(url + ":");
213
+ terminal.log(qr);
214
+ });
215
+ break;
216
+ }
217
+
218
+ case "d":
219
+ terminal.log(chalk.green("Opening developer menu..."));
220
+ messageSocket.broadcast("devMenu", undefined);
221
+ break;
222
+
223
+ case "r":
224
+ terminal.log(chalk.green("Reloading app..."));
225
+ messageSocket.broadcast("reload", undefined);
226
+ break;
227
+ }
210
228
  }
211
229
  });
212
230
  }
@@ -12,6 +12,11 @@ import {
12
12
  import path from "path";
13
13
  import ts from "typescript";
14
14
 
15
+ export type ProjectInfo = {
16
+ tsproject: Project;
17
+ tssourceFiles: Set<string>;
18
+ };
19
+
15
20
  /**
16
21
  * Collection of TypeScript projects, separated by their target platform.
17
22
  *
@@ -32,14 +37,14 @@ export interface ProjectCache {
32
37
  clearPlatform(platform: AllPlatforms): void;
33
38
 
34
39
  /**
35
- * Get the project which targets a specific platform and contains a specific
40
+ * Get info on the project which targets a specific platform and contains a specific
36
41
  * source file. If the project is not cached, load it and add it to the cache.
37
42
  *
38
43
  * @param platform Target platform
39
44
  * @param sourceFile Source file
40
45
  * @returns Project targeting the given platform and containing the given source file
41
46
  */
42
- getProject(sourceFile: string, platform: AllPlatforms): Project;
47
+ getProjectInfo(sourceFile: string, platform: AllPlatforms): ProjectInfo;
43
48
  }
44
49
 
45
50
  /**
@@ -55,7 +60,10 @@ export function createProjectCache(
55
60
  const diagnosticWriter = createDiagnosticWriter(print);
56
61
 
57
62
  // Collection of projects organized by root directory, then by platform.
58
- const projects: Record<string, Partial<Record<AllPlatforms, Project>>> = {};
63
+ const projects: Record<
64
+ string,
65
+ Partial<Record<AllPlatforms, ProjectInfo>>
66
+ > = {};
59
67
 
60
68
  function findProjectRoot(sourceFile: string): string {
61
69
  // Search known root directories to see if the source file is in one of them.
@@ -91,10 +99,25 @@ export function createProjectCache(
91
99
  return cmdLine;
92
100
  }
93
101
 
94
- function createProject(root: string, platform: AllPlatforms): Project {
102
+ function createProjectInfo(
103
+ root: string,
104
+ platform: AllPlatforms
105
+ ): ProjectInfo {
95
106
  // Load the TypeScript configuration file for this project.
96
107
  const cmdLine = readTSConfig(root);
97
108
 
109
+ // Trim down the list of source files found by TypeScript. This ensures
110
+ // that only explicitly added files are loaded and parsed by TypeScript.
111
+ // This is a perf optimization. We don't want to spend cycles on files
112
+ // that won't be used, such as *.android.ts when bundling for ios.
113
+ //
114
+ // The exception to this rule are .d.ts files. They hold global types,
115
+ // modules and namespaces, and having them in the project is the only
116
+ // way they can be loaded.
117
+
118
+ const tssourceFiles = new Set(cmdLine.fileNames);
119
+ cmdLine.fileNames = cmdLine.fileNames.filter((f) => f.endsWith(".d.ts"));
120
+
98
121
  // Create a TypeScript project using the configuration file. Enhance the
99
122
  // underlying TS language service with our react-native module resolver.
100
123
  const enhanceLanguageServiceHost = (host: ts.LanguageServiceHost): void => {
@@ -119,28 +142,34 @@ export function createProjectCache(
119
142
  enhanceLanguageServiceHost
120
143
  );
121
144
 
122
- // Start with an empty project, ignoring the file graph from tsconfig.json.
123
- tsproject.removeAllFiles();
124
-
125
- return tsproject;
145
+ return {
146
+ tsproject,
147
+ tssourceFiles,
148
+ };
126
149
  }
127
150
 
128
- function getProject(sourceFile: string, platform: AllPlatforms): Project {
151
+ function getProjectInfo(
152
+ sourceFile: string,
153
+ platform: AllPlatforms
154
+ ): ProjectInfo {
129
155
  const root = findProjectRoot(sourceFile);
130
- if (!projects[root]) {
131
- projects[root] = {};
132
- }
133
- if (!projects[root][platform]) {
134
- projects[root][platform] = createProject(root, platform);
156
+ projects[root] ||= {};
157
+
158
+ let info = projects[root][platform];
159
+ if (!info) {
160
+ info = createProjectInfo(root, platform);
161
+ projects[root][platform] = info;
135
162
  }
136
- return projects[root][platform]!;
163
+ return info;
137
164
  }
138
165
 
139
166
  function clearPlatform(platform: AllPlatforms): void {
140
167
  Object.values(projects).forEach((projectsByPlatform) => {
141
- const project = projectsByPlatform[platform];
142
- if (project) {
143
- project.dispose();
168
+ const info = projectsByPlatform[platform];
169
+ if (info) {
170
+ if (info.tsproject) {
171
+ info.tsproject.dispose();
172
+ }
144
173
  delete projectsByPlatform[platform];
145
174
  }
146
175
  });
@@ -148,6 +177,6 @@ export function createProjectCache(
148
177
 
149
178
  return {
150
179
  clearPlatform,
151
- getProject,
180
+ getProjectInfo,
152
181
  };
153
182
  }