native-update 1.4.0 → 1.4.2
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/AI-INTEGRATION-GUIDE.md +290 -0
- package/Readme.md +2 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/AppUpdatePlugin.kt +0 -3
- package/cli/node_modules/.yarn-integrity +16 -0
- package/cli/node_modules/commander/LICENSE +22 -0
- package/cli/node_modules/commander/Readme.md +1148 -0
- package/cli/node_modules/commander/esm.mjs +16 -0
- package/cli/node_modules/commander/index.js +26 -0
- package/cli/node_modules/commander/lib/argument.js +145 -0
- package/cli/node_modules/commander/lib/command.js +2179 -0
- package/cli/node_modules/commander/lib/error.js +43 -0
- package/cli/node_modules/commander/lib/help.js +462 -0
- package/cli/node_modules/commander/lib/option.js +329 -0
- package/cli/node_modules/commander/lib/suggestSimilar.js +100 -0
- package/cli/node_modules/commander/package-support.json +16 -0
- package/cli/node_modules/commander/package.json +80 -0
- package/cli/node_modules/commander/typings/esm.d.mts +3 -0
- package/cli/node_modules/commander/typings/index.d.ts +884 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/plugin.js.map +1 -1
- package/package.json +16 -12
- package/example-apps/react-capacitor/android/app/build/.npmkeep +0 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# AI Integration Guide - Native Update
|
|
2
|
+
|
|
3
|
+
Quick reference for AI development agents (Claude Code, Cursor, Copilot, etc.) to integrate native-update into Capacitor projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn add native-update
|
|
9
|
+
# or
|
|
10
|
+
npm install native-update
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Core Concepts
|
|
14
|
+
|
|
15
|
+
Native Update provides three main features:
|
|
16
|
+
1. **Live Updates (OTA)** - Deploy JS/HTML/CSS updates without app store approval
|
|
17
|
+
2. **App Updates** - Native app store update management (Google Play, App Store)
|
|
18
|
+
3. **App Reviews** - In-app review prompts
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Setup
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { NativeUpdate } from 'native-update';
|
|
26
|
+
|
|
27
|
+
// Configure the plugin
|
|
28
|
+
await NativeUpdate.configure({
|
|
29
|
+
appId: 'your-app-id',
|
|
30
|
+
channel: 'production', // 'development' | 'staging' | 'production'
|
|
31
|
+
updateUrl: 'https://your-update-server.com/api',
|
|
32
|
+
autoCheck: true,
|
|
33
|
+
checkInterval: 3600000, // 1 hour in ms
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Live Updates (OTA)
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { NativeUpdate } from 'native-update';
|
|
41
|
+
|
|
42
|
+
// Check and apply updates
|
|
43
|
+
const result = await NativeUpdate.sync();
|
|
44
|
+
if (result.updateAvailable) {
|
|
45
|
+
console.log('Update applied, reload required');
|
|
46
|
+
await NativeUpdate.reload();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Manual update flow
|
|
50
|
+
const latest = await NativeUpdate.getLatest();
|
|
51
|
+
if (latest.available) {
|
|
52
|
+
const bundle = await NativeUpdate.download({ version: latest.version });
|
|
53
|
+
await NativeUpdate.set(bundle);
|
|
54
|
+
await NativeUpdate.reload();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Notify app is stable after update (prevents auto-rollback)
|
|
58
|
+
await NativeUpdate.notifyAppReady();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### App Store Updates
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { NativeUpdate } from 'native-update';
|
|
65
|
+
|
|
66
|
+
// Check for app store updates
|
|
67
|
+
const updateInfo = await NativeUpdate.getAppUpdateInfo();
|
|
68
|
+
if (updateInfo.updateAvailable) {
|
|
69
|
+
if (updateInfo.updatePriority >= 4) {
|
|
70
|
+
// Critical update - force immediate
|
|
71
|
+
await NativeUpdate.performImmediateUpdate();
|
|
72
|
+
} else {
|
|
73
|
+
// Flexible update - download in background
|
|
74
|
+
await NativeUpdate.startFlexibleUpdate();
|
|
75
|
+
// Later, when ready to install
|
|
76
|
+
await NativeUpdate.completeFlexibleUpdate();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### App Reviews
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { NativeUpdate } from 'native-update';
|
|
85
|
+
|
|
86
|
+
// Request review at appropriate moment
|
|
87
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
88
|
+
if (canRequest.eligible) {
|
|
89
|
+
const result = await NativeUpdate.requestReview();
|
|
90
|
+
// Note: Actual review submission not guaranteed (platform controls)
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API Reference
|
|
95
|
+
|
|
96
|
+
### Live Update Methods
|
|
97
|
+
|
|
98
|
+
| Method | Description | Returns |
|
|
99
|
+
|--------|-------------|---------|
|
|
100
|
+
| `sync(options?)` | Check and apply updates | `Promise<SyncResult>` |
|
|
101
|
+
| `download(options)` | Download specific version | `Promise<BundleInfo>` |
|
|
102
|
+
| `set(bundle)` | Set active bundle | `Promise<void>` |
|
|
103
|
+
| `reload()` | Reload app with current bundle | `Promise<void>` |
|
|
104
|
+
| `reset()` | Reset to original bundle | `Promise<void>` |
|
|
105
|
+
| `current()` | Get current bundle info | `Promise<BundleInfo>` |
|
|
106
|
+
| `list()` | List all downloaded bundles | `Promise<BundleInfo[]>` |
|
|
107
|
+
| `delete(options)` | Delete bundles | `Promise<void>` |
|
|
108
|
+
| `notifyAppReady()` | Mark update as stable | `Promise<void>` |
|
|
109
|
+
| `getLatest()` | Check for latest version | `Promise<LatestVersion>` |
|
|
110
|
+
| `setChannel(channel)` | Switch update channel | `Promise<void>` |
|
|
111
|
+
| `setUpdateUrl(url)` | Set update server URL | `Promise<void>` |
|
|
112
|
+
|
|
113
|
+
### App Update Methods
|
|
114
|
+
|
|
115
|
+
| Method | Description | Returns |
|
|
116
|
+
|--------|-------------|---------|
|
|
117
|
+
| `getAppUpdateInfo()` | Get app store update info | `Promise<AppUpdateInfo>` |
|
|
118
|
+
| `performImmediateUpdate()` | Force immediate update | `Promise<void>` |
|
|
119
|
+
| `startFlexibleUpdate()` | Start background download | `Promise<void>` |
|
|
120
|
+
| `completeFlexibleUpdate()` | Install downloaded update | `Promise<void>` |
|
|
121
|
+
| `openAppStore(options?)` | Open app store page | `Promise<void>` |
|
|
122
|
+
|
|
123
|
+
### App Review Methods
|
|
124
|
+
|
|
125
|
+
| Method | Description | Returns |
|
|
126
|
+
|--------|-------------|---------|
|
|
127
|
+
| `requestReview()` | Request in-app review | `Promise<ReviewResult>` |
|
|
128
|
+
| `canRequestReview()` | Check review eligibility | `Promise<CanRequestReviewResult>` |
|
|
129
|
+
|
|
130
|
+
## Configuration Options
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
interface NativeUpdateConfig {
|
|
134
|
+
appId: string; // Your app identifier
|
|
135
|
+
channel?: string; // Update channel (default: 'production')
|
|
136
|
+
updateUrl?: string; // Update server URL
|
|
137
|
+
autoCheck?: boolean; // Auto-check for updates (default: true)
|
|
138
|
+
checkInterval?: number; // Check interval in ms (default: 3600000)
|
|
139
|
+
autoDownload?: boolean; // Auto-download updates (default: false)
|
|
140
|
+
autoInstall?: boolean; // Auto-install after download (default: false)
|
|
141
|
+
requireWifi?: boolean; // Only download on WiFi (default: true)
|
|
142
|
+
minBatteryLevel?: number; // Min battery % for updates (default: 20)
|
|
143
|
+
publicKey?: string; // Public key for signature verification
|
|
144
|
+
checksumAlgorithm?: 'sha256' | 'sha512'; // Checksum algorithm (default: 'sha256')
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Event Listeners
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { NativeUpdate } from 'native-update';
|
|
152
|
+
|
|
153
|
+
// Listen for update events
|
|
154
|
+
NativeUpdate.addListener('updateAvailable', (info) => {
|
|
155
|
+
console.log('Update available:', info.version);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
NativeUpdate.addListener('downloadProgress', (progress) => {
|
|
159
|
+
console.log(`Download: ${progress.percent}%`);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
NativeUpdate.addListener('downloadComplete', (bundle) => {
|
|
163
|
+
console.log('Download complete:', bundle.version);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
NativeUpdate.addListener('updateFailed', (error) => {
|
|
167
|
+
console.error('Update failed:', error.message);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
NativeUpdate.addListener('updateInstalled', (bundle) => {
|
|
171
|
+
console.log('Update installed:', bundle.version);
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Update Channels
|
|
176
|
+
|
|
177
|
+
| Channel | Purpose | Auto-Update | Check Interval |
|
|
178
|
+
|---------|---------|-------------|----------------|
|
|
179
|
+
| `development` | Internal testing | Yes | 1 minute |
|
|
180
|
+
| `staging` | QA/Beta testing | Configurable | 1 hour |
|
|
181
|
+
| `production` | Live users | No (consent) | Daily |
|
|
182
|
+
|
|
183
|
+
## Backend Requirements
|
|
184
|
+
|
|
185
|
+
Your update server must implement these endpoints:
|
|
186
|
+
|
|
187
|
+
### GET /api/check
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"available": true,
|
|
191
|
+
"version": "1.2.0",
|
|
192
|
+
"url": "https://cdn.example.com/bundles/1.2.0.zip",
|
|
193
|
+
"checksum": "sha256:abc123...",
|
|
194
|
+
"signature": "base64signature...",
|
|
195
|
+
"releaseNotes": "Bug fixes and improvements"
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### GET /api/download/:version
|
|
200
|
+
Returns the bundle zip file.
|
|
201
|
+
|
|
202
|
+
## CLI Tools
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Create a bundle from your build
|
|
206
|
+
npx native-update bundle create ./dist --version 1.2.0 --output ./bundles
|
|
207
|
+
|
|
208
|
+
# Sign a bundle
|
|
209
|
+
npx native-update bundle sign ./bundles/1.2.0.zip --key ./private.key
|
|
210
|
+
|
|
211
|
+
# Verify a bundle
|
|
212
|
+
npx native-update bundle verify ./bundles/1.2.0.zip --key ./public.key
|
|
213
|
+
|
|
214
|
+
# Upload to server
|
|
215
|
+
npx native-update bundle upload ./bundles/1.2.0.zip --server https://api.example.com
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Platform-Specific Setup
|
|
219
|
+
|
|
220
|
+
### Android
|
|
221
|
+
|
|
222
|
+
Add to `android/app/build.gradle`:
|
|
223
|
+
```gradle
|
|
224
|
+
dependencies {
|
|
225
|
+
implementation 'com.google.android.play:core:1.10.3'
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### iOS
|
|
230
|
+
|
|
231
|
+
No additional setup required. Uses native APIs.
|
|
232
|
+
|
|
233
|
+
### Web (Limited Support)
|
|
234
|
+
|
|
235
|
+
Web platform supports checking for updates only. Actual OTA updates require native platforms.
|
|
236
|
+
|
|
237
|
+
## Security Best Practices
|
|
238
|
+
|
|
239
|
+
1. **Always use HTTPS** for update URLs
|
|
240
|
+
2. **Enable signature verification** with RSA/ECDSA keys
|
|
241
|
+
3. **Use checksums** to verify bundle integrity
|
|
242
|
+
4. **Test rollback** scenarios before production
|
|
243
|
+
5. **Implement `notifyAppReady()`** to prevent auto-rollback on stable updates
|
|
244
|
+
|
|
245
|
+
## Common Patterns
|
|
246
|
+
|
|
247
|
+
### Check on App Start
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { App } from '@capacitor/app';
|
|
251
|
+
import { NativeUpdate } from 'native-update';
|
|
252
|
+
|
|
253
|
+
App.addListener('appStateChange', async ({ isActive }) => {
|
|
254
|
+
if (isActive) {
|
|
255
|
+
const result = await NativeUpdate.sync({ silent: true });
|
|
256
|
+
if (result.updateAvailable && result.updateReady) {
|
|
257
|
+
// Show user prompt to reload
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Review After Positive Action
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
async function handlePurchaseComplete() {
|
|
267
|
+
// After successful purchase
|
|
268
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
269
|
+
if (canRequest.eligible) {
|
|
270
|
+
await NativeUpdate.requestReview();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Troubleshooting
|
|
276
|
+
|
|
277
|
+
| Issue | Solution |
|
|
278
|
+
|-------|----------|
|
|
279
|
+
| Update not applying | Call `notifyAppReady()` after successful update |
|
|
280
|
+
| Rollback on restart | Previous update crashed; check error logs |
|
|
281
|
+
| Download fails | Verify network, check server response format |
|
|
282
|
+
| Signature invalid | Regenerate keys, re-sign bundle |
|
|
283
|
+
|
|
284
|
+
## Links
|
|
285
|
+
|
|
286
|
+
- [Full Documentation](./docs/)
|
|
287
|
+
- [API Reference](./docs/api/)
|
|
288
|
+
- [Example Apps](./example-apps/)
|
|
289
|
+
- [CLI Reference](./docs/cli-reference.md)
|
|
290
|
+
- [Security Guide](./docs/guides/security-best-practices.md)
|
package/Readme.md
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
## 📚 Documentation
|
|
17
17
|
|
|
18
|
+
- **[AI Integration Guide](./AI-INTEGRATION-GUIDE.md)** - Quick reference for AI development agents (Claude, Cursor, Copilot)
|
|
19
|
+
|
|
18
20
|
### Getting Started
|
|
19
21
|
|
|
20
22
|
- **[Installation Guide](./docs/getting-started/installation.md)** - Step-by-step installation instructions
|
|
@@ -191,9 +191,6 @@ class AppUpdatePlugin(
|
|
|
191
191
|
// Emit state change event
|
|
192
192
|
val eventData = JSObject()
|
|
193
193
|
eventData.put("status", getInstallStatusString(state.installStatus()))
|
|
194
|
-
if (state.installError() != 0) {
|
|
195
|
-
eventData.put("installErrorCode", state.installError())
|
|
196
|
-
}
|
|
197
194
|
eventListener?.invoke("appUpdateStateChanged", eventData)
|
|
198
195
|
|
|
199
196
|
// Emit progress event for downloads
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"systemParams": "linux-x64-137",
|
|
3
|
+
"modulesFolders": [
|
|
4
|
+
"node_modules"
|
|
5
|
+
],
|
|
6
|
+
"flags": [],
|
|
7
|
+
"linkedModules": [],
|
|
8
|
+
"topLevelPatterns": [
|
|
9
|
+
"commander@^11.0.0"
|
|
10
|
+
],
|
|
11
|
+
"lockfileEntries": {
|
|
12
|
+
"commander@^11.0.0": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
|
|
13
|
+
},
|
|
14
|
+
"files": [],
|
|
15
|
+
"artifacts": {}
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
(The MIT License)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|