@capawesome/capacitor-live-update 7.4.0 → 7.5.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 (28) hide show
  1. package/CapawesomeCapacitorLiveUpdate.podspec +1 -1
  2. package/Package.swift +2 -2
  3. package/README.md +96 -1
  4. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +91 -3
  5. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateHttpClient.java +12 -1
  6. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +31 -1
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/api/GetChannelsResponseItem.java +28 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/FetchChannelsOptions.java +38 -0
  9. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/ChannelResult.java +28 -0
  10. package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/FetchChannelsResult.java +28 -0
  11. package/dist/docs.json +150 -2
  12. package/dist/esm/definitions.d.ts +83 -0
  13. package/dist/esm/definitions.js.map +1 -1
  14. package/dist/esm/web.d.ts +2 -1
  15. package/dist/esm/web.js +3 -0
  16. package/dist/esm/web.js.map +1 -1
  17. package/dist/plugin.cjs.js +3 -0
  18. package/dist/plugin.cjs.js.map +1 -1
  19. package/dist/plugin.js +3 -0
  20. package/dist/plugin.js.map +1 -1
  21. package/ios/Plugin/Classes/Options/FetchChannelsOptions.swift +26 -0
  22. package/ios/Plugin/Classes/Results/ChannelResult.swift +19 -0
  23. package/ios/Plugin/Classes/Results/FetchChannelsResult.swift +16 -0
  24. package/ios/Plugin/LiveUpdate.swift +45 -8
  25. package/ios/Plugin/LiveUpdateHttpClient.swift +11 -0
  26. package/ios/Plugin/LiveUpdatePlugin.swift +21 -1
  27. package/ios/Plugin/Protocols/Api/GetChannelsResponseItem.swift +4 -0
  28. package/package.json +1 -1
@@ -1,10 +1,6 @@
1
1
  import Foundation
2
2
  import CryptoKit
3
- #if canImport(ZipArchive)
4
- import ZipArchive
5
- #else
6
- import SSZipArchive
7
- #endif
3
+ import ZIPFoundation
8
4
  import Capacitor
9
5
  import Alamofire
10
6
  import CommonCrypto
@@ -38,6 +34,9 @@ import CommonCrypto
38
34
  // Check version and reset config if version changed
39
35
  checkAndResetConfigIfVersionChanged()
40
36
 
37
+ // Set the device ID on the HTTP client (after any potential config reset)
38
+ self.httpClient.setDeviceId(getDeviceId())
39
+
41
40
  // Start the rollback timer to rollback to the default bundle
42
41
  // if the app is not ready after a certain time
43
42
  startRollbackTimer()
@@ -84,6 +83,36 @@ import CommonCrypto
84
83
  }
85
84
  }
86
85
 
86
+ @objc public func fetchChannels(_ options: FetchChannelsOptions) async throws -> FetchChannelsResult {
87
+ var parameters = [String: String]()
88
+ if let limit = options.getLimit() {
89
+ parameters["limit"] = String(limit)
90
+ }
91
+ if let offset = options.getOffset() {
92
+ parameters["offset"] = String(offset)
93
+ }
94
+ if let query = options.getQuery() {
95
+ parameters["query"] = query
96
+ }
97
+ var urlComponents = URLComponents(string: "https://\(config.serverDomain)/v1/apps/\(getAppId() ?? "")/channels")!
98
+ if !parameters.isEmpty {
99
+ urlComponents.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
100
+ }
101
+ let url = try urlComponents.asURL()
102
+ let response = try await self.httpClient.request(url: url, type: [GetChannelsResponseItem].self)
103
+ if let error = response.error {
104
+ if let urlError = error.underlyingError as? URLError {
105
+ if urlError.code == .timedOut {
106
+ throw urlError
107
+ }
108
+ }
109
+ throw error
110
+ }
111
+ let items = response.value ?? []
112
+ let channels = items.map { ChannelResult(id: $0.id, name: $0.name) }
113
+ return FetchChannelsResult(channels: channels)
114
+ }
115
+
87
116
  @objc public func fetchLatestBundle(_ options: FetchLatestBundleOptions) async throws -> FetchLatestBundleResult {
88
117
  let response: GetLatestBundleResponse? = try await self.fetchLatestBundle(options)
89
118
  return FetchLatestBundleResult(artifactType: response?.artifactType, bundleId: response?.bundleId, checksum: response?.checksum, customProperties: response?.customProperties, downloadUrl: response?.url, signature: response?.signature)
@@ -323,7 +352,7 @@ import CommonCrypto
323
352
 
324
353
  private func addBundleOfTypeZip(bundleId: String, zipFile: URL) async throws {
325
354
  // Unzip the bundle
326
- let unzippedDirectory = self.unzipFile(zipFile: zipFile)
355
+ let unzippedDirectory = try self.unzipFile(zipFile: zipFile)
327
356
  // Add the bundle
328
357
  try self.addBundle(bundleId: bundleId, directory: unzippedDirectory)
329
358
  }
@@ -605,6 +634,9 @@ import CommonCrypto
605
634
 
606
635
  private func getChannel() -> String? {
607
636
  var channel: String?
637
+ if let nativeChannel = getNativeChannel() {
638
+ channel = nativeChannel
639
+ }
608
640
  if let _ = config.defaultChannel {
609
641
  channel = config.defaultChannel
610
642
  }
@@ -614,6 +646,10 @@ import CommonCrypto
614
646
  return channel
615
647
  }
616
648
 
649
+ private func getNativeChannel() -> String? {
650
+ return Bundle.main.object(forInfoDictionaryKey: "CapawesomeLiveUpdateDefaultChannel") as? String
651
+ }
652
+
617
653
  /// - Returns: The sha256 checksum of the file at the given URL.
618
654
  private func getChecksumForFile(url: URL) throws -> String {
619
655
  let handle = try FileHandle(forReadingFrom: url)
@@ -923,9 +959,10 @@ import CommonCrypto
923
959
  }
924
960
  }
925
961
 
926
- private func unzipFile(zipFile: URL) -> URL {
962
+ private func unzipFile(zipFile: URL) throws -> URL {
927
963
  let destinationDirectory = zipFile.deletingPathExtension()
928
- SSZipArchive.unzipFile(atPath: zipFile.path, toDestination: destinationDirectory.path)
964
+ try FileManager.default.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
965
+ try FileManager.default.unzipItem(at: zipFile, to: destinationDirectory)
929
966
  return destinationDirectory
930
967
  }
931
968
 
@@ -5,6 +5,7 @@ import Alamofire
5
5
  public class LiveUpdateHttpClient: NSObject {
6
6
 
7
7
  private let config: LiveUpdateConfig
8
+ private var deviceId: String?
8
9
 
9
10
  public static func getChecksumFromResponse(response: HTTPURLResponse) -> String? {
10
11
  guard let headers = response.allHeaderFields as? [String: String] else { return nil }
@@ -20,10 +21,17 @@ public class LiveUpdateHttpClient: NSObject {
20
21
  self.config = config
21
22
  }
22
23
 
24
+ public func setDeviceId(_ deviceId: String) {
25
+ self.deviceId = deviceId
26
+ }
27
+
23
28
  public func download(url: URL, destination: @escaping DownloadRequest.Destination, callback: ((Progress) -> Void)?) async throws -> AFDownloadResponse<Data> {
24
29
  var request = URLRequest(url: url)
25
30
  request.httpMethod = HTTPMethod.get.rawValue
26
31
  request.timeoutInterval = Double(config.httpTimeout) / 1000.0
32
+ if let deviceId = deviceId, !deviceId.isEmpty {
33
+ request.setValue(deviceId, forHTTPHeaderField: "X-Device-Id")
34
+ }
27
35
  return try await withCheckedThrowingContinuation { continuation in
28
36
  AF.download(request, to: destination).downloadProgress { progress in
29
37
  if let callback = callback {
@@ -39,6 +47,9 @@ public class LiveUpdateHttpClient: NSObject {
39
47
  var request = URLRequest(url: url)
40
48
  request.httpMethod = HTTPMethod.get.rawValue
41
49
  request.timeoutInterval = Double(config.httpTimeout) / 1000.0
50
+ if let deviceId = deviceId, !deviceId.isEmpty {
51
+ request.setValue(deviceId, forHTTPHeaderField: "X-Device-Id")
52
+ }
42
53
  return try await withCheckedThrowingContinuation { continuation in
43
54
  AF.request(request).validate().responseDecodable(of: type) { response in
44
55
  continuation.resume(returning: response)
@@ -8,7 +8,7 @@ import Capacitor
8
8
  @objc(LiveUpdatePlugin)
9
9
  public class LiveUpdatePlugin: CAPPlugin, CAPBridgedPlugin {
10
10
  public static let tag = "LiveUpdate"
11
- public static let version = "7.4.0"
11
+ public static let version = "7.5.0"
12
12
  public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
13
13
 
14
14
  public let identifier = "LiveUpdatePlugin"
@@ -17,6 +17,7 @@ public class LiveUpdatePlugin: CAPPlugin, CAPBridgedPlugin {
17
17
  CAPPluginMethod(name: "clearBlockedBundles", returnType: CAPPluginReturnPromise),
18
18
  CAPPluginMethod(name: "deleteBundle", returnType: CAPPluginReturnPromise),
19
19
  CAPPluginMethod(name: "downloadBundle", returnType: CAPPluginReturnPromise),
20
+ CAPPluginMethod(name: "fetchChannels", returnType: CAPPluginReturnPromise),
20
21
  CAPPluginMethod(name: "fetchLatestBundle", returnType: CAPPluginReturnPromise),
21
22
  CAPPluginMethod(name: "getBlockedBundles", returnType: CAPPluginReturnPromise),
22
23
  CAPPluginMethod(name: "getBundles", returnType: CAPPluginReturnPromise),
@@ -111,6 +112,25 @@ public class LiveUpdatePlugin: CAPPlugin, CAPBridgedPlugin {
111
112
  }
112
113
  }
113
114
 
115
+ @objc func fetchChannels(_ call: CAPPluginCall) {
116
+ Task {
117
+ do {
118
+ guard let appId = config?.appId, !appId.isEmpty else {
119
+ call.reject(CustomError.appIdMissing.localizedDescription)
120
+ return
121
+ }
122
+
123
+ let options = FetchChannelsOptions(call)
124
+ let result = try await implementation?.fetchChannels(options)
125
+ if let result = result?.toJSObject() as? JSObject {
126
+ self.resolveCall(call, result)
127
+ }
128
+ } catch {
129
+ rejectCall(call, error)
130
+ }
131
+ }
132
+ }
133
+
114
134
  @objc func fetchLatestBundle(_ call: CAPPluginCall) {
115
135
  Task {
116
136
  do {
@@ -0,0 +1,4 @@
1
+ public struct GetChannelsResponseItem: Codable {
2
+ var id: String
3
+ var name: String
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capawesome/capacitor-live-update",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "description": "Capacitor plugin to update your app remotely in real-time.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",