cordova-plugin-hot-updates 2.2.2 → 2.2.3
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 +54 -12
- package/package.json +1 -1
- package/plugin.xml +1 -1
- package/src/ios/HotUpdates.h +8 -6
- package/src/ios/HotUpdates.m +63 -2
- package/src/ios/HotUpdatesConstants.h +1 -0
- package/src/ios/HotUpdatesConstants.m +1 -0
package/README.md
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
# Cordova Hot Updates Plugin v2.2.
|
|
1
|
+
# Cordova Hot Updates Plugin v2.2.3
|
|
2
2
|
|
|
3
3
|
Frontend-controlled manual hot updates for Cordova iOS applications using WebView Reload approach.
|
|
4
4
|
|
|
5
|
-
## Changelog
|
|
6
|
-
|
|
7
|
-
### v2.2.2 (2024-11-28)
|
|
8
|
-
- **Fixed**: Failed download no longer corrupts previously downloaded update
|
|
9
|
-
- **Fixed**: Infinite loop when pending update installation fails (flags now cleared)
|
|
10
|
-
- **Fixed**: UserDefaults now saved only after successful download (not before)
|
|
11
|
-
- **Improved**: ZIP file validation with magic bytes check (PK\x03\x04) before extraction
|
|
12
|
-
- **Improved**: Cleaner logs without duplicates and full paths
|
|
13
|
-
- **Improved**: All errors now have consistent format with `ERROR:` prefix
|
|
14
|
-
- **Removed**: Redundant initialization code
|
|
15
|
-
|
|
16
5
|
[](https://badge.fury.io/js/cordova-plugin-hot-updates)
|
|
17
6
|
[](#license)
|
|
18
7
|
|
|
@@ -25,6 +14,7 @@ This plugin enables **manual, JavaScript-controlled** web content updates for yo
|
|
|
25
14
|
- **Auto-Install on Launch**: If user ignores update prompt, it installs on next app launch
|
|
26
15
|
- **Canary System**: Automatic rollback if update fails to load (20-second timeout)
|
|
27
16
|
- **IgnoreList**: Tracks problematic versions (information only, does NOT block installation)
|
|
17
|
+
- **Version History** *(new in v2.2.3)*: Tracks successful versions for progressive data migrations
|
|
28
18
|
- **Instant Effect**: WebView Reload approach - no app restart needed
|
|
29
19
|
- **Cache Management**: Clears WKWebView cache (disk, memory, Service Worker) before reload
|
|
30
20
|
|
|
@@ -279,6 +269,58 @@ window.hotUpdate.getIgnoreList(function(result) {
|
|
|
279
269
|
|
|
280
270
|
---
|
|
281
271
|
|
|
272
|
+
### window.hotUpdate.getVersionHistory(callback)
|
|
273
|
+
|
|
274
|
+
Returns list of all successfully installed versions (excluding rolled back ones).
|
|
275
|
+
|
|
276
|
+
**New in v2.2.3** - Enables progressive data migrations.
|
|
277
|
+
|
|
278
|
+
When internal data structure changes, you may need to run migrations. This method returns the version history so your app can determine which migrations to run.
|
|
279
|
+
|
|
280
|
+
**Key behaviors:**
|
|
281
|
+
- **Automatically initialized** with `appBundleVersion` on first launch
|
|
282
|
+
- **Added to history** when update is successfully installed
|
|
283
|
+
- **Removed from history** when version is rolled back (failed canary)
|
|
284
|
+
- **Excludes ignoreList** - only contains successful versions
|
|
285
|
+
|
|
286
|
+
**Parameters:**
|
|
287
|
+
- `callback` (Function) - `callback(result)`
|
|
288
|
+
- `result`: `{versions: string[]}` - Array of successful version strings
|
|
289
|
+
|
|
290
|
+
**Example:**
|
|
291
|
+
```javascript
|
|
292
|
+
window.hotUpdate.getVersionHistory(function(result) {
|
|
293
|
+
console.log('Version history:', result.versions);
|
|
294
|
+
// Example: ["2.7.7", "2.7.8", "2.7.9"]
|
|
295
|
+
|
|
296
|
+
// Run migrations based on version progression
|
|
297
|
+
result.versions.forEach((version, index) => {
|
|
298
|
+
if (index > 0) {
|
|
299
|
+
const from = result.versions[index - 1];
|
|
300
|
+
const to = version;
|
|
301
|
+
runMigration(from, to);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Use Case:**
|
|
308
|
+
```javascript
|
|
309
|
+
// Check for missed critical versions
|
|
310
|
+
window.hotUpdate.getVersionHistory(function(result) {
|
|
311
|
+
const criticalVersions = ['2.8.0', '3.0.0']; // Versions with important migrations
|
|
312
|
+
const missed = criticalVersions.filter(v => !result.versions.includes(v));
|
|
313
|
+
|
|
314
|
+
if (missed.length > 0) {
|
|
315
|
+
console.warn('User skipped critical versions:', missed);
|
|
316
|
+
// Run all missed critical migrations
|
|
317
|
+
missed.forEach(v => runCriticalMigration(v));
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
282
324
|
### window.hotUpdate.getVersionInfo(callback)
|
|
283
325
|
|
|
284
326
|
Returns version information (debug method).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cordova-plugin-hot-updates",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
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": {
|
package/plugin.xml
CHANGED
package/src/ios/HotUpdates.h
CHANGED
|
@@ -29,16 +29,18 @@
|
|
|
29
29
|
|
|
30
30
|
// Settings
|
|
31
31
|
NSMutableArray *ignoreList; // Список игнорируемых версий (управляется только native)
|
|
32
|
+
NSMutableArray *versionHistory; // История успешно установленных версий (исключая откаченные)
|
|
32
33
|
NSString *previousVersionPath; // Путь к предыдущей версии
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
// JavaScript API methods (v2.
|
|
36
|
-
- (void)getUpdate:(CDVInvokedUrlCommand*)command;
|
|
37
|
-
- (void)forceUpdate:(CDVInvokedUrlCommand*)command;
|
|
38
|
-
- (void)canary:(CDVInvokedUrlCommand*)command;
|
|
39
|
-
- (void)getIgnoreList:(CDVInvokedUrlCommand*)command;
|
|
36
|
+
// JavaScript API methods (v2.2.2)
|
|
37
|
+
- (void)getUpdate:(CDVInvokedUrlCommand*)command; // Download update
|
|
38
|
+
- (void)forceUpdate:(CDVInvokedUrlCommand*)command; // Install downloaded update
|
|
39
|
+
- (void)canary:(CDVInvokedUrlCommand*)command; // Confirm successful load
|
|
40
|
+
- (void)getIgnoreList:(CDVInvokedUrlCommand*)command; // Get ignore list (JS reads only)
|
|
41
|
+
- (void)getVersionHistory:(CDVInvokedUrlCommand*)command; // Get version history (successful installs only)
|
|
40
42
|
|
|
41
43
|
// Debug method
|
|
42
|
-
- (void)getVersionInfo:(CDVInvokedUrlCommand*)command;
|
|
44
|
+
- (void)getVersionInfo:(CDVInvokedUrlCommand*)command; // Get all version info for debugging
|
|
43
45
|
|
|
44
46
|
@end
|
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.
|
|
16
|
-
* @date 2025-11-
|
|
15
|
+
* @version 2.1.2
|
|
16
|
+
* @date 2025-11-26
|
|
17
17
|
* @author Mustafin Vladimir
|
|
18
18
|
* @copyright Copyright (c) 2025. All rights reserved.
|
|
19
19
|
*/
|
|
@@ -55,6 +55,7 @@ static BOOL hasPerformedInitialReload = NO;
|
|
|
55
55
|
|
|
56
56
|
[self loadConfiguration];
|
|
57
57
|
[self loadIgnoreList];
|
|
58
|
+
[self loadVersionHistory];
|
|
58
59
|
|
|
59
60
|
// Сбрасываем флаг загрузки (если приложение было убито во время загрузки)
|
|
60
61
|
isDownloadingUpdate = NO;
|
|
@@ -127,6 +128,9 @@ static BOOL hasPerformedInitialReload = NO;
|
|
|
127
128
|
|
|
128
129
|
[[NSFileManager defaultManager] removeItemAtPath:pendingUpdatePath error:nil];
|
|
129
130
|
|
|
131
|
+
// Добавляем версию в историю при успешной установке
|
|
132
|
+
[self addVersionToHistory:pendingVersion];
|
|
133
|
+
|
|
130
134
|
NSLog(@"[HotUpdates] Update %@ installed successfully", pendingVersion);
|
|
131
135
|
} else {
|
|
132
136
|
NSLog(@"[HotUpdates] Failed to install pending update: %@", copyError.localizedDescription);
|
|
@@ -395,6 +399,58 @@ static BOOL hasPerformedInitialReload = NO;
|
|
|
395
399
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
396
400
|
}
|
|
397
401
|
|
|
402
|
+
#pragma mark - Version History Management
|
|
403
|
+
|
|
404
|
+
- (void)loadVersionHistory {
|
|
405
|
+
NSArray *savedHistory = [[NSUserDefaults standardUserDefaults] arrayForKey:kVersionHistory];
|
|
406
|
+
if (savedHistory) {
|
|
407
|
+
versionHistory = [savedHistory mutableCopy];
|
|
408
|
+
} else {
|
|
409
|
+
versionHistory = [NSMutableArray array];
|
|
410
|
+
// При первом запуске добавляем исходную версию приложения
|
|
411
|
+
if (appBundleVersion) {
|
|
412
|
+
[versionHistory addObject:appBundleVersion];
|
|
413
|
+
[self saveVersionHistory];
|
|
414
|
+
NSLog(@"[HotUpdates] Initial version history created with app version: %@", appBundleVersion);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
- (NSArray*)getVersionHistoryInternal {
|
|
420
|
+
return [versionHistory copy];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
- (void)saveVersionHistory {
|
|
424
|
+
[[NSUserDefaults standardUserDefaults] setObject:versionHistory forKey:kVersionHistory];
|
|
425
|
+
[[NSUserDefaults standardUserDefaults] synchronize];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
- (void)addVersionToHistory:(NSString*)version {
|
|
429
|
+
if (version && ![versionHistory containsObject:version]) {
|
|
430
|
+
[versionHistory addObject:version];
|
|
431
|
+
[self saveVersionHistory];
|
|
432
|
+
NSLog(@"[HotUpdates] Added version %@ to version history", version);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
- (void)removeVersionFromHistory:(NSString*)version {
|
|
437
|
+
if (version && [versionHistory containsObject:version]) {
|
|
438
|
+
[versionHistory removeObject:version];
|
|
439
|
+
[self saveVersionHistory];
|
|
440
|
+
NSLog(@"[HotUpdates] Removed version %@ from version history", version);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
- (void)getVersionHistory:(CDVInvokedUrlCommand*)command {
|
|
445
|
+
NSArray *history = [self getVersionHistoryInternal];
|
|
446
|
+
|
|
447
|
+
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
|
|
448
|
+
messageAsDictionary:@{
|
|
449
|
+
@"versions": history
|
|
450
|
+
}];
|
|
451
|
+
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
452
|
+
}
|
|
453
|
+
|
|
398
454
|
#pragma mark - Canary Timer
|
|
399
455
|
|
|
400
456
|
/*!
|
|
@@ -543,6 +599,8 @@ static BOOL hasPerformedInitialReload = NO;
|
|
|
543
599
|
|
|
544
600
|
if (currentVersion) {
|
|
545
601
|
[self addVersionToIgnoreList:currentVersion];
|
|
602
|
+
// Удаляем откаченную версию из истории (она не прошла canary)
|
|
603
|
+
[self removeVersionFromHistory:currentVersion];
|
|
546
604
|
}
|
|
547
605
|
|
|
548
606
|
return YES;
|
|
@@ -851,6 +909,9 @@ static BOOL hasPerformedInitialReload = NO;
|
|
|
851
909
|
pendingUpdateURL = nil;
|
|
852
910
|
pendingUpdateVersion = nil;
|
|
853
911
|
|
|
912
|
+
// Добавляем версию в историю при успешной установке
|
|
913
|
+
[self addVersionToHistory:newVersion];
|
|
914
|
+
|
|
854
915
|
NSLog(@"[HotUpdates] Update installed successfully");
|
|
855
916
|
NSLog(@"[HotUpdates] Starting canary timer for version %@", newVersion);
|
|
856
917
|
|
|
@@ -39,6 +39,7 @@ extern NSString * const kCanaryVersion;
|
|
|
39
39
|
extern NSString * const kDownloadInProgress;
|
|
40
40
|
extern NSString * const kPendingUpdateURL;
|
|
41
41
|
extern NSString * const kPendingUpdateReady;
|
|
42
|
+
extern NSString * const kVersionHistory;
|
|
42
43
|
|
|
43
44
|
#pragma mark - Directory Names
|
|
44
45
|
|
|
@@ -37,6 +37,7 @@ NSString * const kCanaryVersion = @"hot_updates_canary_version";
|
|
|
37
37
|
NSString * const kDownloadInProgress = @"hot_updates_download_in_progress";
|
|
38
38
|
NSString * const kPendingUpdateURL = @"hot_updates_pending_update_url";
|
|
39
39
|
NSString * const kPendingUpdateReady = @"hot_updates_pending_ready";
|
|
40
|
+
NSString * const kVersionHistory = @"hot_updates_version_history";
|
|
40
41
|
|
|
41
42
|
#pragma mark - Directory Names
|
|
42
43
|
|