@capgo/capacitor-updater 7.40.0 → 7.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 = "7.40.0";
88
+ private final String pluginVersion = "7.40.2";
89
89
  private static final String DELAY_CONDITION_PREFERENCES = "";
90
90
 
91
91
  private SharedPreferences.Editor editor;
@@ -179,7 +179,8 @@ public class CapgoUpdater {
179
179
  ZipEntry entry;
180
180
  while ((entry = zis.getNextEntry()) != null) {
181
181
  if (entry.getName().contains("\\")) {
182
- logger.error("unzip: Windows path is not supported, please use unix path as require by zip RFC: " + entry.getName());
182
+ logger.error("Unzip failed: Windows path not supported");
183
+ logger.debug("Invalid path: " + entry.getName());
183
184
  this.sendStats("windows_path_fail");
184
185
  }
185
186
  final File file = new File(targetDirectory, entry.getName());
@@ -275,7 +276,8 @@ public class CapgoUpdater {
275
276
  boolean success = finishDownload(id, dest, version, sessionKey, checksum, true, isManifest);
276
277
  BundleInfo resultBundle;
277
278
  if (!success) {
278
- logger.error("Finish download failed: " + version);
279
+ logger.error("Finish download failed");
280
+ logger.debug("Version: " + version);
279
281
  resultBundle = new BundleInfo(
280
282
  id,
281
283
  version,
@@ -307,7 +309,8 @@ public class CapgoUpdater {
307
309
  case FAILED:
308
310
  Data failedData = workInfo.getOutputData();
309
311
  String error = failedData.getString(DownloadService.ERROR);
310
- logger.error("Download failed: " + error + " " + workInfo.getState());
312
+ logger.error("Download failed");
313
+ logger.debug("Error: " + error + ", State: " + workInfo.getState());
311
314
  String failedVersion = failedData.getString(DownloadService.VERSION);
312
315
 
313
316
  io.execute(() -> {
@@ -423,7 +426,8 @@ public class CapgoUpdater {
423
426
  CryptoCipher.logChecksumInfo("Calculated checksum", checksum);
424
427
  CryptoCipher.logChecksumInfo("Expected checksum", checksumDecrypted);
425
428
  if ((!checksumDecrypted.isEmpty() || !this.publicKey.isEmpty()) && !checksumDecrypted.equals(checksum)) {
426
- logger.error("Error checksum '" + checksumDecrypted + "' '" + checksum + "' '");
429
+ logger.error("Checksum mismatch");
430
+ logger.debug("Expected: " + checksumDecrypted + ", Got: " + checksum);
427
431
  this.sendStats("checksum_fail");
428
432
  throw new IOException("Checksum failed: " + id);
429
433
  }
@@ -435,7 +439,8 @@ public class CapgoUpdater {
435
439
  }
436
440
  final Boolean res = this.delete(id);
437
441
  if (!res) {
438
- logger.info("Double error, cannot cleanup: " + version);
442
+ logger.info("Failed to cleanup after error");
443
+ logger.debug("Version: " + version);
439
444
  }
440
445
 
441
446
  final Map<String, Object> ret = new HashMap<>();
@@ -536,7 +541,8 @@ public class CapgoUpdater {
536
541
  this.deleteDirectory(cacheFolder, threadToCheck);
537
542
  logger.info("Cleaned up delta cache folder");
538
543
  } catch (IOException e) {
539
- logger.error("Failed to cleanup delta cache: " + e.getMessage());
544
+ logger.error("Failed to cleanup delta cache");
545
+ logger.debug("Error: " + e.getMessage());
540
546
  }
541
547
  }
542
548
 
@@ -577,9 +583,11 @@ public class CapgoUpdater {
577
583
  try {
578
584
  this.deleteDirectory(entry, threadToCheck);
579
585
  this.removeBundleInfo(id);
580
- logger.info("Deleted orphan bundle directory: " + id);
586
+ logger.info("Deleted orphan bundle directory");
587
+ logger.debug("Bundle ID: " + id);
581
588
  } catch (IOException e) {
582
- logger.error("Failed to delete orphan bundle directory: " + id + " " + e.getMessage());
589
+ logger.error("Failed to delete orphan bundle directory");
590
+ logger.debug("Bundle ID: " + id + ", Error: " + e.getMessage());
583
591
  }
584
592
  }
585
593
  }
@@ -616,9 +624,11 @@ public class CapgoUpdater {
616
624
 
617
625
  try {
618
626
  this.deleteDirectory(entry, threadToCheck);
619
- logger.info("Deleted orphaned temp unzip folder: " + folderName);
627
+ logger.info("Deleted orphaned temp unzip folder");
628
+ logger.debug("Folder: " + folderName);
620
629
  } catch (IOException e) {
621
- logger.error("Failed to delete orphaned temp folder: " + folderName + " " + e.getMessage());
630
+ logger.error("Failed to delete orphaned temp folder");
631
+ logger.debug("Folder: " + folderName + ", Error: " + e.getMessage());
622
632
  }
623
633
  }
624
634
  }
@@ -705,7 +715,8 @@ public class CapgoUpdater {
705
715
  } catch (Exception e) {
706
716
  // Clean up on failure
707
717
  downloadFutures.remove(id);
708
- logger.error("Error waiting for download: " + e.getMessage());
718
+ logger.error("Error waiting for download");
719
+ logger.debug("Error: " + e.getMessage());
709
720
  BundleInfo errorBundle = new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), "");
710
721
  saveBundleInfo(id, errorBundle);
711
722
  if (e instanceof IOException) {
@@ -745,12 +756,14 @@ public class CapgoUpdater {
745
756
  public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
746
757
  final BundleInfo deleted = this.getBundleInfo(id);
747
758
  if (deleted.isBuiltin() || this.getCurrentBundleId().equals(id)) {
748
- logger.error("Cannot delete " + id);
759
+ logger.error("Cannot delete current or builtin bundle");
760
+ logger.debug("Bundle ID: " + id);
749
761
  return false;
750
762
  }
751
763
  final BundleInfo next = this.getNextBundle();
752
764
  if (next != null && !next.isDeleted() && !next.isErrorStatus() && next.getId().equals(id)) {
753
- logger.error("Cannot delete the next bundle" + id);
765
+ logger.error("Cannot delete the next bundle");
766
+ logger.debug("Bundle ID: " + id);
754
767
  return false;
755
768
  }
756
769
  // Cancel download for this version if active
@@ -767,7 +780,8 @@ public class CapgoUpdater {
767
780
  }
768
781
  return true;
769
782
  }
770
- logger.error("bundle removed: " + deleted.getVersionName());
783
+ logger.info("Bundle not found on disk");
784
+ logger.debug("Version: " + deleted.getVersionName());
771
785
  // perhaps we did not find the bundle in the files, but if the user requested a delete, we delete
772
786
  if (removeInfo) {
773
787
  this.removeBundleInfo(id);
@@ -938,11 +952,13 @@ public class CapgoUpdater {
938
952
  if (response.isSuccessful()) {
939
953
  logger.info("Rate limit statistic sent");
940
954
  } else {
941
- logger.error("Error sending rate limit statistic: " + response.code());
955
+ logger.error("Error sending rate limit statistic");
956
+ logger.debug("Response code: " + response.code());
942
957
  }
943
958
  }
944
959
  } catch (final Exception e) {
945
- logger.error("Failed to send rate limit statistic: " + e.getMessage());
960
+ logger.error("Failed to send rate limit statistic");
961
+ logger.debug("Error: " + e.getMessage());
946
962
  }
947
963
  }
948
964
 
@@ -1039,7 +1055,8 @@ public class CapgoUpdater {
1039
1055
  json.put("defaultChannel", channel);
1040
1056
  }
1041
1057
  } catch (JSONException e) {
1042
- logger.error("Error getLatest JSONException " + e.getMessage());
1058
+ logger.error("Error getting latest version");
1059
+ logger.debug("JSONException: " + e.getMessage());
1043
1060
  final Map<String, Object> retError = new HashMap<>();
1044
1061
  retError.put("message", "Cannot get info: " + e);
1045
1062
  retError.put("error", "json_error");
@@ -1111,7 +1128,8 @@ public class CapgoUpdater {
1111
1128
  json = this.createInfoObject();
1112
1129
  json.put("channel", channel);
1113
1130
  } catch (JSONException e) {
1114
- logger.error("Error setChannel JSONException " + e.getMessage());
1131
+ logger.error("Error setting channel");
1132
+ logger.debug("JSONException: " + e.getMessage());
1115
1133
  final Map<String, Object> retError = new HashMap<>();
1116
1134
  retError.put("message", "Cannot get info: " + e);
1117
1135
  retError.put("error", "json_error");
@@ -1157,7 +1175,8 @@ public class CapgoUpdater {
1157
1175
  try {
1158
1176
  json = this.createInfoObject();
1159
1177
  } catch (JSONException e) {
1160
- logger.error("Error getChannel JSONException " + e.getMessage());
1178
+ logger.error("Error getting channel");
1179
+ logger.debug("JSONException: " + e.getMessage());
1161
1180
  final Map<String, Object> retError = new HashMap<>();
1162
1181
  retError.put("message", "Cannot get info: " + e);
1163
1182
  retError.put("error", "json_error");
@@ -1279,7 +1298,8 @@ public class CapgoUpdater {
1279
1298
  try {
1280
1299
  json = this.createInfoObject();
1281
1300
  } catch (JSONException e) {
1282
- logger.error("Error creating info object: " + e.getMessage());
1301
+ logger.error("Error creating info object");
1302
+ logger.debug("JSONException: " + e.getMessage());
1283
1303
  final Map<String, Object> retError = new HashMap<>();
1284
1304
  retError.put("message", "Cannot get info: " + e);
1285
1305
  retError.put("error", "json_error");
@@ -1299,7 +1319,8 @@ public class CapgoUpdater {
1299
1319
  }
1300
1320
  }
1301
1321
  } catch (JSONException e) {
1302
- logger.error("Error adding query parameters: " + e.getMessage());
1322
+ logger.error("Error adding query parameters");
1323
+ logger.debug("JSONException: " + e.getMessage());
1303
1324
  }
1304
1325
 
1305
1326
  Request request = new Request.Builder().url(urlBuilder.build()).get().build();
@@ -1420,7 +1441,8 @@ public class CapgoUpdater {
1420
1441
  json.put("old_version_name", oldVersionName);
1421
1442
  json.put("action", action);
1422
1443
  } catch (JSONException e) {
1423
- logger.error("Error sendStats JSONException " + e.getMessage());
1444
+ logger.error("Error preparing stats");
1445
+ logger.debug("JSONException: " + e.getMessage());
1424
1446
  return;
1425
1447
  }
1426
1448
 
@@ -1435,7 +1457,8 @@ public class CapgoUpdater {
1435
1457
  new okhttp3.Callback() {
1436
1458
  @Override
1437
1459
  public void onFailure(@NonNull Call call, @NonNull IOException e) {
1438
- logger.error("Failed to send stats: " + e.getMessage());
1460
+ logger.error("Failed to send stats");
1461
+ logger.debug("Error: " + e.getMessage());
1439
1462
  }
1440
1463
 
1441
1464
  @Override
@@ -1447,9 +1470,11 @@ public class CapgoUpdater {
1447
1470
  }
1448
1471
 
1449
1472
  if (response.isSuccessful()) {
1450
- logger.info("Stats send for \"" + action + "\", version " + versionName);
1473
+ logger.info("Stats sent successfully");
1474
+ logger.debug("Action: " + action + ", Version: " + versionName);
1451
1475
  } else {
1452
- logger.error("Error sending stats: " + response.code());
1476
+ logger.error("Error sending stats");
1477
+ logger.debug("Response code: " + response.code());
1453
1478
  }
1454
1479
  }
1455
1480
  }
@@ -1476,14 +1501,8 @@ public class CapgoUpdater {
1476
1501
  result = BundleInfo.fromJSON(stored);
1477
1502
  }
1478
1503
  } catch (JSONException e) {
1479
- logger.error(
1480
- "Failed to parse info for bundle [" +
1481
- trueId +
1482
- "] stored value: '" +
1483
- this.prefs.getString(trueId + INFO_SUFFIX, "") +
1484
- "' error: " +
1485
- e.getMessage()
1486
- );
1504
+ logger.error("Failed to parse bundle info");
1505
+ logger.debug("Bundle ID: " + trueId + ", Error: " + e.getMessage());
1487
1506
  // Clear corrupted data
1488
1507
  this.editor.remove(trueId + INFO_SUFFIX);
1489
1508
  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 = "7.40.0"
63
+ private let pluginVersion: String = "7.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"
@@ -155,7 +155,8 @@ import UIKit
155
155
  case .success:
156
156
  self.logger.info("Rate limit statistic sent")
157
157
  case let .failure(error):
158
- self.logger.error("Error sending rate limit statistic: \(error.localizedDescription)")
158
+ self.logger.error("Error sending rate limit statistic")
159
+ self.logger.debug("Error: \(error.localizedDescription)")
159
160
  }
160
161
  semaphore.signal()
161
162
  }
@@ -201,7 +202,8 @@ import UIKit
201
202
  do {
202
203
  try FileManager.default.createDirectory(atPath: source.path, withIntermediateDirectories: true, attributes: nil)
203
204
  } catch {
204
- logger.error("Cannot createDirectory \(source.path)")
205
+ logger.error("Cannot create directory")
206
+ logger.debug("Directory path: \(source.path)")
205
207
  throw CustomError.cannotCreateDirectory
206
208
  }
207
209
  }
@@ -211,7 +213,8 @@ import UIKit
211
213
  do {
212
214
  try FileManager.default.removeItem(atPath: source.path)
213
215
  } catch {
214
- logger.error("File not removed. \(source.path)")
216
+ logger.error("File not removed")
217
+ logger.debug("Path: \(source.path)")
215
218
  throw CustomError.cannotDeleteDirectory
216
219
  }
217
220
  }
@@ -228,7 +231,8 @@ import UIKit
228
231
  return false
229
232
  }
230
233
  } catch {
231
- logger.error("File not moved. source: \(source.path) dest: \(dest.path)")
234
+ logger.error("File not moved")
235
+ logger.debug("Source: \(source.path), Dest: \(dest.path)")
232
236
  throw CustomError.cannotUnflat
233
237
  }
234
238
  }
@@ -236,7 +240,8 @@ import UIKit
236
240
  private func validateZipEntry(path: String, destUnZip: URL) throws {
237
241
  // Check for Windows paths
238
242
  if path.contains("\\") {
239
- logger.error("unzip: Windows path is not supported, please use unix path as required by zip RFC: \(path)")
243
+ logger.error("Unzip failed: Windows path not supported")
244
+ logger.debug("Invalid path: \(path)")
240
245
  self.sendStats(action: "windows_path_fail")
241
246
  throw CustomError.cannotUnzip
242
247
  }
@@ -318,7 +323,8 @@ import UIKit
318
323
  try FileManager.default.removeItem(at: sourceZip)
319
324
  }
320
325
  } catch {
321
- logger.error("Could not delete source zip at \(sourceZip.path): \(error)")
326
+ logger.error("Could not delete source zip")
327
+ logger.debug("Path: \(sourceZip.path), Error: \(error)")
322
328
  }
323
329
  }
324
330
 
@@ -393,8 +399,9 @@ import UIKit
393
399
  latest.comment = comment
394
400
  }
395
401
  case let .failure(error):
396
- self.logger.error("Error getting Latest \(response.value.debugDescription) \(error)")
397
- latest.message = "Error getting Latest \(String(describing: response.value))"
402
+ self.logger.error("Error getting latest version")
403
+ self.logger.debug("Response: \(response.value.debugDescription), Error: \(error)")
404
+ latest.message = "Error getting Latest"
398
405
  latest.error = "response_error"
399
406
  latest.statusCode = response.response?.statusCode ?? 0
400
407
  }
@@ -461,7 +468,8 @@ import UIKit
461
468
  fileHash = try CryptoCipher.decryptChecksum(checksum: fileHash, publicKey: self.publicKey)
462
469
  } catch {
463
470
  downloadError = error
464
- logger.error("CryptoCipher.decryptChecksum error \(id) \(fileName) error: \(error)")
471
+ logger.error("Checksum decryption failed")
472
+ logger.debug("Bundle: \(id), File: \(fileName), Error: \(error)")
465
473
  }
466
474
  }
467
475
 
@@ -490,7 +498,8 @@ import UIKit
490
498
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
491
499
  } catch {
492
500
  downloadError = error
493
- logger.error("Failed to copy builtin file \(fileName): \(error.localizedDescription)")
501
+ logger.error("Failed to copy builtin file")
502
+ logger.debug("File: \(fileName), Error: \(error.localizedDescription)")
494
503
  }
495
504
  dispatchGroup.leave()
496
505
  } else if self.tryCopyFromCache(from: cacheFilePath, to: destFilePath, expectedHash: fileHash) {
@@ -562,15 +571,18 @@ import UIKit
562
571
 
563
572
  completedFiles += 1
564
573
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
565
- self.logger.info("downloadManifest \(id) \(fileName) downloaded\(isBrotli ? ", decompressed" : "")\(!self.publicKey.isEmpty && !sessionKey.isEmpty ? ", decrypted" : ""), and cached")
574
+ self.logger.info("Manifest file downloaded and cached")
575
+ self.logger.debug("Bundle: \(id), File: \(fileName), Brotli: \(isBrotli), Encrypted: \(!self.publicKey.isEmpty && !sessionKey.isEmpty)")
566
576
  } catch {
567
577
  downloadError = error
568
- self.logger.error("downloadManifest \(id) \(fileName) error: \(error.localizedDescription)")
578
+ self.logger.error("Manifest file download failed")
579
+ self.logger.debug("Bundle: \(id), File: \(fileName), Error: \(error.localizedDescription)")
569
580
  }
570
581
  case .failure(let error):
571
582
  downloadError = error
572
583
  self.sendStats(action: "download_manifest_file_fail", versionName: "\(version):\(fileName)")
573
- self.logger.error("downloadManifest \(id) \(fileName) download error: \(error.localizedDescription). Debug response: \(response.debugDescription).")
584
+ self.logger.error("Manifest file download network error")
585
+ self.logger.debug("Bundle: \(id), File: \(fileName), Error: \(error.localizedDescription), Response: \(response.debugDescription)")
574
586
  }
575
587
  }
576
588
  }
@@ -658,7 +670,8 @@ import UIKit
658
670
  var status = compression_stream_init(streamPointer, COMPRESSION_STREAM_DECODE, COMPRESSION_BROTLI)
659
671
 
660
672
  guard status != COMPRESSION_STATUS_ERROR else {
661
- logger.error("Error: Failed to initialize Brotli stream for \(fileName). Status: \(status)")
673
+ logger.error("Failed to initialize Brotli stream")
674
+ logger.debug("File: \(fileName), Status: \(status)")
662
675
  return nil
663
676
  }
664
677
 
@@ -680,7 +693,8 @@ import UIKit
680
693
  if let baseAddress = rawBufferPointer.baseAddress {
681
694
  streamPointer.pointee.src_ptr = baseAddress.assumingMemoryBound(to: UInt8.self)
682
695
  } else {
683
- logger.error("Error: Failed to get base address for \(fileName)")
696
+ logger.error("Failed to get base address for Brotli decompression")
697
+ logger.debug("File: \(fileName)")
684
698
  status = COMPRESSION_STATUS_ERROR
685
699
  return
686
700
  }
@@ -690,7 +704,8 @@ import UIKit
690
704
  if status == COMPRESSION_STATUS_ERROR {
691
705
  let maxBytes = min(32, data.count)
692
706
  let hexDump = data.prefix(maxBytes).map { String(format: "%02x", $0) }.joined(separator: " ")
693
- logger.error("Error: Brotli decompression failed for \(fileName). First \(maxBytes) bytes: \(hexDump)")
707
+ logger.error("Brotli decompression failed")
708
+ logger.debug("File: \(fileName), First \(maxBytes) bytes: \(hexDump)")
694
709
  break
695
710
  }
696
711
 
@@ -704,18 +719,19 @@ import UIKit
704
719
  if status == COMPRESSION_STATUS_END {
705
720
  break
706
721
  } else if status == COMPRESSION_STATUS_ERROR {
707
- logger.error("Error: Brotli process failed for \(fileName). Status: \(status)")
722
+ logger.error("Brotli process failed")
723
+ logger.debug("File: \(fileName), Status: \(status)")
708
724
  if let text = String(data: data, encoding: .utf8) {
709
725
  let asciiCount = text.unicodeScalars.filter { $0.isASCII }.count
710
726
  let totalCount = text.unicodeScalars.count
711
727
  if totalCount > 0 && Double(asciiCount) / Double(totalCount) >= 0.8 {
712
- logger.error("Error: Input appears to be plain text: \(text)")
728
+ logger.debug("Input appears to be plain text: \(text)")
713
729
  }
714
730
  }
715
731
 
716
732
  let maxBytes = min(32, data.count)
717
733
  let hexDump = data.prefix(maxBytes).map { String(format: "%02x", $0) }.joined(separator: " ")
718
- logger.error("Error: Raw data (\(fileName)): \(hexDump)")
734
+ logger.debug("Raw data: \(hexDump)")
719
735
 
720
736
  return nil
721
737
  }
@@ -726,7 +742,8 @@ import UIKit
726
742
  }
727
743
 
728
744
  if input.count == 0 {
729
- logger.error("Error: Zero input size for \(fileName)")
745
+ logger.error("Zero input size for Brotli decompression")
746
+ logger.debug("File: \(fileName)")
730
747
  break
731
748
  }
732
749
  }
@@ -818,7 +835,8 @@ import UIKit
818
835
  reachabilityManager?.stopListening()
819
836
 
820
837
  if mainError != nil {
821
- logger.error("Failed to download: \(String(describing: mainError))")
838
+ logger.error("Failed to download bundle")
839
+ logger.debug("Error: \(String(describing: mainError))")
822
840
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
823
841
  throw mainError!
824
842
  }
@@ -828,7 +846,8 @@ import UIKit
828
846
  try CryptoCipher.decryptFile(filePath: tempDataPath, publicKey: self.publicKey, sessionKey: sessionKey, version: version)
829
847
  try FileManager.default.moveItem(at: tempDataPath, to: finalPath)
830
848
  } catch {
831
- logger.error("Failed decrypt file : \(error)")
849
+ logger.error("Failed to decrypt file")
850
+ logger.debug("Error: \(error)")
832
851
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
833
852
  cleanDownloadData()
834
853
  throw error
@@ -841,7 +860,8 @@ import UIKit
841
860
  try self.saveDownloaded(sourceZip: finalPath, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory), notify: true)
842
861
 
843
862
  } catch {
844
- logger.error("Failed to unzip file: \(error)")
863
+ logger.error("Failed to unzip file")
864
+ logger.debug("Error: \(error)")
845
865
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum, link: link, comment: comment))
846
866
  // Best-effort cleanup of the decrypted zip file when unzip fails
847
867
  do {
@@ -849,7 +869,8 @@ import UIKit
849
869
  try FileManager.default.removeItem(at: finalPath)
850
870
  }
851
871
  } catch {
852
- logger.error("Could not delete failed zip at \(finalPath.path): \(error)")
872
+ logger.error("Could not delete failed zip")
873
+ logger.debug("Path: \(finalPath.path), Error: \(error)")
853
874
  }
854
875
  cleanDownloadData()
855
876
  throw error
@@ -872,13 +893,15 @@ import UIKit
872
893
  let fileManager = FileManager.default
873
894
  if !fileManager.fileExists(atPath: tempDataPath.path) {
874
895
  if !fileManager.createFile(atPath: tempDataPath.path, contents: Data()) {
875
- logger.error("Cannot ensure that a file at \(tempDataPath.path) exists")
896
+ logger.error("Cannot ensure temp data file exists")
897
+ logger.debug("Path: \(tempDataPath.path)")
876
898
  }
877
899
  }
878
900
 
879
901
  if !fileManager.fileExists(atPath: updateInfo.path) {
880
902
  if !fileManager.createFile(atPath: updateInfo.path, contents: Data()) {
881
- logger.error("Cannot ensure that a file at \(updateInfo.path) exists")
903
+ logger.error("Cannot ensure update info file exists")
904
+ logger.debug("Path: \(updateInfo.path)")
882
905
  }
883
906
  }
884
907
  }
@@ -890,7 +913,8 @@ import UIKit
890
913
  do {
891
914
  try fileManager.removeItem(at: tempDataPath)
892
915
  } catch {
893
- logger.error("Could not delete file at \(tempDataPath): \(error)")
916
+ logger.error("Could not delete temp data file")
917
+ logger.debug("Path: \(tempDataPath), Error: \(error)")
894
918
  }
895
919
  }
896
920
  // Deleting update.dat
@@ -898,7 +922,8 @@ import UIKit
898
922
  do {
899
923
  try fileManager.removeItem(at: updateInfo)
900
924
  } catch {
901
- logger.error("Could not delete file at \(updateInfo): \(error)")
925
+ logger.error("Could not delete update info file")
926
+ logger.debug("Path: \(updateInfo), Error: \(error)")
902
927
  }
903
928
  }
904
929
  }
@@ -917,7 +942,8 @@ import UIKit
917
942
  fileHandle.closeFile()
918
943
  }
919
944
  } catch {
920
- logger.error("Failed to write data starting at byte \(byteOffset): \(error)")
945
+ logger.error("Failed to write partial data")
946
+ logger.debug("Byte offset: \(byteOffset), Error: \(error)")
921
947
  }
922
948
  self.tempData.removeAll() // Clearing tempData to avoid writing the same data multiple times
923
949
  }
@@ -926,7 +952,8 @@ import UIKit
926
952
  do {
927
953
  try "\(version)".write(to: updateInfo, atomically: true, encoding: .utf8)
928
954
  } catch {
929
- logger.error("Failed to save progress: \(error)")
955
+ logger.error("Failed to save download progress")
956
+ logger.debug("Error: \(error)")
930
957
  }
931
958
  }
932
959
  private func getLocalUpdateVersion() -> String { // Return the version that was tried to be downloaded on last download attempt
@@ -948,7 +975,8 @@ import UIKit
948
975
  return fileSize.int64Value
949
976
  }
950
977
  } catch {
951
- logger.error("Could not retrieve already downloaded data size : \(error)")
978
+ logger.error("Could not retrieve download progress size")
979
+ logger.debug("Error: \(error)")
952
980
  }
953
981
  return 0
954
982
  }
@@ -992,7 +1020,8 @@ import UIKit
992
1020
  public func delete(id: String, removeInfo: Bool) -> Bool {
993
1021
  let deleted: BundleInfo = self.getBundleInfo(id: id)
994
1022
  if deleted.isBuiltin() || self.getCurrentBundleId() == id {
995
- logger.info("Cannot delete \(id)")
1023
+ logger.info("Cannot delete current or builtin bundle")
1024
+ logger.debug("Bundle ID: \(id)")
996
1025
  return false
997
1026
  }
998
1027
 
@@ -1001,7 +1030,8 @@ import UIKit
1001
1030
  !next.isDeleted() &&
1002
1031
  !next.isErrorStatus() &&
1003
1032
  next.getId() == id {
1004
- logger.info("Cannot delete the next bundle \(id)")
1033
+ logger.info("Cannot delete the next bundle")
1034
+ logger.debug("Bundle ID: \(id)")
1005
1035
  return false
1006
1036
  }
1007
1037
 
@@ -1009,7 +1039,8 @@ import UIKit
1009
1039
  do {
1010
1040
  try FileManager.default.removeItem(atPath: destPersist.path)
1011
1041
  } catch {
1012
- logger.error("Folder \(destPersist.path), not removed.")
1042
+ logger.error("Bundle folder not removed")
1043
+ logger.debug("Path: \(destPersist.path)")
1013
1044
  // even if, we don;t care. Android doesn't care
1014
1045
  if removeInfo {
1015
1046
  self.removeBundleInfo(id: id)
@@ -1022,7 +1053,8 @@ import UIKit
1022
1053
  } else {
1023
1054
  self.saveBundleInfo(id: id, bundle: deleted.setStatus(status: BundleStatus.DELETED.localizedString))
1024
1055
  }
1025
- logger.info("bundle delete \(deleted.getVersionName())")
1056
+ logger.info("Bundle deleted successfully")
1057
+ logger.debug("Version: \(deleted.getVersionName())")
1026
1058
  self.sendStats(action: "delete", versionName: deleted.getVersionName())
1027
1059
  return true
1028
1060
  }
@@ -1050,7 +1082,8 @@ import UIKit
1050
1082
  try fileManager.removeItem(at: cacheFolder)
1051
1083
  logger.info("Cleaned up delta cache folder")
1052
1084
  } catch {
1053
- logger.error("Failed to cleanup delta cache: \(error.localizedDescription)")
1085
+ logger.error("Failed to cleanup delta cache")
1086
+ logger.debug("Error: \(error.localizedDescription)")
1054
1087
  }
1055
1088
  }
1056
1089
 
@@ -1090,13 +1123,16 @@ import UIKit
1090
1123
  do {
1091
1124
  try fileManager.removeItem(at: url)
1092
1125
  self.removeBundleInfo(id: id)
1093
- logger.info("Deleted orphan bundle directory: \(id)")
1126
+ logger.info("Deleted orphan bundle directory")
1127
+ logger.debug("Bundle ID: \(id)")
1094
1128
  } catch {
1095
- logger.error("Failed to delete orphan bundle directory: \(id) \(error.localizedDescription)")
1129
+ logger.error("Failed to delete orphan bundle directory")
1130
+ logger.debug("Bundle ID: \(id), Error: \(error.localizedDescription)")
1096
1131
  }
1097
1132
  }
1098
1133
  } catch {
1099
- logger.error("Failed to enumerate bundle directory for cleanup: \(error.localizedDescription)")
1134
+ logger.error("Failed to enumerate bundle directory for cleanup")
1135
+ logger.debug("Error: \(error.localizedDescription)")
1100
1136
  }
1101
1137
  }
1102
1138
 
@@ -1127,13 +1163,16 @@ import UIKit
1127
1163
 
1128
1164
  do {
1129
1165
  try fileManager.removeItem(at: url)
1130
- logger.info("Deleted orphaned temp unzip folder: \(folderName)")
1166
+ logger.info("Deleted orphaned temp unzip folder")
1167
+ logger.debug("Folder: \(folderName)")
1131
1168
  } catch {
1132
- logger.error("Failed to delete orphaned temp folder: \(folderName) \(error.localizedDescription)")
1169
+ logger.error("Failed to delete orphaned temp folder")
1170
+ logger.debug("Folder: \(folderName), Error: \(error.localizedDescription)")
1133
1171
  }
1134
1172
  }
1135
1173
  } catch {
1136
- logger.error("Failed to enumerate library directory for temp folder cleanup: \(error.localizedDescription)")
1174
+ logger.error("Failed to enumerate library directory for temp folder cleanup")
1175
+ logger.debug("Error: \(error.localizedDescription)")
1137
1176
  }
1138
1177
  }
1139
1178
 
@@ -1209,9 +1248,11 @@ import UIKit
1209
1248
  if autoDeletePrevious && !fallback.isBuiltin() && fallback.getId() != bundle.getId() {
1210
1249
  let res = self.delete(id: fallback.getId())
1211
1250
  if res {
1212
- logger.info("Deleted previous bundle: \(fallback.toString())")
1251
+ logger.info("Deleted previous bundle")
1252
+ logger.debug("Bundle: \(fallback.toString())")
1213
1253
  } else {
1214
- logger.error("Failed to delete previous bundle: \(fallback.toString())")
1254
+ logger.error("Failed to delete previous bundle")
1255
+ logger.debug("Bundle: \(fallback.toString())")
1215
1256
  }
1216
1257
  }
1217
1258
  self.setFallbackBundle(fallback: bundle)
@@ -1292,7 +1333,8 @@ import UIKit
1292
1333
  }
1293
1334
  }
1294
1335
  case let .failure(error):
1295
- self.logger.error("Error set Channel \(error)")
1336
+ self.logger.error("Error setting channel")
1337
+ self.logger.debug("Error: \(error)")
1296
1338
  setChannel.error = "Request failed: \(error.localizedDescription)"
1297
1339
  }
1298
1340
  semaphore.signal()
@@ -1355,7 +1397,8 @@ import UIKit
1355
1397
  }
1356
1398
  }
1357
1399
 
1358
- self.logger.error("Error get Channel \(error)")
1400
+ self.logger.error("Error getting channel")
1401
+ self.logger.debug("Error: \(error)")
1359
1402
  getChannel.error = "Request failed: \(error.localizedDescription)"
1360
1403
  }
1361
1404
  }
@@ -1445,7 +1488,8 @@ import UIKit
1445
1488
  }
1446
1489
  }
1447
1490
  case let .failure(error):
1448
- self.logger.error("Error list channels \(error)")
1491
+ self.logger.error("Error listing channels")
1492
+ self.logger.debug("Error: \(error)")
1449
1493
  listChannels.error = "Request failed: \(error.localizedDescription)"
1450
1494
  }
1451
1495
  }
@@ -1491,9 +1535,11 @@ import UIKit
1491
1535
 
1492
1536
  switch response.result {
1493
1537
  case .success:
1494
- self.logger.info("Stats sent for \(action), version \(versionName)")
1538
+ self.logger.info("Stats sent successfully")
1539
+ self.logger.debug("Action: \(action), Version: \(versionName)")
1495
1540
  case let .failure(error):
1496
- self.logger.error("Error sending stats: \(response.value?.debugDescription ?? "") \(error.localizedDescription)")
1541
+ self.logger.error("Error sending stats")
1542
+ self.logger.debug("Response: \(response.value?.debugDescription ?? "nil"), Error: \(error.localizedDescription)")
1497
1543
  }
1498
1544
  semaphore.signal()
1499
1545
  }
@@ -1517,7 +1563,8 @@ import UIKit
1517
1563
  do {
1518
1564
  result = try UserDefaults.standard.getObj(forKey: "\(trueId)\(self.INFO_SUFFIX)", castTo: BundleInfo.self)
1519
1565
  } catch {
1520
- logger.error("Failed to parse info for bundle [\(trueId)] \(error.localizedDescription)")
1566
+ logger.error("Failed to parse bundle info")
1567
+ logger.debug("Bundle ID: \(trueId), Error: \(error.localizedDescription)")
1521
1568
  result = BundleInfo(id: trueId, version: "", status: BundleStatus.PENDING, checksum: "")
1522
1569
  }
1523
1570
  }
@@ -1552,7 +1599,8 @@ import UIKit
1552
1599
  do {
1553
1600
  try UserDefaults.standard.setObj(update, forKey: "\(id)\(self.INFO_SUFFIX)")
1554
1601
  } catch {
1555
- logger.error("Failed to save info for bundle [\(id)] \(error.localizedDescription)")
1602
+ logger.error("Failed to save bundle info")
1603
+ logger.debug("Bundle ID: \(id), Error: \(error.localizedDescription)")
1556
1604
  }
1557
1605
  }
1558
1606
  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": "7.40.0",
3
+ "version": "7.40.2",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",