δΈζζζ‘£ | Chinese Documentation
A unified React Native Update CLI that supports both traditional commands and modular architecture with custom publishing workflows.
- Unified CLI: Single
pushy
command for all functionality - Backward Compatibility: All existing commands work as before
- Modular Architecture: Split CLI functionality into independent modules
- Custom Workflows: Support for creating custom publishing workflows
- Extensibility: Users can import and register custom modules
- Type Safety: Complete TypeScript type support
npm install react-native-update-cli
# Use unified CLI
npx pushy help
# List all available commands and workflows
npx pushy list
# Execute built-in workflow
npx pushy workflow setup-app
# Execute custom workflow
npx pushy workflow custom-publish
import { moduleManager, CLIProviderImpl } from 'react-native-update-cli';
// Get CLI provider
const provider = moduleManager.getProvider();
// Execute bundling
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
});
// Publish version
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and improvements',
rollout: 100
});
import type { CLIModule, CommandDefinition, CustomWorkflow } from 'react-native-update-cli';
export const myCustomModule: CLIModule = {
name: 'my-custom',
version: '1.0.0',
commands: [
{
name: 'custom-command',
description: 'My custom command',
handler: async (context) => {
console.log('Executing custom command...');
return {
success: true,
data: { message: 'Custom command executed' }
};
},
options: {
param: { hasValue: true, description: 'Custom parameter' }
}
}
],
workflows: [
{
name: 'my-workflow',
description: 'My custom workflow',
steps: [
{
name: 'step1',
description: 'First step',
execute: async (context, previousResult) => {
console.log('Executing step 1...');
return { step1Completed: true };
}
},
{
name: 'step2',
description: 'Second step',
execute: async (context, previousResult) => {
console.log('Executing step 2...');
return { ...previousResult, step2Completed: true };
}
}
]
}
],
init: (provider) => {
console.log('Custom module initialized');
},
cleanup: () => {
console.log('Custom module cleanup');
}
};
import { moduleManager } from 'react-native-update-cli';
import { myCustomModule } from './my-custom-module';
// Register custom module
moduleManager.registerModule(myCustomModule);
// Execute custom command
const result = await moduleManager.executeCommand('custom-command', {
args: [],
options: { param: 'value' }
});
// Execute custom workflow
const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
args: [],
options: {}
});
Each workflow step contains:
name
: Step namedescription
: Step descriptionexecute
: Execution functioncondition
: Optional condition function
{
name: 'conditional-step',
description: 'Only execute in production',
execute: async (context, previousResult) => {
// Execution logic
},
condition: (context) => {
return context.options.environment === 'production';
}
}
{
name: 'validated-workflow',
description: 'Workflow with validation',
steps: [...],
validate: (context) => {
if (!context.options.requiredParam) {
console.error('Required parameter missing');
return false;
}
return true;
}
}
bundle
: Bundle JavaScript code and optionally publishdiff
: Generate differences between two PPK fileshdiff
: Generate hdiff between two PPK filesdiffFromApk
: Generate differences from APK fileshdiffFromApk
: Generate hdiff from APK fileshdiffFromApp
: Generate hdiff from APP filesdiffFromIpa
: Generate differences from IPA fileshdiffFromIpa
: Generate hdiff from IPA files
publish
: Publish new versionversions
: List all versionsupdate
: Update version informationupdateVersionInfo
: Update version metadata
createApp
: Create new applicationapps
: List all applicationsselectApp
: Select applicationdeleteApp
: Delete application
uploadIpa
: Upload IPA filesuploadApk
: Upload APK filesuploadApp
: Upload APP filesparseApp
: Parse APP file informationparseIpa
: Parse IPA file informationparseApk
: Parse APK file informationpackages
: List packages
login
: Loginlogout
: Logoutme
: Show user information
interface CLIProvider {
// Bundle
bundle(options: BundleOptions): Promise<CommandResult>;
// Publish
publish(options: PublishOptions): Promise<CommandResult>;
// Upload
upload(options: UploadOptions): Promise<CommandResult>;
// Application management
getSelectedApp(platform?: Platform): Promise<{ appId: string; platform: Platform }>;
listApps(platform?: Platform): Promise<CommandResult>;
createApp(name: string, platform: Platform): Promise<CommandResult>;
// Version management
listVersions(appId: string): Promise<CommandResult>;
getVersion(appId: string, versionId: string): Promise<CommandResult>;
updateVersion(appId: string, versionId: string, updates: Partial<Version>): Promise<CommandResult>;
// Package management
listPackages(appId: string, platform?: Platform): Promise<CommandResult>;
getPackage(appId: string, packageId: string): Promise<CommandResult>;
// Utility functions
getPlatform(platform?: Platform): Promise<Platform>;
loadSession(): Promise<Session>;
saveToLocal(key: string, value: string): void;
question(prompt: string): Promise<string>;
// Workflows
registerWorkflow(workflow: CustomWorkflow): void;
executeWorkflow(workflowName: string, context: CommandContext): Promise<CommandResult>;
}
// Execute custom bundle command
const bundleResult = await moduleManager.executeCommand('custom-bundle', {
args: [],
options: {
platform: 'android',
validate: true,
optimize: true
}
});
// Generate diff file
const diffResult = await moduleManager.executeCommand('diff', {
args: [],
options: {
origin: './build/v1.0.0.ppk',
next: './build/v1.1.0.ppk',
output: './build/diff.patch'
}
});
// Generate diff from APK files
const apkDiffResult = await moduleManager.executeCommand('diffFromApk', {
args: [],
options: {
origin: './build/app-v1.0.0.apk',
next: './build/app-v1.1.0.apk',
output: './build/apk-diff.patch'
}
});
# Set API endpoint
export PUSHY_REGISTRY=https://your-api-endpoint.com
# Set non-interactive mode
export NO_INTERACTIVE=true
Create update.json
file:
{
"ios": {
"appId": "your-ios-app-id",
"appKey": "your-ios-app-key"
},
"android": {
"appId": "your-android-app-id",
"appKey": "your-android-app-key"
}
}
- Backward Compatibility: The new modular CLI maintains compatibility with existing CLI
- Type Safety: All APIs have complete TypeScript type definitions
- Error Handling: All operations return standardized result formats
- Resource Cleanup: Modules support cleanup functions to release resources
- Module Separation: Functionality is logically separated into different modules for easy maintenance and extension
Welcome to submit Issues and Pull Requests to improve this project!
Provider provides a concise programming interface suitable for integrating React Native Update CLI functionality in applications.
// Bundle application
await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
});
// Publish version
await provider.publish({
name: 'v1.0.0',
description: 'Bug fixes',
rollout: 100
});
// Upload file
await provider.upload({
filePath: 'app.ipa',
platform: 'ios'
});
// Create application
await provider.createApp('MyApp', 'ios');
// List applications
await provider.listApps('ios');
// Get current application
const { appId, platform } = await provider.getSelectedApp('ios');
// List versions
await provider.listVersions('app123');
// Update version
await provider.updateVersion('app123', 'version456', {
name: 'v1.1.0',
description: 'New features'
});
// Get platform
const platform = await provider.getPlatform('ios');
// Load session
const session = await provider.loadSession();
import { moduleManager } from 'react-native-update-cli';
async function buildAndPublish() {
const provider = moduleManager.getProvider();
// 1. Bundle
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
});
if (!bundleResult.success) {
throw new Error(`Bundle failed: ${bundleResult.error}`);
}
// 2. Publish
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and performance improvements',
rollout: 100
});
if (!publishResult.success) {
throw new Error(`Publish failed: ${publishResult.error}`);
}
console.log('Build and publish completed!');
}
async function ciBuild() {
const provider = moduleManager.getProvider();
const result = await provider.bundle({
platform: process.env.PLATFORM as 'ios' | 'android',
dev: process.env.NODE_ENV !== 'production',
sourcemap: process.env.NODE_ENV === 'production'
});
return result;
}
class AppManagementService {
private provider = moduleManager.getProvider();
async setupNewApp(name: string, platform: Platform) {
// Create application
const createResult = await this.provider.createApp(name, platform);
if (createResult.success) {
// Get application information
const { appId } = await this.provider.getSelectedApp(platform);
// List versions
await this.provider.listVersions(appId);
return { appId, success: true };
}
return { success: false, error: createResult.error };
}
}
- Error Handling: All Provider methods return
CommandResult
, need to check thesuccess
field - Type Safety: Provider provides complete TypeScript type support
- Session Management: Ensure login before use, can check via
loadSession()
- Platform Support: Supports
'ios' | 'android' | 'harmony'
three platforms
// Register custom workflow
provider.registerWorkflow({
name: 'quick-release',
description: 'Quick release process',
steps: [
{
name: 'bundle',
execute: async () => {
return await provider.bundle({ platform: 'ios', dev: false });
}
},
{
name: 'publish',
execute: async (context, bundleResult) => {
if (!bundleResult.success) {
throw new Error('Bundle failed, cannot publish');
}
return await provider.publish({ name: 'auto-release', rollout: 50 });
}
}
]
});
// Execute workflow
await provider.executeWorkflow('quick-release', { args: [], options: {} });
import { moduleManager } from 'react-native-update-cli';
class ReactNativeUpdateService {
private provider = moduleManager.getProvider();
async initialize() {
// Load session
await this.provider.loadSession();
}
async buildAndDeploy(platform: Platform, version: string) {
try {
// 1. Bundle
const bundleResult = await this.provider.bundle({
platform,
dev: false,
sourcemap: true
});
if (!bundleResult.success) {
throw new Error(`Bundle failed: ${bundleResult.error}`);
}
// 2. Publish
const publishResult = await this.provider.publish({
name: version,
description: `Release ${version}`,
rollout: 100
});
if (!publishResult.success) {
throw new Error(`Publish failed: ${publishResult.error}`);
}
return { success: true, data: publishResult.data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async getAppInfo(platform: Platform) {
const { appId } = await this.provider.getSelectedApp(platform);
const versions = await this.provider.listVersions(appId);
return { appId, versions };
}
}
// Usage example
const service = new ReactNativeUpdateService();
await service.initialize();
await service.buildAndDeploy('ios', 'v1.0.0');