native-update 1.0.9 → 1.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.md +35 -17
- package/cli/cap-update.js +45 -0
- package/cli/commands/backend-create.js +582 -0
- package/cli/commands/bundle-create.js +113 -0
- package/cli/commands/bundle-sign.js +58 -0
- package/cli/commands/bundle-verify.js +55 -0
- package/cli/commands/init.js +146 -0
- package/cli/commands/keys-generate.js +92 -0
- package/cli/commands/monitor.js +68 -0
- package/cli/commands/server-start.js +96 -0
- package/cli/index.js +269 -0
- package/cli/package.json +12 -0
- package/docs/BUNDLE_SIGNING.md +16 -9
- package/docs/LIVE_UPDATES_GUIDE.md +1 -1
- package/docs/README.md +1 -0
- package/docs/cli-reference.md +321 -0
- package/docs/getting-started/configuration.md +3 -2
- package/docs/getting-started/quick-start.md +53 -1
- package/docs/guides/deployment-guide.md +9 -7
- package/docs/guides/key-management.md +284 -0
- package/docs/guides/migration-from-codepush.md +9 -5
- package/docs/guides/testing-guide.md +4 -4
- package/package.json +15 -2
package/cli/index.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Native Update CLI
|
|
5
|
+
*
|
|
6
|
+
* Provides command-line tools for managing Capacitor Native Update plugin
|
|
7
|
+
* Can be used with npx, global install, or local install
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
import fs from 'fs/promises';
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
const packagePath = join(__dirname, '..', 'package.json');
|
|
19
|
+
const packageJson = JSON.parse(await fs.readFile(packagePath, 'utf-8'));
|
|
20
|
+
|
|
21
|
+
const program = new Command();
|
|
22
|
+
|
|
23
|
+
program
|
|
24
|
+
.name('native-update')
|
|
25
|
+
.description(`CLI tools for Capacitor Native Update plugin
|
|
26
|
+
|
|
27
|
+
${chalk.bold('Quick Start:')}
|
|
28
|
+
${chalk.gray('npx native-update init --example')} # Initialize with examples
|
|
29
|
+
${chalk.gray('npx native-update backend create express')} # Create backend server
|
|
30
|
+
${chalk.gray('npx native-update bundle create ./www')} # Create update bundle
|
|
31
|
+
|
|
32
|
+
${chalk.bold('Documentation:')}
|
|
33
|
+
${chalk.blue('https://github.com/aoneahsan/native-update/blob/main/docs/cli-reference.md')}`)
|
|
34
|
+
.version(packageJson.version)
|
|
35
|
+
.configureHelp({
|
|
36
|
+
sortSubcommands: true,
|
|
37
|
+
subcommandTerm: (cmd) => cmd.name() + ' ' + cmd.aliases().join(', ')
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Bundle Management Commands
|
|
41
|
+
program
|
|
42
|
+
.command('bundle')
|
|
43
|
+
.description('Bundle management commands')
|
|
44
|
+
.command('create <webDir>')
|
|
45
|
+
.alias('create-bundle')
|
|
46
|
+
.description(`Create an update bundle from your web directory
|
|
47
|
+
|
|
48
|
+
${chalk.bold('Examples:')}
|
|
49
|
+
${chalk.gray('# Create bundle from default build directory')}
|
|
50
|
+
${chalk.green('npx native-update bundle create ./www')}
|
|
51
|
+
|
|
52
|
+
${chalk.gray('# Create with specific version and channel')}
|
|
53
|
+
${chalk.green('npx native-update bundle create ./dist --version 1.2.0 --channel staging')}
|
|
54
|
+
|
|
55
|
+
${chalk.gray('# Add metadata like release notes')}
|
|
56
|
+
${chalk.green(`npx native-update bundle create ./www --metadata '{"releaseNotes":"Bug fixes"}'`)}`)
|
|
57
|
+
.option('-o, --output <path>', 'Output directory for the bundle', './update-bundles')
|
|
58
|
+
.option('-v, --version <version>', 'Bundle version (defaults to package.json version)')
|
|
59
|
+
.option('-c, --channel <channel>', 'Release channel', 'production')
|
|
60
|
+
.option('-m, --metadata <json>', 'Additional metadata as JSON string')
|
|
61
|
+
.action(async (webDir, options) => {
|
|
62
|
+
const { createBundle } = await import('./commands/bundle-create.js');
|
|
63
|
+
await createBundle(webDir, options);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
program
|
|
67
|
+
.command('bundle')
|
|
68
|
+
.command('sign <bundlePath>')
|
|
69
|
+
.alias('sign-bundle')
|
|
70
|
+
.description(`Sign an update bundle with your private key
|
|
71
|
+
|
|
72
|
+
${chalk.bold('Examples:')}
|
|
73
|
+
${chalk.gray('# Sign a bundle with your private key')}
|
|
74
|
+
${chalk.green('npx native-update bundle sign ./bundle.zip --key ./keys/private.pem')}
|
|
75
|
+
|
|
76
|
+
${chalk.gray('# Specify output path for signed bundle')}
|
|
77
|
+
${chalk.green('npx native-update bundle sign ./bundle.zip --key private.pem --output ./signed-bundle.zip')}`)
|
|
78
|
+
.requiredOption('-k, --key <path>', 'Path to private key file')
|
|
79
|
+
.option('-o, --output <path>', 'Output path for signed bundle')
|
|
80
|
+
.action(async (bundlePath, options) => {
|
|
81
|
+
const { signBundle } = await import('./commands/bundle-sign.js');
|
|
82
|
+
await signBundle(bundlePath, options);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
program
|
|
86
|
+
.command('bundle')
|
|
87
|
+
.command('verify <bundlePath>')
|
|
88
|
+
.alias('verify-bundle')
|
|
89
|
+
.description(`Verify a signed bundle with public key
|
|
90
|
+
|
|
91
|
+
${chalk.bold('Example:')}
|
|
92
|
+
${chalk.green('npx native-update bundle verify ./signed-bundle.zip --key ./keys/public.pem')}`)
|
|
93
|
+
.requiredOption('-k, --key <path>', 'Path to public key file')
|
|
94
|
+
.action(async (bundlePath, options) => {
|
|
95
|
+
const { verifyBundle } = await import('./commands/bundle-verify.js');
|
|
96
|
+
await verifyBundle(bundlePath, options);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Key Management Commands
|
|
100
|
+
program
|
|
101
|
+
.command('keys')
|
|
102
|
+
.description('Key management commands')
|
|
103
|
+
.command('generate')
|
|
104
|
+
.alias('generate-keys')
|
|
105
|
+
.description(`Generate a new key pair for bundle signing
|
|
106
|
+
|
|
107
|
+
${chalk.bold('Examples:')}
|
|
108
|
+
${chalk.gray('# Generate default RSA 2048-bit keys')}
|
|
109
|
+
${chalk.green('npx native-update keys generate')}
|
|
110
|
+
|
|
111
|
+
${chalk.gray('# Generate strong RSA 4096-bit keys for production')}
|
|
112
|
+
${chalk.green('npx native-update keys generate --type rsa --size 4096')}
|
|
113
|
+
|
|
114
|
+
${chalk.gray('# Generate EC keys for smaller signatures')}
|
|
115
|
+
${chalk.green('npx native-update keys generate --type ec --size 256 --output ./my-keys')}`)
|
|
116
|
+
.option('-o, --output <dir>', 'Output directory for keys', './keys')
|
|
117
|
+
.option('-t, --type <type>', 'Key type (rsa or ec)', 'rsa')
|
|
118
|
+
.option('-s, --size <size>', 'Key size (RSA: 2048/4096, EC: 256/384)', '2048')
|
|
119
|
+
.action(async (options) => {
|
|
120
|
+
const { generateKeys } = await import('./commands/keys-generate.js');
|
|
121
|
+
await generateKeys(options);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Server Commands
|
|
125
|
+
program
|
|
126
|
+
.command('server')
|
|
127
|
+
.description('Development server commands')
|
|
128
|
+
.command('start')
|
|
129
|
+
.alias('start-server')
|
|
130
|
+
.description('Start a local update server for testing')
|
|
131
|
+
.option('-p, --port <port>', 'Server port', '3000')
|
|
132
|
+
.option('-d, --dir <dir>', 'Directory containing update bundles', './update-bundles')
|
|
133
|
+
.option('--cors', 'Enable CORS for testing', true)
|
|
134
|
+
.action(async (options) => {
|
|
135
|
+
const { startServer } = await import('./commands/server-start.js');
|
|
136
|
+
await startServer(options);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Init Commands
|
|
140
|
+
program
|
|
141
|
+
.command('init')
|
|
142
|
+
.description(`Initialize native-update in your project
|
|
143
|
+
|
|
144
|
+
${chalk.bold('Examples:')}
|
|
145
|
+
${chalk.gray('# Basic initialization')}
|
|
146
|
+
${chalk.green('npx native-update init')}
|
|
147
|
+
|
|
148
|
+
${chalk.gray('# Initialize with example code and configuration')}
|
|
149
|
+
${chalk.green('npx native-update init --example')}
|
|
150
|
+
|
|
151
|
+
${chalk.gray('# Initialize for Firebase backend')}
|
|
152
|
+
${chalk.green('npx native-update init --backend firebase --example')}`)
|
|
153
|
+
.option('--example', 'Include example configuration')
|
|
154
|
+
.option('--backend <type>', 'Backend type (firebase, express, custom)', 'custom')
|
|
155
|
+
.action(async (options) => {
|
|
156
|
+
const { init } = await import('./commands/init.js');
|
|
157
|
+
await init(options);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Backend Commands
|
|
161
|
+
program
|
|
162
|
+
.command('backend')
|
|
163
|
+
.description('Backend template commands')
|
|
164
|
+
.command('create <type>')
|
|
165
|
+
.alias('create-backend')
|
|
166
|
+
.description(`Create a backend template (express, firebase, vercel)
|
|
167
|
+
|
|
168
|
+
${chalk.bold('Examples:')}
|
|
169
|
+
${chalk.gray('# Create Express.js backend with admin dashboard')}
|
|
170
|
+
${chalk.green('npx native-update backend create express --with-admin')}
|
|
171
|
+
|
|
172
|
+
${chalk.gray('# Create Firebase Functions backend with monitoring')}
|
|
173
|
+
${chalk.green('npx native-update backend create firebase --with-monitoring')}
|
|
174
|
+
|
|
175
|
+
${chalk.gray('# Create Vercel serverless backend')}
|
|
176
|
+
${chalk.green('npx native-update backend create vercel --output my-backend')}`)
|
|
177
|
+
.option('-o, --output <dir>', 'Output directory', './native-update-backend')
|
|
178
|
+
.option('--with-monitoring', 'Include monitoring setup', false)
|
|
179
|
+
.option('--with-admin', 'Include admin dashboard', false)
|
|
180
|
+
.action(async (type, options) => {
|
|
181
|
+
const { createBackend } = await import('./commands/backend-create.js');
|
|
182
|
+
await createBackend(type, options);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Config Commands
|
|
186
|
+
program
|
|
187
|
+
.command('config')
|
|
188
|
+
.description('Configuration commands')
|
|
189
|
+
.command('check')
|
|
190
|
+
.description('Validate your native-update configuration')
|
|
191
|
+
.action(async () => {
|
|
192
|
+
const { checkConfig } = await import('./commands/config-check.js');
|
|
193
|
+
await checkConfig();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Migration Commands
|
|
197
|
+
program
|
|
198
|
+
.command('migrate')
|
|
199
|
+
.description('Migrate from other OTA solutions')
|
|
200
|
+
.option('--from <solution>', 'Source solution (codepush, appflow)', 'codepush')
|
|
201
|
+
.action(async (options) => {
|
|
202
|
+
const { migrate } = await import('./commands/migrate.js');
|
|
203
|
+
await migrate(options);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Monitoring Commands
|
|
207
|
+
program
|
|
208
|
+
.command('monitor')
|
|
209
|
+
.description('Monitor update deployments')
|
|
210
|
+
.option('-s, --server <url>', 'Backend server URL')
|
|
211
|
+
.option('-k, --key <key>', 'API key for authentication')
|
|
212
|
+
.action(async (options) => {
|
|
213
|
+
const { monitor } = await import('./commands/monitor.js');
|
|
214
|
+
await monitor(options);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Add helpful examples
|
|
218
|
+
program.on('--help', () => {
|
|
219
|
+
console.log('');
|
|
220
|
+
console.log('Examples:');
|
|
221
|
+
console.log('');
|
|
222
|
+
console.log(' Quick Start:');
|
|
223
|
+
console.log(' $ npx native-update init --example');
|
|
224
|
+
console.log(' $ npx native-update backend create express --with-admin');
|
|
225
|
+
console.log('');
|
|
226
|
+
console.log(' Bundle Management:');
|
|
227
|
+
console.log(' $ npx native-update bundle create ./www');
|
|
228
|
+
console.log(' $ npx native-update bundle sign ./bundle.zip --key ./keys/private.pem');
|
|
229
|
+
console.log(' $ npx native-update bundle verify ./bundle.zip --key ./keys/public.pem');
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log(' Key Management:');
|
|
232
|
+
console.log(' $ npx native-update keys generate --type rsa --size 4096');
|
|
233
|
+
console.log('');
|
|
234
|
+
console.log(' Development:');
|
|
235
|
+
console.log(' $ npx native-update server start --port 3000');
|
|
236
|
+
console.log(' $ npx native-update monitor --server http://localhost:3000');
|
|
237
|
+
console.log('');
|
|
238
|
+
console.log(' Backend Templates:');
|
|
239
|
+
console.log(' $ npx native-update backend create express');
|
|
240
|
+
console.log(' $ npx native-update backend create firebase --with-monitoring');
|
|
241
|
+
console.log(' $ npx native-update backend create vercel --with-admin');
|
|
242
|
+
console.log('');
|
|
243
|
+
console.log(chalk.bold('Resources:'));
|
|
244
|
+
console.log(' Documentation: ' + chalk.blue('https://github.com/aoneahsan/native-update/blob/main/docs/'));
|
|
245
|
+
console.log(' CLI Reference: ' + chalk.blue('https://github.com/aoneahsan/native-update/blob/main/docs/cli-reference.md'));
|
|
246
|
+
console.log(' Quick Start: ' + chalk.blue('https://github.com/aoneahsan/native-update/blob/main/docs/getting-started/quick-start.md'));
|
|
247
|
+
console.log('');
|
|
248
|
+
console.log(chalk.bold('Support:'));
|
|
249
|
+
console.log(' Issues: ' + chalk.blue('https://github.com/aoneahsan/native-update/issues'));
|
|
250
|
+
console.log(' Author: Ahsan Mahmood (' + chalk.blue('https://aoneahsan.com') + ')');
|
|
251
|
+
console.log(' Email: ' + chalk.blue('aoneahsan@gmail.com'));
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Error handling
|
|
255
|
+
program.exitOverride();
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
await program.parseAsync(process.argv);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
if (error.code === 'commander.missingArgument') {
|
|
261
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
262
|
+
} else if (error.code === 'commander.unknownCommand') {
|
|
263
|
+
console.error(chalk.red(`Error: Unknown command`));
|
|
264
|
+
program.outputHelp();
|
|
265
|
+
} else {
|
|
266
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
267
|
+
}
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
package/cli/package.json
ADDED
package/docs/BUNDLE_SIGNING.md
CHANGED
|
@@ -14,16 +14,23 @@ Bundle signing uses RSA-2048 with SHA-256 to create digital signatures that veri
|
|
|
14
14
|
|
|
15
15
|
### 1. Generate RSA Key Pair
|
|
16
16
|
|
|
17
|
+
The easiest way is using our CLI tool:
|
|
18
|
+
|
|
17
19
|
```bash
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
# Generate strong RSA keys for production
|
|
21
|
+
npx native-update keys generate --type rsa --size 4096
|
|
22
|
+
|
|
23
|
+
# Or generate EC keys for smaller signatures
|
|
24
|
+
npx native-update keys generate --type ec --size 256
|
|
20
25
|
```
|
|
21
26
|
|
|
22
27
|
This creates:
|
|
23
28
|
|
|
24
|
-
- `private.
|
|
25
|
-
- `public.
|
|
26
|
-
-
|
|
29
|
+
- `private-{timestamp}.pem` - Keep secure on your server (NEVER commit to git!)
|
|
30
|
+
- `public-{timestamp}.pem` - Include in your app
|
|
31
|
+
- Proper file permissions (600) are set automatically
|
|
32
|
+
|
|
33
|
+
For detailed key management instructions, see the [Key Management Guide](./guides/key-management.md).
|
|
27
34
|
|
|
28
35
|
### 2. Secure Private Key
|
|
29
36
|
|
|
@@ -55,7 +62,7 @@ const signature = signBundle(fileBuffer, privateKey);
|
|
|
55
62
|
Sign bundles manually:
|
|
56
63
|
|
|
57
64
|
```bash
|
|
58
|
-
|
|
65
|
+
npx native-update bundle sign bundle-1.0.0.zip --key /secure/keys/private.key
|
|
59
66
|
```
|
|
60
67
|
|
|
61
68
|
This creates `bundle-1.0.0.zip.sig` containing the base64 signature.
|
|
@@ -161,7 +168,7 @@ async function verifyBundle(
|
|
|
161
168
|
PRIVATE_KEY: ${{ secrets.BUNDLE_SIGNING_KEY }}
|
|
162
169
|
run: |
|
|
163
170
|
echo "$PRIVATE_KEY" > private.key
|
|
164
|
-
|
|
171
|
+
npx native-update bundle sign dist/bundle.zip --key private.key
|
|
165
172
|
rm private.key
|
|
166
173
|
```
|
|
167
174
|
|
|
@@ -169,7 +176,7 @@ async function verifyBundle(
|
|
|
169
176
|
|
|
170
177
|
```groovy
|
|
171
178
|
withCredentials([file(credentialsId: 'bundle-signing-key', variable: 'KEY_FILE')]) {
|
|
172
|
-
sh '
|
|
179
|
+
sh 'npx native-update bundle sign dist/bundle.zip --key $KEY_FILE'
|
|
173
180
|
}
|
|
174
181
|
```
|
|
175
182
|
|
|
@@ -198,7 +205,7 @@ Test signature verification:
|
|
|
198
205
|
|
|
199
206
|
```bash
|
|
200
207
|
# Verify manually
|
|
201
|
-
|
|
208
|
+
npx native-update bundle verify bundle.zip --key public.key
|
|
202
209
|
|
|
203
210
|
# Check signature format
|
|
204
211
|
cat bundle.zip.sig | base64 -d | xxd | head
|
|
@@ -397,7 +397,7 @@ zip -r ../bundle-1.0.1.zip www/
|
|
|
397
397
|
|
|
398
398
|
# 3. Sign the bundle (optional but recommended)
|
|
399
399
|
cd ..
|
|
400
|
-
|
|
400
|
+
npx native-update bundle sign bundle-1.0.1.zip --key private.key
|
|
401
401
|
|
|
402
402
|
# 4. Upload to server
|
|
403
403
|
curl -X POST https://updates.example.com/api/v1/bundles \
|
package/docs/README.md
CHANGED
|
@@ -33,6 +33,7 @@ Created by **Ahsan Mahmood** and open-sourced for the developer community, this
|
|
|
33
33
|
### Guides
|
|
34
34
|
|
|
35
35
|
- [**Security Best Practices**](./guides/security-best-practices.md) - Implement secure updates
|
|
36
|
+
- [**Key Management**](./guides/key-management.md) - Generate and manage signing keys
|
|
36
37
|
- [**Migration from CodePush**](./guides/migration-from-codepush.md) - Migrate from CodePush
|
|
37
38
|
- [**Testing Guide**](./guides/testing-guide.md) - Testing your update implementation
|
|
38
39
|
- [**Deployment Guide**](./guides/deployment-guide.md) - Deploy to production
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# CLI Reference
|
|
2
|
+
|
|
3
|
+
The Native Update CLI provides comprehensive tools for managing your update workflow.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The CLI is included with the native-update package. You can use it via npx without any additional installation:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Use directly with npx (recommended)
|
|
11
|
+
npx native-update <command>
|
|
12
|
+
|
|
13
|
+
# Or install globally
|
|
14
|
+
npm install -g native-update
|
|
15
|
+
|
|
16
|
+
# Or use locally in your project
|
|
17
|
+
npm install native-update
|
|
18
|
+
npx native-update <command>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
### Bundle Management
|
|
24
|
+
|
|
25
|
+
#### `bundle create <webDir>`
|
|
26
|
+
|
|
27
|
+
Creates an update bundle from your web build directory.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx native-update bundle create ./www
|
|
31
|
+
|
|
32
|
+
# Options:
|
|
33
|
+
# -o, --output <path> Output directory (default: ./update-bundles)
|
|
34
|
+
# -v, --version <version> Bundle version (default: from package.json)
|
|
35
|
+
# -c, --channel <channel> Release channel (default: production)
|
|
36
|
+
# -m, --metadata <json> Additional metadata as JSON string
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Example:**
|
|
40
|
+
```bash
|
|
41
|
+
npx native-update bundle create ./dist \
|
|
42
|
+
--version 1.2.0 \
|
|
43
|
+
--channel staging \
|
|
44
|
+
--metadata '{"releaseNotes":"Bug fixes"}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### `bundle sign <bundlePath>`
|
|
48
|
+
|
|
49
|
+
Signs a bundle with your private key for security verification.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx native-update bundle sign ./bundle.zip --key ./keys/private.pem
|
|
53
|
+
|
|
54
|
+
# Options:
|
|
55
|
+
# -k, --key <path> Path to private key file (required)
|
|
56
|
+
# -o, --output <path> Output path for signed bundle
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### `bundle verify <bundlePath>`
|
|
60
|
+
|
|
61
|
+
Verifies a signed bundle with the public key.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx native-update bundle verify ./bundle.zip --key ./keys/public.pem
|
|
65
|
+
|
|
66
|
+
# Options:
|
|
67
|
+
# -k, --key <path> Path to public key file (required)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Key Management
|
|
71
|
+
|
|
72
|
+
#### `keys generate`
|
|
73
|
+
|
|
74
|
+
Generates a new cryptographic key pair for bundle signing. This is the recommended way to create keys for the Native Update plugin.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx native-update keys generate
|
|
78
|
+
|
|
79
|
+
# Options:
|
|
80
|
+
# -o, --output <dir> Output directory (default: ./keys)
|
|
81
|
+
# -t, --type <type> Key type: rsa or ec (default: rsa)
|
|
82
|
+
# -s, --size <size> Key size - RSA: 2048/4096, EC: 256/384 (default: 2048)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**What it creates:**
|
|
86
|
+
- `private-{timestamp}.pem` - Private key for signing (keep SECRET on server)
|
|
87
|
+
- `public-{timestamp}.pem` - Public key for verification (include in app)
|
|
88
|
+
- Sets proper file permissions (600) on private key
|
|
89
|
+
- Timestamps prevent accidental overwriting
|
|
90
|
+
|
|
91
|
+
**Example:**
|
|
92
|
+
```bash
|
|
93
|
+
# Generate strong RSA keys for production (recommended)
|
|
94
|
+
npx native-update keys generate --type rsa --size 4096
|
|
95
|
+
|
|
96
|
+
# Generate EC keys for smaller signature size
|
|
97
|
+
npx native-update keys generate --type ec --size 256
|
|
98
|
+
|
|
99
|
+
# Generate in custom directory
|
|
100
|
+
npx native-update keys generate --output ./my-keys --type rsa --size 4096
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Security Notes:**
|
|
104
|
+
- NEVER commit private keys to version control
|
|
105
|
+
- Store private keys in secure locations with restricted access
|
|
106
|
+
- Use environment variables or key management services in production
|
|
107
|
+
- See [Key Management Guide](./guides/key-management.md) for best practices
|
|
108
|
+
|
|
109
|
+
### Backend Templates
|
|
110
|
+
|
|
111
|
+
#### `backend create <type>`
|
|
112
|
+
|
|
113
|
+
Creates a backend server template for hosting updates.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx native-update backend create express
|
|
117
|
+
|
|
118
|
+
# Types available:
|
|
119
|
+
# express - Node.js Express server
|
|
120
|
+
# firebase - Firebase Functions
|
|
121
|
+
# vercel - Vercel serverless functions
|
|
122
|
+
|
|
123
|
+
# Options:
|
|
124
|
+
# -o, --output <dir> Output directory (default: ./native-update-backend)
|
|
125
|
+
# --with-monitoring Include monitoring setup
|
|
126
|
+
# --with-admin Include admin dashboard
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Examples:**
|
|
130
|
+
```bash
|
|
131
|
+
# Express server with admin dashboard
|
|
132
|
+
npx native-update backend create express --with-admin
|
|
133
|
+
|
|
134
|
+
# Firebase Functions with monitoring
|
|
135
|
+
npx native-update backend create firebase --with-monitoring
|
|
136
|
+
|
|
137
|
+
# Vercel deployment ready backend
|
|
138
|
+
npx native-update backend create vercel
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Development Tools
|
|
142
|
+
|
|
143
|
+
#### `server start`
|
|
144
|
+
|
|
145
|
+
Starts a local update server for development and testing.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx native-update server start
|
|
149
|
+
|
|
150
|
+
# Options:
|
|
151
|
+
# -p, --port <port> Server port (default: 3000)
|
|
152
|
+
# -d, --dir <dir> Directory containing bundles (default: ./update-bundles)
|
|
153
|
+
# --cors Enable CORS (default: true)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### `init`
|
|
157
|
+
|
|
158
|
+
Initializes Native Update configuration in your project.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npx native-update init
|
|
162
|
+
|
|
163
|
+
# Options:
|
|
164
|
+
# --example Include example code
|
|
165
|
+
# --backend <type> Backend type: firebase, express, custom (default: custom)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Monitoring
|
|
169
|
+
|
|
170
|
+
#### `monitor`
|
|
171
|
+
|
|
172
|
+
Monitors update deployment statistics in real-time.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx native-update monitor --server https://your-update-server.com
|
|
176
|
+
|
|
177
|
+
# Options:
|
|
178
|
+
# -s, --server <url> Backend server URL (required)
|
|
179
|
+
# -k, --key <key> API key for authentication
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Configuration
|
|
183
|
+
|
|
184
|
+
#### `config check`
|
|
185
|
+
|
|
186
|
+
Validates your Native Update configuration.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npx native-update config check
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Migration
|
|
193
|
+
|
|
194
|
+
#### `migrate`
|
|
195
|
+
|
|
196
|
+
Helps migrate from other OTA solutions.
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npx native-update migrate --from codepush
|
|
200
|
+
|
|
201
|
+
# Options:
|
|
202
|
+
# --from <solution> Source solution: codepush, appflow (default: codepush)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Complete Workflow Example
|
|
206
|
+
|
|
207
|
+
Here's a typical workflow using the CLI:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# 1. Initialize in your project
|
|
211
|
+
npx native-update init --example
|
|
212
|
+
|
|
213
|
+
# 2. Generate signing keys
|
|
214
|
+
npx native-update keys generate --type rsa --size 4096
|
|
215
|
+
|
|
216
|
+
# 3. Create a backend
|
|
217
|
+
npx native-update backend create express --with-admin
|
|
218
|
+
|
|
219
|
+
# 4. Start the backend (in another terminal)
|
|
220
|
+
cd native-update-backend
|
|
221
|
+
npm install
|
|
222
|
+
npm run dev
|
|
223
|
+
|
|
224
|
+
# 5. Build your app
|
|
225
|
+
npm run build
|
|
226
|
+
|
|
227
|
+
# 6. Create and sign a bundle
|
|
228
|
+
npx native-update bundle create ./www --version 1.0.1
|
|
229
|
+
npx native-update bundle sign ./update-bundles/bundle-*.zip --key ./keys/private-*.pem
|
|
230
|
+
|
|
231
|
+
# 7. Upload to your server (use the admin dashboard or API)
|
|
232
|
+
|
|
233
|
+
# 8. Monitor deployments
|
|
234
|
+
npx native-update monitor --server http://localhost:3000
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## CI/CD Integration
|
|
238
|
+
|
|
239
|
+
### GitHub Actions
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
- name: Create Update Bundle
|
|
243
|
+
run: |
|
|
244
|
+
npx native-update bundle create ./dist \
|
|
245
|
+
--version ${{ github.event.release.tag_name }}
|
|
246
|
+
--channel production
|
|
247
|
+
|
|
248
|
+
- name: Sign Bundle
|
|
249
|
+
run: |
|
|
250
|
+
npx native-update bundle sign ./update-bundles/*.zip \
|
|
251
|
+
--key ${{ secrets.PRIVATE_KEY }}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Jenkins
|
|
255
|
+
|
|
256
|
+
```groovy
|
|
257
|
+
stage('Create Update') {
|
|
258
|
+
steps {
|
|
259
|
+
sh 'npx native-update bundle create ./www --version ${BUILD_NUMBER}'
|
|
260
|
+
sh 'npx native-update bundle sign ./update-bundles/*.zip --key ${PRIVATE_KEY_PATH}'
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Environment Variables
|
|
266
|
+
|
|
267
|
+
The CLI respects these environment variables:
|
|
268
|
+
|
|
269
|
+
- `NATIVE_UPDATE_SERVER` - Default server URL for commands
|
|
270
|
+
- `NATIVE_UPDATE_API_KEY` - Default API key for authentication
|
|
271
|
+
- `NATIVE_UPDATE_CHANNEL` - Default release channel
|
|
272
|
+
- `NO_COLOR` - Disable colored output
|
|
273
|
+
|
|
274
|
+
## Troubleshooting
|
|
275
|
+
|
|
276
|
+
### "Command not found"
|
|
277
|
+
|
|
278
|
+
Make sure you're using `npx` or have installed the package:
|
|
279
|
+
```bash
|
|
280
|
+
npx native-update <command>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### "EACCES: permission denied"
|
|
284
|
+
|
|
285
|
+
Key files need proper permissions:
|
|
286
|
+
```bash
|
|
287
|
+
chmod 600 ./keys/private-*.pem
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Bundle creation fails
|
|
291
|
+
|
|
292
|
+
Ensure your web directory contains built files:
|
|
293
|
+
```bash
|
|
294
|
+
# Build first
|
|
295
|
+
npm run build
|
|
296
|
+
|
|
297
|
+
# Then create bundle
|
|
298
|
+
npx native-update bundle create ./www
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Best Practices
|
|
302
|
+
|
|
303
|
+
1. **Security**
|
|
304
|
+
- Keep private keys secure and never commit them
|
|
305
|
+
- Use strong RSA 4096 keys for production
|
|
306
|
+
- Always sign bundles before deployment
|
|
307
|
+
|
|
308
|
+
2. **Versioning**
|
|
309
|
+
- Use semantic versioning (1.0.0, 1.0.1, etc.)
|
|
310
|
+
- Increment versions for each update
|
|
311
|
+
- Use channels for staged rollouts
|
|
312
|
+
|
|
313
|
+
3. **Testing**
|
|
314
|
+
- Test updates locally first using `server start`
|
|
315
|
+
- Verify bundles before deployment
|
|
316
|
+
- Use staging channel before production
|
|
317
|
+
|
|
318
|
+
4. **Monitoring**
|
|
319
|
+
- Always monitor deployments
|
|
320
|
+
- Set up alerts for failed updates
|
|
321
|
+
- Track adoption rates
|
|
@@ -66,8 +66,9 @@ liveUpdate: {
|
|
|
66
66
|
serverUrl: 'https://updates.yourserver.com',
|
|
67
67
|
channel: 'production',
|
|
68
68
|
|
|
69
|
-
// Security
|
|
70
|
-
|
|
69
|
+
// Security (see Key Management Guide for generating keys)
|
|
70
|
+
// Generate keys: npx native-update keys generate --type rsa --size 4096
|
|
71
|
+
publicKey: 'YOUR_RSA_PUBLIC_KEY', // Base64 encoded public key
|
|
71
72
|
requireSignature: true,
|
|
72
73
|
checksumAlgorithm: 'SHA-256', // or 'SHA-512'
|
|
73
74
|
|