@rnx-kit/cli 0.12.1 → 0.12.4

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +21 -21
  3. package/coverage/clover.xml +158 -131
  4. package/coverage/coverage-final.json +2 -2
  5. package/coverage/lcov-report/index.html +20 -20
  6. package/coverage/lcov-report/src/bundle/index.html +1 -1
  7. package/coverage/lcov-report/src/bundle/kit-config.ts.html +13 -13
  8. package/coverage/lcov-report/src/bundle/metro.ts.html +2 -2
  9. package/coverage/lcov-report/src/bundle/overrides.ts.html +4 -4
  10. package/coverage/lcov-report/src/copy-assets.ts.html +480 -111
  11. package/coverage/lcov-report/src/index.html +21 -21
  12. package/coverage/lcov-report/src/metro-config.ts.html +4 -4
  13. package/coverage/lcov-report/src/typescript/index.html +1 -1
  14. package/coverage/lcov-report/src/typescript/project-cache.ts.html +1 -1
  15. package/coverage/lcov.info +289 -242
  16. package/lib/bundle/metro.js +1 -1
  17. package/lib/bundle/metro.js.map +1 -1
  18. package/lib/bundle/overrides.d.ts +1 -1
  19. package/lib/bundle/overrides.d.ts.map +1 -1
  20. package/lib/bundle/overrides.js +2 -2
  21. package/lib/bundle/overrides.js.map +1 -1
  22. package/lib/bundle.d.ts +1 -0
  23. package/lib/bundle.d.ts.map +1 -1
  24. package/lib/bundle.js +8 -0
  25. package/lib/bundle.js.map +1 -1
  26. package/lib/clean.d.ts.map +1 -1
  27. package/lib/clean.js +40 -18
  28. package/lib/clean.js.map +1 -1
  29. package/lib/copy-assets.d.ts +10 -1
  30. package/lib/copy-assets.d.ts.map +1 -1
  31. package/lib/copy-assets.js +111 -32
  32. package/lib/copy-assets.js.map +1 -1
  33. package/lib/metro-config.d.ts +2 -2
  34. package/lib/metro-config.d.ts.map +1 -1
  35. package/lib/metro-config.js +3 -3
  36. package/lib/metro-config.js.map +1 -1
  37. package/lib/start.d.ts.map +1 -1
  38. package/lib/start.js +28 -9
  39. package/lib/start.js.map +1 -1
  40. package/lib/test.js +3 -6
  41. package/lib/test.js.map +1 -1
  42. package/package.json +1 -1
  43. package/react-native.config.js +6 -1
  44. package/src/bundle/metro.ts +1 -1
  45. package/src/bundle/overrides.ts +3 -3
  46. package/src/bundle.ts +13 -1
  47. package/src/clean.ts +6 -7
  48. package/src/copy-assets.ts +169 -46
  49. package/src/metro-config.ts +3 -3
  50. package/src/start.ts +49 -9
  51. package/src/test.ts +3 -3
  52. package/test/__mocks__/child_process.js +5 -0
  53. package/test/__mocks__/fs-extra.js +2 -0
  54. package/test/__mocks__/fs.js +19 -0
  55. package/test/bundle/kit-config.test.ts +23 -1
  56. package/test/bundle/metro.test.ts +1 -1
  57. package/test/bundle/overrides.test.ts +3 -13
  58. package/test/copy-assets/assembleAarBundle.test.ts +306 -0
  59. package/test/{copy-assets.test.ts → copy-assets/copyAssets.test.ts} +3 -13
  60. package/test/copy-assets/helpers.ts +13 -0
@@ -14,7 +14,9 @@ fs.__toJSON = () => vol.toJSON();
14
14
 
15
15
  fs.copy = (...args) => vol.promises.copyFile(...args);
16
16
  fs.ensureDir = (dir) => vol.promises.mkdir(dir, { recursive: true });
17
+ fs.existsSync = (...args) => vol.existsSync(...args);
17
18
  fs.pathExists = (...args) => Promise.resolve(vol.existsSync(...args));
18
19
  fs.readFile = (...args) => vol.promises.readFile(...args);
20
+ fs.writeFile = (...args) => vol.promises.writeFile(...args);
19
21
 
20
22
  module.exports = fs;
@@ -0,0 +1,19 @@
1
+ const fs = jest.createMockFromModule("fs");
2
+
3
+ const { vol } = require("memfs");
4
+
5
+ /** @type {(newMockFiles: { [filename: string]: string }) => void} */
6
+ fs.__setMockFiles = (files) => {
7
+ vol.reset();
8
+ vol.fromJSON(files);
9
+ };
10
+
11
+ fs.__toJSON = () => vol.toJSON();
12
+
13
+ fs.lstat = (...args) => Promise.resolve(vol.lstat(...args));
14
+ fs.lstatSync = (...args) => vol.lstatSync(...args);
15
+ fs.readFileSync = (...args) => vol.readFileSync(...args);
16
+ fs.stat = (...args) => Promise.resolve(vol.stat(...args));
17
+ fs.statSync = (...args) => vol.statSync(...args);
18
+
19
+ module.exports = fs;
@@ -80,7 +80,7 @@ describe("CLI > Bundle > Kit Config > getKitBundleConfigs", () => {
80
80
  detectCyclicDependencies: true,
81
81
  detectDuplicateDependencies: true,
82
82
  typescriptValidation: true,
83
- experimental_treeShake: true,
83
+ treeShake: true,
84
84
  targets: ["ios", "android"],
85
85
  platforms: {
86
86
  ios: {
@@ -123,4 +123,26 @@ describe("CLI > Bundle > Kit Config > getKitBundleConfigs", () => {
123
123
  platform: "android",
124
124
  });
125
125
  });
126
+
127
+ test("uses deprecated experimental_treeShake", () => {
128
+ const d: Record<string, unknown> = { ...definition };
129
+ delete d.treeShake;
130
+ d.experimental_treeShake = true;
131
+ rnxKitConfig.__setMockConfig({
132
+ bundle: {
133
+ ...d,
134
+ },
135
+ });
136
+ consoleWarnSpy.mockReset();
137
+
138
+ const kitBundleConfigs = getKitBundleConfigs(undefined, "ios");
139
+ expect(kitBundleConfigs[0].treeShake).toBe(true);
140
+ expect(consoleWarnSpy).toBeCalledTimes(1);
141
+ expect(consoleWarnSpy).toBeCalledWith(
142
+ expect.stringContaining("deprecated")
143
+ );
144
+ expect(consoleWarnSpy).toBeCalledWith(
145
+ expect.stringContaining("experimental_treeShake")
146
+ );
147
+ });
126
148
  });
@@ -8,7 +8,7 @@ describe("CLI > Bundle > Metro > createMetroBundleArgs", () => {
8
8
  detectCyclicDependencies: true,
9
9
  detectDuplicateDependencies: true,
10
10
  typescriptValidation: true,
11
- experimental_treeShake: true,
11
+ treeShake: true,
12
12
  entryPath: "out/entry.js",
13
13
  distPath: "out",
14
14
  assetsPath: "out/assets",
@@ -7,7 +7,7 @@ describe("CLI > Bundle > Overrides > applyKitBundleConfigOverrides", () => {
7
7
  detectCyclicDependencies: true,
8
8
  detectDuplicateDependencies: true,
9
9
  typescriptValidation: true,
10
- experimental_treeShake: true,
10
+ treeShake: true,
11
11
  entryPath: "dist/index.js",
12
12
  distPath: "dist",
13
13
  assetsPath: "dist",
@@ -63,17 +63,7 @@ describe("CLI > Bundle > Overrides > applyKitBundleConfigOverrides", () => {
63
63
  testOverride("sourcemapSourcesRoot", "out");
64
64
  });
65
65
 
66
- test("set experimental_treeShake using override experimentalTreeShake", () => {
67
- const copy = { ...config };
68
- applyKitBundleConfigOverrides(
69
- {
70
- experimentalTreeShake: true,
71
- },
72
- [copy]
73
- );
74
- expect(copy).toEqual({
75
- ...config,
76
- experimental_treeShake: true,
77
- });
66
+ test("changes treeShake using an override", () => {
67
+ testOverride("treeShake", true);
78
68
  });
79
69
  });
@@ -0,0 +1,306 @@
1
+ import { spawnSync } from "child_process";
2
+ import * as path from "path";
3
+ import { findFiles, mockFiles } from "./helpers";
4
+ import { assembleAarBundle } from "../../src/copy-assets";
5
+
6
+ jest.mock("child_process");
7
+ jest.mock("fs");
8
+
9
+ export const options = {
10
+ platform: "android" as const,
11
+ assetsDest: "dist",
12
+ bundleAar: true,
13
+ };
14
+
15
+ export const context = {
16
+ projectRoot: path.resolve(__dirname, "..", ".."),
17
+ manifest: {
18
+ name: "@rnx-kit/cli",
19
+ version: "0.0.0-dev",
20
+ },
21
+ options,
22
+ };
23
+
24
+ describe("assembleAarBundle", () => {
25
+ const consoleWarnSpy = jest.spyOn(global.console, "warn");
26
+
27
+ afterEach(() => {
28
+ mockFiles();
29
+ consoleWarnSpy.mockReset();
30
+ spawnSync.mockReset();
31
+ });
32
+
33
+ afterAll(() => {
34
+ jest.resetAllMocks();
35
+ });
36
+
37
+ test("returns early if there is nothing to assemble", async () => {
38
+ await assembleAarBundle(context, context.manifest.name, {});
39
+
40
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
41
+ expect(findFiles()).toEqual([]);
42
+ });
43
+
44
+ test("returns early if Gradle wrapper cannot be found", async () => {
45
+ await assembleAarBundle(context, context.manifest.name, { aar: {} });
46
+
47
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
48
+ expect.anything(),
49
+ expect.stringMatching(/cannot find `gradlew`$/)
50
+ );
51
+ expect(spawnSync).not.toHaveBeenCalled();
52
+ expect(findFiles()).toEqual([]);
53
+ });
54
+
55
+ test("throws if target package cannot be found", async () => {
56
+ mockFiles({
57
+ gradlew: "",
58
+ "gradlew.bat": "",
59
+ });
60
+
61
+ expect(
62
+ assembleAarBundle(context, context.manifest.name, { aar: {} })
63
+ ).rejects.toThrow();
64
+ expect(findFiles()).toEqual([
65
+ [expect.stringMatching(/[/\\]gradlew$/), ""],
66
+ [expect.stringMatching(/[/\\]gradlew.bat$/), ""],
67
+ ]);
68
+ });
69
+
70
+ test("returns early if Gradle project cannot be found", async () => {
71
+ mockFiles({
72
+ gradlew: "",
73
+ "gradlew.bat": "",
74
+ "node_modules/@rnx-kit/react-native-auth/package.json": JSON.stringify({
75
+ version: "0.0.0-dev",
76
+ }),
77
+ });
78
+
79
+ await assembleAarBundle(context, "@rnx-kit/react-native-auth", { aar: {} });
80
+
81
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
82
+ expect.anything(),
83
+ expect.stringMatching(/cannot find `build.gradle`/)
84
+ );
85
+ expect(spawnSync).not.toHaveBeenCalled();
86
+ expect(findFiles()).toEqual([
87
+ [expect.stringMatching(/[/\\]gradlew$/), ""],
88
+ [expect.stringMatching(/[/\\]gradlew.bat$/), ""],
89
+ [
90
+ expect.stringMatching(
91
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]package.json$/
92
+ ),
93
+ JSON.stringify({ version: "0.0.0-dev" }),
94
+ ],
95
+ ]);
96
+ });
97
+
98
+ test("generates Android project if necessary", async () => {
99
+ mockFiles({
100
+ gradlew: "",
101
+ "gradlew.bat": "",
102
+ "node_modules/@rnx-kit/react-native-auth/android/build.gradle":
103
+ "build.gradle",
104
+ "node_modules/@rnx-kit/react-native-auth/android/build/outputs/aar/rnx-kit_react-native-auth-release.aar":
105
+ "rnx-kit_react-native-auth-release.aar",
106
+ "node_modules/@rnx-kit/react-native-auth/package.json": JSON.stringify({
107
+ version: "0.0.0-dev",
108
+ }),
109
+ "node_modules/react-native/package.json": JSON.stringify({
110
+ version: "1000.0.0-dev",
111
+ }),
112
+ });
113
+
114
+ await assembleAarBundle(context, "@rnx-kit/react-native-auth", { aar: {} });
115
+
116
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
117
+ expect(spawnSync).toHaveBeenCalledWith(
118
+ expect.stringMatching(/[/\\]gradlew(?:\.bat)?$/),
119
+ [":rnx-kit_react-native-auth:assembleRelease"],
120
+ expect.objectContaining({
121
+ cwd: expect.stringMatching(
122
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth$/
123
+ ),
124
+ })
125
+ );
126
+ expect(findFiles()).toEqual([
127
+ [expect.stringMatching(/[/\\]gradlew$/), ""],
128
+ [expect.stringMatching(/[/\\]gradlew.bat$/), ""],
129
+ [
130
+ expect.stringMatching(
131
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android[/\\]build.gradle$/
132
+ ),
133
+ "build.gradle",
134
+ ],
135
+ [
136
+ expect.stringMatching(
137
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android[/\\]build[/\\]outputs[/\\]aar[/\\]rnx-kit_react-native-auth-release.aar$/
138
+ ),
139
+ "rnx-kit_react-native-auth-release.aar",
140
+ ],
141
+ [
142
+ expect.stringMatching(
143
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]package.json$/
144
+ ),
145
+ JSON.stringify({ version: "0.0.0-dev" }),
146
+ ],
147
+ [
148
+ expect.stringMatching(
149
+ /[/\\]node_modules[/\\]react-native[/\\]package.json$/
150
+ ),
151
+ JSON.stringify({ version: "1000.0.0-dev" }),
152
+ ],
153
+ [
154
+ expect.stringMatching(
155
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth[/\\]build.gradle$/
156
+ ),
157
+ expect.stringMatching(/^buildscript/),
158
+ ],
159
+ [
160
+ expect.stringMatching(
161
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth[/\\]gradle.properties/
162
+ ),
163
+ expect.stringMatching(/^android.useAndroidX=true/),
164
+ ],
165
+ [
166
+ expect.stringMatching(
167
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth[/\\]settings.gradle$/
168
+ ),
169
+ expect.stringMatching(
170
+ /include\(":rnx-kit_react-native-auth"\)\nproject\(":rnx-kit_react-native-auth"\).projectDir = file\(".*?[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android"\)/
171
+ ),
172
+ ],
173
+ [
174
+ expect.stringMatching(
175
+ /[/\\]dist[/\\]aar[/\\]rnx-kit_react-native-auth-0.0.0-dev.aar$/
176
+ ),
177
+ "rnx-kit_react-native-auth-release.aar",
178
+ ],
179
+ ]);
180
+ });
181
+
182
+ test("assembles Android archive using existing project", async () => {
183
+ mockFiles({
184
+ gradlew: "",
185
+ "gradlew.bat": "",
186
+ "node_modules/@rnx-kit/react-native-auth/android/build.gradle":
187
+ "build.gradle",
188
+ "node_modules/@rnx-kit/react-native-auth/android/build/outputs/aar/rnx-kit_react-native-auth-release.aar":
189
+ "rnx-kit_react-native-auth-release.aar",
190
+ "node_modules/@rnx-kit/react-native-auth/android/settings.gradle":
191
+ "settings.gradle",
192
+ "node_modules/@rnx-kit/react-native-auth/package.json": JSON.stringify({
193
+ version: "0.0.0-dev",
194
+ }),
195
+ "node_modules/react-native/package.json": JSON.stringify({
196
+ version: "1000.0.0-dev",
197
+ }),
198
+ });
199
+
200
+ await assembleAarBundle(context, "@rnx-kit/react-native-auth", { aar: {} });
201
+
202
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
203
+ expect(spawnSync).toHaveBeenCalledWith(
204
+ expect.stringMatching(/[/\\]gradlew(?:\.bat)?$/),
205
+ [":rnx-kit_react-native-auth:assembleRelease"],
206
+ expect.objectContaining({
207
+ cwd: expect.stringMatching(
208
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android$/
209
+ ),
210
+ })
211
+ );
212
+ expect(findFiles()).toEqual([
213
+ [expect.stringMatching(/[/\\]gradlew$/), ""],
214
+ [expect.stringMatching(/[/\\]gradlew.bat$/), ""],
215
+ [
216
+ expect.stringMatching(
217
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android[/\\]build.gradle$/
218
+ ),
219
+ "build.gradle",
220
+ ],
221
+ [
222
+ expect.stringMatching(
223
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android[/\\]build[/\\]outputs[/\\]aar[/\\]rnx-kit_react-native-auth-release.aar$/
224
+ ),
225
+ "rnx-kit_react-native-auth-release.aar",
226
+ ],
227
+ [
228
+ expect.stringMatching(
229
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]android[/\\]settings.gradle$/
230
+ ),
231
+ "settings.gradle",
232
+ ],
233
+ [
234
+ expect.stringMatching(
235
+ /[/\\]node_modules[/\\]@rnx-kit[/\\]react-native-auth[/\\]package.json$/
236
+ ),
237
+ JSON.stringify({ version: "0.0.0-dev" }),
238
+ ],
239
+ [
240
+ expect.stringMatching(
241
+ /[/\\]node_modules[/\\]react-native[/\\]package.json$/
242
+ ),
243
+ JSON.stringify({ version: "1000.0.0-dev" }),
244
+ ],
245
+ [
246
+ expect.stringMatching(
247
+ /[/\\]dist[/\\]aar[/\\]rnx-kit_react-native-auth-0.0.0-dev.aar$/
248
+ ),
249
+ "rnx-kit_react-native-auth-release.aar",
250
+ ],
251
+ ]);
252
+ });
253
+
254
+ test("allows the generated Android project to be configured", async () => {
255
+ mockFiles({
256
+ gradlew: "",
257
+ "gradlew.bat": "",
258
+ "node_modules/@rnx-kit/react-native-auth/android/build.gradle":
259
+ "build.gradle",
260
+ "node_modules/@rnx-kit/react-native-auth/android/build/outputs/aar/rnx-kit_react-native-auth-release.aar":
261
+ "rnx-kit_react-native-auth-release.aar",
262
+ "node_modules/@rnx-kit/react-native-auth/package.json": JSON.stringify({
263
+ version: "0.0.0-dev",
264
+ }),
265
+ "node_modules/react-native/package.json": JSON.stringify({
266
+ version: "1000.0.0-dev",
267
+ }),
268
+ });
269
+
270
+ await assembleAarBundle(context, "@rnx-kit/react-native-auth", {
271
+ aar: {
272
+ android: {
273
+ androidPluginVersion: "7.1.3",
274
+ compileSdkVersion: 31,
275
+ defaultConfig: {
276
+ minSdkVersion: 26,
277
+ targetSdkVersion: 30,
278
+ },
279
+ },
280
+ },
281
+ });
282
+
283
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
284
+ expect(spawnSync).toHaveBeenCalledWith(
285
+ expect.stringMatching(/[/\\]gradlew(?:\.bat)?$/),
286
+ [":rnx-kit_react-native-auth:assembleRelease"],
287
+ expect.objectContaining({
288
+ cwd: expect.stringMatching(
289
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth$/
290
+ ),
291
+ })
292
+ );
293
+ expect(findFiles()).toEqual(
294
+ expect.arrayContaining([
295
+ [
296
+ expect.stringMatching(
297
+ /[/\\]node_modules[/\\].rnx-gradle-build[/\\]rnx-kit_react-native-auth[/\\]build.gradle$/
298
+ ),
299
+ expect.stringMatching(
300
+ /compileSdkVersion = 31\s+minSdkVersion = 26\s+targetSdkVersion = 30\s+androidPluginVersion = "7\.1\.3"/
301
+ ),
302
+ ],
303
+ ])
304
+ );
305
+ });
306
+ });
@@ -1,6 +1,6 @@
1
- import fs from "fs-extra";
2
1
  import * as path from "path";
3
- import { copyAssets, gatherConfigs, versionOf } from "../src/copy-assets";
2
+ import { findFiles, mockFiles } from "./helpers";
3
+ import { copyAssets, gatherConfigs, versionOf } from "../../src/copy-assets";
4
4
 
5
5
  const options = {
6
6
  platform: "ios" as const,
@@ -10,7 +10,7 @@ const options = {
10
10
  };
11
11
 
12
12
  const context = {
13
- projectRoot: path.resolve(__dirname, ".."),
13
+ projectRoot: path.resolve(__dirname, "..", ".."),
14
14
  manifest: {
15
15
  name: "@rnx-kit/cli",
16
16
  version: "0.0.0-dev",
@@ -18,16 +18,6 @@ const context = {
18
18
  options,
19
19
  };
20
20
 
21
- function findFiles() {
22
- // @ts-ignore `__toJSON`
23
- return Object.entries(fs.__toJSON());
24
- }
25
-
26
- function mockFiles(files: Record<string, string> = {}) {
27
- // @ts-ignore `__setMockFiles`
28
- fs.__setMockFiles(files);
29
- }
30
-
31
21
  describe("copyAssets", () => {
32
22
  afterEach(() => {
33
23
  mockFiles();
@@ -0,0 +1,13 @@
1
+ // istanbul ignore file
2
+
3
+ import * as fs from "fs-extra";
4
+
5
+ export function findFiles() {
6
+ // @ts-ignore `__toJSON`
7
+ return Object.entries(fs.__toJSON());
8
+ }
9
+
10
+ export function mockFiles(files: Record<string, string> = {}) {
11
+ // @ts-ignore `__setMockFiles`
12
+ fs.__setMockFiles(files);
13
+ }