react-native-update-cli 1.43.5 → 1.44.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/versions.js CHANGED
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "commands", {
10
10
  });
11
11
  const _api = require("./api");
12
12
  const _utils = require("./utils");
13
+ const _i18n = require("./utils/i18n");
13
14
  const _app = require("./app");
14
15
  const _package = require("./package");
15
16
  const _compareversions = require("compare-versions");
@@ -17,7 +18,9 @@ const _depversions = require("./utils/dep-versions");
17
18
  const _git = require("./utils/git");
18
19
  async function showVersion(appId, offset) {
19
20
  const { data, count } = await (0, _api.get)(`/app/${appId}/version/list`);
20
- console.log(`Offset ${offset}`);
21
+ console.log((0, _i18n.t)('offset', {
22
+ offset
23
+ }));
21
24
  for (const version of data){
22
25
  var _version_packages;
23
26
  const pkgCount = ((_version_packages = version.packages) == null ? void 0 : _version_packages.length) || 0;
@@ -104,7 +107,9 @@ const commands = {
104
107
  });
105
108
  // TODO local diff
106
109
  (0, _utils.saveToLocal)(fn, `${appId}/ppk/${id}.ppk`);
107
- console.log(`已成功上传新热更包(id: ${id})`);
110
+ console.log((0, _i18n.t)('packageUploadSuccess', {
111
+ id
112
+ }));
108
113
  const v = await (0, _utils.question)('是否现在将此热更应用到原生包上?(Y/N)');
109
114
  if (v.toLowerCase() === 'y') {
110
115
  await this.update({
@@ -138,10 +143,10 @@ const commands = {
138
143
  try {
139
144
  rollout = Number.parseInt(options.rollout);
140
145
  } catch (e) {
141
- throw new Error('rollout 必须是 1-100 的整数');
146
+ throw new Error((0, _i18n.t)('rolloutRangeError'));
142
147
  }
143
148
  if (rollout < 1 || rollout > 100) {
144
- throw new Error('rollout 必须是 1-100 的整数');
149
+ throw new Error((0, _i18n.t)('rolloutRangeError'));
145
150
  }
146
151
  }
147
152
  if (minPkgVersion) {
@@ -149,7 +154,9 @@ const commands = {
149
154
  const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
150
155
  const pkgs = data.filter((pkg)=>(0, _compareversions.compare)(pkg.name, minPkgVersion, '>='));
151
156
  if (pkgs.length === 0) {
152
- throw new Error(`未查询到 >= ${minPkgVersion} 的原生版本`);
157
+ throw new Error((0, _i18n.t)('nativeVersionNotFound', {
158
+ version: minPkgVersion
159
+ }));
153
160
  }
154
161
  if (rollout !== undefined) {
155
162
  const rolloutConfig = {};
@@ -161,15 +168,24 @@ const commands = {
161
168
  rollout: rolloutConfig
162
169
  }
163
170
  });
164
- console.log(`已在原生版本 ${pkgs.map((pkg)=>pkg.name).join(', ')} 上设置灰度发布 ${rollout}% 热更版本 ${versionId}`);
171
+ console.log(`${(0, _i18n.t)('rolloutConfigSet', {
172
+ versions: pkgs.map((pkg)=>pkg.name).join(', '),
173
+ rollout: rollout
174
+ })}`);
165
175
  }
166
176
  for (const pkg of pkgs){
167
177
  await (0, _api.put)(`/app/${appId}/package/${pkg.id}`, {
168
178
  versionId
169
179
  });
170
- console.log(`已将热更版本 ${versionId} 绑定到原生版本 ${pkg.name} (id: ${pkg.id})`);
180
+ console.log(`${(0, _i18n.t)('versionBind', {
181
+ version: versionId,
182
+ nativeVersion: pkg.name,
183
+ id: pkg.id
184
+ })}`);
171
185
  }
172
- console.log(`操作完成,共已绑定 ${pkgs.length} 个原生版本`);
186
+ console.log((0, _i18n.t)('operationComplete', {
187
+ count: pkgs.length
188
+ }));
173
189
  return;
174
190
  }
175
191
  if (maxPkgVersion) {
@@ -177,7 +193,9 @@ const commands = {
177
193
  const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
178
194
  const pkgs = data.filter((pkg)=>(0, _compareversions.compare)(pkg.name, maxPkgVersion, '<='));
179
195
  if (pkgs.length === 0) {
180
- throw new Error(`未查询到 <= ${maxPkgVersion} 的原生版本`);
196
+ throw new Error((0, _i18n.t)('nativeVersionNotFoundLess', {
197
+ version: maxPkgVersion
198
+ }));
181
199
  }
182
200
  if (rollout !== undefined) {
183
201
  const rolloutConfig = {};
@@ -189,15 +207,24 @@ const commands = {
189
207
  rollout: rolloutConfig
190
208
  }
191
209
  });
192
- console.log(`已在原生版本 ${pkgs.map((pkg)=>pkg.name).join(', ')} 上设置灰度发布 ${rollout}% 热更版本 ${versionId}`);
210
+ console.log(`${(0, _i18n.t)('rolloutConfigSet', {
211
+ versions: pkgs.map((pkg)=>pkg.name).join(', '),
212
+ rollout: rollout
213
+ })}`);
193
214
  }
194
215
  for (const pkg of pkgs){
195
216
  await (0, _api.put)(`/app/${appId}/package/${pkg.id}`, {
196
217
  versionId
197
218
  });
198
- console.log(`已将热更版本 ${versionId} 绑定到原生版本 ${pkg.name} (id: ${pkg.id})`);
219
+ console.log(`${(0, _i18n.t)('versionBind', {
220
+ version: versionId,
221
+ nativeVersion: pkg.name,
222
+ id: pkg.id
223
+ })}`);
199
224
  }
200
- console.log(`操作完成,共已绑定 ${pkgs.length} 个原生版本`);
225
+ console.log((0, _i18n.t)('operationComplete', {
226
+ count: pkgs.length
227
+ }));
201
228
  return;
202
229
  }
203
230
  const { data } = await (0, _api.get)(`/app/${appId}/package/list?limit=1000`);
@@ -207,14 +234,16 @@ const commands = {
207
234
  if (pkg) {
208
235
  pkgId = pkg.id;
209
236
  } else {
210
- throw new Error(`未查询到匹配原生版本:${pkgVersion}`);
237
+ throw new Error((0, _i18n.t)('nativeVersionNotFoundMatch', {
238
+ version: pkgVersion
239
+ }));
211
240
  }
212
241
  }
213
242
  if (!pkgId) {
214
243
  pkgId = options.packageId || (await (0, _package.choosePackage)(appId)).id;
215
244
  }
216
245
  if (!pkgId) {
217
- throw new Error('请提供 packageId 或 packageVersion 参数');
246
+ throw new Error((0, _i18n.t)('packageIdRequired'));
218
247
  }
219
248
  if (!pkgVersion) {
220
249
  const pkg = data.find((pkg)=>String(pkg.id) === String(pkgId));
@@ -230,14 +259,22 @@ const commands = {
230
259
  }
231
260
  }
232
261
  });
233
- console.log(`已将在原生版本 ${pkgVersion} (id: ${pkgId}) 上设置灰度发布 ${rollout}% 热更版本 ${versionId} `);
262
+ console.log(`${(0, _i18n.t)('rolloutConfigSet', {
263
+ versions: pkgVersion,
264
+ rollout: rollout
265
+ })}`);
234
266
  }
235
267
  if (versionId !== undefined) {
236
268
  await (0, _api.put)(`/app/${appId}/package/${pkgId}`, {
237
269
  versionId
238
270
  });
239
- console.log(`已将热更版本 ${versionId} 绑定到原生版本 ${pkgVersion} (id: ${pkgId})`);
271
+ console.log(`${(0, _i18n.t)('versionBind', {
272
+ version: versionId,
273
+ nativeVersion: pkgVersion,
274
+ id: pkgId
275
+ })}`);
240
276
  }
277
+ console.log((0, _i18n.t)('operationSuccess'));
241
278
  },
242
279
  updateVersionInfo: async ({ args, options })=>{
243
280
  const platform = (0, _app.checkPlatform)(options.platform || await (0, _utils.question)('平台(ios/android/harmony):'));
@@ -248,6 +285,6 @@ const commands = {
248
285
  if (options.description) updateParams.description = options.description;
249
286
  if (options.metaInfo) updateParams.metaInfo = options.metaInfo;
250
287
  await (0, _api.put)(`/app/${appId}/version/${versionId}`, updateParams);
251
- console.log('操作成功');
288
+ console.log((0, _i18n.t)('operationSuccess'));
252
289
  }
253
290
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-update-cli",
3
- "version": "1.43.5",
3
+ "version": "1.44.0",
4
4
  "description": "command line tool for react-native-update (remote updates for react native)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -58,7 +58,6 @@
58
58
  "semver": "^7.7.1",
59
59
  "tcp-ping": "^0.1.1",
60
60
  "tty-table": "4.2",
61
- "update-notifier": "^5.1.0",
62
61
  "yauzl": "^3.2.0",
63
62
  "yazl": "3.3.1"
64
63
  },
@@ -67,18 +66,21 @@
67
66
  },
68
67
  "devDependencies": {
69
68
  "@biomejs/biome": "^1.9.4",
70
- "@swc/cli": "^0.6.0",
71
- "@swc/core": "^1.11.18",
69
+ "@swc/cli": "^0.7.2",
70
+ "@swc/core": "^1.11.21",
72
71
  "@types/filesize-parser": "^1.5.3",
73
72
  "@types/fs-extra": "^11.0.4",
74
- "@types/node": "^22.14.0",
73
+ "@types/node": "^22.14.1",
75
74
  "@types/node-fetch": "^2.6.12",
76
75
  "@types/progress": "^2.0.7",
77
76
  "@types/semver": "^7.7.0",
78
77
  "@types/tcp-ping": "^0.1.6",
79
- "@types/update-notifier": "^6.0.8",
80
78
  "@types/yauzl": "^2.10.3",
81
79
  "@types/yazl": "^2.4.6",
82
80
  "typescript": "^5.8.3"
83
- }
81
+ },
82
+ "trustedDependencies": [
83
+ "@biomejs/biome",
84
+ "@swc/core"
85
+ ]
84
86
  }
package/src/bundle.ts CHANGED
@@ -214,17 +214,13 @@ async function runReactNativeBundleCommand({
214
214
 
215
215
  reactNativeBundleProcess.on('close', async (exitCode) => {
216
216
  if (exitCode) {
217
- reject(
218
- new Error(
219
- `"react-native bundle" command exited with code ${exitCode}.`,
220
- ),
221
- );
217
+ reject(new Error(t('bundleCommandError', { code: exitCode })));
222
218
  } else {
223
219
  let hermesEnabled: boolean | undefined = false;
224
220
 
225
221
  if (disableHermes) {
226
222
  hermesEnabled = false;
227
- console.log('Hermes disabled');
223
+ console.log(t('hermesDisabled'));
228
224
  } else if (platform === 'android') {
229
225
  const gradlePropeties = await new Promise<{
230
226
  hermesEnabled?: boolean;
@@ -283,8 +279,8 @@ async function copyHarmonyBundle(outputFolder: string) {
283
279
  await fs.ensureDir(outputFolder);
284
280
  await fs.copy(harmonyRawPath, outputFolder);
285
281
  } catch (error: any) {
286
- console.error('copyHarmonyBundle 错误:', error);
287
- throw new Error(`复制文件失败: ${error.message}`);
282
+ console.error(t('copyHarmonyBundleError', { error }));
283
+ throw new Error(t('copyFileFailed', { error: error.message }));
288
284
  }
289
285
  }
290
286
 
@@ -355,7 +351,7 @@ async function compileHermesByteCode(
355
351
  );
356
352
  args.push('-output-source-map');
357
353
  }
358
- console.log(`Running hermesc: ${hermesCommand} ${args.join(' ')}`);
354
+ console.log(t('runningHermesc', { command: hermesCommand, args: args.join(' ') }));
359
355
  spawnSync(hermesCommand, args, {
360
356
  stdio: 'ignore',
361
357
  });
@@ -365,7 +361,7 @@ async function compileHermesByteCode(
365
361
  if (!fs.existsSync(composerPath)) {
366
362
  return;
367
363
  }
368
- console.log('Composing source map');
364
+ console.log(t('composingSourceMap'));
369
365
  spawnSync(
370
366
  'node',
371
367
  [
@@ -400,16 +396,14 @@ async function copyDebugidForSentry(
400
396
  },
401
397
  );
402
398
  } catch (error) {
403
- console.error(
404
- '无法找到 Sentry copy-debugid.js 脚本文件,请确保已正确安装 @sentry/react-native',
405
- );
399
+ console.error(t('sentryCliNotFound'));
406
400
  return;
407
401
  }
408
402
 
409
403
  if (!fs.existsSync(copyDebugidPath)) {
410
404
  return;
411
405
  }
412
- console.log('Copying debugid');
406
+ console.log(t('copyingDebugId'));
413
407
  spawnSync(
414
408
  'node',
415
409
  [
@@ -453,9 +447,9 @@ async function uploadSourcemapForSentry(
453
447
  stdio: 'inherit',
454
448
  },
455
449
  );
456
- console.log(`Sentry release created for version: ${version}`);
450
+ console.log(t('sentryReleaseCreated', { version }));
457
451
 
458
- console.log('Uploading sourcemap');
452
+ console.log(t('uploadingSourcemap'));
459
453
  spawnSync(
460
454
  'node',
461
455
  [
@@ -479,7 +473,7 @@ async function uploadSourcemapForSentry(
479
473
  const ignorePackingFileNames = ['.', '..', 'index.bundlejs.map'];
480
474
  const ignorePackingExtensions = ['DS_Store','txt.map'];
481
475
  async function pack(dir: string, output: string) {
482
- console.log('Packing');
476
+ console.log(t('packing'));
483
477
  fs.ensureDirSync(path.dirname(output));
484
478
  await new Promise<void>((resolve, reject) => {
485
479
  const zipfile = new ZipFile();
@@ -516,7 +510,7 @@ async function pack(dir: string, output: string) {
516
510
  });
517
511
  zipfile.end();
518
512
  });
519
- console.log(t('ppkPackageGenerated', { output }));
513
+ console.log(t('fileGenerated', { file: output }));
520
514
  }
521
515
 
522
516
  export function readEntire(entry: string, zipFile: ZipFile) {
@@ -671,7 +665,7 @@ async function diffFromPPK(origin: string, next: string, output: string) {
671
665
 
672
666
  for (const k in originEntries) {
673
667
  if (!newEntries[k]) {
674
- console.log(`Delete ${k}`);
668
+ console.log(t('deleteFile', { file: k }));
675
669
  deletes[k] = 1;
676
670
  }
677
671
  }
@@ -844,7 +838,7 @@ export async function enumZipEntries(
844
838
  await result;
845
839
  }
846
840
  } catch (error) {
847
- console.error('处理文件时出错:', error);
841
+ console.error(t('processingError', { error }));
848
842
  }
849
843
 
850
844
  zipfile.readEntry();
@@ -860,7 +854,7 @@ function diffArgsCheck(args, options, diffFn) {
860
854
  const [origin, next] = args;
861
855
 
862
856
  if (!origin || !next) {
863
- console.error(`Usage: pushy ${diffFn} <origin> <next>`);
857
+ console.error(t('usageDiff', { command: diffFn }));
864
858
  process.exit(1);
865
859
  }
866
860
 
@@ -927,7 +921,7 @@ export const commands = {
927
921
  const realOutput = output.replace(/\$\{time\}/g, `${Date.now()}`);
928
922
 
929
923
  if (!platform) {
930
- throw new Error('Platform must be specified.');
924
+ throw new Error(t('platformRequired'));
931
925
  }
932
926
 
933
927
  console.log(`Bundling with react-native: ${depVersions['react-native']}`);
@@ -972,14 +966,14 @@ export const commands = {
972
966
  async diff({ args, options }) {
973
967
  const { origin, next, realOutput } = diffArgsCheck(args, options, 'diff');
974
968
 
975
- await diffFromPPK(origin, next, realOutput, 'index.bundlejs');
969
+ await diffFromPPK(origin, next, realOutput);
976
970
  console.log(`${realOutput} generated.`);
977
971
  },
978
972
 
979
973
  async hdiff({ args, options }) {
980
974
  const { origin, next, realOutput } = diffArgsCheck(args, options, 'hdiff');
981
975
 
982
- await diffFromPPK(origin, next, realOutput, 'index.bundlejs');
976
+ await diffFromPPK(origin, next, realOutput);
983
977
  console.log(`${realOutput} generated.`);
984
978
  },
985
979
 
package/src/index.ts CHANGED
@@ -1,16 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { loadSession } from './api';
4
- import updateNotifier from 'update-notifier';
5
4
  import { printVersionCommand } from './utils';
6
- import pkg from '../package.json';
7
5
  import { t } from './utils/i18n';
8
6
 
9
- updateNotifier({ pkg }).notify({
10
- isGlobal: true,
11
- message: t('updateNotifier'),
12
- });
13
-
14
7
  function printUsage() {
15
8
  // const commandName = args[0];
16
9
  // TODO: print usage of commandName, or print global usage.
package/src/locales/en.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  export default {
2
- updateNotifier:
3
- 'Run `{updateCommand}` to update the CLI to get continuous improvements in features, performance, and security.',
4
2
  loginFirst:
5
3
  'Not logged in.\nPlease run `cresc login` in the project directory to login.',
6
4
  lockNotFound:
@@ -29,7 +27,7 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
29
27
  appId: 'App ID',
30
28
  appName: 'App Name',
31
29
  platform: 'Platform',
32
- totalApps: 'Total {{count}} apps',
30
+ totalApps: 'Total {{count}} {{platform}} apps',
33
31
  appNotSelected:
34
32
  'App not selected. run `cresc selectApp --platform {{platform}}` first!',
35
33
  enterAppIdQuestion: 'Enter AppId:',
@@ -38,6 +36,60 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
38
36
  createAppSuccess: 'App created successfully (id: {{id}})',
39
37
  cancelled: 'Cancelled',
40
38
  operationSuccess: 'Operation successful',
41
- failedToParseUpdateJson: 'Failed to parse file `update.json`. Try to remove it manually.',
39
+ failedToParseUpdateJson:
40
+ 'Failed to parse file `update.json`. Try to remove it manually.',
42
41
  ppkPackageGenerated: 'ppk package generated and saved to: {{- output}}',
42
+ Message: 'Welcome to Cresc hot update service, {{name}}.',
43
+ loggedOut: 'Logged out',
44
+ usageUnderDevelopment: 'Usage is under development now.',
45
+ hermesDisabled: 'Hermes disabled',
46
+ hermesEnabled: 'Hermes enabled, now compiling to hermes bytecode:\n',
47
+ runningHermesc: 'Running hermesc: {{command}} {{args}}',
48
+ composingSourceMap: 'Composing source map',
49
+ copyingDebugId: 'Copying debugid',
50
+ sentryCliNotFound:
51
+ 'Cannot find Sentry CLI tool, please make sure @sentry/cli is properly installed',
52
+ sentryReleaseCreated: 'Sentry release created for version: {{version}}',
53
+ uploadingSourcemap: 'Uploading sourcemap',
54
+ packing: 'Packing',
55
+ deletingFile: 'Delete {{- file}}',
56
+ bundlingWithRN: 'Bundling with react-native: {{version}}',
57
+ fileGenerated: '{{- file}} generated.',
58
+ processingError: 'Error processing file: {{error}}',
59
+ usageDiff: 'Usage: cresc {{command}} <origin> <next>',
60
+ pluginDetected: 'detected {{name}} plugin',
61
+ pluginDetectionError: 'error while detecting {{name}} plugin: {{error}}',
62
+ addedToGitignore: 'Added {{line}} to .gitignore',
63
+ processingStringPool: 'Processing the string pool ...',
64
+ processingPackage: 'Processing the package {{count}} ...',
65
+ typeStrings: 'Type strings:',
66
+ keyStrings: 'Key strings:',
67
+ failedToParseIcon: '[Warning] failed to parse icon: {{error}}',
68
+ errorInHarmonyApp: 'Error in getEntryFromHarmonyApp: {{error}}',
69
+ totalPackages: 'Total {{count}} packages',
70
+ usageUploadIpa: 'Usage: cresc uploadIpa <ipa file>',
71
+ usageUploadApk: 'Usage: cresc uploadApk <apk file>',
72
+ usageUploadApp: 'Usage: cresc uploadApp <app file>',
73
+ usageParseApp: 'Usage: cresc parseApp <app file>',
74
+ usageParseIpa: 'Usage: cresc parseIpa <ipa file>',
75
+ usageParseApk: 'Usage: cresc parseApk <apk file>',
76
+ offset: 'Offset {{offset}}',
77
+ packageUploadSuccess:
78
+ 'Successfully uploaded new hot update package (id: {{id}})',
79
+ rolloutRangeError: 'rollout must be an integer between 1-100',
80
+ nativeVersionNotFound: 'No native version found >= {{version}}',
81
+ nativeVersionNotFoundLess: 'No native version found <= {{version}}',
82
+ nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
83
+ packageIdRequired: 'Please provide packageId or packageVersion parameter',
84
+ operationComplete: 'Operation complete, bound to {{count}} native versions',
85
+ platformRequired: 'Platform must be specified.',
86
+ bundleCommandError:
87
+ '"react-native bundle" command exited with code {{code}}.',
88
+ copyHarmonyBundleError: 'Error copying Harmony bundle: {{error}}',
89
+ copyFileFailed: 'Failed to copy file: {{error}}',
90
+ deleteFile: 'Delete {{- file}}',
91
+ rolloutConfigSet:
92
+ 'Set {{rollout}}% rollout for version {{version}} on native version(s) {{versions}}',
93
+ versionBind:
94
+ 'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
43
95
  };
package/src/locales/zh.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  export default {
2
- updateNotifier:
3
- '建议运行 `{updateCommand}` 来更新命令行工具以获得功能、性能和安全性的持续改进',
4
2
  loginFirst: '尚未登录。\n请在项目目录中运行`pushy login`命令来登录',
5
3
  lockNotFound:
6
4
  '没有检测到任何 lock 文件,这可能导致依赖关系不一致而使热更异常。',
@@ -27,7 +25,7 @@ export default {
27
25
  appId: '应用 id',
28
26
  appName: '应用名称',
29
27
  platform: '平台',
30
- totalApps: '共 {{count}} 个{{platform}}应用',
28
+ totalApps: '共 {{count}} 个 {{platform}} 应用',
31
29
  appNotSelected:
32
30
  '尚未选择应用。请先运行 `pushy selectApp --platform {{platform}}` 来选择应用',
33
31
  enterAppIdQuestion: '输入应用 id:',
@@ -38,4 +36,54 @@ export default {
38
36
  operationSuccess: '操作成功',
39
37
  failedToParseUpdateJson: '无法解析文件 `update.json`。请手动删除它。',
40
38
  ppkPackageGenerated: 'ppk 热更包已生成并保存到: {{- output}}',
39
+ welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
40
+ loggedOut: '已退出登录',
41
+ usageUnderDevelopment: '使用说明正在开发中。',
42
+ hermesDisabled: 'Hermes 已禁用',
43
+ hermesEnabled: 'Hermes 已启用,正在编译为 hermes 字节码:\n',
44
+ runningHermesc: '运行 hermesc:{{command}} {{args}}',
45
+ composingSourceMap: '正在生成 source map',
46
+ copyingDebugId: '正在复制 debugid',
47
+ sentryCliNotFound: '无法找到 Sentry CLI 工具,请确保已正确安装 @sentry/cli',
48
+ sentryReleaseCreated: '已为版本 {{version}} 创建 Sentry release',
49
+ uploadingSourcemap: '正在上传 sourcemap',
50
+ packing: '正在打包',
51
+ deletingFile: '删除 {{- file}}',
52
+ bundlingWithRN: '正在使用 react-native {{version}} 打包',
53
+ fileGenerated: '已生成 {{- file}}。',
54
+ processingError: '处理文件时出错:{{error}}',
55
+ usageDiff: '用法:pushy {{command}} <origin> <next>',
56
+ pluginDetected: '检测到 {{name}} 插件',
57
+ pluginDetectionError: '检测 {{name}} 插件时出错:{{error}}',
58
+ addedToGitignore: '已将 {{line}} 添加到 .gitignore',
59
+ processingStringPool: '正在处理字符串池...',
60
+ processingPackage: '正在处理包 {{count}}...',
61
+ typeStrings: '类型字符串:',
62
+ keyStrings: '键字符串:',
63
+ failedToParseIcon: '[警告] 解析图标失败:{{error}}',
64
+ errorInHarmonyApp: '获取 Harmony 应用入口时出错:{{error}}',
65
+ totalPackages: '共 {{count}} 个包',
66
+ usageUploadIpa: '使用方法: pushy uploadIpa ipa后缀文件',
67
+ usageUploadApk: '使用方法: pushy uploadApk apk后缀文件',
68
+ usageUploadApp: '使用方法: pushy uploadApp app后缀文件',
69
+ usageParseApp: '使用方法: pushy parseApp app后缀文件',
70
+ usageParseIpa: '使用方法: pushy parseIpa ipa后缀文件',
71
+ usageParseApk: '使用方法: pushy parseApk apk后缀文件',
72
+ offset: '偏移量 {{offset}}',
73
+ packageUploadSuccess: '已成功上传新热更包(id: {{id}})',
74
+ rolloutRangeError: 'rollout 必须是 1-100 的整数',
75
+ nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
76
+ nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
77
+ nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
78
+ packageIdRequired: '请提供 packageId 或 packageVersion 参数',
79
+ operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
80
+ platformRequired: '必须指定平台。',
81
+ bundleCommandError: '"react-native bundle" 命令退出,代码为 {{code}}。',
82
+ copyHarmonyBundleError: '复制 Harmony bundle 错误:{{error}}',
83
+ copyFileFailed: '复制文件失败:{{error}}',
84
+ deleteFile: '删除 {{- file}}',
85
+ rolloutConfigSet:
86
+ '已在原生版本 {{versions}} 上设置灰度发布 {{rollout}}% 热更版本 {{version}}',
87
+ versionBind:
88
+ '已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
41
89
  };
package/src/package.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { get, post, uploadFile } from './api';
2
2
  import { question, saveToLocal } from './utils';
3
+ import { t } from './utils/i18n';
3
4
 
4
5
  import { checkPlatform, getSelectedApp } from './app';
5
6
 
@@ -34,7 +35,7 @@ export async function listPackage(appId: string) {
34
35
  }
35
36
 
36
37
  console.log(Table(header, rows).render());
37
- console.log(`\n共 ${data.length} 个包`);
38
+ console.log(t('totalPackages', { count: data.length }));
38
39
  return data;
39
40
  }
40
41
 
@@ -54,7 +55,7 @@ export const commands = {
54
55
  uploadIpa: async ({ args }: { args: string[] }) => {
55
56
  const fn = args[0];
56
57
  if (!fn || !fn.endsWith('.ipa')) {
57
- throw new Error('使用方法: pushy uploadIpa ipa后缀文件');
58
+ throw new Error(t('usageUploadIpa'));
58
59
  }
59
60
  const {
60
61
  versionName,
@@ -93,7 +94,7 @@ export const commands = {
93
94
  uploadApk: async ({ args }: { args: string[] }) => {
94
95
  const fn = args[0];
95
96
  if (!fn || !fn.endsWith('.apk')) {
96
- throw new Error('使用方法: pushy uploadApk apk后缀文件');
97
+ throw new Error(t('usageUploadApk'));
97
98
  }
98
99
  const {
99
100
  versionName,
@@ -132,7 +133,7 @@ export const commands = {
132
133
  uploadApp: async ({ args }: { args: string[] }) => {
133
134
  const fn = args[0];
134
135
  if (!fn || !fn.endsWith('.app')) {
135
- throw new Error('使用方法: pushy uploadApp app后缀文件');
136
+ throw new Error(t('usageUploadApp'));
136
137
  }
137
138
  const {
138
139
  versionName,
@@ -171,21 +172,21 @@ export const commands = {
171
172
  parseApp: async ({ args }: { args: string[] }) => {
172
173
  const fn = args[0];
173
174
  if (!fn || !fn.endsWith('.app')) {
174
- throw new Error('使用方法: pushy parseApp app后缀文件');
175
+ throw new Error(t('usageParseApp'));
175
176
  }
176
177
  console.log(await getAppInfo(fn));
177
178
  },
178
179
  parseIpa: async ({ args }: { args: string[] }) => {
179
180
  const fn = args[0];
180
181
  if (!fn || !fn.endsWith('.ipa')) {
181
- throw new Error('使用方法: pushy parseIpa ipa后缀文件');
182
+ throw new Error(t('usageParseIpa'));
182
183
  }
183
184
  console.log(await getIpaInfo(fn));
184
185
  },
185
186
  parseApk: async ({ args }: { args: string[] }) => {
186
187
  const fn = args[0];
187
188
  if (!fn || !fn.endsWith('.apk')) {
188
- throw new Error('使用方法: pushy parseApk apk后缀文件');
189
+ throw new Error(t('usageParseApk'));
189
190
  }
190
191
  console.log(await getApkInfo(fn));
191
192
  },
package/src/user.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { question } from './utils';
2
2
  import { post, get, replaceSession, saveSession, closeSession } from './api';
3
3
  import crypto from 'node:crypto';
4
+ import { t } from './utils/i18n';
4
5
 
5
6
  function md5(str: string) {
6
7
  return crypto.createHash('md5').update(str).digest('hex');
@@ -16,11 +17,11 @@ export const commands = {
16
17
  });
17
18
  replaceSession({ token });
18
19
  await saveSession();
19
- console.log(`欢迎使用 pushy 热更新服务, ${info.name}.`);
20
+ console.log(t('welcomeMessage', { name: info.name }));
20
21
  },
21
22
  logout: async () => {
22
23
  await closeSession();
23
- console.log('已退出登录');
24
+ console.log(t('loggedOut'));
24
25
  },
25
26
  me: async () => {
26
27
  const me = await get('/user/me');
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  // import path from 'node:path';
3
3
  import { credentialFile, tempDir } from './constants';
4
+ import { t } from './i18n';
4
5
 
5
6
  export function addGitIgnore() {
6
7
  const shouldIgnore = [credentialFile, tempDir];
@@ -26,7 +27,7 @@ export function addGitIgnore() {
26
27
  gitignoreLines.push('# react-native-update');
27
28
  for (const line of shouldIgnore) {
28
29
  gitignoreLines.push(line);
29
- console.log(`Added ${line} to .gitignore`);
30
+ console.log(t('addedToGitignore', { line }));
30
31
  }
31
32
 
32
33
  fs.writeFileSync(gitignorePath, gitignoreLines.join('\n'));