@capgo/capacitor-updater 6.0.0 → 6.0.2

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.
@@ -17,11 +17,6 @@ extension URL {
17
17
  return FileManager().fileExists(atPath: self.path)
18
18
  }
19
19
  }
20
- extension Date {
21
- func adding(minutes: Int) -> Date {
22
- return Calendar.current.date(byAdding: .minute, value: minutes, to: self)!
23
- }
24
- }
25
20
  struct SetChannelDec: Decodable {
26
21
  let status: String?
27
22
  let error: String?
@@ -78,12 +73,14 @@ struct InfoObject: Codable {
78
73
  let version_build: String?
79
74
  let version_code: String?
80
75
  let version_os: String?
81
- let version_name: String?
76
+ var version_name: String?
77
+ var old_version_name: String?
82
78
  let plugin_version: String?
83
79
  let is_emulator: Bool?
84
80
  let is_prod: Bool?
85
81
  var action: String?
86
82
  var channel: String?
83
+ var defaultChannel: String?
87
84
  }
88
85
  struct AppVersionDec: Decodable {
89
86
  let version: String?
@@ -93,6 +90,7 @@ struct AppVersionDec: Decodable {
93
90
  let error: String?
94
91
  let session_key: String?
95
92
  let major: Bool?
93
+ let data: [String: String]?
96
94
  }
97
95
  public class AppVersion: NSObject {
98
96
  var version: String = ""
@@ -102,6 +100,7 @@ public class AppVersion: NSObject {
102
100
  var error: String?
103
101
  var sessionKey: String?
104
102
  var major: Bool?
103
+ var data: [String: String]?
105
104
  }
106
105
 
107
106
  extension AppVersion {
@@ -223,21 +222,22 @@ extension CustomError: LocalizedError {
223
222
  private let versionOs = UIDevice.current.systemVersion
224
223
  private let documentsDir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
225
224
  private let libraryDir: URL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
226
- private let bundleDirectoryHot: String = "versions"
227
225
  private let DEFAULT_FOLDER: String = ""
228
226
  private let bundleDirectory: String = "NoCloud/ionic_built_snapshots"
229
227
  private let INFO_SUFFIX: String = "_info"
230
228
  private let FALLBACK_VERSION: String = "pastVersion"
231
229
  private let NEXT_VERSION: String = "nextVersion"
230
+ private var unzipPercent = 0
232
231
 
233
232
  public let TAG: String = "✨ Capacitor-updater:"
234
233
  public let CAP_SERVER_PATH: String = "serverBasePath"
235
- public var versionName: String = ""
234
+ public var versionBuild: String = ""
236
235
  public var customId: String = ""
237
236
  public var PLUGIN_VERSION: String = ""
238
- public let timeout: Double = 20
237
+ public var timeout: Double = 20
239
238
  public var statsUrl: String = ""
240
239
  public var channelUrl: String = ""
240
+ public var defaultChannel: String = ""
241
241
  public var appId: String = ""
242
242
  public var deviceID = UIDevice.current.identifierForVendor?.uuidString ?? ""
243
243
  public var privateKey: String = ""
@@ -295,8 +295,7 @@ extension CustomError: LocalizedError {
295
295
  return false
296
296
  #endif
297
297
  }
298
- // Persistent path /var/mobile/Containers/Data/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/Library/NoCloud/ionic_built_snapshots/FOLDER
299
- // Hot Reload path /var/mobile/Containers/Data/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/Documents/FOLDER
298
+ // Hot Reload path /var/mobile/Containers/Data/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/Library/NoCloud/ionic_built_snapshots/FOLDER
300
299
  // Normal /private/var/containers/Bundle/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/App.app/public
301
300
 
302
301
  private func prepareFolder(source: URL) throws {
@@ -337,9 +336,27 @@ extension CustomError: LocalizedError {
337
336
  }
338
337
 
339
338
  private func getChecksum(filePath: URL) -> String {
339
+ let bufferSize = 1024 * 1024 * 5 // 5 MB
340
+ var checksum = uLong(0)
341
+
340
342
  do {
341
- let fileData: Data = try Data.init(contentsOf: filePath)
342
- let checksum: uLong = fileData.withUnsafeBytes { crc32(0, $0.bindMemory(to: Bytef.self).baseAddress, uInt(fileData.count)) }
343
+ let fileHandle = try FileHandle(forReadingFrom: filePath)
344
+ defer {
345
+ fileHandle.closeFile()
346
+ }
347
+
348
+ while autoreleasepool(invoking: {
349
+ let fileData = fileHandle.readData(ofLength: bufferSize)
350
+ if fileData.count > 0 {
351
+ checksum = fileData.withUnsafeBytes {
352
+ crc32(checksum, $0.bindMemory(to: Bytef.self).baseAddress, uInt(fileData.count))
353
+ }
354
+ return true // Continue
355
+ } else {
356
+ return false // End of file
357
+ }
358
+ }) {}
359
+
343
360
  return String(format: "%08X", checksum).lowercased()
344
361
  } catch {
345
362
  print("\(self.TAG) Cannot get checksum: \(filePath.path)", error)
@@ -348,7 +365,7 @@ extension CustomError: LocalizedError {
348
365
  }
349
366
 
350
367
  private func decryptFile(filePath: URL, sessionKey: String, version: String) throws {
351
- if self.privateKey.isEmpty || sessionKey.isEmpty {
368
+ if self.privateKey.isEmpty || sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
352
369
  print("\(self.TAG) Cannot found privateKey or sessionKey")
353
370
  return
354
371
  }
@@ -363,11 +380,24 @@ extension CustomError: LocalizedError {
363
380
  print("cannot decode sessionKey", sessionKey)
364
381
  throw CustomError.cannotDecode
365
382
  }
366
- let sessionKeyDataEncrypted: Data = Data(base64Encoded: sessionKeyArray[1])!
367
- let sessionKeyDataDecrypted: Data = rsaPrivateKey.decrypt(data: sessionKeyDataEncrypted)!
368
- let aesPrivateKey: AES128Key = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted)
369
- let encryptedData: Data = try Data(contentsOf: filePath)
370
- let decryptedData: Data = aesPrivateKey.decrypt(data: encryptedData)!
383
+
384
+ guard let sessionKeyDataEncrypted = Data(base64Encoded: sessionKeyArray[1]) else {
385
+ throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
386
+ }
387
+
388
+ guard let sessionKeyDataDecrypted = rsaPrivateKey.decrypt(data: sessionKeyDataEncrypted) else {
389
+ throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
390
+ }
391
+
392
+ let aesPrivateKey = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted)
393
+
394
+ guard let encryptedData = try? Data(contentsOf: filePath) else {
395
+ throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
396
+ }
397
+
398
+ guard let decryptedData = aesPrivateKey.decrypt(data: encryptedData) else {
399
+ throw NSError(domain: "Failed to decrypt data", code: 4, userInfo: nil)
400
+ }
371
401
 
372
402
  try decryptedData.write(to: filePath)
373
403
  } catch {
@@ -377,13 +407,80 @@ extension CustomError: LocalizedError {
377
407
  }
378
408
  }
379
409
 
380
- private func saveDownloaded(sourceZip: URL, id: String, base: URL) throws {
410
+ private func unzipProgressHandler(entry: String, zipInfo: unz_file_info, entryNumber: Int, total: Int, destUnZip: URL, id: String, unzipError: inout NSError?) {
411
+ if entry.contains("\\") {
412
+ print("\(self.TAG) unzip: Windows path is not supported, please use unix path as required by zip RFC: \(entry)")
413
+ self.sendStats(action: "windows_path_fail")
414
+ }
415
+
416
+ let fileURL = destUnZip.appendingPathComponent(entry)
417
+ let canonicalPath = fileURL.path
418
+ let canonicalDir = destUnZip.path
419
+
420
+ if !canonicalPath.hasPrefix(canonicalDir) {
421
+ self.sendStats(action: "canonical_path_fail")
422
+ unzipError = NSError(domain: "CanonicalPathError", code: 0, userInfo: nil)
423
+ }
424
+
425
+ let isDirectory = entry.hasSuffix("/")
426
+ if !isDirectory {
427
+ let folderURL = fileURL.deletingLastPathComponent()
428
+ if !FileManager.default.fileExists(atPath: folderURL.path) {
429
+ do {
430
+ try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true, attributes: nil)
431
+ } catch {
432
+ self.sendStats(action: "directory_path_fail")
433
+ unzipError = error as NSError
434
+ }
435
+ }
436
+ }
437
+
438
+ let newPercent = self.calcTotalPercent(percent: Int(Double(entryNumber) / Double(total) * 100), min: 75, max: 81)
439
+ if newPercent != self.unzipPercent {
440
+ self.unzipPercent = newPercent
441
+ self.notifyDownload(id, newPercent)
442
+ }
443
+ }
444
+
445
+ private func saveDownloaded(sourceZip: URL, id: String, base: URL, notify: Bool) throws {
381
446
  try prepareFolder(source: base)
382
447
  let destHot: URL = base.appendingPathComponent(id)
383
448
  let destUnZip: URL = documentsDir.appendingPathComponent(randomString(length: 10))
384
- if !SSZipArchive.unzipFile(atPath: sourceZip.path, toDestination: destUnZip.path) {
385
- throw CustomError.cannotUnzip
449
+
450
+ self.unzipPercent = 0
451
+ self.notifyDownload(id, 75)
452
+
453
+ let semaphore = DispatchSemaphore(value: 0)
454
+ var unzipError: NSError?
455
+
456
+ let success = SSZipArchive.unzipFile(atPath: sourceZip.path,
457
+ toDestination: destUnZip.path,
458
+ preserveAttributes: true,
459
+ overwrite: true,
460
+ nestedZipLevel: 1,
461
+ password: nil,
462
+ error: &unzipError,
463
+ delegate: nil,
464
+ progressHandler: { [weak self] (entry, zipInfo, entryNumber, total) in
465
+ DispatchQueue.global(qos: .background).async {
466
+ guard let self = self else { return }
467
+ if !notify {
468
+ return
469
+ }
470
+ self.unzipProgressHandler(entry: entry, zipInfo: zipInfo, entryNumber: entryNumber, total: total, destUnZip: destUnZip, id: id, unzipError: &unzipError)
471
+ }
472
+ },
473
+ completionHandler: { _, _, _ in
474
+ semaphore.signal()
475
+ })
476
+
477
+ semaphore.wait()
478
+
479
+ if !success || unzipError != nil {
480
+ self.sendStats(action: "unzip_fail")
481
+ throw unzipError ?? CustomError.cannotUnzip
386
482
  }
483
+
387
484
  if try unflatFolder(source: destUnZip, dest: destHot) {
388
485
  try deleteFolder(source: destUnZip)
389
486
  }
@@ -395,7 +492,7 @@ extension CustomError: LocalizedError {
395
492
  device_id: self.deviceID,
396
493
  app_id: self.appId,
397
494
  custom_id: self.customId,
398
- version_build: self.versionName,
495
+ version_build: self.versionBuild,
399
496
  version_code: self.versionCode,
400
497
  version_os: self.versionOs,
401
498
  version_name: self.getCurrentBundle().getVersionName(),
@@ -403,7 +500,8 @@ extension CustomError: LocalizedError {
403
500
  is_emulator: self.isEmulator(),
404
501
  is_prod: self.isProd(),
405
502
  action: nil,
406
- channel: nil
503
+ channel: nil,
504
+ defaultChannel: self.defaultChannel
407
505
  )
408
506
  }
409
507
 
@@ -438,6 +536,9 @@ extension CustomError: LocalizedError {
438
536
  if let sessionKey = response.value?.session_key {
439
537
  latest.sessionKey = sessionKey
440
538
  }
539
+ if let data = response.value?.data {
540
+ latest.data = data
541
+ }
441
542
  case let .failure(error):
442
543
  print("\(self.TAG) Error getting Latest", response.value ?? "", error )
443
544
  latest.message = "Error getting Latest \(String(describing: response.value))"
@@ -473,7 +574,7 @@ extension CustomError: LocalizedError {
473
574
  let percent = self.calcTotalPercent(percent: Int(progress.fractionCompleted * 100), min: 10, max: 70)
474
575
  self.notifyDownload(id, percent)
475
576
  }
476
- request.responseURL { (response) in
577
+ request.responseURL(queue: .global(qos: .background), completionHandler: { (response) in
477
578
  if let fileURL = response.fileURL {
478
579
  switch response.result {
479
580
  case .success:
@@ -481,27 +582,43 @@ extension CustomError: LocalizedError {
481
582
  do {
482
583
  try self.decryptFile(filePath: fileURL, sessionKey: sessionKey, version: version)
483
584
  checksum = self.getChecksum(filePath: fileURL)
484
- try self.saveDownloaded(sourceZip: fileURL, id: id, base: self.documentsDir.appendingPathComponent(self.bundleDirectoryHot))
485
- self.notifyDownload(id, 85)
486
- try self.saveDownloaded(sourceZip: fileURL, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory))
487
- self.notifyDownload(id, 100)
585
+ try self.saveDownloaded(sourceZip: fileURL, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory), notify: true)
488
586
  try self.deleteFolder(source: fileURL)
587
+ self.notifyDownload(id, 100)
489
588
  } catch {
490
589
  print("\(self.TAG) download unzip error", error)
491
590
  mainError = error as NSError
492
591
  }
493
592
  case let .failure(error):
494
593
  print("\(self.TAG) download error", response.value ?? "", error)
594
+ if let afError = error as? AFError,
595
+ case .sessionTaskFailed(let urlError as URLError) = afError,
596
+ urlError.code == .cannotWriteToFile {
597
+ self.sendStats(action: "low_mem_fail", versionName: version)
598
+ }
495
599
  mainError = error as NSError
496
600
  }
497
601
  }
498
602
  semaphore.signal()
499
- }
603
+ })
500
604
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.DOWNLOADING, downloaded: Date(), checksum: checksum))
501
605
  self.notifyDownload(id, 0)
606
+ let reachabilityManager = NetworkReachabilityManager()
607
+ reachabilityManager?.startListening { status in
608
+ switch status {
609
+ case .notReachable:
610
+ // Stop the download request if the network is not reachable
611
+ request.cancel()
612
+ mainError = NSError(domain: NSURLErrorDomain, code: NSURLErrorNotConnectedToInternet, userInfo: nil)
613
+ semaphore.signal()
614
+ default:
615
+ break
616
+ }
617
+ }
502
618
  semaphore.wait()
503
- if mainError != nil {
504
- throw mainError!
619
+ reachabilityManager?.stopListening()
620
+ if let error = mainError {
621
+ throw error
505
622
  }
506
623
  let info: BundleInfo = BundleInfo(id: id, version: version, status: BundleStatus.PENDING, downloaded: Date(), checksum: checksum)
507
624
  self.saveBundleInfo(id: id, bundle: info)
@@ -509,7 +626,7 @@ extension CustomError: LocalizedError {
509
626
  }
510
627
 
511
628
  public func list() -> [BundleInfo] {
512
- let dest: URL = documentsDir.appendingPathComponent(bundleDirectoryHot)
629
+ let dest: URL = documentsDir.appendingPathComponent(bundleDirectory)
513
630
  do {
514
631
  let files: [String] = try FileManager.default.contentsOfDirectory(atPath: dest.path)
515
632
  var res: [BundleInfo] = []
@@ -532,17 +649,11 @@ extension CustomError: LocalizedError {
532
649
  print("\(self.TAG) Cannot delete \(id)")
533
650
  return false
534
651
  }
535
- let destHot: URL = documentsDir.appendingPathComponent(bundleDirectoryHot).appendingPathComponent(id)
536
- let destPersist: URL = libraryDir.appendingPathComponent(bundleDirectory).appendingPathComponent(id)
652
+ let destHot: URL = libraryDir.appendingPathComponent(bundleDirectory).appendingPathComponent(id)
537
653
  do {
538
654
  try FileManager.default.removeItem(atPath: destHot.path)
539
655
  } catch {
540
- print("\(self.TAG) Hot Folder \(destHot.path), not removed.")
541
- }
542
- do {
543
- try FileManager.default.removeItem(atPath: destPersist.path)
544
- } catch {
545
- print("\(self.TAG) Folder \(destPersist.path), not removed.")
656
+ print("\(self.TAG) Folder \(destHot.path), not removed.")
546
657
  return false
547
658
  }
548
659
  if removeInfo {
@@ -568,13 +679,15 @@ extension CustomError: LocalizedError {
568
679
  }
569
680
 
570
681
  private func bundleExists(id: String) -> Bool {
571
- let destHot: URL = self.getPathHot(id: id)
572
- let destHotPersist: URL = self.getPathPersist(id: id)
682
+ let destHot: URL = self.getBundleDirectory(id: id)
573
683
  let indexHot: URL = destHot.appendingPathComponent("index.html")
574
- let indexPersist: URL = destHotPersist.appendingPathComponent("index.html")
575
- let url: URL = self.getBundleDirectory(id: id)
576
684
  let bundleIndo: BundleInfo = self.getBundleInfo(id: id)
577
- if url.isDirectory && destHotPersist.isDirectory && indexHot.exist && indexPersist.exist && !bundleIndo.isDeleted() {
685
+ if
686
+ destHot.exist &&
687
+ destHot.isDirectory &&
688
+ !indexHot.isDirectory &&
689
+ indexHot.exist &&
690
+ !bundleIndo.isDeleted() {
578
691
  return true
579
692
  }
580
693
  return false
@@ -587,9 +700,10 @@ extension CustomError: LocalizedError {
587
700
  return true
588
701
  }
589
702
  if bundleExists(id: id) {
703
+ let currentBundleName = self.getCurrentBundle().getVersionName()
590
704
  self.setCurrentBundle(bundle: self.getBundleDirectory(id: id).path)
591
705
  self.setBundleStatus(id: id, status: BundleStatus.PENDING)
592
- self.sendStats(action: "set", versionName: newBundle.getVersionName())
706
+ self.sendStats(action: "set", versionName: newBundle.getVersionName(), oldVersionName: currentBundleName)
593
707
  return true
594
708
  }
595
709
  self.setBundleStatus(id: id, status: BundleStatus.ERROR)
@@ -597,12 +711,12 @@ extension CustomError: LocalizedError {
597
711
  return false
598
712
  }
599
713
 
600
- public func getPathHot(id: String) -> URL {
601
- return documentsDir.appendingPathComponent(self.bundleDirectoryHot).appendingPathComponent(id)
602
- }
603
-
604
- public func getPathPersist(id: String) -> URL {
605
- return libraryDir.appendingPathComponent(self.bundleDirectory).appendingPathComponent(id)
714
+ public func autoReset() {
715
+ let currentBundle: BundleInfo = self.getCurrentBundle()
716
+ if !currentBundle.isBuiltin() && !self.bundleExists(id: currentBundle.getId()) {
717
+ print("\(self.TAG) Folder at bundle path does not exist. Triggering reset.")
718
+ self.reset()
719
+ }
606
720
  }
607
721
 
608
722
  public func reset() {
@@ -611,11 +725,12 @@ extension CustomError: LocalizedError {
611
725
 
612
726
  public func reset(isInternal: Bool) {
613
727
  print("\(self.TAG) reset: \(isInternal)")
728
+ let currentBundleName = self.getCurrentBundle().getVersionName()
614
729
  self.setCurrentBundle(bundle: "")
615
730
  self.setFallbackBundle(fallback: Optional<BundleInfo>.none)
616
731
  _ = self.setNextBundle(next: Optional<String>.none)
617
732
  if !isInternal {
618
- self.sendStats(action: "reset", versionName: self.getCurrentBundle().getVersionName())
733
+ self.sendStats(action: "reset", versionName: self.getCurrentBundle().getVersionName(), oldVersionName: currentBundleName)
619
734
  }
620
735
  }
621
736
 
@@ -639,6 +754,42 @@ extension CustomError: LocalizedError {
639
754
  self.setBundleStatus(id: bundle.getId(), status: BundleStatus.ERROR)
640
755
  }
641
756
 
757
+ func unsetChannel() -> SetChannel {
758
+ let setChannel: SetChannel = SetChannel()
759
+ if (self.channelUrl ).isEmpty {
760
+ print("\(self.TAG) Channel URL is not set")
761
+ setChannel.message = "Channel URL is not set"
762
+ setChannel.error = "missing_config"
763
+ return setChannel
764
+ }
765
+ let semaphore: DispatchSemaphore = DispatchSemaphore(value: 0)
766
+ let parameters: InfoObject = self.createInfoObject()
767
+
768
+ let request = AF.request(self.channelUrl, method: .delete, parameters: parameters, encoder: JSONParameterEncoder.default, requestModifier: { $0.timeoutInterval = self.timeout })
769
+
770
+ request.validate().responseDecodable(of: SetChannelDec.self) { response in
771
+ switch response.result {
772
+ case .success:
773
+ if let status = response.value?.status {
774
+ setChannel.status = status
775
+ }
776
+ if let error = response.value?.error {
777
+ setChannel.error = error
778
+ }
779
+ if let message = response.value?.message {
780
+ setChannel.message = message
781
+ }
782
+ case let .failure(error):
783
+ print("\(self.TAG) Error unset Channel", response.value ?? "", error)
784
+ setChannel.message = "Error unset Channel \(String(describing: response.value))"
785
+ setChannel.error = "response_error"
786
+ }
787
+ semaphore.signal()
788
+ }
789
+ semaphore.wait()
790
+ return setChannel
791
+ }
792
+
642
793
  func setChannel(channel: String) -> SetChannel {
643
794
  let setChannel: SetChannel = SetChannel()
644
795
  if (self.channelUrl ).isEmpty {
@@ -717,18 +868,31 @@ extension CustomError: LocalizedError {
717
868
  return getChannel
718
869
  }
719
870
 
720
- func sendStats(action: String, versionName: String) {
721
- if (self.statsUrl ).isEmpty {
871
+ func sendStats(action: String, versionName: String? = nil, oldVersionName: String? = "") {
872
+ guard !statsUrl.isEmpty else {
722
873
  return
723
874
  }
724
- var parameters: InfoObject = self.createInfoObject()
875
+
876
+ let versionName = versionName ?? getCurrentBundle().getVersionName()
877
+
878
+ var parameters = createInfoObject()
725
879
  parameters.action = action
880
+ parameters.version_name = versionName
881
+ parameters.old_version_name = oldVersionName
882
+
726
883
  DispatchQueue.global(qos: .background).async {
727
- let request = AF.request(self.statsUrl, method: .post, parameters: parameters, encoder: JSONParameterEncoder.default, requestModifier: { $0.timeoutInterval = self.timeout })
884
+ let request = AF.request(
885
+ self.statsUrl,
886
+ method: .post,
887
+ parameters: parameters,
888
+ encoder: JSONParameterEncoder.default,
889
+ requestModifier: { $0.timeoutInterval = self.timeout }
890
+ )
891
+
728
892
  request.responseData { response in
729
893
  switch response.result {
730
894
  case .success:
731
- print("\(self.TAG) Stats send for \(action), version \(versionName)")
895
+ print("\(self.TAG) Stats sent for \(action), version \(versionName)")
732
896
  case let .failure(error):
733
897
  print("\(self.TAG) Error sending stats: ", response.value ?? "", error)
734
898
  }
@@ -741,7 +905,7 @@ extension CustomError: LocalizedError {
741
905
  if id != nil {
742
906
  trueId = id!
743
907
  }
744
- print("\(self.TAG) Getting info for bundle [\(trueId)]")
908
+ // print("\(self.TAG) Getting info for bundle [\(trueId)]")
745
909
  let result: BundleInfo
746
910
  if BundleInfo.ID_BUILTIN == trueId {
747
911
  result = BundleInfo(id: trueId, version: "", status: BundleStatus.SUCCESS, checksum: "")
@@ -773,7 +937,7 @@ extension CustomError: LocalizedError {
773
937
  self.saveBundleInfo(id: id, bundle: nil)
774
938
  }
775
939
 
776
- private func saveBundleInfo(id: String, bundle: BundleInfo?) {
940
+ public func saveBundleInfo(id: String, bundle: BundleInfo?) {
777
941
  if bundle != nil && (bundle!.isBuiltin() || bundle!.isUnknown()) {
778
942
  print("\(self.TAG) Not saving info for bundle [\(id)]", bundle?.toString() ?? "")
779
943
  return
@@ -793,12 +957,6 @@ extension CustomError: LocalizedError {
793
957
  UserDefaults.standard.synchronize()
794
958
  }
795
959
 
796
- public func setVersionName(id: String, version: String) {
797
- print("\(self.TAG) Setting version for folder [\(id)] to \(version)")
798
- let info = self.getBundleInfo(id: id)
799
- self.saveBundleInfo(id: id, bundle: info.setVersionName(version: version))
800
- }
801
-
802
960
  private func setBundleStatus(id: String, status: BundleStatus) {
803
961
  print("\(self.TAG) Setting status for bundle [\(id)] to \(status)")
804
962
  let info = self.getBundleInfo(id: id)
@@ -846,8 +1004,7 @@ extension CustomError: LocalizedError {
846
1004
  return false
847
1005
  }
848
1006
  let newBundle: BundleInfo = self.getBundleInfo(id: nextId)
849
- let bundle: URL = self.getBundleDirectory(id: nextId)
850
- if !newBundle.isBuiltin() && !bundle.exist {
1007
+ if !newBundle.isBuiltin() && !self.bundleExists(id: nextId) {
851
1008
  return false
852
1009
  }
853
1010
  UserDefaults.standard.set(nextId, forKey: self.NEXT_VERSION)
@@ -5,6 +5,9 @@
5
5
  // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
6
  CAP_PLUGIN(CapacitorUpdaterPlugin, "CapacitorUpdater",
7
7
  CAP_PLUGIN_METHOD(download, CAPPluginReturnPromise);
8
+ CAP_PLUGIN_METHOD(setUpdateUrl, CAPPluginReturnPromise);
9
+ CAP_PLUGIN_METHOD(setStatsUrl, CAPPluginReturnPromise);
10
+ CAP_PLUGIN_METHOD(setChannelUrl, CAPPluginReturnPromise);
8
11
  CAP_PLUGIN_METHOD(set, CAPPluginReturnPromise);
9
12
  CAP_PLUGIN_METHOD(list, CAPPluginReturnPromise);
10
13
  CAP_PLUGIN_METHOD(delete, CAPPluginReturnPromise);
@@ -23,5 +26,5 @@ CAP_PLUGIN(CapacitorUpdaterPlugin, "CapacitorUpdater",
23
26
  CAP_PLUGIN_METHOD(getPluginVersion, CAPPluginReturnPromise);
24
27
  CAP_PLUGIN_METHOD(next, CAPPluginReturnPromise);
25
28
  CAP_PLUGIN_METHOD(isAutoUpdateEnabled, CAPPluginReturnPromise);
26
- CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnPromise);
29
+ CAP_PLUGIN_METHOD(getBuiltinVersion, CAPPluginReturnPromise);
27
30
  )