cordova-plugin-hot-updates 2.1.0 → 2.1.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/README.md CHANGED
@@ -1,487 +1,459 @@
1
- # Cordova Hot Updates Plugin
1
+ # Cordova Hot Updates Plugin v2.1.2
2
2
 
3
- 🔥 **Automatic over-the-air (OTA) hot updates for Cordova applications using WebView Reload approach**
3
+ Frontend-controlled manual hot updates for Cordova iOS applications using WebView Reload approach.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/cordova-plugin-hot-updates.svg)](https://badge.fury.io/js/cordova-plugin-hot-updates)
6
6
  [![License](https://img.shields.io/badge/License-Custom%20Non--Commercial-blue.svg)](#license)
7
7
 
8
- This plugin enables seamless web content updates for your Cordova iOS applications without requiring App Store approval. Updates are downloaded in the background and applied automatically on the next app launch.
8
+ This plugin enables **manual, JavaScript-controlled** web content updates for your Cordova iOS applications without requiring App Store approval. Your frontend code decides when to check, download, and install updates.
9
9
 
10
- ## 🚀 Key Features
10
+ ## Features
11
11
 
12
- - **🔄 Automatic Background Updates**: Continuously checks for and downloads updates
13
- - **⚡ Instant Application**: WebView Reload approach for immediate effect
14
- - **📦 Semantic Versioning**: Smart version comparison and compatibility checks
15
- - **🛡️ Rollback Support**: Automatic fallback on corrupted updates
16
- - **⚙️ Configurable**: Customizable server URLs and check intervals
17
- - **🎯 Zero Configuration**: Works out of the box with sensible defaults
12
+ - **Frontend Control**: JavaScript decides when to update (no automatic background checking)
13
+ - **Two-Step Updates**: Separate download (`getUpdate`) and install (`forceUpdate`) for better UX
14
+ - **Auto-Install on Launch**: If user ignores update prompt, it installs on next app launch
15
+ - **Canary System**: Automatic rollback if update fails to load (20-second timeout)
16
+ - **IgnoreList**: Tracks problematic versions (information only, does NOT block installation)
17
+ - **Instant Effect**: WebView Reload approach - no app restart needed
18
+ - **Cache Management**: Clears WKWebView cache (disk, memory, Service Worker) before reload
18
19
 
19
- ## 📋 Table of Contents
20
-
21
- - [Installation](#-installation)
22
- - [Quick Start](#-quick-start)
23
- - [Configuration](#-configuration)
24
- - [API Reference](#-api-reference)
25
- - [Server Implementation](#-server-implementation)
26
- - [How It Works](#-how-it-works)
27
- - [Troubleshooting](#-troubleshooting)
28
- - [Contributing](#-contributing)
29
- - [License](#-license)
30
-
31
- ## 📦 Installation
32
-
33
- ### Standard Installation (Recommended)
20
+ ## Installation
34
21
 
35
22
  ```bash
36
- # Install from npm registry
23
+ # Install from npm
37
24
  cordova plugin add cordova-plugin-hot-updates
38
25
 
39
- # Install CocoaPods dependencies (iOS)
26
+ # Install CocoaPods dependencies (required)
40
27
  cd platforms/ios
41
28
  pod install
42
29
  ```
43
30
 
44
- ### Alternative Installation Methods
31
+ Or install from local directory:
45
32
 
46
33
  ```bash
47
- # Install from GitHub
48
- cordova plugin add https://github.com/vladimirDarksy/Cordova_hot_update.git
49
-
50
- # Install from local path
51
34
  cordova plugin add /path/to/cordova-plugin-hot-updates
35
+ ```
52
36
 
53
- # Install specific version
54
- cordova plugin add cordova-plugin-hot-updates@1.0.0
37
+ Or install from GitHub:
38
+
39
+ ```bash
40
+ cordova plugin add https://github.com/vladimirDarksy/Cordova_hot_update.git
55
41
  ```
56
42
 
57
- ### Installation with pnpm
43
+ **Requirements:**
44
+ - Cordova >= 7.0.0
45
+ - cordova-ios >= 4.4.0
46
+ - iOS >= 11.2
47
+ - CocoaPods (for SSZipArchive dependency)
58
48
 
59
- If your project uses pnpm, you may need additional configuration:
49
+ ## Quick Start
60
50
 
61
- 1. Create or update `.npmrc` in your project root:
51
+ ### 1. Minimal Integration
62
52
 
63
- ```
64
- public-hoist-pattern[]=cordova-plugin-*
65
- shamefully-hoist=true
66
- auto-install-peers=true
53
+ ```javascript
54
+ document.addEventListener('deviceready', function() {
55
+ // CRITICAL: Confirm successful bundle load within 20 seconds
56
+ var currentVersion = localStorage.getItem('app_version') || '1.0.0';
57
+ window.hotUpdate.canary(currentVersion);
58
+
59
+ // Check for updates
60
+ checkForUpdates();
61
+ }, false);
62
+
63
+ function checkForUpdates() {
64
+ fetch('https://your-server.com/api/check-update?version=1.0.0')
65
+ .then(response => response.json())
66
+ .then(data => {
67
+ if (data.hasUpdate) {
68
+ downloadAndInstall(data.downloadUrl, data.version);
69
+ }
70
+ });
71
+ }
72
+
73
+ function downloadAndInstall(url, version) {
74
+ window.hotUpdate.getUpdate({url: url, version: version}, function(error) {
75
+ if (!error) {
76
+ if (confirm('Update available. Install now?')) {
77
+ localStorage.setItem('app_version', version);
78
+ window.hotUpdate.forceUpdate(function(error) {
79
+ // WebView will reload, canary() will be called in deviceready
80
+ });
81
+ }
82
+ // If user declines, update auto-installs on next launch
83
+ }
84
+ });
85
+ }
67
86
  ```
68
87
 
69
- 2. Then install the plugin:
88
+ ## API Reference
70
89
 
71
- ```bash
72
- cordova plugin add cordova-plugin-hot-updates
73
- ```
90
+ All API methods are available via `window.hotUpdate` after the `deviceready` event.
74
91
 
75
- **Note**: Cordova CLI internally uses npm, which can sometimes conflict with pnpm's node_modules structure. The above configuration helps resolve this.
92
+ ### window.hotUpdate.getUpdate(options, callback)
76
93
 
77
- ## 🚀 Quick Start
94
+ Downloads update from server.
78
95
 
79
- ### 1. Configure Your Server URL
96
+ Downloads ZIP from provided URL and saves to two locations:
97
+ - `temp_downloaded_update` (for immediate installation via `forceUpdate()`)
98
+ - `pending_update` (for auto-installation on next app launch)
80
99
 
81
- Add to your `config.xml`:
100
+ If version already downloaded, returns success without re-downloading.
82
101
 
83
- ```xml
84
- <preference name="hot_updates_server_url" value="https://your-server.com/api/updates" />
85
- <preference name="hot_updates_check_interval" value="300000" />
86
- ```
102
+ **Does NOT check ignoreList** - JavaScript controls all installation decisions.
87
103
 
88
- ### 2. Basic Usage
104
+ **Parameters:**
105
+ - `options` (Object):
106
+ - `url` (string, required) - URL to download ZIP archive
107
+ - `version` (string, optional) - Version string
108
+ - `callback` (Function) - `callback(error)`
109
+ - `null` on success
110
+ - `{error: {message?: string}}` on error
89
111
 
112
+ **Example:**
90
113
  ```javascript
91
- // Check current version
92
- HotUpdates.getCurrentVersion(
93
- function(version) {
94
- console.log('Current version:', version);
95
- },
96
- function(error) {
97
- console.error('Error:', error);
98
- }
99
- );
100
-
101
- // Check for pending updates
102
- HotUpdates.getPendingUpdateInfo(
103
- function(info) {
104
- if (info.hasPendingUpdate) {
105
- console.log('Update ready:', info.pendingVersion);
106
- alert('New update will be applied on next app restart');
114
+ window.hotUpdate.getUpdate({
115
+ url: 'https://your-server.com/updates/2.0.0.zip',
116
+ version: '2.0.0'
117
+ }, function(error) {
118
+ if (error) {
119
+ console.error('Download failed:', error);
120
+ } else {
121
+ console.log('Update downloaded successfully');
107
122
  }
108
- },
109
- function(error) {
110
- console.error('Error:', error);
111
- }
112
- );
113
-
114
- // Manually check for updates
115
- HotUpdates.checkForUpdates(
116
- function(result) {
117
- if (result.hasUpdate) {
118
- console.log('Update available:', result.availableVersion);
119
- // Optionally download manually
120
- HotUpdates.downloadUpdate(
121
- result.downloadURL,
122
- result.availableVersion,
123
- function() {
124
- console.log('Download completed');
125
- },
126
- function(error) {
127
- console.error('Download failed:', error);
128
- }
129
- );
130
- }
131
- },
132
- function(error) {
133
- console.error('Check failed:', error);
134
- }
135
- );
123
+ });
136
124
  ```
137
125
 
138
- ## ⚙️ Configuration
126
+ ---
127
+
128
+ ### window.hotUpdate.forceUpdate(callback)
129
+
130
+ Installs downloaded update immediately and reloads WebView.
139
131
 
140
- ### config.xml Preferences
132
+ **Process:**
133
+ 1. Backup current version to `www_previous`
134
+ 2. Copy downloaded update to `Documents/www`
135
+ 3. Clear WebView cache (disk, memory, Service Worker)
136
+ 4. Reload WebView
137
+ 5. Start 20-second canary timer
141
138
 
142
- | Preference | Default | Description |
143
- |------------|---------|-------------|
144
- | `hot_updates_server_url` | `https://your-server.com/api/updates` | Update server endpoint |
145
- | `hot_updates_check_interval` | `300000` | Check interval in milliseconds (5 minutes) |
146
- | `hot_updates_auto_download` | `true` | Enable automatic download |
147
- | `hot_updates_auto_install` | `true` | Enable automatic installation on restart |
139
+ **IMPORTANT:** JavaScript MUST call `canary(version)` within 20 seconds after reload to confirm successful bundle load. Otherwise automatic rollback occurs.
148
140
 
149
- ### Example Configuration
141
+ **Does NOT check ignoreList** - JavaScript decides what to install.
150
142
 
151
- ```xml
152
- <widget id="com.yourcompany.yourapp" version="1.0.0">
153
- <!-- Hot Updates Configuration -->
154
- <preference name="hot_updates_server_url" value="https://updates.yourapp.com/api/check" />
155
- <preference name="hot_updates_check_interval" value="600000" />
156
- <preference name="hot_updates_auto_download" value="true" />
157
- <preference name="hot_updates_auto_install" value="true" />
143
+ **Parameters:**
144
+ - `callback` (Function) - `callback(error)`
145
+ - `null` on success (before WebView reload)
146
+ - `{error: {message?: string}}` on error
158
147
 
159
- <!-- Your other configurations... -->
160
- </widget>
148
+ **Example:**
149
+ ```javascript
150
+ window.hotUpdate.forceUpdate(function(error) {
151
+ if (error) {
152
+ console.error('Install failed:', error);
153
+ } else {
154
+ console.log('Update installing, WebView will reload...');
155
+ }
156
+ });
161
157
  ```
162
158
 
163
- ## 📚 API Reference
159
+ ---
160
+
161
+ ### window.hotUpdate.canary(version, callback)
162
+
163
+ Confirms successful bundle load after update.
164
164
 
165
- ### Methods
165
+ **MUST be called within 20 seconds** after `forceUpdate()` to stop canary timer and prevent automatic rollback.
166
166
 
167
- #### `getCurrentVersion(successCallback, errorCallback)`
167
+ **If not called within 20 seconds:**
168
+ - Automatic rollback to previous version
169
+ - Failed version added to ignoreList
170
+ - WebView reloaded with previous version
168
171
 
169
- Gets the currently active version string.
172
+ **Parameters:**
173
+ - `version` (string) - Version that loaded successfully
174
+ - `callback` (Function, optional) - Not used, method is synchronous
170
175
 
176
+ **Example:**
171
177
  ```javascript
172
- HotUpdates.getCurrentVersion(
173
- function(version) {
174
- console.log('Current version:', version); // "1.2.3"
175
- },
176
- function(error) {
177
- console.error('Error getting version:', error);
178
- }
179
- );
178
+ document.addEventListener('deviceready', function() {
179
+ var version = localStorage.getItem('app_version') || '1.0.0';
180
+ window.hotUpdate.canary(version);
181
+ }, false);
180
182
  ```
181
183
 
182
- #### `getPendingUpdateInfo(successCallback, errorCallback)`
184
+ ---
183
185
 
184
- Gets information about downloaded updates waiting to be installed.
186
+ ### window.hotUpdate.getIgnoreList(callback)
185
187
 
186
- ```javascript
187
- HotUpdates.getPendingUpdateInfo(
188
- function(info) {
189
- // info object contains:
190
- // - hasPendingUpdate: boolean
191
- // - pendingVersion: string
192
- // - appBundleVersion: string
193
- // - installedVersion: string
194
- // - message: string
195
- },
196
- function(error) {
197
- console.error('Error getting update info:', error);
198
- }
199
- );
200
- ```
188
+ Returns list of problematic versions (information only).
201
189
 
202
- #### `checkForUpdates(successCallback, errorCallback)`
190
+ **This is an INFORMATION-ONLY system** - native does NOT block installation. JavaScript should read this list and decide whether to skip these versions.
203
191
 
204
- Manually triggers an update check.
192
+ Native automatically adds versions to this list when rollback occurs.
205
193
 
194
+ **Parameters:**
195
+ - `callback` (Function) - `callback(result)`
196
+ - `result`: `{versions: string[]}` - Array of problematic version strings
197
+
198
+ **Example:**
206
199
  ```javascript
207
- HotUpdates.checkForUpdates(
208
- function(result) {
209
- // result object contains:
210
- // - hasUpdate: boolean
211
- // - currentVersion: string
212
- // - availableVersion: string (if hasUpdate is true)
213
- // - downloadURL: string (if hasUpdate is true)
214
- // - minAppVersion: string (if specified)
215
- },
216
- function(error) {
217
- console.error('Update check failed:', error);
218
- }
219
- );
200
+ window.hotUpdate.getIgnoreList(function(result) {
201
+ console.log('Problematic versions:', result.versions);
202
+
203
+ if (result.versions.includes(newVersion)) {
204
+ console.log('Skipping known problematic version');
205
+ }
206
+ });
220
207
  ```
221
208
 
222
- #### `downloadUpdate(downloadURL, version, successCallback, errorCallback, progressCallback)`
209
+ ---
223
210
 
224
- Manually downloads a specific update.
211
+ ## Complete Update Flow
225
212
 
226
213
  ```javascript
227
- HotUpdates.downloadUpdate(
228
- 'https://server.com/updates/v2.0.0.zip',
229
- '2.0.0',
230
- function() {
231
- console.log('Download completed');
232
- },
233
- function(error) {
234
- console.error('Download failed:', error);
235
- },
236
- function(progress) {
237
- console.log('Download progress:', progress + '%');
238
- }
239
- );
214
+ // Step 1: Check for updates on your server
215
+ function checkForUpdates() {
216
+ var currentVersion = localStorage.getItem('app_version') || '1.0.0';
217
+
218
+ fetch('https://your-server.com/api/check-update?version=' + currentVersion)
219
+ .then(response => response.json())
220
+ .then(data => {
221
+ if (data.hasUpdate) {
222
+ // Step 2: Check ignoreList
223
+ window.hotUpdate.getIgnoreList(function(ignoreList) {
224
+ if (ignoreList.versions.includes(data.version)) {
225
+ console.log('Skipping problematic version');
226
+ return;
227
+ }
228
+
229
+ // Step 3: Download
230
+ window.hotUpdate.getUpdate({
231
+ url: data.downloadUrl,
232
+ version: data.version
233
+ }, function(error) {
234
+ if (!error) {
235
+ // Step 4: Prompt user
236
+ if (confirm('Update available. Install now?')) {
237
+ // Save version for canary check
238
+ localStorage.setItem('app_version', data.version);
239
+
240
+ // Step 5: Install
241
+ window.hotUpdate.forceUpdate(function(error) {
242
+ // WebView will reload
243
+ });
244
+ }
245
+ // If declined, auto-installs on next launch
246
+ }
247
+ });
248
+ });
249
+ }
250
+ });
251
+ }
252
+
253
+ // Step 6: After reload, confirm success
254
+ document.addEventListener('deviceready', function() {
255
+ var version = localStorage.getItem('app_version') || '1.0.0';
256
+ window.hotUpdate.canary(version); // Must call within 20 seconds!
257
+
258
+ initApp();
259
+ }, false);
240
260
  ```
241
261
 
242
- #### `getConfiguration(successCallback, errorCallback)`
262
+ ## How It Works
243
263
 
244
- Gets the current plugin configuration.
264
+ ### Update Flow
265
+
266
+ 1. **Download** (`getUpdate()`):
267
+ - Downloads ZIP from URL
268
+ - Validates `www` folder structure
269
+ - Saves to TWO locations:
270
+ - `temp_downloaded_update` (for immediate install)
271
+ - `pending_update` (for auto-install on next launch)
272
+
273
+ 2. **Installation Options**:
274
+ - **Immediate**: User clicks "Update" → `forceUpdate()` installs now
275
+ - **Deferred**: User ignores → Auto-installs on next app launch
276
+
277
+ 3. **Rollback Protection**:
278
+ - Previous version backed up before installation
279
+ - 20-second canary timer starts after reload
280
+ - If `canary()` not called → automatic rollback
281
+ - Failed version added to ignoreList
282
+
283
+ 4. **IgnoreList System**:
284
+ - Native tracks failed versions
285
+ - JavaScript reads via `getIgnoreList()`
286
+ - **Does NOT block** - JS decides what to install
287
+
288
+ ### Storage Structure
245
289
 
246
- ```javascript
247
- HotUpdates.getConfiguration(
248
- function(config) {
249
- // config object contains:
250
- // - serverURL: string
251
- // - checkInterval: number (milliseconds)
252
- // - appBundleVersion: string
253
- // - autoDownload: boolean
254
- },
255
- function(error) {
256
- console.error('Error getting config:', error);
257
- }
258
- );
290
+ ```
291
+ Documents/
292
+ ├── www/ // Active version
293
+ ├── www_previous/ // Previous version (rollback)
294
+ ├── pending_update/ // Next launch auto-install
295
+ └── temp_downloaded_update/ // Immediate install
259
296
  ```
260
297
 
261
- ## 🖥️ Server Implementation
298
+ ### Version Management
262
299
 
263
- Your update server should implement the following API:
300
+ - **appBundleVersion** - Native app version from Info.plist
301
+ - **installedVersion** - Current hot update version
302
+ - **previousVersion** - Last working version (rollback)
264
303
 
265
- ### Check for Updates Endpoint
304
+ ## Update Server API
266
305
 
267
- **GET** `/check?version={currentVersion}&platform=ios`
306
+ Your server should provide:
268
307
 
269
- **Response** (when update available):
270
- ```json
271
- {
272
- "hasUpdate": true,
273
- "version": "1.2.0",
274
- "downloadURL": "https://yourserver.com/updates/v1.2.0.zip",
275
- "minAppVersion": "1.0.0",
276
- "releaseNotes": "Bug fixes and improvements"
277
- }
308
+ **Check API:**
278
309
  ```
310
+ GET https://your-server.com/api/check-update?version=1.0.0&platform=ios
279
311
 
280
- **Response** (when no update available):
281
- ```json
312
+ Response:
282
313
  {
283
- "hasUpdate": false,
284
- "message": "No updates available"
314
+ "hasUpdate": true,
315
+ "version": "2.0.0",
316
+ "downloadUrl": "https://your-server.com/updates/2.0.0.zip",
317
+ "minAppVersion": "2.7.0",
318
+ "releaseNotes": "Bug fixes"
285
319
  }
286
320
  ```
287
321
 
288
- ### Update Package Format
289
-
290
- Your update ZIP file should contain a `www` folder with your web content:
291
-
322
+ **Update ZIP Structure:**
292
323
  ```
293
324
  update.zip
294
325
  └── www/
295
326
  ├── index.html
296
327
  ├── js/
297
328
  ├── css/
298
- ├── img/
299
329
  └── ...
300
330
  ```
301
331
 
302
- ### Example Server Implementation (Node.js)
332
+ ## Best Practices
303
333
 
304
- ```javascript
305
- const express = require('express');
306
- const app = express();
307
-
308
- app.get('/api/updates/check', (req, res) => {
309
- const { version, platform } = req.query;
310
- const currentVersion = version || '1.0.0';
311
- const latestVersion = '1.2.0'; // Your latest version
312
-
313
- if (compareVersions(currentVersion, latestVersion) < 0) {
314
- res.json({
315
- hasUpdate: true,
316
- version: latestVersion,
317
- downloadURL: `https://yourserver.com/updates/v${latestVersion}.zip`,
318
- minAppVersion: '1.0.0',
319
- releaseNotes: 'Bug fixes and improvements'
320
- });
321
- } else {
322
- res.json({
323
- hasUpdate: false,
324
- message: 'No updates available'
325
- });
326
- }
327
- });
328
-
329
- function compareVersions(version1, version2) {
330
- const v1parts = version1.split('.').map(Number);
331
- const v2parts = version2.split('.').map(Number);
332
-
333
- for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
334
- const v1part = v1parts[i] || 0;
335
- const v2part = v2parts[i] || 0;
336
-
337
- if (v1part < v2part) return -1;
338
- if (v1part > v2part) return 1;
339
- }
334
+ ### 1. Always Call Canary
340
335
 
341
- return 0;
342
- }
343
-
344
- app.listen(3000, () => {
345
- console.log('Update server running on port 3000');
346
- });
336
+ ```javascript
337
+ document.addEventListener('deviceready', function() {
338
+ var version = localStorage.getItem('app_version');
339
+ window.hotUpdate.canary(version); // Within 20 seconds!
340
+ }, false);
347
341
  ```
348
342
 
349
- ## 🔧 How It Works
350
-
351
- ### WebView Reload Approach
343
+ ### 2. Check IgnoreList
352
344
 
353
- 1. **Startup Check**: On app launch, the plugin checks for pending updates
354
- 2. **Installation**: If found, updates are installed to `Documents/www`
355
- 3. **WebView Switch**: The WebView is configured to load from `Documents/www` instead of bundle
356
- 4. **Background Process**: Automatic checking and downloading runs in background
357
- 5. **Next Launch**: New updates are applied on next app restart
358
-
359
- ### File Structure
360
-
361
- ```
362
- Documents/
363
- ├── www/ # Updated web content (active)
364
- ├── pending_update/ # Downloaded update waiting for installation
365
- │ └── www/ # New web content
366
- └── www_backup/ # Backup of previous version (for rollback)
345
+ ```javascript
346
+ window.hotUpdate.getIgnoreList(function(result) {
347
+ if (result.versions.includes(newVersion)) {
348
+ console.log('Known problematic version');
349
+ }
350
+ });
367
351
  ```
368
352
 
369
- ### Update Lifecycle
353
+ ### 3. Handle Errors
370
354
 
355
+ ```javascript
356
+ window.hotUpdate.getUpdate(options, function(error) {
357
+ if (error) {
358
+ analytics.track('update_failed', {error: error.message});
359
+ showUserMessage('Update failed');
360
+ }
361
+ });
371
362
  ```
372
- [Bundle] -> [Check] -> [Download] -> [Prepare] -> [Install] -> [Reload]
373
- ↑ ↓
374
- └─────────────────── [Next App Launch] ←──────────────────────┘
375
- ```
376
-
377
- ## 🐛 Troubleshooting
378
363
 
379
- ### Common Issues
364
+ ### 4. Store Version
380
365
 
381
- **Plugin installation fails or plugin not found**
382
- - **npm registry**: Ensure plugin is published to npm
383
- - **pnpm users**: Add hoisting configuration to `.npmrc` (see Installation with pnpm section)
384
- - **Git installation**: Use full GitHub URL: `cordova plugin add https://github.com/vladimirDarksy/Cordova_hot_update.git`
385
- - **Verify installation**: Run `cordova plugin list` to check if plugin is installed
386
-
387
- **pnpm + Cordova compatibility issues**
388
- If you're using pnpm and Cordova can't find the plugin:
389
-
390
- 1. Add to your project's `.npmrc`:
391
- ```
392
- public-hoist-pattern[]=cordova-plugin-*
393
- shamefully-hoist=true
394
- ```
395
-
396
- 2. Remove and reinstall:
397
- ```bash
398
- cordova plugin remove cordova-plugin-hot-updates
399
- rm -rf node_modules
400
- pnpm install
401
- cordova plugin add cordova-plugin-hot-updates
402
- ```
366
+ ```javascript
367
+ // Before forceUpdate
368
+ localStorage.setItem('app_version', newVersion);
403
369
 
404
- 3. If still not working, check that Cordova CLI can access the plugin:
405
- ```bash
406
- ls node_modules/cordova-plugin-hot-updates
407
- ```
370
+ // After reload
371
+ var version = localStorage.getItem('app_version');
372
+ window.hotUpdate.canary(version);
373
+ ```
408
374
 
409
- **Updates not downloading**
410
- - Check your server URL in config.xml
411
- - Verify server is returning correct JSON format
412
- - Check device network connectivity
413
- - Enable debugging with `cordova run ios --device --debug`
375
+ ## Troubleshooting
414
376
 
415
- **WebView not reloading updated content**
416
- - Ensure `Documents/www/index.html` exists
417
- - Check iOS device logs for WebView errors
418
- - Verify ZIP package contains `www` folder
377
+ ### Update doesn't install
419
378
 
420
- **CocoaPods issues**
421
- - Run `pod install` in `platforms/ios` directory
422
- - Update CocoaPods: `sudo gem install cocoapods`
423
- - Clean and rebuild: `cordova clean ios && cordova build ios`
379
+ - Check ZIP structure (must have `www/` folder)
380
+ - Check URL accessibility
381
+ - Check Xcode console: `[HotUpdates] ...`
424
382
 
425
- ### Debug Logging
383
+ ### Automatic rollback
426
384
 
427
- The plugin provides extensive console logging. To view:
385
+ **Cause:** `canary()` not called within 20 seconds
428
386
 
429
- ```bash
430
- # iOS Simulator
431
- cordova run ios --debug
432
-
433
- # iOS Device
434
- # Use Xcode console or Safari Web Inspector
387
+ **Solution:** Call immediately in `deviceready`:
388
+ ```javascript
389
+ document.addEventListener('deviceready', function() {
390
+ window.hotUpdate.canary(version); // First thing!
391
+ }, false);
435
392
  ```
436
393
 
437
- ### Reset Plugin State
394
+ ### window.hotUpdate is undefined
395
+
396
+ **Cause:** Called before `deviceready`
438
397
 
398
+ **Solution:**
439
399
  ```javascript
440
- // Clear all plugin data (for testing)
441
- localStorage.removeItem('hot_updates_installed_version');
442
- localStorage.removeItem('hot_updates_pending_version');
443
- localStorage.removeItem('hot_updates_has_pending');
400
+ document.addEventListener('deviceready', function() {
401
+ console.log(window.hotUpdate); // Now available
402
+ }, false);
444
403
  ```
445
404
 
446
- ## ⚠️ Important Notes
405
+ ## Migration from v1.0.0
447
406
 
448
- - **iOS Only**: Currently supports iOS platform only
449
- - **HTTPS Required**: Update server should use HTTPS in production
450
- - **App Store Compliance**: Only update web content, not native code
451
- - **Testing**: Test thoroughly on real devices before production
452
- - **Rollback**: Keep ability to rollback via App Store if needed
407
+ **Removed methods:**
408
+ - `getCurrentVersion()` - Manage in JS
409
+ - `getPendingUpdateInfo()` - Not needed
410
+ - `checkForUpdates()` - Frontend controls
411
+ - `downloadUpdate()` - Use `getUpdate()`
412
+ - `installUpdate()` - Use `forceUpdate()`
453
413
 
454
- ## 📄 Requirements
414
+ **New API:**
415
+ - `window.hotUpdate.getUpdate({url, version?}, callback)`
416
+ - `window.hotUpdate.forceUpdate(callback)`
417
+ - `window.hotUpdate.canary(version, callback)`
418
+ - `window.hotUpdate.getIgnoreList(callback)`
455
419
 
456
- - **Cordova**: >= 7.0.0
457
- - **cordova-ios**: >= 4.4.0
458
- - **iOS**: >= 11.0
459
- - **CocoaPods**: For SSZipArchive dependency
420
+ **Changes:**
421
+ - API via `window.hotUpdate` (not `window.HotUpdates`)
422
+ - Callback signature: `callback(error)` pattern
423
+ - No automatic background checking
460
424
 
461
- ## 🤝 Contributing
425
+ ## Changelog
462
426
 
463
- Contributions are welcome! Please feel free to submit a Pull Request.
427
+ ### v2.1.2 (2025-11-13)
464
428
 
465
- 1. Fork the repository
466
- 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
467
- 3. Commit your changes (`git commit -m 'Add amazing feature'`)
468
- 4. Push to the branch (`git push origin feature/amazing-feature`)
469
- 5. Open a Pull Request
429
+ **Breaking Changes:**
430
+ - Changed API from `window.HotUpdates` to `window.hotUpdate`
431
+ - Removed automatic update checking
432
+ - Simplified to 4 methods: `getUpdate`, `forceUpdate`, `canary`, `getIgnoreList`
470
433
 
471
- ## 📝 License
434
+ **New Features:**
435
+ - Frontend-controlled manual updates
436
+ - Two-step update flow
437
+ - 20-second canary timer
438
+ - IgnoreList system
439
+ - Auto-install on next launch
440
+ - WebView cache clearing
472
441
 
473
- This project is licensed under the Custom Non-Commercial License - see the [LICENSE](LICENSE) file for details.
442
+ ### v1.0.0
474
443
 
475
- **⚠️ Commercial use is strictly prohibited without explicit written permission from the copyright holder.**
444
+ - Initial release
476
445
 
477
- For commercial licensing inquiries, please contact: **Mustafin Vladimir**
446
+ ## License
478
447
 
479
- ## 🙋‍♂️ Support
448
+ Custom Non-Commercial License - See [LICENSE](LICENSE) file
480
449
 
481
- - **Issues**: [GitHub Issues](https://github.com/vladimirDarksy/Cordova_hot_update/issues)
482
- - **Documentation**: This README and inline code documentation
483
- - **Discussions**: [GitHub Discussions](https://github.com/vladimirDarksy/Cordova_hot_update/discussions)
450
+ ## Author
484
451
 
485
- ---
452
+ **Mustafin Vladimir**
453
+ - GitHub: [@vladimirDarksy](https://github.com/vladimirDarksy)
454
+ - Email: outvova.gor@gmail.com
455
+
456
+ ## Support
486
457
 
487
- **Made with ❤️ by [Mustafin Vladimir](https://github.com/vladimirDarksy)**
458
+ - Issues: https://github.com/vladimirDarksy/Cordova_hot_update/issues
459
+ - Repository: https://github.com/vladimirDarksy/Cordova_hot_update