react-native-update-cli 1.18.0 → 1.20.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/lib/api.js +58 -37
- package/lib/app.js +10 -8
- package/lib/bundle.js +46 -33
- package/lib/index.js +12 -5
- package/lib/package.js +13 -13
- package/lib/user.js +18 -17
- package/lib/utils/index.js +16 -11
- package/lib/versions.js +8 -9
- package/package.json +10 -6
- package/src/api.js +24 -26
- package/src/app.js +2 -2
- package/src/bundle.js +25 -24
- package/src/index.js +3 -3
- package/src/package.js +8 -8
- package/src/user.js +12 -22
- package/src/utils/index.js +3 -7
- package/src/versions.js +1 -1
package/lib/api.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.doDelete = exports.put = exports.post = exports.get = exports.closeSession = exports.saveSession = exports.loadSession = exports.replaceSession = exports.getSession = undefined;
|
|
7
|
+
exports.uploadFile = uploadFile;
|
|
8
|
+
|
|
9
|
+
var _nodeFetch = require('node-fetch');
|
|
10
|
+
|
|
11
|
+
var _nodeFetch2 = _interopRequireDefault(_nodeFetch);
|
|
12
|
+
|
|
13
|
+
var _fs = require('fs');
|
|
14
|
+
|
|
15
|
+
var _fs2 = _interopRequireDefault(_fs);
|
|
16
|
+
|
|
3
17
|
var _request = require('request');
|
|
4
18
|
|
|
5
19
|
var _request2 = _interopRequireDefault(_request);
|
|
@@ -8,6 +22,22 @@ var _progress = require('progress');
|
|
|
8
22
|
|
|
9
23
|
var _progress2 = _interopRequireDefault(_progress);
|
|
10
24
|
|
|
25
|
+
var _package = require('../package.json');
|
|
26
|
+
|
|
27
|
+
var _package2 = _interopRequireDefault(_package);
|
|
28
|
+
|
|
29
|
+
var _tcpPing = require('tcp-ping');
|
|
30
|
+
|
|
31
|
+
var _tcpPing2 = _interopRequireDefault(_tcpPing);
|
|
32
|
+
|
|
33
|
+
var _util = require('util');
|
|
34
|
+
|
|
35
|
+
var _util2 = _interopRequireDefault(_util);
|
|
36
|
+
|
|
37
|
+
var _path = require('path');
|
|
38
|
+
|
|
39
|
+
var _path2 = _interopRequireDefault(_path);
|
|
40
|
+
|
|
11
41
|
var _filesizeParser = require('filesize-parser');
|
|
12
42
|
|
|
13
43
|
var _filesizeParser2 = _interopRequireDefault(_filesizeParser);
|
|
@@ -16,28 +46,29 @@ var _utils = require('./utils');
|
|
|
16
46
|
|
|
17
47
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
48
|
|
|
19
|
-
const fetch = require('node-fetch');
|
|
20
49
|
const defaultEndpoint = 'https://update.reactnative.cn/api';
|
|
21
50
|
let host = process.env.PUSHY_REGISTRY || defaultEndpoint;
|
|
22
|
-
const fs = require('fs');
|
|
23
|
-
|
|
24
|
-
const packageJson = require('../package.json');
|
|
25
|
-
const tcpp = require('tcp-ping');
|
|
26
|
-
const util = require('util');
|
|
27
|
-
const path = require('path');
|
|
28
51
|
|
|
29
52
|
|
|
30
|
-
const tcpPing =
|
|
53
|
+
const tcpPing = _util2.default.promisify(_tcpPing2.default.ping);
|
|
31
54
|
|
|
32
55
|
let session = undefined;
|
|
33
56
|
let savedSession = undefined;
|
|
34
57
|
|
|
35
|
-
const userAgent = `react-native-update-cli/${
|
|
58
|
+
const userAgent = `react-native-update-cli/${_package2.default.version}`;
|
|
36
59
|
|
|
37
|
-
exports.
|
|
38
|
-
|
|
60
|
+
const getSession = exports.getSession = function () {
|
|
61
|
+
return session;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const replaceSession = exports.replaceSession = function (newSession) {
|
|
65
|
+
session = newSession;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const loadSession = exports.loadSession = async function () {
|
|
69
|
+
if (_fs2.default.existsSync('.update')) {
|
|
39
70
|
try {
|
|
40
|
-
|
|
71
|
+
replaceSession(JSON.parse(_fs2.default.readFileSync('.update', 'utf8')));
|
|
41
72
|
savedSession = session;
|
|
42
73
|
} catch (e) {
|
|
43
74
|
console.error('Failed to parse file `.update`. Try to remove it manually.');
|
|
@@ -46,27 +77,19 @@ exports.loadSession = async function () {
|
|
|
46
77
|
}
|
|
47
78
|
};
|
|
48
79
|
|
|
49
|
-
exports.
|
|
50
|
-
return session;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
exports.replaceSession = function (newSession) {
|
|
54
|
-
session = newSession;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
exports.saveSession = function () {
|
|
80
|
+
const saveSession = exports.saveSession = function () {
|
|
58
81
|
// Only save on change.
|
|
59
82
|
if (session !== savedSession) {
|
|
60
83
|
const current = session;
|
|
61
84
|
const data = JSON.stringify(current, null, 4);
|
|
62
|
-
|
|
85
|
+
_fs2.default.writeFileSync('.update', data, 'utf8');
|
|
63
86
|
savedSession = current;
|
|
64
87
|
}
|
|
65
88
|
};
|
|
66
89
|
|
|
67
|
-
exports.closeSession = function () {
|
|
68
|
-
if (
|
|
69
|
-
|
|
90
|
+
const closeSession = exports.closeSession = function () {
|
|
91
|
+
if (_fs2.default.existsSync('.update')) {
|
|
92
|
+
_fs2.default.unlinkSync('.update');
|
|
70
93
|
savedSession = undefined;
|
|
71
94
|
}
|
|
72
95
|
session = undefined;
|
|
@@ -74,7 +97,7 @@ exports.closeSession = function () {
|
|
|
74
97
|
};
|
|
75
98
|
|
|
76
99
|
async function query(url, options) {
|
|
77
|
-
const resp = await
|
|
100
|
+
const resp = await (0, _nodeFetch2.default)(url, options);
|
|
78
101
|
const text = await resp.text();
|
|
79
102
|
let json;
|
|
80
103
|
try {
|
|
@@ -117,14 +140,14 @@ function queryWithBody(method) {
|
|
|
117
140
|
};
|
|
118
141
|
}
|
|
119
142
|
|
|
120
|
-
exports.get = queryWithoutBody('GET');
|
|
121
|
-
exports.post = queryWithBody('POST');
|
|
122
|
-
exports.put = queryWithBody('PUT');
|
|
123
|
-
exports.doDelete = queryWithBody('DELETE');
|
|
143
|
+
const get = exports.get = queryWithoutBody('GET');
|
|
144
|
+
const post = exports.post = queryWithBody('POST');
|
|
145
|
+
const put = exports.put = queryWithBody('PUT');
|
|
146
|
+
const doDelete = exports.doDelete = queryWithBody('DELETE');
|
|
124
147
|
|
|
125
148
|
async function uploadFile(fn, key) {
|
|
126
|
-
const { url, backupUrl, formData, maxSize } = await
|
|
127
|
-
ext:
|
|
149
|
+
const { url, backupUrl, formData, maxSize } = await post('/upload', {
|
|
150
|
+
ext: _path2.default.extname(fn)
|
|
128
151
|
});
|
|
129
152
|
let realUrl = url;
|
|
130
153
|
|
|
@@ -145,7 +168,7 @@ async function uploadFile(fn, key) {
|
|
|
145
168
|
// console.log({realUrl});
|
|
146
169
|
}
|
|
147
170
|
|
|
148
|
-
const fileSize =
|
|
171
|
+
const fileSize = _fs2.default.statSync(fn).size;
|
|
149
172
|
if (maxSize && fileSize > (0, _filesizeParser2.default)(maxSize)) {
|
|
150
173
|
throw new Error(`此文件大小${(fileSize / 1048576).toFixed(1)}m, 超出当前额度${maxSize}。您可以考虑升级付费业务以提升此额度。详情请访问: ${_utils.pricingPageUrl}`);
|
|
151
174
|
}
|
|
@@ -160,7 +183,7 @@ async function uploadFile(fn, key) {
|
|
|
160
183
|
if (key) {
|
|
161
184
|
formData.key = key;
|
|
162
185
|
}
|
|
163
|
-
formData.file =
|
|
186
|
+
formData.file = _fs2.default.createReadStream(fn);
|
|
164
187
|
|
|
165
188
|
formData.file.on('data', function (data) {
|
|
166
189
|
bar.tick(data.length);
|
|
@@ -178,6 +201,4 @@ async function uploadFile(fn, key) {
|
|
|
178
201
|
});
|
|
179
202
|
});
|
|
180
203
|
return info;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
exports.uploadFile = uploadFile;
|
|
204
|
+
}
|
package/lib/app.js
CHANGED
|
@@ -15,11 +15,13 @@ var _fs = require('fs');
|
|
|
15
15
|
|
|
16
16
|
var _fs2 = _interopRequireDefault(_fs);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
var _ttyTable = require('tty-table');
|
|
19
|
+
|
|
20
|
+
var _ttyTable2 = _interopRequireDefault(_ttyTable);
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
var _api = require('./api');
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
25
|
|
|
24
26
|
const validPlatforms = {
|
|
25
27
|
ios: 1,
|
|
@@ -47,7 +49,7 @@ function getSelectedApp(platform) {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
async function listApp(platform) {
|
|
50
|
-
const { data } = await get('/app/list');
|
|
52
|
+
const { data } = await (0, _api.get)('/app/list');
|
|
51
53
|
const list = platform ? data.filter(v => v.platform === platform) : data;
|
|
52
54
|
|
|
53
55
|
const header = [{ value: '应用 id' }, { value: '应用名称' }, { value: '平台' }];
|
|
@@ -56,7 +58,7 @@ async function listApp(platform) {
|
|
|
56
58
|
rows.push([app.id, app.name, app.platform]);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
console.log(
|
|
61
|
+
console.log((0, _ttyTable2.default)(header, rows).render());
|
|
60
62
|
|
|
61
63
|
if (platform) {
|
|
62
64
|
console.log(`\共 ${list.length} ${platform} 个应用`);
|
|
@@ -83,7 +85,7 @@ const commands = exports.commands = {
|
|
|
83
85
|
const name = options.name || (await (0, _utils.question)('应用名称:'));
|
|
84
86
|
const { downloadUrl } = options;
|
|
85
87
|
const platform = checkPlatform(options.platform || (await (0, _utils.question)('平台(ios/android):')));
|
|
86
|
-
const { id } = await post('/app/create', { name, platform });
|
|
88
|
+
const { id } = await (0, _api.post)('/app/create', { name, platform });
|
|
87
89
|
console.log(`已成功创建应用(id: ${id})`);
|
|
88
90
|
await this.selectApp({
|
|
89
91
|
args: [id],
|
|
@@ -96,7 +98,7 @@ const commands = exports.commands = {
|
|
|
96
98
|
if (!id) {
|
|
97
99
|
console.log('已取消');
|
|
98
100
|
}
|
|
99
|
-
await doDelete(`/app/${id}`);
|
|
101
|
+
await (0, _api.doDelete)(`/app/${id}`);
|
|
100
102
|
console.log('操作成功');
|
|
101
103
|
},
|
|
102
104
|
apps: async function ({ options }) {
|
|
@@ -116,7 +118,7 @@ const commands = exports.commands = {
|
|
|
116
118
|
throw e;
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
|
-
const { appKey } = await get(`/app/${id}`);
|
|
121
|
+
const { appKey } = await (0, _api.get)(`/app/${id}`);
|
|
120
122
|
updateInfo[platform] = {
|
|
121
123
|
appId: id,
|
|
122
124
|
appKey
|
package/lib/bundle.js
CHANGED
|
@@ -7,6 +7,10 @@ exports.commands = undefined;
|
|
|
7
7
|
|
|
8
8
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
9
9
|
|
|
10
|
+
var _path = require('path');
|
|
11
|
+
|
|
12
|
+
var _path2 = _interopRequireDefault(_path);
|
|
13
|
+
|
|
10
14
|
var _utils = require('./utils');
|
|
11
15
|
|
|
12
16
|
var _fsExtra = require('fs-extra');
|
|
@@ -19,16 +23,21 @@ var _yauzl = require('yauzl');
|
|
|
19
23
|
|
|
20
24
|
var _app = require('./app');
|
|
21
25
|
|
|
26
|
+
var _child_process = require('child_process');
|
|
27
|
+
|
|
28
|
+
var _os = require('os');
|
|
29
|
+
|
|
30
|
+
var _os2 = _interopRequireDefault(_os);
|
|
31
|
+
|
|
22
32
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
35
|
|
|
26
|
-
const { spawn, spawnSync } = require('child_process');
|
|
27
36
|
const g2js = require('gradle-to-js/lib/parser');
|
|
28
|
-
|
|
37
|
+
|
|
29
38
|
const properties = require('properties');
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
let bsdiff, hdiff, diff;
|
|
32
41
|
try {
|
|
33
42
|
bsdiff = require('node-bsdiff').diff;
|
|
34
43
|
} catch (e) {}
|
|
@@ -41,9 +50,9 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
41
50
|
let gradleConfig = {};
|
|
42
51
|
if (platform === 'android') {
|
|
43
52
|
gradleConfig = await checkGradleConfig();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if (gradleConfig.crunchPngs !== false) {
|
|
54
|
+
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');
|
|
55
|
+
}
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
let reactNativeBundleArgs = [];
|
|
@@ -60,13 +69,19 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
60
69
|
paths: [process.cwd()]
|
|
61
70
|
});
|
|
62
71
|
try {
|
|
72
|
+
require.resolve('expo-router', {
|
|
73
|
+
paths: [process.cwd()]
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
console.log(`expo-router detected, will use @expo/cli to bundle.\n`);
|
|
77
|
+
// if using expo-router, use expo-cli
|
|
63
78
|
cliPath = require.resolve('@expo/cli', {
|
|
64
79
|
paths: [process.cwd()]
|
|
65
80
|
});
|
|
66
81
|
} catch (e) {}
|
|
67
82
|
const bundleCommand = cliPath.includes('@expo/cli') ? 'export:embed' : 'bundle';
|
|
68
83
|
|
|
69
|
-
Array.prototype.push.apply(reactNativeBundleArgs, [cliPath, bundleCommand, '--assets-dest', outputFolder, '--bundle-output',
|
|
84
|
+
Array.prototype.push.apply(reactNativeBundleArgs, [cliPath, bundleCommand, '--assets-dest', outputFolder, '--bundle-output', _path2.default.join(outputFolder, bundleName), '--dev', development, '--entry-file', entryFile, '--platform', platform, '--reset-cache']);
|
|
70
85
|
|
|
71
86
|
if (sourcemapOutput) {
|
|
72
87
|
reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
|
|
@@ -76,7 +91,7 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
76
91
|
reactNativeBundleArgs.push('--config', config);
|
|
77
92
|
}
|
|
78
93
|
|
|
79
|
-
const reactNativeBundleProcess = spawn('node', reactNativeBundleArgs);
|
|
94
|
+
const reactNativeBundleProcess = (0, _child_process.spawn)('node', reactNativeBundleArgs);
|
|
80
95
|
console.log(`Running bundle command: node ${reactNativeBundleArgs.join(' ')}`);
|
|
81
96
|
|
|
82
97
|
return new Promise((resolve, reject) => {
|
|
@@ -121,9 +136,9 @@ async function runReactNativeBundleCommand(bundleName, development, entryFile, o
|
|
|
121
136
|
}
|
|
122
137
|
|
|
123
138
|
function getHermesOSBin() {
|
|
124
|
-
if (
|
|
125
|
-
if (
|
|
126
|
-
if (
|
|
139
|
+
if (_os2.default.platform() === 'win32') return 'win64-bin';
|
|
140
|
+
if (_os2.default.platform() === 'darwin') return 'osx-bin';
|
|
141
|
+
if (_os2.default.platform() === 'linux') return 'linux64-bin';
|
|
127
142
|
}
|
|
128
143
|
|
|
129
144
|
async function checkGradleConfig() {
|
|
@@ -149,35 +164,33 @@ async function checkGradleConfig() {
|
|
|
149
164
|
async function compileHermesByteCode(bundleName, outputFolder, sourcemapOutput) {
|
|
150
165
|
console.log(`Hermes enabled, now compiling to hermes bytecode:\n`);
|
|
151
166
|
// >= rn 0.69
|
|
152
|
-
const rnDir =
|
|
167
|
+
const rnDir = _path2.default.dirname(require.resolve('react-native', {
|
|
153
168
|
paths: [process.cwd()]
|
|
154
169
|
}));
|
|
155
|
-
|
|
170
|
+
let hermesPath = _path2.default.join(rnDir, `/sdks/hermesc/${getHermesOSBin()}`);
|
|
156
171
|
|
|
157
172
|
// < rn 0.69
|
|
158
|
-
if (!fs.existsSync(
|
|
159
|
-
|
|
160
|
-
: 'node_modules/hermesvm'; // < 0.2
|
|
161
|
-
const hermesPath = `${hermesPackage}/${getHermesOSBin()}`;
|
|
162
|
-
|
|
163
|
-
hermesCommand = fs.existsSync(`${hermesPath}/hermesc`) ? `${hermesPath}/hermesc` // 0.5+
|
|
164
|
-
: `${hermesPath}/hermes`; // < 0.5
|
|
173
|
+
if (!fs.existsSync(hermesPath)) {
|
|
174
|
+
hermesPath = `node_modules/hermes-engine/${getHermesOSBin()}`;
|
|
165
175
|
}
|
|
166
|
-
|
|
176
|
+
|
|
177
|
+
const hermesCommand = `${hermesPath}/hermesc`;
|
|
178
|
+
|
|
179
|
+
const args = ['-emit-binary', '-out', _path2.default.join(outputFolder, bundleName), _path2.default.join(outputFolder, bundleName), '-O'];
|
|
167
180
|
if (sourcemapOutput) {
|
|
168
181
|
args.push('-output-source-map');
|
|
169
182
|
}
|
|
170
183
|
console.log('Running hermesc: ' + hermesCommand + ' ' + args.join(' ') + '\n');
|
|
171
|
-
spawnSync(hermesCommand, args, {
|
|
184
|
+
(0, _child_process.spawnSync)(hermesCommand, args, {
|
|
172
185
|
stdio: 'ignore'
|
|
173
186
|
});
|
|
174
187
|
}
|
|
175
188
|
|
|
176
189
|
async function pack(dir, output) {
|
|
177
190
|
console.log('Packing');
|
|
178
|
-
fs.ensureDirSync(
|
|
191
|
+
fs.ensureDirSync(_path2.default.dirname(output));
|
|
179
192
|
await new Promise((resolve, reject) => {
|
|
180
|
-
|
|
193
|
+
const zipfile = new _yazl.ZipFile();
|
|
181
194
|
|
|
182
195
|
function addDirectory(root, rel) {
|
|
183
196
|
if (rel) {
|
|
@@ -188,7 +201,7 @@ async function pack(dir, output) {
|
|
|
188
201
|
if (name === '.' || name === '..') {
|
|
189
202
|
continue;
|
|
190
203
|
}
|
|
191
|
-
const fullPath =
|
|
204
|
+
const fullPath = _path2.default.join(root, name);
|
|
192
205
|
const stat = fs.statSync(fullPath);
|
|
193
206
|
if (stat.isFile()) {
|
|
194
207
|
//console.log('adding: ' + rel+name);
|
|
@@ -237,7 +250,7 @@ function basename(fn) {
|
|
|
237
250
|
}
|
|
238
251
|
|
|
239
252
|
async function diffFromPPK(origin, next, output) {
|
|
240
|
-
fs.ensureDirSync(
|
|
253
|
+
fs.ensureDirSync(_path2.default.dirname(output));
|
|
241
254
|
|
|
242
255
|
const originEntries = {};
|
|
243
256
|
const originMap = {};
|
|
@@ -263,7 +276,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
263
276
|
|
|
264
277
|
const copies = {};
|
|
265
278
|
|
|
266
|
-
|
|
279
|
+
const zipfile = new _yazl.ZipFile();
|
|
267
280
|
|
|
268
281
|
const writePromise = new Promise((resolve, reject) => {
|
|
269
282
|
zipfile.outputStream.on('error', err => {
|
|
@@ -343,7 +356,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
343
356
|
|
|
344
357
|
const deletes = {};
|
|
345
358
|
|
|
346
|
-
for (
|
|
359
|
+
for (let k in originEntries) {
|
|
347
360
|
if (!newEntries[k]) {
|
|
348
361
|
console.log('Delete ' + k);
|
|
349
362
|
deletes[k] = 1;
|
|
@@ -357,7 +370,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
357
370
|
}
|
|
358
371
|
|
|
359
372
|
async function diffFromPackage(origin, next, output, originBundleName, transformPackagePath = v => v) {
|
|
360
|
-
fs.ensureDirSync(
|
|
373
|
+
fs.ensureDirSync(_path2.default.dirname(output));
|
|
361
374
|
|
|
362
375
|
const originEntries = {};
|
|
363
376
|
const originMap = {};
|
|
@@ -389,7 +402,7 @@ async function diffFromPackage(origin, next, output, originBundleName, transform
|
|
|
389
402
|
|
|
390
403
|
const copies = {};
|
|
391
404
|
|
|
392
|
-
|
|
405
|
+
const zipfile = new _yazl.ZipFile();
|
|
393
406
|
|
|
394
407
|
const writePromise = new Promise((resolve, reject) => {
|
|
395
408
|
zipfile.outputStream.on('error', err => {
|
|
@@ -504,7 +517,7 @@ const commands = exports.commands = {
|
|
|
504
517
|
platform
|
|
505
518
|
}));
|
|
506
519
|
|
|
507
|
-
const sourcemapOutput =
|
|
520
|
+
const sourcemapOutput = _path2.default.join(intermediaDir, bundleName + '.map');
|
|
508
521
|
|
|
509
522
|
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
|
|
510
523
|
|
|
@@ -519,7 +532,7 @@ const commands = exports.commands = {
|
|
|
519
532
|
|
|
520
533
|
await runReactNativeBundleCommand(bundleName, dev, entryFile, intermediaDir, platform, sourcemap ? sourcemapOutput : '');
|
|
521
534
|
|
|
522
|
-
await pack(
|
|
535
|
+
await pack(_path2.default.resolve(intermediaDir), realOutput);
|
|
523
536
|
|
|
524
537
|
const v = await (0, _utils.question)('是否现在上传此热更包?(Y/N)');
|
|
525
538
|
if (v.toLowerCase() === 'y') {
|
package/lib/index.js
CHANGED
|
@@ -3,14 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
5
5
|
|
|
6
|
+
var _api = require('./api');
|
|
7
|
+
|
|
8
|
+
var _updateNotifier = require('update-notifier');
|
|
9
|
+
|
|
10
|
+
var _updateNotifier2 = _interopRequireDefault(_updateNotifier);
|
|
11
|
+
|
|
6
12
|
var _index = require('./utils/index.js');
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
var _package = require('../package.json');
|
|
15
|
+
|
|
16
|
+
var _package2 = _interopRequireDefault(_package);
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
(0, _updateNotifier2.default)({ pkg: _package2.default }).notify({ isGlobal: true });
|
|
14
21
|
|
|
15
22
|
function printUsage({ args }) {
|
|
16
23
|
// const commandName = args[0];
|
|
@@ -35,7 +42,7 @@ function run() {
|
|
|
35
42
|
global.NO_INTERACTIVE = argv.options['no-interactive'];
|
|
36
43
|
global.USE_ACC_OSS = argv.options['acc'];
|
|
37
44
|
|
|
38
|
-
loadSession().then(() => commands[argv.command](argv)).catch(err => {
|
|
45
|
+
(0, _api.loadSession)().then(() => commands[argv.command](argv)).catch(err => {
|
|
39
46
|
if (err.status === 401) {
|
|
40
47
|
console.log('尚未登录。\n请在项目目录中运行`pushy login`命令来登录');
|
|
41
48
|
return;
|
package/lib/package.js
CHANGED
|
@@ -7,20 +7,20 @@ exports.commands = undefined;
|
|
|
7
7
|
exports.listPackage = listPackage;
|
|
8
8
|
exports.choosePackage = choosePackage;
|
|
9
9
|
|
|
10
|
+
var _api = require('./api');
|
|
11
|
+
|
|
10
12
|
var _utils = require('./utils');
|
|
11
13
|
|
|
12
14
|
var _app = require('./app');
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
* Created by tdzl2003 on 4/2/16.
|
|
16
|
-
*/
|
|
16
|
+
var _ttyTable = require('tty-table');
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
var _ttyTable2 = _interopRequireDefault(_ttyTable);
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
21
|
|
|
22
22
|
async function listPackage(appId) {
|
|
23
|
-
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
|
|
23
|
+
const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
|
|
24
24
|
|
|
25
25
|
const header = [{ value: '原生包 Id' }, { value: '原生版本' }];
|
|
26
26
|
const rows = [];
|
|
@@ -43,7 +43,7 @@ async function listPackage(appId) {
|
|
|
43
43
|
rows.push([pkg.id, output]);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
console.log(
|
|
46
|
+
console.log((0, _ttyTable2.default)(header, rows).render());
|
|
47
47
|
console.log(`\n共 ${data.length} 个包`);
|
|
48
48
|
return data;
|
|
49
49
|
}
|
|
@@ -82,15 +82,15 @@ const commands = exports.commands = {
|
|
|
82
82
|
throw new Error(`appKey不匹配!当前ipa: ${appKeyInPkg}, 当前update.json: ${appKey}`);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const { hash } = await uploadFile(fn);
|
|
85
|
+
const { hash } = await (0, _api.uploadFile)(fn);
|
|
86
86
|
|
|
87
|
-
const { id } = await post(`/app/${appId}/package/create`, {
|
|
87
|
+
const { id } = await (0, _api.post)(`/app/${appId}/package/create`, {
|
|
88
88
|
name: versionName,
|
|
89
89
|
hash,
|
|
90
90
|
buildTime
|
|
91
91
|
});
|
|
92
92
|
(0, _utils.saveToLocal)(fn, `${appId}/package/${id}.ipa`);
|
|
93
|
-
console.log(`已成功上传ipa原生包(id: ${id})`);
|
|
93
|
+
console.log(`已成功上传ipa原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`);
|
|
94
94
|
},
|
|
95
95
|
uploadApk: async function ({ args }) {
|
|
96
96
|
const fn = args[0];
|
|
@@ -113,15 +113,15 @@ const commands = exports.commands = {
|
|
|
113
113
|
throw new Error(`appKey不匹配!当前apk: ${appKeyInPkg}, 当前update.json: ${appKey}`);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
const { hash } = await uploadFile(fn);
|
|
116
|
+
const { hash } = await (0, _api.uploadFile)(fn);
|
|
117
117
|
|
|
118
|
-
const { id } = await post(`/app/${appId}/package/create`, {
|
|
118
|
+
const { id } = await (0, _api.post)(`/app/${appId}/package/create`, {
|
|
119
119
|
name: versionName,
|
|
120
120
|
hash,
|
|
121
121
|
buildTime
|
|
122
122
|
});
|
|
123
123
|
(0, _utils.saveToLocal)(fn, `${appId}/package/${id}.apk`);
|
|
124
|
-
console.log(`已成功上传apk原生包(id: ${id})`);
|
|
124
|
+
console.log(`已成功上传apk原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`);
|
|
125
125
|
},
|
|
126
126
|
parseIpa: async function ({ args }) {
|
|
127
127
|
const fn = args[0];
|
package/lib/user.js
CHANGED
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.commands = undefined;
|
|
7
|
+
|
|
3
8
|
var _utils = require('./utils');
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
closeSession
|
|
11
|
-
} = require('./api'); /**
|
|
12
|
-
* Created by tdzl2003 on 2/13/16.
|
|
13
|
-
*/
|
|
10
|
+
var _api = require('./api');
|
|
11
|
+
|
|
12
|
+
var _crypto = require('crypto');
|
|
13
|
+
|
|
14
|
+
var _crypto2 = _interopRequireDefault(_crypto);
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
17
|
|
|
17
18
|
function md5(str) {
|
|
18
|
-
return
|
|
19
|
+
return _crypto2.default.createHash('md5').update(str).digest('hex');
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
exports.commands = {
|
|
22
|
+
const commands = exports.commands = {
|
|
22
23
|
login: async function ({ args }) {
|
|
23
24
|
const email = args[0] || (await (0, _utils.question)('email:'));
|
|
24
25
|
const pwd = args[1] || (await (0, _utils.question)('password:', true));
|
|
25
|
-
const { token, info } = await post('/user/login', {
|
|
26
|
+
const { token, info } = await (0, _api.post)('/user/login', {
|
|
26
27
|
email,
|
|
27
28
|
pwd: md5(pwd)
|
|
28
29
|
});
|
|
29
|
-
replaceSession({ token });
|
|
30
|
-
await saveSession();
|
|
30
|
+
(0, _api.replaceSession)({ token });
|
|
31
|
+
await (0, _api.saveSession)();
|
|
31
32
|
console.log(`欢迎使用 pushy 热更新服务, ${info.name}.`);
|
|
32
33
|
},
|
|
33
34
|
logout: async function () {
|
|
34
|
-
await closeSession();
|
|
35
|
+
await (0, _api.closeSession)();
|
|
35
36
|
console.log('已退出登录');
|
|
36
37
|
},
|
|
37
38
|
me: async function () {
|
|
38
|
-
const me = await get('/user/me');
|
|
39
|
+
const me = await (0, _api.get)('/user/me');
|
|
39
40
|
for (const k in me) {
|
|
40
41
|
if (k !== 'ok') {
|
|
41
42
|
console.log(`${k}: ${me[k]}`);
|
package/lib/utils/index.js
CHANGED
|
@@ -5,9 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.pricingPageUrl = undefined;
|
|
7
7
|
|
|
8
|
-
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
9
|
-
* Created by tdzl2003 on 2/13/16.
|
|
10
|
-
*/
|
|
8
|
+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
11
9
|
|
|
12
10
|
exports.question = question;
|
|
13
11
|
exports.translateOptions = translateOptions;
|
|
@@ -29,18 +27,25 @@ var _path = require('path');
|
|
|
29
27
|
|
|
30
28
|
var _path2 = _interopRequireDefault(_path);
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
var _package = require('../../package.json');
|
|
31
|
+
|
|
32
|
+
var _package2 = _interopRequireDefault(_package);
|
|
33
|
+
|
|
34
|
+
var _appInfoParser = require('app-info-parser');
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
const AppInfoParser = require('app-info-parser');
|
|
36
|
+
var _appInfoParser2 = _interopRequireDefault(_appInfoParser);
|
|
36
37
|
|
|
37
|
-
var
|
|
38
|
+
var _read = require('read');
|
|
39
|
+
|
|
40
|
+
var _read2 = _interopRequireDefault(_read);
|
|
41
|
+
|
|
42
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
38
43
|
|
|
39
44
|
function question(query, password) {
|
|
40
45
|
if (NO_INTERACTIVE) {
|
|
41
46
|
return Promise.resolve('');
|
|
42
47
|
}
|
|
43
|
-
return new Promise((resolve, reject) =>
|
|
48
|
+
return new Promise((resolve, reject) => (0, _read2.default)({
|
|
44
49
|
prompt: query,
|
|
45
50
|
silent: password,
|
|
46
51
|
replace: password ? '*' : undefined
|
|
@@ -77,7 +82,7 @@ function getRNVersion() {
|
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
async function getApkInfo(fn) {
|
|
80
|
-
const appInfoParser = new
|
|
85
|
+
const appInfoParser = new _appInfoParser2.default(fn);
|
|
81
86
|
const bundleFile = await appInfoParser.parser.getEntry(/assets\/index.android.bundle/);
|
|
82
87
|
if (!bundleFile) {
|
|
83
88
|
throw new Error('找不到bundle文件。请确保此apk为release版本,且bundle文件名为默认的index.android.bundle');
|
|
@@ -103,7 +108,7 @@ async function getApkInfo(fn) {
|
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
async function getIpaInfo(fn) {
|
|
106
|
-
const appInfoParser = new
|
|
111
|
+
const appInfoParser = new _appInfoParser2.default(fn);
|
|
107
112
|
const bundleFile = await appInfoParser.parser.getEntry(/payload\/.+?\.app\/main.jsbundle/);
|
|
108
113
|
if (!bundleFile) {
|
|
109
114
|
throw new Error('找不到bundle文件。请确保此ipa为release版本,且bundle文件名为默认的main.jsbundle');
|
|
@@ -136,7 +141,7 @@ function saveToLocal(originPath, destName) {
|
|
|
136
141
|
}
|
|
137
142
|
|
|
138
143
|
function printVersionCommand() {
|
|
139
|
-
console.log('react-native-update-cli: ' +
|
|
144
|
+
console.log('react-native-update-cli: ' + _package2.default.version);
|
|
140
145
|
try {
|
|
141
146
|
const PACKAGE_JSON_PATH = require.resolve('react-native-update/package.json', {
|
|
142
147
|
paths: [process.cwd()]
|
package/lib/versions.js
CHANGED
|
@@ -5,17 +5,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.commands = undefined;
|
|
7
7
|
|
|
8
|
+
var _api = require('./api');
|
|
9
|
+
|
|
8
10
|
var _utils = require('./utils');
|
|
9
11
|
|
|
10
12
|
var _app = require('./app');
|
|
11
13
|
|
|
12
14
|
var _package = require('./package');
|
|
13
15
|
|
|
14
|
-
const { get, post, put, uploadFile } = require('./api');
|
|
15
|
-
|
|
16
|
-
|
|
17
16
|
async function showVersion(appId, offset) {
|
|
18
|
-
const { data, count } = await get(`/app/${appId}/version/list`);
|
|
17
|
+
const { data, count } = await (0, _api.get)(`/app/${appId}/version/list`);
|
|
19
18
|
console.log(`Offset ${offset}`);
|
|
20
19
|
for (const version of data) {
|
|
21
20
|
let packageInfo = version.packages.slice(0, 3).map(v => v.name).join(', ');
|
|
@@ -92,9 +91,9 @@ const commands = exports.commands = {
|
|
|
92
91
|
const platform = (0, _app.checkPlatform)(options.platform || (await (0, _utils.question)('平台(ios/android):')));
|
|
93
92
|
const { appId } = await (0, _app.getSelectedApp)(platform);
|
|
94
93
|
|
|
95
|
-
const { hash } = await uploadFile(fn);
|
|
94
|
+
const { hash } = await (0, _api.uploadFile)(fn);
|
|
96
95
|
|
|
97
|
-
const { id } = await post(`/app/${appId}/version/create`, {
|
|
96
|
+
const { id } = await (0, _api.post)(`/app/${appId}/version/create`, {
|
|
98
97
|
name: name || (await (0, _utils.question)('输入版本名称: ')) || '(未命名)',
|
|
99
98
|
hash,
|
|
100
99
|
description: description || (await (0, _utils.question)('输入版本描述:')),
|
|
@@ -123,7 +122,7 @@ const commands = exports.commands = {
|
|
|
123
122
|
let pkgVersion = options.packageVersion;
|
|
124
123
|
if (pkgVersion) {
|
|
125
124
|
pkgVersion = pkgVersion.trim();
|
|
126
|
-
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
|
|
125
|
+
const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
|
|
127
126
|
const pkg = data.find(d => d.name === pkgVersion);
|
|
128
127
|
if (pkg) {
|
|
129
128
|
pkgId = pkg.id;
|
|
@@ -138,7 +137,7 @@ const commands = exports.commands = {
|
|
|
138
137
|
if (!pkgId) {
|
|
139
138
|
throw new Error('请提供 packageId 或 packageVersion 参数');
|
|
140
139
|
}
|
|
141
|
-
await put(`/app/${appId}/package/${pkgId}`, {
|
|
140
|
+
await (0, _api.put)(`/app/${appId}/package/${pkgId}`, {
|
|
142
141
|
versionId
|
|
143
142
|
});
|
|
144
143
|
console.log('操作成功');
|
|
@@ -152,7 +151,7 @@ const commands = exports.commands = {
|
|
|
152
151
|
options.name && (updateParams.name = options.name);
|
|
153
152
|
options.description && (updateParams.description = options.description);
|
|
154
153
|
options.metaInfo && (updateParams.metaInfo = options.metaInfo);
|
|
155
|
-
await put(`/app/${appId}/version/${versionId}`, updateParams);
|
|
154
|
+
await (0, _api.put)(`/app/${appId}/version/${versionId}`, updateParams);
|
|
156
155
|
console.log('操作成功');
|
|
157
156
|
}
|
|
158
157
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Command tools for javaScript updater with `pushy` service for react native apps.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"cli.json"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
16
15
|
"prepublish": "babel src --out-dir lib"
|
|
17
16
|
},
|
|
18
17
|
"repository": {
|
|
@@ -32,7 +31,7 @@
|
|
|
32
31
|
},
|
|
33
32
|
"homepage": "https://github.com/reactnativecn/react-native-pushy/tree/master/react-native-pushy-cli",
|
|
34
33
|
"dependencies": {
|
|
35
|
-
"app-info-parser": "^1.
|
|
34
|
+
"app-info-parser": "^1.1.6",
|
|
36
35
|
"cli-arguments": "^0.2.1",
|
|
37
36
|
"filesize-parser": "^1.5.0",
|
|
38
37
|
"fs-extra": "8",
|
|
@@ -43,8 +42,8 @@
|
|
|
43
42
|
"read": "^1.0.7",
|
|
44
43
|
"request": "^2.88.2",
|
|
45
44
|
"tcp-ping": "^0.1.1",
|
|
46
|
-
"tty-table": "4.
|
|
47
|
-
"update-notifier": "^
|
|
45
|
+
"tty-table": "4.2",
|
|
46
|
+
"update-notifier": "^5.1.0",
|
|
48
47
|
"yauzl": "^2.10.0",
|
|
49
48
|
"yazl": "2.5.1"
|
|
50
49
|
},
|
|
@@ -56,6 +55,11 @@
|
|
|
56
55
|
"babel-plugin-transform-object-rest-spread": "^6.26.0"
|
|
57
56
|
},
|
|
58
57
|
"engines": {
|
|
59
|
-
"node": ">=
|
|
58
|
+
"node": ">= 10"
|
|
59
|
+
},
|
|
60
|
+
"pnpm": {
|
|
61
|
+
"patchedDependencies": {
|
|
62
|
+
"app-info-parser@1.1.6": "patches/app-info-parser@1.1.6.patch"
|
|
63
|
+
}
|
|
60
64
|
}
|
|
61
65
|
}
|
package/src/api.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
2
|
const defaultEndpoint = 'https://update.reactnative.cn/api';
|
|
3
3
|
let host = process.env.PUSHY_REGISTRY || defaultEndpoint;
|
|
4
|
-
|
|
4
|
+
import fs from 'fs';
|
|
5
5
|
import request from 'request';
|
|
6
6
|
import ProgressBar from 'progress';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
import packageJson from '../package.json';
|
|
8
|
+
import tcpp from 'tcp-ping';
|
|
9
|
+
import util from 'util';
|
|
10
|
+
import path from 'path';
|
|
11
11
|
import filesizeParser from 'filesize-parser';
|
|
12
12
|
import { pricingPageUrl } from './utils';
|
|
13
13
|
|
|
@@ -18,10 +18,18 @@ let savedSession = undefined;
|
|
|
18
18
|
|
|
19
19
|
const userAgent = `react-native-update-cli/${packageJson.version}`;
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
export const getSession = function () {
|
|
22
|
+
return session;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const replaceSession = function (newSession) {
|
|
26
|
+
session = newSession;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const loadSession = async function () {
|
|
22
30
|
if (fs.existsSync('.update')) {
|
|
23
31
|
try {
|
|
24
|
-
|
|
32
|
+
replaceSession(JSON.parse(fs.readFileSync('.update', 'utf8')));
|
|
25
33
|
savedSession = session;
|
|
26
34
|
} catch (e) {
|
|
27
35
|
console.error(
|
|
@@ -32,15 +40,7 @@ exports.loadSession = async function () {
|
|
|
32
40
|
}
|
|
33
41
|
};
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
return session;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
exports.replaceSession = function (newSession) {
|
|
40
|
-
session = newSession;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
exports.saveSession = function () {
|
|
43
|
+
export const saveSession = function () {
|
|
44
44
|
// Only save on change.
|
|
45
45
|
if (session !== savedSession) {
|
|
46
46
|
const current = session;
|
|
@@ -50,7 +50,7 @@ exports.saveSession = function () {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
export const closeSession = function () {
|
|
54
54
|
if (fs.existsSync('.update')) {
|
|
55
55
|
fs.unlinkSync('.update');
|
|
56
56
|
savedSession = undefined;
|
|
@@ -103,13 +103,13 @@ function queryWithBody(method) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
export const get = queryWithoutBody('GET');
|
|
107
|
+
export const post = queryWithBody('POST');
|
|
108
|
+
export const put = queryWithBody('PUT');
|
|
109
|
+
export const doDelete = queryWithBody('DELETE');
|
|
110
110
|
|
|
111
|
-
async function uploadFile(fn, key) {
|
|
112
|
-
const { url, backupUrl, formData, maxSize } = await
|
|
111
|
+
export async function uploadFile(fn, key) {
|
|
112
|
+
const { url, backupUrl, formData, maxSize } = await post('/upload', {
|
|
113
113
|
ext: path.extname(fn),
|
|
114
114
|
});
|
|
115
115
|
let realUrl = url;
|
|
@@ -175,5 +175,3 @@ async function uploadFile(fn, key) {
|
|
|
175
175
|
});
|
|
176
176
|
return info;
|
|
177
177
|
}
|
|
178
|
-
|
|
179
|
-
exports.uploadFile = uploadFile;
|
package/src/app.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { question } from './utils';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
-
|
|
3
|
+
import Table from 'tty-table';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { post, get, doDelete } from './api';
|
|
6
6
|
|
|
7
7
|
const validPlatforms = {
|
|
8
8
|
ios: 1,
|
package/src/bundle.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'path';
|
|
2
2
|
import { getRNVersion, translateOptions } from './utils';
|
|
3
3
|
import * as fs from 'fs-extra';
|
|
4
4
|
import { ZipFile } from 'yazl';
|
|
5
5
|
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 'child_process';
|
|
9
9
|
const g2js = require('gradle-to-js/lib/parser');
|
|
10
|
-
|
|
10
|
+
import os from 'os';
|
|
11
11
|
const properties = require('properties');
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
let bsdiff, hdiff, diff;
|
|
14
14
|
try {
|
|
15
15
|
bsdiff = require('node-bsdiff').diff;
|
|
16
16
|
} catch (e) {}
|
|
@@ -31,9 +31,11 @@ async function runReactNativeBundleCommand(
|
|
|
31
31
|
let gradleConfig = {};
|
|
32
32
|
if (platform === 'android') {
|
|
33
33
|
gradleConfig = await checkGradleConfig();
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (gradleConfig.crunchPngs !== false) {
|
|
35
|
+
console.warn(
|
|
36
|
+
'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',
|
|
37
|
+
);
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
let reactNativeBundleArgs = [];
|
|
@@ -53,6 +55,12 @@ async function runReactNativeBundleCommand(
|
|
|
53
55
|
paths: [process.cwd()],
|
|
54
56
|
});
|
|
55
57
|
try {
|
|
58
|
+
require.resolve('expo-router', {
|
|
59
|
+
paths: [process.cwd()],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
console.log(`expo-router detected, will use @expo/cli to bundle.\n`);
|
|
63
|
+
// if using expo-router, use expo-cli
|
|
56
64
|
cliPath = require.resolve('@expo/cli', {
|
|
57
65
|
paths: [process.cwd()],
|
|
58
66
|
});
|
|
@@ -188,22 +196,15 @@ async function compileHermesByteCode(
|
|
|
188
196
|
paths: [process.cwd()],
|
|
189
197
|
}),
|
|
190
198
|
);
|
|
191
|
-
|
|
192
|
-
rnDir,
|
|
193
|
-
`/sdks/hermesc/${getHermesOSBin()}/hermesc`,
|
|
194
|
-
);
|
|
199
|
+
let hermesPath = path.join(rnDir, `/sdks/hermesc/${getHermesOSBin()}`);
|
|
195
200
|
|
|
196
201
|
// < rn 0.69
|
|
197
|
-
if (!fs.existsSync(
|
|
198
|
-
|
|
199
|
-
? 'node_modules/hermes-engine' // 0.2+
|
|
200
|
-
: 'node_modules/hermesvm'; // < 0.2
|
|
201
|
-
const hermesPath = `${hermesPackage}/${getHermesOSBin()}`;
|
|
202
|
-
|
|
203
|
-
hermesCommand = fs.existsSync(`${hermesPath}/hermesc`)
|
|
204
|
-
? `${hermesPath}/hermesc` // 0.5+
|
|
205
|
-
: `${hermesPath}/hermes`; // < 0.5
|
|
202
|
+
if (!fs.existsSync(hermesPath)) {
|
|
203
|
+
hermesPath = `node_modules/hermes-engine/${getHermesOSBin()}`;
|
|
206
204
|
}
|
|
205
|
+
|
|
206
|
+
const hermesCommand = `${hermesPath}/hermesc`;
|
|
207
|
+
|
|
207
208
|
const args = [
|
|
208
209
|
'-emit-binary',
|
|
209
210
|
'-out',
|
|
@@ -226,7 +227,7 @@ async function pack(dir, output) {
|
|
|
226
227
|
console.log('Packing');
|
|
227
228
|
fs.ensureDirSync(path.dirname(output));
|
|
228
229
|
await new Promise((resolve, reject) => {
|
|
229
|
-
|
|
230
|
+
const zipfile = new ZipFile();
|
|
230
231
|
|
|
231
232
|
function addDirectory(root, rel) {
|
|
232
233
|
if (rel) {
|
|
@@ -316,7 +317,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
316
317
|
|
|
317
318
|
const copies = {};
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
const zipfile = new ZipFile();
|
|
320
321
|
|
|
321
322
|
const writePromise = new Promise((resolve, reject) => {
|
|
322
323
|
zipfile.outputStream.on('error', (err) => {
|
|
@@ -401,7 +402,7 @@ async function diffFromPPK(origin, next, output) {
|
|
|
401
402
|
|
|
402
403
|
const deletes = {};
|
|
403
404
|
|
|
404
|
-
for (
|
|
405
|
+
for (let k in originEntries) {
|
|
405
406
|
if (!newEntries[k]) {
|
|
406
407
|
console.log('Delete ' + k);
|
|
407
408
|
deletes[k] = 1;
|
|
@@ -458,7 +459,7 @@ async function diffFromPackage(
|
|
|
458
459
|
|
|
459
460
|
const copies = {};
|
|
460
461
|
|
|
461
|
-
|
|
462
|
+
const zipfile = new ZipFile();
|
|
462
463
|
|
|
463
464
|
const writePromise = new Promise((resolve, reject) => {
|
|
464
465
|
zipfile.outputStream.on('error', (err) => {
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { loadSession } from './api';
|
|
4
|
+
import updateNotifier from 'update-notifier';
|
|
5
5
|
import { printVersionCommand } from './utils/index.js';
|
|
6
|
-
|
|
6
|
+
import pkg from '../package.json';
|
|
7
7
|
|
|
8
8
|
updateNotifier({ pkg }).notify({ isGlobal: true });
|
|
9
9
|
|
package/src/package.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
* Created by tdzl2003 on 4/2/16.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { get, post, uploadFile } = require('./api');
|
|
1
|
+
import { get, post, uploadFile } from './api';
|
|
6
2
|
import { question, saveToLocal } from './utils';
|
|
7
3
|
|
|
8
4
|
import { checkPlatform, getSelectedApp } from './app';
|
|
9
5
|
|
|
10
6
|
import { getApkInfo, getIpaInfo } from './utils';
|
|
11
|
-
|
|
7
|
+
import Table from 'tty-table';
|
|
12
8
|
|
|
13
9
|
export async function listPackage(appId) {
|
|
14
10
|
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
|
|
@@ -85,7 +81,9 @@ export const commands = {
|
|
|
85
81
|
buildTime,
|
|
86
82
|
});
|
|
87
83
|
saveToLocal(fn, `${appId}/package/${id}.ipa`);
|
|
88
|
-
console.log(
|
|
84
|
+
console.log(
|
|
85
|
+
`已成功上传ipa原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`,
|
|
86
|
+
);
|
|
89
87
|
},
|
|
90
88
|
uploadApk: async function ({ args }) {
|
|
91
89
|
const fn = args[0];
|
|
@@ -120,7 +118,9 @@ export const commands = {
|
|
|
120
118
|
buildTime,
|
|
121
119
|
});
|
|
122
120
|
saveToLocal(fn, `${appId}/package/${id}.apk`);
|
|
123
|
-
console.log(
|
|
121
|
+
console.log(
|
|
122
|
+
`已成功上传apk原生包(id: ${id}, version: ${versionName}, buildTime: ${buildTime})`,
|
|
123
|
+
);
|
|
124
124
|
},
|
|
125
125
|
parseIpa: async function ({ args }) {
|
|
126
126
|
const fn = args[0];
|
package/src/user.js
CHANGED
|
@@ -1,38 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {question} from './utils';
|
|
6
|
-
const {
|
|
7
|
-
post,
|
|
8
|
-
get,
|
|
9
|
-
replaceSession,
|
|
10
|
-
saveSession,
|
|
11
|
-
closeSession,
|
|
12
|
-
} = require('./api');
|
|
13
|
-
const crypto = require('crypto');
|
|
1
|
+
import { question } from './utils';
|
|
2
|
+
import { post, get, replaceSession, saveSession, closeSession } from './api';
|
|
3
|
+
import crypto from 'crypto';
|
|
14
4
|
|
|
15
5
|
function md5(str) {
|
|
16
6
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
17
7
|
}
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
login: async function ({args}){
|
|
21
|
-
const email = args[0] || await question('email:');
|
|
22
|
-
const pwd = args[1] || await question('password:', true);
|
|
23
|
-
const {token, info} = await post('/user/login', {
|
|
9
|
+
export const commands = {
|
|
10
|
+
login: async function ({ args }) {
|
|
11
|
+
const email = args[0] || (await question('email:'));
|
|
12
|
+
const pwd = args[1] || (await question('password:', true));
|
|
13
|
+
const { token, info } = await post('/user/login', {
|
|
24
14
|
email,
|
|
25
15
|
pwd: md5(pwd),
|
|
26
16
|
});
|
|
27
|
-
replaceSession({token});
|
|
17
|
+
replaceSession({ token });
|
|
28
18
|
await saveSession();
|
|
29
19
|
console.log(`欢迎使用 pushy 热更新服务, ${info.name}.`);
|
|
30
20
|
},
|
|
31
|
-
logout: async function (){
|
|
21
|
+
logout: async function () {
|
|
32
22
|
await closeSession();
|
|
33
23
|
console.log('已退出登录');
|
|
34
24
|
},
|
|
35
|
-
me: async function (){
|
|
25
|
+
me: async function () {
|
|
36
26
|
const me = await get('/user/me');
|
|
37
27
|
for (const k in me) {
|
|
38
28
|
if (k !== 'ok') {
|
|
@@ -40,4 +30,4 @@ exports.commands = {
|
|
|
40
30
|
}
|
|
41
31
|
}
|
|
42
32
|
},
|
|
43
|
-
}
|
|
33
|
+
};
|
package/src/utils/index.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by tdzl2003 on 2/13/16.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
import fs from 'fs-extra';
|
|
6
2
|
import os from 'os';
|
|
7
3
|
import path from 'path';
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
import pkg from '../../package.json';
|
|
5
|
+
import AppInfoParser from 'app-info-parser';
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
import read from 'read';
|
|
12
8
|
|
|
13
9
|
export function question(query, password) {
|
|
14
10
|
if (NO_INTERACTIVE) {
|
package/src/versions.js
CHANGED