@otakit/capacitor-updater 2.1.2 → 2.2.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.
- package/README.md +142 -4
- package/android/src/main/java/com/otakit/updater/BundleCrypto.java +81 -0
- package/android/src/main/java/com/otakit/updater/BundleStore.java +15 -0
- package/android/src/main/java/com/otakit/updater/ManifestClient.java +69 -2
- package/android/src/main/java/com/otakit/updater/ManifestVerifier.java +43 -0
- package/android/src/main/java/com/otakit/updater/UpdaterPlugin.java +277 -19
- package/dist/esm/definitions.d.ts +98 -0
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +7 -1
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +25 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +31 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +31 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/UpdaterPlugin/BundleCrypto.swift +91 -0
- package/ios/Sources/UpdaterPlugin/BundleStore.swift +13 -0
- package/ios/Sources/UpdaterPlugin/ManifestClient.swift +45 -1
- package/ios/Sources/UpdaterPlugin/ManifestVerifier.swift +29 -0
- package/ios/Sources/UpdaterPlugin/UpdaterPlugin.swift +256 -19
- package/package.json +1 -1
|
@@ -68,18 +68,24 @@ public class UpdaterPlugin extends Plugin {
|
|
|
68
68
|
|
|
69
69
|
final String kind;
|
|
70
70
|
final BundleInfo bundle;
|
|
71
|
+
final boolean forceImmediate;
|
|
71
72
|
|
|
72
|
-
private DownloadResolution(String kind, BundleInfo bundle) {
|
|
73
|
+
private DownloadResolution(String kind, BundleInfo bundle, boolean forceImmediate) {
|
|
73
74
|
this.kind = kind;
|
|
74
75
|
this.bundle = bundle;
|
|
76
|
+
this.forceImmediate = forceImmediate;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
static DownloadResolution noUpdate() {
|
|
78
|
-
return new DownloadResolution("no_update", null);
|
|
80
|
+
return new DownloadResolution("no_update", null, false);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
static DownloadResolution staged(BundleInfo bundle) {
|
|
82
|
-
return new DownloadResolution("staged", bundle);
|
|
83
|
+
static DownloadResolution staged(BundleInfo bundle, boolean forceImmediate) {
|
|
84
|
+
return new DownloadResolution("staged", bundle, forceImmediate);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
boolean isForcedStaged() {
|
|
88
|
+
return "staged".equals(kind) && forceImmediate;
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -107,6 +113,7 @@ public class UpdaterPlugin extends Plugin {
|
|
|
107
113
|
private String channel;
|
|
108
114
|
private String runtimeVersion;
|
|
109
115
|
private java.util.List<ManifestVerifier.KeyEntry> manifestKeys = new java.util.ArrayList<>();
|
|
116
|
+
private final java.util.Map<String, byte[]> bundleKeys = new java.util.HashMap<>();
|
|
110
117
|
private long checkIntervalMs = 600_000;
|
|
111
118
|
private boolean coldStartInProgress = false;
|
|
112
119
|
private static final String DEFAULT_INGEST_URL = "https://ingest.otakit.app/v1";
|
|
@@ -115,6 +122,8 @@ public class UpdaterPlugin extends Plugin {
|
|
|
115
122
|
private static final String KEY_LAST_CHECK_TIMESTAMP = "last_check_timestamp";
|
|
116
123
|
private static final String DEFAULT_RUNTIME_KEY = "__default__";
|
|
117
124
|
private static final String BUILTIN_ASSET_PATH = "public";
|
|
125
|
+
private static final java.util.regex.Pattern CHANNEL_NAME_PATTERN =
|
|
126
|
+
java.util.regex.Pattern.compile("^[A-Za-z0-9._-]{1,64}$");
|
|
118
127
|
private UpdaterCoordinator.StartupPreparation pendingStartupPreparation;
|
|
119
128
|
|
|
120
129
|
@Override
|
|
@@ -187,6 +196,38 @@ public class UpdaterPlugin extends Plugin {
|
|
|
187
196
|
manifestKeys.addAll(HostedManifestKeys.createDefaultKeys());
|
|
188
197
|
}
|
|
189
198
|
|
|
199
|
+
try {
|
|
200
|
+
org.json.JSONArray rawBundleKeys = getConfig().getConfigJSON().optJSONArray("bundleKeys");
|
|
201
|
+
if (rawBundleKeys != null && rawBundleKeys.length() > 0) {
|
|
202
|
+
for (int i = 0; i < rawBundleKeys.length(); i++) {
|
|
203
|
+
org.json.JSONObject entry = rawBundleKeys.optJSONObject(i);
|
|
204
|
+
if (entry == null) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
String kid = entry.optString("kid", null);
|
|
208
|
+
String keyBase64 = entry.optString("key", null);
|
|
209
|
+
if (kid != null && keyBase64 != null) {
|
|
210
|
+
byte[] keyBytes = android.util.Base64.decode(keyBase64, android.util.Base64.DEFAULT);
|
|
211
|
+
if (keyBytes.length == 32) {
|
|
212
|
+
bundleKeys.put(kid, keyBytes);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (bundleKeys.isEmpty()) {
|
|
217
|
+
android.util.Log.e(
|
|
218
|
+
"OtaKit",
|
|
219
|
+
"bundleKeys configured but all entries are invalid. Encrypted bundles cannot be decrypted."
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (Exception e) {
|
|
224
|
+
android.util.Log.e(
|
|
225
|
+
"OtaKit",
|
|
226
|
+
"Failed to parse bundleKeys. Encrypted bundles cannot be decrypted.",
|
|
227
|
+
e
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
190
231
|
this.appReadyTimeoutMs = Math.max(1000, getConfig().getInt("appReadyTimeout", 10_000));
|
|
191
232
|
this.checkIntervalMs = getConfig().getInt("checkInterval", 600_000);
|
|
192
233
|
|
|
@@ -290,14 +331,20 @@ public class UpdaterPlugin extends Plugin {
|
|
|
290
331
|
return;
|
|
291
332
|
}
|
|
292
333
|
executeAutomaticUpdate("runtime apply-staged fallback", () -> {
|
|
293
|
-
downloadLatest(false, null);
|
|
334
|
+
DownloadResolution result = downloadLatest(false, null);
|
|
294
335
|
resolveCurrentRuntimeKey();
|
|
336
|
+
if (result.isForcedStaged()) {
|
|
337
|
+
requireApplyStaged(true);
|
|
338
|
+
}
|
|
295
339
|
});
|
|
296
340
|
return;
|
|
297
341
|
case SHADOW:
|
|
298
342
|
executeAutomaticUpdate("runtime shadow", () -> {
|
|
299
|
-
downloadLatest(false, null);
|
|
343
|
+
DownloadResolution result = downloadLatest(false, null);
|
|
300
344
|
resolveCurrentRuntimeKey();
|
|
345
|
+
if (result.isForcedStaged()) {
|
|
346
|
+
requireApplyStaged(true);
|
|
347
|
+
}
|
|
301
348
|
});
|
|
302
349
|
return;
|
|
303
350
|
case IMMEDIATE:
|
|
@@ -327,10 +374,20 @@ public class UpdaterPlugin extends Plugin {
|
|
|
327
374
|
android.util.Log.w("OtaKit", "launch apply-staged failed", e);
|
|
328
375
|
return;
|
|
329
376
|
}
|
|
330
|
-
executeAutomaticUpdate("launch apply-staged fallback", () ->
|
|
377
|
+
executeAutomaticUpdate("launch apply-staged fallback", () -> {
|
|
378
|
+
DownloadResolution result = downloadLatest(false, null);
|
|
379
|
+
if (result.isForcedStaged()) {
|
|
380
|
+
requireApplyStaged(true);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
331
383
|
return;
|
|
332
384
|
case SHADOW:
|
|
333
|
-
executeAutomaticUpdate("launch shadow", () ->
|
|
385
|
+
executeAutomaticUpdate("launch shadow", () -> {
|
|
386
|
+
DownloadResolution result = downloadLatest(false, null);
|
|
387
|
+
if (result.isForcedStaged()) {
|
|
388
|
+
requireApplyStaged(true);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
334
391
|
return;
|
|
335
392
|
case IMMEDIATE:
|
|
336
393
|
executeAutomaticUpdate("launch immediate", () -> {
|
|
@@ -352,11 +409,19 @@ public class UpdaterPlugin extends Plugin {
|
|
|
352
409
|
if (applyStaged(true)) {
|
|
353
410
|
return;
|
|
354
411
|
}
|
|
355
|
-
downloadLatest(true, null);
|
|
412
|
+
DownloadResolution result = downloadLatest(true, null);
|
|
413
|
+
if (result.isForcedStaged()) {
|
|
414
|
+
requireApplyStaged(true);
|
|
415
|
+
}
|
|
356
416
|
});
|
|
357
417
|
return;
|
|
358
418
|
case SHADOW:
|
|
359
|
-
executeAutomaticUpdate("resume shadow", () ->
|
|
419
|
+
executeAutomaticUpdate("resume shadow", () -> {
|
|
420
|
+
DownloadResolution result = downloadLatest(true, null);
|
|
421
|
+
if (result.isForcedStaged()) {
|
|
422
|
+
requireApplyStaged(true);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
360
425
|
return;
|
|
361
426
|
case IMMEDIATE:
|
|
362
427
|
executeAutomaticUpdate("resume immediate", () -> {
|
|
@@ -512,6 +577,11 @@ public class UpdaterPlugin extends Plugin {
|
|
|
512
577
|
coordinator.cleanupBundles(preparation.cleanupBundleIds);
|
|
513
578
|
if (preparation.eventPayload != null) {
|
|
514
579
|
sendDeviceEvent(preparation.eventPayload);
|
|
580
|
+
// eventPayload is non-null only on a genuine trial -> success transition,
|
|
581
|
+
// so repeat notifyAppReady() calls never double-emit.
|
|
582
|
+
JSObject appliedData = new JSObject();
|
|
583
|
+
appliedData.put("bundle", store.getCurrentBundle().toJSObject());
|
|
584
|
+
emitEvent("updateApplied", appliedData);
|
|
515
585
|
}
|
|
516
586
|
call.resolve();
|
|
517
587
|
}
|
|
@@ -526,6 +596,63 @@ public class UpdaterPlugin extends Plugin {
|
|
|
526
596
|
call.resolve(failed.toJSObject());
|
|
527
597
|
}
|
|
528
598
|
|
|
599
|
+
@PluginMethod
|
|
600
|
+
public void setChannel(PluginCall call) {
|
|
601
|
+
Object raw = call.getData().opt("channel");
|
|
602
|
+
if (raw == null || raw == org.json.JSONObject.NULL) {
|
|
603
|
+
store.setOverrideChannel(null);
|
|
604
|
+
call.resolve();
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (!(raw instanceof String)) {
|
|
608
|
+
call.reject("channel must be a string or null");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
String name = (String) raw;
|
|
612
|
+
if (!isValidChannelName(name)) {
|
|
613
|
+
call.reject(
|
|
614
|
+
"Invalid channel name '" +
|
|
615
|
+
name +
|
|
616
|
+
"': use 1-64 letters, numbers, '.', '_' or '-' (reserved names: base, default)"
|
|
617
|
+
);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
store.setOverrideChannel(name);
|
|
621
|
+
call.resolve();
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
@PluginMethod
|
|
625
|
+
public void getChannel(PluginCall call) {
|
|
626
|
+
JSObject result = new JSObject();
|
|
627
|
+
String override = store.getOverrideChannel();
|
|
628
|
+
if (override != null) {
|
|
629
|
+
result.put("channel", override);
|
|
630
|
+
result.put("source", "override");
|
|
631
|
+
call.resolve(result);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
result.put("channel", channel != null ? channel : org.json.JSONObject.NULL);
|
|
635
|
+
result.put("source", "config");
|
|
636
|
+
call.resolve(result);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Mirrors the server's isValidChannelName (console/lib/validation.ts):
|
|
641
|
+
* charset regex plus reserved names. The channel is interpolated into the
|
|
642
|
+
* manifest CDN path, so anything outside this charset (or a ".." sequence)
|
|
643
|
+
* is rejected before it is persisted or used.
|
|
644
|
+
*/
|
|
645
|
+
private boolean isValidChannelName(String name) {
|
|
646
|
+
if (!CHANNEL_NAME_PATTERN.matcher(name).matches()) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
if (name.contains("..") || ".".equals(name)) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
String lower = name.toLowerCase(java.util.Locale.ROOT);
|
|
653
|
+
return !"base".equals(lower) && !"default".equals(lower);
|
|
654
|
+
}
|
|
655
|
+
|
|
529
656
|
private ManifestClient.LatestManifest fetchLatest(String channel) throws Exception {
|
|
530
657
|
if (appId == null || appId.trim().isEmpty()) {
|
|
531
658
|
throw new IllegalStateException("Missing appId in plugin config");
|
|
@@ -558,6 +685,10 @@ public class UpdaterPlugin extends Plugin {
|
|
|
558
685
|
|
|
559
686
|
CheckResolution resolution = classifyLatestManifest(latest, targetChannel);
|
|
560
687
|
|
|
688
|
+
if ("update_available".equals(resolution.kind) && resolution.latest != null) {
|
|
689
|
+
emitEvent("updateAvailable", manifestToJSObject(resolution.latest));
|
|
690
|
+
}
|
|
691
|
+
|
|
561
692
|
if (respectInterval) {
|
|
562
693
|
recordCheckTimestamp();
|
|
563
694
|
}
|
|
@@ -572,10 +703,13 @@ public class UpdaterPlugin extends Plugin {
|
|
|
572
703
|
case "no_update":
|
|
573
704
|
return DownloadResolution.noUpdate();
|
|
574
705
|
case "already_staged":
|
|
575
|
-
return DownloadResolution.staged(result.bundle);
|
|
706
|
+
return DownloadResolution.staged(result.bundle, result.latest.forceImmediate);
|
|
576
707
|
case "update_available":
|
|
577
708
|
try {
|
|
578
|
-
return DownloadResolution.staged(
|
|
709
|
+
return DownloadResolution.staged(
|
|
710
|
+
downloadLatestManifest(result.latest, targetChannel),
|
|
711
|
+
result.latest.forceImmediate
|
|
712
|
+
);
|
|
579
713
|
} catch (Exception e) {
|
|
580
714
|
if (!isExpiredURLError(e)) {
|
|
581
715
|
throw e;
|
|
@@ -591,10 +725,14 @@ public class UpdaterPlugin extends Plugin {
|
|
|
591
725
|
case "no_update":
|
|
592
726
|
return DownloadResolution.noUpdate();
|
|
593
727
|
case "already_staged":
|
|
594
|
-
return DownloadResolution.staged(
|
|
728
|
+
return DownloadResolution.staged(
|
|
729
|
+
refreshedResolution.bundle,
|
|
730
|
+
refreshedResolution.latest.forceImmediate
|
|
731
|
+
);
|
|
595
732
|
case "update_available":
|
|
596
733
|
return DownloadResolution.staged(
|
|
597
|
-
downloadLatestManifest(refreshedResolution.latest, targetChannel)
|
|
734
|
+
downloadLatestManifest(refreshedResolution.latest, targetChannel),
|
|
735
|
+
refreshedResolution.latest.forceImmediate
|
|
598
736
|
);
|
|
599
737
|
default:
|
|
600
738
|
throw new IllegalStateException(
|
|
@@ -665,11 +803,15 @@ public class UpdaterPlugin extends Plugin {
|
|
|
665
803
|
int expectedSize,
|
|
666
804
|
String runtimeVersion,
|
|
667
805
|
String channel,
|
|
668
|
-
String releaseId
|
|
806
|
+
String releaseId,
|
|
807
|
+
ManifestClient.ManifestEncryption encryption
|
|
669
808
|
) throws Exception {
|
|
670
809
|
// Check disk space before downloading
|
|
671
810
|
if (expectedSize > 0) {
|
|
672
|
-
|
|
811
|
+
// zip + extracted + buffer; encrypted bundles keep an extra decrypted
|
|
812
|
+
// zip copy on disk between decrypt and extract.
|
|
813
|
+
double multiplier = encryption != null ? 3.5 : 2.5;
|
|
814
|
+
long requiredSpace = (long) (expectedSize * multiplier);
|
|
673
815
|
long availableSpace = getFreeDiskSpace();
|
|
674
816
|
if (availableSpace < requiredSpace) {
|
|
675
817
|
sendDeviceEvent(
|
|
@@ -680,19 +822,50 @@ public class UpdaterPlugin extends Plugin {
|
|
|
680
822
|
releaseId,
|
|
681
823
|
"insufficient_disk_space"
|
|
682
824
|
);
|
|
825
|
+
emitEvent(
|
|
826
|
+
"downloadFailed",
|
|
827
|
+
failureEventData(version, runtimeVersion, channel, releaseId, "insufficient_disk_space")
|
|
828
|
+
);
|
|
683
829
|
throw new IllegalStateException("Insufficient disk space");
|
|
684
830
|
}
|
|
685
831
|
}
|
|
686
832
|
|
|
687
833
|
File downloadedZip = null;
|
|
834
|
+
File decryptedZip = null;
|
|
688
835
|
File extractedDirectory = null;
|
|
689
836
|
|
|
690
837
|
try {
|
|
691
838
|
downloadedZip = downloadZip(url);
|
|
839
|
+
// The manifest sha256 covers the downloaded object as-is — the
|
|
840
|
+
// ciphertext when the bundle is encrypted.
|
|
692
841
|
if (!HashUtils.verify(downloadedZip, expectedSha256)) {
|
|
693
842
|
throw new IllegalStateException("Downloaded bundle hash mismatch");
|
|
694
843
|
}
|
|
695
844
|
|
|
845
|
+
File zipToExtract = downloadedZip;
|
|
846
|
+
if (encryption != null) {
|
|
847
|
+
byte[] kek = bundleKeys.get(encryption.kid);
|
|
848
|
+
if (kek == null) {
|
|
849
|
+
throw new IllegalStateException("no matching bundle key (kid " + encryption.kid + ")");
|
|
850
|
+
}
|
|
851
|
+
byte[] dek = BundleCrypto.unwrapDek(
|
|
852
|
+
kek,
|
|
853
|
+
android.util.Base64.decode(encryption.wrapNonce, android.util.Base64.DEFAULT),
|
|
854
|
+
android.util.Base64.decode(encryption.wrappedDek, android.util.Base64.DEFAULT)
|
|
855
|
+
);
|
|
856
|
+
decryptedZip = new File(
|
|
857
|
+
getContext().getCacheDir(),
|
|
858
|
+
"otakit-decrypted-" + System.currentTimeMillis() + ".zip"
|
|
859
|
+
);
|
|
860
|
+
BundleCrypto.decryptFile(
|
|
861
|
+
dek,
|
|
862
|
+
android.util.Base64.decode(encryption.nonce, android.util.Base64.DEFAULT),
|
|
863
|
+
downloadedZip,
|
|
864
|
+
decryptedZip
|
|
865
|
+
);
|
|
866
|
+
zipToExtract = decryptedZip;
|
|
867
|
+
}
|
|
868
|
+
|
|
696
869
|
extractedDirectory = new File(
|
|
697
870
|
getContext().getCacheDir(),
|
|
698
871
|
"otakit-extract-" + System.currentTimeMillis()
|
|
@@ -701,7 +874,7 @@ public class UpdaterPlugin extends Plugin {
|
|
|
701
874
|
throw new IllegalStateException("Cannot create temporary extraction directory");
|
|
702
875
|
}
|
|
703
876
|
|
|
704
|
-
zipUtils.extractSecurely(
|
|
877
|
+
zipUtils.extractSecurely(zipToExtract, extractedDirectory);
|
|
705
878
|
File bundleRoot = resolveBundleRoot(extractedDirectory);
|
|
706
879
|
|
|
707
880
|
String bundleId = buildBundleId(version, releaseId, expectedSha256);
|
|
@@ -726,6 +899,9 @@ public class UpdaterPlugin extends Plugin {
|
|
|
726
899
|
coordinator.cleanupBundles(cleanupBundleIds);
|
|
727
900
|
|
|
728
901
|
sendDeviceEvent("downloaded", version, runtimeVersion, channel, releaseId, null);
|
|
902
|
+
JSObject stagedData = new JSObject();
|
|
903
|
+
stagedData.put("bundle", info.toJSObject());
|
|
904
|
+
emitEvent("updateStaged", stagedData);
|
|
729
905
|
return info;
|
|
730
906
|
} catch (Exception e) {
|
|
731
907
|
sendDeviceEvent(
|
|
@@ -736,12 +912,20 @@ public class UpdaterPlugin extends Plugin {
|
|
|
736
912
|
releaseId,
|
|
737
913
|
e.getMessage()
|
|
738
914
|
);
|
|
915
|
+
emitEvent(
|
|
916
|
+
"downloadFailed",
|
|
917
|
+
failureEventData(version, runtimeVersion, channel, releaseId, failureReason(e))
|
|
918
|
+
);
|
|
739
919
|
throw e;
|
|
740
920
|
} finally {
|
|
741
921
|
if (downloadedZip != null && downloadedZip.exists()) {
|
|
742
922
|
//noinspection ResultOfMethodCallIgnored
|
|
743
923
|
downloadedZip.delete();
|
|
744
924
|
}
|
|
925
|
+
if (decryptedZip != null && decryptedZip.exists()) {
|
|
926
|
+
//noinspection ResultOfMethodCallIgnored
|
|
927
|
+
decryptedZip.delete();
|
|
928
|
+
}
|
|
745
929
|
if (extractedDirectory != null && extractedDirectory.exists()) {
|
|
746
930
|
try {
|
|
747
931
|
deleteRecursively(extractedDirectory);
|
|
@@ -856,6 +1040,18 @@ public class UpdaterPlugin extends Plugin {
|
|
|
856
1040
|
coordinator.cleanupBundles(preparation.cleanupBundleIds);
|
|
857
1041
|
if (preparation.eventPayload != null) {
|
|
858
1042
|
sendDeviceEvent(preparation.eventPayload);
|
|
1043
|
+
emitEvent(
|
|
1044
|
+
"rollback",
|
|
1045
|
+
failureEventData(
|
|
1046
|
+
preparation.eventPayload.bundleVersion != null
|
|
1047
|
+
? preparation.eventPayload.bundleVersion
|
|
1048
|
+
: "",
|
|
1049
|
+
preparation.eventPayload.runtimeVersion,
|
|
1050
|
+
preparation.eventPayload.channel,
|
|
1051
|
+
preparation.eventPayload.releaseId,
|
|
1052
|
+
reason
|
|
1053
|
+
)
|
|
1054
|
+
);
|
|
859
1055
|
}
|
|
860
1056
|
|
|
861
1057
|
try {
|
|
@@ -935,6 +1131,7 @@ public class UpdaterPlugin extends Plugin {
|
|
|
935
1131
|
object.put("runtimeVersion", latest.runtimeVersion);
|
|
936
1132
|
}
|
|
937
1133
|
object.put("releaseId", latest.releaseId);
|
|
1134
|
+
object.put("forceImmediate", latest.forceImmediate);
|
|
938
1135
|
return object;
|
|
939
1136
|
}
|
|
940
1137
|
|
|
@@ -949,7 +1146,8 @@ public class UpdaterPlugin extends Plugin {
|
|
|
949
1146
|
latest.size,
|
|
950
1147
|
latest.runtimeVersion,
|
|
951
1148
|
targetChannel,
|
|
952
|
-
latest.releaseId
|
|
1149
|
+
latest.releaseId,
|
|
1150
|
+
latest.encryption
|
|
953
1151
|
);
|
|
954
1152
|
}
|
|
955
1153
|
|
|
@@ -1092,7 +1290,67 @@ public class UpdaterPlugin extends Plugin {
|
|
|
1092
1290
|
|
|
1093
1291
|
private String resolveTargetChannel(String channel) {
|
|
1094
1292
|
String resolved = trimToNull(channel);
|
|
1095
|
-
|
|
1293
|
+
if (resolved != null) {
|
|
1294
|
+
return resolved;
|
|
1295
|
+
}
|
|
1296
|
+
String override = store.getOverrideChannel();
|
|
1297
|
+
if (override != null) {
|
|
1298
|
+
return override;
|
|
1299
|
+
}
|
|
1300
|
+
return this.channel;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
* Emit a JS lifecycle event. notifyListeners marshals to the bridge
|
|
1305
|
+
* safely from any thread, so no manual dispatch is needed.
|
|
1306
|
+
*/
|
|
1307
|
+
private void emitEvent(String name, JSObject data) {
|
|
1308
|
+
notifyListeners(name, data);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
private JSObject failureEventData(
|
|
1312
|
+
String version,
|
|
1313
|
+
String runtimeVersion,
|
|
1314
|
+
String channel,
|
|
1315
|
+
String releaseId,
|
|
1316
|
+
String reason
|
|
1317
|
+
) {
|
|
1318
|
+
JSObject data = new JSObject();
|
|
1319
|
+
data.put("version", version);
|
|
1320
|
+
data.put("reason", reason);
|
|
1321
|
+
if (trimToNull(runtimeVersion) != null) {
|
|
1322
|
+
data.put("runtimeVersion", runtimeVersion.trim());
|
|
1323
|
+
}
|
|
1324
|
+
if (trimToNull(channel) != null) {
|
|
1325
|
+
data.put("channel", channel.trim());
|
|
1326
|
+
}
|
|
1327
|
+
if (trimToNull(releaseId) != null) {
|
|
1328
|
+
data.put("releaseId", releaseId.trim());
|
|
1329
|
+
}
|
|
1330
|
+
return data;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/** Map a native error to a stable event reason string. */
|
|
1334
|
+
private String failureReason(Exception e) {
|
|
1335
|
+
String message = e.getMessage() != null ? e.getMessage().toLowerCase() : "";
|
|
1336
|
+
if (message.contains("hash mismatch")) {
|
|
1337
|
+
return "hash_mismatch";
|
|
1338
|
+
}
|
|
1339
|
+
if (message.contains("disk space")) {
|
|
1340
|
+
return "insufficient_disk_space";
|
|
1341
|
+
}
|
|
1342
|
+
if (message.contains("index.html")) {
|
|
1343
|
+
return "invalid_bundle";
|
|
1344
|
+
}
|
|
1345
|
+
// ZipUtils throws SecurityException for guard violations and prefixes
|
|
1346
|
+
// its messages with "Zip ". Don't match ".zip" anywhere in the message:
|
|
1347
|
+
// network failures often carry the temp file path (…/otakit-….zip).
|
|
1348
|
+
if (
|
|
1349
|
+
e instanceof SecurityException || message.startsWith("zip ") || message.contains("extract")
|
|
1350
|
+
) {
|
|
1351
|
+
return "extract_failed";
|
|
1352
|
+
}
|
|
1353
|
+
return "download_failed";
|
|
1096
1354
|
}
|
|
1097
1355
|
|
|
1098
1356
|
private void sendDeviceEvent(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PluginListenerHandle } from '@capacitor/core';
|
|
1
2
|
/**
|
|
2
3
|
* Bundle status enum.
|
|
3
4
|
*/
|
|
@@ -44,6 +45,12 @@ export interface LatestVersion {
|
|
|
44
45
|
size: number;
|
|
45
46
|
/** Release history ID associated with this manifest */
|
|
46
47
|
releaseId: string;
|
|
48
|
+
/**
|
|
49
|
+
* True when the release is marked force-immediate: automatic flows apply
|
|
50
|
+
* and reload it on the next lifecycle event regardless of shadow or
|
|
51
|
+
* apply-staged policies. Manual API behavior is unchanged.
|
|
52
|
+
*/
|
|
53
|
+
forceImmediate?: boolean;
|
|
47
54
|
}
|
|
48
55
|
export interface OtaKitState {
|
|
49
56
|
current: BundleInfo;
|
|
@@ -56,6 +63,12 @@ export interface OtaKitManifestKey {
|
|
|
56
63
|
kid: string;
|
|
57
64
|
key: string;
|
|
58
65
|
}
|
|
66
|
+
export interface OtaKitBundleKey {
|
|
67
|
+
/** Key ID: first 16 hex chars of sha256(key). Printed by `otakit generate-encryption-key`. */
|
|
68
|
+
kid: string;
|
|
69
|
+
/** 256-bit AES key, base64. Inject from an env var at build time; do not commit. */
|
|
70
|
+
key: string;
|
|
71
|
+
}
|
|
59
72
|
export interface CheckNoUpdateResult {
|
|
60
73
|
kind: 'no_update';
|
|
61
74
|
}
|
|
@@ -76,6 +89,46 @@ export interface DownloadStagedResult {
|
|
|
76
89
|
bundle: BundleInfo;
|
|
77
90
|
}
|
|
78
91
|
export type DownloadResult = DownloadNoUpdateResult | DownloadStagedResult;
|
|
92
|
+
export interface ChannelInfo {
|
|
93
|
+
/** The effective release channel, or null for the base channel. */
|
|
94
|
+
channel: string | null;
|
|
95
|
+
/** Where the effective channel comes from: a runtime override or static config. */
|
|
96
|
+
source: 'override' | 'config';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Payload for the `updateStaged` event: a bundle was downloaded, verified,
|
|
100
|
+
* and staged, ready to apply.
|
|
101
|
+
*/
|
|
102
|
+
export interface UpdateStagedEvent {
|
|
103
|
+
bundle: BundleInfo;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Payload for the `updateApplied` event: a newly activated bundle was
|
|
107
|
+
* confirmed healthy via notifyAppReady().
|
|
108
|
+
*/
|
|
109
|
+
export interface UpdateAppliedEvent {
|
|
110
|
+
bundle: BundleInfo;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Payload for the `downloadFailed` and `rollback` events.
|
|
114
|
+
*/
|
|
115
|
+
export interface UpdateFailedEvent {
|
|
116
|
+
version: string;
|
|
117
|
+
runtimeVersion?: string;
|
|
118
|
+
releaseId?: string;
|
|
119
|
+
channel?: string;
|
|
120
|
+
/** Stable failure reason, e.g. "hash_mismatch", "insufficient_disk_space", "notify_timeout". */
|
|
121
|
+
reason: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Update lifecycle events emitted by the plugin.
|
|
125
|
+
*
|
|
126
|
+
* Events fire only while the app process is alive. Reconcile with
|
|
127
|
+
* getState() and getLastFailure() on startup for anything that happened
|
|
128
|
+
* while no listener was attached (e.g. a bundle staged in a previous
|
|
129
|
+
* session, or a startup rollback).
|
|
130
|
+
*/
|
|
131
|
+
export type OtaKitEventName = 'updateAvailable' | 'updateStaged' | 'updateApplied' | 'downloadFailed' | 'rollback';
|
|
79
132
|
/**
|
|
80
133
|
* Plugin configuration for capacitor.config.ts.
|
|
81
134
|
*/
|
|
@@ -109,6 +162,11 @@ export interface OtaKitConfig {
|
|
|
109
162
|
cdnUrl?: string;
|
|
110
163
|
/** Custom manifest verification keys for self-hosted or custom trust. */
|
|
111
164
|
manifestKeys?: OtaKitManifestKey[];
|
|
165
|
+
/**
|
|
166
|
+
* Bundle decryption keys for end-to-end encrypted bundles.
|
|
167
|
+
* Array to allow rotation: ship old + new keys together during a transition.
|
|
168
|
+
*/
|
|
169
|
+
bundleKeys?: OtaKitBundleKey[];
|
|
112
170
|
/** Allow HTTP only for localhost development. Defaults to false. */
|
|
113
171
|
allowInsecureUrls?: boolean;
|
|
114
172
|
}
|
|
@@ -153,6 +211,40 @@ export interface OtaKitPlugin {
|
|
|
153
211
|
* Returns null if no failure has occurred.
|
|
154
212
|
*/
|
|
155
213
|
getLastFailure(): Promise<BundleInfo | null>;
|
|
214
|
+
/**
|
|
215
|
+
* Override the release channel at runtime (e.g. a "Join beta" toggle).
|
|
216
|
+
* Pass null to clear the override and return to the configured channel.
|
|
217
|
+
*
|
|
218
|
+
* The override is persisted across launches and takes effect on the next
|
|
219
|
+
* check/download/automatic cycle — it does not trigger anything by itself.
|
|
220
|
+
* Rejects invalid channel names without persisting.
|
|
221
|
+
*/
|
|
222
|
+
setChannel(options: {
|
|
223
|
+
channel: string | null;
|
|
224
|
+
}): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* Get the effective release channel and where it comes from
|
|
227
|
+
* (a runtime override or the static plugin config).
|
|
228
|
+
*/
|
|
229
|
+
getChannel(): Promise<ChannelInfo>;
|
|
230
|
+
/**
|
|
231
|
+
* Subscribe to update lifecycle events.
|
|
232
|
+
*
|
|
233
|
+
* Events fire only while the app is running. On startup, reconcile with
|
|
234
|
+
* getState() (anything staged while not listening) and getLastFailure()
|
|
235
|
+
* (startup rollbacks happen before JS boots and cannot reach a listener).
|
|
236
|
+
* apply() reloads the WebView and destroys the JS context, so attach
|
|
237
|
+
* `updateApplied` / `rollback` listeners early in app startup.
|
|
238
|
+
*/
|
|
239
|
+
addListener(eventName: 'updateAvailable', listenerFunc: (latest: LatestVersion) => void): Promise<PluginListenerHandle>;
|
|
240
|
+
addListener(eventName: 'updateStaged', listenerFunc: (event: UpdateStagedEvent) => void): Promise<PluginListenerHandle>;
|
|
241
|
+
addListener(eventName: 'updateApplied', listenerFunc: (event: UpdateAppliedEvent) => void): Promise<PluginListenerHandle>;
|
|
242
|
+
addListener(eventName: 'downloadFailed', listenerFunc: (event: UpdateFailedEvent) => void): Promise<PluginListenerHandle>;
|
|
243
|
+
addListener(eventName: 'rollback', listenerFunc: (event: UpdateFailedEvent) => void): Promise<PluginListenerHandle>;
|
|
244
|
+
/**
|
|
245
|
+
* Remove all registered event listeners.
|
|
246
|
+
*/
|
|
247
|
+
removeAllListeners(): Promise<void>;
|
|
156
248
|
}
|
|
157
249
|
export interface OtaKitBridgePlugin {
|
|
158
250
|
getState(): Promise<OtaKitState>;
|
|
@@ -162,5 +254,11 @@ export interface OtaKitBridgePlugin {
|
|
|
162
254
|
update(): Promise<void>;
|
|
163
255
|
notifyAppReady(): Promise<void>;
|
|
164
256
|
getLastFailure(): Promise<BundleInfo | null>;
|
|
257
|
+
setChannel(options: {
|
|
258
|
+
channel: string | null;
|
|
259
|
+
}): Promise<void>;
|
|
260
|
+
getChannel(): Promise<ChannelInfo>;
|
|
261
|
+
addListener(eventName: OtaKitEventName, listenerFunc: (event: unknown) => void): Promise<PluginListenerHandle>;
|
|
262
|
+
removeAllListeners(): Promise<void>;
|
|
165
263
|
}
|
|
166
264
|
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,YAAY;IACtB,+BAA+B;IAC/B,OAAO,YAAY;IACnB,iDAAiD;IACjD,OAAO,YAAY;IACnB,mCAAmC;IACnC,KAAK,UAAU;IACf,wBAAwB;IACxB,OAAO,YAAY;IACnB,yDAAyD;IACzD,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAN,IAAY,YAWX;AAXD,WAAY,YAAY;IACtB,+BAA+B;IAC/B,mCAAmB,CAAA;IACnB,iDAAiD;IACjD,mCAAmB,CAAA;IACnB,mCAAmC;IACnC,+BAAe,CAAA;IACf,wBAAwB;IACxB,mCAAmB,CAAA;IACnB,yDAAyD;IACzD,+BAAe,CAAA;AACjB,CAAC,EAXW,YAAY,KAAZ,YAAY,QAWvB"}
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,YAAY,EAA+B,MAAM,eAAe,CAAC;AAqBnG,QAAA,MAAM,MAAM,EAAE,YAgBb,CAAC;AAEF,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -23,6 +23,12 @@ const OtaKit = {
|
|
|
23
23
|
update: () => NativeOtaKit.update(),
|
|
24
24
|
notifyAppReady: () => NativeOtaKit.notifyAppReady(),
|
|
25
25
|
getLastFailure: async () => normalizeNullable(await NativeOtaKit.getLastFailure()),
|
|
26
|
+
setChannel: (options) => NativeOtaKit.setChannel(options),
|
|
27
|
+
getChannel: () => NativeOtaKit.getChannel(),
|
|
28
|
+
// NativeOtaKit is the registerPlugin proxy, which implements Capacitor's
|
|
29
|
+
// listener API; this plain-object wrapper must forward it explicitly.
|
|
30
|
+
addListener: ((eventName, listenerFunc) => NativeOtaKit.addListener(eventName, listenerFunc)),
|
|
31
|
+
removeAllListeners: () => NativeOtaKit.removeAllListeners(),
|
|
26
32
|
};
|
|
27
33
|
export * from './definitions';
|
|
28
34
|
export { OtaKit };
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,QAAQ,EAAE;IAChE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;CAC1D,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,aAAa,CAAC,GAAY;IACjC,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAI,KAAQ;IACpC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7C,CAAC;AAED,MAAM,MAAM,GAAiB;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE;IACvC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE;IACjC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE;IACvC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE;IACjC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;IACnC,cAAc,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE;IACnD,cAAc,EAAE,KAAK,IAAgC,EAAE,CACrD,iBAAiB,CAAC,MAAM,YAAY,CAAC,cAAc,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,QAAQ,EAAE;IAChE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;CAC1D,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,aAAa,CAAC,GAAY;IACjC,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAI,KAAQ;IACpC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7C,CAAC;AAED,MAAM,MAAM,GAAiB;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE;IACvC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE;IACjC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE;IACvC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE;IACjC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;IACnC,cAAc,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE;IACnD,cAAc,EAAE,KAAK,IAAgC,EAAE,CACrD,iBAAiB,CAAC,MAAM,YAAY,CAAC,cAAc,EAAE,CAAC;IACxD,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC;IACzD,UAAU,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE;IAC3C,yEAAyE;IACzE,sEAAsE;IACtE,WAAW,EAAE,CAAC,CAAC,SAA0B,EAAE,YAAsC,EAAE,EAAE,CACnF,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAgC;IACnF,kBAAkB,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE;CAC5D,CAAC;AAEF,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,CAAC"}
|