react-native-update-cli 2.0.0 → 2.1.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/README.zh-CN.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # React Native Update CLI
2
2
 
3
- 这是一个统一的React Native Update CLI,同时支持传统命令和模块化架构以及自定义发布流程。
3
+ 这是一个统一的 React Native Update CLI,同时支持传统命令和模块化架构以及自定义发布流程。
4
4
 
5
5
  ## 🚀 特性
6
6
 
7
- - **统一CLI**: 使用单个`pushy`命令提供所有功能
7
+ - **统一 CLI**: 使用单个`pushy`命令提供所有功能
8
8
  - **向后兼容**: 所有现有命令都能正常工作
9
- - **模块化架构**: 将CLI功能拆分为独立的模块
9
+ - **模块化架构**: 将 CLI 功能拆分为独立的模块
10
10
  - **自定义工作流**: 支持创建自定义的发布流程
11
11
  - **可扩展性**: 用户可以导入和注册自定义模块
12
- - **类型安全**: 完整的TypeScript类型支持
12
+ - **类型安全**: 完整的 TypeScript 类型支持
13
13
 
14
14
  ## 📦 安装
15
15
 
@@ -47,14 +47,14 @@ const provider = moduleManager.getProvider();
47
47
  const bundleResult = await provider.bundle({
48
48
  platform: 'ios',
49
49
  dev: false,
50
- sourcemap: true
50
+ sourcemap: true,
51
51
  });
52
52
 
53
53
  // 发布版本
54
54
  const publishResult = await provider.publish({
55
55
  name: 'v1.2.3',
56
56
  description: 'Bug fixes and improvements',
57
- rollout: 100
57
+ rollout: 100,
58
58
  });
59
59
  ```
60
60
 
@@ -63,12 +63,16 @@ const publishResult = await provider.publish({
63
63
  ### 1. 定义模块
64
64
 
65
65
  ```typescript
66
- import type { CLIModule, CommandDefinition, CustomWorkflow } from 'react-native-update-cli';
66
+ import type {
67
+ CLIModule,
68
+ CommandDefinition,
69
+ CustomWorkflow,
70
+ } from 'react-native-update-cli';
67
71
 
68
72
  export const myCustomModule: CLIModule = {
69
73
  name: 'my-custom',
70
74
  version: '1.0.0',
71
-
75
+
72
76
  commands: [
73
77
  {
74
78
  name: 'custom-command',
@@ -77,15 +81,15 @@ export const myCustomModule: CLIModule = {
77
81
  console.log('Executing custom command...');
78
82
  return {
79
83
  success: true,
80
- data: { message: 'Custom command executed' }
84
+ data: { message: 'Custom command executed' },
81
85
  };
82
86
  },
83
87
  options: {
84
- param: { hasValue: true, description: 'Custom parameter' }
85
- }
86
- }
88
+ param: { hasValue: true, description: 'Custom parameter' },
89
+ },
90
+ },
87
91
  ],
88
-
92
+
89
93
  workflows: [
90
94
  {
91
95
  name: 'my-workflow',
@@ -97,7 +101,7 @@ export const myCustomModule: CLIModule = {
97
101
  execute: async (context, previousResult) => {
98
102
  console.log('Executing step 1...');
99
103
  return { step1Completed: true };
100
- }
104
+ },
101
105
  },
102
106
  {
103
107
  name: 'step2',
@@ -105,19 +109,19 @@ export const myCustomModule: CLIModule = {
105
109
  execute: async (context, previousResult) => {
106
110
  console.log('Executing step 2...');
107
111
  return { ...previousResult, step2Completed: true };
108
- }
109
- }
110
- ]
111
- }
112
+ },
113
+ },
114
+ ],
115
+ },
112
116
  ],
113
-
117
+
114
118
  init: (provider) => {
115
119
  console.log('Custom module initialized');
116
120
  },
117
-
121
+
118
122
  cleanup: () => {
119
123
  console.log('Custom module cleanup');
120
- }
124
+ },
121
125
  };
122
126
  ```
123
127
 
@@ -133,13 +137,13 @@ moduleManager.registerModule(myCustomModule);
133
137
  // 执行自定义命令
134
138
  const result = await moduleManager.executeCommand('custom-command', {
135
139
  args: [],
136
- options: { param: 'value' }
140
+ options: { param: 'value' },
137
141
  });
138
142
 
139
143
  // 执行自定义工作流
140
144
  const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
141
145
  args: [],
142
- options: {}
146
+ options: {},
143
147
  });
144
148
  ```
145
149
 
@@ -188,43 +192,48 @@ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
188
192
 
189
193
  ## 📋 内置模块
190
194
 
191
- ### Bundle模块 (`bundle`)
192
- - `bundle`: 打包JavaScript代码并可选发布
193
- - `diff`: 生成两个PPK文件之间的差异
194
- - `hdiff`: 生成两个PPK文件之间的hdiff
195
- - `diffFromApk`: 从APK文件生成差异
196
- - `hdiffFromApk`: 从APK文件生成hdiff
197
- - `hdiffFromApp`: 从APP文件生成hdiff
198
- - `diffFromIpa`: 从IPA文件生成差异
199
- - `hdiffFromIpa`: 从IPA文件生成hdiff
200
-
201
- ### Version模块 (`version`)
195
+ ### Bundle 模块 (`bundle`)
196
+
197
+ - `bundle`: 打包 JavaScript 代码并可选发布
198
+ - `diff`: 生成两个 PPK 文件之间的差异
199
+ - `hdiff`: 生成两个 PPK 文件之间的 hdiff
200
+ - `diffFromApk`: 从 APK 文件生成差异
201
+ - `hdiffFromApk`: 从 APK 文件生成 hdiff
202
+ - `hdiffFromApp`: 从 APP 文件生成 hdiff
203
+ - `diffFromIpa`: 从 IPA 文件生成差异
204
+ - `hdiffFromIpa`: 从 IPA 文件生成 hdiff
205
+
206
+ ### Version 模块 (`version`)
207
+
202
208
  - `publish`: 发布新版本
203
209
  - `versions`: 列出所有版本
204
210
  - `update`: 更新版本信息
205
211
  - `updateVersionInfo`: 更新版本元数据
206
212
 
207
- ### App模块 (`app`)
213
+ ### App 模块 (`app`)
214
+
208
215
  - `createApp`: 创建新应用
209
216
  - `apps`: 列出所有应用
210
217
  - `selectApp`: 选择应用
211
218
  - `deleteApp`: 删除应用
212
219
 
213
- ### Package模块 (`package`)
214
- - `uploadIpa`: 上传IPA文件
215
- - `uploadApk`: 上传APK文件
216
- - `uploadApp`: 上传APP文件
217
- - `parseApp`: 解析APP文件信息
218
- - `parseIpa`: 解析IPA文件信息
219
- - `parseApk`: 解析APK文件信息
220
+ ### Package 模块 (`package`)
221
+
222
+ - `uploadIpa`: 上传 IPA 文件(支持 `--version` 参数覆盖提取的版本)
223
+ - `uploadApk`: 上传 APK 文件(支持 `--version` 参数覆盖提取的版本)
224
+ - `uploadApp`: 上传 APP 文件(支持 `--version` 参数覆盖提取的版本)
225
+ - `parseApp`: 解析 APP 文件信息
226
+ - `parseIpa`: 解析 IPA 文件信息
227
+ - `parseApk`: 解析 APK 文件信息
220
228
  - `packages`: 列出包
221
229
 
222
- ### User模块 (`user`)
230
+ ### User 模块 (`user`)
231
+
223
232
  - `login`: 登录
224
233
  - `logout`: 登出
225
234
  - `me`: 显示用户信息
226
235
 
227
- ## 🛠️ CLI提供者API
236
+ ## 🛠️ CLI 提供者 API
228
237
 
229
238
  ### 核心功能
230
239
 
@@ -232,36 +241,45 @@ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
232
241
  interface CLIProvider {
233
242
  // 打包
234
243
  bundle(options: BundleOptions): Promise<CommandResult>;
235
-
244
+
236
245
  // 发布
237
246
  publish(options: PublishOptions): Promise<CommandResult>;
238
-
247
+
239
248
  // 上传
240
249
  upload(options: UploadOptions): Promise<CommandResult>;
241
-
250
+
242
251
  // 应用管理
243
- getSelectedApp(platform?: Platform): Promise<{ appId: string; platform: Platform }>;
252
+ getSelectedApp(
253
+ platform?: Platform,
254
+ ): Promise<{ appId: string; platform: Platform }>;
244
255
  listApps(platform?: Platform): Promise<CommandResult>;
245
256
  createApp(name: string, platform: Platform): Promise<CommandResult>;
246
-
257
+
247
258
  // 版本管理
248
259
  listVersions(appId: string): Promise<CommandResult>;
249
260
  getVersion(appId: string, versionId: string): Promise<CommandResult>;
250
- updateVersion(appId: string, versionId: string, updates: Partial<Version>): Promise<CommandResult>;
251
-
261
+ updateVersion(
262
+ appId: string,
263
+ versionId: string,
264
+ updates: Partial<Version>,
265
+ ): Promise<CommandResult>;
266
+
252
267
  // 包管理
253
268
  listPackages(appId: string, platform?: Platform): Promise<CommandResult>;
254
269
  getPackage(appId: string, packageId: string): Promise<CommandResult>;
255
-
270
+
256
271
  // 工具函数
257
272
  getPlatform(platform?: Platform): Promise<Platform>;
258
273
  loadSession(): Promise<Session>;
259
274
  saveToLocal(key: string, value: string): void;
260
275
  question(prompt: string): Promise<string>;
261
-
276
+
262
277
  // 工作流
263
278
  registerWorkflow(workflow: CustomWorkflow): void;
264
- executeWorkflow(workflowName: string, context: CommandContext): Promise<CommandResult>;
279
+ executeWorkflow(
280
+ workflowName: string,
281
+ context: CommandContext,
282
+ ): Promise<CommandResult>;
265
283
  }
266
284
  ```
267
285
 
@@ -274,8 +292,8 @@ const bundleResult = await moduleManager.executeCommand('custom-bundle', {
274
292
  options: {
275
293
  platform: 'android',
276
294
  validate: true,
277
- optimize: true
278
- }
295
+ optimize: true,
296
+ },
279
297
  });
280
298
 
281
299
  // 生成差异文件
@@ -284,8 +302,8 @@ const diffResult = await moduleManager.executeCommand('diff', {
284
302
  options: {
285
303
  origin: './build/v1.0.0.ppk',
286
304
  next: './build/v1.1.0.ppk',
287
- output: './build/diff.patch'
288
- }
305
+ output: './build/diff.patch',
306
+ },
289
307
  });
290
308
 
291
309
  // 从APK文件生成差异
@@ -294,8 +312,8 @@ const apkDiffResult = await moduleManager.executeCommand('diffFromApk', {
294
312
  options: {
295
313
  origin: './build/app-v1.0.0.apk',
296
314
  next: './build/app-v1.1.0.apk',
297
- output: './build/apk-diff.patch'
298
- }
315
+ output: './build/apk-diff.patch',
316
+ },
299
317
  });
300
318
  ```
301
319
 
@@ -330,46 +348,48 @@ export NO_INTERACTIVE=true
330
348
 
331
349
  ## 🚨 注意事项
332
350
 
333
- 1. **向后兼容**: 新的模块化CLI保持与现有CLI的兼容性
334
- 2. **类型安全**: 所有API都有完整的TypeScript类型定义
351
+ 1. **向后兼容**: 新的模块化 CLI 保持与现有 CLI 的兼容性
352
+ 2. **类型安全**: 所有 API 都有完整的 TypeScript 类型定义
335
353
  3. **错误处理**: 所有操作都返回标准化的结果格式
336
354
  4. **资源清理**: 模块支持清理函数来释放资源
337
355
  5. **模块分离**: 功能按逻辑分离到不同模块中,便于维护和扩展
338
356
 
339
357
  ## 🤝 贡献
340
358
 
341
- 欢迎提交Issue和Pull Request来改进这个项目!
359
+ 欢迎提交 Issue Pull Request 来改进这个项目!
342
360
 
343
361
  ## 🚀 Provider API 使用指南
344
362
 
345
- Provider提供了简洁的编程接口,适合在应用程序中集成React Native Update CLI功能。
363
+ Provider 提供了简洁的编程接口,适合在应用程序中集成 React Native Update CLI 功能。
346
364
 
347
- ### 📋 核心API方法
365
+ ### 📋 核心 API 方法
348
366
 
349
367
  #### 核心业务功能
368
+
350
369
  ```typescript
351
370
  // 打包应用
352
371
  await provider.bundle({
353
372
  platform: 'ios',
354
373
  dev: false,
355
- sourcemap: true
374
+ sourcemap: true,
356
375
  });
357
376
 
358
377
  // 发布版本
359
378
  await provider.publish({
360
379
  name: 'v1.0.0',
361
380
  description: 'Bug fixes',
362
- rollout: 100
381
+ rollout: 100,
363
382
  });
364
383
 
365
384
  // 上传文件
366
385
  await provider.upload({
367
386
  filePath: 'app.ipa',
368
- platform: 'ios'
387
+ platform: 'ios',
369
388
  });
370
389
  ```
371
390
 
372
391
  #### 应用管理
392
+
373
393
  ```typescript
374
394
  // 创建应用
375
395
  await provider.createApp('MyApp', 'ios');
@@ -382,6 +402,7 @@ const { appId, platform } = await provider.getSelectedApp('ios');
382
402
  ```
383
403
 
384
404
  #### 版本管理
405
+
385
406
  ```typescript
386
407
  // 列出版本
387
408
  await provider.listVersions('app123');
@@ -389,11 +410,12 @@ await provider.listVersions('app123');
389
410
  // 更新版本
390
411
  await provider.updateVersion('app123', 'version456', {
391
412
  name: 'v1.1.0',
392
- description: 'New features'
413
+ description: 'New features',
393
414
  });
394
415
  ```
395
416
 
396
417
  #### 工具函数
418
+
397
419
  ```typescript
398
420
  // 获取平台
399
421
  const platform = await provider.getPlatform('ios');
@@ -405,72 +427,75 @@ const session = await provider.loadSession();
405
427
  ### 🎯 使用场景
406
428
 
407
429
  #### 1. 自动化构建脚本
430
+
408
431
  ```typescript
409
432
  import { moduleManager } from 'react-native-update-cli';
410
433
 
411
434
  async function buildAndPublish() {
412
435
  const provider = moduleManager.getProvider();
413
-
436
+
414
437
  // 1. 打包
415
438
  const bundleResult = await provider.bundle({
416
439
  platform: 'ios',
417
440
  dev: false,
418
- sourcemap: true
441
+ sourcemap: true,
419
442
  });
420
-
443
+
421
444
  if (!bundleResult.success) {
422
445
  throw new Error(`打包失败: ${bundleResult.error}`);
423
446
  }
424
-
447
+
425
448
  // 2. 发布
426
449
  const publishResult = await provider.publish({
427
450
  name: 'v1.2.3',
428
451
  description: 'Bug fixes and performance improvements',
429
- rollout: 100
452
+ rollout: 100,
430
453
  });
431
-
454
+
432
455
  if (!publishResult.success) {
433
456
  throw new Error(`发布失败: ${publishResult.error}`);
434
457
  }
435
-
458
+
436
459
  console.log('构建和发布完成!');
437
460
  }
438
461
  ```
439
462
 
440
- #### 2. CI/CD集成
463
+ #### 2. CI/CD 集成
464
+
441
465
  ```typescript
442
466
  async function ciBuild() {
443
467
  const provider = moduleManager.getProvider();
444
-
468
+
445
469
  const result = await provider.bundle({
446
470
  platform: process.env.PLATFORM as 'ios' | 'android',
447
471
  dev: process.env.NODE_ENV !== 'production',
448
- sourcemap: process.env.NODE_ENV === 'production'
472
+ sourcemap: process.env.NODE_ENV === 'production',
449
473
  });
450
-
474
+
451
475
  return result;
452
476
  }
453
477
  ```
454
478
 
455
479
  #### 3. 应用管理服务
480
+
456
481
  ```typescript
457
482
  class AppManagementService {
458
483
  private provider = moduleManager.getProvider();
459
-
484
+
460
485
  async setupNewApp(name: string, platform: Platform) {
461
486
  // 创建应用
462
487
  const createResult = await this.provider.createApp(name, platform);
463
-
488
+
464
489
  if (createResult.success) {
465
490
  // 获取应用信息
466
491
  const { appId } = await this.provider.getSelectedApp(platform);
467
-
492
+
468
493
  // 列出版本
469
494
  await this.provider.listVersions(appId);
470
-
495
+
471
496
  return { appId, success: true };
472
497
  }
473
-
498
+
474
499
  return { success: false, error: createResult.error };
475
500
  }
476
501
  }
@@ -478,14 +503,15 @@ class AppManagementService {
478
503
 
479
504
  ### ⚠️ 注意事项
480
505
 
481
- 1. **错误处理**: 所有Provider方法都返回`CommandResult`,需要检查`success`字段
482
- 2. **类型安全**: Provider提供完整的TypeScript类型支持
506
+ 1. **错误处理**: 所有 Provider 方法都返回`CommandResult`,需要检查`success`字段
507
+ 2. **类型安全**: Provider 提供完整的 TypeScript 类型支持
483
508
  3. **会话管理**: 使用前确保已登录,可通过`loadSession()`检查
484
509
  4. **平台支持**: 支持`'ios' | 'android' | 'harmony'`三个平台
485
510
 
486
511
  ### 🔧 高级功能
487
512
 
488
513
  #### 自定义工作流
514
+
489
515
  ```typescript
490
516
  // 注册自定义工作流
491
517
  provider.registerWorkflow({
@@ -496,7 +522,7 @@ provider.registerWorkflow({
496
522
  name: 'bundle',
497
523
  execute: async () => {
498
524
  return await provider.bundle({ platform: 'ios', dev: false });
499
- }
525
+ },
500
526
  },
501
527
  {
502
528
  name: 'publish',
@@ -505,9 +531,9 @@ provider.registerWorkflow({
505
531
  throw new Error('打包失败,无法发布');
506
532
  }
507
533
  return await provider.publish({ name: 'auto-release', rollout: 50 });
508
- }
509
- }
510
- ]
534
+ },
535
+ },
536
+ ],
511
537
  });
512
538
 
513
539
  // 执行工作流
@@ -521,50 +547,49 @@ import { moduleManager } from 'react-native-update-cli';
521
547
 
522
548
  class ReactNativeUpdateService {
523
549
  private provider = moduleManager.getProvider();
524
-
550
+
525
551
  async initialize() {
526
552
  // 加载会话
527
553
  await this.provider.loadSession();
528
554
  }
529
-
555
+
530
556
  async buildAndDeploy(platform: Platform, version: string) {
531
557
  try {
532
558
  // 1. 打包
533
559
  const bundleResult = await this.provider.bundle({
534
560
  platform,
535
561
  dev: false,
536
- sourcemap: true
562
+ sourcemap: true,
537
563
  });
538
-
564
+
539
565
  if (!bundleResult.success) {
540
566
  throw new Error(`打包失败: ${bundleResult.error}`);
541
567
  }
542
-
568
+
543
569
  // 2. 发布
544
570
  const publishResult = await this.provider.publish({
545
571
  name: version,
546
572
  description: `Release ${version}`,
547
- rollout: 100
573
+ rollout: 100,
548
574
  });
549
-
575
+
550
576
  if (!publishResult.success) {
551
577
  throw new Error(`发布失败: ${publishResult.error}`);
552
578
  }
553
-
579
+
554
580
  return { success: true, data: publishResult.data };
555
-
556
581
  } catch (error) {
557
- return {
558
- success: false,
559
- error: error instanceof Error ? error.message : 'Unknown error'
582
+ return {
583
+ success: false,
584
+ error: error instanceof Error ? error.message : 'Unknown error',
560
585
  };
561
586
  }
562
587
  }
563
-
588
+
564
589
  async getAppInfo(platform: Platform) {
565
590
  const { appId } = await this.provider.getSelectedApp(platform);
566
591
  const versions = await this.provider.listVersions(appId);
567
-
592
+
568
593
  return { appId, versions };
569
594
  }
570
595
  }
@@ -573,4 +598,4 @@ class ReactNativeUpdateService {
573
598
  const service = new ReactNativeUpdateService();
574
599
  await service.initialize();
575
600
  await service.buildAndDeploy('ios', 'v1.0.0');
576
- ```
601
+ ```
package/cli.json CHANGED
@@ -31,9 +31,27 @@
31
31
  }
32
32
  }
33
33
  },
34
- "uploadIpa": {},
35
- "uploadApk": {},
36
- "uploadApp": {},
34
+ "uploadIpa": {
35
+ "options": {
36
+ "version": {
37
+ "hasValue": true
38
+ }
39
+ }
40
+ },
41
+ "uploadApk": {
42
+ "options": {
43
+ "version": {
44
+ "hasValue": true
45
+ }
46
+ }
47
+ },
48
+ "uploadApp": {
49
+ "options": {
50
+ "version": {
51
+ "hasValue": true
52
+ }
53
+ }
54
+ },
37
55
  "parseApp": {},
38
56
  "parseIpa": {},
39
57
  "parseApk": {},
@@ -44,6 +62,13 @@
44
62
  }
45
63
  }
46
64
  },
65
+ "deletePackage": {
66
+ "options": {
67
+ "appId": {
68
+ "hasValue": true
69
+ }
70
+ }
71
+ },
47
72
  "publish": {
48
73
  "options": {
49
74
  "platform": {
package/lib/locales/en.js CHANGED
@@ -113,5 +113,10 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
113
113
  versionMetaInfoQuestion: 'Enter custom meta info:',
114
114
  updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
115
115
  unnamed: '(Unnamed)',
116
- dryRun: 'Below is the dry-run result, no actual operation will be performed:'
116
+ dryRun: 'Below is the dry-run result, no actual operation will be performed:',
117
+ usingCustomVersion: 'Using custom version: {{version}}',
118
+ confirmDeletePackage: 'Confirm delete native package {{packageId}}? This operation cannot be undone (Y/N):',
119
+ deletePackageSuccess: 'Native package {{packageId}} deleted successfully',
120
+ deletePackageError: 'Failed to delete native package {{packageId}}: {{error}}',
121
+ usageDeletePackage: 'Usage: cresc deletePackage [packageId] --appId [appId]'
117
122
  };
package/lib/locales/zh.js CHANGED
@@ -112,5 +112,10 @@ const _default = {
112
112
  versionMetaInfoQuestion: '输入自定义的 meta info:',
113
113
  updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
114
114
  unnamed: '(未命名)',
115
- dryRun: '以下是 dry-run 模拟运行结果,不会实际执行任何操作:'
115
+ dryRun: '以下是 dry-run 模拟运行结果,不会实际执行任何操作:',
116
+ usingCustomVersion: '使用自定义版本:{{version}}',
117
+ confirmDeletePackage: '确认删除原生包 {{packageId}}? 此操作不可撤销 (Y/N):',
118
+ deletePackageSuccess: '原生包 {{packageId}} 删除成功',
119
+ deletePackageError: '删除原生包 {{packageId}} 失败: {{error}}',
120
+ usageDeletePackage: '使用方法: pushy deletePackage [packageId] --appId [appId]'
116
121
  };