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 +332 -360
- package/package.json +4 -5
- package/plugin.xml +5 -10
- package/src/ios/HotUpdates.m +2 -2
- package/www/HotUpdates.js +162 -142
- package/CHANGELOG.md +0 -239
- package/docs/API.md +0 -352
- package/docs/README.md +0 -187
- package/docs/hot-updates-admin.html +0 -467
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cordova-plugin-hot-updates",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.1.2",
|
|
4
|
+
"description": "Frontend-controlled manual hot updates for Cordova iOS apps using WebView Reload approach. Manual updates only, JavaScript controls all decisions.",
|
|
5
5
|
"main": "www/HotUpdates.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"over-the-air",
|
|
24
24
|
"webview",
|
|
25
25
|
"reload",
|
|
26
|
+
"manual",
|
|
26
27
|
"ecosystem:cordova",
|
|
27
28
|
"cordova-ios",
|
|
28
29
|
"mobile",
|
|
@@ -58,10 +59,8 @@
|
|
|
58
59
|
"www/",
|
|
59
60
|
"src/",
|
|
60
61
|
"scripts/",
|
|
61
|
-
"docs/",
|
|
62
62
|
"plugin.xml",
|
|
63
63
|
"README.md",
|
|
64
|
-
"LICENSE"
|
|
65
|
-
"CHANGELOG.md"
|
|
64
|
+
"LICENSE"
|
|
66
65
|
]
|
|
67
66
|
}
|
package/plugin.xml
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<?xml version='1.0' encoding='utf-8'?>
|
|
2
2
|
<plugin id="cordova-plugin-hot-updates"
|
|
3
|
-
version="1.
|
|
3
|
+
version="2.1.2"
|
|
4
4
|
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
5
5
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
6
6
|
|
|
7
7
|
<name>Cordova Hot Updates Plugin</name>
|
|
8
8
|
<description>
|
|
9
|
-
Cordova plugin for
|
|
9
|
+
Cordova plugin for frontend-controlled manual hot updates using WebView Reload approach.
|
|
10
|
+
Manual updates only, JavaScript controls all decisions.
|
|
10
11
|
Enables seamless web content updates without requiring App Store approval.
|
|
11
12
|
</description>
|
|
12
13
|
<license>Custom Non-Commercial</license>
|
|
13
|
-
<keywords>cordova,hot,updates,ota,over-the-air,webview,reload</keywords>
|
|
14
|
+
<keywords>cordova,hot,updates,ota,over-the-air,webview,reload,manual</keywords>
|
|
14
15
|
<repo>https://github.com/vladimirDarksy/Cordova_hot_update.git</repo>
|
|
15
16
|
<issue>https://github.com/vladimirDarksy/Cordova_hot_update/issues</issue>
|
|
16
17
|
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
|
|
24
25
|
<!-- JavaScript interface -->
|
|
25
26
|
<js-module src="www/HotUpdates.js" name="HotUpdates">
|
|
26
|
-
<clobbers target="
|
|
27
|
+
<clobbers target="hotUpdate" />
|
|
27
28
|
</js-module>
|
|
28
29
|
|
|
29
30
|
<!-- iOS platform -->
|
|
@@ -62,12 +63,6 @@
|
|
|
62
63
|
<true/>
|
|
63
64
|
</dict>
|
|
64
65
|
</edit-config>
|
|
65
|
-
|
|
66
|
-
<!-- Configuration preferences with default values -->
|
|
67
|
-
<preference name="hot_updates_server_url" default="https://your-server.com/api/updates" />
|
|
68
|
-
<preference name="hot_updates_check_interval" default="300000" />
|
|
69
|
-
<preference name="hot_updates_auto_download" default="true" />
|
|
70
|
-
<preference name="hot_updates_auto_install" default="true" />
|
|
71
66
|
</platform>
|
|
72
67
|
|
|
73
68
|
<!-- Android platform (placeholder for future implementation) -->
|
package/src/ios/HotUpdates.m
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - IgnoreList for tracking problematic versions
|
|
13
13
|
* - Auto-install pending updates on next app launch
|
|
14
14
|
*
|
|
15
|
-
* @version 2.1.
|
|
16
|
-
* @date 2025-11-
|
|
15
|
+
* @version 2.1.2
|
|
16
|
+
* @date 2025-11-13
|
|
17
17
|
* @author Mustafin Vladimir
|
|
18
18
|
* @copyright Copyright (c) 2025. All rights reserved.
|
|
19
19
|
*/
|
package/www/HotUpdates.js
CHANGED
|
@@ -1,192 +1,212 @@
|
|
|
1
1
|
var exec = require('cordova/exec');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Cordova Hot Updates Plugin
|
|
4
|
+
* Cordova Hot Updates Plugin v2.1.2
|
|
5
|
+
* Frontend-controlled manual hot updates for iOS
|
|
5
6
|
*
|
|
6
|
-
* Provides
|
|
7
|
-
* using the WebView Reload approach
|
|
7
|
+
* Provides manual over-the-air (OTA) updates for Cordova applications
|
|
8
|
+
* using the WebView Reload approach. All update decisions are controlled
|
|
9
|
+
* by JavaScript - the native plugin only executes commands.
|
|
8
10
|
*
|
|
9
11
|
* Features:
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
12
|
+
* - Frontend-controlled manual updates (no automatic checking)
|
|
13
|
+
* - Two-step update flow: getUpdate() downloads, forceUpdate() installs
|
|
14
|
+
* - Automatic rollback with 20-second canary timer
|
|
15
|
+
* - IgnoreList system for tracking problematic versions (information only)
|
|
16
|
+
* - Auto-install pending updates on next app launch
|
|
17
|
+
* - WebView reload approach for instant updates without app restart
|
|
14
18
|
* - No App Store approval required for web content updates
|
|
15
19
|
*
|
|
16
|
-
* @version 1.
|
|
20
|
+
* @version 2.1.2
|
|
17
21
|
* @author Mustafin Vladimir
|
|
18
22
|
*/
|
|
19
23
|
var HotUpdates = {
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
|
-
*
|
|
23
|
-
* Returns the currently active version (installed update or bundle version)
|
|
26
|
+
* Download update from server
|
|
24
27
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
28
|
+
* Downloads update ZIP archive from the provided URL and saves to two locations:
|
|
29
|
+
* - temp_downloaded_update (for immediate installation via forceUpdate)
|
|
30
|
+
* - pending_update (for auto-installation on next app launch)
|
|
27
31
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* function(version) {
|
|
31
|
-
* console.log('Current version:', version);
|
|
32
|
-
* },
|
|
33
|
-
* function(error) {
|
|
34
|
-
* console.error('Error getting version:', error);
|
|
35
|
-
* }
|
|
36
|
-
* );
|
|
37
|
-
*/
|
|
38
|
-
getCurrentVersion: function(successCallback, errorCallback) {
|
|
39
|
-
exec(successCallback, errorCallback, 'HotUpdates', 'getCurrentVersion', []);
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get pending update information
|
|
44
|
-
* Returns information about downloaded updates waiting to be installed
|
|
45
|
-
*
|
|
46
|
-
* @param {Function} successCallback - Success callback with update info object
|
|
47
|
-
* @param {Function} errorCallback - Error callback
|
|
32
|
+
* If the specified version is already downloaded, returns success without re-downloading.
|
|
33
|
+
* Does NOT check ignoreList - JavaScript controls all installation decisions.
|
|
48
34
|
*
|
|
49
|
-
*
|
|
50
|
-
* -
|
|
51
|
-
* -
|
|
52
|
-
* -
|
|
53
|
-
*
|
|
54
|
-
*
|
|
35
|
+
* @param {Object} options - Update options
|
|
36
|
+
* @param {string} options.url - URL to download ZIP archive (required)
|
|
37
|
+
* @param {string} [options.version] - Version string (optional)
|
|
38
|
+
* @param {Function} callback - Callback function
|
|
39
|
+
* - Called with null on success
|
|
40
|
+
* - Called with {error: {message?: string}} on error
|
|
55
41
|
*
|
|
56
42
|
* @example
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
43
|
+
* window.hotUpdate.getUpdate({
|
|
44
|
+
* url: 'https://your-server.com/updates/2.0.0.zip',
|
|
45
|
+
* version: '2.0.0'
|
|
46
|
+
* }, function(error) {
|
|
47
|
+
* if (error) {
|
|
48
|
+
* console.error('Download failed:', error);
|
|
49
|
+
* } else {
|
|
50
|
+
* console.log('Update downloaded successfully');
|
|
51
|
+
* // Can now call forceUpdate() to install immediately
|
|
52
|
+
* // Or user can ignore and it will auto-install on next launch
|
|
62
53
|
* }
|
|
63
|
-
*
|
|
64
|
-
* function(error) {
|
|
65
|
-
* console.error('Error getting update info:', error);
|
|
66
|
-
* }
|
|
67
|
-
* );
|
|
54
|
+
* });
|
|
68
55
|
*/
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
getUpdate: function(options, callback) {
|
|
57
|
+
if (!options || !options.url) {
|
|
58
|
+
if (callback) {
|
|
59
|
+
callback({error: {message: 'URL is required'}});
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exec(
|
|
65
|
+
function() {
|
|
66
|
+
// Success
|
|
67
|
+
if (callback) callback(null);
|
|
68
|
+
},
|
|
69
|
+
function(error) {
|
|
70
|
+
// Error
|
|
71
|
+
if (callback) callback({error: error});
|
|
72
|
+
},
|
|
73
|
+
'HotUpdates',
|
|
74
|
+
'getUpdate',
|
|
75
|
+
[options]
|
|
76
|
+
);
|
|
71
77
|
},
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
80
|
+
* Install downloaded update immediately
|
|
81
|
+
*
|
|
82
|
+
* Installs the update that was downloaded via getUpdate().
|
|
83
|
+
* This will:
|
|
84
|
+
* 1. Backup current version to www_previous
|
|
85
|
+
* 2. Copy downloaded update to Documents/www
|
|
86
|
+
* 3. Clear WebView cache (disk, memory, Service Worker)
|
|
87
|
+
* 4. Reload WebView
|
|
88
|
+
* 5. Start 20-second canary timer
|
|
76
89
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
90
|
+
* IMPORTANT: JavaScript MUST call canary(version) within 20 seconds
|
|
91
|
+
* after reload to confirm successful bundle load. Otherwise automatic
|
|
92
|
+
* rollback will occur.
|
|
79
93
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* -
|
|
83
|
-
*
|
|
84
|
-
*
|
|
94
|
+
* Does NOT check ignoreList - JavaScript decides what to install.
|
|
95
|
+
*
|
|
96
|
+
* @param {Function} callback - Callback function
|
|
97
|
+
* - Called with null on success (before WebView reload)
|
|
98
|
+
* - Called with {error: {message?: string}} on error
|
|
85
99
|
*
|
|
86
100
|
* @example
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* console.log('Update available:', result.availableVersion);
|
|
101
|
+
* window.hotUpdate.forceUpdate(function(error) {
|
|
102
|
+
* if (error) {
|
|
103
|
+
* console.error('Install failed:', error);
|
|
91
104
|
* } else {
|
|
92
|
-
*
|
|
105
|
+
* console.log('Update installing, WebView will reload...');
|
|
106
|
+
* // After reload, MUST call canary() within 20 seconds!
|
|
93
107
|
* }
|
|
94
|
-
*
|
|
95
|
-
* function(error) {
|
|
96
|
-
* console.error('Update check failed:', error);
|
|
97
|
-
* }
|
|
98
|
-
* );
|
|
108
|
+
* });
|
|
99
109
|
*/
|
|
100
|
-
|
|
101
|
-
exec(
|
|
110
|
+
forceUpdate: function(callback) {
|
|
111
|
+
exec(
|
|
112
|
+
function() {
|
|
113
|
+
// Success
|
|
114
|
+
if (callback) callback(null);
|
|
115
|
+
},
|
|
116
|
+
function(error) {
|
|
117
|
+
// Error
|
|
118
|
+
if (callback) callback({error: error});
|
|
119
|
+
},
|
|
120
|
+
'HotUpdates',
|
|
121
|
+
'forceUpdate',
|
|
122
|
+
[]
|
|
123
|
+
);
|
|
102
124
|
},
|
|
103
125
|
|
|
104
126
|
/**
|
|
105
|
-
*
|
|
106
|
-
* Manually triggers download of an available update
|
|
127
|
+
* Confirm successful bundle load (canary check)
|
|
107
128
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* @param {Function} errorCallback - Error callback
|
|
112
|
-
* @param {Function} progressCallback - Optional progress callback with download percentage
|
|
129
|
+
* MUST be called within 20 seconds after forceUpdate() to confirm
|
|
130
|
+
* that the new bundle loaded successfully. This stops the canary timer
|
|
131
|
+
* and prevents automatic rollback.
|
|
113
132
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* function() {
|
|
119
|
-
* console.log('Download completed, update will install on restart');
|
|
120
|
-
* },
|
|
121
|
-
* function(error) {
|
|
122
|
-
* console.error('Download failed:', error);
|
|
123
|
-
* },
|
|
124
|
-
* function(progress) {
|
|
125
|
-
* console.log('Download progress:', progress + '%');
|
|
126
|
-
* }
|
|
127
|
-
* );
|
|
128
|
-
*/
|
|
129
|
-
downloadUpdate: function(downloadURL, version, successCallback, errorCallback, progressCallback) {
|
|
130
|
-
var callbackId = successCallback ? 'HotUpdates' + Date.now() : null;
|
|
131
|
-
|
|
132
|
-
if (progressCallback) {
|
|
133
|
-
// Register progress callback if provided
|
|
134
|
-
exec(progressCallback, null, 'HotUpdates', 'setProgressCallback', [callbackId]);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
exec(successCallback, errorCallback, 'HotUpdates', 'downloadUpdate', [downloadURL, version, callbackId]);
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get plugin configuration
|
|
142
|
-
* Returns current plugin configuration settings
|
|
133
|
+
* If not called within 20 seconds:
|
|
134
|
+
* - Automatic rollback to previous version
|
|
135
|
+
* - Failed version added to ignoreList
|
|
136
|
+
* - WebView reloaded with previous version
|
|
143
137
|
*
|
|
144
|
-
*
|
|
145
|
-
* @param {Function} errorCallback - Error callback
|
|
138
|
+
* Call this immediately after your app initialization completes.
|
|
146
139
|
*
|
|
147
|
-
*
|
|
148
|
-
* -
|
|
149
|
-
* - checkInterval: number (check interval in milliseconds)
|
|
150
|
-
* - appBundleVersion: string (native app version)
|
|
151
|
-
* - autoDownload: boolean (automatic download enabled)
|
|
140
|
+
* @param {string} version - Version that loaded successfully
|
|
141
|
+
* @param {Function} [callback] - Optional callback (not used, method is synchronous)
|
|
152
142
|
*
|
|
153
143
|
* @example
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* console.log('
|
|
158
|
-
*
|
|
159
|
-
* function(error) {
|
|
160
|
-
* console.error('Error getting config:', error);
|
|
161
|
-
* }
|
|
162
|
-
* );
|
|
144
|
+
* // Call as early as possible after app loads
|
|
145
|
+
* document.addEventListener('deviceready', function() {
|
|
146
|
+
* window.hotUpdate.canary('2.0.0');
|
|
147
|
+
* console.log('Canary confirmed, update successful');
|
|
148
|
+
* }, false);
|
|
163
149
|
*/
|
|
164
|
-
|
|
165
|
-
exec(
|
|
150
|
+
canary: function(version, callback) {
|
|
151
|
+
exec(
|
|
152
|
+
function() {
|
|
153
|
+
if (callback) callback();
|
|
154
|
+
},
|
|
155
|
+
function() {
|
|
156
|
+
if (callback) callback();
|
|
157
|
+
},
|
|
158
|
+
'HotUpdates',
|
|
159
|
+
'canary',
|
|
160
|
+
[version]
|
|
161
|
+
);
|
|
166
162
|
},
|
|
167
163
|
|
|
168
164
|
/**
|
|
169
|
-
*
|
|
170
|
-
* Forces installation of a downloaded update without waiting for next app launch
|
|
171
|
-
* This will restart the application!
|
|
165
|
+
* Get list of problematic versions (information only)
|
|
172
166
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
167
|
+
* Returns array of version strings that failed to load (triggered rollback).
|
|
168
|
+
* This is an INFORMATION-ONLY system - native does NOT block installation
|
|
169
|
+
* of versions in this list.
|
|
170
|
+
*
|
|
171
|
+
* JavaScript should read this list and decide whether to skip downloading/
|
|
172
|
+
* installing these versions. If JS decides to install a version from the
|
|
173
|
+
* ignoreList, that's allowed (per TS requirements).
|
|
174
|
+
*
|
|
175
|
+
* Native automatically adds versions to this list when rollback occurs.
|
|
176
|
+
* JavaScript cannot modify the list (no add/remove/clear methods per TS v2.1.0).
|
|
177
|
+
*
|
|
178
|
+
* @param {Function} callback - Callback function
|
|
179
|
+
* - Called with {versions: string[]} - Array of problematic version strings
|
|
175
180
|
*
|
|
176
181
|
* @example
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* //
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
182
|
+
* window.hotUpdate.getIgnoreList(function(result) {
|
|
183
|
+
* console.log('Problematic versions:', result.versions);
|
|
184
|
+
* // Example: {versions: ['1.9.0', '2.0.1']}
|
|
185
|
+
*
|
|
186
|
+
* // JavaScript decides what to do with this information
|
|
187
|
+
* var shouldSkip = result.versions.includes(availableVersion);
|
|
188
|
+
* if (shouldSkip) {
|
|
189
|
+
* console.log('Skipping known problematic version');
|
|
190
|
+
* } else {
|
|
191
|
+
* // Download and install
|
|
192
|
+
* }
|
|
193
|
+
* });
|
|
186
194
|
*/
|
|
187
|
-
|
|
188
|
-
exec(
|
|
195
|
+
getIgnoreList: function(callback) {
|
|
196
|
+
exec(
|
|
197
|
+
function(versions) {
|
|
198
|
+
// Success - native returns array of version strings
|
|
199
|
+
if (callback) callback({versions: versions || []});
|
|
200
|
+
},
|
|
201
|
+
function(error) {
|
|
202
|
+
// Error - return empty list
|
|
203
|
+
if (callback) callback({versions: []});
|
|
204
|
+
},
|
|
205
|
+
'HotUpdates',
|
|
206
|
+
'getIgnoreList',
|
|
207
|
+
[]
|
|
208
|
+
);
|
|
189
209
|
}
|
|
190
210
|
};
|
|
191
211
|
|
|
192
|
-
module.exports = HotUpdates;
|
|
212
|
+
module.exports = HotUpdates;
|