@capgo/capacitor-updater 6.40.0 → 6.40.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.
@@ -85,7 +85,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
85
85
  private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
86
86
  private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
87
87
 
88
- private final String pluginVersion = "6.40.0";
88
+ private final String pluginVersion = "6.40.2";
89
89
  private static final String DELAY_CONDITION_PREFERENCES = "";
90
90
 
91
91
  private SharedPreferences.Editor editor;
@@ -181,7 +181,8 @@ public class CapgoUpdater {
181
181
  ZipEntry entry;
182
182
  while ((entry = zis.getNextEntry()) != null) {
183
183
  if (entry.getName().contains("\\")) {
184
- logger.error("unzip: Windows path is not supported, please use unix path as require by zip RFC: " + entry.getName());
184
+ logger.error("Unzip failed: Windows path not supported");
185
+ logger.debug("Invalid path: " + entry.getName());
185
186
  this.sendStats("windows_path_fail");
186
187
  }
187
188
  final File file = new File(targetDirectory, entry.getName());
@@ -277,7 +278,8 @@ public class CapgoUpdater {
277
278
  boolean success = finishDownload(id, dest, version, sessionKey, checksum, true, isManifest);
278
279
  BundleInfo resultBundle;
279
280
  if (!success) {
280
- logger.error("Finish download failed: " + version);
281
+ logger.error("Finish download failed");
282
+ logger.debug("Version: " + version);
281
283
  resultBundle = new BundleInfo(
282
284
  id,
283
285
  version,
@@ -309,7 +311,8 @@ public class CapgoUpdater {
309
311
  case FAILED:
310
312
  Data failedData = workInfo.getOutputData();
311
313
  String error = failedData.getString(DownloadService.ERROR);
312
- logger.error("Download failed: " + error + " " + workInfo.getState());
314
+ logger.error("Download failed");
315
+ logger.debug("Error: " + error + ", State: " + workInfo.getState());
313
316
  String failedVersion = failedData.getString(DownloadService.VERSION);
314
317
 
315
318
  io.execute(() -> {
@@ -428,7 +431,8 @@ public class CapgoUpdater {
428
431
  CryptoCipher.logChecksumInfo("Calculated checksum", checksum);
429
432
  CryptoCipher.logChecksumInfo("Expected checksum", checksumDecrypted);
430
433
  if ((!checksumDecrypted.isEmpty() || !this.publicKey.isEmpty()) && !checksumDecrypted.equals(checksum)) {
431
- logger.error("Error checksum '" + checksumDecrypted + "' '" + checksum + "' '");
434
+ logger.error("Checksum mismatch");
435
+ logger.debug("Expected: " + checksumDecrypted + ", Got: " + checksum);
432
436
  this.sendStats("checksum_fail");
433
437
  throw new IOException("Checksum failed: " + id);
434
438
  }
@@ -440,7 +444,8 @@ public class CapgoUpdater {
440
444
  }
441
445
  final Boolean res = this.delete(id);
442
446
  if (!res) {
443
- logger.info("Double error, cannot cleanup: " + version);
447
+ logger.info("Failed to cleanup after error");
448
+ logger.debug("Version: " + version);
444
449
  }
445
450
 
446
451
  final Map<String, Object> ret = new HashMap<>();
@@ -541,7 +546,8 @@ public class CapgoUpdater {
541
546
  this.deleteDirectory(cacheFolder, threadToCheck);
542
547
  logger.info("Cleaned up delta cache folder");
543
548
  } catch (IOException e) {
544
- logger.error("Failed to cleanup delta cache: " + e.getMessage());
549
+ logger.error("Failed to cleanup delta cache");
550
+ logger.debug("Error: " + e.getMessage());
545
551
  }
546
552
  }
547
553
 
@@ -582,9 +588,11 @@ public class CapgoUpdater {
582
588
  try {
583
589
  this.deleteDirectory(entry, threadToCheck);
584
590
  this.removeBundleInfo(id);
585
- logger.info("Deleted orphan bundle directory: " + id);
591
+ logger.info("Deleted orphan bundle directory");
592
+ logger.debug("Bundle ID: " + id);
586
593
  } catch (IOException e) {
587
- logger.error("Failed to delete orphan bundle directory: " + id + " " + e.getMessage());
594
+ logger.error("Failed to delete orphan bundle directory");
595
+ logger.debug("Bundle ID: " + id + ", Error: " + e.getMessage());
588
596
  }
589
597
  }
590
598
  }
@@ -621,9 +629,11 @@ public class CapgoUpdater {
621
629
 
622
630
  try {
623
631
  this.deleteDirectory(entry, threadToCheck);
624
- logger.info("Deleted orphaned temp unzip folder: " + folderName);
632
+ logger.info("Deleted orphaned temp unzip folder");
633
+ logger.debug("Folder: " + folderName);
625
634
  } catch (IOException e) {
626
- logger.error("Failed to delete orphaned temp folder: " + folderName + " " + e.getMessage());
635
+ logger.error("Failed to delete orphaned temp folder");
636
+ logger.debug("Folder: " + folderName + ", Error: " + e.getMessage());
627
637
  }
628
638
  }
629
639
  }
@@ -710,7 +720,8 @@ public class CapgoUpdater {
710
720
  } catch (Exception e) {
711
721
  // Clean up on failure
712
722
  downloadFutures.remove(id);
713
- logger.error("Error waiting for download: " + e.getMessage());
723
+ logger.error("Error waiting for download");
724
+ logger.debug("Error: " + e.getMessage());
714
725
  BundleInfo errorBundle = new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), "");
715
726
  saveBundleInfo(id, errorBundle);
716
727
  if (e instanceof IOException) {
@@ -750,12 +761,14 @@ public class CapgoUpdater {
750
761
  public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
751
762
  final BundleInfo deleted = this.getBundleInfo(id);
752
763
  if (deleted.isBuiltin() || this.getCurrentBundleId().equals(id)) {
753
- logger.error("Cannot delete " + id);
764
+ logger.error("Cannot delete current or builtin bundle");
765
+ logger.debug("Bundle ID: " + id);
754
766
  return false;
755
767
  }
756
768
  final BundleInfo next = this.getNextBundle();
757
769
  if (next != null && !next.isDeleted() && !next.isErrorStatus() && next.getId().equals(id)) {
758
- logger.error("Cannot delete the next bundle" + id);
770
+ logger.error("Cannot delete the next bundle");
771
+ logger.debug("Bundle ID: " + id);
759
772
  return false;
760
773
  }
761
774
  // Cancel download for this version if active
@@ -772,7 +785,8 @@ public class CapgoUpdater {
772
785
  }
773
786
  return true;
774
787
  }
775
- logger.error("bundle removed: " + deleted.getVersionName());
788
+ logger.info("Bundle not found on disk");
789
+ logger.debug("Version: " + deleted.getVersionName());
776
790
  // perhaps we did not find the bundle in the files, but if the user requested a delete, we delete
777
791
  if (removeInfo) {
778
792
  this.removeBundleInfo(id);
@@ -943,11 +957,13 @@ public class CapgoUpdater {
943
957
  if (response.isSuccessful()) {
944
958
  logger.info("Rate limit statistic sent");
945
959
  } else {
946
- logger.error("Error sending rate limit statistic: " + response.code());
960
+ logger.error("Error sending rate limit statistic");
961
+ logger.debug("Response code: " + response.code());
947
962
  }
948
963
  }
949
964
  } catch (final Exception e) {
950
- logger.error("Failed to send rate limit statistic: " + e.getMessage());
965
+ logger.error("Failed to send rate limit statistic");
966
+ logger.debug("Error: " + e.getMessage());
951
967
  }
952
968
  }
953
969
 
@@ -1044,7 +1060,8 @@ public class CapgoUpdater {
1044
1060
  json.put("defaultChannel", channel);
1045
1061
  }
1046
1062
  } catch (JSONException e) {
1047
- logger.error("Error getLatest JSONException " + e.getMessage());
1063
+ logger.error("Error getting latest version");
1064
+ logger.debug("JSONException: " + e.getMessage());
1048
1065
  final Map<String, Object> retError = new HashMap<>();
1049
1066
  retError.put("message", "Cannot get info: " + e);
1050
1067
  retError.put("error", "json_error");
@@ -1116,7 +1133,8 @@ public class CapgoUpdater {
1116
1133
  json = this.createInfoObject();
1117
1134
  json.put("channel", channel);
1118
1135
  } catch (JSONException e) {
1119
- logger.error("Error setChannel JSONException " + e.getMessage());
1136
+ logger.error("Error setting channel");
1137
+ logger.debug("JSONException: " + e.getMessage());
1120
1138
  final Map<String, Object> retError = new HashMap<>();
1121
1139
  retError.put("message", "Cannot get info: " + e);
1122
1140
  retError.put("error", "json_error");
@@ -1162,7 +1180,8 @@ public class CapgoUpdater {
1162
1180
  try {
1163
1181
  json = this.createInfoObject();
1164
1182
  } catch (JSONException e) {
1165
- logger.error("Error getChannel JSONException " + e.getMessage());
1183
+ logger.error("Error getting channel");
1184
+ logger.debug("JSONException: " + e.getMessage());
1166
1185
  final Map<String, Object> retError = new HashMap<>();
1167
1186
  retError.put("message", "Cannot get info: " + e);
1168
1187
  retError.put("error", "json_error");
@@ -1284,7 +1303,8 @@ public class CapgoUpdater {
1284
1303
  try {
1285
1304
  json = this.createInfoObject();
1286
1305
  } catch (JSONException e) {
1287
- logger.error("Error creating info object: " + e.getMessage());
1306
+ logger.error("Error creating info object");
1307
+ logger.debug("JSONException: " + e.getMessage());
1288
1308
  final Map<String, Object> retError = new HashMap<>();
1289
1309
  retError.put("message", "Cannot get info: " + e);
1290
1310
  retError.put("error", "json_error");
@@ -1304,7 +1324,8 @@ public class CapgoUpdater {
1304
1324
  }
1305
1325
  }
1306
1326
  } catch (JSONException e) {
1307
- logger.error("Error adding query parameters: " + e.getMessage());
1327
+ logger.error("Error adding query parameters");
1328
+ logger.debug("JSONException: " + e.getMessage());
1308
1329
  }
1309
1330
 
1310
1331
  Request request = new Request.Builder().url(urlBuilder.build()).get().build();
@@ -1425,7 +1446,8 @@ public class CapgoUpdater {
1425
1446
  json.put("old_version_name", oldVersionName);
1426
1447
  json.put("action", action);
1427
1448
  } catch (JSONException e) {
1428
- logger.error("Error sendStats JSONException " + e.getMessage());
1449
+ logger.error("Error preparing stats");
1450
+ logger.debug("JSONException: " + e.getMessage());
1429
1451
  return;
1430
1452
  }
1431
1453
 
@@ -1440,7 +1462,8 @@ public class CapgoUpdater {
1440
1462
  new okhttp3.Callback() {
1441
1463
  @Override
1442
1464
  public void onFailure(@NonNull Call call, @NonNull IOException e) {
1443
- logger.error("Failed to send stats: " + e.getMessage());
1465
+ logger.error("Failed to send stats");
1466
+ logger.debug("Error: " + e.getMessage());
1444
1467
  }
1445
1468
 
1446
1469
  @Override
@@ -1452,9 +1475,11 @@ public class CapgoUpdater {
1452
1475
  }
1453
1476
 
1454
1477
  if (response.isSuccessful()) {
1455
- logger.info("Stats send for \"" + action + "\", version " + versionName);
1478
+ logger.info("Stats sent successfully");
1479
+ logger.debug("Action: " + action + ", Version: " + versionName);
1456
1480
  } else {
1457
- logger.error("Error sending stats: " + response.code());
1481
+ logger.error("Error sending stats");
1482
+ logger.debug("Response code: " + response.code());
1458
1483
  }
1459
1484
  }
1460
1485
  }
@@ -1481,14 +1506,8 @@ public class CapgoUpdater {
1481
1506
  result = BundleInfo.fromJSON(stored);
1482
1507
  }
1483
1508
  } catch (JSONException e) {
1484
- logger.error(
1485
- "Failed to parse info for bundle [" +
1486
- trueId +
1487
- "] stored value: '" +
1488
- this.prefs.getString(trueId + INFO_SUFFIX, "") +
1489
- "' error: " +
1490
- e.getMessage()
1491
- );
1509
+ logger.error("Failed to parse bundle info");
1510
+ logger.debug("Bundle ID: " + trueId + ", Error: " + e.getMessage());
1492
1511
  // Clear corrupted data
1493
1512
  this.editor.remove(trueId + INFO_SUFFIX);
1494
1513
  this.editor.commit();
@@ -235,14 +235,11 @@ public class CryptoCipher {
235
235
  detectedAlgorithm = "SHA-256";
236
236
  } else if (decryptedChecksum.length == 4) {
237
237
  detectedAlgorithm = "CRC32 (deprecated)";
238
- logger.error(
239
- "CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
240
- );
238
+ logger.error("CRC32 checksum detected - deprecated algorithm");
241
239
  } else {
242
240
  detectedAlgorithm = "unknown (" + decryptedChecksum.length + " bytes)";
243
- logger.error(
244
- "Unknown checksum algorithm detected with " + decryptedChecksum.length + " bytes. Expected SHA-256 (32 bytes)."
245
- );
241
+ logger.error("Unknown checksum algorithm detected");
242
+ logger.debug("Byte count: " + decryptedChecksum.length + ", Expected: 32 (SHA-256)");
246
243
  }
247
244
  logger.debug(
248
245
  "Decrypted checksum: " +
@@ -255,7 +252,8 @@ public class CryptoCipher {
255
252
  );
256
253
  return result;
257
254
  } catch (GeneralSecurityException e) {
258
- logger.error("decryptChecksum fail: " + e.getMessage());
255
+ logger.error("Checksum decryption failed");
256
+ logger.debug("Error: " + e.getMessage());
259
257
  throw new IOException("Decryption failed: " + e.getMessage());
260
258
  }
261
259
  }
@@ -286,13 +284,10 @@ public class CryptoCipher {
286
284
  String algorithm = detectChecksumAlgorithm(hexChecksum);
287
285
  logger.debug(label + ": " + algorithm + " hex format (length: " + hexChecksum.length() + " chars)");
288
286
  if (algorithm.contains("CRC32")) {
289
- logger.error(
290
- "CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
291
- );
287
+ logger.error("CRC32 checksum detected - deprecated algorithm");
292
288
  } else if (algorithm.contains("unknown")) {
293
- logger.error(
294
- "Unknown checksum algorithm detected. Expected SHA-256 (64 hex chars) but got " + hexChecksum.length() + " chars."
295
- );
289
+ logger.error("Unknown checksum algorithm detected");
290
+ logger.debug("Char count: " + hexChecksum.length() + ", Expected: 64 (SHA-256)");
296
291
  }
297
292
  }
298
293
 
@@ -321,7 +316,8 @@ public class CryptoCipher {
321
316
  }
322
317
  return hexString.toString();
323
318
  } catch (IOException e) {
324
- logger.error("Cannot calc checksum v2: " + file.getPath() + " " + e.getMessage());
319
+ logger.error("Cannot calculate checksum");
320
+ logger.debug("Path: " + file.getPath() + ", Error: " + e.getMessage());
325
321
  return "";
326
322
  }
327
323
  }
@@ -60,7 +60,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
60
60
  CAPPluginMethod(name: "completeFlexibleUpdate", returnType: CAPPluginReturnPromise)
61
61
  ]
62
62
  public var implementation = CapgoUpdater()
63
- private let pluginVersion: String = "6.40.0"
63
+ private let pluginVersion: String = "6.40.2"
64
64
  static let updateUrlDefault = "https://plugin.capgo.app/updates"
65
65
  static let statsUrlDefault = "https://plugin.capgo.app/stats"
66
66
  static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
@@ -157,7 +157,8 @@ import UIKit
157
157
  case .success:
158
158
  self.logger.info("Rate limit statistic sent")
159
159
  case let .failure(error):
160
- self.logger.error("Error sending rate limit statistic: \(error.localizedDescription)")
160
+ self.logger.error("Error sending rate limit statistic")
161
+ self.logger.debug("Error: \(error.localizedDescription)")
161
162
  }
162
163
  semaphore.signal()
163
164
  }
@@ -203,7 +204,8 @@ import UIKit
203
204
  do {
204
205
  try FileManager.default.createDirectory(atPath: source.path, withIntermediateDirectories: true, attributes: nil)
205
206
  } catch {
206
- logger.error("Cannot createDirectory \(source.path)")
207
+ logger.error("Cannot create directory")
208
+ logger.debug("Directory path: \(source.path)")
207
209
  throw CustomError.cannotCreateDirectory
208
210
  }
209
211
  }
@@ -213,7 +215,8 @@ import UIKit
213
215
  do {
214
216
  try FileManager.default.removeItem(atPath: source.path)
215
217
  } catch {
216
- logger.error("File not removed. \(source.path)")
218
+ logger.error("File not removed")
219
+ logger.debug("Path: \(source.path)")
217
220
  throw CustomError.cannotDeleteDirectory
218
221
  }
219
222
  }
@@ -230,7 +233,8 @@ import UIKit
230
233
  return false
231
234
  }
232
235
  } catch {
233
- logger.error("File not moved. source: \(source.path) dest: \(dest.path)")
236
+ logger.error("File not moved")
237
+ logger.debug("Source: \(source.path), Dest: \(dest.path)")
234
238
  throw CustomError.cannotUnflat
235
239
  }
236
240
  }
@@ -238,7 +242,8 @@ import UIKit
238
242
  private func validateZipEntry(path: String, destUnZip: URL) throws {
239
243
  // Check for Windows paths
240
244
  if path.contains("\\") {
241
- logger.error("unzip: Windows path is not supported, please use unix path as required by zip RFC: \(path)")
245
+ logger.error("Unzip failed: Windows path not supported")
246
+ logger.debug("Invalid path: \(path)")
242
247
  self.sendStats(action: "windows_path_fail")
243
248
  throw CustomError.cannotUnzip
244
249
  }
@@ -320,7 +325,8 @@ import UIKit
320
325
  try FileManager.default.removeItem(at: sourceZip)
321
326
  }
322
327
  } catch {
323
- logger.error("Could not delete source zip at \(sourceZip.path): \(error)")
328
+ logger.error("Could not delete source zip")
329
+ logger.debug("Path: \(sourceZip.path), Error: \(error)")
324
330
  }
325
331
  }
326
332
 
@@ -395,8 +401,9 @@ import UIKit
395
401
  latest.comment = comment
396
402
  }
397
403
  case let .failure(error):
398
- self.logger.error("Error getting Latest \(response.value.debugDescription) \(error)")
399
- latest.message = "Error getting Latest \(String(describing: response.value))"
404
+ self.logger.error("Error getting latest version")
405
+ self.logger.debug("Response: \(response.value.debugDescription), Error: \(error)")
406
+ latest.message = "Error getting Latest"
400
407
  latest.error = "response_error"
401
408
  latest.statusCode = response.response?.statusCode ?? 0
402
409
  }
@@ -464,7 +471,8 @@ import UIKit
464
471
  fileHash = try CryptoCipher.decryptChecksum(checksum: fileHash, publicKey: self.publicKey)
465
472
  } catch {
466
473
  downloadError = error
467
- logger.error("CryptoCipher.decryptChecksum error \(id) \(fileName) error: \(error)")
474
+ logger.error("Checksum decryption failed")
475
+ logger.debug("Bundle: \(id), File: \(fileName), Error: \(error)")
468
476
  }
469
477
  } else if self.hasOldPrivateKeyPropertyInConfig {
470
478
  // V1 Encryption (privateKey) - deprecated but supported
@@ -496,7 +504,8 @@ import UIKit
496
504
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
497
505
  } catch {
498
506
  downloadError = error
499
- logger.error("Failed to copy builtin file \(fileName): \(error.localizedDescription)")
507
+ logger.error("Failed to copy builtin file")
508
+ logger.debug("File: \(fileName), Error: \(error.localizedDescription)")
500
509
  }
501
510
  dispatchGroup.leave()
502
511
  } else if self.tryCopyFromCache(from: cacheFilePath, to: destFilePath, expectedHash: fileHash) {
@@ -570,15 +579,18 @@ import UIKit
570
579
 
571
580
  completedFiles += 1
572
581
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
573
- self.logger.info("downloadManifest \(id) \(fileName) downloaded\(isBrotli ? ", decompressed" : "")\(!self.publicKey.isEmpty && !sessionKey.isEmpty ? ", decrypted" : ""), and cached")
582
+ self.logger.info("Manifest file downloaded and cached")
583
+ self.logger.debug("Bundle: \(id), File: \(fileName), Brotli: \(isBrotli), Encrypted: \(!self.publicKey.isEmpty && !sessionKey.isEmpty)")
574
584
  } catch {
575
585
  downloadError = error
576
- self.logger.error("downloadManifest \(id) \(fileName) error: \(error.localizedDescription)")
586
+ self.logger.error("Manifest file download failed")
587
+ self.logger.debug("Bundle: \(id), File: \(fileName), Error: \(error.localizedDescription)")
577
588
  }
578
589
  case .failure(let error):
579
590
  downloadError = error
580
591
  self.sendStats(action: "download_manifest_file_fail", versionName: "\(version):\(fileName)")
581
- self.logger.error("downloadManifest \(id) \(fileName) download error: \(error.localizedDescription). Debug response: \(response.debugDescription).")
592
+ self.logger.error("Manifest file download network error")
593
+ self.logger.debug("Bundle: \(id), File: \(fileName), Error: \(error.localizedDescription), Response: \(response.debugDescription)")
582
594
  }
583
595
  }
584
596
  }
@@ -666,7 +678,8 @@ import UIKit
666
678
  var status = compression_stream_init(streamPointer, COMPRESSION_STREAM_DECODE, COMPRESSION_BROTLI)
667
679
 
668
680
  guard status != COMPRESSION_STATUS_ERROR else {
669
- logger.error("Error: Failed to initialize Brotli stream for \(fileName). Status: \(status)")
681
+ logger.error("Failed to initialize Brotli stream")
682
+ logger.debug("File: \(fileName), Status: \(status)")
670
683
  return nil
671
684
  }
672
685
 
@@ -688,7 +701,8 @@ import UIKit
688
701
  if let baseAddress = rawBufferPointer.baseAddress {
689
702
  streamPointer.pointee.src_ptr = baseAddress.assumingMemoryBound(to: UInt8.self)
690
703
  } else {
691
- logger.error("Error: Failed to get base address for \(fileName)")
704
+ logger.error("Failed to get base address for Brotli decompression")
705
+ logger.debug("File: \(fileName)")
692
706
  status = COMPRESSION_STATUS_ERROR
693
707
  return
694
708
  }
@@ -698,7 +712,8 @@ import UIKit
698
712
  if status == COMPRESSION_STATUS_ERROR {
699
713
  let maxBytes = min(32, data.count)
700
714
  let hexDump = data.prefix(maxBytes).map { String(format: "%02x", $0) }.joined(separator: " ")
701
- logger.error("Error: Brotli decompression failed for \(fileName). First \(maxBytes) bytes: \(hexDump)")
715
+ logger.error("Brotli decompression failed")
716
+ logger.debug("File: \(fileName), First \(maxBytes) bytes: \(hexDump)")
702
717
  break
703
718
  }
704
719
 
@@ -712,18 +727,19 @@ import UIKit
712
727
  if status == COMPRESSION_STATUS_END {
713
728
  break
714
729
  } else if status == COMPRESSION_STATUS_ERROR {
715
- logger.error("Error: Brotli process failed for \(fileName). Status: \(status)")
730
+ logger.error("Brotli process failed")
731
+ logger.debug("File: \(fileName), Status: \(status)")
716
732
  if let text = String(data: data, encoding: .utf8) {
717
733
  let asciiCount = text.unicodeScalars.filter { $0.isASCII }.count
718
734
  let totalCount = text.unicodeScalars.count
719
735
  if totalCount > 0 && Double(asciiCount) / Double(totalCount) >= 0.8 {
720
- logger.error("Error: Input appears to be plain text: \(text)")
736
+ logger.debug("Input appears to be plain text: \(text)")
721
737
  }
722
738
  }
723
739
 
724
740
  let maxBytes = min(32, data.count)
725
741
  let hexDump = data.prefix(maxBytes).map { String(format: "%02x", $0) }.joined(separator: " ")
726
- logger.error("Error: Raw data (\(fileName)): \(hexDump)")
742
+ logger.debug("Raw data: \(hexDump)")
727
743
 
728
744
  return nil
729
745
  }
@@ -734,7 +750,8 @@ import UIKit
734
750
  }
735
751
 
736
752
  if input.count == 0 {
737
- logger.error("Error: Zero input size for \(fileName)")
753
+ logger.error("Zero input size for Brotli decompression")
754
+ logger.debug("File: \(fileName)")
738
755
  break
739
756
  }
740
757
  }
@@ -826,7 +843,8 @@ import UIKit
826
843
  reachabilityManager?.stopListening()
827
844
 
828
845
  if mainError != nil {
829
- logger.error("Failed to download: \(String(describing: mainError))")
846
+ logger.error("Failed to download bundle")
847
+ logger.debug("Error: \(String(describing: mainError))")
830
848
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
831
849
  throw mainError!
832
850
  }
@@ -837,7 +855,8 @@ import UIKit
837
855
  try CryptoCipher.decryptFile(filePath: tempDataPath, publicKey: self.publicKey, sessionKey: sessionKey, version: version)
838
856
  try FileManager.default.moveItem(at: tempDataPath, to: finalPath)
839
857
  } catch {
840
- logger.error("Failed decrypt file : \(error)")
858
+ logger.error("Failed to decrypt file")
859
+ logger.debug("Error: \(error)")
841
860
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
842
861
  cleanDownloadData()
843
862
  throw error
@@ -850,7 +869,8 @@ import UIKit
850
869
  try self.saveDownloaded(sourceZip: finalPath, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory), notify: true)
851
870
 
852
871
  } catch {
853
- logger.error("Failed to unzip file: \(error)")
872
+ logger.error("Failed to unzip file")
873
+ logger.debug("Error: \(error)")
854
874
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
855
875
  // Best-effort cleanup of the decrypted zip file when unzip fails
856
876
  do {
@@ -858,7 +878,8 @@ import UIKit
858
878
  try FileManager.default.removeItem(at: finalPath)
859
879
  }
860
880
  } catch {
861
- logger.error("Could not delete failed zip at \(finalPath.path): \(error)")
881
+ logger.error("Could not delete failed zip")
882
+ logger.debug("Path: \(finalPath.path), Error: \(error)")
862
883
  }
863
884
  cleanDownloadData()
864
885
  throw error
@@ -881,13 +902,15 @@ import UIKit
881
902
  let fileManager = FileManager.default
882
903
  if !fileManager.fileExists(atPath: tempDataPath.path) {
883
904
  if !fileManager.createFile(atPath: tempDataPath.path, contents: Data()) {
884
- logger.error("Cannot ensure that a file at \(tempDataPath.path) exists")
905
+ logger.error("Cannot ensure temp data file exists")
906
+ logger.debug("Path: \(tempDataPath.path)")
885
907
  }
886
908
  }
887
909
 
888
910
  if !fileManager.fileExists(atPath: updateInfo.path) {
889
911
  if !fileManager.createFile(atPath: updateInfo.path, contents: Data()) {
890
- logger.error("Cannot ensure that a file at \(updateInfo.path) exists")
912
+ logger.error("Cannot ensure update info file exists")
913
+ logger.debug("Path: \(updateInfo.path)")
891
914
  }
892
915
  }
893
916
  }
@@ -899,7 +922,8 @@ import UIKit
899
922
  do {
900
923
  try fileManager.removeItem(at: tempDataPath)
901
924
  } catch {
902
- logger.error("Could not delete file at \(tempDataPath): \(error)")
925
+ logger.error("Could not delete temp data file")
926
+ logger.debug("Path: \(tempDataPath), Error: \(error)")
903
927
  }
904
928
  }
905
929
  // Deleting update.dat
@@ -907,7 +931,8 @@ import UIKit
907
931
  do {
908
932
  try fileManager.removeItem(at: updateInfo)
909
933
  } catch {
910
- logger.error("Could not delete file at \(updateInfo): \(error)")
934
+ logger.error("Could not delete update info file")
935
+ logger.debug("Path: \(updateInfo), Error: \(error)")
911
936
  }
912
937
  }
913
938
  }
@@ -926,7 +951,8 @@ import UIKit
926
951
  fileHandle.closeFile()
927
952
  }
928
953
  } catch {
929
- logger.error("Failed to write data starting at byte \(byteOffset): \(error)")
954
+ logger.error("Failed to write partial data")
955
+ logger.debug("Byte offset: \(byteOffset), Error: \(error)")
930
956
  }
931
957
  self.tempData.removeAll() // Clearing tempData to avoid writing the same data multiple times
932
958
  }
@@ -935,7 +961,8 @@ import UIKit
935
961
  do {
936
962
  try "\(version)".write(to: updateInfo, atomically: true, encoding: .utf8)
937
963
  } catch {
938
- logger.error("Failed to save progress: \(error)")
964
+ logger.error("Failed to save download progress")
965
+ logger.debug("Error: \(error)")
939
966
  }
940
967
  }
941
968
  private func getLocalUpdateVersion() -> String { // Return the version that was tried to be downloaded on last download attempt
@@ -957,7 +984,8 @@ import UIKit
957
984
  return fileSize.int64Value
958
985
  }
959
986
  } catch {
960
- logger.error("Could not retrieve already downloaded data size : \(error)")
987
+ logger.error("Could not retrieve download progress size")
988
+ logger.debug("Error: \(error)")
961
989
  }
962
990
  return 0
963
991
  }
@@ -1001,7 +1029,8 @@ import UIKit
1001
1029
  public func delete(id: String, removeInfo: Bool) -> Bool {
1002
1030
  let deleted: BundleInfo = self.getBundleInfo(id: id)
1003
1031
  if deleted.isBuiltin() || self.getCurrentBundleId() == id {
1004
- logger.info("Cannot delete \(id)")
1032
+ logger.info("Cannot delete current or builtin bundle")
1033
+ logger.debug("Bundle ID: \(id)")
1005
1034
  return false
1006
1035
  }
1007
1036
 
@@ -1010,7 +1039,8 @@ import UIKit
1010
1039
  !next.isDeleted() &&
1011
1040
  !next.isErrorStatus() &&
1012
1041
  next.getId() == id {
1013
- logger.info("Cannot delete the next bundle \(id)")
1042
+ logger.info("Cannot delete the next bundle")
1043
+ logger.debug("Bundle ID: \(id)")
1014
1044
  return false
1015
1045
  }
1016
1046
 
@@ -1018,7 +1048,8 @@ import UIKit
1018
1048
  do {
1019
1049
  try FileManager.default.removeItem(atPath: destPersist.path)
1020
1050
  } catch {
1021
- logger.error("Folder \(destPersist.path), not removed.")
1051
+ logger.error("Bundle folder not removed")
1052
+ logger.debug("Path: \(destPersist.path)")
1022
1053
  // even if, we don;t care. Android doesn't care
1023
1054
  if removeInfo {
1024
1055
  self.removeBundleInfo(id: id)
@@ -1031,7 +1062,8 @@ import UIKit
1031
1062
  } else {
1032
1063
  self.saveBundleInfo(id: id, bundle: deleted.setStatus(status: BundleStatus.DELETED.localizedString))
1033
1064
  }
1034
- logger.info("bundle delete \(deleted.getVersionName())")
1065
+ logger.info("Bundle deleted successfully")
1066
+ logger.debug("Version: \(deleted.getVersionName())")
1035
1067
  self.sendStats(action: "delete", versionName: deleted.getVersionName())
1036
1068
  return true
1037
1069
  }
@@ -1059,7 +1091,8 @@ import UIKit
1059
1091
  try fileManager.removeItem(at: cacheFolder)
1060
1092
  logger.info("Cleaned up delta cache folder")
1061
1093
  } catch {
1062
- logger.error("Failed to cleanup delta cache: \(error.localizedDescription)")
1094
+ logger.error("Failed to cleanup delta cache")
1095
+ logger.debug("Error: \(error.localizedDescription)")
1063
1096
  }
1064
1097
  }
1065
1098
 
@@ -1099,13 +1132,16 @@ import UIKit
1099
1132
  do {
1100
1133
  try fileManager.removeItem(at: url)
1101
1134
  self.removeBundleInfo(id: id)
1102
- logger.info("Deleted orphan bundle directory: \(id)")
1135
+ logger.info("Deleted orphan bundle directory")
1136
+ logger.debug("Bundle ID: \(id)")
1103
1137
  } catch {
1104
- logger.error("Failed to delete orphan bundle directory: \(id) \(error.localizedDescription)")
1138
+ logger.error("Failed to delete orphan bundle directory")
1139
+ logger.debug("Bundle ID: \(id), Error: \(error.localizedDescription)")
1105
1140
  }
1106
1141
  }
1107
1142
  } catch {
1108
- logger.error("Failed to enumerate bundle directory for cleanup: \(error.localizedDescription)")
1143
+ logger.error("Failed to enumerate bundle directory for cleanup")
1144
+ logger.debug("Error: \(error.localizedDescription)")
1109
1145
  }
1110
1146
  }
1111
1147
 
@@ -1136,13 +1172,16 @@ import UIKit
1136
1172
 
1137
1173
  do {
1138
1174
  try fileManager.removeItem(at: url)
1139
- logger.info("Deleted orphaned temp unzip folder: \(folderName)")
1175
+ logger.info("Deleted orphaned temp unzip folder")
1176
+ logger.debug("Folder: \(folderName)")
1140
1177
  } catch {
1141
- logger.error("Failed to delete orphaned temp folder: \(folderName) \(error.localizedDescription)")
1178
+ logger.error("Failed to delete orphaned temp folder")
1179
+ logger.debug("Folder: \(folderName), Error: \(error.localizedDescription)")
1142
1180
  }
1143
1181
  }
1144
1182
  } catch {
1145
- logger.error("Failed to enumerate library directory for temp folder cleanup: \(error.localizedDescription)")
1183
+ logger.error("Failed to enumerate library directory for temp folder cleanup")
1184
+ logger.debug("Error: \(error.localizedDescription)")
1146
1185
  }
1147
1186
  }
1148
1187
 
@@ -1218,9 +1257,11 @@ import UIKit
1218
1257
  if autoDeletePrevious && !fallback.isBuiltin() && fallback.getId() != bundle.getId() {
1219
1258
  let res = self.delete(id: fallback.getId())
1220
1259
  if res {
1221
- logger.info("Deleted previous bundle: \(fallback.toString())")
1260
+ logger.info("Deleted previous bundle")
1261
+ logger.debug("Bundle: \(fallback.toString())")
1222
1262
  } else {
1223
- logger.error("Failed to delete previous bundle: \(fallback.toString())")
1263
+ logger.error("Failed to delete previous bundle")
1264
+ logger.debug("Bundle: \(fallback.toString())")
1224
1265
  }
1225
1266
  }
1226
1267
  self.setFallbackBundle(fallback: bundle)
@@ -1301,7 +1342,8 @@ import UIKit
1301
1342
  }
1302
1343
  }
1303
1344
  case let .failure(error):
1304
- self.logger.error("Error set Channel \(error)")
1345
+ self.logger.error("Error setting channel")
1346
+ self.logger.debug("Error: \(error)")
1305
1347
  setChannel.error = "Request failed: \(error.localizedDescription)"
1306
1348
  }
1307
1349
  semaphore.signal()
@@ -1364,7 +1406,8 @@ import UIKit
1364
1406
  }
1365
1407
  }
1366
1408
 
1367
- self.logger.error("Error get Channel \(error)")
1409
+ self.logger.error("Error getting channel")
1410
+ self.logger.debug("Error: \(error)")
1368
1411
  getChannel.error = "Request failed: \(error.localizedDescription)"
1369
1412
  }
1370
1413
  }
@@ -1454,7 +1497,8 @@ import UIKit
1454
1497
  }
1455
1498
  }
1456
1499
  case let .failure(error):
1457
- self.logger.error("Error list channels \(error)")
1500
+ self.logger.error("Error listing channels")
1501
+ self.logger.debug("Error: \(error)")
1458
1502
  listChannels.error = "Request failed: \(error.localizedDescription)"
1459
1503
  }
1460
1504
  }
@@ -1500,9 +1544,11 @@ import UIKit
1500
1544
 
1501
1545
  switch response.result {
1502
1546
  case .success:
1503
- self.logger.info("Stats sent for \(action), version \(versionName)")
1547
+ self.logger.info("Stats sent successfully")
1548
+ self.logger.debug("Action: \(action), Version: \(versionName)")
1504
1549
  case let .failure(error):
1505
- self.logger.error("Error sending stats: \(response.value?.debugDescription ?? "") \(error.localizedDescription)")
1550
+ self.logger.error("Error sending stats")
1551
+ self.logger.debug("Response: \(response.value?.debugDescription ?? "nil"), Error: \(error.localizedDescription)")
1506
1552
  }
1507
1553
  semaphore.signal()
1508
1554
  }
@@ -1526,7 +1572,8 @@ import UIKit
1526
1572
  do {
1527
1573
  result = try UserDefaults.standard.getObj(forKey: "\(trueId)\(self.INFO_SUFFIX)", castTo: BundleInfo.self)
1528
1574
  } catch {
1529
- logger.error("Failed to parse info for bundle [\(trueId)] \(error.localizedDescription)")
1575
+ logger.error("Failed to parse bundle info")
1576
+ logger.debug("Bundle ID: \(trueId), Error: \(error.localizedDescription)")
1530
1577
  result = BundleInfo(id: trueId, version: "", status: BundleStatus.PENDING, checksum: "")
1531
1578
  }
1532
1579
  }
@@ -1561,7 +1608,8 @@ import UIKit
1561
1608
  do {
1562
1609
  try UserDefaults.standard.setObj(update, forKey: "\(id)\(self.INFO_SUFFIX)")
1563
1610
  } catch {
1564
- logger.error("Failed to save info for bundle [\(id)] \(error.localizedDescription)")
1611
+ logger.error("Failed to save bundle info")
1612
+ logger.debug("Bundle ID: \(id), Error: \(error.localizedDescription)")
1565
1613
  }
1566
1614
  }
1567
1615
  UserDefaults.standard.synchronize()
@@ -45,7 +45,8 @@ public struct CryptoCipher {
45
45
  if isHexString(checksum) {
46
46
  // Hex encoded (new format from CLI for plugin versions >= 5.30.0, 6.30.0, 7.30.0)
47
47
  guard let hexData = hexStringToData(checksum) else {
48
- logger.error("Cannot decode checksum as hex: \(checksum)")
48
+ logger.error("Cannot decode checksum as hex")
49
+ logger.debug("Checksum value: \(checksum)")
49
50
  throw CustomError.cannotDecode
50
51
  }
51
52
  checksumBytes = hexData
@@ -54,7 +55,8 @@ public struct CryptoCipher {
54
55
  // TODO: remove backwards compatibility
55
56
  // Base64 encoded (old format for backwards compatibility)
56
57
  guard let base64Data = Data(base64Encoded: checksum) else {
57
- logger.error("Cannot decode checksum as base64: \(checksum)")
58
+ logger.error("Cannot decode checksum as base64")
59
+ logger.debug("Checksum value: \(checksum)")
58
60
  throw CustomError.cannotDecode
59
61
  }
60
62
  checksumBytes = base64Data
@@ -86,15 +88,17 @@ public struct CryptoCipher {
86
88
  detectedAlgorithm = "SHA-256"
87
89
  } else if decryptedChecksum.count == 4 {
88
90
  detectedAlgorithm = "CRC32 (deprecated)"
89
- logger.error("CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums.")
91
+ logger.error("CRC32 checksum detected - deprecated algorithm")
90
92
  } else {
91
93
  detectedAlgorithm = "unknown (\(decryptedChecksum.count) bytes)"
92
- logger.error("Unknown checksum algorithm detected with \(decryptedChecksum.count) bytes. Expected SHA-256 (32 bytes).")
94
+ logger.error("Unknown checksum algorithm detected")
95
+ logger.debug("Byte count: \(decryptedChecksum.count), Expected: 32 (SHA-256)")
93
96
  }
94
97
  logger.debug("Decrypted checksum: \(detectedAlgorithm) hex format (length: \(result.count) chars, \(decryptedChecksum.count) bytes)")
95
98
  return result
96
99
  } catch {
97
- logger.error("decryptChecksum fail: \(error.localizedDescription)")
100
+ logger.error("Checksum decryption failed")
101
+ logger.debug("Error: \(error.localizedDescription)")
98
102
  throw CustomError.cannotDecode
99
103
  }
100
104
  }
@@ -121,9 +125,10 @@ public struct CryptoCipher {
121
125
  let algorithm = detectChecksumAlgorithm(hexChecksum)
122
126
  logger.debug("\(label): \(algorithm) hex format (length: \(hexChecksum.count) chars)")
123
127
  if algorithm.contains("CRC32") {
124
- logger.error("CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums.")
128
+ logger.error("CRC32 checksum detected - deprecated algorithm")
125
129
  } else if algorithm.contains("unknown") {
126
- logger.error("Unknown checksum algorithm detected. Expected SHA-256 (64 hex chars) but got \(hexChecksum.count) chars.")
130
+ logger.error("Unknown checksum algorithm detected")
131
+ logger.debug("Char count: \(hexChecksum.count), Expected: 64 (SHA-256)")
127
132
  }
128
133
  }
129
134
 
@@ -136,7 +141,8 @@ public struct CryptoCipher {
136
141
  do {
137
142
  fileHandle = try FileHandle(forReadingFrom: filePath)
138
143
  } catch {
139
- logger.error("Cannot open file for checksum: \(filePath.path) \(error)")
144
+ logger.error("Cannot open file for checksum calculation")
145
+ logger.debug("Path: \(filePath.path), Error: \(error)")
140
146
  return ""
141
147
  }
142
148
 
@@ -144,7 +150,8 @@ public struct CryptoCipher {
144
150
  do {
145
151
  try fileHandle.close()
146
152
  } catch {
147
- logger.error("Error closing file: \(error)")
153
+ logger.error("Error closing file during checksum")
154
+ logger.debug("Error: \(error)")
148
155
  }
149
156
  }
150
157
 
@@ -153,7 +160,8 @@ public struct CryptoCipher {
153
160
  do {
154
161
  fileData = try fileHandle.read(upToCount: bufferSize) ?? Data()
155
162
  } catch {
156
- logger.error("Error reading file: \(error)")
163
+ logger.error("Error reading file during checksum")
164
+ logger.debug("Error: \(error)")
157
165
  return false
158
166
  }
159
167
 
@@ -168,7 +176,8 @@ public struct CryptoCipher {
168
176
  let digest = sha256.finalize()
169
177
  return digest.compactMap { String(format: "%02x", $0) }.joined()
170
178
  } catch {
171
- logger.error("Cannot get checksum: \(filePath.path) \(error)")
179
+ logger.error("Cannot calculate checksum")
180
+ logger.debug("Path: \(filePath.path), Error: \(error)")
172
181
  return ""
173
182
  }
174
183
  }
@@ -195,17 +204,20 @@ public struct CryptoCipher {
195
204
  let encryptedKeyBase64 = sessionKeyComponents[1]
196
205
 
197
206
  guard let ivData = Data(base64Encoded: ivBase64) else {
198
- logger.error("Cannot decode sessionKey IV \(ivBase64)")
207
+ logger.error("Cannot decode sessionKey IV")
208
+ logger.debug("IV value: \(ivBase64)")
199
209
  throw CustomError.cannotDecode
200
210
  }
201
211
 
202
212
  if ivData.count != 16 {
203
- logger.error("IV data has invalid length: \(ivData.count), expected 16")
213
+ logger.error("IV data has invalid length")
214
+ logger.debug("Length: \(ivData.count), Expected: 16")
204
215
  throw CustomError.cannotDecode
205
216
  }
206
217
 
207
218
  guard let sessionKeyDataEncrypted = Data(base64Encoded: encryptedKeyBase64) else {
208
- logger.error("Cannot decode sessionKey data \(encryptedKeyBase64)")
219
+ logger.error("Cannot decode sessionKey data")
220
+ logger.debug("Key value: \(encryptedKeyBase64)")
209
221
  throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
210
222
  }
211
223
 
@@ -215,7 +227,8 @@ public struct CryptoCipher {
215
227
  }
216
228
 
217
229
  if sessionKeyDataDecrypted.count != 16 {
218
- logger.error("Decrypted session key has invalid length: \(sessionKeyDataDecrypted.count), expected 16")
230
+ logger.error("Decrypted session key has invalid length")
231
+ logger.debug("Length: \(sessionKeyDataDecrypted.count), Expected: 16")
219
232
  throw NSError(domain: "Invalid decrypted session key", code: 5, userInfo: nil)
220
233
  }
221
234
 
@@ -225,7 +238,8 @@ public struct CryptoCipher {
225
238
  do {
226
239
  encryptedData = try Data(contentsOf: filePath)
227
240
  } catch {
228
- logger.error("Failed to read encrypted data: \(error)")
241
+ logger.error("Failed to read encrypted data")
242
+ logger.debug("Error: \(error)")
229
243
  throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
230
244
  }
231
245
 
@@ -251,12 +265,13 @@ public struct CryptoCipher {
251
265
  throw NSError(domain: "File write failed", code: 8, userInfo: nil)
252
266
  }
253
267
  } catch {
254
- logger.error("Error writing decrypted file: \(error)")
268
+ logger.error("Error writing decrypted file")
269
+ logger.debug("Error: \(error)")
255
270
  throw error
256
271
  }
257
272
 
258
273
  } catch {
259
- logger.error("decryptFile fail")
274
+ logger.error("File decryption failed")
260
275
  throw CustomError.cannotDecode
261
276
  }
262
277
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "6.40.0",
3
+ "version": "6.40.2",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",