@capgo/capacitor-updater 4.41.0 → 4.43.5

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 (67) hide show
  1. package/CapgoCapacitorUpdater.podspec +7 -5
  2. package/Package.swift +40 -0
  3. package/README.md +1913 -303
  4. package/android/build.gradle +41 -8
  5. package/android/proguard-rules.pro +45 -0
  6. package/android/src/main/AndroidManifest.xml +1 -3
  7. package/android/src/main/java/ee/forgr/capacitor_updater/AppLifecycleObserver.java +88 -0
  8. package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +223 -195
  9. package/android/src/main/java/ee/forgr/capacitor_updater/BundleStatus.java +23 -23
  10. package/android/src/main/java/ee/forgr/capacitor_updater/Callback.java +13 -0
  11. package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +2720 -1242
  12. package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +1854 -0
  13. package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +359 -121
  14. package/android/src/main/java/ee/forgr/capacitor_updater/DataManager.java +28 -0
  15. package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +44 -49
  16. package/android/src/main/java/ee/forgr/capacitor_updater/DelayUntilNext.java +4 -4
  17. package/android/src/main/java/ee/forgr/capacitor_updater/DelayUpdateUtils.java +296 -0
  18. package/android/src/main/java/ee/forgr/capacitor_updater/DeviceIdHelper.java +215 -0
  19. package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +858 -117
  20. package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +156 -0
  21. package/android/src/main/java/ee/forgr/capacitor_updater/InternalUtils.java +45 -0
  22. package/android/src/main/java/ee/forgr/capacitor_updater/Logger.java +360 -0
  23. package/android/src/main/java/ee/forgr/capacitor_updater/ShakeDetector.java +72 -0
  24. package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +603 -0
  25. package/dist/docs.json +3022 -765
  26. package/dist/esm/definitions.d.ts +1717 -198
  27. package/dist/esm/definitions.js +103 -1
  28. package/dist/esm/definitions.js.map +1 -1
  29. package/dist/esm/history.d.ts +1 -0
  30. package/dist/esm/history.js +283 -0
  31. package/dist/esm/history.js.map +1 -0
  32. package/dist/esm/index.d.ts +3 -2
  33. package/dist/esm/index.js +5 -4
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/web.d.ts +43 -42
  36. package/dist/esm/web.js +122 -37
  37. package/dist/esm/web.js.map +1 -1
  38. package/dist/plugin.cjs.js +512 -37
  39. package/dist/plugin.cjs.js.map +1 -1
  40. package/dist/plugin.js +512 -37
  41. package/dist/plugin.js.map +1 -1
  42. package/ios/Sources/CapacitorUpdaterPlugin/AES.swift +87 -0
  43. package/ios/Sources/CapacitorUpdaterPlugin/BigInt.swift +55 -0
  44. package/ios/Sources/CapacitorUpdaterPlugin/BundleInfo.swift +177 -0
  45. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/BundleStatus.swift +12 -12
  46. package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +2020 -0
  47. package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +1959 -0
  48. package/ios/Sources/CapacitorUpdaterPlugin/CryptoCipher.swift +313 -0
  49. package/ios/Sources/CapacitorUpdaterPlugin/DelayUpdateUtils.swift +257 -0
  50. package/ios/Sources/CapacitorUpdaterPlugin/DeviceIdHelper.swift +120 -0
  51. package/ios/Sources/CapacitorUpdaterPlugin/InternalUtils.swift +392 -0
  52. package/ios/Sources/CapacitorUpdaterPlugin/Logger.swift +310 -0
  53. package/ios/Sources/CapacitorUpdaterPlugin/RSA.swift +274 -0
  54. package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +441 -0
  55. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/UserDefaultsExtension.swift +1 -2
  56. package/package.json +49 -41
  57. package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +0 -1131
  58. package/ios/Plugin/BundleInfo.swift +0 -113
  59. package/ios/Plugin/CapacitorUpdater.swift +0 -850
  60. package/ios/Plugin/CapacitorUpdaterPlugin.h +0 -10
  61. package/ios/Plugin/CapacitorUpdaterPlugin.m +0 -27
  62. package/ios/Plugin/CapacitorUpdaterPlugin.swift +0 -678
  63. package/ios/Plugin/CryptoCipher.swift +0 -240
  64. /package/{LICENCE → LICENSE} +0 -0
  65. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/DelayCondition.swift +0 -0
  66. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/DelayUntilNext.swift +0 -0
  67. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/Info.plist +0 -0
@@ -0,0 +1,441 @@
1
+ /*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+ import UIKit
8
+ import Capacitor
9
+
10
+ extension UIApplication {
11
+ // swiftlint:disable:next line_length
12
+ public class func topViewController(_ base: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
13
+ if let nav = base as? UINavigationController {
14
+ return topViewController(nav.visibleViewController)
15
+ }
16
+ if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
17
+ return topViewController(selected)
18
+ }
19
+ if let presented = base?.presentedViewController {
20
+ return topViewController(presented)
21
+ }
22
+ return base
23
+ }
24
+ }
25
+
26
+ extension UIWindow {
27
+ override open func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
28
+ if motion == .motionShake {
29
+ // Find the CapacitorUpdaterPlugin instance
30
+ guard let bridge = (rootViewController as? CAPBridgeProtocol),
31
+ let plugin = bridge.plugin(withName: "CapacitorUpdaterPlugin") as? CapacitorUpdaterPlugin else {
32
+ return
33
+ }
34
+
35
+ // Check if shake menu is enabled
36
+ if !plugin.shakeMenuEnabled {
37
+ return
38
+ }
39
+
40
+ // Check if channel selector mode is enabled
41
+ if plugin.shakeChannelSelectorEnabled {
42
+ showChannelSelector(plugin: plugin, bridge: bridge)
43
+ } else {
44
+ showDefaultMenu(plugin: plugin, bridge: bridge)
45
+ }
46
+ }
47
+ }
48
+
49
+ private func showDefaultMenu(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
50
+ // Prevent multiple alerts from showing
51
+ if let topVC = UIApplication.topViewController(),
52
+ topVC.isKind(of: UIAlertController.self) {
53
+ plugin.logger.info("UIAlertController is already presented")
54
+ return
55
+ }
56
+
57
+ let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String ?? "App"
58
+ let title = "Preview \(appName) Menu"
59
+ let message = "What would you like to do?"
60
+ let okButtonTitle = "Go Home"
61
+ let reloadButtonTitle = "Reload app"
62
+ let cancelButtonTitle = "Close menu"
63
+
64
+ let updater = plugin.implementation
65
+
66
+ func resetBuiltin() {
67
+ updater.reset()
68
+ bridge.setServerBasePath("")
69
+ DispatchQueue.main.async {
70
+ if let viewController = (self.rootViewController as? CAPBridgeViewController) {
71
+ viewController.loadView()
72
+ viewController.viewDidLoad()
73
+ }
74
+ _ = updater.delete(id: updater.getCurrentBundleId())
75
+ plugin.logger.info("Reset to builtin version")
76
+ }
77
+ }
78
+
79
+ let bundleId = updater.getCurrentBundleId()
80
+ if let viewController = (self.rootViewController as? CAPBridgeViewController) {
81
+ plugin.logger.info("getServerBasePath: \(viewController.getServerBasePath())")
82
+ }
83
+ plugin.logger.info("bundleId: \(bundleId)")
84
+
85
+ let alertShake = UIAlertController(title: title, message: message, preferredStyle: .alert)
86
+
87
+ alertShake.addAction(UIAlertAction(title: okButtonTitle, style: .default) { _ in
88
+ guard let next = updater.getNextBundle() else {
89
+ resetBuiltin()
90
+ return
91
+ }
92
+ if !next.isBuiltin() {
93
+ plugin.logger.info("Resetting to: \(next.toString())")
94
+ _ = updater.set(bundle: next)
95
+ let destHot = updater.getBundleDirectory(id: next.getId())
96
+ plugin.logger.info("Reloading \(next.toString())")
97
+ bridge.setServerBasePath(destHot.path)
98
+ } else {
99
+ resetBuiltin()
100
+ }
101
+ plugin.logger.info("Reload app done")
102
+ })
103
+
104
+ alertShake.addAction(UIAlertAction(title: cancelButtonTitle, style: .default))
105
+
106
+ alertShake.addAction(UIAlertAction(title: reloadButtonTitle, style: .default) { _ in
107
+ DispatchQueue.main.async {
108
+ bridge.webView?.reload()
109
+ }
110
+ })
111
+
112
+ DispatchQueue.main.async {
113
+ if let topVC = UIApplication.topViewController() {
114
+ topVC.present(alertShake, animated: true)
115
+ }
116
+ }
117
+ }
118
+
119
+ private func showChannelSelector(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
120
+ // Prevent multiple alerts from showing
121
+ if let topVC = UIApplication.topViewController(),
122
+ topVC.isKind(of: UIAlertController.self) {
123
+ plugin.logger.info("UIAlertController is already presented")
124
+ return
125
+ }
126
+
127
+ let updater = plugin.implementation
128
+
129
+ // Show loading indicator
130
+ let loadingAlert = UIAlertController(title: "Loading Channels...", message: nil, preferredStyle: .alert)
131
+ var didCancel = false
132
+ let loadingIndicator = UIActivityIndicatorView(style: .medium)
133
+ loadingIndicator.translatesAutoresizingMaskIntoConstraints = false
134
+ loadingIndicator.startAnimating()
135
+ loadingAlert.view.addSubview(loadingIndicator)
136
+
137
+ NSLayoutConstraint.activate([
138
+ loadingIndicator.centerXAnchor.constraint(equalTo: loadingAlert.view.centerXAnchor),
139
+ loadingIndicator.bottomAnchor.constraint(equalTo: loadingAlert.view.bottomAnchor, constant: -20)
140
+ ])
141
+
142
+ // Add cancel button to loading alert
143
+ loadingAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
144
+ didCancel = true
145
+ })
146
+
147
+ DispatchQueue.main.async {
148
+ if let topVC = UIApplication.topViewController() {
149
+ topVC.present(loadingAlert, animated: true) {
150
+ // Fetch channels in background
151
+ DispatchQueue.global(qos: .userInitiated).async {
152
+ let result = updater.listChannels()
153
+
154
+ DispatchQueue.main.async {
155
+ loadingAlert.dismiss(animated: true) {
156
+ guard !didCancel else { return }
157
+ if !result.error.isEmpty {
158
+ self.showError(message: "Failed to load channels: \(result.error)", plugin: plugin)
159
+ } else if result.channels.isEmpty {
160
+ self.showError(message: "No channels available for self-assignment", plugin: plugin)
161
+ } else {
162
+ self.presentChannelPicker(channels: result.channels, plugin: plugin, bridge: bridge)
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ private func presentChannelPicker(channels: [[String: Any]], plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
173
+ let alert = UIAlertController(title: "Select Channel", message: "Choose a channel to switch to", preferredStyle: .actionSheet)
174
+
175
+ // Get channel names
176
+ let channelNames = channels.compactMap { $0["name"] as? String }
177
+
178
+ // Show first 5 channels as actions
179
+ let channelsToShow = Array(channelNames.prefix(5))
180
+
181
+ for channelName in channelsToShow {
182
+ alert.addAction(UIAlertAction(title: channelName, style: .default) { [weak self] _ in
183
+ self?.selectChannel(name: channelName, plugin: plugin, bridge: bridge)
184
+ })
185
+ }
186
+
187
+ // If there are more channels, add a "More..." option
188
+ if channelNames.count > 5 {
189
+ alert.addAction(UIAlertAction(title: "More channels...", style: .default) { [weak self] _ in
190
+ self?.showSearchableChannelPicker(channels: channels, plugin: plugin, bridge: bridge)
191
+ })
192
+ }
193
+
194
+ alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
195
+
196
+ // For iPad support
197
+ if let popoverController = alert.popoverPresentationController {
198
+ popoverController.sourceView = self
199
+ popoverController.sourceRect = CGRect(x: self.bounds.midX, y: self.bounds.midY, width: 0, height: 0)
200
+ popoverController.permittedArrowDirections = []
201
+ }
202
+
203
+ DispatchQueue.main.async {
204
+ if let topVC = UIApplication.topViewController() {
205
+ topVC.present(alert, animated: true)
206
+ }
207
+ }
208
+ }
209
+
210
+ private func showSearchableChannelPicker(channels: [[String: Any]], plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
211
+ let alert = UIAlertController(title: "Search Channels", message: "Enter channel name to search", preferredStyle: .alert)
212
+
213
+ alert.addTextField { textField in
214
+ textField.placeholder = "Channel name..."
215
+ }
216
+
217
+ let channelNames = channels.compactMap { $0["name"] as? String }
218
+
219
+ alert.addAction(UIAlertAction(title: "Search", style: .default) { [weak self, weak alert] _ in
220
+ guard let searchText = alert?.textFields?.first?.text?.lowercased(), !searchText.isEmpty else {
221
+ // If empty, show first 5
222
+ self?.presentChannelPicker(channels: channels, plugin: plugin, bridge: bridge)
223
+ return
224
+ }
225
+
226
+ // Filter channels
227
+ let filtered = channelNames.filter { $0.lowercased().contains(searchText) }
228
+
229
+ if filtered.isEmpty {
230
+ self?.showError(message: "No channels found matching '\(searchText)'", plugin: plugin)
231
+ } else if filtered.count == 1 {
232
+ // Directly select if only one match
233
+ self?.selectChannel(name: filtered[0], plugin: plugin, bridge: bridge)
234
+ } else {
235
+ // Show filtered results
236
+ let filteredChannels = channels.filter { channel in
237
+ if let name = channel["name"] as? String {
238
+ return name.lowercased().contains(searchText)
239
+ }
240
+ return false
241
+ }
242
+ self?.presentChannelPicker(channels: filteredChannels, plugin: plugin, bridge: bridge)
243
+ }
244
+ })
245
+
246
+ alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
247
+
248
+ DispatchQueue.main.async {
249
+ if let topVC = UIApplication.topViewController() {
250
+ topVC.present(alert, animated: true)
251
+ }
252
+ }
253
+ }
254
+
255
+ private func selectChannel(name: String, plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
256
+ let updater = plugin.implementation
257
+
258
+ // Show progress indicator
259
+ let progressAlert = UIAlertController(title: "Switching to \(name)", message: "Setting channel...", preferredStyle: .alert)
260
+ let indicator = UIActivityIndicatorView(style: .medium)
261
+ indicator.translatesAutoresizingMaskIntoConstraints = false
262
+ indicator.startAnimating()
263
+ progressAlert.view.addSubview(indicator)
264
+
265
+ NSLayoutConstraint.activate([
266
+ indicator.centerXAnchor.constraint(equalTo: progressAlert.view.centerXAnchor),
267
+ indicator.bottomAnchor.constraint(equalTo: progressAlert.view.bottomAnchor, constant: -20)
268
+ ])
269
+
270
+ DispatchQueue.main.async {
271
+ if let topVC = UIApplication.topViewController() {
272
+ topVC.present(progressAlert, animated: true) {
273
+ DispatchQueue.global(qos: .userInitiated).async {
274
+ // Set the channel - respect plugin's allowSetDefaultChannel config
275
+ let setResult = updater.setChannel(
276
+ channel: name,
277
+ defaultChannelKey: "CapacitorUpdater.defaultChannel",
278
+ allowSetDefaultChannel: plugin.allowSetDefaultChannel
279
+ )
280
+
281
+ if !setResult.error.isEmpty {
282
+ DispatchQueue.main.async {
283
+ progressAlert.dismiss(animated: true) {
284
+ self.showError(message: "Failed to set channel: \(setResult.error)", plugin: plugin)
285
+ }
286
+ }
287
+ return
288
+ }
289
+
290
+ // Update progress message
291
+ DispatchQueue.main.async {
292
+ progressAlert.message = "Checking for updates..."
293
+ }
294
+
295
+ // Check for updates with the new channel
296
+ let pluginUpdateUrl = plugin.getUpdateUrl()
297
+ let updateUrlStr = pluginUpdateUrl.isEmpty ? CapacitorUpdaterPlugin.updateUrlDefault : pluginUpdateUrl
298
+ guard let updateUrl = URL(string: updateUrlStr) else {
299
+ DispatchQueue.main.async {
300
+ progressAlert.dismiss(animated: true) {
301
+ self.showError(
302
+ message: "Channel set to \(name). Invalid update URL, could not check for updates.",
303
+ plugin: plugin
304
+ )
305
+ }
306
+ }
307
+ return
308
+ }
309
+
310
+ let latest = updater.getLatest(url: updateUrl, channel: name)
311
+
312
+ // Handle update errors first (before "no new version" check)
313
+ if let error = latest.error, !error.isEmpty && error != "no_new_version_available" {
314
+ DispatchQueue.main.async {
315
+ progressAlert.dismiss(animated: true) {
316
+ self.showError(message: "Channel set to \(name). Update check failed: \(error)", plugin: plugin)
317
+ }
318
+ }
319
+ return
320
+ }
321
+
322
+ // Check if there's an actual update available
323
+ if latest.error == "no_new_version_available" || latest.url.isEmpty {
324
+ DispatchQueue.main.async {
325
+ progressAlert.dismiss(animated: true) {
326
+ self.showSuccess(message: "Channel set to \(name). Already on latest version.", plugin: plugin)
327
+ }
328
+ }
329
+ return
330
+ }
331
+
332
+ // Update message
333
+ DispatchQueue.main.async {
334
+ progressAlert.message = "Downloading update \(latest.version)..."
335
+ }
336
+
337
+ // Download the update
338
+ do {
339
+ let bundle: BundleInfo
340
+ if let manifest = latest.manifest, !manifest.isEmpty {
341
+ bundle = try updater.downloadManifest(
342
+ manifest: manifest,
343
+ version: latest.version,
344
+ sessionKey: latest.sessionKey ?? ""
345
+ )
346
+ } else {
347
+ // Safe unwrap URL
348
+ guard let downloadUrl = URL(string: latest.url) else {
349
+ DispatchQueue.main.async {
350
+ progressAlert.dismiss(animated: true) {
351
+ self.showError(message: "Failed to download update: invalid update URL.", plugin: plugin)
352
+ }
353
+ }
354
+ return
355
+ }
356
+ bundle = try updater.download(
357
+ url: downloadUrl,
358
+ version: latest.version,
359
+ sessionKey: latest.sessionKey ?? ""
360
+ )
361
+ }
362
+
363
+ // Set as next bundle
364
+ _ = updater.setNextBundle(next: bundle.getId())
365
+
366
+ DispatchQueue.main.async {
367
+ progressAlert.dismiss(animated: true) {
368
+ self.showSuccessWithReload(
369
+ message: "Update downloaded! Reload to apply version \(latest.version)?",
370
+ plugin: plugin,
371
+ bridge: bridge,
372
+ onReload: { [weak plugin] in
373
+ _ = updater.set(bundle: bundle)
374
+ _ = plugin?._reload()
375
+ }
376
+ )
377
+ }
378
+ }
379
+ } catch {
380
+ DispatchQueue.main.async {
381
+ progressAlert.dismiss(animated: true) {
382
+ self.showError(message: "Failed to download update: \(error.localizedDescription)", plugin: plugin)
383
+ }
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ private func showError(message: String, plugin: CapacitorUpdaterPlugin) {
393
+ plugin.logger.error(message)
394
+ let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
395
+ alert.addAction(UIAlertAction(title: "OK", style: .default))
396
+
397
+ DispatchQueue.main.async {
398
+ if let topVC = UIApplication.topViewController() {
399
+ topVC.present(alert, animated: true)
400
+ }
401
+ }
402
+ }
403
+
404
+ private func showSuccess(message: String, plugin: CapacitorUpdaterPlugin) {
405
+ plugin.logger.info(message)
406
+ let alert = UIAlertController(title: "Success", message: message, preferredStyle: .alert)
407
+ alert.addAction(UIAlertAction(title: "OK", style: .default))
408
+
409
+ DispatchQueue.main.async {
410
+ if let topVC = UIApplication.topViewController() {
411
+ topVC.present(alert, animated: true)
412
+ }
413
+ }
414
+ }
415
+
416
+ private func showSuccessWithReload(
417
+ message: String,
418
+ plugin: CapacitorUpdaterPlugin,
419
+ bridge: CAPBridgeProtocol,
420
+ onReload: (() -> Void)? = nil
421
+ ) {
422
+ plugin.logger.info(message)
423
+ let alert = UIAlertController(title: "Update Ready", message: message, preferredStyle: .alert)
424
+ alert.addAction(UIAlertAction(title: "Later", style: .cancel))
425
+ alert.addAction(UIAlertAction(title: "Reload Now", style: .default) { _ in
426
+ if let onReload = onReload {
427
+ onReload()
428
+ } else {
429
+ DispatchQueue.main.async {
430
+ bridge.webView?.reload()
431
+ }
432
+ }
433
+ })
434
+
435
+ DispatchQueue.main.async {
436
+ if let topVC = UIApplication.topViewController() {
437
+ topVC.present(alert, animated: true)
438
+ }
439
+ }
440
+ }
441
+ }
@@ -15,6 +15,7 @@ enum ObjectSavableError: String, LocalizedError {
15
15
  case unableToEncode = "Unable to encode object into data"
16
16
  case noValue = "No data object found for the given key"
17
17
  case unableToDecode = "Unable to decode object into given type"
18
+ case checksum = "Checksum failed"
18
19
 
19
20
  var errorDescription: String? {
20
21
  rawValue
@@ -33,9 +34,7 @@ extension UserDefaults: ObjectSavable {
33
34
  }
34
35
 
35
36
  func getObj<Object>(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable {
36
- // print("forKey", forKey)
37
37
  guard let data: Data = data(forKey: forKey) else { throw ObjectSavableError.noValue }
38
- // print("data", data)
39
38
  let decoder: JSONDecoder = JSONDecoder()
40
39
  do {
41
40
  let object: Object = try decoder.decode(type, from: data)
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "4.41.0",
4
- "packageManager": "pnpm@8.2.0",
3
+ "version": "4.43.5",
5
4
  "license": "MPL-2.0",
6
5
  "description": "Live update for capacitor apps",
7
6
  "main": "dist/plugin.cjs.js",
@@ -10,12 +9,14 @@
10
9
  "unpkg": "dist/plugin.js",
11
10
  "files": [
12
11
  "android/src/main/",
12
+ "android/proguard-rules.pro",
13
13
  "android/build.gradle",
14
14
  "dist/",
15
- "ios/Plugin/",
16
- "CapgoCapacitorUpdater.podspec"
15
+ "ios/Sources/",
16
+ "CapgoCapacitorUpdater.podspec",
17
+ "Package.swift"
17
18
  ],
18
- "author": "Martin Donadieu",
19
+ "author": "Martin Donadieu <martin@capgo.app>",
19
20
  "repository": {
20
21
  "type": "git",
21
22
  "url": "git+https://github.com/Cap-go/capacitor-updater.git"
@@ -23,58 +24,65 @@
23
24
  "bugs": {
24
25
  "url": "https://github.com/Cap-go/capacitor-updater/issues"
25
26
  },
27
+ "homepage": "https://capgo.app/docs/plugins/updater/",
26
28
  "keywords": [
27
29
  "capacitor",
28
- "plugin",
29
- "OTA",
30
- "manual update",
30
+ "live updates",
31
31
  "live update",
32
+ "updates",
32
33
  "auto update",
34
+ "manual update",
35
+ "capgo",
36
+ "plugin",
37
+ "OTA",
33
38
  "ionic",
34
39
  "appflow alternative",
35
- "capgo",
40
+ "microsoft alternative",
36
41
  "native"
37
42
  ],
38
43
  "scripts": {
39
- "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
40
- "verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin && cd ..",
41
- "verify:android": "cd android && ./gradlew clean build test && cd ..",
42
- "verify:web": "npm run build",
43
- "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
44
- "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --autocorrect --format",
45
- "eslint": "eslint . --ext ts",
46
- "prettier": "prettier --config .prettierrc.js \"**/*.{css,html,ts,js,java}\"",
44
+ "verify": "bun run verify:ios && bun run verify:android && bun run verify:web",
45
+ "verify:ios": "xcodebuild -scheme CapgoCapacitorUpdater -destination generic/platform=iOS",
46
+ "verify:android": "cd android && ./gradlew clean assemble test && cd ..",
47
+ "verify:web": "bun run build",
48
+ "test": "bun run test:ios && bun run test:android",
49
+ "test:ios": "./scripts/test-ios.sh",
50
+ "test:android": "cd android && ./gradlew test && cd ..",
51
+ "lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
52
+ "fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
53
+ "eslint": "eslint . --ext .ts",
54
+ "prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
47
55
  "swiftlint": "node-swiftlint",
48
- "docgen": "docgen --api CapacitorUpdaterPlugin --output-readme README.md --output-json dist/docs.json",
49
- "docgen:api": "docgen --api CapacitorUpdaterPlugin --output-readme api.md --output-json dist/docs.json && awk '{sub(/###/,\"##\")}1' api.md > temp.txt && mv temp.txt api.md",
50
- "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
56
+ "docgen": "node scripts/generate-docs.js",
57
+ "build": "bun run clean && bun run docgen && tsc && rollup -c rollup.config.mjs",
51
58
  "clean": "rimraf ./dist",
52
59
  "watch": "tsc --watch",
53
- "prepublishOnly": "npm run build"
60
+ "prepublishOnly": "bun run build",
61
+ "check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs"
54
62
  },
55
63
  "devDependencies": {
56
- "@capacitor/android": "^4.7.3",
57
- "@capacitor/cli": "^4.7.3",
58
- "@capacitor/core": "^4.7.3",
59
- "@capacitor/docgen": "^0.2.1",
60
- "@capacitor/ios": "^4.7.3",
61
- "@ionic/eslint-config": "^0.3.0",
62
- "@ionic/prettier-config": "^2.0.0",
63
- "@ionic/swiftlint-config": "^1.1.2",
64
- "@types/node": "^18.15.11",
65
- "@typescript-eslint/eslint-plugin": "^5.58.0",
66
- "@typescript-eslint/parser": "^5.58.0",
67
- "eslint": "^8.38.0",
68
- "eslint-plugin-import": "^2.27.5",
69
- "prettier": "^2.8.7",
70
- "prettier-plugin-java": "^2.1.0",
71
- "rimraf": "^4.4.1",
72
- "rollup": "^3.20.2",
73
- "swiftlint": "^1.0.1",
74
- "typescript": "^4.9.5"
64
+ "@capacitor/android": "^4.8.2",
65
+ "@capacitor/cli": "^4.8.2",
66
+ "@capacitor/core": "^4.8.2",
67
+ "@capacitor/docgen": "^0.3.0",
68
+ "@capacitor/ios": "^4.8.2",
69
+ "@ionic/eslint-config": "^0.4.0",
70
+ "@ionic/prettier-config": "^4.0.0",
71
+ "@ionic/swiftlint-config": "^2.0.0",
72
+ "@types/node": "^24.3.0",
73
+ "eslint": "^8.57.0",
74
+ "eslint-plugin-import": "^2.32.0",
75
+ "husky": "^9.1.7",
76
+ "prettier": "^3.6.2",
77
+ "prettier-plugin-java": "^2.7.4",
78
+ "rimraf": "^6.0.1",
79
+ "rollup": "^4.50.0",
80
+ "swiftlint": "^2.0.0",
81
+ "typescript": "^5.9.2",
82
+ "prettier-pretty-check": "^0.2.0"
75
83
  },
76
84
  "peerDependencies": {
77
- "@capacitor/core": "^4.0.0 || ^5.0.0"
85
+ "@capacitor/core": "^4.0.0"
78
86
  },
79
87
  "prettier": "@ionic/prettier-config",
80
88
  "swiftlint": "@ionic/swiftlint-config",