@rnx-kit/cli 0.15.3 → 0.16.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/CHANGELOG.md +23 -0
- package/README.md +32 -20
- package/coverage/clover.xml +81 -32
- package/coverage/coverage-final.json +3 -3
- package/coverage/lcov-report/index.html +23 -23
- package/coverage/lcov-report/src/bundle/defaultPlugins.ts.html +31 -13
- package/coverage/lcov-report/src/bundle/index.html +9 -9
- package/coverage/lcov-report/src/bundle/kit-config.ts.html +1 -1
- package/coverage/lcov-report/src/bundle/metro.ts.html +14 -5
- package/coverage/lcov-report/src/bundle/overrides.ts.html +1 -1
- package/coverage/lcov-report/src/copy-assets.ts.html +1 -1
- package/coverage/lcov-report/src/index.html +20 -20
- package/coverage/lcov-report/src/metro-config.ts.html +430 -46
- package/coverage/lcov.info +138 -51
- package/lib/bundle/defaultPlugins.d.ts +4 -2
- package/lib/bundle/defaultPlugins.d.ts.map +1 -1
- package/lib/bundle/defaultPlugins.js +9 -6
- package/lib/bundle/defaultPlugins.js.map +1 -1
- package/lib/bundle/metro.d.ts.map +1 -1
- package/lib/bundle/metro.js +4 -1
- package/lib/bundle/metro.js.map +1 -1
- package/lib/bundle/types.d.ts +1 -1
- package/lib/bundle/types.d.ts.map +1 -1
- package/lib/metro-config.d.ts +5 -3
- package/lib/metro-config.d.ts.map +1 -1
- package/lib/metro-config.js +122 -21
- package/lib/metro-config.js.map +1 -1
- package/lib/serve/kit-config.d.ts +7 -3
- package/lib/serve/kit-config.d.ts.map +1 -1
- package/lib/serve/kit-config.js +1 -1
- package/lib/serve/kit-config.js.map +1 -1
- package/package.json +7 -11
- package/src/bundle/defaultPlugins.ts +14 -8
- package/src/bundle/metro.ts +4 -1
- package/src/bundle/types.ts +1 -3
- package/src/metro-config.ts +154 -26
- package/src/serve/kit-config.ts +8 -5
- package/src/start.ts +1 -1
- package/test/bundle/kit-config.test.ts +25 -15
- package/test/bundle/metro.test.ts +10 -11
- package/test/bundle/overrides.test.ts +5 -4
- package/test/metro-config.test.ts +71 -32
package/src/bundle/types.ts
CHANGED
|
@@ -28,10 +28,8 @@ export type CliPlatformBundleConfig = BundleParameters &
|
|
|
28
28
|
| "entryFile"
|
|
29
29
|
| "bundleOutput"
|
|
30
30
|
| "sourcemapUseAbsolutePath"
|
|
31
|
-
| "detectCyclicDependencies"
|
|
32
|
-
| "detectDuplicateDependencies"
|
|
33
|
-
| "typescriptValidation"
|
|
34
31
|
| "treeShake"
|
|
32
|
+
| "plugins"
|
|
35
33
|
>
|
|
36
34
|
> & {
|
|
37
35
|
unstableTransformProfile?: TransformProfile;
|
package/src/metro-config.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BundleParameters } from "@rnx-kit/config";
|
|
2
|
+
import { warn } from "@rnx-kit/console";
|
|
2
3
|
import { CyclicDependencies } from "@rnx-kit/metro-plugin-cyclic-dependencies-detector";
|
|
3
4
|
import { DuplicateDependencies } from "@rnx-kit/metro-plugin-duplicates-checker";
|
|
4
5
|
import { TypeScriptPlugin } from "@rnx-kit/metro-plugin-typescript";
|
|
@@ -9,44 +10,158 @@ import {
|
|
|
9
10
|
MetroSerializer as MetroSerializerEsbuild,
|
|
10
11
|
} from "@rnx-kit/metro-serializer-esbuild";
|
|
11
12
|
import type { InputConfigT, SerializerConfigT } from "metro-config";
|
|
13
|
+
import { getDefaultBundlerPlugins } from "./bundle/defaultPlugins";
|
|
14
|
+
|
|
15
|
+
type MetroExtraParams = Pick<
|
|
16
|
+
BundleParameters,
|
|
17
|
+
| "detectCyclicDependencies"
|
|
18
|
+
| "detectDuplicateDependencies"
|
|
19
|
+
| "typescriptValidation"
|
|
20
|
+
| "plugins"
|
|
21
|
+
| "treeShake"
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
function resolvePlugin(name: string): string {
|
|
25
|
+
try {
|
|
26
|
+
return require.resolve(name);
|
|
27
|
+
} catch (_) {
|
|
28
|
+
return require.resolve(name, { paths: [process.cwd()] });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function importPlugin(name: string) {
|
|
33
|
+
const plugin = require(resolvePlugin(name));
|
|
34
|
+
return plugin.default || plugin;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function readLegacyOptions({
|
|
38
|
+
detectCyclicDependencies,
|
|
39
|
+
detectDuplicateDependencies,
|
|
40
|
+
typescriptValidation,
|
|
41
|
+
}: MetroExtraParams): string | undefined {
|
|
42
|
+
const oldOptions = [];
|
|
43
|
+
const deprecatedOptions: Record<string, Record<string, unknown> | true> = {};
|
|
44
|
+
|
|
45
|
+
if (detectCyclicDependencies) {
|
|
46
|
+
oldOptions.push("detectCyclicDependencies");
|
|
47
|
+
deprecatedOptions["@rnx-kit/metro-plugin-cyclic-dependencies-detector"] =
|
|
48
|
+
detectCyclicDependencies;
|
|
49
|
+
}
|
|
50
|
+
if (detectDuplicateDependencies) {
|
|
51
|
+
oldOptions.push("detectDuplicateDependencies");
|
|
52
|
+
deprecatedOptions["@rnx-kit/metro-plugin-duplicates-checker"] =
|
|
53
|
+
detectDuplicateDependencies;
|
|
54
|
+
}
|
|
55
|
+
if (typescriptValidation) {
|
|
56
|
+
oldOptions.push("typescriptValidation");
|
|
57
|
+
deprecatedOptions["@rnx-kit/metro-plugin-typescript"] =
|
|
58
|
+
typescriptValidation;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (oldOptions.length === 0) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
`'${oldOptions.join("', '")}' have been replaced by a new 'plugins' ` +
|
|
67
|
+
"option. Below is an equivalent config:\n" +
|
|
68
|
+
"\n" +
|
|
69
|
+
' "plugins": [\n' +
|
|
70
|
+
Object.entries(deprecatedOptions)
|
|
71
|
+
.map(([name, options]) => {
|
|
72
|
+
if (typeof options === "object") {
|
|
73
|
+
const json = JSON.stringify(options, null, 2)
|
|
74
|
+
.split("\n")
|
|
75
|
+
.join("\n ");
|
|
76
|
+
return ` ["${name}", ${json}]`;
|
|
77
|
+
} else {
|
|
78
|
+
return ` "${name}"`;
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.join(",\n") +
|
|
82
|
+
"\n" +
|
|
83
|
+
" ]\n" +
|
|
84
|
+
"\n" +
|
|
85
|
+
"For more details, see " +
|
|
86
|
+
"https://github.com/microsoft/rnx-kit/tree/main/packages/cli#readme"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
12
89
|
|
|
13
90
|
/**
|
|
14
91
|
* Customize the Metro configuration.
|
|
15
92
|
*
|
|
16
93
|
* @param metroConfigReadonly Metro configuration
|
|
17
|
-
* @param
|
|
94
|
+
* @param extraParams Parameters used to further customize Metro configuration
|
|
18
95
|
* @param print Optional function to use when printing status messages to the Metro console
|
|
19
96
|
*/
|
|
20
97
|
export function customizeMetroConfig(
|
|
21
98
|
metroConfigReadonly: InputConfigT,
|
|
22
|
-
|
|
23
|
-
detectCyclicDependencies,
|
|
24
|
-
detectDuplicateDependencies,
|
|
25
|
-
treeShake,
|
|
26
|
-
typescriptValidation,
|
|
27
|
-
}: BundlerPlugins,
|
|
99
|
+
extraParams: MetroExtraParams,
|
|
28
100
|
print?: (message: string) => void
|
|
29
101
|
): void {
|
|
30
|
-
//
|
|
31
|
-
//
|
|
102
|
+
// We will be making changes to the Metro configuration. Coerce from a type
|
|
103
|
+
// with readonly props to a type where the props are writeable.
|
|
32
104
|
const metroConfig = metroConfigReadonly as InputConfigT;
|
|
33
105
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
106
|
+
const metroPlugins: MetroPlugin[] = [];
|
|
107
|
+
const serializerHooks: Record<
|
|
108
|
+
string,
|
|
109
|
+
SerializerConfigT["experimentalSerializerHook"]
|
|
110
|
+
> = {};
|
|
111
|
+
|
|
112
|
+
const legacyWarning = readLegacyOptions(extraParams);
|
|
113
|
+
if (legacyWarning) {
|
|
114
|
+
warn(legacyWarning);
|
|
115
|
+
|
|
116
|
+
const {
|
|
117
|
+
detectCyclicDependencies,
|
|
118
|
+
detectDuplicateDependencies,
|
|
119
|
+
typescriptValidation,
|
|
120
|
+
} = extraParams;
|
|
121
|
+
|
|
122
|
+
if (typeof detectDuplicateDependencies === "object") {
|
|
123
|
+
metroPlugins.push(DuplicateDependencies(detectDuplicateDependencies));
|
|
124
|
+
} else if (detectDuplicateDependencies !== false) {
|
|
125
|
+
metroPlugins.push(DuplicateDependencies());
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof detectCyclicDependencies === "object") {
|
|
129
|
+
metroPlugins.push(CyclicDependencies(detectCyclicDependencies));
|
|
130
|
+
} else if (detectCyclicDependencies !== false) {
|
|
131
|
+
metroPlugins.push(CyclicDependencies());
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (typescriptValidation !== false) {
|
|
135
|
+
const plugin = TypeScriptPlugin(typescriptValidation, print);
|
|
136
|
+
serializerHooks["@rnx-kit/metro-plugin-typescript"] = plugin;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
const plugins = extraParams.plugins || getDefaultBundlerPlugins().plugins;
|
|
140
|
+
for (const entry of plugins) {
|
|
141
|
+
const [module, options] = Array.isArray(entry)
|
|
142
|
+
? entry
|
|
143
|
+
: [entry, undefined];
|
|
144
|
+
const plugin = importPlugin(module);
|
|
145
|
+
switch (plugin.type) {
|
|
146
|
+
case "serializer":
|
|
147
|
+
metroPlugins.push(plugin(options));
|
|
148
|
+
break;
|
|
149
|
+
|
|
150
|
+
case "serializerHook":
|
|
151
|
+
serializerHooks[module] = plugin(options, print);
|
|
152
|
+
break;
|
|
153
|
+
|
|
154
|
+
default:
|
|
155
|
+
throw new Error(`${module}: unknown plugin type: ${plugin.type}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
44
158
|
}
|
|
45
159
|
|
|
46
|
-
if (treeShake) {
|
|
47
|
-
metroConfig.serializer.customSerializer =
|
|
160
|
+
if (extraParams.treeShake) {
|
|
161
|
+
metroConfig.serializer.customSerializer =
|
|
162
|
+
MetroSerializerEsbuild(metroPlugins);
|
|
48
163
|
Object.assign(metroConfig.transformer, esbuildTransformerConfig);
|
|
49
|
-
} else if (
|
|
164
|
+
} else if (metroPlugins.length > 0) {
|
|
50
165
|
// MetroSerializer acts as a CustomSerializer, and it works with both
|
|
51
166
|
// older and newer versions of Metro. Older versions expect a return
|
|
52
167
|
// value, while newer versions expect a promise.
|
|
@@ -58,12 +173,25 @@ export function customizeMetroConfig(
|
|
|
58
173
|
// Since it can handle either scenario, just coerce it to whatever
|
|
59
174
|
// the current version of Metro expects.
|
|
60
175
|
metroConfig.serializer.customSerializer = MetroSerializer(
|
|
61
|
-
|
|
176
|
+
metroPlugins
|
|
62
177
|
) as SerializerConfigT["customSerializer"];
|
|
63
178
|
} else {
|
|
64
179
|
delete metroConfig.serializer.customSerializer;
|
|
65
180
|
}
|
|
66
181
|
|
|
67
|
-
const
|
|
68
|
-
|
|
182
|
+
const hooks = Object.values(serializerHooks);
|
|
183
|
+
switch (hooks.length) {
|
|
184
|
+
case 0:
|
|
185
|
+
break;
|
|
186
|
+
case 1:
|
|
187
|
+
metroConfig.serializer.experimentalSerializerHook = hooks[0];
|
|
188
|
+
break;
|
|
189
|
+
default:
|
|
190
|
+
metroConfig.serializer.experimentalSerializerHook = (graph, delta) => {
|
|
191
|
+
for (const hook of hooks) {
|
|
192
|
+
hook(graph, delta);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
69
197
|
}
|
package/src/serve/kit-config.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import type { ServerConfig
|
|
2
|
-
import {
|
|
1
|
+
import type { ServerConfig } from "@rnx-kit/config";
|
|
2
|
+
import { getBundleConfig, getKitConfig } from "@rnx-kit/config";
|
|
3
3
|
import { pickValues } from "@rnx-kit/tools-language/properties";
|
|
4
4
|
import { getDefaultBundlerPlugins } from "../bundle/defaultPlugins";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type ServerConfigOverrides = {
|
|
7
7
|
projectRoot?: string;
|
|
8
8
|
assetPlugins?: string[];
|
|
9
9
|
sourceExts?: string[];
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
type CliServerConfig = ServerConfig & {
|
|
13
|
+
plugins: Required<ServerConfig>["plugins"];
|
|
14
|
+
treeShake: false;
|
|
15
|
+
};
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Get the server configuration from the rnx-kit configuration. Apply any overrides.
|
|
@@ -29,7 +32,7 @@ export function getKitServerConfig(
|
|
|
29
32
|
"detectCyclicDependencies",
|
|
30
33
|
"detectDuplicateDependencies",
|
|
31
34
|
"typescriptValidation",
|
|
32
|
-
|
|
35
|
+
"plugins",
|
|
33
36
|
]);
|
|
34
37
|
}
|
|
35
38
|
}
|
package/src/start.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { customizeMetroConfig } from "./metro-config";
|
|
|
19
19
|
import { getKitServerConfig } from "./serve/kit-config";
|
|
20
20
|
|
|
21
21
|
type DevServerMiddleware = ReturnType<
|
|
22
|
-
typeof CliServerApi["createDevServerMiddleware"]
|
|
22
|
+
(typeof CliServerApi)["createDevServerMiddleware"]
|
|
23
23
|
>;
|
|
24
24
|
|
|
25
25
|
type DevServerMiddleware6 = Pick<DevServerMiddleware, "middleware"> & {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "jest-extended";
|
|
2
1
|
import {
|
|
3
2
|
getTargetPlatforms,
|
|
4
3
|
getCliPlatformBundleConfigs,
|
|
@@ -9,8 +8,9 @@ const rnxKitConfig = require("@rnx-kit/config");
|
|
|
9
8
|
describe("CLI > Bundle > Kit Config > getTargetPlatforms", () => {
|
|
10
9
|
test("returns the override platform", () => {
|
|
11
10
|
const platforms = getTargetPlatforms("ios", ["android", "ios", "windows"]);
|
|
12
|
-
expect(platforms).
|
|
13
|
-
expect(platforms).
|
|
11
|
+
expect(Array.isArray(platforms)).toBe(true);
|
|
12
|
+
expect(platforms.length).toBe(1);
|
|
13
|
+
expect(platforms).toEqual(["ios"]);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
test("returns the target platforms", () => {
|
|
@@ -19,8 +19,9 @@ describe("CLI > Bundle > Kit Config > getTargetPlatforms", () => {
|
|
|
19
19
|
"ios",
|
|
20
20
|
"windows",
|
|
21
21
|
]);
|
|
22
|
-
expect(platforms).
|
|
23
|
-
expect(platforms).
|
|
22
|
+
expect(Array.isArray(platforms)).toBe(true);
|
|
23
|
+
expect(platforms.length).toBe(3);
|
|
24
|
+
expect(platforms).toEqual(["android", "ios", "windows"]);
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
test("throws when no override or target platform is given", () => {
|
|
@@ -32,10 +33,12 @@ describe("CLI > Bundle > Kit Config > getCliPlatformBundleConfigs", () => {
|
|
|
32
33
|
const defaultConfig = {
|
|
33
34
|
entryFile: "index.js",
|
|
34
35
|
sourcemapUseAbsolutePath: false,
|
|
35
|
-
detectCyclicDependencies: true,
|
|
36
|
-
detectDuplicateDependencies: true,
|
|
37
|
-
typescriptValidation: true,
|
|
38
36
|
treeShake: false,
|
|
37
|
+
plugins: [
|
|
38
|
+
"@rnx-kit/metro-plugin-cyclic-dependencies-detector",
|
|
39
|
+
"@rnx-kit/metro-plugin-duplicates-checker",
|
|
40
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
41
|
+
],
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
const defaultConfigIOS = {
|
|
@@ -68,25 +71,29 @@ describe("CLI > Bundle > Kit Config > getCliPlatformBundleConfigs", () => {
|
|
|
68
71
|
|
|
69
72
|
test("returns defaults for iOS when package has no config", () => {
|
|
70
73
|
const configs = getCliPlatformBundleConfigs(undefined, "ios");
|
|
71
|
-
expect(configs).
|
|
74
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
75
|
+
expect(configs.length).toBe(1);
|
|
72
76
|
expect(configs[0]).toEqual(defaultConfigIOS);
|
|
73
77
|
});
|
|
74
78
|
|
|
75
79
|
test("returns defaults for MacOS when package has no config", () => {
|
|
76
80
|
const configs = getCliPlatformBundleConfigs(undefined, "macos");
|
|
77
|
-
expect(configs).
|
|
81
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
82
|
+
expect(configs.length).toBe(1);
|
|
78
83
|
expect(configs[0]).toEqual(defaultConfigMacOS);
|
|
79
84
|
});
|
|
80
85
|
|
|
81
86
|
test("returns defaults for Android when package has no config", () => {
|
|
82
87
|
const configs = getCliPlatformBundleConfigs(undefined, "android");
|
|
83
|
-
expect(configs).
|
|
88
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
89
|
+
expect(configs.length).toBe(1);
|
|
84
90
|
expect(configs[0]).toEqual(defaultConfigAndroid);
|
|
85
91
|
});
|
|
86
92
|
|
|
87
93
|
test("returns defaults for Windows when package has no config", () => {
|
|
88
94
|
const configs = getCliPlatformBundleConfigs(undefined, "windows");
|
|
89
|
-
expect(configs).
|
|
95
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
96
|
+
expect(configs.length).toBe(1);
|
|
90
97
|
expect(configs[0]).toEqual(defaultConfigWindows);
|
|
91
98
|
});
|
|
92
99
|
|
|
@@ -102,7 +109,8 @@ describe("CLI > Bundle > Kit Config > getCliPlatformBundleConfigs", () => {
|
|
|
102
109
|
test("returns config with defaults for all target platforms", () => {
|
|
103
110
|
rnxKitConfig.__setMockConfig(testConfig);
|
|
104
111
|
const configs = getCliPlatformBundleConfigs();
|
|
105
|
-
expect(configs).
|
|
112
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
113
|
+
expect(configs.length).toBe(4);
|
|
106
114
|
expect(configs[0]).toEqual({ ...defaultConfigIOS, ...testConfig.bundle });
|
|
107
115
|
expect(configs[1]).toEqual({ ...defaultConfigMacOS, ...testConfig.bundle });
|
|
108
116
|
expect(configs[2]).toEqual({
|
|
@@ -131,7 +139,8 @@ describe("CLI > Bundle > Kit Config > getCliPlatformBundleConfigs", () => {
|
|
|
131
139
|
test("returns the first config when no id is given", () => {
|
|
132
140
|
rnxKitConfig.__setMockConfig(testMultiConfig);
|
|
133
141
|
const configs = getCliPlatformBundleConfigs(undefined, "ios");
|
|
134
|
-
expect(configs).
|
|
142
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
143
|
+
expect(configs.length).toBe(1);
|
|
135
144
|
expect(configs[0]).toEqual({
|
|
136
145
|
...defaultConfigIOS,
|
|
137
146
|
...testMultiConfig.bundle[0],
|
|
@@ -141,7 +150,8 @@ describe("CLI > Bundle > Kit Config > getCliPlatformBundleConfigs", () => {
|
|
|
141
150
|
test("returns the selected config when an id is given", () => {
|
|
142
151
|
rnxKitConfig.__setMockConfig(testMultiConfig);
|
|
143
152
|
const configs = getCliPlatformBundleConfigs("second", "android");
|
|
144
|
-
expect(configs).
|
|
153
|
+
expect(Array.isArray(configs)).toBe(true);
|
|
154
|
+
expect(configs.length).toBe(1);
|
|
145
155
|
expect(configs[0]).toEqual({
|
|
146
156
|
...defaultConfigAndroid,
|
|
147
157
|
...testMultiConfig.bundle[1],
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "jest-extended";
|
|
2
1
|
import { metroBundle } from "../../src/bundle/metro";
|
|
3
2
|
import type { CliPlatformBundleConfig } from "../../src/bundle/types";
|
|
4
3
|
|
|
@@ -19,10 +18,8 @@ describe("CLI > Bundle > Metro > metroBundle", () => {
|
|
|
19
18
|
const bundleConfigNoPlugins: CliPlatformBundleConfig = {
|
|
20
19
|
entryFile: "out/entry.js",
|
|
21
20
|
bundleOutput: "src/main.jsbundle",
|
|
22
|
-
detectCyclicDependencies: false,
|
|
23
|
-
detectDuplicateDependencies: false,
|
|
24
|
-
typescriptValidation: false,
|
|
25
21
|
treeShake: false,
|
|
22
|
+
plugins: [],
|
|
26
23
|
platform: "ios",
|
|
27
24
|
sourcemapOutput: "map/main.map",
|
|
28
25
|
sourcemapSourcesRoot: "root-path-for-source-maps",
|
|
@@ -32,10 +29,12 @@ describe("CLI > Bundle > Metro > metroBundle", () => {
|
|
|
32
29
|
|
|
33
30
|
const bundleConfig: CliPlatformBundleConfig = {
|
|
34
31
|
...bundleConfigNoPlugins,
|
|
35
|
-
detectCyclicDependencies: true,
|
|
36
|
-
detectDuplicateDependencies: true,
|
|
37
|
-
typescriptValidation: true,
|
|
38
32
|
treeShake: true,
|
|
33
|
+
plugins: [
|
|
34
|
+
"@rnx-kit/metro-plugin-cyclic-dependencies-detector",
|
|
35
|
+
"@rnx-kit/metro-plugin-duplicates-checker",
|
|
36
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
37
|
+
],
|
|
39
38
|
};
|
|
40
39
|
|
|
41
40
|
const dev = true;
|
|
@@ -43,16 +42,16 @@ describe("CLI > Bundle > Metro > metroBundle", () => {
|
|
|
43
42
|
|
|
44
43
|
it("does not use a custom serializer when all plugins are disabled", async () => {
|
|
45
44
|
const metroConfig = await getDefaultConfig();
|
|
46
|
-
expect(metroConfig.serializer.customSerializer).
|
|
45
|
+
expect(metroConfig.serializer.customSerializer).toBeFalsy();
|
|
47
46
|
await metroBundle(metroConfig, bundleConfigNoPlugins, dev, minify);
|
|
48
|
-
expect(metroConfig.serializer.customSerializer).
|
|
47
|
+
expect(metroConfig.serializer.customSerializer).toBeFalsy();
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
it("uses a custom serializer when at least one plugin is enabled", async () => {
|
|
52
51
|
const metroConfig = await getDefaultConfig();
|
|
53
|
-
expect(metroConfig.serializer.customSerializer).
|
|
52
|
+
expect(metroConfig.serializer.customSerializer).toBeFalsy();
|
|
54
53
|
await metroBundle(metroConfig, bundleConfig, dev, minify);
|
|
55
|
-
expect(metroConfig.serializer.customSerializer).
|
|
54
|
+
expect(metroConfig.serializer.customSerializer).toBeTruthy();
|
|
56
55
|
});
|
|
57
56
|
|
|
58
57
|
it("creates directories for the bundle, the source map, and assets", async () => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "jest-extended";
|
|
2
1
|
import {
|
|
3
2
|
applyBundleConfigOverrides,
|
|
4
3
|
overridableCommonBundleOptions,
|
|
@@ -10,10 +9,12 @@ describe("CLI > Bundle > Overrides > applyBundleConfigOverrides", () => {
|
|
|
10
9
|
entryFile: "src/index.js",
|
|
11
10
|
bundleOutput: "main.jsbundle",
|
|
12
11
|
sourcemapUseAbsolutePath: false,
|
|
13
|
-
detectCyclicDependencies: true,
|
|
14
|
-
detectDuplicateDependencies: true,
|
|
15
|
-
typescriptValidation: true,
|
|
16
12
|
treeShake: true,
|
|
13
|
+
plugins: [
|
|
14
|
+
"@rnx-kit/metro-plugin-cyclic-dependencies-detector",
|
|
15
|
+
"@rnx-kit/metro-plugin-duplicates-checker",
|
|
16
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
17
|
+
],
|
|
17
18
|
indexedRamBundle: false,
|
|
18
19
|
platform: "ios",
|
|
19
20
|
};
|
|
@@ -1,18 +1,36 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import CyclicDependencies from "@rnx-kit/metro-plugin-cyclic-dependencies-detector";
|
|
2
|
+
import DuplicateDependencies from "@rnx-kit/metro-plugin-duplicates-checker";
|
|
3
3
|
import type { InputConfigT } from "metro-config";
|
|
4
4
|
import { customizeMetroConfig } from "../src/metro-config";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
function mockPlugin(moduleName: string) {
|
|
7
|
+
const state: { timesCalled: number; options?: Record<string, unknown> } = {
|
|
8
|
+
timesCalled: 0,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function PluginMock(options: Record<string, unknown>) {
|
|
12
|
+
state.timesCalled = state.timesCalled + 1;
|
|
13
|
+
state.options = options;
|
|
14
|
+
return () => ({});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const Plugin = jest.requireActual(moduleName);
|
|
18
|
+
PluginMock.type = Plugin.default.type;
|
|
19
|
+
PluginMock.__context = state;
|
|
20
|
+
PluginMock.mockClear = () => {
|
|
21
|
+
state.timesCalled = 0;
|
|
22
|
+
state.options = undefined;
|
|
9
23
|
};
|
|
24
|
+
|
|
25
|
+
return PluginMock;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
jest.mock("@rnx-kit/metro-plugin-cyclic-dependencies-detector", () => {
|
|
29
|
+
return mockPlugin("@rnx-kit/metro-plugin-cyclic-dependencies-detector");
|
|
10
30
|
});
|
|
11
31
|
|
|
12
32
|
jest.mock("@rnx-kit/metro-plugin-duplicates-checker", () => {
|
|
13
|
-
return
|
|
14
|
-
DuplicateDependencies: jest.fn(),
|
|
15
|
-
};
|
|
33
|
+
return mockPlugin("@rnx-kit/metro-plugin-duplicates-checker");
|
|
16
34
|
});
|
|
17
35
|
|
|
18
36
|
// Always use a new mock since `customizeMetroConfig()` modifies the object.
|
|
@@ -26,10 +44,14 @@ function makeMockConfig(): InputConfigT {
|
|
|
26
44
|
} as unknown as InputConfigT;
|
|
27
45
|
}
|
|
28
46
|
|
|
47
|
+
function toMock(module: unknown): ReturnType<typeof mockPlugin> {
|
|
48
|
+
return module as ReturnType<typeof mockPlugin>;
|
|
49
|
+
}
|
|
50
|
+
|
|
29
51
|
describe("cli/metro-config/customizeMetroConfig", () => {
|
|
30
52
|
afterEach(() => {
|
|
31
|
-
(CyclicDependencies
|
|
32
|
-
(DuplicateDependencies
|
|
53
|
+
toMock(CyclicDependencies).mockClear();
|
|
54
|
+
toMock(DuplicateDependencies).mockClear();
|
|
33
55
|
});
|
|
34
56
|
|
|
35
57
|
test("returns a config with plugins by default", () => {
|
|
@@ -47,15 +69,14 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
47
69
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
48
70
|
"function"
|
|
49
71
|
);
|
|
50
|
-
expect(CyclicDependencies).
|
|
51
|
-
expect(DuplicateDependencies).
|
|
72
|
+
expect(toMock(CyclicDependencies).__context).toEqual({ timesCalled: 1 });
|
|
73
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({ timesCalled: 1 });
|
|
52
74
|
});
|
|
53
75
|
|
|
54
76
|
test("returns a config without a custom serializer when there are no plugins", () => {
|
|
55
77
|
const inputConfig = makeMockConfig();
|
|
56
78
|
customizeMetroConfig(inputConfig, {
|
|
57
|
-
|
|
58
|
-
detectDuplicateDependencies: false,
|
|
79
|
+
plugins: ["@rnx-kit/metro-plugin-typescript"],
|
|
59
80
|
});
|
|
60
81
|
|
|
61
82
|
expect(inputConfig).toEqual({
|
|
@@ -68,14 +89,17 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
68
89
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
69
90
|
"function"
|
|
70
91
|
);
|
|
71
|
-
expect(CyclicDependencies).
|
|
72
|
-
expect(DuplicateDependencies).
|
|
92
|
+
expect(toMock(CyclicDependencies).__context).toEqual({ timesCalled: 0 });
|
|
93
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({ timesCalled: 0 });
|
|
73
94
|
});
|
|
74
95
|
|
|
75
96
|
test("returns a config with only duplicates plugin", () => {
|
|
76
97
|
const inputConfig = makeMockConfig();
|
|
77
98
|
customizeMetroConfig(inputConfig, {
|
|
78
|
-
|
|
99
|
+
plugins: [
|
|
100
|
+
"@rnx-kit/metro-plugin-duplicates-checker",
|
|
101
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
102
|
+
],
|
|
79
103
|
});
|
|
80
104
|
|
|
81
105
|
expect(inputConfig).toEqual({
|
|
@@ -89,14 +113,17 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
89
113
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
90
114
|
"function"
|
|
91
115
|
);
|
|
92
|
-
expect(CyclicDependencies).
|
|
93
|
-
expect(DuplicateDependencies).
|
|
116
|
+
expect(toMock(CyclicDependencies).__context).toEqual({ timesCalled: 0 });
|
|
117
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({ timesCalled: 1 });
|
|
94
118
|
});
|
|
95
119
|
|
|
96
120
|
test("returns a config with only cyclic dependencies plugin", () => {
|
|
97
121
|
const inputConfig = makeMockConfig();
|
|
98
122
|
customizeMetroConfig(inputConfig, {
|
|
99
|
-
|
|
123
|
+
plugins: [
|
|
124
|
+
"@rnx-kit/metro-plugin-cyclic-dependencies-detector",
|
|
125
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
126
|
+
],
|
|
100
127
|
});
|
|
101
128
|
|
|
102
129
|
expect(inputConfig).toEqual({
|
|
@@ -110,8 +137,8 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
110
137
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
111
138
|
"function"
|
|
112
139
|
);
|
|
113
|
-
expect(CyclicDependencies).
|
|
114
|
-
expect(DuplicateDependencies).
|
|
140
|
+
expect(toMock(CyclicDependencies).__context).toEqual({ timesCalled: 1 });
|
|
141
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({ timesCalled: 0 });
|
|
115
142
|
});
|
|
116
143
|
|
|
117
144
|
test("forwards plugin options", () => {
|
|
@@ -119,8 +146,17 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
119
146
|
const cyclicDependenciesOptions = { cyclicDependencies: true } as any;
|
|
120
147
|
const duplicateDependencesOptions = { duplicateDependencies: true } as any;
|
|
121
148
|
customizeMetroConfig(inputConfig, {
|
|
122
|
-
|
|
123
|
-
|
|
149
|
+
plugins: [
|
|
150
|
+
[
|
|
151
|
+
"@rnx-kit/metro-plugin-cyclic-dependencies-detector",
|
|
152
|
+
cyclicDependenciesOptions,
|
|
153
|
+
],
|
|
154
|
+
[
|
|
155
|
+
"@rnx-kit/metro-plugin-duplicates-checker",
|
|
156
|
+
duplicateDependencesOptions,
|
|
157
|
+
],
|
|
158
|
+
"@rnx-kit/metro-plugin-typescript",
|
|
159
|
+
],
|
|
124
160
|
});
|
|
125
161
|
|
|
126
162
|
expect(inputConfig).toEqual({
|
|
@@ -134,18 +170,21 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
134
170
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
135
171
|
"function"
|
|
136
172
|
);
|
|
137
|
-
expect(CyclicDependencies).
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
);
|
|
173
|
+
expect(toMock(CyclicDependencies).__context).toEqual({
|
|
174
|
+
timesCalled: 1,
|
|
175
|
+
options: cyclicDependenciesOptions,
|
|
176
|
+
});
|
|
177
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({
|
|
178
|
+
timesCalled: 1,
|
|
179
|
+
options: duplicateDependencesOptions,
|
|
180
|
+
});
|
|
141
181
|
});
|
|
142
182
|
|
|
143
183
|
test("returns a config with a custom serializer when tree shaking is enabled", () => {
|
|
144
184
|
const inputConfig = makeMockConfig();
|
|
145
185
|
customizeMetroConfig(inputConfig, {
|
|
146
|
-
detectCyclicDependencies: false,
|
|
147
|
-
detectDuplicateDependencies: false,
|
|
148
186
|
treeShake: true,
|
|
187
|
+
plugins: ["@rnx-kit/metro-plugin-typescript"],
|
|
149
188
|
});
|
|
150
189
|
|
|
151
190
|
expect(inputConfig).toEqual({
|
|
@@ -161,7 +200,7 @@ describe("cli/metro-config/customizeMetroConfig", () => {
|
|
|
161
200
|
expect(typeof inputConfig.serializer.experimentalSerializerHook).toBe(
|
|
162
201
|
"function"
|
|
163
202
|
);
|
|
164
|
-
expect(CyclicDependencies).
|
|
165
|
-
expect(DuplicateDependencies).
|
|
203
|
+
expect(toMock(CyclicDependencies).__context).toEqual({ timesCalled: 0 });
|
|
204
|
+
expect(toMock(DuplicateDependencies).__context).toEqual({ timesCalled: 0 });
|
|
166
205
|
});
|
|
167
206
|
});
|