@rnx-kit/cli 0.16.29 → 0.17.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/README.md +172 -98
- package/bin/rnx-cli.cjs +2 -0
- package/lib/align-deps.js +5 -5
- package/lib/bin/context.d.ts +25 -0
- package/lib/bin/context.js +98 -0
- package/lib/bin/externalCommands.d.ts +3 -0
- package/lib/bin/externalCommands.js +34 -0
- package/lib/bin/rnx-cli.d.ts +2 -0
- package/lib/bin/rnx-cli.js +55 -0
- package/lib/bundle/cliOptions.d.ts +2 -2
- package/lib/bundle/cliOptions.js +27 -27
- package/lib/bundle/hermes.d.ts +2 -1
- package/lib/bundle/hermes.js +9 -15
- package/lib/bundle/metro.js +6 -9
- package/lib/bundle.d.ts +3 -3
- package/lib/bundle.js +4 -4
- package/lib/clean.d.ts +3 -3
- package/lib/clean.js +47 -67
- package/lib/copy-assets.d.ts +5 -3
- package/lib/copy-assets.js +31 -28
- package/lib/helpers/externals.d.ts +4 -0
- package/lib/{serve/external.js → helpers/externals.js} +10 -8
- package/lib/helpers/filesystem.d.ts +3 -0
- package/lib/helpers/filesystem.js +31 -0
- package/lib/{metro-config.js → helpers/metro-config.js} +1 -1
- package/lib/{parsers.d.ts → helpers/parsers.d.ts} +1 -1
- package/lib/{parsers.js → helpers/parsers.js} +17 -15
- package/lib/index.d.ts +2 -188
- package/lib/index.js +1 -5
- package/lib/ram-bundle.d.ts +4 -4
- package/lib/ram-bundle.js +2 -2
- package/lib/serve/keyboard.js +3 -6
- package/lib/serve/types.d.ts +2 -2
- package/lib/start.d.ts +1 -1
- package/lib/start.js +34 -34
- package/lib/test.d.ts +2 -1
- package/lib/test.js +7 -5
- package/lib/write-third-party-notices.js +13 -13
- package/package.json +24 -23
- package/lib/serve/external.d.ts +0 -7
- package/src/align-deps.ts +0 -82
- package/src/bundle/cliOptions.ts +0 -82
- package/src/bundle/defaultPlugins.ts +0 -16
- package/src/bundle/hermes.ts +0 -114
- package/src/bundle/kit-config.ts +0 -81
- package/src/bundle/metro.ts +0 -66
- package/src/bundle/overrides.ts +0 -51
- package/src/bundle/types.ts +0 -41
- package/src/bundle.ts +0 -69
- package/src/clean.ts +0 -223
- package/src/copy-assets.ts +0 -545
- package/src/index.ts +0 -34
- package/src/metro-config.ts +0 -208
- package/src/parsers.ts +0 -44
- package/src/ram-bundle.ts +0 -78
- package/src/serve/external.ts +0 -62
- package/src/serve/help.ts +0 -59
- package/src/serve/keyboard.ts +0 -76
- package/src/serve/kit-config.ts +0 -47
- package/src/serve/types.ts +0 -87
- package/src/start.ts +0 -316
- package/src/test.ts +0 -137
- package/src/write-third-party-notices.ts +0 -85
- /package/lib/{metro-config.d.ts → helpers/metro-config.d.ts} +0 -0
package/src/metro-config.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import type { BundleParameters } from "@rnx-kit/config";
|
|
2
|
-
import { warn } from "@rnx-kit/console";
|
|
3
|
-
import { CyclicDependencies } from "@rnx-kit/metro-plugin-cyclic-dependencies-detector";
|
|
4
|
-
import { DuplicateDependencies } from "@rnx-kit/metro-plugin-duplicates-checker";
|
|
5
|
-
import { TypeScriptPlugin } from "@rnx-kit/metro-plugin-typescript";
|
|
6
|
-
import type { MetroPlugin } from "@rnx-kit/metro-serializer";
|
|
7
|
-
import { MetroSerializer } from "@rnx-kit/metro-serializer";
|
|
8
|
-
import {
|
|
9
|
-
esbuildTransformerConfig,
|
|
10
|
-
MetroSerializer as MetroSerializerEsbuild,
|
|
11
|
-
} from "@rnx-kit/metro-serializer-esbuild";
|
|
12
|
-
import type { ConfigT, SerializerConfigT } from "metro-config";
|
|
13
|
-
import type { WritableDeep } from "type-fest";
|
|
14
|
-
import { getDefaultBundlerPlugins } from "./bundle/defaultPlugins";
|
|
15
|
-
|
|
16
|
-
type MetroExtraParams = Pick<
|
|
17
|
-
BundleParameters,
|
|
18
|
-
| "detectCyclicDependencies"
|
|
19
|
-
| "detectDuplicateDependencies"
|
|
20
|
-
| "typescriptValidation"
|
|
21
|
-
| "plugins"
|
|
22
|
-
| "treeShake"
|
|
23
|
-
>;
|
|
24
|
-
|
|
25
|
-
function resolvePlugin(name: string): string {
|
|
26
|
-
try {
|
|
27
|
-
return require.resolve(name);
|
|
28
|
-
} catch (_) {
|
|
29
|
-
return require.resolve(name, { paths: [process.cwd()] });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function importPlugin(name: string) {
|
|
34
|
-
const plugin = require(resolvePlugin(name));
|
|
35
|
-
return plugin.default || plugin;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function readLegacyOptions({
|
|
39
|
-
detectCyclicDependencies,
|
|
40
|
-
detectDuplicateDependencies,
|
|
41
|
-
typescriptValidation,
|
|
42
|
-
}: MetroExtraParams): string | undefined {
|
|
43
|
-
const oldOptions = [];
|
|
44
|
-
const deprecatedOptions: Record<string, Record<string, unknown> | true> = {};
|
|
45
|
-
|
|
46
|
-
if (detectCyclicDependencies) {
|
|
47
|
-
oldOptions.push("detectCyclicDependencies");
|
|
48
|
-
deprecatedOptions["@rnx-kit/metro-plugin-cyclic-dependencies-detector"] =
|
|
49
|
-
detectCyclicDependencies;
|
|
50
|
-
}
|
|
51
|
-
if (detectDuplicateDependencies) {
|
|
52
|
-
oldOptions.push("detectDuplicateDependencies");
|
|
53
|
-
deprecatedOptions["@rnx-kit/metro-plugin-duplicates-checker"] =
|
|
54
|
-
detectDuplicateDependencies;
|
|
55
|
-
}
|
|
56
|
-
if (typescriptValidation) {
|
|
57
|
-
oldOptions.push("typescriptValidation");
|
|
58
|
-
deprecatedOptions["@rnx-kit/metro-plugin-typescript"] =
|
|
59
|
-
typescriptValidation;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (oldOptions.length === 0) {
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
`'${oldOptions.join("', '")}' have been replaced by a new 'plugins' ` +
|
|
68
|
-
"option. Below is an equivalent config:\n" +
|
|
69
|
-
"\n" +
|
|
70
|
-
' "plugins": [\n' +
|
|
71
|
-
Object.entries(deprecatedOptions)
|
|
72
|
-
.map(([name, options]) => {
|
|
73
|
-
if (typeof options === "object") {
|
|
74
|
-
const json = JSON.stringify(options, null, 2)
|
|
75
|
-
.split("\n")
|
|
76
|
-
.join("\n ");
|
|
77
|
-
return ` ["${name}", ${json}]`;
|
|
78
|
-
} else {
|
|
79
|
-
return ` "${name}"`;
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
.join(",\n") +
|
|
83
|
-
"\n" +
|
|
84
|
-
" ]\n" +
|
|
85
|
-
"\n" +
|
|
86
|
-
"For more details, see " +
|
|
87
|
-
"https://github.com/microsoft/rnx-kit/tree/main/packages/cli#readme"
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Customize the Metro configuration.
|
|
93
|
-
*
|
|
94
|
-
* @param metroConfigReadonly Metro configuration
|
|
95
|
-
* @param extraParams Parameters used to further customize Metro configuration
|
|
96
|
-
* @param print Optional function to use when printing status messages to the Metro console
|
|
97
|
-
*/
|
|
98
|
-
export function customizeMetroConfig(
|
|
99
|
-
metroConfigReadonly: ConfigT,
|
|
100
|
-
extraParams: MetroExtraParams,
|
|
101
|
-
print?: (message: string) => void
|
|
102
|
-
): void {
|
|
103
|
-
// We will be making changes to the Metro configuration. Coerce from a type
|
|
104
|
-
// with readonly props to a type where the props are writeable.
|
|
105
|
-
const metroConfig = metroConfigReadonly as WritableDeep<ConfigT>;
|
|
106
|
-
|
|
107
|
-
const metroPlugins: MetroPlugin[] = [];
|
|
108
|
-
const serializerHooks: Record<
|
|
109
|
-
string,
|
|
110
|
-
SerializerConfigT["experimentalSerializerHook"]
|
|
111
|
-
> = {};
|
|
112
|
-
|
|
113
|
-
const legacyWarning = readLegacyOptions(extraParams);
|
|
114
|
-
if (legacyWarning) {
|
|
115
|
-
warn(legacyWarning);
|
|
116
|
-
|
|
117
|
-
const {
|
|
118
|
-
detectCyclicDependencies,
|
|
119
|
-
detectDuplicateDependencies,
|
|
120
|
-
typescriptValidation,
|
|
121
|
-
} = extraParams;
|
|
122
|
-
|
|
123
|
-
if (typeof detectDuplicateDependencies === "object") {
|
|
124
|
-
metroPlugins.push(DuplicateDependencies(detectDuplicateDependencies));
|
|
125
|
-
} else if (detectDuplicateDependencies !== false) {
|
|
126
|
-
metroPlugins.push(DuplicateDependencies());
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (typeof detectCyclicDependencies === "object") {
|
|
130
|
-
metroPlugins.push(CyclicDependencies(detectCyclicDependencies));
|
|
131
|
-
} else if (detectCyclicDependencies !== false) {
|
|
132
|
-
metroPlugins.push(CyclicDependencies());
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (typescriptValidation !== false) {
|
|
136
|
-
const plugin = TypeScriptPlugin(typescriptValidation, print);
|
|
137
|
-
serializerHooks["@rnx-kit/metro-plugin-typescript"] = plugin;
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
const plugins = extraParams.plugins || getDefaultBundlerPlugins().plugins;
|
|
141
|
-
for (const entry of plugins) {
|
|
142
|
-
const [module, options] = Array.isArray(entry)
|
|
143
|
-
? entry
|
|
144
|
-
: [entry, undefined];
|
|
145
|
-
const plugin = importPlugin(module);
|
|
146
|
-
switch (plugin.type) {
|
|
147
|
-
case "serializer":
|
|
148
|
-
metroPlugins.push(plugin(options));
|
|
149
|
-
break;
|
|
150
|
-
|
|
151
|
-
case "serializerHook":
|
|
152
|
-
serializerHooks[module] = plugin(options, print);
|
|
153
|
-
break;
|
|
154
|
-
|
|
155
|
-
default:
|
|
156
|
-
throw new Error(`${module}: unknown plugin type: ${plugin.type}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (extraParams.treeShake) {
|
|
162
|
-
if (metroConfig.serializer.customSerializer) {
|
|
163
|
-
warn(
|
|
164
|
-
"`serializer.customSerializer` in `metro.config.js` will be overwritten to enable tree shaking"
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
metroConfig.serializer.customSerializer = MetroSerializerEsbuild(
|
|
168
|
-
metroPlugins,
|
|
169
|
-
typeof extraParams.treeShake === "object"
|
|
170
|
-
? extraParams.treeShake
|
|
171
|
-
: undefined
|
|
172
|
-
);
|
|
173
|
-
Object.assign(metroConfig.transformer, esbuildTransformerConfig);
|
|
174
|
-
} else if (metroPlugins.length > 0) {
|
|
175
|
-
// MetroSerializer acts as a CustomSerializer, and it works with both
|
|
176
|
-
// older and newer versions of Metro. Older versions expect a return
|
|
177
|
-
// value, while newer versions expect a promise.
|
|
178
|
-
//
|
|
179
|
-
// Its return type is the union of both the value and the promise.
|
|
180
|
-
// This makes TypeScript upset because for any given version of Metro,
|
|
181
|
-
// it's one or the other. Not both.
|
|
182
|
-
//
|
|
183
|
-
// Since it can handle either scenario, just coerce it to whatever
|
|
184
|
-
// the current version of Metro expects.
|
|
185
|
-
metroConfig.serializer.customSerializer = MetroSerializer(
|
|
186
|
-
metroPlugins
|
|
187
|
-
) as SerializerConfigT["customSerializer"];
|
|
188
|
-
} else {
|
|
189
|
-
// @ts-expect-error We don't want this set if unused
|
|
190
|
-
delete metroConfig.serializer.customSerializer;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const hooks = Object.values(serializerHooks);
|
|
194
|
-
switch (hooks.length) {
|
|
195
|
-
case 0:
|
|
196
|
-
break;
|
|
197
|
-
case 1:
|
|
198
|
-
metroConfig.serializer.experimentalSerializerHook = hooks[0];
|
|
199
|
-
break;
|
|
200
|
-
default:
|
|
201
|
-
metroConfig.serializer.experimentalSerializerHook = (graph, delta) => {
|
|
202
|
-
for (const hook of hooks) {
|
|
203
|
-
hook(graph, delta);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
}
|
package/src/parsers.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { TransformProfile } from "metro-babel-transformer";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
export function asBoolean(value: string): boolean {
|
|
5
|
-
switch (value) {
|
|
6
|
-
case "false":
|
|
7
|
-
return false;
|
|
8
|
-
case "true":
|
|
9
|
-
return true;
|
|
10
|
-
default:
|
|
11
|
-
throw new Error(
|
|
12
|
-
"Invalid boolean value '" + value + "' — must be true or false"
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function asNumber(value: string): number {
|
|
18
|
-
return Number(value);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function asResolvedPath(value: string): string {
|
|
22
|
-
return path.resolve(value);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function asStringArray(value: string): string[] {
|
|
26
|
-
return value.split(",");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function parseTransformProfile(val: string): TransformProfile {
|
|
30
|
-
const allowedProfiles: TransformProfile[] = [
|
|
31
|
-
"hermes-stable",
|
|
32
|
-
"hermes-canary",
|
|
33
|
-
"default",
|
|
34
|
-
];
|
|
35
|
-
if (val in allowedProfiles) {
|
|
36
|
-
return val as TransformProfile;
|
|
37
|
-
}
|
|
38
|
-
throw new Error(
|
|
39
|
-
"Invalid transform profile '" +
|
|
40
|
-
val +
|
|
41
|
-
"' -- must be one of " +
|
|
42
|
-
allowedProfiles.join(", ")
|
|
43
|
-
);
|
|
44
|
-
}
|
package/src/ram-bundle.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { Config as CLIConfig } from "@react-native-community/cli-types";
|
|
2
|
-
import { info } from "@rnx-kit/console";
|
|
3
|
-
import { loadMetroConfig, ramBundle } from "@rnx-kit/metro-service";
|
|
4
|
-
import { commonBundleCommandOptions } from "./bundle/cliOptions";
|
|
5
|
-
import { getCliPlatformBundleConfigs } from "./bundle/kit-config";
|
|
6
|
-
import { metroBundle } from "./bundle/metro";
|
|
7
|
-
import {
|
|
8
|
-
applyBundleConfigOverrides,
|
|
9
|
-
overridableCommonBundleOptions,
|
|
10
|
-
} from "./bundle/overrides";
|
|
11
|
-
import type {
|
|
12
|
-
CLICommonBundleOptions,
|
|
13
|
-
CliPlatformBundleConfig,
|
|
14
|
-
} from "./bundle/types";
|
|
15
|
-
|
|
16
|
-
type CLIRamBundleOptions = CLICommonBundleOptions & {
|
|
17
|
-
indexedRamBundle?: boolean;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
function disableTreeShaking(configs: CliPlatformBundleConfig[]): void {
|
|
21
|
-
const wasEnabled = configs.reduce((modified, config) => {
|
|
22
|
-
if (config.treeShake) {
|
|
23
|
-
config.treeShake = false;
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
return modified;
|
|
27
|
-
}, false);
|
|
28
|
-
if (wasEnabled) {
|
|
29
|
-
info(
|
|
30
|
-
"`treeShake` was disabled because it is not compatible with the RAM bundle format"
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function rnxRamBundle(
|
|
36
|
-
_argv: string[],
|
|
37
|
-
cliConfig: CLIConfig,
|
|
38
|
-
cliOptions: CLIRamBundleOptions
|
|
39
|
-
): Promise<void> {
|
|
40
|
-
const metroConfig = await loadMetroConfig(cliConfig, cliOptions);
|
|
41
|
-
|
|
42
|
-
const bundleConfigs = getCliPlatformBundleConfigs(
|
|
43
|
-
cliOptions.id,
|
|
44
|
-
cliOptions.platform
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
applyBundleConfigOverrides(cliOptions, bundleConfigs, [
|
|
48
|
-
...overridableCommonBundleOptions,
|
|
49
|
-
"indexedRamBundle",
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
disableTreeShaking(bundleConfigs);
|
|
53
|
-
|
|
54
|
-
for (const bundleConfig of bundleConfigs) {
|
|
55
|
-
await metroBundle(
|
|
56
|
-
metroConfig,
|
|
57
|
-
bundleConfig,
|
|
58
|
-
cliOptions.dev,
|
|
59
|
-
cliOptions.minify,
|
|
60
|
-
ramBundle
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const rnxRamBundleCommand = {
|
|
66
|
-
name: "rnx-ram-bundle",
|
|
67
|
-
description:
|
|
68
|
-
"Bundle your rnx-kit package in the RAM bundle format for offline use. See https://aka.ms/rnx-kit.",
|
|
69
|
-
func: rnxRamBundle,
|
|
70
|
-
options: [
|
|
71
|
-
...commonBundleCommandOptions,
|
|
72
|
-
{
|
|
73
|
-
name: "--indexed-ram-bundle",
|
|
74
|
-
description:
|
|
75
|
-
'Force the "Indexed RAM" bundle file format, even when targeting Android.',
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
};
|
package/src/serve/external.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { resolveDependencyChain } from "@rnx-kit/tools-node/package";
|
|
2
|
-
import type { CliServerApi, CoreDevMiddleware } from "./types";
|
|
3
|
-
|
|
4
|
-
type CliClean = typeof import("@react-native-community/cli-clean");
|
|
5
|
-
|
|
6
|
-
type ExternalModule =
|
|
7
|
-
| "@react-native-community/cli-clean"
|
|
8
|
-
| "@react-native-community/cli-server-api"
|
|
9
|
-
| "@react-native/dev-middleware";
|
|
10
|
-
|
|
11
|
-
function friendlyRequire<T>(...modules: string[]): T {
|
|
12
|
-
try {
|
|
13
|
-
const modulePath = resolveDependencyChain(modules);
|
|
14
|
-
return require(modulePath) as T;
|
|
15
|
-
} catch (_) {
|
|
16
|
-
const module = modules[modules.length - 1];
|
|
17
|
-
throw new Error(
|
|
18
|
-
`Cannot find module '${module}'. This probably means that ` +
|
|
19
|
-
"'@rnx-kit/cli' is not compatible with the version of 'react-native' " +
|
|
20
|
-
"that you are currently using. Please update to the latest version " +
|
|
21
|
-
"and try again. If the issue still persists after the update, please " +
|
|
22
|
-
"file a bug at https://github.com/microsoft/rnx-kit/issues."
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function requireExternal(
|
|
28
|
-
module: "@react-native-community/cli-clean"
|
|
29
|
-
): CliClean;
|
|
30
|
-
|
|
31
|
-
export function requireExternal(
|
|
32
|
-
module: "@react-native-community/cli-server-api"
|
|
33
|
-
): CliServerApi;
|
|
34
|
-
|
|
35
|
-
export function requireExternal(
|
|
36
|
-
module: "@react-native/dev-middleware"
|
|
37
|
-
): CoreDevMiddleware;
|
|
38
|
-
|
|
39
|
-
export function requireExternal(
|
|
40
|
-
module: ExternalModule
|
|
41
|
-
): CliClean | CliServerApi | CoreDevMiddleware {
|
|
42
|
-
switch (module) {
|
|
43
|
-
case "@react-native-community/cli-clean":
|
|
44
|
-
return friendlyRequire<CliClean>(
|
|
45
|
-
"react-native",
|
|
46
|
-
"@react-native-community/cli",
|
|
47
|
-
"@react-native-community/cli-clean"
|
|
48
|
-
);
|
|
49
|
-
case "@react-native-community/cli-server-api":
|
|
50
|
-
return friendlyRequire<CliServerApi>(
|
|
51
|
-
"react-native",
|
|
52
|
-
"@react-native-community/cli",
|
|
53
|
-
"@react-native-community/cli-server-api"
|
|
54
|
-
);
|
|
55
|
-
case "@react-native/dev-middleware":
|
|
56
|
-
return friendlyRequire<CoreDevMiddleware>(
|
|
57
|
-
"react-native",
|
|
58
|
-
"@react-native/community-cli-plugin",
|
|
59
|
-
"@react-native/dev-middleware"
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
}
|
package/src/serve/help.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { dim } from "@rnx-kit/console";
|
|
2
|
-
import type { MetroTerminal } from "@rnx-kit/metro-service";
|
|
3
|
-
|
|
4
|
-
type HelpOptions = {
|
|
5
|
-
hasDebugger: boolean;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
type MenuItem = [string, string];
|
|
9
|
-
|
|
10
|
-
export function makeHelp(
|
|
11
|
-
terminal: MetroTerminal["terminal"],
|
|
12
|
-
{ hasDebugger }: HelpOptions
|
|
13
|
-
): () => void {
|
|
14
|
-
const openDebugger: MenuItem | null = hasDebugger
|
|
15
|
-
? ["J", "Open debugger"]
|
|
16
|
-
: null;
|
|
17
|
-
|
|
18
|
-
const menuItems: ("" | MenuItem)[] = [
|
|
19
|
-
["D", "Open developer menu"],
|
|
20
|
-
...(openDebugger ? [openDebugger] : []),
|
|
21
|
-
["Q", "Show bundler address QR code"],
|
|
22
|
-
["R", "Reload the app"],
|
|
23
|
-
"",
|
|
24
|
-
["H", "Show this help message"],
|
|
25
|
-
["Ctrl-C", "Quit"],
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
const margin = 4;
|
|
29
|
-
const maxColumnWidth = (index: number) => {
|
|
30
|
-
return (max: number, item: (typeof menuItems)[number]) => {
|
|
31
|
-
if (!item) {
|
|
32
|
-
return max;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const width = item[index].length;
|
|
36
|
-
return width > max ? width : max;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const keyWidth = menuItems.reduce(maxColumnWidth(0), 0);
|
|
41
|
-
const labelWidth = menuItems.reduce(maxColumnWidth(1), 0);
|
|
42
|
-
const separator = `┠${"─".repeat(labelWidth + keyWidth + margin + 1)}`;
|
|
43
|
-
|
|
44
|
-
const lines = menuItems.map((item) => {
|
|
45
|
-
if (!item) {
|
|
46
|
-
return separator;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const [key, label] = item;
|
|
50
|
-
const labelPadding = labelWidth - label.length;
|
|
51
|
-
const keyPadding = keyWidth - key.length;
|
|
52
|
-
const padding = " ".repeat(labelPadding + keyPadding + margin);
|
|
53
|
-
return `┃ ${dim(label)}${padding}${key}`;
|
|
54
|
-
});
|
|
55
|
-
lines.push("");
|
|
56
|
-
|
|
57
|
-
const help = lines.join("\n");
|
|
58
|
-
return () => terminal.log(help);
|
|
59
|
-
}
|
package/src/serve/keyboard.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { info } from "@rnx-kit/console";
|
|
2
|
-
import type { MetroTerminal } from "@rnx-kit/metro-service";
|
|
3
|
-
import nodeFetch from "node-fetch";
|
|
4
|
-
import qrcode from "qrcode";
|
|
5
|
-
import readline from "readline";
|
|
6
|
-
import type { DevServerMiddleware } from "./types";
|
|
7
|
-
|
|
8
|
-
type Options = {
|
|
9
|
-
devServerUrl: string;
|
|
10
|
-
help: () => void;
|
|
11
|
-
messageSocketEndpoint: DevServerMiddleware["messageSocketEndpoint"];
|
|
12
|
-
terminal: MetroTerminal["terminal"];
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export function attachKeyHandlers({
|
|
16
|
-
devServerUrl,
|
|
17
|
-
help,
|
|
18
|
-
messageSocketEndpoint,
|
|
19
|
-
terminal,
|
|
20
|
-
}: Options) {
|
|
21
|
-
process.stdin.setRawMode(true);
|
|
22
|
-
process.stdin.on("keypress", (_key, data) => {
|
|
23
|
-
const { ctrl, name } = data;
|
|
24
|
-
if (ctrl === true) {
|
|
25
|
-
switch (name) {
|
|
26
|
-
case "c":
|
|
27
|
-
info("Exiting...");
|
|
28
|
-
process.exit();
|
|
29
|
-
break;
|
|
30
|
-
case "z":
|
|
31
|
-
process.emit("SIGTSTP", "SIGTSTP");
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
} else {
|
|
35
|
-
switch (name) {
|
|
36
|
-
case "d":
|
|
37
|
-
info("Opening developer menu...");
|
|
38
|
-
messageSocketEndpoint.broadcast("devMenu", undefined);
|
|
39
|
-
break;
|
|
40
|
-
|
|
41
|
-
case "h":
|
|
42
|
-
help();
|
|
43
|
-
break;
|
|
44
|
-
|
|
45
|
-
case "j": {
|
|
46
|
-
info("Opening debugger...");
|
|
47
|
-
// TODO: Remove `node-fetch` when we drop support for Node 16
|
|
48
|
-
const ftch = "fetch" in globalThis ? fetch : nodeFetch;
|
|
49
|
-
ftch(devServerUrl + "/open-debugger", { method: "POST" });
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
case "q": {
|
|
54
|
-
const url = `${devServerUrl}/index.bundle`;
|
|
55
|
-
qrcode.toString(url, { type: "terminal" }, (_err, qr) => {
|
|
56
|
-
terminal.log("");
|
|
57
|
-
terminal.log(url + ":");
|
|
58
|
-
terminal.log(qr);
|
|
59
|
-
});
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
case "r":
|
|
64
|
-
info("Reloading app...");
|
|
65
|
-
messageSocketEndpoint.broadcast("reload", undefined);
|
|
66
|
-
break;
|
|
67
|
-
|
|
68
|
-
case "return":
|
|
69
|
-
terminal.log("");
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
readline.emitKeypressEvents(process.stdin);
|
|
76
|
-
}
|
package/src/serve/kit-config.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { ServerConfig } from "@rnx-kit/config";
|
|
2
|
-
import { getBundleConfig, getKitConfig } from "@rnx-kit/config";
|
|
3
|
-
import { pickValues } from "@rnx-kit/tools-language/properties";
|
|
4
|
-
import { getDefaultBundlerPlugins } from "../bundle/defaultPlugins";
|
|
5
|
-
|
|
6
|
-
type ServerConfigOverrides = {
|
|
7
|
-
projectRoot?: string;
|
|
8
|
-
assetPlugins?: string[];
|
|
9
|
-
sourceExts?: string[];
|
|
10
|
-
id?: string;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
type CliServerConfig = ServerConfig & {
|
|
14
|
-
plugins: Required<ServerConfig>["plugins"];
|
|
15
|
-
treeShake: false;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Get the server configuration from the rnx-kit configuration. Apply any overrides.
|
|
20
|
-
*
|
|
21
|
-
* @param overrides Overrides to apply. These take precedence over the values in the rnx-kit configuration.
|
|
22
|
-
* @returns Server configuration
|
|
23
|
-
*/
|
|
24
|
-
export function getKitServerConfig(
|
|
25
|
-
overrides: ServerConfigOverrides
|
|
26
|
-
): CliServerConfig {
|
|
27
|
-
const kitConfig = getKitConfig();
|
|
28
|
-
let serverConfig = kitConfig?.server;
|
|
29
|
-
if (!serverConfig && kitConfig) {
|
|
30
|
-
const maybeBundleConfig = getBundleConfig(kitConfig, overrides?.id);
|
|
31
|
-
if (maybeBundleConfig) {
|
|
32
|
-
serverConfig = pickValues(maybeBundleConfig, [
|
|
33
|
-
"detectCyclicDependencies",
|
|
34
|
-
"detectDuplicateDependencies",
|
|
35
|
-
"typescriptValidation",
|
|
36
|
-
"plugins",
|
|
37
|
-
]);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
...getDefaultBundlerPlugins(),
|
|
43
|
-
...serverConfig,
|
|
44
|
-
treeShake: false, // tree shaking does not work with the bundle server
|
|
45
|
-
...pickValues(overrides, ["projectRoot", "assetPlugins", "sourceExts"]),
|
|
46
|
-
};
|
|
47
|
-
}
|
package/src/serve/types.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type * as logger from "@rnx-kit/console";
|
|
2
|
-
import type { Server as Middleware } from "connect";
|
|
3
|
-
import type { Server as HttpServer } from "http";
|
|
4
|
-
import type { Server as HttpsServer } from "https";
|
|
5
|
-
import type { RunServerOptions } from "metro";
|
|
6
|
-
|
|
7
|
-
// https://github.com/react-native-community/cli/blob/11.x/packages/cli-server-api/src/index.ts#L32
|
|
8
|
-
type MiddlewareOptions = {
|
|
9
|
-
host?: string;
|
|
10
|
-
watchFolders: readonly string[];
|
|
11
|
-
port: number;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
type WebSocketServer = Required<RunServerOptions>["websocketEndpoints"][string];
|
|
15
|
-
|
|
16
|
-
export type DevServerMiddleware = {
|
|
17
|
-
websocketEndpoints: RunServerOptions["websocketEndpoints"];
|
|
18
|
-
debuggerProxyEndpoint: {
|
|
19
|
-
server: WebSocketServer;
|
|
20
|
-
isDebuggerConnected: () => boolean;
|
|
21
|
-
};
|
|
22
|
-
messageSocketEndpoint: {
|
|
23
|
-
server: WebSocketServer;
|
|
24
|
-
broadcast: (method: string, params?: Record<string, unknown>) => void;
|
|
25
|
-
};
|
|
26
|
-
eventsSocketEndpoint: {
|
|
27
|
-
server: WebSocketServer;
|
|
28
|
-
reportEvent: (event: unknown) => void;
|
|
29
|
-
};
|
|
30
|
-
middleware: Middleware;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export type DevServerMiddleware6 = Pick<DevServerMiddleware, "middleware"> & {
|
|
34
|
-
attachToServer: (server: HttpServer | HttpsServer) => {
|
|
35
|
-
debuggerProxy: DevServerMiddleware["debuggerProxyEndpoint"];
|
|
36
|
-
eventsSocket: DevServerMiddleware["eventsSocketEndpoint"];
|
|
37
|
-
messageSocket: DevServerMiddleware["messageSocketEndpoint"];
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/** `@react-native-community/cli-server-api` */
|
|
42
|
-
export type CliServerApi = {
|
|
43
|
-
createDevServerMiddleware: (
|
|
44
|
-
options: MiddlewareOptions
|
|
45
|
-
) => DevServerMiddleware | DevServerMiddleware6;
|
|
46
|
-
indexPageMiddleware: Middleware;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// https://github.com/facebook/react-native/blob/d208dc422c9239d126e0da674451c5898d57319d/packages/community-cli-plugin/src/commands/start/runServer.js#L32
|
|
50
|
-
export type StartCommandArgs = {
|
|
51
|
-
assetPlugins?: string[];
|
|
52
|
-
cert?: string;
|
|
53
|
-
customLogReporterPath?: string;
|
|
54
|
-
host?: string;
|
|
55
|
-
https?: boolean;
|
|
56
|
-
maxWorkers?: number;
|
|
57
|
-
key?: string;
|
|
58
|
-
platforms?: string[];
|
|
59
|
-
port?: number;
|
|
60
|
-
resetCache?: boolean;
|
|
61
|
-
sourceExts?: string[];
|
|
62
|
-
transformer?: string;
|
|
63
|
-
watchFolders?: string[];
|
|
64
|
-
config?: string;
|
|
65
|
-
projectRoot?: string;
|
|
66
|
-
interactive: boolean;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// https://github.com/facebook/react-native/blob/3e7a873f2d1c5170a7f4c88064897e74a149c5d5/packages/dev-middleware/src/createDevMiddleware.js#L40
|
|
70
|
-
type DevMiddlewareAPI = {
|
|
71
|
-
middleware: Middleware;
|
|
72
|
-
websocketEndpoints: RunServerOptions["websocketEndpoints"];
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
type DevMiddlewareOptions = {
|
|
76
|
-
projectRoot: string;
|
|
77
|
-
serverBaseUrl: string;
|
|
78
|
-
logger?: typeof logger;
|
|
79
|
-
unstable_browserLauncher?: unknown;
|
|
80
|
-
unstable_eventReporter?: unknown;
|
|
81
|
-
unstable_experiments?: unknown;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/** `@react-native/dev-middleware` */
|
|
85
|
-
export type CoreDevMiddleware = {
|
|
86
|
-
createDevMiddleware: (options: DevMiddlewareOptions) => DevMiddlewareAPI;
|
|
87
|
-
};
|