@capawesome/cordova-live-update 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1113 -0
  3. package/dist/docs.json +1654 -0
  4. package/dist/esm/definitions.d.ts +788 -0
  5. package/dist/esm/definitions.js +7 -0
  6. package/dist/esm/definitions.js.map +1 -0
  7. package/dist/esm/exec.d.ts +1 -0
  8. package/dist/esm/exec.js +8 -0
  9. package/dist/esm/exec.js.map +1 -0
  10. package/dist/esm/index.d.ts +4 -0
  11. package/dist/esm/index.js +46 -0
  12. package/dist/esm/index.js.map +1 -0
  13. package/dist/plugin.js +56 -0
  14. package/dist/plugin.js.map +1 -0
  15. package/package.json +93 -0
  16. package/plugin.xml +268 -0
  17. package/src/android/capawesome-cordova-live-update.gradle +12 -0
  18. package/src/android/capawesome-live-update.xml +5 -0
  19. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdate.java +1480 -0
  20. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdateConfig.java +105 -0
  21. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdateHttpClient.java +114 -0
  22. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdatePathHandler.java +96 -0
  23. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdatePlugin.java +550 -0
  24. package/src/android/io/capawesome/cordova/plugins/liveupdate/LiveUpdatePreferences.java +151 -0
  25. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/Manifest.java +58 -0
  26. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/ManifestItem.java +37 -0
  27. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/api/GetChannelsResponseItem.java +28 -0
  28. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/api/GetLatestBundleResponse.java +74 -0
  29. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/events/DownloadBundleProgressEvent.java +33 -0
  30. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/events/NextBundleSetEvent.java +26 -0
  31. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/DeleteBundleOptions.java +18 -0
  32. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/DownloadBundleOptions.java +66 -0
  33. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/FetchChannelsOptions.java +39 -0
  34. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/FetchLatestBundleOptions.java +25 -0
  35. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/SetChannelOptions.java +18 -0
  36. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/SetConfigOptions.java +20 -0
  37. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/SetCustomIdOptions.java +18 -0
  38. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/SetNextBundleOptions.java +21 -0
  39. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/options/SyncOptions.java +25 -0
  40. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/ChannelResult.java +29 -0
  41. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/FetchChannelsResult.java +29 -0
  42. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/FetchLatestBundleResult.java +69 -0
  43. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetBlockedBundlesResult.java +28 -0
  44. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetBundlesResult.java +28 -0
  45. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetChannelResult.java +22 -0
  46. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetConfigResult.java +40 -0
  47. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetCurrentBundleResult.java +22 -0
  48. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetCustomIdResult.java +22 -0
  49. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetDeviceIdResult.java +22 -0
  50. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetDownloadedBundlesResult.java +28 -0
  51. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetNextBundleResult.java +22 -0
  52. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetVersionCodeResult.java +21 -0
  53. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/GetVersionNameResult.java +22 -0
  54. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/IsSyncingResult.java +27 -0
  55. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/ReadyResult.java +32 -0
  56. package/src/android/io/capawesome/cordova/plugins/liveupdate/classes/results/SyncResult.java +22 -0
  57. package/src/android/io/capawesome/cordova/plugins/liveupdate/enums/ArtifactType.java +6 -0
  58. package/src/android/io/capawesome/cordova/plugins/liveupdate/interfaces/Callback.java +5 -0
  59. package/src/android/io/capawesome/cordova/plugins/liveupdate/interfaces/DownloadProgressCallback.java +5 -0
  60. package/src/android/io/capawesome/cordova/plugins/liveupdate/interfaces/EmptyCallback.java +5 -0
  61. package/src/android/io/capawesome/cordova/plugins/liveupdate/interfaces/NonEmptyCallback.java +7 -0
  62. package/src/android/io/capawesome/cordova/plugins/liveupdate/interfaces/Result.java +8 -0
  63. package/src/ios/LiveUpdate.swift +895 -0
  64. package/src/ios/LiveUpdateArtifactType.swift +4 -0
  65. package/src/ios/LiveUpdateChannelResult.swift +18 -0
  66. package/src/ios/LiveUpdateConfig.swift +11 -0
  67. package/src/ios/LiveUpdateDeleteBundleOptions.swift +13 -0
  68. package/src/ios/LiveUpdateDownloadBundleOptions.swift +41 -0
  69. package/src/ios/LiveUpdateDownloadBundleProgressEvent.swift +24 -0
  70. package/src/ios/LiveUpdateError.swift +62 -0
  71. package/src/ios/LiveUpdateFetchChannelsOptions.swift +25 -0
  72. package/src/ios/LiveUpdateFetchChannelsResult.swift +15 -0
  73. package/src/ios/LiveUpdateFetchLatestBundleOptions.swift +17 -0
  74. package/src/ios/LiveUpdateFetchLatestBundleResult.swift +42 -0
  75. package/src/ios/LiveUpdateGetBlockedBundlesResult.swift +15 -0
  76. package/src/ios/LiveUpdateGetBundlesResult.swift +15 -0
  77. package/src/ios/LiveUpdateGetChannelResult.swift +15 -0
  78. package/src/ios/LiveUpdateGetChannelsResponseItem.swift +4 -0
  79. package/src/ios/LiveUpdateGetConfigResult.swift +18 -0
  80. package/src/ios/LiveUpdateGetCurrentBundleResult.swift +15 -0
  81. package/src/ios/LiveUpdateGetCustomIdResult.swift +15 -0
  82. package/src/ios/LiveUpdateGetDeviceIdResult.swift +15 -0
  83. package/src/ios/LiveUpdateGetDownloadedBundlesResult.swift +15 -0
  84. package/src/ios/LiveUpdateGetLatestBundleResponse.swift +8 -0
  85. package/src/ios/LiveUpdateGetNextBundleResult.swift +15 -0
  86. package/src/ios/LiveUpdateGetVersionCodeResult.swift +15 -0
  87. package/src/ios/LiveUpdateGetVersionNameResult.swift +15 -0
  88. package/src/ios/LiveUpdateHttpClient.swift +58 -0
  89. package/src/ios/LiveUpdateIsSyncingResult.swift +15 -0
  90. package/src/ios/LiveUpdateManifest.swift +19 -0
  91. package/src/ios/LiveUpdateManifestItem.swift +5 -0
  92. package/src/ios/LiveUpdateNextBundleSetEvent.swift +15 -0
  93. package/src/ios/LiveUpdatePlugin.swift +521 -0
  94. package/src/ios/LiveUpdatePreferences.swift +116 -0
  95. package/src/ios/LiveUpdateReadyResult.swift +21 -0
  96. package/src/ios/LiveUpdateResult.swift +5 -0
  97. package/src/ios/LiveUpdateSchemeHandler.swift +286 -0
  98. package/src/ios/LiveUpdateSetChannelOptions.swift +13 -0
  99. package/src/ios/LiveUpdateSetConfigOptions.swift +13 -0
  100. package/src/ios/LiveUpdateSetCustomIdOptions.swift +13 -0
  101. package/src/ios/LiveUpdateSetNextBundleOptions.swift +13 -0
  102. package/src/ios/LiveUpdateSyncOptions.swift +17 -0
  103. package/src/ios/LiveUpdateSyncResult.swift +15 -0
@@ -0,0 +1,105 @@
1
+ package io.capawesome.cordova.plugins.liveupdate;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import java.security.Key;
6
+
7
+ public class LiveUpdateConfig {
8
+
9
+ @Nullable
10
+ private String appId = null;
11
+
12
+ private boolean autoBlockRolledBackBundles = false;
13
+
14
+ private boolean autoDeleteBundles = false;
15
+
16
+ @NonNull
17
+ private String autoUpdateStrategy = "none";
18
+
19
+ @Nullable
20
+ private String defaultChannel = null;
21
+
22
+ private int httpTimeout = 60000;
23
+
24
+ @Nullable
25
+ private String publicKey = null;
26
+
27
+ private int readyTimeout = 0;
28
+ private String serverDomain = "api.cloud.capawesome.io";
29
+
30
+ @Nullable
31
+ public String getAppId() {
32
+ return appId;
33
+ }
34
+
35
+ public boolean getAutoBlockRolledBackBundles() {
36
+ return autoBlockRolledBackBundles;
37
+ }
38
+
39
+ public boolean getAutoDeleteBundles() {
40
+ return autoDeleteBundles;
41
+ }
42
+
43
+ @NonNull
44
+ public String getAutoUpdateStrategy() {
45
+ return autoUpdateStrategy;
46
+ }
47
+
48
+ @Nullable
49
+ public String getDefaultChannel() {
50
+ return defaultChannel;
51
+ }
52
+
53
+ public int getHttpTimeout() {
54
+ return httpTimeout;
55
+ }
56
+
57
+ @Nullable
58
+ public String getPublicKey() {
59
+ return publicKey;
60
+ }
61
+
62
+ public int getReadyTimeout() {
63
+ return readyTimeout;
64
+ }
65
+
66
+ public String getServerDomain() {
67
+ return serverDomain;
68
+ }
69
+
70
+ public void setAppId(@Nullable String appId) {
71
+ this.appId = appId;
72
+ }
73
+
74
+ public void setAutoBlockRolledBackBundles(boolean autoBlockRolledBackBundles) {
75
+ this.autoBlockRolledBackBundles = autoBlockRolledBackBundles;
76
+ }
77
+
78
+ public void setAutoDeleteBundles(boolean autoDeleteBundles) {
79
+ this.autoDeleteBundles = autoDeleteBundles;
80
+ }
81
+
82
+ public void setAutoUpdateStrategy(@NonNull String autoUpdateStrategy) {
83
+ this.autoUpdateStrategy = autoUpdateStrategy;
84
+ }
85
+
86
+ public void setDefaultChannel(@Nullable String defaultChannel) {
87
+ this.defaultChannel = defaultChannel;
88
+ }
89
+
90
+ public void setHttpTimeout(int httpTimeout) {
91
+ this.httpTimeout = httpTimeout;
92
+ }
93
+
94
+ public void setPublicKey(@Nullable String publicKey) {
95
+ this.publicKey = publicKey;
96
+ }
97
+
98
+ public void setReadyTimeout(int readyTimeout) {
99
+ this.readyTimeout = readyTimeout;
100
+ }
101
+
102
+ public void setServerDomain(String serverDomain) {
103
+ this.serverDomain = serverDomain;
104
+ }
105
+ }
@@ -0,0 +1,114 @@
1
+ package io.capawesome.cordova.plugins.liveupdate;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import io.capawesome.cordova.plugins.liveupdate.interfaces.DownloadProgressCallback;
6
+ import io.capawesome.cordova.plugins.liveupdate.interfaces.EmptyCallback;
7
+ import io.capawesome.cordova.plugins.liveupdate.interfaces.NonEmptyCallback;
8
+ import java.io.File;
9
+ import java.io.IOException;
10
+ import java.util.concurrent.TimeUnit;
11
+ import okhttp3.Call;
12
+ import okhttp3.Callback;
13
+ import okhttp3.OkHttpClient;
14
+ import okhttp3.Request;
15
+ import okhttp3.Response;
16
+ import okhttp3.ResponseBody;
17
+ import okio.Buffer;
18
+ import okio.BufferedSink;
19
+ import okio.BufferedSource;
20
+ import okio.Okio;
21
+
22
+ public class LiveUpdateHttpClient {
23
+
24
+ @NonNull
25
+ private final LiveUpdateConfig config;
26
+
27
+ @Nullable
28
+ private String deviceId;
29
+
30
+ @NonNull
31
+ private final OkHttpClient okHttpClient;
32
+
33
+ @Nullable
34
+ public static String getChecksumFromResponse(Response response) {
35
+ String checksum = response.header("X-Checksum");
36
+ if (checksum == null) {
37
+ return null;
38
+ }
39
+ return checksum;
40
+ }
41
+
42
+ @Nullable
43
+ public static String getSignatureFromResponse(Response response) {
44
+ String signature = response.header("X-Signature");
45
+ if (signature == null) {
46
+ return null;
47
+ }
48
+ return signature;
49
+ }
50
+
51
+ public LiveUpdateHttpClient(@NonNull LiveUpdateConfig config) {
52
+ this.config = config;
53
+ int httpTimeout = config.getHttpTimeout();
54
+
55
+ // Increase max requests per host to allow multiple parallel downloads from the same host
56
+ okhttp3.Dispatcher dispatcher = new okhttp3.Dispatcher();
57
+ dispatcher.setMaxRequestsPerHost(30);
58
+
59
+ this.okHttpClient = new OkHttpClient.Builder()
60
+ .dispatcher(dispatcher)
61
+ .connectTimeout(httpTimeout, TimeUnit.MILLISECONDS)
62
+ .readTimeout(httpTimeout, TimeUnit.MILLISECONDS)
63
+ .writeTimeout(httpTimeout, TimeUnit.MILLISECONDS)
64
+ .build();
65
+ }
66
+
67
+ public void setDeviceId(@NonNull String deviceId) {
68
+ this.deviceId = deviceId;
69
+ }
70
+
71
+ public Call enqueue(String url, NonEmptyCallback<Response> callback) {
72
+ Request.Builder builder = new Request.Builder().url(url);
73
+ if (deviceId != null) {
74
+ builder.addHeader("X-Capawesome-Device-Id", deviceId);
75
+ }
76
+ Request request = builder.build();
77
+
78
+ Call call = okHttpClient.newCall(request);
79
+ call.enqueue(
80
+ new Callback() {
81
+ @Override
82
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
83
+ callback.success(response);
84
+ }
85
+
86
+ @Override
87
+ public void onFailure(@NonNull Call call, @NonNull IOException e) {
88
+ callback.error(new Exception(e));
89
+ }
90
+ }
91
+ );
92
+ return call;
93
+ }
94
+
95
+ public static void writeResponseBodyToFile(ResponseBody body, File file, @Nullable DownloadProgressCallback callback)
96
+ throws IOException {
97
+ long contentLength = body.contentLength();
98
+ BufferedSource source = body.source();
99
+ BufferedSink sink = Okio.buffer(Okio.sink(file));
100
+ Buffer sinkBuffer = sink.getBuffer();
101
+ long totalBytesRead = 0;
102
+ int bufferSize = 8 * 1024;
103
+ for (long bytesRead; (bytesRead = source.read(sinkBuffer, bufferSize)) != -1;) {
104
+ sink.emit();
105
+ totalBytesRead += bytesRead;
106
+ if (callback != null) {
107
+ callback.onProgress(totalBytesRead, contentLength);
108
+ }
109
+ }
110
+ sink.flush();
111
+ sink.close();
112
+ source.close();
113
+ }
114
+ }
@@ -0,0 +1,96 @@
1
+ package io.capawesome.cordova.plugins.liveupdate;
2
+
3
+ import android.util.Log;
4
+ import android.webkit.MimeTypeMap;
5
+ import android.webkit.WebResourceResponse;
6
+ import androidx.annotation.NonNull;
7
+ import androidx.annotation.Nullable;
8
+ import androidx.webkit.WebViewAssetLoader;
9
+ import java.io.File;
10
+ import java.io.FileInputStream;
11
+ import java.io.IOException;
12
+ import java.io.InputStream;
13
+ import java.util.concurrent.atomic.AtomicReference;
14
+
15
+ /**
16
+ * {@link WebViewAssetLoader.PathHandler} that serves files from the active live-update
17
+ * bundle directory when one is set. Returns {@code null} otherwise so that Cordova's
18
+ * default {@code www/} asset handler can serve the original APK assets.
19
+ */
20
+ public class LiveUpdatePathHandler implements WebViewAssetLoader.PathHandler {
21
+
22
+ private final AtomicReference<File> activeBundleDir = new AtomicReference<>(null);
23
+
24
+ public void setActiveBundleDir(@Nullable File dir) {
25
+ activeBundleDir.set(dir);
26
+ }
27
+
28
+ @Nullable
29
+ public File getActiveBundleDir() {
30
+ return activeBundleDir.get();
31
+ }
32
+
33
+ @Override
34
+ @Nullable
35
+ public WebResourceResponse handle(@NonNull String path) {
36
+ File baseDir = activeBundleDir.get();
37
+ if (baseDir == null) {
38
+ // No live bundle active — fall through to Cordova's default www/ handler.
39
+ return null;
40
+ }
41
+
42
+ String resolvedPath = path;
43
+ if (resolvedPath.isEmpty() || resolvedPath.endsWith("/")) {
44
+ resolvedPath = resolvedPath + "index.html";
45
+ }
46
+
47
+ File file = new File(baseDir, resolvedPath);
48
+
49
+ // Defense-in-depth against path traversal: ensure the resolved file is inside baseDir.
50
+ try {
51
+ String canonicalBase = baseDir.getCanonicalPath();
52
+ String canonicalFile = file.getCanonicalPath();
53
+ if (!canonicalFile.equals(canonicalBase) && !canonicalFile.startsWith(canonicalBase + File.separator)) {
54
+ return null;
55
+ }
56
+ } catch (IOException e) {
57
+ return null;
58
+ }
59
+
60
+ if (!file.isFile()) {
61
+ // Not in active bundle — let the default handler try.
62
+ return null;
63
+ }
64
+
65
+ try {
66
+ InputStream stream = new FileInputStream(file);
67
+ String mimeType = guessMimeType(resolvedPath);
68
+ return new WebResourceResponse(mimeType, null, stream);
69
+ } catch (IOException e) {
70
+ Log.e(LiveUpdatePlugin.TAG, "Failed to open bundle file: " + file.getAbsolutePath(), e);
71
+ return null;
72
+ }
73
+ }
74
+
75
+ private String guessMimeType(@NonNull String path) {
76
+ // Mirror Cordova's SystemWebViewClient logic so behavior is consistent
77
+ // whether we serve from the bundle or fall through to the default handler.
78
+ if (path.endsWith(".js") || path.endsWith(".mjs")) {
79
+ return "application/javascript";
80
+ }
81
+ if (path.endsWith(".wasm")) {
82
+ return "application/wasm";
83
+ }
84
+ String extension = MimeTypeMap.getFileExtensionFromUrl(path);
85
+ if (extension != null) {
86
+ String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
87
+ if (mime != null) {
88
+ return mime;
89
+ }
90
+ }
91
+ if (path.endsWith(".html") || path.endsWith(".htm")) {
92
+ return "text/html";
93
+ }
94
+ return "application/octet-stream";
95
+ }
96
+ }