react-native-update-cli 2.8.4 → 2.9.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.
Files changed (112) hide show
  1. package/lib/api.d.ts +18 -0
  2. package/lib/app.d.ts +38 -0
  3. package/lib/app.js +5 -4
  4. package/lib/bundle-pack.d.ts +1 -0
  5. package/lib/bundle-pack.js +104 -0
  6. package/lib/bundle-runner.d.ts +20 -0
  7. package/lib/bundle-runner.js +404 -0
  8. package/lib/bundle.d.ts +6 -0
  9. package/lib/bundle.js +73 -471
  10. package/lib/diff.d.ts +13 -0
  11. package/lib/diff.js +144 -123
  12. package/lib/exports.d.ts +12 -0
  13. package/lib/index.d.ts +5 -0
  14. package/lib/index.js +5 -13
  15. package/lib/install.d.ts +4 -0
  16. package/lib/locales/en.d.ts +137 -0
  17. package/lib/locales/en.js +11 -0
  18. package/lib/locales/zh.d.ts +136 -0
  19. package/lib/locales/zh.js +11 -0
  20. package/lib/module-manager.d.ts +20 -0
  21. package/lib/module-manager.js +3 -9
  22. package/lib/modules/app-module.d.ts +2 -0
  23. package/lib/modules/app-module.js +84 -44
  24. package/lib/modules/bundle-module.d.ts +2 -0
  25. package/lib/modules/bundle-module.js +7 -8
  26. package/lib/modules/index.d.ts +6 -0
  27. package/lib/modules/package-module.d.ts +2 -0
  28. package/lib/modules/user-module.d.ts +2 -0
  29. package/lib/modules/user-module.js +55 -44
  30. package/lib/modules/version-module.d.ts +2 -0
  31. package/lib/package.d.ts +58 -0
  32. package/lib/package.js +103 -139
  33. package/lib/provider.d.ts +26 -0
  34. package/lib/provider.js +115 -217
  35. package/lib/types.d.ts +120 -0
  36. package/lib/user.d.ts +8 -0
  37. package/lib/utils/add-gitignore.d.ts +1 -0
  38. package/lib/utils/app-info-parser/aab.d.ts +22 -0
  39. package/lib/utils/app-info-parser/aab.js +0 -4
  40. package/lib/utils/app-info-parser/apk.d.ts +14 -0
  41. package/lib/utils/app-info-parser/apk.js +6 -4
  42. package/lib/utils/app-info-parser/app.d.ts +4 -0
  43. package/lib/utils/app-info-parser/app.js +3 -0
  44. package/lib/utils/app-info-parser/index.d.ts +16 -0
  45. package/lib/utils/app-info-parser/index.js +2 -0
  46. package/lib/utils/app-info-parser/ipa.d.ts +14 -0
  47. package/lib/utils/app-info-parser/ipa.js +1 -1
  48. package/lib/utils/app-info-parser/resource-finder.d.ts +49 -0
  49. package/lib/utils/app-info-parser/utils.d.ts +31 -0
  50. package/lib/utils/app-info-parser/utils.js +1 -0
  51. package/lib/utils/app-info-parser/xml-parser/binary.d.ts +56 -0
  52. package/lib/utils/app-info-parser/xml-parser/manifest.d.ts +10 -0
  53. package/lib/utils/app-info-parser/zip.d.ts +18 -0
  54. package/lib/utils/app-info-parser/zip.js +7 -9
  55. package/lib/utils/check-lockfile.d.ts +1 -0
  56. package/lib/utils/check-plugin.d.ts +7 -0
  57. package/lib/utils/command-result.d.ts +3 -0
  58. package/lib/utils/command-result.js +35 -0
  59. package/lib/utils/constants.d.ts +9 -0
  60. package/lib/utils/dep-versions.d.ts +1 -0
  61. package/lib/utils/git.d.ts +8 -0
  62. package/lib/utils/http-helper.d.ts +4 -0
  63. package/lib/utils/i18n.d.ts +12 -0
  64. package/lib/utils/index.d.ts +22 -0
  65. package/lib/utils/index.js +52 -22
  66. package/lib/utils/latest-version/cli.d.ts +1 -0
  67. package/lib/utils/latest-version/cli.js +24 -60
  68. package/lib/utils/latest-version/index.d.ts +146 -0
  69. package/lib/utils/latest-version/index.js +22 -22
  70. package/lib/utils/options.d.ts +4 -0
  71. package/lib/utils/options.js +63 -0
  72. package/lib/utils/plugin-config.d.ts +9 -0
  73. package/lib/utils/zip-entries.d.ts +3 -0
  74. package/lib/versions.d.ts +43 -0
  75. package/lib/versions.js +186 -2
  76. package/lib/workflow-runner.d.ts +2 -0
  77. package/lib/workflow-runner.js +25 -0
  78. package/package.json +20 -5
  79. package/src/api.ts +1 -1
  80. package/src/app.ts +20 -11
  81. package/src/bundle-pack.ts +51 -0
  82. package/src/bundle-runner.ts +463 -0
  83. package/src/bundle.ts +184 -571
  84. package/src/diff.ts +208 -174
  85. package/src/index.ts +15 -17
  86. package/src/locales/en.ts +15 -0
  87. package/src/locales/zh.ts +13 -0
  88. package/src/module-manager.ts +15 -15
  89. package/src/modules/app-module.ts +120 -48
  90. package/src/modules/bundle-module.ts +21 -11
  91. package/src/modules/package-module.ts +0 -1
  92. package/src/modules/user-module.ts +117 -58
  93. package/src/package.ts +158 -138
  94. package/src/provider.ts +164 -240
  95. package/src/types.ts +15 -8
  96. package/src/utils/app-info-parser/aab.ts +0 -7
  97. package/src/utils/app-info-parser/apk.ts +9 -6
  98. package/src/utils/app-info-parser/app.ts +5 -1
  99. package/src/utils/app-info-parser/index.ts +11 -6
  100. package/src/utils/app-info-parser/ipa.ts +1 -1
  101. package/src/utils/app-info-parser/utils.ts +3 -0
  102. package/src/utils/app-info-parser/xml-parser/manifest.ts +3 -1
  103. package/src/utils/app-info-parser/zip.ts +12 -14
  104. package/src/utils/command-result.ts +24 -0
  105. package/src/utils/index.ts +138 -39
  106. package/src/utils/latest-version/cli.ts +22 -20
  107. package/src/utils/latest-version/index.ts +20 -20
  108. package/src/utils/options.ts +56 -0
  109. package/src/utils/zip-entries.ts +1 -1
  110. package/src/versions.ts +265 -2
  111. package/src/workflow-runner.ts +24 -0
  112. package/index.js +0 -1
@@ -0,0 +1,463 @@
1
+ import { spawn, spawnSync } from 'child_process';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { satisfies } from 'compare-versions';
5
+ import * as fs from 'fs-extra';
6
+ import { t } from './utils/i18n';
7
+
8
+ const g2js = require('gradle-to-js/lib/parser');
9
+ const properties = require('properties');
10
+
11
+ export interface BundleCliOptions {
12
+ taro?: boolean;
13
+ expo?: boolean;
14
+ rncli?: boolean;
15
+ }
16
+
17
+ export interface RunBundleCommandOptions {
18
+ bundleName: string;
19
+ dev: string;
20
+ entryFile: string;
21
+ outputFolder: string;
22
+ platform: string;
23
+ sourcemapOutput: string;
24
+ config?: string;
25
+ forceHermes?: boolean;
26
+ cli: BundleCliOptions;
27
+ isSentry: boolean;
28
+ }
29
+
30
+ interface GradleConfig {
31
+ crunchPngs?: boolean;
32
+ enableHermes?: boolean;
33
+ }
34
+
35
+ export async function runReactNativeBundleCommand({
36
+ bundleName,
37
+ dev,
38
+ entryFile,
39
+ outputFolder,
40
+ platform,
41
+ sourcemapOutput,
42
+ config,
43
+ forceHermes,
44
+ cli,
45
+ isSentry,
46
+ }: RunBundleCommandOptions): Promise<void> {
47
+ let gradleConfig: GradleConfig = {};
48
+ if (platform === 'android') {
49
+ gradleConfig = await checkGradleConfig();
50
+ if (gradleConfig.crunchPngs !== false) {
51
+ console.warn(t('androidCrunchPngsWarning'));
52
+ }
53
+ }
54
+
55
+ const reactNativeBundleArgs: string[] = [];
56
+ const envArgs = process.env.PUSHY_ENV_ARGS;
57
+
58
+ if (envArgs) {
59
+ reactNativeBundleArgs.push(...envArgs.trim().split(/\s+/));
60
+ }
61
+
62
+ fs.emptyDirSync(outputFolder);
63
+
64
+ let cliPath = '';
65
+ let usingExpo = false;
66
+
67
+ const getExpoCli = () => {
68
+ try {
69
+ const searchPaths = [process.cwd()];
70
+
71
+ try {
72
+ const expoPath = require.resolve('expo/package.json', {
73
+ paths: [process.cwd()],
74
+ });
75
+ const expoDir = expoPath.replace(/\/package\.json$/, '');
76
+ searchPaths.push(expoDir);
77
+ } catch {
78
+ // expo 包不存在,忽略
79
+ }
80
+
81
+ cliPath = require.resolve('@expo/cli', {
82
+ paths: searchPaths,
83
+ });
84
+
85
+ const expoCliVersion = JSON.parse(
86
+ fs
87
+ .readFileSync(
88
+ require.resolve('@expo/cli/package.json', {
89
+ paths: searchPaths,
90
+ }),
91
+ )
92
+ .toString(),
93
+ ).version;
94
+ if (satisfies(expoCliVersion, '>= 0.10.17')) {
95
+ usingExpo = true;
96
+ } else {
97
+ cliPath = '';
98
+ }
99
+ } catch {
100
+ // fallback 到 RN CLI
101
+ }
102
+ };
103
+
104
+ const getRnCli = () => {
105
+ try {
106
+ cliPath = require.resolve('react-native/local-cli/cli.js', {
107
+ paths: [process.cwd()],
108
+ });
109
+ } catch {
110
+ cliPath = require.resolve('@react-native-community/cli/build/bin.js', {
111
+ paths: [process.cwd()],
112
+ });
113
+ }
114
+ };
115
+
116
+ const getTaroCli = () => {
117
+ try {
118
+ cliPath = require.resolve('@tarojs/cli/bin/taro', {
119
+ paths: [process.cwd()],
120
+ });
121
+ } catch {
122
+ // fallback 到 RN CLI
123
+ }
124
+ };
125
+
126
+ if (cli.expo) {
127
+ getExpoCli();
128
+ } else if (cli.taro) {
129
+ getTaroCli();
130
+ } else if (cli.rncli) {
131
+ getRnCli();
132
+ }
133
+
134
+ if (!cliPath) {
135
+ getExpoCli();
136
+ if (!usingExpo) {
137
+ getRnCli();
138
+ }
139
+ }
140
+
141
+ if (isSentry) {
142
+ if (platform === 'ios') {
143
+ process.env.SENTRY_PROPERTIES = 'ios/sentry.properties';
144
+ } else if (platform === 'android') {
145
+ process.env.SENTRY_PROPERTIES = 'android/sentry.properties';
146
+ }
147
+ }
148
+
149
+ let bundleCommand = 'bundle';
150
+ if (usingExpo) {
151
+ bundleCommand = 'export:embed';
152
+ } else if (platform === 'harmony') {
153
+ bundleCommand = 'bundle-harmony';
154
+ } else if (cli.taro) {
155
+ bundleCommand = 'build';
156
+ }
157
+
158
+ if (platform === 'harmony') {
159
+ bundleName = 'bundle.harmony.js';
160
+ if (forceHermes === undefined) {
161
+ forceHermes = true;
162
+ }
163
+ }
164
+
165
+ reactNativeBundleArgs.push(
166
+ cliPath,
167
+ bundleCommand,
168
+ '--assets-dest',
169
+ outputFolder,
170
+ '--bundle-output',
171
+ path.join(outputFolder, bundleName),
172
+ );
173
+
174
+ if (platform !== 'harmony') {
175
+ reactNativeBundleArgs.push('--platform', platform, '--reset-cache');
176
+ }
177
+
178
+ if (cli.taro) {
179
+ reactNativeBundleArgs.push('--type', 'rn');
180
+ } else {
181
+ reactNativeBundleArgs.push('--dev', dev, '--entry-file', entryFile);
182
+ }
183
+
184
+ if (sourcemapOutput) {
185
+ reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
186
+ }
187
+
188
+ if (config) {
189
+ reactNativeBundleArgs.push('--config', config);
190
+ }
191
+
192
+ const reactNativeBundleProcess = spawn('node', reactNativeBundleArgs);
193
+ console.log(
194
+ `Running bundle command: node ${reactNativeBundleArgs.join(' ')}`,
195
+ );
196
+
197
+ await new Promise<void>((resolve, reject) => {
198
+ reactNativeBundleProcess.stdout.on('data', (data) => {
199
+ console.log(data.toString().trim());
200
+ });
201
+
202
+ reactNativeBundleProcess.stderr.on('data', (data) => {
203
+ console.error(data.toString().trim());
204
+ });
205
+
206
+ reactNativeBundleProcess.on('close', async (exitCode) => {
207
+ if (exitCode) {
208
+ reject(new Error(t('bundleCommandError', { code: exitCode })));
209
+ return;
210
+ }
211
+
212
+ let hermesEnabled: boolean | undefined = false;
213
+
214
+ if (forceHermes) {
215
+ hermesEnabled = true;
216
+ console.log(t('forceHermes'));
217
+ } else if (platform === 'android') {
218
+ const gradleProperties = await new Promise<{ hermesEnabled?: boolean }>(
219
+ (resolve) => {
220
+ properties.parse(
221
+ './android/gradle.properties',
222
+ { path: true },
223
+ (
224
+ error: Error | null,
225
+ props: { hermesEnabled?: boolean } = {},
226
+ ) => {
227
+ if (error) {
228
+ console.error(error);
229
+ resolve({});
230
+ return;
231
+ }
232
+ resolve(props);
233
+ },
234
+ );
235
+ },
236
+ );
237
+ hermesEnabled = gradleProperties.hermesEnabled;
238
+
239
+ if (typeof hermesEnabled !== 'boolean') {
240
+ hermesEnabled = gradleConfig.enableHermes;
241
+ }
242
+ } else if (
243
+ platform === 'ios' &&
244
+ fs.existsSync('ios/Pods/hermes-engine')
245
+ ) {
246
+ hermesEnabled = true;
247
+ }
248
+
249
+ if (hermesEnabled) {
250
+ await compileHermesByteCode(
251
+ bundleName,
252
+ outputFolder,
253
+ sourcemapOutput,
254
+ !isSentry,
255
+ );
256
+ }
257
+
258
+ if (platform === 'harmony') {
259
+ const harmonyRawAssetsPath =
260
+ 'harmony/entry/src/main/resources/rawfile/assets';
261
+ fs.ensureDirSync(harmonyRawAssetsPath);
262
+ fs.copySync(outputFolder, harmonyRawAssetsPath, { overwrite: true });
263
+ fs.moveSync(
264
+ `${harmonyRawAssetsPath}/bundle.harmony.js`,
265
+ `${harmonyRawAssetsPath}/../bundle.harmony.js`,
266
+ { overwrite: true },
267
+ );
268
+ }
269
+
270
+ resolve();
271
+ });
272
+ });
273
+ }
274
+
275
+ function getHermesOSBin() {
276
+ if (os.platform() === 'win32') return 'win64-bin';
277
+ if (os.platform() === 'darwin') return 'osx-bin';
278
+ if (os.platform() === 'linux') return 'linux64-bin';
279
+ }
280
+
281
+ async function checkGradleConfig(): Promise<GradleConfig> {
282
+ let enableHermes = false;
283
+ let crunchPngs: boolean | undefined;
284
+ try {
285
+ const gradleConfig = await g2js.parseFile('android/app/build.gradle');
286
+ crunchPngs = gradleConfig.android.buildTypes.release.crunchPngs;
287
+ const projectConfig = gradleConfig['project.ext.react'];
288
+ if (projectConfig) {
289
+ for (const packagerConfig of projectConfig) {
290
+ if (
291
+ packagerConfig.includes('enableHermes') &&
292
+ packagerConfig.includes('true')
293
+ ) {
294
+ enableHermes = true;
295
+ break;
296
+ }
297
+ }
298
+ }
299
+ } catch {
300
+ // ignore parsing failures
301
+ }
302
+ return {
303
+ enableHermes,
304
+ crunchPngs,
305
+ };
306
+ }
307
+
308
+ async function compileHermesByteCode(
309
+ bundleName: string,
310
+ outputFolder: string,
311
+ sourcemapOutput: string,
312
+ shouldCleanSourcemap: boolean,
313
+ ) {
314
+ console.log(t('hermesEnabledCompiling'));
315
+ const rnDir = path.dirname(
316
+ require.resolve('react-native', {
317
+ paths: [process.cwd()],
318
+ }),
319
+ );
320
+ let hermesPath = path.join(rnDir, `/sdks/hermesc/${getHermesOSBin()}`);
321
+
322
+ if (!fs.existsSync(hermesPath)) {
323
+ hermesPath = `node_modules/hermes-engine/${getHermesOSBin()}`;
324
+ }
325
+
326
+ const hermesCommand = `${hermesPath}/hermesc`;
327
+
328
+ const args = [
329
+ '-emit-binary',
330
+ '-out',
331
+ path.join(outputFolder, bundleName),
332
+ path.join(outputFolder, bundleName),
333
+ '-O',
334
+ ];
335
+ if (sourcemapOutput) {
336
+ fs.copyFileSync(
337
+ sourcemapOutput,
338
+ path.join(outputFolder, `${bundleName}.txt.map`),
339
+ );
340
+ args.push('-output-source-map');
341
+ }
342
+ console.log(
343
+ t('runningHermesc', { command: hermesCommand, args: args.join(' ') }),
344
+ );
345
+ spawnSync(hermesCommand, args, {
346
+ stdio: 'ignore',
347
+ });
348
+ if (sourcemapOutput) {
349
+ const composerPath =
350
+ 'node_modules/react-native/scripts/compose-source-maps.js';
351
+ if (!fs.existsSync(composerPath)) {
352
+ return;
353
+ }
354
+ console.log(t('composingSourceMap'));
355
+ spawnSync(
356
+ 'node',
357
+ [
358
+ composerPath,
359
+ path.join(outputFolder, `${bundleName}.txt.map`),
360
+ path.join(outputFolder, `${bundleName}.map`),
361
+ '-o',
362
+ sourcemapOutput,
363
+ ],
364
+ {
365
+ stdio: 'ignore',
366
+ },
367
+ );
368
+ }
369
+ if (shouldCleanSourcemap) {
370
+ fs.removeSync(path.join(outputFolder, `${bundleName}.txt.map`));
371
+ }
372
+ }
373
+
374
+ export async function copyDebugidForSentry(
375
+ bundleName: string,
376
+ outputFolder: string,
377
+ sourcemapOutput: string,
378
+ ): Promise<void> {
379
+ if (sourcemapOutput) {
380
+ let copyDebugidPath: string | undefined;
381
+ try {
382
+ copyDebugidPath = require.resolve(
383
+ '@sentry/react-native/scripts/copy-debugid.js',
384
+ {
385
+ paths: [process.cwd()],
386
+ },
387
+ );
388
+ } catch {
389
+ console.error(t('sentryCliNotFound'));
390
+ return;
391
+ }
392
+
393
+ if (!fs.existsSync(copyDebugidPath)) {
394
+ return;
395
+ }
396
+ console.log(t('copyingDebugId'));
397
+ spawnSync(
398
+ 'node',
399
+ [
400
+ copyDebugidPath,
401
+ path.join(outputFolder, `${bundleName}.txt.map`),
402
+ path.join(outputFolder, `${bundleName}.map`),
403
+ ],
404
+ {
405
+ stdio: 'ignore',
406
+ },
407
+ );
408
+ }
409
+ fs.removeSync(path.join(outputFolder, `${bundleName}.txt.map`));
410
+ }
411
+
412
+ export async function uploadSourcemapForSentry(
413
+ bundleName: string,
414
+ outputFolder: string,
415
+ sourcemapOutput: string,
416
+ version: string,
417
+ ): Promise<void> {
418
+ if (!sourcemapOutput) {
419
+ return;
420
+ }
421
+
422
+ let sentryCliPath: string | undefined;
423
+ try {
424
+ sentryCliPath = require.resolve('@sentry/cli/bin/sentry-cli', {
425
+ paths: [process.cwd()],
426
+ });
427
+ } catch {
428
+ console.error(t('sentryCliNotFound'));
429
+ return;
430
+ }
431
+
432
+ if (!fs.existsSync(sentryCliPath)) {
433
+ return;
434
+ }
435
+
436
+ spawnSync(
437
+ 'node',
438
+ [sentryCliPath, 'releases', 'set-commits', version, '--auto'],
439
+ {
440
+ stdio: 'inherit',
441
+ },
442
+ );
443
+ console.log(t('sentryReleaseCreated', { version }));
444
+
445
+ console.log(t('uploadingSourcemap'));
446
+ spawnSync(
447
+ 'node',
448
+ [
449
+ sentryCliPath,
450
+ 'releases',
451
+ 'files',
452
+ version,
453
+ 'upload-sourcemaps',
454
+ '--strip-prefix',
455
+ path.join(process.cwd(), outputFolder),
456
+ path.join(outputFolder, bundleName),
457
+ path.join(outputFolder, `${bundleName}.map`),
458
+ ],
459
+ {
460
+ stdio: 'inherit',
461
+ },
462
+ );
463
+ }