react-native-update-cli 1.44.7 → 1.45.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 CHANGED
@@ -18,6 +18,9 @@ _export(exports, {
18
18
  get: function() {
19
19
  return get;
20
20
  },
21
+ getAllPackages: function() {
22
+ return getAllPackages;
23
+ },
21
24
  getSession: function() {
22
25
  return getSession;
23
26
  },
@@ -191,3 +194,7 @@ async function uploadFile(fn, key) {
191
194
  hash: key || formData.key
192
195
  };
193
196
  }
197
+ const getAllPackages = async (appId)=>{
198
+ const { data } = await get(`/app/${appId}/package/list?limit=1000`);
199
+ return data;
200
+ };
package/lib/app.js CHANGED
@@ -9,8 +9,8 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- checkPlatform: function() {
13
- return checkPlatform;
12
+ assertPlatform: function() {
13
+ return assertPlatform;
14
14
  },
15
15
  chooseApp: function() {
16
16
  return chooseApp;
@@ -18,6 +18,9 @@ _export(exports, {
18
18
  commands: function() {
19
19
  return commands;
20
20
  },
21
+ getPlatform: function() {
22
+ return getPlatform;
23
+ },
21
24
  getSelectedApp: function() {
22
25
  return getSelectedApp;
23
26
  },
@@ -40,7 +43,10 @@ const validPlatforms = [
40
43
  'android',
41
44
  'harmony'
42
45
  ];
43
- function checkPlatform(platform) {
46
+ async function getPlatform(platform) {
47
+ return assertPlatform(platform || await (0, _utils.question)((0, _i18n.t)('platformQuestion')));
48
+ }
49
+ function assertPlatform(platform) {
44
50
  if (!validPlatforms.includes(platform)) {
45
51
  throw new Error((0, _i18n.t)('unsupportedPlatform', {
46
52
  platform
@@ -49,7 +55,7 @@ function checkPlatform(platform) {
49
55
  return platform;
50
56
  }
51
57
  function getSelectedApp(platform) {
52
- checkPlatform(platform);
58
+ assertPlatform(platform);
53
59
  if (!_fs.default.existsSync('update.json')) {
54
60
  throw new Error((0, _i18n.t)('appNotSelected', {
55
61
  platform
@@ -106,7 +112,7 @@ const commands = {
106
112
  createApp: async function({ options }) {
107
113
  const name = options.name || await (0, _utils.question)((0, _i18n.t)('appNameQuestion'));
108
114
  const { downloadUrl } = options;
109
- const platform = checkPlatform(options.platform || await (0, _utils.question)((0, _i18n.t)('platformQuestion')));
115
+ const platform = await getPlatform(options.platform);
110
116
  const { id } = await (0, _api.post)('/app/create', {
111
117
  name,
112
118
  platform,
@@ -138,7 +144,7 @@ const commands = {
138
144
  listApp(platform);
139
145
  },
140
146
  selectApp: async ({ args, options })=>{
141
- const platform = checkPlatform(options.platform || await (0, _utils.question)((0, _i18n.t)('platformQuestion')));
147
+ const platform = await getPlatform(options.platform);
142
148
  const id = args[0] ? Number.parseInt(args[0]) : (await chooseApp(platform)).id;
143
149
  let updateInfo = {};
144
150
  if (_fs.default.existsSync('update.json')) {
package/lib/bundle.js CHANGED
@@ -779,7 +779,7 @@ function diffArgsCheck(args, options, diffFn) {
779
779
  }
780
780
  const commands = {
781
781
  bundle: async ({ options })=>{
782
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)((0, _i18n.t)('platformPrompt')));
782
+ const platform = await (0, _app.getPlatform)(options.platform);
783
783
  const { bundleName, entryFile, intermediaDir, output, dev, sourcemap, taro, expo, rncli, disableHermes, name, description, metaInfo } = (0, _utils.translateOptions)({
784
784
  ...options,
785
785
  tempDir: _constants.tempDir,
package/lib/locales/en.js CHANGED
@@ -63,9 +63,11 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
63
63
  multipleLocksFound: 'Multiple lock files detected ({{- lockFiles}}), which may cause inconsistent dependencies and hot-updating issues.',
64
64
  nativePackageId: 'Native Package ID',
65
65
  nativeVersion: 'Native Version',
66
- nativeVersionNotFound: 'No native version found >= {{version}}',
67
- nativeVersionNotFoundLess: 'No native version found <= {{version}}',
66
+ nativeVersionNotFoundGte: 'No native version found >= {{version}}',
67
+ nativeVersionNotFoundLte: 'No native version found <= {{version}}',
68
68
  nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
69
+ nativePackageIdNotFound: 'No native package id found: {{id}}',
70
+ noPackagesFound: 'No packages found. (appId: {{appId}})',
69
71
  offset: 'Offset {{offset}}',
70
72
  operationComplete: 'Operation complete, bound to {{count}} native versions',
71
73
  operationSuccess: 'Operation successful',
@@ -105,5 +107,10 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
105
107
  usageUploadApp: 'Usage: cresc uploadApp <app file>',
106
108
  usageUploadIpa: 'Usage: cresc uploadIpa <ipa file>',
107
109
  versionBind: 'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
108
- welcomeMessage: 'Welcome to Cresc hot update service, {{name}}.'
110
+ welcomeMessage: 'Welcome to Cresc hot update service, {{name}}.',
111
+ versionNameQuestion: 'Enter version name:',
112
+ versionDescriptionQuestion: 'Enter version description:',
113
+ versionMetaInfoQuestion: 'Enter custom meta info:',
114
+ updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
115
+ unnamed: '(Unnamed)'
109
116
  };
package/lib/locales/zh.js CHANGED
@@ -63,9 +63,11 @@ const _default = {
63
63
  multipleLocksFound: '检测到多种不同格式的锁文件({{- lockFiles}}),这可能导致依赖关系不一致而使热更异常。',
64
64
  nativePackageId: '原生包 Id',
65
65
  nativeVersion: '原生版本',
66
- nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
67
- nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
66
+ nativeVersionNotFoundGte: '未查询到 >= {{version}} 的原生版本',
67
+ nativeVersionNotFoundLte: '未查询到 <= {{version}} 的原生版本',
68
68
  nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
69
+ nativePackageIdNotFound: '未查询到原生包 id: {{id}}',
70
+ noPackagesFound: '未查询到任何原生包(appId: {{appId}})',
69
71
  offset: '偏移量 {{offset}}',
70
72
  operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
71
73
  operationSuccess: '操作成功',
@@ -104,5 +106,10 @@ const _default = {
104
106
  usageUploadApp: '使用方法: pushy uploadApp app后缀文件',
105
107
  usageUploadIpa: '使用方法: pushy uploadIpa ipa后缀文件',
106
108
  versionBind: '已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
107
- welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。'
109
+ welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
110
+ versionNameQuestion: '输入版本名称:',
111
+ versionDescriptionQuestion: '输入版本描述:',
112
+ versionMetaInfoQuestion: '输入自定义的 meta info:',
113
+ updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
114
+ unnamed: '(未命名)'
108
115
  };
package/lib/package.js CHANGED
@@ -32,7 +32,7 @@ function _interop_require_default(obj) {
32
32
  };
33
33
  }
34
34
  async function listPackage(appId) {
35
- const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
35
+ const allPkgs = await (0, _api.getAllPackages)(appId);
36
36
  const header = [
37
37
  {
38
38
  value: (0, _i18n.t)('nativePackageId')
@@ -42,7 +42,7 @@ async function listPackage(appId) {
42
42
  }
43
43
  ];
44
44
  const rows = [];
45
- for (const pkg of data){
45
+ for (const pkg of allPkgs){
46
46
  const { version } = pkg;
47
47
  let versionInfo = '';
48
48
  if (version) {
@@ -66,9 +66,9 @@ async function listPackage(appId) {
66
66
  }
67
67
  console.log((0, _ttytable.default)(header, rows).render());
68
68
  console.log((0, _i18n.t)('totalPackages', {
69
- count: data.length
69
+ count: allPkgs.length
70
70
  }));
71
- return data;
71
+ return allPkgs;
72
72
  }
73
73
  async function choosePackage(appId) {
74
74
  const list = await listPackage(appId);
@@ -205,7 +205,7 @@ const commands = {
205
205
  console.log(await (0, _utils.getApkInfo)(fn));
206
206
  },
207
207
  packages: async ({ options })=>{
208
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)((0, _i18n.t)('platformPrompt')));
208
+ const platform = await (0, _app.getPlatform)(options.platform);
209
209
  const { appId } = await (0, _app.getSelectedApp)(platform);
210
210
  await listPackage(appId);
211
211
  }
package/lib/versions.js CHANGED
@@ -2,9 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "commands", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ bindVersionToPackages: function() {
13
+ return bindVersionToPackages;
14
+ },
15
+ commands: function() {
8
16
  return commands;
9
17
  }
10
18
  });
@@ -13,9 +21,14 @@ const _utils = require("./utils");
13
21
  const _i18n = require("./utils/i18n");
14
22
  const _app = require("./app");
15
23
  const _package = require("./package");
16
- const _compareversions = require("compare-versions");
17
24
  const _depversions = require("./utils/dep-versions");
18
25
  const _git = require("./utils/git");
26
+ const _satisfies = /*#__PURE__*/ _interop_require_default(require("semver/functions/satisfies"));
27
+ function _interop_require_default(obj) {
28
+ return obj && obj.__esModule ? obj : {
29
+ default: obj
30
+ };
31
+ }
19
32
  async function showVersion(appId, offset) {
20
33
  const { data, count } = await (0, _api.get)(`/app/${appId}/version/list`);
21
34
  console.log((0, _i18n.t)('offset', {
@@ -86,6 +99,36 @@ async function chooseVersion(appId) {
86
99
  }
87
100
  }
88
101
  }
102
+ const bindVersionToPackages = async ({ appId, versionId, pkgs, rollout })=>{
103
+ if (rollout !== undefined) {
104
+ const rolloutConfig = {};
105
+ for (const pkg of pkgs){
106
+ rolloutConfig[pkg.name] = rollout;
107
+ }
108
+ await (0, _api.put)(`/app/${appId}/version/${versionId}`, {
109
+ config: {
110
+ rollout: rolloutConfig
111
+ }
112
+ });
113
+ console.log(`${(0, _i18n.t)('rolloutConfigSet', {
114
+ versions: pkgs.map((pkg)=>pkg.name).join(', '),
115
+ rollout: rollout
116
+ })}`);
117
+ }
118
+ for (const pkg of pkgs){
119
+ await (0, _api.put)(`/app/${appId}/package/${pkg.id}`, {
120
+ versionId
121
+ });
122
+ console.log(`${(0, _i18n.t)('versionBind', {
123
+ version: versionId,
124
+ nativeVersion: pkg.name,
125
+ id: pkg.id
126
+ })}`);
127
+ }
128
+ console.log((0, _i18n.t)('operationComplete', {
129
+ count: pkgs.length
130
+ }));
131
+ };
89
132
  const commands = {
90
133
  publish: async function({ args, options }) {
91
134
  const fn = args[0];
@@ -93,15 +136,15 @@ const commands = {
93
136
  if (!fn || !fn.endsWith('.ppk')) {
94
137
  throw new Error((0, _i18n.t)('publishUsage'));
95
138
  }
96
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
139
+ const platform = await (0, _app.getPlatform)(options.platform);
97
140
  const { appId } = await (0, _app.getSelectedApp)(platform);
98
141
  const { hash } = await (0, _api.uploadFile)(fn);
99
- const versionName = name || await (0, _utils.question)('输入版本名称: ') || '(未命名)';
142
+ const versionName = name || await (0, _utils.question)((0, _i18n.t)('versionNameQuestion')) || (0, _i18n.t)('unnamed');
100
143
  const { id } = await (0, _api.post)(`/app/${appId}/version/create`, {
101
144
  name: versionName,
102
145
  hash,
103
- description: description || await (0, _utils.question)('输入版本描述:'),
104
- metaInfo: metaInfo || await (0, _utils.question)('输入自定义的 meta info:'),
146
+ description: description || await (0, _utils.question)((0, _i18n.t)('versionDescriptionQuestion')),
147
+ metaInfo: metaInfo || await (0, _utils.question)((0, _i18n.t)('versionMetaInfoQuestion')),
105
148
  deps: _depversions.depVersions,
106
149
  commit: await (0, _git.getCommitInfo)()
107
150
  });
@@ -110,7 +153,7 @@ const commands = {
110
153
  console.log((0, _i18n.t)('packageUploadSuccess', {
111
154
  id
112
155
  }));
113
- const v = await (0, _utils.question)('是否现在将此热更应用到原生包上?(Y/N)');
156
+ const v = await (0, _utils.question)((0, _i18n.t)('updateNativePackageQuestion'));
114
157
  if (v.toLowerCase() === 'y') {
115
158
  await this.update({
116
159
  args: [],
@@ -123,21 +166,22 @@ const commands = {
123
166
  return versionName;
124
167
  },
125
168
  versions: async ({ options })=>{
126
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
169
+ const platform = await (0, _app.getPlatform)(options.platform);
127
170
  const { appId } = await (0, _app.getSelectedApp)(platform);
128
171
  await listVersions(appId);
129
172
  },
130
173
  update: async ({ args, options })=>{
131
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
174
+ const platform = await (0, _app.getPlatform)(options.platform);
132
175
  const { appId } = await (0, _app.getSelectedApp)(platform);
133
176
  let versionId = options.versionId || (await chooseVersion(appId)).id;
134
177
  if (versionId === 'null') {
135
178
  versionId = undefined;
136
179
  }
137
- let pkgId;
180
+ let pkgId = options.packageId;
138
181
  let pkgVersion = options.packageVersion;
139
182
  let minPkgVersion = options.minPackageVersion;
140
183
  let maxPkgVersion = options.maxPackageVersion;
184
+ let semverRange = options.semverRange;
141
185
  let rollout = undefined;
142
186
  if (options.rollout !== undefined) {
143
187
  try {
@@ -149,135 +193,77 @@ const commands = {
149
193
  throw new Error((0, _i18n.t)('rolloutRangeError'));
150
194
  }
151
195
  }
196
+ const allPkgs = await (0, _api.getAllPackages)(appId);
197
+ if (!allPkgs) {
198
+ throw new Error((0, _i18n.t)('noPackagesFound', {
199
+ appId
200
+ }));
201
+ }
202
+ let pkgsToBind = [];
152
203
  if (minPkgVersion) {
153
204
  minPkgVersion = String(minPkgVersion).trim();
154
- const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
155
- const pkgs = data.filter((pkg)=>(0, _compareversions.compare)(pkg.name, minPkgVersion, '>='));
156
- if (pkgs.length === 0) {
157
- throw new Error((0, _i18n.t)('nativeVersionNotFound', {
205
+ pkgsToBind = allPkgs.filter((pkg)=>(0, _satisfies.default)(pkg.name, `>=${minPkgVersion}`));
206
+ if (pkgsToBind.length === 0) {
207
+ throw new Error((0, _i18n.t)('nativeVersionNotFoundGte', {
158
208
  version: minPkgVersion
159
209
  }));
160
210
  }
161
- if (rollout !== undefined) {
162
- const rolloutConfig = {};
163
- for (const pkg of pkgs){
164
- rolloutConfig[pkg.name] = rollout;
165
- }
166
- await (0, _api.put)(`/app/${appId}/version/${versionId}`, {
167
- config: {
168
- rollout: rolloutConfig
169
- }
170
- });
171
- console.log(`${(0, _i18n.t)('rolloutConfigSet', {
172
- versions: pkgs.map((pkg)=>pkg.name).join(', '),
173
- rollout: rollout
174
- })}`);
175
- }
176
- for (const pkg of pkgs){
177
- await (0, _api.put)(`/app/${appId}/package/${pkg.id}`, {
178
- versionId
179
- });
180
- console.log(`${(0, _i18n.t)('versionBind', {
181
- version: versionId,
182
- nativeVersion: pkg.name,
183
- id: pkg.id
184
- })}`);
185
- }
186
- console.log((0, _i18n.t)('operationComplete', {
187
- count: pkgs.length
188
- }));
189
- return;
190
- }
191
- if (maxPkgVersion) {
211
+ } else if (maxPkgVersion) {
192
212
  maxPkgVersion = String(maxPkgVersion).trim();
193
- const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
194
- const pkgs = data.filter((pkg)=>(0, _compareversions.compare)(pkg.name, maxPkgVersion, '<='));
195
- if (pkgs.length === 0) {
196
- throw new Error((0, _i18n.t)('nativeVersionNotFoundLess', {
213
+ pkgsToBind = allPkgs.filter((pkg)=>(0, _satisfies.default)(pkg.name, `<=${maxPkgVersion}`));
214
+ if (pkgsToBind.length === 0) {
215
+ throw new Error((0, _i18n.t)('nativeVersionNotFoundLte', {
197
216
  version: maxPkgVersion
198
217
  }));
199
218
  }
200
- if (rollout !== undefined) {
201
- const rolloutConfig = {};
202
- for (const pkg of pkgs){
203
- rolloutConfig[pkg.name] = rollout;
204
- }
205
- await (0, _api.put)(`/app/${appId}/version/${versionId}`, {
206
- config: {
207
- rollout: rolloutConfig
208
- }
209
- });
210
- console.log(`${(0, _i18n.t)('rolloutConfigSet', {
211
- versions: pkgs.map((pkg)=>pkg.name).join(', '),
212
- rollout: rollout
213
- })}`);
214
- }
215
- for (const pkg of pkgs){
216
- await (0, _api.put)(`/app/${appId}/package/${pkg.id}`, {
217
- versionId
218
- });
219
- console.log(`${(0, _i18n.t)('versionBind', {
220
- version: versionId,
221
- nativeVersion: pkg.name,
222
- id: pkg.id
223
- })}`);
224
- }
225
- console.log((0, _i18n.t)('operationComplete', {
226
- count: pkgs.length
227
- }));
228
- return;
229
- }
230
- const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
231
- if (pkgVersion) {
219
+ } else if (pkgVersion) {
232
220
  pkgVersion = pkgVersion.trim();
233
- const pkg = data.find((pkg)=>pkg.name === pkgVersion);
221
+ const pkg = allPkgs.find((pkg)=>pkg.name === pkgVersion);
234
222
  if (pkg) {
235
- pkgId = pkg.id;
223
+ pkgsToBind = [
224
+ pkg
225
+ ];
236
226
  } else {
237
227
  throw new Error((0, _i18n.t)('nativeVersionNotFoundMatch', {
238
228
  version: pkgVersion
239
229
  }));
240
230
  }
241
- }
242
- if (!pkgId) {
243
- pkgId = options.packageId || (await (0, _package.choosePackage)(appId)).id;
244
- }
245
- if (!pkgId) {
246
- throw new Error((0, _i18n.t)('packageIdRequired'));
247
- }
248
- if (!pkgVersion) {
249
- const pkg = data.find((pkg)=>String(pkg.id) === String(pkgId));
231
+ } else if (semverRange) {
232
+ semverRange = semverRange.trim();
233
+ pkgsToBind = allPkgs.filter((pkg)=>(0, _satisfies.default)(pkg.name, semverRange));
234
+ if (pkgsToBind.length === 0) {
235
+ throw new Error((0, _i18n.t)('nativeVersionNotFoundMatch', {
236
+ version: semverRange
237
+ }));
238
+ }
239
+ } else {
240
+ if (!pkgId) {
241
+ pkgId = (await (0, _package.choosePackage)(appId)).id;
242
+ }
243
+ if (!pkgId) {
244
+ throw new Error((0, _i18n.t)('packageIdRequired'));
245
+ }
246
+ const pkg = allPkgs.find((pkg)=>String(pkg.id) === String(pkgId));
250
247
  if (pkg) {
251
- pkgVersion = pkg.name;
248
+ pkgsToBind = [
249
+ pkg
250
+ ];
251
+ } else {
252
+ throw new Error((0, _i18n.t)('nativePackageIdNotFound', {
253
+ id: pkgId
254
+ }));
252
255
  }
253
256
  }
254
- if (rollout !== undefined && pkgVersion) {
255
- await (0, _api.put)(`/app/${appId}/version/${versionId}`, {
256
- config: {
257
- rollout: {
258
- [pkgVersion]: rollout
259
- }
260
- }
261
- });
262
- console.log(`${(0, _i18n.t)('rolloutConfigSet', {
263
- versions: pkgVersion,
264
- rollout: rollout
265
- })}`);
266
- }
267
- if (versionId !== undefined) {
268
- await (0, _api.put)(`/app/${appId}/package/${pkgId}`, {
269
- versionId
270
- });
271
- console.log(`${(0, _i18n.t)('versionBind', {
272
- version: versionId,
273
- nativeVersion: pkgVersion,
274
- id: pkgId
275
- })}`);
276
- }
257
+ await bindVersionToPackages({
258
+ appId,
259
+ versionId,
260
+ pkgs: pkgsToBind,
261
+ rollout
262
+ });
277
263
  console.log((0, _i18n.t)('operationSuccess'));
278
264
  },
279
265
  updateVersionInfo: async ({ args, options })=>{
280
- const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
266
+ const platform = await (0, _app.getPlatform)(options.platform);
281
267
  const { appId } = await (0, _app.getSelectedApp)(platform);
282
268
  const versionId = options.versionId || (await chooseVersion(appId)).id;
283
269
  const updateParams = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-update-cli",
3
- "version": "1.44.7",
3
+ "version": "1.45.0",
4
4
  "description": "command line tool for react-native-update (remote updates for react native)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -42,7 +42,6 @@
42
42
  "chalk": "4",
43
43
  "cli-arguments": "^0.2.1",
44
44
  "commander": "^13",
45
- "compare-versions": "^6.1.1",
46
45
  "filesize-parser": "^1.5.1",
47
46
  "form-data": "^4.0.2",
48
47
  "fs-extra": "8",
@@ -57,7 +56,7 @@
57
56
  "properties": "^1.2.1",
58
57
  "read": "^4.1.0",
59
58
  "registry-auth-token": "^5.1.0",
60
- "semver": "^7.7.1",
59
+ "semver": "^7.7.2",
61
60
  "tcp-ping": "^0.1.1",
62
61
  "tty-table": "4.2",
63
62
  "yauzl": "^3.2.0",
@@ -68,11 +67,11 @@
68
67
  },
69
68
  "devDependencies": {
70
69
  "@biomejs/biome": "^1.9.4",
71
- "@swc/cli": "0.7.3",
70
+ "@swc/cli": "0.7.7",
72
71
  "@swc/core": "^1.11.24",
73
72
  "@types/filesize-parser": "^1.5.3",
74
73
  "@types/fs-extra": "^11.0.4",
75
- "@types/node": "^22.14.1",
74
+ "@types/node": "^22.15.18",
76
75
  "@types/node-fetch": "^2.6.12",
77
76
  "@types/progress": "^2.0.7",
78
77
  "@types/semver": "^7.7.0",
package/src/api.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  credentialFile,
12
12
  defaultEndpoint,
13
13
  } from './utils/constants';
14
- import type { Session } from 'types';
14
+ import type { Session, Package } from 'types';
15
15
  import FormData from 'form-data';
16
16
  import { t } from './utils/i18n';
17
17
 
@@ -177,3 +177,8 @@ export async function uploadFile(fn: string, key?: string) {
177
177
  // const body = await response.json();
178
178
  return { hash: key || formData.key };
179
179
  }
180
+
181
+ export const getAllPackages = async (appId: string) => {
182
+ const { data } = await get(`/app/${appId}/package/list?limit=1000`);
183
+ return data as Package[] | undefined | null;
184
+ };
package/src/app.ts CHANGED
@@ -8,7 +8,13 @@ import { t } from './utils/i18n';
8
8
 
9
9
  const validPlatforms = ['ios', 'android', 'harmony'];
10
10
 
11
- export function checkPlatform(platform: Platform) {
11
+ export async function getPlatform(platform?: string) {
12
+ return assertPlatform(
13
+ platform || (await question(t('platformQuestion'))),
14
+ ) as Platform;
15
+ }
16
+
17
+ export function assertPlatform(platform: string) {
12
18
  if (!validPlatforms.includes(platform)) {
13
19
  throw new Error(t('unsupportedPlatform', { platform }));
14
20
  }
@@ -16,7 +22,7 @@ export function checkPlatform(platform: Platform) {
16
22
  }
17
23
 
18
24
  export function getSelectedApp(platform: Platform) {
19
- checkPlatform(platform);
25
+ assertPlatform(platform);
20
26
 
21
27
  if (!fs.existsSync('update.json')) {
22
28
  throw new Error(t('appNotSelected', { platform }));
@@ -68,9 +74,7 @@ export const commands = {
68
74
  }) {
69
75
  const name = options.name || (await question(t('appNameQuestion')));
70
76
  const { downloadUrl } = options;
71
- const platform = checkPlatform(
72
- options.platform || (await question(t('platformQuestion'))),
73
- );
77
+ const platform = await getPlatform(options.platform);
74
78
  const { id } = await post('/app/create', { name, platform, downloadUrl });
75
79
  console.log(t('createAppSuccess', { id }));
76
80
  await this.selectApp({
@@ -104,9 +108,7 @@ export const commands = {
104
108
  args: string[];
105
109
  options: { platform: Platform };
106
110
  }) => {
107
- const platform = checkPlatform(
108
- options.platform || (await question(t('platformQuestion'))),
109
- );
111
+ const platform = await getPlatform(options.platform);
110
112
  const id = args[0]
111
113
  ? Number.parseInt(args[0])
112
114
  : (await chooseApp(platform)).id;
package/src/bundle.ts CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  type ZipFile as YauzlZipFile,
9
9
  } from 'yauzl';
10
10
  import { question, checkPlugins } from './utils';
11
- import { checkPlatform } from './app';
11
+ import { checkPlatform, getPlatform } from './app';
12
12
  import { spawn, spawnSync } from 'child_process';
13
13
  import semverSatisfies from 'semver/functions/satisfies';
14
14
  const g2js = require('gradle-to-js/lib/parser');
@@ -902,9 +902,7 @@ function diffArgsCheck(args: string[], options: any, diffFn: string) {
902
902
 
903
903
  export const commands = {
904
904
  bundle: async ({ options }) => {
905
- const platform = checkPlatform(
906
- options.platform || (await question(t('platformPrompt'))),
907
- );
905
+ const platform = await getPlatform(options.platform);
908
906
 
909
907
  const {
910
908
  bundleName,
package/src/locales/en.ts CHANGED
@@ -73,9 +73,11 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
73
73
  'Multiple lock files detected ({{- lockFiles}}), which may cause inconsistent dependencies and hot-updating issues.',
74
74
  nativePackageId: 'Native Package ID',
75
75
  nativeVersion: 'Native Version',
76
- nativeVersionNotFound: 'No native version found >= {{version}}',
77
- nativeVersionNotFoundLess: 'No native version found <= {{version}}',
76
+ nativeVersionNotFoundGte: 'No native version found >= {{version}}',
77
+ nativeVersionNotFoundLte: 'No native version found <= {{version}}',
78
78
  nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
79
+ nativePackageIdNotFound: 'No native package id found: {{id}}',
80
+ noPackagesFound: 'No packages found. (appId: {{appId}})',
79
81
  offset: 'Offset {{offset}}',
80
82
  operationComplete: 'Operation complete, bound to {{count}} native versions',
81
83
  operationSuccess: 'Operation successful',
@@ -122,4 +124,9 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
122
124
  versionBind:
123
125
  'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
124
126
  welcomeMessage: 'Welcome to Cresc hot update service, {{name}}.',
127
+ versionNameQuestion: 'Enter version name:',
128
+ versionDescriptionQuestion: 'Enter version description:',
129
+ versionMetaInfoQuestion: 'Enter custom meta info:',
130
+ updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
131
+ unnamed: '(Unnamed)',
125
132
  };
package/src/locales/zh.ts CHANGED
@@ -69,9 +69,11 @@ export default {
69
69
  '检测到多种不同格式的锁文件({{- lockFiles}}),这可能导致依赖关系不一致而使热更异常。',
70
70
  nativePackageId: '原生包 Id',
71
71
  nativeVersion: '原生版本',
72
- nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
73
- nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
72
+ nativeVersionNotFoundGte: '未查询到 >= {{version}} 的原生版本',
73
+ nativeVersionNotFoundLte: '未查询到 <= {{version}} 的原生版本',
74
74
  nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
75
+ nativePackageIdNotFound: '未查询到原生包 id: {{id}}',
76
+ noPackagesFound: '未查询到任何原生包(appId: {{appId}})',
75
77
  offset: '偏移量 {{offset}}',
76
78
  operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
77
79
  operationSuccess: '操作成功',
@@ -115,4 +117,9 @@ export default {
115
117
  versionBind:
116
118
  '已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
117
119
  welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
120
+ versionNameQuestion: '输入版本名称:',
121
+ versionDescriptionQuestion: '输入版本描述:',
122
+ versionMetaInfoQuestion: '输入自定义的 meta info:',
123
+ updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
124
+ unnamed: '(未命名)',
118
125
  };
package/src/package.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { get, post, uploadFile } from './api';
1
+ import { get, getAllPackages, post, uploadFile } from './api';
2
2
  import { question, saveToLocal } from './utils';
3
3
  import { t } from './utils/i18n';
4
4
 
5
- import { checkPlatform, getSelectedApp } from './app';
5
+ import { checkPlatform, getPlatform, getSelectedApp } from './app';
6
6
 
7
7
  import { getApkInfo, getIpaInfo, getAppInfo } from './utils';
8
8
  import Table from 'tty-table';
@@ -11,14 +11,14 @@ import { getCommitInfo } from './utils/git';
11
11
  import type { Platform } from 'types';
12
12
 
13
13
  export async function listPackage(appId: string) {
14
- const { data } = await get(`/app/${appId}/package/list?limit=1000`);
14
+ const allPkgs = await getAllPackages(appId);
15
15
 
16
16
  const header = [
17
17
  { value: t('nativePackageId') },
18
18
  { value: t('nativeVersion') },
19
19
  ];
20
20
  const rows = [];
21
- for (const pkg of data) {
21
+ for (const pkg of allPkgs) {
22
22
  const { version } = pkg;
23
23
  let versionInfo = '';
24
24
  if (version) {
@@ -36,8 +36,8 @@ export async function listPackage(appId: string) {
36
36
  }
37
37
 
38
38
  console.log(Table(header, rows).render());
39
- console.log(t('totalPackages', { count: data.length }));
40
- return data;
39
+ console.log(t('totalPackages', { count: allPkgs.length }));
40
+ return allPkgs;
41
41
  }
42
42
 
43
43
  export async function choosePackage(appId: string) {
@@ -174,9 +174,7 @@ export const commands = {
174
174
  console.log(await getApkInfo(fn));
175
175
  },
176
176
  packages: async ({ options }: { options: { platform: Platform } }) => {
177
- const platform = checkPlatform(
178
- options.platform || (await question(t('platformPrompt'))),
179
- );
177
+ const platform = await getPlatform(options.platform);
180
178
  const { appId } = await getSelectedApp(platform);
181
179
  await listPackage(appId);
182
180
  },
package/src/types.ts CHANGED
@@ -8,3 +8,15 @@ export interface Session {
8
8
  }
9
9
 
10
10
  export type Platform = 'ios' | 'android' | 'harmony';
11
+
12
+ export interface Package {
13
+ id: string;
14
+ name: string;
15
+ }
16
+
17
+ export interface Version {
18
+ id: string;
19
+ hash: string;
20
+ name: string;
21
+ packages?: Package[];
22
+ }
package/src/versions.ts CHANGED
@@ -1,25 +1,13 @@
1
- import { get, post, put, uploadFile } from './api';
1
+ import { get, getAllPackages, post, put, uploadFile } from './api';
2
2
  import { question, saveToLocal } from './utils';
3
3
  import { t } from './utils/i18n';
4
4
 
5
- import { checkPlatform, getSelectedApp } from './app';
5
+ import { getPlatform, getSelectedApp } from './app';
6
6
  import { choosePackage } from './package';
7
- import { compare } from 'compare-versions';
8
7
  import { depVersions } from './utils/dep-versions';
9
8
  import { getCommitInfo } from './utils/git';
10
- import type { Platform } from 'types';
11
-
12
- interface Package {
13
- id: string;
14
- name: string;
15
- }
16
-
17
- interface Version {
18
- id: string;
19
- hash: string;
20
- name: string;
21
- packages?: Package[];
22
- }
9
+ import type { Package, Platform, Version } from 'types';
10
+ import semverSatisfies from 'semver/functions/satisfies';
23
11
 
24
12
  interface CommandOptions {
25
13
  name?: string;
@@ -31,6 +19,7 @@ interface CommandOptions {
31
19
  packageVersion?: string;
32
20
  minPackageVersion?: string;
33
21
  maxPackageVersion?: string;
22
+ semverRange?: string;
34
23
  rollout?: string;
35
24
  }
36
25
 
@@ -113,6 +102,49 @@ async function chooseVersion(appId: string) {
113
102
  }
114
103
  }
115
104
 
105
+ export const bindVersionToPackages = async ({
106
+ appId,
107
+ versionId,
108
+ pkgs,
109
+ rollout,
110
+ }: {
111
+ appId: string;
112
+ versionId: string;
113
+ pkgs: Package[];
114
+ rollout?: number;
115
+ }) => {
116
+ if (rollout !== undefined) {
117
+ const rolloutConfig: Record<string, number> = {};
118
+ for (const pkg of pkgs) {
119
+ rolloutConfig[pkg.name] = rollout;
120
+ }
121
+ await put(`/app/${appId}/version/${versionId}`, {
122
+ config: {
123
+ rollout: rolloutConfig,
124
+ },
125
+ });
126
+ console.log(
127
+ `${t('rolloutConfigSet', {
128
+ versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
129
+ rollout: rollout,
130
+ })}`,
131
+ );
132
+ }
133
+ for (const pkg of pkgs) {
134
+ await put(`/app/${appId}/package/${pkg.id}`, {
135
+ versionId,
136
+ });
137
+ console.log(
138
+ `${t('versionBind', {
139
+ version: versionId,
140
+ nativeVersion: pkg.name,
141
+ id: pkg.id,
142
+ })}`,
143
+ );
144
+ }
145
+ console.log(t('operationComplete', { count: pkgs.length }));
146
+ };
147
+
116
148
  export const commands = {
117
149
  publish: async function ({
118
150
  args,
@@ -128,21 +160,18 @@ export const commands = {
128
160
  throw new Error(t('publishUsage'));
129
161
  }
130
162
 
131
- const platform = checkPlatform(
132
- options.platform ||
133
- ((await question('平台(ios/android/harmony):')) as Platform),
134
- );
163
+ const platform = await getPlatform(options.platform);
135
164
  const { appId } = await getSelectedApp(platform);
136
165
 
137
166
  const { hash } = await uploadFile(fn);
138
167
 
139
168
  const versionName =
140
- name || (await question('输入版本名称: ')) || '(未命名)';
169
+ name || (await question(t('versionNameQuestion'))) || t('unnamed');
141
170
  const { id } = await post(`/app/${appId}/version/create`, {
142
171
  name: versionName,
143
172
  hash,
144
- description: description || (await question('输入版本描述:')),
145
- metaInfo: metaInfo || (await question('输入自定义的 meta info:')),
173
+ description: description || (await question(t('versionDescriptionQuestion'))),
174
+ metaInfo: metaInfo || (await question(t('versionMetaInfoQuestion'))),
146
175
  deps: depVersions,
147
176
  commit: await getCommitInfo(),
148
177
  });
@@ -150,17 +179,14 @@ export const commands = {
150
179
  saveToLocal(fn, `${appId}/ppk/${id}.ppk`);
151
180
  console.log(t('packageUploadSuccess', { id }));
152
181
 
153
- const v = await question('是否现在将此热更应用到原生包上?(Y/N)');
182
+ const v = await question(t('updateNativePackageQuestion'));
154
183
  if (v.toLowerCase() === 'y') {
155
184
  await this.update({ args: [], options: { versionId: id, platform } });
156
185
  }
157
186
  return versionName;
158
187
  },
159
188
  versions: async ({ options }: { options: CommandOptions }) => {
160
- const platform = checkPlatform(
161
- options.platform ||
162
- ((await question('平台(ios/android/harmony):')) as Platform),
163
- );
189
+ const platform = await getPlatform(options.platform);
164
190
  const { appId } = await getSelectedApp(platform);
165
191
  await listVersions(appId);
166
192
  },
@@ -171,20 +197,18 @@ export const commands = {
171
197
  args: string[];
172
198
  options: CommandOptions;
173
199
  }) => {
174
- const platform = checkPlatform(
175
- options.platform ||
176
- ((await question('平台(ios/android/harmony):')) as Platform),
177
- );
200
+ const platform = await getPlatform(options.platform);
178
201
  const { appId } = await getSelectedApp(platform);
179
202
  let versionId = options.versionId || (await chooseVersion(appId)).id;
180
203
  if (versionId === 'null') {
181
204
  versionId = undefined;
182
205
  }
183
206
 
184
- let pkgId: string | undefined;
207
+ let pkgId = options.packageId;
185
208
  let pkgVersion = options.packageVersion;
186
209
  let minPkgVersion = options.minPackageVersion;
187
210
  let maxPkgVersion = options.maxPackageVersion;
211
+ let semverRange = options.semverRange;
188
212
  let rollout: number | undefined = undefined;
189
213
 
190
214
  if (options.rollout !== undefined) {
@@ -198,146 +222,78 @@ export const commands = {
198
222
  }
199
223
  }
200
224
 
225
+ const allPkgs = await getAllPackages(appId);
226
+
227
+ if (!allPkgs) {
228
+ throw new Error(t('noPackagesFound', { appId }));
229
+ }
230
+
231
+ let pkgsToBind: Package[] = [];
232
+
201
233
  if (minPkgVersion) {
202
234
  minPkgVersion = String(minPkgVersion).trim();
203
- const { data } = await get(`/app/${appId}/package/list?limit=1000`);
204
- const pkgs = data.filter((pkg: Package) =>
205
- compare(pkg.name, minPkgVersion!, '>='),
235
+ pkgsToBind = allPkgs.filter((pkg: Package) =>
236
+ semverSatisfies(pkg.name, `>=${minPkgVersion}`),
206
237
  );
207
- if (pkgs.length === 0) {
208
- throw new Error(t('nativeVersionNotFound', { version: minPkgVersion }));
209
- }
210
- if (rollout !== undefined) {
211
- const rolloutConfig: Record<string, number> = {};
212
- for (const pkg of pkgs) {
213
- rolloutConfig[pkg.name] = rollout;
214
- }
215
- await put(`/app/${appId}/version/${versionId}`, {
216
- config: {
217
- rollout: rolloutConfig,
218
- },
219
- });
220
- console.log(
221
- `${t('rolloutConfigSet', {
222
- versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
223
- rollout: rollout,
224
- })}`,
225
- );
226
- }
227
- for (const pkg of pkgs) {
228
- await put(`/app/${appId}/package/${pkg.id}`, {
229
- versionId,
230
- });
231
- console.log(
232
- `${t('versionBind', {
233
- version: versionId,
234
- nativeVersion: pkg.name,
235
- id: pkg.id,
236
- })}`,
238
+ if (pkgsToBind.length === 0) {
239
+ throw new Error(
240
+ t('nativeVersionNotFoundGte', { version: minPkgVersion }),
237
241
  );
238
242
  }
239
- console.log(t('operationComplete', { count: pkgs.length }));
240
- return;
241
- }
242
- if (maxPkgVersion) {
243
+ } else if (maxPkgVersion) {
243
244
  maxPkgVersion = String(maxPkgVersion).trim();
244
- const { data } = await get(`/app/${appId}/package/list?limit=1000`);
245
- const pkgs = data.filter((pkg: Package) =>
246
- compare(pkg.name, maxPkgVersion!, '<='),
245
+ pkgsToBind = allPkgs.filter((pkg: Package) =>
246
+ semverSatisfies(pkg.name, `<=${maxPkgVersion}`),
247
247
  );
248
- if (pkgs.length === 0) {
248
+ if (pkgsToBind.length === 0) {
249
249
  throw new Error(
250
- t('nativeVersionNotFoundLess', { version: maxPkgVersion }),
250
+ t('nativeVersionNotFoundLte', { version: maxPkgVersion }),
251
251
  );
252
252
  }
253
- if (rollout !== undefined) {
254
- const rolloutConfig: Record<string, number> = {};
255
- for (const pkg of pkgs) {
256
- rolloutConfig[pkg.name] = rollout;
257
- }
258
- await put(`/app/${appId}/version/${versionId}`, {
259
- config: {
260
- rollout: rolloutConfig,
261
- },
262
- });
263
- console.log(
264
- `${t('rolloutConfigSet', {
265
- versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
266
- rollout: rollout,
267
- })}`,
268
- );
269
- }
270
- for (const pkg of pkgs) {
271
- await put(`/app/${appId}/package/${pkg.id}`, {
272
- versionId,
273
- });
274
- console.log(
275
- `${t('versionBind', {
276
- version: versionId,
277
- nativeVersion: pkg.name,
278
- id: pkg.id,
279
- })}`,
280
- );
281
- }
282
- console.log(t('operationComplete', { count: pkgs.length }));
283
- return;
284
- }
285
-
286
- const { data } = await get(`/app/${appId}/package/list?limit=1000`);
287
- if (pkgVersion) {
253
+ } else if (pkgVersion) {
288
254
  pkgVersion = pkgVersion.trim();
289
- const pkg = data.find((pkg: Package) => pkg.name === pkgVersion);
255
+ const pkg = allPkgs.find((pkg: Package) => pkg.name === pkgVersion);
290
256
  if (pkg) {
291
- pkgId = pkg.id;
257
+ pkgsToBind = [pkg];
292
258
  } else {
293
259
  throw new Error(
294
260
  t('nativeVersionNotFoundMatch', { version: pkgVersion }),
295
261
  );
296
262
  }
297
- }
298
- if (!pkgId) {
299
- pkgId = options.packageId || (await choosePackage(appId)).id;
300
- }
301
-
302
- if (!pkgId) {
303
- throw new Error(t('packageIdRequired'));
304
- }
305
-
306
- if (!pkgVersion) {
307
- const pkg = data.find((pkg: Package) => String(pkg.id) === String(pkgId));
308
- if (pkg) {
309
- pkgVersion = pkg.name;
263
+ } else if (semverRange) {
264
+ semverRange = semverRange.trim();
265
+ pkgsToBind = allPkgs.filter((pkg: Package) =>
266
+ semverSatisfies(pkg.name, semverRange!),
267
+ );
268
+ if (pkgsToBind.length === 0) {
269
+ throw new Error(
270
+ t('nativeVersionNotFoundMatch', { version: semverRange }),
271
+ );
272
+ }
273
+ } else {
274
+ if (!pkgId) {
275
+ pkgId = (await choosePackage(appId)).id;
310
276
  }
311
- }
312
277
 
313
- if (rollout !== undefined && pkgVersion) {
314
- await put(`/app/${appId}/version/${versionId}`, {
315
- config: {
316
- rollout: {
317
- [pkgVersion]: rollout,
318
- },
319
- },
320
- });
321
- console.log(
322
- `${t('rolloutConfigSet', {
323
- versions: pkgVersion,
324
- rollout: rollout,
325
- })}`,
278
+ if (!pkgId) {
279
+ throw new Error(t('packageIdRequired'));
280
+ }
281
+ const pkg = allPkgs.find(
282
+ (pkg: Package) => String(pkg.id) === String(pkgId),
326
283
  );
284
+ if (pkg) {
285
+ pkgsToBind = [pkg];
286
+ } else {
287
+ throw new Error(t('nativePackageIdNotFound', { id: pkgId }));
288
+ }
327
289
  }
328
290
 
329
- if (versionId !== undefined) {
330
- await put(`/app/${appId}/package/${pkgId}`, {
331
- versionId,
332
- });
333
- console.log(
334
- `${t('versionBind', {
335
- version: versionId,
336
- nativeVersion: pkgVersion,
337
- id: pkgId,
338
- })}`,
339
- );
340
- }
291
+ await bindVersionToPackages({
292
+ appId,
293
+ versionId,
294
+ pkgs: pkgsToBind,
295
+ rollout,
296
+ });
341
297
  console.log(t('operationSuccess'));
342
298
  },
343
299
  updateVersionInfo: async ({
@@ -347,10 +303,7 @@ export const commands = {
347
303
  args: string[];
348
304
  options: CommandOptions;
349
305
  }) => {
350
- const platform = checkPlatform(
351
- options.platform ||
352
- ((await question('平台(ios/android/harmony):')) as Platform),
353
- );
306
+ const platform = await getPlatform(options.platform);
354
307
  const { appId } = await getSelectedApp(platform);
355
308
  const versionId = options.versionId || (await chooseVersion(appId)).id;
356
309