react-native-update-cli 1.46.2 → 2.0.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.
Files changed (64) hide show
  1. package/README.md +578 -1
  2. package/README.zh-CN.md +576 -0
  3. package/cli.json +18 -0
  4. package/lib/api.js +5 -5
  5. package/lib/app.js +1 -1
  6. package/lib/bundle.js +30 -28
  7. package/lib/exports.js +65 -0
  8. package/lib/index.js +100 -9
  9. package/lib/module-manager.js +125 -0
  10. package/lib/modules/app-module.js +223 -0
  11. package/lib/modules/bundle-module.js +188 -0
  12. package/lib/modules/index.js +42 -0
  13. package/lib/modules/package-module.js +16 -0
  14. package/lib/modules/user-module.js +402 -0
  15. package/lib/modules/version-module.js +16 -0
  16. package/lib/package.js +16 -6
  17. package/lib/provider.js +340 -0
  18. package/lib/user.js +3 -3
  19. package/lib/utils/app-info-parser/apk.js +1 -1
  20. package/lib/utils/app-info-parser/ipa.js +2 -2
  21. package/lib/utils/app-info-parser/resource-finder.js +35 -35
  22. package/lib/utils/app-info-parser/xml-parser/manifest.js +2 -2
  23. package/lib/utils/app-info-parser/zip.js +3 -6
  24. package/lib/utils/check-plugin.js +1 -1
  25. package/lib/utils/git.js +1 -1
  26. package/lib/utils/i18n.js +3 -1
  27. package/lib/utils/index.js +4 -4
  28. package/lib/utils/latest-version/cli.js +3 -3
  29. package/lib/utils/latest-version/index.js +4 -4
  30. package/lib/versions.js +2 -2
  31. package/package.json +4 -4
  32. package/src/api.ts +7 -7
  33. package/src/app.ts +2 -2
  34. package/src/bundle.ts +44 -32
  35. package/src/exports.ts +30 -0
  36. package/src/index.ts +118 -16
  37. package/src/module-manager.ts +149 -0
  38. package/src/modules/app-module.ts +205 -0
  39. package/src/modules/bundle-module.ts +202 -0
  40. package/src/modules/index.ts +19 -0
  41. package/src/modules/package-module.ts +11 -0
  42. package/src/modules/user-module.ts +406 -0
  43. package/src/modules/version-module.ts +8 -0
  44. package/src/package.ts +29 -16
  45. package/src/provider.ts +341 -0
  46. package/src/types.ts +125 -0
  47. package/src/user.ts +4 -3
  48. package/src/utils/app-info-parser/apk.js +62 -52
  49. package/src/utils/app-info-parser/app.js +5 -5
  50. package/src/utils/app-info-parser/ipa.js +69 -57
  51. package/src/utils/app-info-parser/resource-finder.js +50 -54
  52. package/src/utils/app-info-parser/utils.js +59 -54
  53. package/src/utils/app-info-parser/xml-parser/binary.js +366 -354
  54. package/src/utils/app-info-parser/xml-parser/manifest.js +145 -137
  55. package/src/utils/app-info-parser/zip.js +1 -1
  56. package/src/utils/check-plugin.ts +4 -2
  57. package/src/utils/dep-versions.ts +13 -6
  58. package/src/utils/git.ts +1 -1
  59. package/src/utils/i18n.ts +3 -1
  60. package/src/utils/index.ts +8 -10
  61. package/src/utils/latest-version/cli.ts +4 -4
  62. package/src/utils/latest-version/index.ts +17 -17
  63. package/src/utils/plugin-config.ts +3 -3
  64. package/src/versions.ts +3 -3
package/README.md CHANGED
@@ -1 +1,578 @@
1
- # react-native-update-cli
1
+ # React Native Update CLI
2
+
3
+ [中文文档](./README.zh-CN.md) | [Chinese Documentation](./README.zh-CN.md)
4
+
5
+ A unified React Native Update CLI that supports both traditional commands and modular architecture with custom publishing workflows.
6
+
7
+ ## 🚀 Features
8
+
9
+ - **Unified CLI**: Single `pushy` command for all functionality
10
+ - **Backward Compatibility**: All existing commands work as before
11
+ - **Modular Architecture**: Split CLI functionality into independent modules
12
+ - **Custom Workflows**: Support for creating custom publishing workflows
13
+ - **Extensibility**: Users can import and register custom modules
14
+ - **Type Safety**: Complete TypeScript type support
15
+
16
+ ## 📦 Installation
17
+
18
+ ```bash
19
+ npm install react-native-update-cli
20
+ ```
21
+
22
+ ## 🎯 Quick Start
23
+
24
+ ### Basic Usage
25
+
26
+ ```bash
27
+ # Use unified CLI
28
+ npx pushy help
29
+
30
+ # List all available commands and workflows
31
+ npx pushy list
32
+
33
+ # Execute built-in workflow
34
+ npx pushy workflow setup-app
35
+
36
+ # Execute custom workflow
37
+ npx pushy workflow custom-publish
38
+ ```
39
+
40
+ ### Programmatic Usage
41
+
42
+ ```typescript
43
+ import { moduleManager, CLIProviderImpl } from 'react-native-update-cli';
44
+
45
+ // Get CLI provider
46
+ const provider = moduleManager.getProvider();
47
+
48
+ // Execute bundling
49
+ const bundleResult = await provider.bundle({
50
+ platform: 'ios',
51
+ dev: false,
52
+ sourcemap: true
53
+ });
54
+
55
+ // Publish version
56
+ const publishResult = await provider.publish({
57
+ name: 'v1.2.3',
58
+ description: 'Bug fixes and improvements',
59
+ rollout: 100
60
+ });
61
+ ```
62
+
63
+ ## 🔧 Creating Custom Modules
64
+
65
+ ### 1. Define Module
66
+
67
+ ```typescript
68
+ import type { CLIModule, CommandDefinition, CustomWorkflow } from 'react-native-update-cli';
69
+
70
+ export const myCustomModule: CLIModule = {
71
+ name: 'my-custom',
72
+ version: '1.0.0',
73
+
74
+ commands: [
75
+ {
76
+ name: 'custom-command',
77
+ description: 'My custom command',
78
+ handler: async (context) => {
79
+ console.log('Executing custom command...');
80
+ return {
81
+ success: true,
82
+ data: { message: 'Custom command executed' }
83
+ };
84
+ },
85
+ options: {
86
+ param: { hasValue: true, description: 'Custom parameter' }
87
+ }
88
+ }
89
+ ],
90
+
91
+ workflows: [
92
+ {
93
+ name: 'my-workflow',
94
+ description: 'My custom workflow',
95
+ steps: [
96
+ {
97
+ name: 'step1',
98
+ description: 'First step',
99
+ execute: async (context, previousResult) => {
100
+ console.log('Executing step 1...');
101
+ return { step1Completed: true };
102
+ }
103
+ },
104
+ {
105
+ name: 'step2',
106
+ description: 'Second step',
107
+ execute: async (context, previousResult) => {
108
+ console.log('Executing step 2...');
109
+ return { ...previousResult, step2Completed: true };
110
+ }
111
+ }
112
+ ]
113
+ }
114
+ ],
115
+
116
+ init: (provider) => {
117
+ console.log('Custom module initialized');
118
+ },
119
+
120
+ cleanup: () => {
121
+ console.log('Custom module cleanup');
122
+ }
123
+ };
124
+ ```
125
+
126
+ ### 2. Register Module
127
+
128
+ ```typescript
129
+ import { moduleManager } from 'react-native-update-cli';
130
+ import { myCustomModule } from './my-custom-module';
131
+
132
+ // Register custom module
133
+ moduleManager.registerModule(myCustomModule);
134
+
135
+ // Execute custom command
136
+ const result = await moduleManager.executeCommand('custom-command', {
137
+ args: [],
138
+ options: { param: 'value' }
139
+ });
140
+
141
+ // Execute custom workflow
142
+ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
143
+ args: [],
144
+ options: {}
145
+ });
146
+ ```
147
+
148
+ ## 🔄 Workflow System
149
+
150
+ ### Workflow Steps
151
+
152
+ Each workflow step contains:
153
+
154
+ - `name`: Step name
155
+ - `description`: Step description
156
+ - `execute`: Execution function
157
+ - `condition`: Optional condition function
158
+
159
+ ### Conditional Execution
160
+
161
+ ```typescript
162
+ {
163
+ name: 'conditional-step',
164
+ description: 'Only execute in production',
165
+ execute: async (context, previousResult) => {
166
+ // Execution logic
167
+ },
168
+ condition: (context) => {
169
+ return context.options.environment === 'production';
170
+ }
171
+ }
172
+ ```
173
+
174
+ ### Workflow Validation
175
+
176
+ ```typescript
177
+ {
178
+ name: 'validated-workflow',
179
+ description: 'Workflow with validation',
180
+ steps: [...],
181
+ validate: (context) => {
182
+ if (!context.options.requiredParam) {
183
+ console.error('Required parameter missing');
184
+ return false;
185
+ }
186
+ return true;
187
+ }
188
+ }
189
+ ```
190
+
191
+ ## 📋 Built-in Modules
192
+
193
+ ### Bundle Module (`bundle`)
194
+ - `bundle`: Bundle JavaScript code and optionally publish
195
+ - `diff`: Generate differences between two PPK files
196
+ - `hdiff`: Generate hdiff between two PPK files
197
+ - `diffFromApk`: Generate differences from APK files
198
+ - `hdiffFromApk`: Generate hdiff from APK files
199
+ - `hdiffFromApp`: Generate hdiff from APP files
200
+ - `diffFromIpa`: Generate differences from IPA files
201
+ - `hdiffFromIpa`: Generate hdiff from IPA files
202
+
203
+ ### Version Module (`version`)
204
+ - `publish`: Publish new version
205
+ - `versions`: List all versions
206
+ - `update`: Update version information
207
+ - `updateVersionInfo`: Update version metadata
208
+
209
+ ### App Module (`app`)
210
+ - `createApp`: Create new application
211
+ - `apps`: List all applications
212
+ - `selectApp`: Select application
213
+ - `deleteApp`: Delete application
214
+
215
+ ### Package Module (`package`)
216
+ - `uploadIpa`: Upload IPA files
217
+ - `uploadApk`: Upload APK files
218
+ - `uploadApp`: Upload APP files
219
+ - `parseApp`: Parse APP file information
220
+ - `parseIpa`: Parse IPA file information
221
+ - `parseApk`: Parse APK file information
222
+ - `packages`: List packages
223
+
224
+ ### User Module (`user`)
225
+ - `login`: Login
226
+ - `logout`: Logout
227
+ - `me`: Show user information
228
+
229
+ ## 🛠️ CLI Provider API
230
+
231
+ ### Core Functionality
232
+
233
+ ```typescript
234
+ interface CLIProvider {
235
+ // Bundle
236
+ bundle(options: BundleOptions): Promise<CommandResult>;
237
+
238
+ // Publish
239
+ publish(options: PublishOptions): Promise<CommandResult>;
240
+
241
+ // Upload
242
+ upload(options: UploadOptions): Promise<CommandResult>;
243
+
244
+ // Application management
245
+ getSelectedApp(platform?: Platform): Promise<{ appId: string; platform: Platform }>;
246
+ listApps(platform?: Platform): Promise<CommandResult>;
247
+ createApp(name: string, platform: Platform): Promise<CommandResult>;
248
+
249
+ // Version management
250
+ listVersions(appId: string): Promise<CommandResult>;
251
+ getVersion(appId: string, versionId: string): Promise<CommandResult>;
252
+ updateVersion(appId: string, versionId: string, updates: Partial<Version>): Promise<CommandResult>;
253
+
254
+ // Package management
255
+ listPackages(appId: string, platform?: Platform): Promise<CommandResult>;
256
+ getPackage(appId: string, packageId: string): Promise<CommandResult>;
257
+
258
+ // Utility functions
259
+ getPlatform(platform?: Platform): Promise<Platform>;
260
+ loadSession(): Promise<Session>;
261
+ saveToLocal(key: string, value: string): void;
262
+ question(prompt: string): Promise<string>;
263
+
264
+ // Workflows
265
+ registerWorkflow(workflow: CustomWorkflow): void;
266
+ executeWorkflow(workflowName: string, context: CommandContext): Promise<CommandResult>;
267
+ }
268
+ ```
269
+
270
+ ### Custom Commands
271
+
272
+ ```typescript
273
+ // Execute custom bundle command
274
+ const bundleResult = await moduleManager.executeCommand('custom-bundle', {
275
+ args: [],
276
+ options: {
277
+ platform: 'android',
278
+ validate: true,
279
+ optimize: true
280
+ }
281
+ });
282
+
283
+ // Generate diff file
284
+ const diffResult = await moduleManager.executeCommand('diff', {
285
+ args: [],
286
+ options: {
287
+ origin: './build/v1.0.0.ppk',
288
+ next: './build/v1.1.0.ppk',
289
+ output: './build/diff.patch'
290
+ }
291
+ });
292
+
293
+ // Generate diff from APK files
294
+ const apkDiffResult = await moduleManager.executeCommand('diffFromApk', {
295
+ args: [],
296
+ options: {
297
+ origin: './build/app-v1.0.0.apk',
298
+ next: './build/app-v1.1.0.apk',
299
+ output: './build/apk-diff.patch'
300
+ }
301
+ });
302
+ ```
303
+
304
+ ## 🔧 Configuration
305
+
306
+ ### Environment Variables
307
+
308
+ ```bash
309
+ # Set API endpoint
310
+ export PUSHY_REGISTRY=https://your-api-endpoint.com
311
+
312
+ # Set non-interactive mode
313
+ export NO_INTERACTIVE=true
314
+ ```
315
+
316
+ ### Configuration File
317
+
318
+ Create `update.json` file:
319
+
320
+ ```json
321
+ {
322
+ "ios": {
323
+ "appId": "your-ios-app-id",
324
+ "appKey": "your-ios-app-key"
325
+ },
326
+ "android": {
327
+ "appId": "your-android-app-id",
328
+ "appKey": "your-android-app-key"
329
+ }
330
+ }
331
+ ```
332
+
333
+ ## 🚨 Important Notes
334
+
335
+ 1. **Backward Compatibility**: The new modular CLI maintains compatibility with existing CLI
336
+ 2. **Type Safety**: All APIs have complete TypeScript type definitions
337
+ 3. **Error Handling**: All operations return standardized result formats
338
+ 4. **Resource Cleanup**: Modules support cleanup functions to release resources
339
+ 5. **Module Separation**: Functionality is logically separated into different modules for easy maintenance and extension
340
+
341
+ ## 🤝 Contributing
342
+
343
+ Welcome to submit Issues and Pull Requests to improve this project!
344
+
345
+ ## 🚀 Provider API Usage Guide
346
+
347
+ Provider provides a concise programming interface suitable for integrating React Native Update CLI functionality in applications.
348
+
349
+ ### 📋 Core API Methods
350
+
351
+ #### Core Business Functions
352
+ ```typescript
353
+ // Bundle application
354
+ await provider.bundle({
355
+ platform: 'ios',
356
+ dev: false,
357
+ sourcemap: true
358
+ });
359
+
360
+ // Publish version
361
+ await provider.publish({
362
+ name: 'v1.0.0',
363
+ description: 'Bug fixes',
364
+ rollout: 100
365
+ });
366
+
367
+ // Upload file
368
+ await provider.upload({
369
+ filePath: 'app.ipa',
370
+ platform: 'ios'
371
+ });
372
+ ```
373
+
374
+ #### Application Management
375
+ ```typescript
376
+ // Create application
377
+ await provider.createApp('MyApp', 'ios');
378
+
379
+ // List applications
380
+ await provider.listApps('ios');
381
+
382
+ // Get current application
383
+ const { appId, platform } = await provider.getSelectedApp('ios');
384
+ ```
385
+
386
+ #### Version Management
387
+ ```typescript
388
+ // List versions
389
+ await provider.listVersions('app123');
390
+
391
+ // Update version
392
+ await provider.updateVersion('app123', 'version456', {
393
+ name: 'v1.1.0',
394
+ description: 'New features'
395
+ });
396
+ ```
397
+
398
+ #### Utility Functions
399
+ ```typescript
400
+ // Get platform
401
+ const platform = await provider.getPlatform('ios');
402
+
403
+ // Load session
404
+ const session = await provider.loadSession();
405
+ ```
406
+
407
+ ### 🎯 Use Cases
408
+
409
+ #### 1. Automated Build Scripts
410
+ ```typescript
411
+ import { moduleManager } from 'react-native-update-cli';
412
+
413
+ async function buildAndPublish() {
414
+ const provider = moduleManager.getProvider();
415
+
416
+ // 1. Bundle
417
+ const bundleResult = await provider.bundle({
418
+ platform: 'ios',
419
+ dev: false,
420
+ sourcemap: true
421
+ });
422
+
423
+ if (!bundleResult.success) {
424
+ throw new Error(`Bundle failed: ${bundleResult.error}`);
425
+ }
426
+
427
+ // 2. Publish
428
+ const publishResult = await provider.publish({
429
+ name: 'v1.2.3',
430
+ description: 'Bug fixes and performance improvements',
431
+ rollout: 100
432
+ });
433
+
434
+ if (!publishResult.success) {
435
+ throw new Error(`Publish failed: ${publishResult.error}`);
436
+ }
437
+
438
+ console.log('Build and publish completed!');
439
+ }
440
+ ```
441
+
442
+ #### 2. CI/CD Integration
443
+ ```typescript
444
+ async function ciBuild() {
445
+ const provider = moduleManager.getProvider();
446
+
447
+ const result = await provider.bundle({
448
+ platform: process.env.PLATFORM as 'ios' | 'android',
449
+ dev: process.env.NODE_ENV !== 'production',
450
+ sourcemap: process.env.NODE_ENV === 'production'
451
+ });
452
+
453
+ return result;
454
+ }
455
+ ```
456
+
457
+ #### 3. Application Management Service
458
+ ```typescript
459
+ class AppManagementService {
460
+ private provider = moduleManager.getProvider();
461
+
462
+ async setupNewApp(name: string, platform: Platform) {
463
+ // Create application
464
+ const createResult = await this.provider.createApp(name, platform);
465
+
466
+ if (createResult.success) {
467
+ // Get application information
468
+ const { appId } = await this.provider.getSelectedApp(platform);
469
+
470
+ // List versions
471
+ await this.provider.listVersions(appId);
472
+
473
+ return { appId, success: true };
474
+ }
475
+
476
+ return { success: false, error: createResult.error };
477
+ }
478
+ }
479
+ ```
480
+
481
+ ### ⚠️ Important Notes
482
+
483
+ 1. **Error Handling**: All Provider methods return `CommandResult`, need to check the `success` field
484
+ 2. **Type Safety**: Provider provides complete TypeScript type support
485
+ 3. **Session Management**: Ensure login before use, can check via `loadSession()`
486
+ 4. **Platform Support**: Supports `'ios' | 'android' | 'harmony'` three platforms
487
+
488
+ ### 🔧 Advanced Features
489
+
490
+ #### Custom Workflows
491
+ ```typescript
492
+ // Register custom workflow
493
+ provider.registerWorkflow({
494
+ name: 'quick-release',
495
+ description: 'Quick release process',
496
+ steps: [
497
+ {
498
+ name: 'bundle',
499
+ execute: async () => {
500
+ return await provider.bundle({ platform: 'ios', dev: false });
501
+ }
502
+ },
503
+ {
504
+ name: 'publish',
505
+ execute: async (context, bundleResult) => {
506
+ if (!bundleResult.success) {
507
+ throw new Error('Bundle failed, cannot publish');
508
+ }
509
+ return await provider.publish({ name: 'auto-release', rollout: 50 });
510
+ }
511
+ }
512
+ ]
513
+ });
514
+
515
+ // Execute workflow
516
+ await provider.executeWorkflow('quick-release', { args: [], options: {} });
517
+ ```
518
+
519
+ ### 📚 Complete Example
520
+
521
+ ```typescript
522
+ import { moduleManager } from 'react-native-update-cli';
523
+
524
+ class ReactNativeUpdateService {
525
+ private provider = moduleManager.getProvider();
526
+
527
+ async initialize() {
528
+ // Load session
529
+ await this.provider.loadSession();
530
+ }
531
+
532
+ async buildAndDeploy(platform: Platform, version: string) {
533
+ try {
534
+ // 1. Bundle
535
+ const bundleResult = await this.provider.bundle({
536
+ platform,
537
+ dev: false,
538
+ sourcemap: true
539
+ });
540
+
541
+ if (!bundleResult.success) {
542
+ throw new Error(`Bundle failed: ${bundleResult.error}`);
543
+ }
544
+
545
+ // 2. Publish
546
+ const publishResult = await this.provider.publish({
547
+ name: version,
548
+ description: `Release ${version}`,
549
+ rollout: 100
550
+ });
551
+
552
+ if (!publishResult.success) {
553
+ throw new Error(`Publish failed: ${publishResult.error}`);
554
+ }
555
+
556
+ return { success: true, data: publishResult.data };
557
+
558
+ } catch (error) {
559
+ return {
560
+ success: false,
561
+ error: error instanceof Error ? error.message : 'Unknown error'
562
+ };
563
+ }
564
+ }
565
+
566
+ async getAppInfo(platform: Platform) {
567
+ const { appId } = await this.provider.getSelectedApp(platform);
568
+ const versions = await this.provider.listVersions(appId);
569
+
570
+ return { appId, versions };
571
+ }
572
+ }
573
+
574
+ // Usage example
575
+ const service = new ReactNativeUpdateService();
576
+ await service.initialize();
577
+ await service.buildAndDeploy('ios', 'v1.0.0');
578
+ ```