native-update 1.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 (184) hide show
  1. package/CapacitorNativeUpdate.podspec +18 -0
  2. package/LICENSE +21 -0
  3. package/Readme.md +451 -0
  4. package/android/build.gradle +92 -0
  5. package/android/gradle/wrapper/gradle-wrapper.properties +8 -0
  6. package/android/gradle.properties +17 -0
  7. package/android/proguard-rules.pro +29 -0
  8. package/android/settings.gradle +2 -0
  9. package/android/src/main/AndroidManifest.xml +34 -0
  10. package/android/src/main/java/com/aoneahsan/nativeupdate/AppReviewPlugin.kt +153 -0
  11. package/android/src/main/java/com/aoneahsan/nativeupdate/AppUpdatePlugin.kt +275 -0
  12. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +390 -0
  13. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateManager.kt +46 -0
  14. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdatePlugin.kt +333 -0
  15. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateWorker.kt +251 -0
  16. package/android/src/main/java/com/aoneahsan/nativeupdate/CapacitorNativeUpdatePlugin.kt +265 -0
  17. package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +526 -0
  18. package/android/src/main/java/com/aoneahsan/nativeupdate/NotificationActionReceiver.kt +99 -0
  19. package/android/src/main/java/com/aoneahsan/nativeupdate/SecurityManager.kt +249 -0
  20. package/dist/esm/__tests__/bundle-manager.test.d.ts +1 -0
  21. package/dist/esm/__tests__/bundle-manager.test.js +123 -0
  22. package/dist/esm/__tests__/bundle-manager.test.js.map +1 -0
  23. package/dist/esm/__tests__/config.test.d.ts +1 -0
  24. package/dist/esm/__tests__/config.test.js +69 -0
  25. package/dist/esm/__tests__/config.test.js.map +1 -0
  26. package/dist/esm/__tests__/integration.test.d.ts +1 -0
  27. package/dist/esm/__tests__/integration.test.js +78 -0
  28. package/dist/esm/__tests__/integration.test.js.map +1 -0
  29. package/dist/esm/__tests__/security.test.d.ts +1 -0
  30. package/dist/esm/__tests__/security.test.js +54 -0
  31. package/dist/esm/__tests__/security.test.js.map +1 -0
  32. package/dist/esm/__tests__/version-manager.test.d.ts +1 -0
  33. package/dist/esm/__tests__/version-manager.test.js +45 -0
  34. package/dist/esm/__tests__/version-manager.test.js.map +1 -0
  35. package/dist/esm/app-review/app-review-manager.d.ts +24 -0
  36. package/dist/esm/app-review/app-review-manager.js +195 -0
  37. package/dist/esm/app-review/app-review-manager.js.map +1 -0
  38. package/dist/esm/app-review/index.d.ts +5 -0
  39. package/dist/esm/app-review/index.js +6 -0
  40. package/dist/esm/app-review/index.js.map +1 -0
  41. package/dist/esm/app-review/platform-review-handler.d.ts +20 -0
  42. package/dist/esm/app-review/platform-review-handler.js +138 -0
  43. package/dist/esm/app-review/platform-review-handler.js.map +1 -0
  44. package/dist/esm/app-review/review-conditions-checker.d.ts +22 -0
  45. package/dist/esm/app-review/review-conditions-checker.js +155 -0
  46. package/dist/esm/app-review/review-conditions-checker.js.map +1 -0
  47. package/dist/esm/app-review/review-rate-limiter.d.ts +23 -0
  48. package/dist/esm/app-review/review-rate-limiter.js +164 -0
  49. package/dist/esm/app-review/review-rate-limiter.js.map +1 -0
  50. package/dist/esm/app-review/types.d.ts +41 -0
  51. package/dist/esm/app-review/types.js +2 -0
  52. package/dist/esm/app-review/types.js.map +1 -0
  53. package/dist/esm/app-update/app-update-checker.d.ts +13 -0
  54. package/dist/esm/app-update/app-update-checker.js +104 -0
  55. package/dist/esm/app-update/app-update-checker.js.map +1 -0
  56. package/dist/esm/app-update/app-update-installer.d.ts +19 -0
  57. package/dist/esm/app-update/app-update-installer.js +123 -0
  58. package/dist/esm/app-update/app-update-installer.js.map +1 -0
  59. package/dist/esm/app-update/app-update-manager.d.ts +28 -0
  60. package/dist/esm/app-update/app-update-manager.js +199 -0
  61. package/dist/esm/app-update/app-update-manager.js.map +1 -0
  62. package/dist/esm/app-update/app-update-notifier.d.ts +14 -0
  63. package/dist/esm/app-update/app-update-notifier.js +100 -0
  64. package/dist/esm/app-update/app-update-notifier.js.map +1 -0
  65. package/dist/esm/app-update/index.d.ts +6 -0
  66. package/dist/esm/app-update/index.js +7 -0
  67. package/dist/esm/app-update/index.js.map +1 -0
  68. package/dist/esm/app-update/platform-app-update.d.ts +19 -0
  69. package/dist/esm/app-update/platform-app-update.js +129 -0
  70. package/dist/esm/app-update/platform-app-update.js.map +1 -0
  71. package/dist/esm/app-update/types.d.ts +58 -0
  72. package/dist/esm/app-update/types.js +12 -0
  73. package/dist/esm/app-update/types.js.map +1 -0
  74. package/dist/esm/background-update/background-scheduler.d.ts +17 -0
  75. package/dist/esm/background-update/background-scheduler.js +195 -0
  76. package/dist/esm/background-update/background-scheduler.js.map +1 -0
  77. package/dist/esm/background-update/index.d.ts +3 -0
  78. package/dist/esm/background-update/index.js +3 -0
  79. package/dist/esm/background-update/index.js.map +1 -0
  80. package/dist/esm/background-update/notification-manager.d.ts +29 -0
  81. package/dist/esm/background-update/notification-manager.js +89 -0
  82. package/dist/esm/background-update/notification-manager.js.map +1 -0
  83. package/dist/esm/core/analytics.d.ts +70 -0
  84. package/dist/esm/core/analytics.js +137 -0
  85. package/dist/esm/core/analytics.js.map +1 -0
  86. package/dist/esm/core/cache-manager.d.ts +72 -0
  87. package/dist/esm/core/cache-manager.js +275 -0
  88. package/dist/esm/core/cache-manager.js.map +1 -0
  89. package/dist/esm/core/config.d.ts +48 -0
  90. package/dist/esm/core/config.js +83 -0
  91. package/dist/esm/core/config.js.map +1 -0
  92. package/dist/esm/core/errors.d.ts +51 -0
  93. package/dist/esm/core/errors.js +80 -0
  94. package/dist/esm/core/errors.js.map +1 -0
  95. package/dist/esm/core/logger.d.ts +21 -0
  96. package/dist/esm/core/logger.js +109 -0
  97. package/dist/esm/core/logger.js.map +1 -0
  98. package/dist/esm/core/performance.d.ts +53 -0
  99. package/dist/esm/core/performance.js +140 -0
  100. package/dist/esm/core/performance.js.map +1 -0
  101. package/dist/esm/core/plugin-manager.d.ts +66 -0
  102. package/dist/esm/core/plugin-manager.js +148 -0
  103. package/dist/esm/core/plugin-manager.js.map +1 -0
  104. package/dist/esm/core/security.d.ts +93 -0
  105. package/dist/esm/core/security.js +315 -0
  106. package/dist/esm/core/security.js.map +1 -0
  107. package/dist/esm/definitions.d.ts +639 -0
  108. package/dist/esm/definitions.js +103 -0
  109. package/dist/esm/definitions.js.map +1 -0
  110. package/dist/esm/index.d.ts +12 -0
  111. package/dist/esm/index.js +16 -0
  112. package/dist/esm/index.js.map +1 -0
  113. package/dist/esm/live-update/bundle-manager.d.ts +94 -0
  114. package/dist/esm/live-update/bundle-manager.js +310 -0
  115. package/dist/esm/live-update/bundle-manager.js.map +1 -0
  116. package/dist/esm/live-update/certificate-pinning.d.ts +38 -0
  117. package/dist/esm/live-update/certificate-pinning.js +78 -0
  118. package/dist/esm/live-update/certificate-pinning.js.map +1 -0
  119. package/dist/esm/live-update/download-manager.d.ts +67 -0
  120. package/dist/esm/live-update/download-manager.js +319 -0
  121. package/dist/esm/live-update/download-manager.js.map +1 -0
  122. package/dist/esm/live-update/update-manager.d.ts +52 -0
  123. package/dist/esm/live-update/update-manager.js +294 -0
  124. package/dist/esm/live-update/update-manager.js.map +1 -0
  125. package/dist/esm/live-update/version-manager.d.ts +84 -0
  126. package/dist/esm/live-update/version-manager.js +335 -0
  127. package/dist/esm/live-update/version-manager.js.map +1 -0
  128. package/dist/esm/plugin.d.ts +6 -0
  129. package/dist/esm/plugin.js +283 -0
  130. package/dist/esm/plugin.js.map +1 -0
  131. package/dist/esm/security/crypto.d.ts +25 -0
  132. package/dist/esm/security/crypto.js +70 -0
  133. package/dist/esm/security/crypto.js.map +1 -0
  134. package/dist/esm/security/validator.d.ts +60 -0
  135. package/dist/esm/security/validator.js +143 -0
  136. package/dist/esm/security/validator.js.map +1 -0
  137. package/dist/esm/web.d.ts +74 -0
  138. package/dist/esm/web.js +595 -0
  139. package/dist/esm/web.js.map +1 -0
  140. package/dist/plugin.cjs.js +2 -0
  141. package/dist/plugin.cjs.js.map +1 -0
  142. package/dist/plugin.esm.js +2 -0
  143. package/dist/plugin.esm.js.map +1 -0
  144. package/dist/plugin.js +3 -0
  145. package/dist/plugin.js.map +1 -0
  146. package/docs/APP_REVIEW_GUIDE.md +768 -0
  147. package/docs/BUNDLE_SIGNING.md +264 -0
  148. package/docs/LIVE_UPDATES_GUIDE.md +650 -0
  149. package/docs/MIGRATION.md +192 -0
  150. package/docs/NATIVE_UPDATES_GUIDE.md +694 -0
  151. package/docs/QUICK_START.md +606 -0
  152. package/docs/README.md +111 -0
  153. package/docs/REMAINING_FEATURES.md +139 -0
  154. package/docs/api/app-review-api.md +259 -0
  155. package/docs/api/app-update-api.md +238 -0
  156. package/docs/api/events-api.md +451 -0
  157. package/docs/api/live-update-api.md +265 -0
  158. package/docs/background-updates.md +392 -0
  159. package/docs/examples/advanced-scenarios.md +410 -0
  160. package/docs/examples/basic-usage.md +185 -0
  161. package/docs/features/app-reviews.md +975 -0
  162. package/docs/features/app-updates.md +785 -0
  163. package/docs/features/live-updates.md +633 -0
  164. package/docs/getting-started/configuration.md +468 -0
  165. package/docs/getting-started/installation.md +209 -0
  166. package/docs/getting-started/quick-start.md +379 -0
  167. package/docs/guides/deployment-guide.md +333 -0
  168. package/docs/guides/migration-from-codepush.md +142 -0
  169. package/docs/guides/security-best-practices.md +1057 -0
  170. package/docs/guides/testing-guide.md +373 -0
  171. package/docs/production-readiness.md +478 -0
  172. package/docs/security/certificate-pinning.md +122 -0
  173. package/docs/server-requirements.md +147 -0
  174. package/ios/Plugin/AppReview/AppReviewPlugin.swift +158 -0
  175. package/ios/Plugin/AppUpdate/AppUpdatePlugin.swift +234 -0
  176. package/ios/Plugin/BackgroundUpdate/BackgroundNotificationManager.swift +329 -0
  177. package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +396 -0
  178. package/ios/Plugin/CapacitorNativeUpdatePlugin.m +45 -0
  179. package/ios/Plugin/CapacitorNativeUpdatePlugin.swift +190 -0
  180. package/ios/Plugin/Info.plist +43 -0
  181. package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +689 -0
  182. package/ios/Plugin/LiveUpdate/WebViewConfiguration.swift +45 -0
  183. package/ios/Plugin/Security/SecurityManager.swift +289 -0
  184. package/package.json +90 -0
@@ -0,0 +1,633 @@
1
+ # Live Updates (OTA)
2
+
3
+ > **⚠️ Backend Infrastructure Required**
4
+ >
5
+ > Live Updates require a complete backend infrastructure that you must build:
6
+ > - **Update Server**: Host and serve update bundles
7
+ > - **Bundle Generation**: CI/CD pipeline to create and sign bundles
8
+ > - **Version Management**: Track versions, channels, and rollbacks
9
+ > - **Security Infrastructure**: Implement signing and verification
10
+ > - **CDN/Storage**: Distribute bundles globally
11
+ >
12
+ > This plugin provides the client-side implementation only. Without the backend, Live Updates will not function.
13
+
14
+ Live Updates, also known as Over-The-Air (OTA) updates, allow you to deploy JavaScript, HTML, and CSS changes to your app instantly without going through app store review processes. This feature is perfect for bug fixes, content updates, and minor feature additions.
15
+
16
+ ## How Live Updates Work
17
+
18
+ 1. **Bundle Creation**: Your web assets are packaged into a bundle with metadata
19
+ 2. **Version Check**: The app checks for new versions on your update server
20
+ 3. **Download**: New bundles are downloaded in the background
21
+ 4. **Verification**: Checksums and signatures are validated for security
22
+ 5. **Installation**: The update is applied based on your configured strategy
23
+ 6. **Activation**: The app reloads with the new bundle
24
+
25
+ ## Key Features
26
+
27
+ ### 🚀 Instant Deployment
28
+
29
+ - Deploy updates within minutes
30
+ - No app store review delays
31
+ - Fix critical bugs immediately
32
+
33
+ ### 🔒 Secure Updates
34
+
35
+ - Cryptographic signature verification
36
+ - Checksum validation
37
+ - HTTPS enforcement
38
+ - Certificate pinning support
39
+
40
+ ### 📦 Smart Bundle Management
41
+
42
+ - Automatic cleanup of old bundles
43
+ - Storage usage optimization
44
+ - Version history tracking
45
+ - Rollback capabilities
46
+
47
+ ### 🎯 Targeted Deployments
48
+
49
+ - Multiple update channels
50
+ - Gradual rollouts
51
+ - A/B testing support
52
+ - User segmentation
53
+
54
+ ## Implementation Guide
55
+
56
+ ### Basic Implementation
57
+
58
+ ```typescript
59
+ // 1. Configure live updates
60
+ await CapacitorNativeUpdate.configure({
61
+ liveUpdate: {
62
+ appId: 'com.myapp.example',
63
+ serverUrl: 'https://updates.myserver.com',
64
+ autoUpdate: true,
65
+ },
66
+ });
67
+
68
+ // 2. Sync updates (automatic with autoUpdate: true)
69
+ const result = await CapacitorNativeUpdate.LiveUpdate.sync();
70
+
71
+ // 3. Handle the result
72
+ switch (result.status) {
73
+ case 'UPDATE_INSTALLED':
74
+ console.log('Update installed:', result.bundle.version);
75
+ break;
76
+ case 'UP_TO_DATE':
77
+ console.log('App is up to date');
78
+ break;
79
+ }
80
+ ```
81
+
82
+ ### Advanced Implementation
83
+
84
+ ```typescript
85
+ class LiveUpdateManager {
86
+ private updateAvailable = false;
87
+
88
+ async initialize() {
89
+ // Configure with advanced options
90
+ await CapacitorNativeUpdate.configure({
91
+ liveUpdate: {
92
+ appId: 'com.myapp.example',
93
+ serverUrl: 'https://updates.myserver.com',
94
+ channel: this.getUpdateChannel(),
95
+ updateStrategy: 'BACKGROUND',
96
+ publicKey: this.getPublicKey(),
97
+ requireSignature: true,
98
+ checksumAlgorithm: 'SHA-512',
99
+ },
100
+ });
101
+
102
+ // Set up listeners
103
+ this.setupUpdateListeners();
104
+
105
+ // Initial check
106
+ await this.checkForUpdates();
107
+ }
108
+
109
+ private setupUpdateListeners() {
110
+ // Download progress
111
+ CapacitorNativeUpdate.LiveUpdate.addListener(
112
+ 'downloadProgress',
113
+ (progress) => {
114
+ this.updateDownloadProgress(progress.percent);
115
+ }
116
+ );
117
+
118
+ // State changes
119
+ CapacitorNativeUpdate.LiveUpdate.addListener(
120
+ 'updateStateChanged',
121
+ (event) => {
122
+ this.handleStateChange(event);
123
+ }
124
+ );
125
+ }
126
+
127
+ async checkForUpdates() {
128
+ try {
129
+ const latest = await CapacitorNativeUpdate.LiveUpdate.getLatest();
130
+ const current = await CapacitorNativeUpdate.LiveUpdate.current();
131
+
132
+ if (this.isNewerVersion(latest.version, current.version)) {
133
+ this.updateAvailable = true;
134
+ this.notifyUpdateAvailable(latest);
135
+ }
136
+ } catch (error) {
137
+ console.error('Update check failed:', error);
138
+ }
139
+ }
140
+
141
+ async downloadUpdate() {
142
+ if (!this.updateAvailable) return;
143
+
144
+ try {
145
+ const bundle = await CapacitorNativeUpdate.LiveUpdate.download({
146
+ version: 'latest',
147
+ onProgress: (progress) => {
148
+ console.log(`Download: ${progress.percent}%`);
149
+ },
150
+ });
151
+
152
+ // Validate the bundle
153
+ const validation = await CapacitorNativeUpdate.LiveUpdate.validateUpdate({
154
+ bundleId: bundle.bundleId,
155
+ });
156
+
157
+ if (validation.valid) {
158
+ await this.installUpdate(bundle);
159
+ } else {
160
+ throw new Error('Bundle validation failed');
161
+ }
162
+ } catch (error) {
163
+ this.handleUpdateError(error);
164
+ }
165
+ }
166
+
167
+ async installUpdate(bundle: BundleInfo) {
168
+ // Set the bundle as active
169
+ await CapacitorNativeUpdate.LiveUpdate.set(bundle);
170
+
171
+ // Notify app is ready (important for rollback mechanism)
172
+ await CapacitorNativeUpdate.LiveUpdate.notifyAppReady();
173
+
174
+ // Schedule reload based on user preference
175
+ this.scheduleReload();
176
+ }
177
+
178
+ private scheduleReload() {
179
+ // Option 1: Immediate reload
180
+ // await CapacitorNativeUpdate.LiveUpdate.reload();
181
+
182
+ // Option 2: Reload on next app resume
183
+ App.addListener('appStateChange', ({ isActive }) => {
184
+ if (isActive) {
185
+ CapacitorNativeUpdate.LiveUpdate.reload();
186
+ }
187
+ });
188
+
189
+ // Option 3: User-triggered reload
190
+ this.showUpdateReadyDialog();
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## Update Strategies
196
+
197
+ ### Immediate Updates
198
+
199
+ Updates are downloaded and applied immediately when detected.
200
+
201
+ ```typescript
202
+ {
203
+ updateStrategy: 'IMMEDIATE',
204
+ mandatoryInstallMode: 'IMMEDIATE'
205
+ }
206
+ ```
207
+
208
+ **Use when:**
209
+
210
+ - Critical bug fixes
211
+ - Security patches
212
+ - Time-sensitive content
213
+
214
+ ### Background Updates
215
+
216
+ Updates download in the background and install based on install mode.
217
+
218
+ ```typescript
219
+ {
220
+ updateStrategy: 'BACKGROUND',
221
+ mandatoryInstallMode: 'ON_NEXT_RESTART',
222
+ optionalInstallMode: 'ON_NEXT_RESUME'
223
+ }
224
+ ```
225
+
226
+ **Use when:**
227
+
228
+ - Regular feature updates
229
+ - Non-critical improvements
230
+ - Large bundle sizes
231
+
232
+ ### Manual Updates
233
+
234
+ Full control over download and installation timing.
235
+
236
+ ```typescript
237
+ {
238
+ updateStrategy: 'MANUAL',
239
+ autoUpdate: false
240
+ }
241
+ ```
242
+
243
+ **Use when:**
244
+
245
+ - User-initiated updates
246
+ - Specific update windows
247
+ - Custom update UI
248
+
249
+ ## Version Management
250
+
251
+ ### Semantic Versioning
252
+
253
+ The plugin uses semantic versioning (MAJOR.MINOR.PATCH):
254
+
255
+ ```typescript
256
+ // Version comparison
257
+ const current = await CapacitorNativeUpdate.LiveUpdate.current();
258
+ console.log(current.version); // "1.2.3"
259
+
260
+ // Check if update is major/minor/patch
261
+ function getUpdateType(oldVersion: string, newVersion: string) {
262
+ const [oldMajor, oldMinor, oldPatch] = oldVersion.split('.').map(Number);
263
+ const [newMajor, newMinor, newPatch] = newVersion.split('.').map(Number);
264
+
265
+ if (newMajor > oldMajor) return 'major';
266
+ if (newMinor > oldMinor) return 'minor';
267
+ if (newPatch > oldPatch) return 'patch';
268
+ return 'none';
269
+ }
270
+ ```
271
+
272
+ ### Bundle History
273
+
274
+ ```typescript
275
+ // List all downloaded bundles
276
+ const bundles = await CapacitorNativeUpdate.LiveUpdate.list();
277
+
278
+ bundles.forEach((bundle) => {
279
+ console.log(`Version: ${bundle.version}`);
280
+ console.log(`Downloaded: ${new Date(bundle.downloadTime)}`);
281
+ console.log(`Size: ${bundle.size} bytes`);
282
+ console.log(`Status: ${bundle.status}`);
283
+ });
284
+
285
+ // Clean up old bundles
286
+ await CapacitorNativeUpdate.LiveUpdate.delete({
287
+ keepNewest: 3, // Keep only 3 most recent bundles
288
+ });
289
+ ```
290
+
291
+ ## Rollback Mechanism
292
+
293
+ The plugin includes automatic rollback for failed updates.
294
+
295
+ ### Automatic Rollback
296
+
297
+ ```typescript
298
+ // Mark app as ready after successful startup
299
+ async function onAppReady() {
300
+ try {
301
+ // Verify app is working correctly
302
+ await performHealthCheck();
303
+
304
+ // Notify that app started successfully
305
+ await CapacitorNativeUpdate.LiveUpdate.notifyAppReady();
306
+ } catch (error) {
307
+ // Don't call notifyAppReady() - automatic rollback will occur
308
+ console.error('App startup failed:', error);
309
+ }
310
+ }
311
+ ```
312
+
313
+ ### Manual Rollback
314
+
315
+ ```typescript
316
+ // Reset to original bundle
317
+ await CapacitorNativeUpdate.LiveUpdate.reset();
318
+
319
+ // Or rollback to previous version
320
+ const bundles = await CapacitorNativeUpdate.LiveUpdate.list();
321
+ const previousBundle = bundles[bundles.length - 2];
322
+ if (previousBundle) {
323
+ await CapacitorNativeUpdate.LiveUpdate.set(previousBundle);
324
+ await CapacitorNativeUpdate.LiveUpdate.reload();
325
+ }
326
+ ```
327
+
328
+ ## Update Channels
329
+
330
+ Use channels to manage different release tracks.
331
+
332
+ ### Channel Configuration
333
+
334
+ ```typescript
335
+ // Set channel based on user preference
336
+ const channel = getUserPreference('updateChannel') || 'production';
337
+ await CapacitorNativeUpdate.LiveUpdate.setChannel(channel);
338
+
339
+ // Available channels examples:
340
+ // - 'production': Stable releases
341
+ // - 'beta': Beta testing
342
+ // - 'alpha': Early access
343
+ // - 'development': Dev builds
344
+ // - 'staging': Pre-production
345
+ ```
346
+
347
+ ### Channel-Based Features
348
+
349
+ ```typescript
350
+ // Enable features based on channel
351
+ async function getFeatureFlags() {
352
+ const bundle = await CapacitorNativeUpdate.LiveUpdate.current();
353
+
354
+ switch (bundle.metadata?.channel) {
355
+ case 'alpha':
356
+ return { experimentalFeatures: true, debugMode: true };
357
+ case 'beta':
358
+ return { experimentalFeatures: true, debugMode: false };
359
+ default:
360
+ return { experimentalFeatures: false, debugMode: false };
361
+ }
362
+ }
363
+ ```
364
+
365
+ ## Performance Optimization
366
+
367
+ ### Bundle Size Optimization
368
+
369
+ 1. **Minimize bundle size**:
370
+
371
+ ```bash
372
+ # Use production builds
373
+ npm run build -- --mode production
374
+
375
+ # Enable compression
376
+ gzip -9 bundle.js
377
+ ```
378
+
379
+ 2. **Implement delta updates** (coming soon):
380
+ ```typescript
381
+ // Future API
382
+ const delta = await CapacitorNativeUpdate.LiveUpdate.downloadDelta({
383
+ fromVersion: current.version,
384
+ toVersion: latest.version,
385
+ });
386
+ ```
387
+
388
+ ### Download Optimization
389
+
390
+ ```typescript
391
+ // Configure optimal download settings
392
+ {
393
+ liveUpdate: {
394
+ // Download only on WiFi
395
+ downloadOnWifiOnly: true,
396
+
397
+ // Limit concurrent downloads
398
+ maxConcurrentDownloads: 1,
399
+
400
+ // Set reasonable timeout
401
+ timeout: 30000,
402
+
403
+ // Enable resume capability
404
+ resumableDownloads: true
405
+ }
406
+ }
407
+ ```
408
+
409
+ ### Storage Management
410
+
411
+ ```typescript
412
+ // Monitor storage usage
413
+ const storage = await CapacitorNativeUpdate.LiveUpdate.getStorageInfo();
414
+ console.log(`Used: ${storage.usedBytes} / ${storage.totalBytes}`);
415
+
416
+ // Clean up when needed
417
+ if (storage.usedBytes > storage.totalBytes * 0.8) {
418
+ await CapacitorNativeUpdate.LiveUpdate.delete({
419
+ olderThan: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days
420
+ });
421
+ }
422
+ ```
423
+
424
+ ## Error Handling
425
+
426
+ ### Common Errors and Solutions
427
+
428
+ ```typescript
429
+ try {
430
+ await CapacitorNativeUpdate.LiveUpdate.sync();
431
+ } catch (error) {
432
+ switch (error.code) {
433
+ case 'NETWORK_ERROR':
434
+ // No internet connection
435
+ showOfflineMessage();
436
+ break;
437
+
438
+ case 'SERVER_ERROR':
439
+ // Update server is down
440
+ scheduleRetry();
441
+ break;
442
+
443
+ case 'CHECKSUM_ERROR':
444
+ // Bundle corrupted
445
+ await CapacitorNativeUpdate.LiveUpdate.delete({
446
+ bundleId: error.bundleId,
447
+ });
448
+ break;
449
+
450
+ case 'SIGNATURE_ERROR':
451
+ // Security validation failed
452
+ logSecurityEvent(error);
453
+ break;
454
+
455
+ case 'STORAGE_ERROR':
456
+ // Not enough space
457
+ await cleanupStorage();
458
+ break;
459
+
460
+ case 'VERSION_MISMATCH':
461
+ // Incompatible update
462
+ promptForAppUpdate();
463
+ break;
464
+ }
465
+ }
466
+ ```
467
+
468
+ ### Retry Logic
469
+
470
+ ```typescript
471
+ class UpdateRetryManager {
472
+ private retryCount = 0;
473
+ private maxRetries = 3;
474
+
475
+ async syncWithRetry() {
476
+ try {
477
+ await CapacitorNativeUpdate.LiveUpdate.sync();
478
+ this.retryCount = 0; // Reset on success
479
+ } catch (error) {
480
+ if (this.shouldRetry(error)) {
481
+ this.retryCount++;
482
+ const delay = this.getRetryDelay();
483
+
484
+ console.log(
485
+ `Retry ${this.retryCount}/${this.maxRetries} in ${delay}ms`
486
+ );
487
+
488
+ setTimeout(() => {
489
+ this.syncWithRetry();
490
+ }, delay);
491
+ } else {
492
+ throw error; // Don't retry
493
+ }
494
+ }
495
+ }
496
+
497
+ private shouldRetry(error: any): boolean {
498
+ return (
499
+ this.retryCount < this.maxRetries &&
500
+ ['NETWORK_ERROR', 'TIMEOUT_ERROR', 'SERVER_ERROR'].includes(error.code)
501
+ );
502
+ }
503
+
504
+ private getRetryDelay(): number {
505
+ // Exponential backoff
506
+ return Math.min(1000 * Math.pow(2, this.retryCount), 30000);
507
+ }
508
+ }
509
+ ```
510
+
511
+ ## Testing Live Updates
512
+
513
+ ### Development Testing
514
+
515
+ ```typescript
516
+ // Enable development mode
517
+ const devConfig = {
518
+ liveUpdate: {
519
+ appId: 'com.myapp.dev',
520
+ serverUrl: 'http://localhost:3000',
521
+ channel: 'development',
522
+ allowEmulator: true,
523
+ requireSignature: false, // Disable in dev
524
+ autoUpdate: false, // Manual control
525
+ },
526
+ };
527
+
528
+ // Force update check
529
+ await CapacitorNativeUpdate.LiveUpdate.sync({ forceCheck: true });
530
+
531
+ // Simulate different scenarios
532
+ await testUpdateScenarios();
533
+ ```
534
+
535
+ ### Update Server Testing
536
+
537
+ Set up a local update server for testing:
538
+
539
+ ```bash
540
+ # See server-example directory
541
+ cd server-example
542
+ npm install
543
+ npm run dev
544
+ ```
545
+
546
+ ### Test Scenarios
547
+
548
+ 1. **Successful update**
549
+ 2. **Network interruption**
550
+ 3. **Corrupted bundle**
551
+ 4. **Version rollback**
552
+ 5. **Storage full**
553
+ 6. **Signature mismatch**
554
+
555
+ ## Best Practices
556
+
557
+ ### 1. Progressive Rollout
558
+
559
+ ```typescript
560
+ // Roll out to percentage of users
561
+ function shouldReceiveUpdate(userId: string, percentage: number): boolean {
562
+ const hash = hashCode(userId);
563
+ return hash % 100 < percentage;
564
+ }
565
+
566
+ if (shouldReceiveUpdate(user.id, 10)) {
567
+ // 10% rollout
568
+ await CapacitorNativeUpdate.LiveUpdate.setChannel('beta');
569
+ }
570
+ ```
571
+
572
+ ### 2. Update Notifications
573
+
574
+ ```typescript
575
+ // Notify users about updates
576
+ CapacitorNativeUpdate.LiveUpdate.addListener('updateStateChanged', (event) => {
577
+ if (event.status === 'READY') {
578
+ showNotification({
579
+ title: 'Update Ready',
580
+ body: 'A new version is available. Restart to apply.',
581
+ actions: [
582
+ { id: 'restart', title: 'Restart Now' },
583
+ { id: 'later', title: 'Later' },
584
+ ],
585
+ });
586
+ }
587
+ });
588
+ ```
589
+
590
+ ### 3. Monitoring
591
+
592
+ ```typescript
593
+ // Track update metrics
594
+ async function trackUpdateMetrics(result: SyncResult) {
595
+ const metrics = {
596
+ event: 'live_update',
597
+ status: result.status,
598
+ version: result.bundle?.version,
599
+ downloadTime: result.downloadTime,
600
+ installTime: result.installTime,
601
+ bundleSize: result.bundle?.size,
602
+ };
603
+
604
+ await analytics.track(metrics);
605
+ }
606
+ ```
607
+
608
+ ### 4. Fallback Strategy
609
+
610
+ ```typescript
611
+ // Implement fallback for critical features
612
+ async function loadFeature(featureName: string) {
613
+ try {
614
+ // Try loading from update bundle
615
+ return await import(`./features/${featureName}`);
616
+ } catch (error) {
617
+ // Fall back to shipped version
618
+ console.warn(`Loading fallback for ${featureName}`);
619
+ return await import(`./features-fallback/${featureName}`);
620
+ }
621
+ }
622
+ ```
623
+
624
+ ## Next Steps
625
+
626
+ - Set up your [Update Server](../examples/server-setup.md)
627
+ - Implement [Security Best Practices](../guides/security-best-practices.md)
628
+ - Configure [App Updates](./app-updates.md) for native changes
629
+ - Explore [API Reference](../api/live-update-api.md)
630
+
631
+ ---
632
+
633
+ Made with ❤️ by Ahsan Mahmood