react-native-update-cli 1.38.1 → 1.38.2
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/lib/app.js +1 -1
- package/lib/bundle.js +65 -53
- package/lib/package.js +8 -8
- package/lib/utils/index.js +3 -5
- package/package.json +1 -1
- package/src/{app.js → app.ts} +6 -5
- package/src/bundle.js +73 -62
- package/src/{package.js → package.ts} +10 -11
- package/src/types.ts +2 -0
- package/src/{user.js → user.ts} +2 -2
- package/src/utils/{index.js → index.ts} +7 -6
package/lib/app.js
CHANGED
|
@@ -90,7 +90,7 @@ async function chooseApp(platform) {
|
|
|
90
90
|
const list = await listApp(platform);
|
|
91
91
|
while(true){
|
|
92
92
|
const id = await (0, _utils.question)('输入应用 id:');
|
|
93
|
-
const app = list.find((v)=>v.id === (id
|
|
93
|
+
const app = list.find((v)=>v.id === Number(id));
|
|
94
94
|
if (app) {
|
|
95
95
|
return app;
|
|
96
96
|
}
|
package/lib/bundle.js
CHANGED
|
@@ -19,13 +19,15 @@ _export(exports, {
|
|
|
19
19
|
return readEntire;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
+
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
22
23
|
const _utils = require("./utils");
|
|
23
24
|
const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
|
|
24
25
|
const _yazl = require("yazl");
|
|
25
26
|
const _yauzl = require("yauzl");
|
|
26
27
|
const _app = require("./app");
|
|
27
28
|
const _nodechild_process = require("node:child_process");
|
|
28
|
-
const
|
|
29
|
+
const _satisfies = /*#__PURE__*/ _interop_require_default(require("semver/functions/satisfies"));
|
|
30
|
+
const _nodeos = /*#__PURE__*/ _interop_require_default(require("node:os"));
|
|
29
31
|
function _interop_require_default(obj) {
|
|
30
32
|
return obj && obj.__esModule ? obj : {
|
|
31
33
|
default: obj
|
|
@@ -74,8 +76,9 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
74
76
|
}
|
|
75
77
|
const g2js = require('gradle-to-js/lib/parser');
|
|
76
78
|
const properties = require('properties');
|
|
77
|
-
|
|
78
|
-
let
|
|
79
|
+
let bsdiff;
|
|
80
|
+
let hdiff;
|
|
81
|
+
let diff;
|
|
79
82
|
try {
|
|
80
83
|
bsdiff = require('node-bsdiff').diff;
|
|
81
84
|
} catch (e) {}
|
|
@@ -90,8 +93,8 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
90
93
|
console.warn('android 的 crunchPngs 选项似乎尚未禁用(如已禁用则请忽略此提示),这可能导致热更包体积异常增大,具体请参考 https://pushy.reactnative.cn/docs/getting-started.html#%E7%A6%81%E7%94%A8-android-%E7%9A%84-crunch-%E4%BC%98%E5%8C%96 \n');
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
const reactNativeBundleArgs = [];
|
|
97
|
+
const envArgs = process.env.PUSHY_ENV_ARGS;
|
|
95
98
|
if (envArgs) {
|
|
96
99
|
Array.prototype.push.apply(reactNativeBundleArgs, envArgs.trim().split(/\s+/));
|
|
97
100
|
}
|
|
@@ -104,8 +107,17 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
104
107
|
process.cwd()
|
|
105
108
|
]
|
|
106
109
|
});
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
const expoCliVersion = JSON.parse(_fsextra.readFileSync(require.resolve('@expo/cli/package.json', {
|
|
111
|
+
paths: [
|
|
112
|
+
process.cwd()
|
|
113
|
+
]
|
|
114
|
+
}))).version;
|
|
115
|
+
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
|
|
116
|
+
if ((0, _satisfies.default)(expoCliVersion, '>= 0.10.17')) {
|
|
117
|
+
usingExpo = true;
|
|
118
|
+
}
|
|
119
|
+
} catch (e) {}
|
|
120
|
+
if (!usingExpo) {
|
|
109
121
|
try {
|
|
110
122
|
// rn >= 0.75
|
|
111
123
|
cliPath = require.resolve('@react-native-community/cli/build/bin.js', {
|
|
@@ -123,7 +135,7 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
137
|
const bundleCommand = usingExpo ? 'export:embed' : platform === 'harmony' ? 'bundle-harmony' : 'bundle';
|
|
126
|
-
if (platform
|
|
138
|
+
if (platform === 'harmony') {
|
|
127
139
|
Array.prototype.push.apply(reactNativeBundleArgs, [
|
|
128
140
|
cliPath,
|
|
129
141
|
bundleCommand,
|
|
@@ -145,7 +157,7 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
145
157
|
'--assets-dest',
|
|
146
158
|
outputFolder,
|
|
147
159
|
'--bundle-output',
|
|
148
|
-
|
|
160
|
+
_nodepath.default.join(outputFolder, bundleName),
|
|
149
161
|
'--dev',
|
|
150
162
|
development,
|
|
151
163
|
'--entry-file',
|
|
@@ -179,7 +191,7 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
179
191
|
const gradlePropeties = await new Promise((resolve)=>{
|
|
180
192
|
properties.parse('./android/gradle.properties', {
|
|
181
193
|
path: true
|
|
182
|
-
},
|
|
194
|
+
}, (error, props)=>{
|
|
183
195
|
if (error) {
|
|
184
196
|
console.error(error);
|
|
185
197
|
resolve(null);
|
|
@@ -211,8 +223,8 @@ async function copyHarmonyBundle(outputFolder) {
|
|
|
211
223
|
} catch (error) {
|
|
212
224
|
await _fsextra.chmod(harmonyRawPath, 0o755);
|
|
213
225
|
}
|
|
214
|
-
await _fsextra.remove(
|
|
215
|
-
await _fsextra.copy('update.json',
|
|
226
|
+
await _fsextra.remove(_nodepath.default.join(harmonyRawPath, 'update.json'));
|
|
227
|
+
await _fsextra.copy('update.json', _nodepath.default.join(harmonyRawPath, 'update.json'));
|
|
216
228
|
await _fsextra.ensureDir(outputFolder);
|
|
217
229
|
await _fsextra.copy(harmonyRawPath, outputFolder);
|
|
218
230
|
} catch (error) {
|
|
@@ -221,9 +233,9 @@ async function copyHarmonyBundle(outputFolder) {
|
|
|
221
233
|
}
|
|
222
234
|
}
|
|
223
235
|
function getHermesOSBin() {
|
|
224
|
-
if (
|
|
225
|
-
if (
|
|
226
|
-
if (
|
|
236
|
+
if (_nodeos.default.platform() === 'win32') return 'win64-bin';
|
|
237
|
+
if (_nodeos.default.platform() === 'darwin') return 'osx-bin';
|
|
238
|
+
if (_nodeos.default.platform() === 'linux') return 'linux64-bin';
|
|
227
239
|
}
|
|
228
240
|
async function checkGradleConfig() {
|
|
229
241
|
let enableHermes = false;
|
|
@@ -247,14 +259,14 @@ async function checkGradleConfig() {
|
|
|
247
259
|
};
|
|
248
260
|
}
|
|
249
261
|
async function compileHermesByteCode(bundleName, outputFolder, sourcemapOutput) {
|
|
250
|
-
console.log(
|
|
262
|
+
console.log('Hermes enabled, now compiling to hermes bytecode:\n');
|
|
251
263
|
// >= rn 0.69
|
|
252
|
-
const rnDir =
|
|
264
|
+
const rnDir = _nodepath.default.dirname(require.resolve('react-native', {
|
|
253
265
|
paths: [
|
|
254
266
|
process.cwd()
|
|
255
267
|
]
|
|
256
268
|
}));
|
|
257
|
-
let hermesPath =
|
|
269
|
+
let hermesPath = _nodepath.default.join(rnDir, `/sdks/hermesc/${getHermesOSBin()}`);
|
|
258
270
|
// < rn 0.69
|
|
259
271
|
if (!_fsextra.existsSync(hermesPath)) {
|
|
260
272
|
hermesPath = `node_modules/hermes-engine/${getHermesOSBin()}`;
|
|
@@ -263,15 +275,15 @@ async function compileHermesByteCode(bundleName, outputFolder, sourcemapOutput)
|
|
|
263
275
|
const args = [
|
|
264
276
|
'-emit-binary',
|
|
265
277
|
'-out',
|
|
266
|
-
|
|
267
|
-
|
|
278
|
+
_nodepath.default.join(outputFolder, bundleName),
|
|
279
|
+
_nodepath.default.join(outputFolder, bundleName),
|
|
268
280
|
'-O'
|
|
269
281
|
];
|
|
270
282
|
if (sourcemapOutput) {
|
|
271
|
-
_fsextra.copyFileSync(sourcemapOutput,
|
|
283
|
+
_fsextra.copyFileSync(sourcemapOutput, _nodepath.default.join(outputFolder, `${bundleName}.txt.map`));
|
|
272
284
|
args.push('-output-source-map');
|
|
273
285
|
}
|
|
274
|
-
console.log(
|
|
286
|
+
console.log(`Running hermesc: ${hermesCommand} ${args.join(' ')}`);
|
|
275
287
|
(0, _nodechild_process.spawnSync)(hermesCommand, args, {
|
|
276
288
|
stdio: 'ignore'
|
|
277
289
|
});
|
|
@@ -280,22 +292,22 @@ async function compileHermesByteCode(bundleName, outputFolder, sourcemapOutput)
|
|
|
280
292
|
if (!_fsextra.existsSync(composerPath)) {
|
|
281
293
|
return;
|
|
282
294
|
}
|
|
283
|
-
console.log(
|
|
295
|
+
console.log('Composing source map');
|
|
284
296
|
(0, _nodechild_process.spawnSync)('node', [
|
|
285
297
|
composerPath,
|
|
286
|
-
|
|
287
|
-
|
|
298
|
+
_nodepath.default.join(outputFolder, `${bundleName}.txt.map`),
|
|
299
|
+
_nodepath.default.join(outputFolder, `${bundleName}.map`),
|
|
288
300
|
'-o',
|
|
289
301
|
sourcemapOutput
|
|
290
302
|
], {
|
|
291
303
|
stdio: 'ignore'
|
|
292
304
|
});
|
|
293
305
|
}
|
|
294
|
-
_fsextra.removeSync(
|
|
306
|
+
_fsextra.removeSync(_nodepath.default.join(outputFolder, `${bundleName}.txt.map`));
|
|
295
307
|
}
|
|
296
308
|
async function pack(dir, output) {
|
|
297
309
|
console.log('Packing');
|
|
298
|
-
_fsextra.ensureDirSync(
|
|
310
|
+
_fsextra.ensureDirSync(_nodepath.default.dirname(output));
|
|
299
311
|
await new Promise((resolve, reject)=>{
|
|
300
312
|
const zipfile = new _yazl.ZipFile();
|
|
301
313
|
function addDirectory(root, rel) {
|
|
@@ -307,25 +319,25 @@ async function pack(dir, output) {
|
|
|
307
319
|
if (name === '.' || name === '..' || name === 'index.bundlejs.map') {
|
|
308
320
|
continue;
|
|
309
321
|
}
|
|
310
|
-
const fullPath =
|
|
322
|
+
const fullPath = _nodepath.default.join(root, name);
|
|
311
323
|
const stat = _fsextra.statSync(fullPath);
|
|
312
324
|
if (stat.isFile()) {
|
|
313
325
|
//console.log('adding: ' + rel+name);
|
|
314
326
|
zipfile.addFile(fullPath, rel + name);
|
|
315
327
|
} else if (stat.isDirectory()) {
|
|
316
328
|
//console.log('adding: ' + rel+name+'/');
|
|
317
|
-
addDirectory(fullPath, rel
|
|
329
|
+
addDirectory(fullPath, `${rel}${name}/`);
|
|
318
330
|
}
|
|
319
331
|
}
|
|
320
332
|
}
|
|
321
333
|
addDirectory(dir, '');
|
|
322
334
|
zipfile.outputStream.on('error', (err)=>reject(err));
|
|
323
|
-
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close',
|
|
335
|
+
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close', ()=>{
|
|
324
336
|
resolve();
|
|
325
337
|
});
|
|
326
338
|
zipfile.end();
|
|
327
339
|
});
|
|
328
|
-
console.log(
|
|
340
|
+
console.log(`ppk热更包已生成并保存到: ${output}`);
|
|
329
341
|
}
|
|
330
342
|
function readEntire(entry, zipFile) {
|
|
331
343
|
const buffers = [];
|
|
@@ -348,10 +360,10 @@ function readEntire(entry, zipFile) {
|
|
|
348
360
|
}
|
|
349
361
|
function basename(fn) {
|
|
350
362
|
const m = /^(.+\/)[^\/]+\/?$/.exec(fn);
|
|
351
|
-
return m
|
|
363
|
+
return m == null ? void 0 : m[1];
|
|
352
364
|
}
|
|
353
365
|
async function diffFromPPK(origin, next, output) {
|
|
354
|
-
_fsextra.ensureDirSync(
|
|
366
|
+
_fsextra.ensureDirSync(_nodepath.default.dirname(output));
|
|
355
367
|
const originEntries = {};
|
|
356
368
|
const originMap = {};
|
|
357
369
|
let originSource;
|
|
@@ -367,7 +379,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
367
379
|
}
|
|
368
380
|
});
|
|
369
381
|
if (!originSource) {
|
|
370
|
-
throw new Error(
|
|
382
|
+
throw new Error('Bundle file not found! Please use default bundle file name and path.');
|
|
371
383
|
}
|
|
372
384
|
const copies = {};
|
|
373
385
|
const zipfile = new _yazl.ZipFile();
|
|
@@ -375,7 +387,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
375
387
|
zipfile.outputStream.on('error', (err)=>{
|
|
376
388
|
throw err;
|
|
377
389
|
});
|
|
378
|
-
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close',
|
|
390
|
+
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close', ()=>{
|
|
379
391
|
resolve();
|
|
380
392
|
});
|
|
381
393
|
});
|
|
@@ -432,7 +444,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
432
444
|
// New file.
|
|
433
445
|
addEntry(basename(entry.fileName));
|
|
434
446
|
return new Promise((resolve, reject)=>{
|
|
435
|
-
nextZipfile.openReadStream(entry,
|
|
447
|
+
nextZipfile.openReadStream(entry, (err, readStream)=>{
|
|
436
448
|
if (err) {
|
|
437
449
|
return reject(err);
|
|
438
450
|
}
|
|
@@ -446,9 +458,9 @@ async function diffFromPPK(origin, next, output) {
|
|
|
446
458
|
}
|
|
447
459
|
});
|
|
448
460
|
const deletes = {};
|
|
449
|
-
for(
|
|
461
|
+
for(const k in originEntries){
|
|
450
462
|
if (!newEntries[k]) {
|
|
451
|
-
console.log(
|
|
463
|
+
console.log(`Delete ${k}`);
|
|
452
464
|
deletes[k] = 1;
|
|
453
465
|
}
|
|
454
466
|
}
|
|
@@ -461,7 +473,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
461
473
|
await writePromise;
|
|
462
474
|
}
|
|
463
475
|
async function diffFromPackage(origin, next, output, originBundleName, transformPackagePath = (v)=>v) {
|
|
464
|
-
_fsextra.ensureDirSync(
|
|
476
|
+
_fsextra.ensureDirSync(_nodepath.default.dirname(output));
|
|
465
477
|
const originEntries = {};
|
|
466
478
|
const originMap = {};
|
|
467
479
|
let originSource;
|
|
@@ -482,7 +494,7 @@ async function diffFromPackage(origin, next, output, originBundleName, transform
|
|
|
482
494
|
}
|
|
483
495
|
});
|
|
484
496
|
if (!originSource) {
|
|
485
|
-
throw new Error(
|
|
497
|
+
throw new Error('Bundle file not found! Please use default bundle file name and path.');
|
|
486
498
|
}
|
|
487
499
|
const copies = {};
|
|
488
500
|
const zipfile = new _yazl.ZipFile();
|
|
@@ -490,7 +502,7 @@ async function diffFromPackage(origin, next, output, originBundleName, transform
|
|
|
490
502
|
zipfile.outputStream.on('error', (err)=>{
|
|
491
503
|
throw err;
|
|
492
504
|
});
|
|
493
|
-
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close',
|
|
505
|
+
zipfile.outputStream.pipe(_fsextra.createWriteStream(output)).on('close', ()=>{
|
|
494
506
|
resolve();
|
|
495
507
|
});
|
|
496
508
|
});
|
|
@@ -524,7 +536,7 @@ async function diffFromPackage(origin, next, output, originBundleName, transform
|
|
|
524
536
|
return;
|
|
525
537
|
}
|
|
526
538
|
return new Promise((resolve, reject)=>{
|
|
527
|
-
nextZipfile.openReadStream(entry,
|
|
539
|
+
nextZipfile.openReadStream(entry, (err, readStream)=>{
|
|
528
540
|
if (err) {
|
|
529
541
|
return reject(err);
|
|
530
542
|
}
|
|
@@ -557,9 +569,9 @@ async function enumZipEntries(zipFn, callback, nestedPath = '') {
|
|
|
557
569
|
const fullPath = nestedPath + entry.fileName;
|
|
558
570
|
try {
|
|
559
571
|
if (!entry.fileName.endsWith('/') && entry.fileName.toLowerCase().endsWith('.hap')) {
|
|
560
|
-
const tempDir =
|
|
572
|
+
const tempDir = _nodepath.default.join(_nodeos.default.tmpdir(), `nested_zip_${Date.now()}`);
|
|
561
573
|
await _fsextra.ensureDir(tempDir);
|
|
562
|
-
const tempZipPath =
|
|
574
|
+
const tempZipPath = _nodepath.default.join(tempDir, 'temp.zip');
|
|
563
575
|
await new Promise((res, rej)=>{
|
|
564
576
|
zipfile.openReadStream(entry, async (err, readStream)=>{
|
|
565
577
|
if (err) return rej(err);
|
|
@@ -569,7 +581,7 @@ async function enumZipEntries(zipFn, callback, nestedPath = '') {
|
|
|
569
581
|
writeStream.on('error', rej);
|
|
570
582
|
});
|
|
571
583
|
});
|
|
572
|
-
await enumZipEntries(tempZipPath, callback, fullPath
|
|
584
|
+
await enumZipEntries(tempZipPath, callback, `${fullPath}/`);
|
|
573
585
|
await _fsextra.remove(tempDir);
|
|
574
586
|
}
|
|
575
587
|
const result = callback(entry, zipfile, fullPath);
|
|
@@ -610,25 +622,25 @@ function diffArgsCheck(args, options, diffFn) {
|
|
|
610
622
|
return {
|
|
611
623
|
origin,
|
|
612
624
|
next,
|
|
613
|
-
realOutput: output.replace(/\$\{time\}/g,
|
|
625
|
+
realOutput: output.replace(/\$\{time\}/g, `${Date.now()}`)
|
|
614
626
|
};
|
|
615
627
|
}
|
|
616
628
|
const commands = {
|
|
617
629
|
bundle: async function({ options }) {
|
|
618
630
|
const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
|
|
619
|
-
|
|
631
|
+
const { bundleName, entryFile, intermediaDir, output, dev, sourcemap } = (0, _utils.translateOptions)({
|
|
620
632
|
...options,
|
|
621
633
|
platform
|
|
622
634
|
});
|
|
623
|
-
const sourcemapOutput =
|
|
624
|
-
const realOutput = output.replace(/\$\{time\}/g,
|
|
635
|
+
const sourcemapOutput = _nodepath.default.join(intermediaDir, `${bundleName}.map`);
|
|
636
|
+
const realOutput = output.replace(/\$\{time\}/g, `${Date.now()}`);
|
|
625
637
|
if (!platform) {
|
|
626
638
|
throw new Error('Platform must be specified.');
|
|
627
639
|
}
|
|
628
640
|
const { version, major, minor } = (0, _utils.getRNVersion)();
|
|
629
|
-
console.log(
|
|
641
|
+
console.log(`Bundling with react-native: ${version}`);
|
|
630
642
|
await runReactNativeBundleCommand(bundleName, dev, entryFile, intermediaDir, platform, sourcemap ? sourcemapOutput : '');
|
|
631
|
-
await pack(
|
|
643
|
+
await pack(_nodepath.default.resolve(intermediaDir), realOutput);
|
|
632
644
|
const v = await (0, _utils.question)('是否现在上传此热更包?(Y/N)');
|
|
633
645
|
if (v.toLowerCase() === 'y') {
|
|
634
646
|
await this.publish({
|
|
@@ -670,7 +682,7 @@ const commands = {
|
|
|
670
682
|
const { origin, next, realOutput } = diffArgsCheck(args, options, 'diffFromIpa');
|
|
671
683
|
await diffFromPackage(origin, next, realOutput, 'main.jsbundle', (v)=>{
|
|
672
684
|
const m = /^Payload\/[^/]+\/(.+)$/.exec(v);
|
|
673
|
-
return m
|
|
685
|
+
return m == null ? void 0 : m[1];
|
|
674
686
|
});
|
|
675
687
|
console.log(`${realOutput} generated.`);
|
|
676
688
|
},
|
|
@@ -678,7 +690,7 @@ const commands = {
|
|
|
678
690
|
const { origin, next, realOutput } = diffArgsCheck(args, options, 'hdiffFromIpa');
|
|
679
691
|
await diffFromPackage(origin, next, realOutput, 'main.jsbundle', (v)=>{
|
|
680
692
|
const m = /^Payload\/[^/]+\/(.+)$/.exec(v);
|
|
681
|
-
return m
|
|
693
|
+
return m == null ? void 0 : m[1];
|
|
682
694
|
});
|
|
683
695
|
console.log(`${realOutput} generated.`);
|
|
684
696
|
}
|
package/lib/package.js
CHANGED
|
@@ -68,14 +68,14 @@ async function choosePackage(appId) {
|
|
|
68
68
|
const list = await listPackage(appId);
|
|
69
69
|
while(true){
|
|
70
70
|
const id = await (0, _utils.question)('输入原生包 id:');
|
|
71
|
-
const app = list.find((v)=>v.id === (id
|
|
71
|
+
const app = list.find((v)=>v.id === Number(id));
|
|
72
72
|
if (app) {
|
|
73
73
|
return app;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
const commands = {
|
|
78
|
-
uploadIpa: async
|
|
78
|
+
uploadIpa: async ({ args })=>{
|
|
79
79
|
const fn = args[0];
|
|
80
80
|
if (!fn || !fn.endsWith('.ipa')) {
|
|
81
81
|
throw new Error('使用方法: pushy uploadIpa ipa后缀文件');
|
|
@@ -97,7 +97,7 @@ const commands = {
|
|
|
97
97
|
(0, _utils.saveToLocal)(fn, `${appId}/package/${id}.ipa`);
|
|
98
98
|
console.log(`已成功上传ipa原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`);
|
|
99
99
|
},
|
|
100
|
-
uploadApk: async
|
|
100
|
+
uploadApk: async ({ args })=>{
|
|
101
101
|
const fn = args[0];
|
|
102
102
|
if (!fn || !fn.endsWith('.apk')) {
|
|
103
103
|
throw new Error('使用方法: pushy uploadApk apk后缀文件');
|
|
@@ -119,7 +119,7 @@ const commands = {
|
|
|
119
119
|
(0, _utils.saveToLocal)(fn, `${appId}/package/${id}.apk`);
|
|
120
120
|
console.log(`已成功上传apk原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`);
|
|
121
121
|
},
|
|
122
|
-
uploadApp: async
|
|
122
|
+
uploadApp: async ({ args })=>{
|
|
123
123
|
const fn = args[0];
|
|
124
124
|
if (!fn || !fn.endsWith('.app')) {
|
|
125
125
|
throw new Error('使用方法: pushy uploadApp app后缀文件');
|
|
@@ -141,28 +141,28 @@ const commands = {
|
|
|
141
141
|
(0, _utils.saveToLocal)(fn, `${appId}/package/${id}.app`);
|
|
142
142
|
console.log(`已成功上传app原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`);
|
|
143
143
|
},
|
|
144
|
-
parseApp: async
|
|
144
|
+
parseApp: async ({ args })=>{
|
|
145
145
|
const fn = args[0];
|
|
146
146
|
if (!fn || !fn.endsWith('.app')) {
|
|
147
147
|
throw new Error('使用方法: pushy parseApp app后缀文件');
|
|
148
148
|
}
|
|
149
149
|
console.log(await (0, _utils.getAppInfo)(fn));
|
|
150
150
|
},
|
|
151
|
-
parseIpa: async
|
|
151
|
+
parseIpa: async ({ args })=>{
|
|
152
152
|
const fn = args[0];
|
|
153
153
|
if (!fn || !fn.endsWith('.ipa')) {
|
|
154
154
|
throw new Error('使用方法: pushy parseIpa ipa后缀文件');
|
|
155
155
|
}
|
|
156
156
|
console.log(await (0, _utils.getIpaInfo)(fn));
|
|
157
157
|
},
|
|
158
|
-
parseApk: async
|
|
158
|
+
parseApk: async ({ args })=>{
|
|
159
159
|
const fn = args[0];
|
|
160
160
|
if (!fn || !fn.endsWith('.apk')) {
|
|
161
161
|
throw new Error('使用方法: pushy parseApk apk后缀文件');
|
|
162
162
|
}
|
|
163
163
|
console.log(await (0, _utils.getApkInfo)(fn));
|
|
164
164
|
},
|
|
165
|
-
packages: async
|
|
165
|
+
packages: async ({ options })=>{
|
|
166
166
|
const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
|
|
167
167
|
const { appId } = await (0, _app.getSelectedApp)(platform);
|
|
168
168
|
await listPackage(appId);
|
package/lib/utils/index.js
CHANGED
|
@@ -63,12 +63,10 @@ async function question(query, password) {
|
|
|
63
63
|
}
|
|
64
64
|
function translateOptions(options) {
|
|
65
65
|
const ret = {};
|
|
66
|
-
for(
|
|
66
|
+
for(const key in options){
|
|
67
67
|
const v = options[key];
|
|
68
68
|
if (typeof v === 'string') {
|
|
69
|
-
ret[key] = v.replace(/\$\{(\w+)\}/g,
|
|
70
|
-
return options[n] || process.env[n] || v;
|
|
71
|
-
});
|
|
69
|
+
ret[key] = v.replace(/\$\{(\w+)\}/g, (v, n)=>options[n] || process.env[n] || v);
|
|
72
70
|
} else {
|
|
73
71
|
ret[key] = v;
|
|
74
72
|
}
|
|
@@ -215,7 +213,7 @@ async function printVersionCommand() {
|
|
|
215
213
|
console.warn(`当前版本已不再支持,请至少升级到 v9 的最新小版本后重新打包(代码无需改动,可直接热更): npm i react-native-update@9 .
|
|
216
214
|
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`);
|
|
217
215
|
} else if ((0, _satisfies.default)(pushyVersion, '10.0.0 - 10.17.0')) {
|
|
218
|
-
console.warn(
|
|
216
|
+
console.warn('当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10');
|
|
219
217
|
}
|
|
220
218
|
}
|
|
221
219
|
}
|
package/package.json
CHANGED
package/src/{app.js → app.ts}
RENAMED
|
@@ -3,6 +3,7 @@ import fs from 'node:fs';
|
|
|
3
3
|
import Table from 'tty-table';
|
|
4
4
|
|
|
5
5
|
import { post, get, doDelete } from './api';
|
|
6
|
+
import type { Platform } from './types';
|
|
6
7
|
|
|
7
8
|
const validPlatforms = {
|
|
8
9
|
ios: 1,
|
|
@@ -10,14 +11,14 @@ const validPlatforms = {
|
|
|
10
11
|
harmony: 1,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
|
-
export function checkPlatform(platform) {
|
|
14
|
+
export function checkPlatform(platform: Platform) {
|
|
14
15
|
if (!validPlatforms[platform]) {
|
|
15
16
|
throw new Error(`无法识别的平台 '${platform}'`);
|
|
16
17
|
}
|
|
17
18
|
return platform;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export function getSelectedApp(platform) {
|
|
21
|
+
export function getSelectedApp(platform: Platform) {
|
|
21
22
|
checkPlatform(platform);
|
|
22
23
|
|
|
23
24
|
if (!fs.existsSync('update.json')) {
|
|
@@ -34,7 +35,7 @@ export function getSelectedApp(platform) {
|
|
|
34
35
|
return updateInfo[platform];
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
export async function listApp(platform) {
|
|
38
|
+
export async function listApp(platform: Platform) {
|
|
38
39
|
const { data } = await get('/app/list');
|
|
39
40
|
const list = platform ? data.filter((v) => v.platform === platform) : data;
|
|
40
41
|
|
|
@@ -58,12 +59,12 @@ export async function listApp(platform) {
|
|
|
58
59
|
return list;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
export async function chooseApp(platform) {
|
|
62
|
+
export async function chooseApp(platform: Platform) {
|
|
62
63
|
const list = await listApp(platform);
|
|
63
64
|
|
|
64
65
|
while (true) {
|
|
65
66
|
const id = await question('输入应用 id:');
|
|
66
|
-
const app = list.find((v) => v.id === (id
|
|
67
|
+
const app = list.find((v) => v.id === Number(id));
|
|
67
68
|
if (app) {
|
|
68
69
|
return app;
|
|
69
70
|
}
|
package/src/bundle.js
CHANGED
|
@@ -6,12 +6,14 @@ import { open as openZipFile } from 'yauzl';
|
|
|
6
6
|
import { question, printVersionCommand } from './utils';
|
|
7
7
|
import { checkPlatform } from './app';
|
|
8
8
|
import { spawn, spawnSync } from 'node:child_process';
|
|
9
|
+
import semverSatisfies from 'semver/functions/satisfies';
|
|
9
10
|
const g2js = require('gradle-to-js/lib/parser');
|
|
10
|
-
import os from 'os';
|
|
11
|
+
import os from 'node:os';
|
|
11
12
|
const properties = require('properties');
|
|
12
|
-
const path = require('path');
|
|
13
13
|
|
|
14
|
-
let bsdiff
|
|
14
|
+
let bsdiff;
|
|
15
|
+
let hdiff;
|
|
16
|
+
let diff;
|
|
15
17
|
try {
|
|
16
18
|
bsdiff = require('node-bsdiff').diff;
|
|
17
19
|
} catch (e) {}
|
|
@@ -39,9 +41,9 @@ async function runReactNativeBundleCommand(
|
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
const reactNativeBundleArgs = [];
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
const envArgs = process.env.PUSHY_ENV_ARGS;
|
|
45
47
|
|
|
46
48
|
if (envArgs) {
|
|
47
49
|
Array.prototype.push.apply(
|
|
@@ -59,8 +61,19 @@ async function runReactNativeBundleCommand(
|
|
|
59
61
|
cliPath = require.resolve('@expo/cli', {
|
|
60
62
|
paths: [process.cwd()],
|
|
61
63
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
const expoCliVersion = JSON.parse(
|
|
65
|
+
fs.readFileSync(
|
|
66
|
+
require.resolve('@expo/cli/package.json', {
|
|
67
|
+
paths: [process.cwd()],
|
|
68
|
+
}),
|
|
69
|
+
),
|
|
70
|
+
).version;
|
|
71
|
+
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
|
|
72
|
+
if (semverSatisfies(expoCliVersion, '>= 0.10.17')) {
|
|
73
|
+
usingExpo = true;
|
|
74
|
+
}
|
|
75
|
+
} catch (e) {}
|
|
76
|
+
if (!usingExpo) {
|
|
64
77
|
try {
|
|
65
78
|
// rn >= 0.75
|
|
66
79
|
cliPath = require.resolve('@react-native-community/cli/build/bin.js', {
|
|
@@ -73,8 +86,12 @@ async function runReactNativeBundleCommand(
|
|
|
73
86
|
});
|
|
74
87
|
}
|
|
75
88
|
}
|
|
76
|
-
const bundleCommand = usingExpo
|
|
77
|
-
|
|
89
|
+
const bundleCommand = usingExpo
|
|
90
|
+
? 'export:embed'
|
|
91
|
+
: platform === 'harmony'
|
|
92
|
+
? 'bundle-harmony'
|
|
93
|
+
: 'bundle';
|
|
94
|
+
if (platform === 'harmony') {
|
|
78
95
|
Array.prototype.push.apply(reactNativeBundleArgs, [
|
|
79
96
|
cliPath,
|
|
80
97
|
bundleCommand,
|
|
@@ -91,8 +108,7 @@ async function runReactNativeBundleCommand(
|
|
|
91
108
|
if (config) {
|
|
92
109
|
reactNativeBundleArgs.push('--config', config);
|
|
93
110
|
}
|
|
94
|
-
}
|
|
95
|
-
else{
|
|
111
|
+
} else {
|
|
96
112
|
Array.prototype.push.apply(reactNativeBundleArgs, [
|
|
97
113
|
cliPath,
|
|
98
114
|
bundleCommand,
|
|
@@ -108,16 +124,16 @@ async function runReactNativeBundleCommand(
|
|
|
108
124
|
platform,
|
|
109
125
|
'--reset-cache',
|
|
110
126
|
]);
|
|
111
|
-
|
|
127
|
+
|
|
112
128
|
if (sourcemapOutput) {
|
|
113
129
|
reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
|
|
114
130
|
}
|
|
115
|
-
|
|
131
|
+
|
|
116
132
|
if (config) {
|
|
117
133
|
reactNativeBundleArgs.push('--config', config);
|
|
118
134
|
}
|
|
119
135
|
}
|
|
120
|
-
|
|
136
|
+
|
|
121
137
|
const reactNativeBundleProcess = spawn('node', reactNativeBundleArgs);
|
|
122
138
|
console.log(
|
|
123
139
|
`Running bundle command: node ${reactNativeBundleArgs.join(' ')}`,
|
|
@@ -147,7 +163,7 @@ async function runReactNativeBundleCommand(
|
|
|
147
163
|
properties.parse(
|
|
148
164
|
'./android/gradle.properties',
|
|
149
165
|
{ path: true },
|
|
150
|
-
|
|
166
|
+
(error, props) => {
|
|
151
167
|
if (error) {
|
|
152
168
|
console.error(error);
|
|
153
169
|
resolve(null);
|
|
@@ -166,7 +182,7 @@ async function runReactNativeBundleCommand(
|
|
|
166
182
|
fs.existsSync('ios/Pods/hermes-engine')
|
|
167
183
|
) {
|
|
168
184
|
hermesEnabled = true;
|
|
169
|
-
}else if (platform === 'harmony') {
|
|
185
|
+
} else if (platform === 'harmony') {
|
|
170
186
|
await copyHarmonyBundle(outputFolder);
|
|
171
187
|
}
|
|
172
188
|
if (hermesEnabled) {
|
|
@@ -193,7 +209,7 @@ async function copyHarmonyBundle(outputFolder) {
|
|
|
193
209
|
}
|
|
194
210
|
await fs.remove(path.join(harmonyRawPath, 'update.json'));
|
|
195
211
|
await fs.copy('update.json', path.join(harmonyRawPath, 'update.json'));
|
|
196
|
-
|
|
212
|
+
|
|
197
213
|
await fs.ensureDir(outputFolder);
|
|
198
214
|
await fs.copy(harmonyRawPath, outputFolder);
|
|
199
215
|
} catch (error) {
|
|
@@ -238,7 +254,7 @@ async function compileHermesByteCode(
|
|
|
238
254
|
outputFolder,
|
|
239
255
|
sourcemapOutput,
|
|
240
256
|
) {
|
|
241
|
-
console.log(
|
|
257
|
+
console.log('Hermes enabled, now compiling to hermes bytecode:\n');
|
|
242
258
|
// >= rn 0.69
|
|
243
259
|
const rnDir = path.dirname(
|
|
244
260
|
require.resolve('react-native', {
|
|
@@ -264,13 +280,11 @@ async function compileHermesByteCode(
|
|
|
264
280
|
if (sourcemapOutput) {
|
|
265
281
|
fs.copyFileSync(
|
|
266
282
|
sourcemapOutput,
|
|
267
|
-
path.join(outputFolder, bundleName
|
|
283
|
+
path.join(outputFolder, `${bundleName}.txt.map`),
|
|
268
284
|
);
|
|
269
285
|
args.push('-output-source-map');
|
|
270
286
|
}
|
|
271
|
-
console.log(
|
|
272
|
-
'Running hermesc: ' + hermesCommand + ' ' + args.join(' ') + '\n',
|
|
273
|
-
);
|
|
287
|
+
console.log(`Running hermesc: ${hermesCommand} ${args.join(' ')}`);
|
|
274
288
|
spawnSync(hermesCommand, args, {
|
|
275
289
|
stdio: 'ignore',
|
|
276
290
|
});
|
|
@@ -280,13 +294,13 @@ async function compileHermesByteCode(
|
|
|
280
294
|
if (!fs.existsSync(composerPath)) {
|
|
281
295
|
return;
|
|
282
296
|
}
|
|
283
|
-
console.log(
|
|
297
|
+
console.log('Composing source map');
|
|
284
298
|
spawnSync(
|
|
285
299
|
'node',
|
|
286
300
|
[
|
|
287
301
|
composerPath,
|
|
288
|
-
path.join(outputFolder, bundleName
|
|
289
|
-
path.join(outputFolder, bundleName
|
|
302
|
+
path.join(outputFolder, `${bundleName}.txt.map`),
|
|
303
|
+
path.join(outputFolder, `${bundleName}.map`),
|
|
290
304
|
'-o',
|
|
291
305
|
sourcemapOutput,
|
|
292
306
|
],
|
|
@@ -295,7 +309,7 @@ async function compileHermesByteCode(
|
|
|
295
309
|
},
|
|
296
310
|
);
|
|
297
311
|
}
|
|
298
|
-
fs.removeSync(path.join(outputFolder, bundleName
|
|
312
|
+
fs.removeSync(path.join(outputFolder, `${bundleName}.txt.map`));
|
|
299
313
|
}
|
|
300
314
|
|
|
301
315
|
async function pack(dir, output) {
|
|
@@ -320,7 +334,7 @@ async function pack(dir, output) {
|
|
|
320
334
|
zipfile.addFile(fullPath, rel + name);
|
|
321
335
|
} else if (stat.isDirectory()) {
|
|
322
336
|
//console.log('adding: ' + rel+name+'/');
|
|
323
|
-
addDirectory(fullPath, rel
|
|
337
|
+
addDirectory(fullPath, `${rel}${name}/`);
|
|
324
338
|
}
|
|
325
339
|
}
|
|
326
340
|
}
|
|
@@ -328,14 +342,12 @@ async function pack(dir, output) {
|
|
|
328
342
|
addDirectory(dir, '');
|
|
329
343
|
|
|
330
344
|
zipfile.outputStream.on('error', (err) => reject(err));
|
|
331
|
-
zipfile.outputStream
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
resolve();
|
|
335
|
-
});
|
|
345
|
+
zipfile.outputStream.pipe(fs.createWriteStream(output)).on('close', () => {
|
|
346
|
+
resolve();
|
|
347
|
+
});
|
|
336
348
|
zipfile.end();
|
|
337
349
|
});
|
|
338
|
-
console.log(
|
|
350
|
+
console.log(`ppk热更包已生成并保存到: ${output}`);
|
|
339
351
|
}
|
|
340
352
|
|
|
341
353
|
export function readEntire(entry, zipFile) {
|
|
@@ -360,7 +372,7 @@ export function readEntire(entry, zipFile) {
|
|
|
360
372
|
|
|
361
373
|
function basename(fn) {
|
|
362
374
|
const m = /^(.+\/)[^\/]+\/?$/.exec(fn);
|
|
363
|
-
return m
|
|
375
|
+
return m?.[1];
|
|
364
376
|
}
|
|
365
377
|
|
|
366
378
|
async function diffFromPPK(origin, next, output) {
|
|
@@ -377,7 +389,10 @@ async function diffFromPPK(origin, next, output) {
|
|
|
377
389
|
// isFile
|
|
378
390
|
originMap[entry.crc32] = entry.fileName;
|
|
379
391
|
|
|
380
|
-
if (
|
|
392
|
+
if (
|
|
393
|
+
entry.fileName === 'index.bundlejs' ||
|
|
394
|
+
entry.fileName === 'bundle.harmony.js'
|
|
395
|
+
) {
|
|
381
396
|
// This is source.
|
|
382
397
|
return readEntire(entry, zipFile).then((v) => (originSource = v));
|
|
383
398
|
}
|
|
@@ -386,7 +401,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
386
401
|
|
|
387
402
|
if (!originSource) {
|
|
388
403
|
throw new Error(
|
|
389
|
-
|
|
404
|
+
'Bundle file not found! Please use default bundle file name and path.',
|
|
390
405
|
);
|
|
391
406
|
}
|
|
392
407
|
|
|
@@ -398,11 +413,9 @@ async function diffFromPPK(origin, next, output) {
|
|
|
398
413
|
zipfile.outputStream.on('error', (err) => {
|
|
399
414
|
throw err;
|
|
400
415
|
});
|
|
401
|
-
zipfile.outputStream
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
resolve();
|
|
405
|
-
});
|
|
416
|
+
zipfile.outputStream.pipe(fs.createWriteStream(output)).on('close', () => {
|
|
417
|
+
resolve();
|
|
418
|
+
});
|
|
406
419
|
});
|
|
407
420
|
|
|
408
421
|
const addedEntry = {};
|
|
@@ -439,7 +452,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
439
452
|
);
|
|
440
453
|
//console.log('End diff');
|
|
441
454
|
});
|
|
442
|
-
}else if (entry.fileName === 'bundle.harmony.js') {
|
|
455
|
+
} else if (entry.fileName === 'bundle.harmony.js') {
|
|
443
456
|
//console.log('Found bundle');
|
|
444
457
|
return readEntire(entry, nextZipfile).then((newSource) => {
|
|
445
458
|
//console.log('Begin diff');
|
|
@@ -471,7 +484,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
471
484
|
addEntry(basename(entry.fileName));
|
|
472
485
|
|
|
473
486
|
return new Promise((resolve, reject) => {
|
|
474
|
-
nextZipfile.openReadStream(entry,
|
|
487
|
+
nextZipfile.openReadStream(entry, (err, readStream) => {
|
|
475
488
|
if (err) {
|
|
476
489
|
return reject(err);
|
|
477
490
|
}
|
|
@@ -487,9 +500,9 @@ async function diffFromPPK(origin, next, output) {
|
|
|
487
500
|
|
|
488
501
|
const deletes = {};
|
|
489
502
|
|
|
490
|
-
for (
|
|
503
|
+
for (const k in originEntries) {
|
|
491
504
|
if (!newEntries[k]) {
|
|
492
|
-
console.log(
|
|
505
|
+
console.log(`Delete ${k}`);
|
|
493
506
|
deletes[k] = 1;
|
|
494
507
|
}
|
|
495
508
|
}
|
|
@@ -538,7 +551,7 @@ async function diffFromPackage(
|
|
|
538
551
|
|
|
539
552
|
if (!originSource) {
|
|
540
553
|
throw new Error(
|
|
541
|
-
|
|
554
|
+
'Bundle file not found! Please use default bundle file name and path.',
|
|
542
555
|
);
|
|
543
556
|
}
|
|
544
557
|
|
|
@@ -550,11 +563,9 @@ async function diffFromPackage(
|
|
|
550
563
|
zipfile.outputStream.on('error', (err) => {
|
|
551
564
|
throw err;
|
|
552
565
|
});
|
|
553
|
-
zipfile.outputStream
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
resolve();
|
|
557
|
-
});
|
|
566
|
+
zipfile.outputStream.pipe(fs.createWriteStream(output)).on('close', () => {
|
|
567
|
+
resolve();
|
|
568
|
+
});
|
|
558
569
|
});
|
|
559
570
|
|
|
560
571
|
await enumZipEntries(next, (entry, nextZipfile) => {
|
|
@@ -581,7 +592,7 @@ async function diffFromPackage(
|
|
|
581
592
|
);
|
|
582
593
|
//console.log('End diff');
|
|
583
594
|
});
|
|
584
|
-
}else {
|
|
595
|
+
} else {
|
|
585
596
|
// If same file.
|
|
586
597
|
if (originEntries[entry.fileName] === entry.crc32) {
|
|
587
598
|
copies[entry.fileName] = '';
|
|
@@ -594,7 +605,7 @@ async function diffFromPackage(
|
|
|
594
605
|
}
|
|
595
606
|
|
|
596
607
|
return new Promise((resolve, reject) => {
|
|
597
|
-
nextZipfile.openReadStream(entry,
|
|
608
|
+
nextZipfile.openReadStream(entry, (err, readStream) => {
|
|
598
609
|
if (err) {
|
|
599
610
|
return reject(err);
|
|
600
611
|
}
|
|
@@ -630,7 +641,7 @@ export async function enumZipEntries(zipFn, callback, nestedPath = '') {
|
|
|
630
641
|
!entry.fileName.endsWith('/') &&
|
|
631
642
|
entry.fileName.toLowerCase().endsWith('.hap')
|
|
632
643
|
) {
|
|
633
|
-
const tempDir = path.join(os.tmpdir(),
|
|
644
|
+
const tempDir = path.join(os.tmpdir(), `nested_zip_${Date.now()}`);
|
|
634
645
|
await fs.ensureDir(tempDir);
|
|
635
646
|
const tempZipPath = path.join(tempDir, 'temp.zip');
|
|
636
647
|
|
|
@@ -644,7 +655,7 @@ export async function enumZipEntries(zipFn, callback, nestedPath = '') {
|
|
|
644
655
|
});
|
|
645
656
|
});
|
|
646
657
|
|
|
647
|
-
await enumZipEntries(tempZipPath, callback, fullPath
|
|
658
|
+
await enumZipEntries(tempZipPath, callback, `${fullPath}/`);
|
|
648
659
|
|
|
649
660
|
await fs.remove(tempDir);
|
|
650
661
|
}
|
|
@@ -697,7 +708,7 @@ function diffArgsCheck(args, options, diffFn) {
|
|
|
697
708
|
return {
|
|
698
709
|
origin,
|
|
699
710
|
next,
|
|
700
|
-
realOutput: output.replace(/\$\{time\}/g,
|
|
711
|
+
realOutput: output.replace(/\$\{time\}/g, `${Date.now()}`),
|
|
701
712
|
};
|
|
702
713
|
}
|
|
703
714
|
|
|
@@ -707,15 +718,15 @@ export const commands = {
|
|
|
707
718
|
options.platform || (await question('平台(ios/android/harmony):')),
|
|
708
719
|
);
|
|
709
720
|
|
|
710
|
-
|
|
721
|
+
const { bundleName, entryFile, intermediaDir, output, dev, sourcemap } =
|
|
711
722
|
translateOptions({
|
|
712
723
|
...options,
|
|
713
724
|
platform,
|
|
714
725
|
});
|
|
715
726
|
|
|
716
|
-
const sourcemapOutput = path.join(intermediaDir, bundleName
|
|
727
|
+
const sourcemapOutput = path.join(intermediaDir, `${bundleName}.map`);
|
|
717
728
|
|
|
718
|
-
const realOutput = output.replace(/\$\{time\}/g,
|
|
729
|
+
const realOutput = output.replace(/\$\{time\}/g, `${Date.now()}`);
|
|
719
730
|
|
|
720
731
|
if (!platform) {
|
|
721
732
|
throw new Error('Platform must be specified.');
|
|
@@ -723,7 +734,7 @@ export const commands = {
|
|
|
723
734
|
|
|
724
735
|
const { version, major, minor } = getRNVersion();
|
|
725
736
|
|
|
726
|
-
console.log(
|
|
737
|
+
console.log(`Bundling with react-native: ${version}`);
|
|
727
738
|
|
|
728
739
|
await runReactNativeBundleCommand(
|
|
729
740
|
bundleName,
|
|
@@ -817,7 +828,7 @@ export const commands = {
|
|
|
817
828
|
|
|
818
829
|
await diffFromPackage(origin, next, realOutput, 'main.jsbundle', (v) => {
|
|
819
830
|
const m = /^Payload\/[^/]+\/(.+)$/.exec(v);
|
|
820
|
-
return m
|
|
831
|
+
return m?.[1];
|
|
821
832
|
});
|
|
822
833
|
|
|
823
834
|
console.log(`${realOutput} generated.`);
|
|
@@ -832,7 +843,7 @@ export const commands = {
|
|
|
832
843
|
|
|
833
844
|
await diffFromPackage(origin, next, realOutput, 'main.jsbundle', (v) => {
|
|
834
845
|
const m = /^Payload\/[^/]+\/(.+)$/.exec(v);
|
|
835
|
-
return m
|
|
846
|
+
return m?.[1];
|
|
836
847
|
});
|
|
837
848
|
|
|
838
849
|
console.log(`${realOutput} generated.`);
|
|
@@ -6,7 +6,7 @@ import { checkPlatform, getSelectedApp } from './app';
|
|
|
6
6
|
import { getApkInfo, getIpaInfo, getAppInfo } from './utils';
|
|
7
7
|
import Table from 'tty-table';
|
|
8
8
|
|
|
9
|
-
export async function listPackage(appId) {
|
|
9
|
+
export async function listPackage(appId: string) {
|
|
10
10
|
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
|
|
11
11
|
|
|
12
12
|
const header = [{ value: '原生包 Id' }, { value: '原生版本' }];
|
|
@@ -35,12 +35,12 @@ export async function listPackage(appId) {
|
|
|
35
35
|
return data;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export async function choosePackage(appId) {
|
|
38
|
+
export async function choosePackage(appId: string) {
|
|
39
39
|
const list = await listPackage(appId);
|
|
40
40
|
|
|
41
41
|
while (true) {
|
|
42
42
|
const id = await question('输入原生包 id:');
|
|
43
|
-
const app = list.find((v) => v.id === (id
|
|
43
|
+
const app = list.find((v) => v.id === Number(id));
|
|
44
44
|
if (app) {
|
|
45
45
|
return app;
|
|
46
46
|
}
|
|
@@ -48,7 +48,7 @@ export async function choosePackage(appId) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export const commands = {
|
|
51
|
-
uploadIpa: async
|
|
51
|
+
uploadIpa: async ({ args }: { args: string[] }) => {
|
|
52
52
|
const fn = args[0];
|
|
53
53
|
if (!fn || !fn.endsWith('.ipa')) {
|
|
54
54
|
throw new Error('使用方法: pushy uploadIpa ipa后缀文件');
|
|
@@ -85,7 +85,7 @@ export const commands = {
|
|
|
85
85
|
`已成功上传ipa原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`,
|
|
86
86
|
);
|
|
87
87
|
},
|
|
88
|
-
uploadApk: async
|
|
88
|
+
uploadApk: async ({ args }) => {
|
|
89
89
|
const fn = args[0];
|
|
90
90
|
if (!fn || !fn.endsWith('.apk')) {
|
|
91
91
|
throw new Error('使用方法: pushy uploadApk apk后缀文件');
|
|
@@ -122,7 +122,7 @@ export const commands = {
|
|
|
122
122
|
`已成功上传apk原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`,
|
|
123
123
|
);
|
|
124
124
|
},
|
|
125
|
-
uploadApp: async
|
|
125
|
+
uploadApp: async ({ args }) => {
|
|
126
126
|
const fn = args[0];
|
|
127
127
|
if (!fn || !fn.endsWith('.app')) {
|
|
128
128
|
throw new Error('使用方法: pushy uploadApp app后缀文件');
|
|
@@ -134,7 +134,6 @@ export const commands = {
|
|
|
134
134
|
appKey: appKeyInPkg,
|
|
135
135
|
} = await getAppInfo(fn);
|
|
136
136
|
const { appId, appKey } = await getSelectedApp('harmony');
|
|
137
|
-
|
|
138
137
|
|
|
139
138
|
if (appIdInPkg && appIdInPkg != appId) {
|
|
140
139
|
throw new Error(
|
|
@@ -160,28 +159,28 @@ export const commands = {
|
|
|
160
159
|
`已成功上传app原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`,
|
|
161
160
|
);
|
|
162
161
|
},
|
|
163
|
-
parseApp: async
|
|
162
|
+
parseApp: async ({ args }) => {
|
|
164
163
|
const fn = args[0];
|
|
165
164
|
if (!fn || !fn.endsWith('.app')) {
|
|
166
165
|
throw new Error('使用方法: pushy parseApp app后缀文件');
|
|
167
166
|
}
|
|
168
167
|
console.log(await getAppInfo(fn));
|
|
169
168
|
},
|
|
170
|
-
parseIpa: async
|
|
169
|
+
parseIpa: async ({ args }) => {
|
|
171
170
|
const fn = args[0];
|
|
172
171
|
if (!fn || !fn.endsWith('.ipa')) {
|
|
173
172
|
throw new Error('使用方法: pushy parseIpa ipa后缀文件');
|
|
174
173
|
}
|
|
175
174
|
console.log(await getIpaInfo(fn));
|
|
176
175
|
},
|
|
177
|
-
parseApk: async
|
|
176
|
+
parseApk: async ({ args }) => {
|
|
178
177
|
const fn = args[0];
|
|
179
178
|
if (!fn || !fn.endsWith('.apk')) {
|
|
180
179
|
throw new Error('使用方法: pushy parseApk apk后缀文件');
|
|
181
180
|
}
|
|
182
181
|
console.log(await getApkInfo(fn));
|
|
183
182
|
},
|
|
184
|
-
packages: async
|
|
183
|
+
packages: async ({ options }) => {
|
|
185
184
|
const platform = checkPlatform(
|
|
186
185
|
options.platform || (await question('平台(ios/android/harmony):')),
|
|
187
186
|
);
|
package/src/types.ts
CHANGED
package/src/{user.js → user.ts}
RENAMED
|
@@ -2,12 +2,12 @@ import { question } from './utils';
|
|
|
2
2
|
import { post, get, replaceSession, saveSession, closeSession } from './api';
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
4
|
|
|
5
|
-
function md5(str) {
|
|
5
|
+
function md5(str: string) {
|
|
6
6
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export const commands = {
|
|
10
|
-
login: async ({ args }) => {
|
|
10
|
+
login: async ({ args }: { args: string[] }) => {
|
|
11
11
|
const email = args[0] || (await question('email:'));
|
|
12
12
|
const pwd = args[1] || (await question('password:', true));
|
|
13
13
|
const { token, info } = await post('/user/login', {
|
|
@@ -22,12 +22,13 @@ export async function question(query, password) {
|
|
|
22
22
|
|
|
23
23
|
export function translateOptions(options) {
|
|
24
24
|
const ret = {};
|
|
25
|
-
for (
|
|
25
|
+
for (const key in options) {
|
|
26
26
|
const v = options[key];
|
|
27
27
|
if (typeof v === 'string') {
|
|
28
|
-
ret[key] = v.replace(
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
ret[key] = v.replace(
|
|
29
|
+
/\$\{(\w+)\}/g,
|
|
30
|
+
(v, n) => options[n] || process.env[n] || v,
|
|
31
|
+
);
|
|
31
32
|
} else {
|
|
32
33
|
ret[key] = v;
|
|
33
34
|
}
|
|
@@ -124,7 +125,7 @@ export async function getAppInfo(fn) {
|
|
|
124
125
|
return { versionName, buildTime, ...appCredential };
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
export async function getIpaInfo(fn) {
|
|
128
|
+
export async function getIpaInfo(fn: string) {
|
|
128
129
|
const appInfoParser = new AppInfoParser(fn);
|
|
129
130
|
const bundleFile = await appInfoParser.parser.getEntry(
|
|
130
131
|
/payload\/.+?\.app\/main.jsbundle/,
|
|
@@ -217,7 +218,7 @@ export async function printVersionCommand() {
|
|
|
217
218
|
);
|
|
218
219
|
} else if (semverSatisfies(pushyVersion, '10.0.0 - 10.17.0')) {
|
|
219
220
|
console.warn(
|
|
220
|
-
|
|
221
|
+
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10',
|
|
221
222
|
);
|
|
222
223
|
}
|
|
223
224
|
}
|