@capawesome/capacitor-live-update 6.7.1 → 6.8.0-dev.2e2696e1.1773643381

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.
package/README.md CHANGED
@@ -651,24 +651,28 @@ Only available on Android and iOS.
651
651
  | ------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
652
652
  | **`artifactType`** | <code>'manifest' \| 'zip'</code> | The artifact type of the bundle. | <code>'zip'</code> | 6.6.0 |
653
653
  | **`bundleId`** | <code>string</code> | The unique identifier of the bundle. | | 5.0.0 |
654
- | **`checksum`** | <code>string</code> | The checksum of the bundle to verify the integrity of the ZIP file. Must be a SHA-256 hash in base64 format. | | 6.1.0 |
654
+ | **`checksum`** | <code>string</code> | The checksum of the self-hosted bundle as a SHA-256 hash in base64 format to verify the integrity of the bundle. **Attention**: Only supported for the `zip` artifact type. | | 6.1.0 |
655
+ | **`signature`** | <code>string</code> | The signature of the self-hosted bundle as a signed SHA-256 hash in base64 format to verify the integrity of the bundle. **Attention**: Only supported for the `zip` artifact type. | | 6.8.0 |
655
656
  | **`url`** | <code>string</code> | The URL of the bundle to download. For the `zip` artifact type, the URL must point to a ZIP file. For the `manifest` artifact type, the URL serves as the base URL to download the individual files. For example, if the URL is `https://example.com/download`, the plugin will download the file with the href `index.html` from `https://example.com/download?href=index.html`. To **verify the integrity** of the file, the server must return a `X-Checksum` header with the SHA-256 hash in base64 format. To **verify the signature** of the file, the server must return a `X-Signature` header with the signed SHA-256 hash in base64 format. | | 5.0.0 |
656
657
 
657
658
 
658
659
  #### FetchLatestBundleResult
659
660
 
660
- | Prop | Type | Description | Since |
661
- | ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----- |
662
- | **`artifactType`** | <code>'manifest' \| 'zip'</code> | The artifact type of the bundle. | 6.7.0 |
663
- | **`bundleId`** | <code>string \| null</code> | The unique identifier of the latest bundle. If `null`, no bundle is available. | 6.6.0 |
664
- | **`downloadUrl`** | <code>string</code> | The URL of the latest bundle to download. Pass this URL to the `downloadBundle(...)` method to download the bundle. | 6.7.0 |
661
+ | Prop | Type | Description | Since |
662
+ | ------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
663
+ | **`artifactType`** | <code>'manifest' \| 'zip'</code> | The artifact type of the bundle. | 6.7.0 |
664
+ | **`bundleId`** | <code>string \| null</code> | The unique identifier of the latest bundle. If `null`, no bundle is available. | 6.6.0 |
665
+ | **`channel`** | <code>string</code> | The name of the channel that the bundle is actually from. This is the resolved channel after applying any forced channel assignment and may differ from the channel set by the Live Update SDK. | 6.9.0 |
666
+ | **`checksum`** | <code>string</code> | The checksum of the latest bundle if the bundle is self-hosted. If the bundle is hosted on Capawesome Cloud, the checksum will be returned as response header when downloading the bundle. | 6.8.0 |
667
+ | **`downloadUrl`** | <code>string</code> | The URL of the latest bundle to download. Pass this URL to the `downloadBundle(...)` method to download the bundle. | 6.7.0 |
668
+ | **`signature`** | <code>string</code> | The signature of the latest bundle if the bundle is self-hosted. If the bundle is hosted on Capawesome Cloud, the signature will be returned as response header when downloading the bundle. | 6.8.0 |
665
669
 
666
670
 
667
671
  #### FetchLatestBundleOptions
668
672
 
669
- | Prop | Type | Description | Since |
670
- | ------------- | ------------------- | ---------------------------------------------------------------- | ----- |
671
- | **`channel`** | <code>string</code> | The name of the channel where the latest bundle is fetched from. | 6.7.0 |
673
+ | Prop | Type | Description | Since |
674
+ | ------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
675
+ | **`channel`** | <code>string</code> | The preferred channel name from which the latest bundle should be fetched. This is the SDK preference and may be overridden by a forced channel assignment configured in the Capawesome Cloud Console. | 6.7.0 |
672
676
 
673
677
 
674
678
  #### GetBundleResult
@@ -771,9 +775,9 @@ Only available on Android and iOS.
771
775
 
772
776
  #### SyncOptions
773
777
 
774
- | Prop | Type | Description | Since |
775
- | ------------- | ------------------- | ---------------------------------------------------------------- | ----- |
776
- | **`channel`** | <code>string</code> | The name of the channel where the latest bundle is fetched from. | 6.7.0 |
778
+ | Prop | Type | Description | Since |
779
+ | ------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
780
+ | **`channel`** | <code>string</code> | The preferred channel name from which the latest bundle should be fetched. This is the SDK preference and may be overridden by a forced channel assignment configured in the Capawesome Cloud Console. | 6.7.0 |
777
781
 
778
782
  </docgen-api>
779
783
 
@@ -104,6 +104,7 @@ public class LiveUpdate {
104
104
 
105
105
  if (config.getEnabled()) {
106
106
  if (wasUpdated() && config.getResetOnUpdate()) {
107
+ Logger.debug(LiveUpdatePlugin.TAG, "App was updated. Resetting to default bundle.");
107
108
  reset();
108
109
  } else {
109
110
  startRollbackTimer();
@@ -129,6 +130,7 @@ public class LiveUpdate {
129
130
  ArtifactType artifactType = options.getArtifactType();
130
131
  String bundleId = options.getBundleId();
131
132
  String checksum = options.getChecksum();
133
+ String signature = options.getSignature();
132
134
  String url = options.getUrl();
133
135
 
134
136
  // Check if the bundle already exists
@@ -142,7 +144,7 @@ public class LiveUpdate {
142
144
  if (artifactType == ArtifactType.MANIFEST) {
143
145
  downloadBundleOfTypeManifest(bundleId, url);
144
146
  } else {
145
- downloadBundleOfTypeZip(bundleId, url, checksum);
147
+ downloadBundleOfTypeZip(bundleId, url, checksum, signature);
146
148
  }
147
149
  callback.success();
148
150
  }
@@ -151,8 +153,11 @@ public class LiveUpdate {
151
153
  GetLatestBundleResponse response = fetchLatestBundle(options);
152
154
  ArtifactType artifactType = response == null ? null : response.getArtifactType();
153
155
  String bundleId = response == null ? null : response.getBundleId();
156
+ String channel = response == null ? null : response.getChannelName();
157
+ String checksum = response == null ? null : response.getChecksum();
154
158
  String downloadUrl = response == null ? null : response.getUrl();
155
- FetchLatestBundleResult result = new FetchLatestBundleResult(artifactType, bundleId, downloadUrl);
159
+ String signature = response == null ? null : response.getSignature();
160
+ FetchLatestBundleResult result = new FetchLatestBundleResult(artifactType, bundleId, channel, checksum, downloadUrl, signature);
156
161
  callback.success(result);
157
162
  }
158
163
 
@@ -295,6 +300,8 @@ public class LiveUpdate {
295
300
  return;
296
301
  }
297
302
  ArtifactType artifactType = response.getArtifactType();
303
+ String checksum = response.getChecksum();
304
+ String signature = response.getSignature();
298
305
  String latestBundleId = response.getBundleId();
299
306
  String url = response.getUrl();
300
307
  // Check if the bundle already exists
@@ -314,7 +321,7 @@ public class LiveUpdate {
314
321
  if (artifactType == ArtifactType.MANIFEST) {
315
322
  downloadBundleOfTypeManifest(latestBundleId, url);
316
323
  } else {
317
- downloadBundleOfTypeZip(latestBundleId, url, null);
324
+ downloadBundleOfTypeZip(latestBundleId, url, checksum, signature);
318
325
  }
319
326
  // Set the next bundle
320
327
  setNextBundle(latestBundleId);
@@ -474,14 +481,15 @@ public class LiveUpdate {
474
481
  }
475
482
  }
476
483
 
477
- private void downloadAndVerifyFile(@NonNull String url, @NonNull File file, @Nullable String checksum) throws Exception {
484
+ private void downloadAndVerifyFile(@NonNull String url, @NonNull File file, @Nullable String checksum, @Nullable String signature)
485
+ throws Exception {
478
486
  Response response = httpClient.execute(url);
479
487
  ResponseBody responseBody = response.body();
480
488
  if (response.isSuccessful()) {
481
489
  LiveUpdateHttpClient.writeResponseBodyToFile(responseBody, file);
482
490
  // Verify the file
483
491
  checksum = checksum == null ? LiveUpdateHttpClient.getChecksumFromResponse(response) : checksum;
484
- String signature = LiveUpdateHttpClient.getSignatureFromResponse(response);
492
+ signature = signature == null ? LiveUpdateHttpClient.getSignatureFromResponse(response) : signature;
485
493
  verifyFile(file, checksum, signature);
486
494
  } else {
487
495
  Exception exception = new Exception(responseBody.string());
@@ -497,7 +505,7 @@ public class LiveUpdate {
497
505
 
498
506
  File destinationFile = new File(destinationDirectory, href);
499
507
  destinationFile.getParentFile().mkdirs();
500
- downloadAndVerifyFile(url, destinationFile, null);
508
+ downloadAndVerifyFile(url, destinationFile, null, null);
501
509
  return destinationFile;
502
510
  }
503
511
 
@@ -579,11 +587,15 @@ public class LiveUpdate {
579
587
  addBundleOfTypeManifest(bundleId, temporaryDirectory);
580
588
  }
581
589
 
582
- private void downloadBundleOfTypeZip(@NonNull String bundleId, @NonNull String downloadUrl, @Nullable String checksum)
583
- throws Exception {
590
+ private void downloadBundleOfTypeZip(
591
+ @NonNull String bundleId,
592
+ @NonNull String downloadUrl,
593
+ @Nullable String checksum,
594
+ @Nullable String signature
595
+ ) throws Exception {
584
596
  File file = buildTemporaryZipFile();
585
597
  // Download the bundle
586
- downloadAndVerifyFile(downloadUrl, file, checksum);
598
+ downloadAndVerifyFile(downloadUrl, file, checksum, signature);
587
599
  // Add the bundle
588
600
  addBundleOfTypeZip(bundleId, file);
589
601
  // Delete the temporary file
@@ -24,7 +24,7 @@ import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
24
24
  public class LiveUpdatePlugin extends Plugin {
25
25
 
26
26
  public static final String TAG = "LiveUpdate";
27
- public static final String VERSION = "6.7.1";
27
+ public static final String VERSION = "6.8.0";
28
28
  public static final String SHARED_PREFERENCES_NAME = "CapawesomeLiveUpdate"; // DO NOT CHANGE
29
29
  public static final String ERROR_APP_ID_MISSING = "appId must be configured.";
30
30
  public static final String ERROR_BUNDLE_EXISTS = "bundle already exists.";
@@ -98,13 +98,14 @@ public class LiveUpdatePlugin extends Plugin {
98
98
  return;
99
99
  }
100
100
  String checksum = call.getString("checksum");
101
+ String signature = call.getString("signature");
101
102
  String url = call.getString("url");
102
103
  if (url == null) {
103
104
  call.reject(ERROR_URL_MISSING);
104
105
  return;
105
106
  }
106
107
 
107
- DownloadBundleOptions options = new DownloadBundleOptions(artifactType, bundleId, checksum, url);
108
+ DownloadBundleOptions options = new DownloadBundleOptions(artifactType, bundleId, checksum, signature, url);
108
109
  EmptyCallback callback = new EmptyCallback() {
109
110
  @Override
110
111
  public void success() {
@@ -16,6 +16,15 @@ public class GetLatestBundleResponse {
16
16
  @NonNull
17
17
  private String bundleId;
18
18
 
19
+ @Nullable
20
+ private String channelName;
21
+
22
+ @Nullable
23
+ private String checksum;
24
+
25
+ @Nullable
26
+ private String signature;
27
+
19
28
  @NonNull
20
29
  private String url;
21
30
 
@@ -27,6 +36,9 @@ public class GetLatestBundleResponse {
27
36
  this.artifactType = ArtifactType.ZIP;
28
37
  }
29
38
  this.bundleId = responseJson.optString("bundleId");
39
+ this.channelName = responseJson.isNull("channelName") ? null : responseJson.optString("channelName");
40
+ this.checksum = responseJson.optString("checksum");
41
+ this.signature = responseJson.optString("signature");
30
42
  this.url = responseJson.optString("url");
31
43
  }
32
44
 
@@ -40,6 +52,21 @@ public class GetLatestBundleResponse {
40
52
  return bundleId;
41
53
  }
42
54
 
55
+ @Nullable
56
+ public String getChannelName() {
57
+ return channelName;
58
+ }
59
+
60
+ @Nullable
61
+ public String getChecksum() {
62
+ return checksum;
63
+ }
64
+
65
+ @Nullable
66
+ public String getSignature() {
67
+ return signature;
68
+ }
69
+
43
70
  @NonNull
44
71
  public String getUrl() {
45
72
  return url;
@@ -15,10 +15,19 @@ public class DownloadBundleOptions {
15
15
  @Nullable
16
16
  private String checksum;
17
17
 
18
+ @Nullable
19
+ private String signature;
20
+
18
21
  @NonNull
19
22
  private String url;
20
23
 
21
- public DownloadBundleOptions(@NonNull String artifactType, @NonNull String bundleId, @Nullable String checksum, @NonNull String url) {
24
+ public DownloadBundleOptions(
25
+ @NonNull String artifactType,
26
+ @NonNull String bundleId,
27
+ @Nullable String checksum,
28
+ @Nullable String signature,
29
+ @NonNull String url
30
+ ) {
22
31
  if (artifactType.equals("manifest")) {
23
32
  this.artifactType = ArtifactType.MANIFEST;
24
33
  } else {
@@ -26,6 +35,7 @@ public class DownloadBundleOptions {
26
35
  }
27
36
  this.bundleId = bundleId;
28
37
  this.checksum = checksum;
38
+ this.signature = signature;
29
39
  this.url = url;
30
40
  }
31
41
 
@@ -44,6 +54,11 @@ public class DownloadBundleOptions {
44
54
  return checksum;
45
55
  }
46
56
 
57
+ @Nullable
58
+ public String getSignature() {
59
+ return signature;
60
+ }
61
+
47
62
  @NonNull
48
63
  public String getUrl() {
49
64
  return url;
@@ -15,13 +15,32 @@ public class FetchLatestBundleResult implements Result {
15
15
  @Nullable
16
16
  private final String bundleId;
17
17
 
18
+ @Nullable
19
+ private final String channel;
20
+
21
+ @Nullable
22
+ private final String checksum;
23
+
18
24
  @Nullable
19
25
  private final String downloadUrl;
20
26
 
21
- public FetchLatestBundleResult(@Nullable ArtifactType artifactType, @Nullable String bundleId, @Nullable String downloadUrl) {
27
+ @Nullable
28
+ private final String signature;
29
+
30
+ public FetchLatestBundleResult(
31
+ @Nullable ArtifactType artifactType,
32
+ @Nullable String bundleId,
33
+ @Nullable String channel,
34
+ @Nullable String checksum,
35
+ @Nullable String downloadUrl,
36
+ @Nullable String signature
37
+ ) {
22
38
  this.artifactType = artifactType;
23
39
  this.bundleId = bundleId;
40
+ this.channel = channel;
41
+ this.checksum = checksum;
24
42
  this.downloadUrl = downloadUrl;
43
+ this.signature = signature;
25
44
  }
26
45
 
27
46
  @NonNull
@@ -33,9 +52,18 @@ public class FetchLatestBundleResult implements Result {
33
52
  result.put("artifactType", "zip");
34
53
  }
35
54
  result.put("bundleId", bundleId == null ? JSONObject.NULL : bundleId);
55
+ if (channel != null) {
56
+ result.put("channel", channel);
57
+ }
58
+ if (checksum != null) {
59
+ result.put("checksum", checksum);
60
+ }
36
61
  if (downloadUrl != null) {
37
62
  result.put("downloadUrl", downloadUrl);
38
63
  }
64
+ if (signature != null) {
65
+ result.put("signature", signature);
66
+ }
39
67
  return result;
40
68
  }
41
69
  }
package/dist/docs.json CHANGED
@@ -480,13 +480,21 @@
480
480
  {
481
481
  "text": "6.1.0",
482
482
  "name": "since"
483
- },
483
+ }
484
+ ],
485
+ "docs": "The checksum of the self-hosted bundle as a SHA-256 hash\nin base64 format to verify the integrity of the bundle.\n\n**Attention**: Only supported for the `zip` artifact type.",
486
+ "complexTypes": [],
487
+ "type": "string | undefined"
488
+ },
489
+ {
490
+ "name": "signature",
491
+ "tags": [
484
492
  {
485
- "text": "The server should return a `X-Checksum` header instead.",
486
- "name": "deprecated"
493
+ "text": "6.8.0",
494
+ "name": "since"
487
495
  }
488
496
  ],
489
- "docs": "The checksum of the bundle to verify the integrity of the ZIP file.\n\nMust be a SHA-256 hash in base64 format.",
497
+ "docs": "The signature of the self-hosted bundle as a signed SHA-256 hash\nin base64 format to verify the integrity of the bundle.\n\n**Attention**: Only supported for the `zip` artifact type.",
490
498
  "complexTypes": [],
491
499
  "type": "string | undefined"
492
500
  },
@@ -544,6 +552,30 @@
544
552
  "complexTypes": [],
545
553
  "type": "string | null"
546
554
  },
555
+ {
556
+ "name": "channel",
557
+ "tags": [
558
+ {
559
+ "text": "6.9.0",
560
+ "name": "since"
561
+ }
562
+ ],
563
+ "docs": "The name of the channel that the bundle is actually from.\n\nThis is the resolved channel after applying any forced channel assignment\nand may differ from the channel set by the Live Update SDK.",
564
+ "complexTypes": [],
565
+ "type": "string | undefined"
566
+ },
567
+ {
568
+ "name": "checksum",
569
+ "tags": [
570
+ {
571
+ "text": "6.8.0",
572
+ "name": "since"
573
+ }
574
+ ],
575
+ "docs": "The checksum of the latest bundle if the bundle is self-hosted.\n\nIf the bundle is hosted on Capawesome Cloud, the checksum will be\nreturned as response header when downloading the bundle.",
576
+ "complexTypes": [],
577
+ "type": "string | undefined"
578
+ },
547
579
  {
548
580
  "name": "downloadUrl",
549
581
  "tags": [
@@ -555,6 +587,18 @@
555
587
  "docs": "The URL of the latest bundle to download.\nPass this URL to the `downloadBundle(...)` method to download the bundle.",
556
588
  "complexTypes": [],
557
589
  "type": "string | undefined"
590
+ },
591
+ {
592
+ "name": "signature",
593
+ "tags": [
594
+ {
595
+ "text": "6.8.0",
596
+ "name": "since"
597
+ }
598
+ ],
599
+ "docs": "The signature of the latest bundle if the bundle is self-hosted.\n\nIf the bundle is hosted on Capawesome Cloud, the signature will be\nreturned as response header when downloading the bundle.",
600
+ "complexTypes": [],
601
+ "type": "string | undefined"
558
602
  }
559
603
  ]
560
604
  },
@@ -578,7 +622,7 @@
578
622
  "name": "since"
579
623
  }
580
624
  ],
581
- "docs": "The name of the channel where the latest bundle is fetched from.",
625
+ "docs": "The preferred channel name from which the latest bundle should be fetched.\n\nThis is the SDK preference and may be overridden by a forced channel assignment\nconfigured in the Capawesome Cloud Console.",
582
626
  "complexTypes": [],
583
627
  "type": "string | undefined"
584
628
  }
@@ -1000,7 +1044,7 @@
1000
1044
  "name": "since"
1001
1045
  }
1002
1046
  ],
1003
- "docs": "The name of the channel where the latest bundle is fetched from.",
1047
+ "docs": "The preferred channel name from which the latest bundle should be fetched.\n\nThis is the SDK preference and may be overridden by a forced channel assignment\nconfigured in the Capawesome Cloud Console.",
1004
1048
  "complexTypes": [],
1005
1049
  "type": "string | undefined"
1006
1050
  }
@@ -283,14 +283,23 @@ export interface DownloadBundleOptions {
283
283
  */
284
284
  bundleId: string;
285
285
  /**
286
- * The checksum of the bundle to verify the integrity of the ZIP file.
286
+ * The checksum of the self-hosted bundle as a SHA-256 hash
287
+ * in base64 format to verify the integrity of the bundle.
287
288
  *
288
- * Must be a SHA-256 hash in base64 format.
289
+ * **Attention**: Only supported for the `zip` artifact type.
289
290
  *
290
291
  * @since 6.1.0
291
- * @deprecated The server should return a `X-Checksum` header instead.
292
292
  */
293
293
  checksum?: string;
294
+ /**
295
+ * The signature of the self-hosted bundle as a signed SHA-256 hash
296
+ * in base64 format to verify the integrity of the bundle.
297
+ *
298
+ * **Attention**: Only supported for the `zip` artifact type.
299
+ *
300
+ * @since 6.8.0
301
+ */
302
+ signature?: string;
294
303
  /**
295
304
  * The URL of the bundle to download.
296
305
  *
@@ -316,7 +325,10 @@ export interface DownloadBundleOptions {
316
325
  */
317
326
  export interface FetchLatestBundleOptions {
318
327
  /**
319
- * The name of the channel where the latest bundle is fetched from.
328
+ * The preferred channel name from which the latest bundle should be fetched.
329
+ *
330
+ * This is the SDK preference and may be overridden by a forced channel assignment
331
+ * configured in the Capawesome Cloud Console.
320
332
  *
321
333
  * @since 6.7.0
322
334
  */
@@ -340,6 +352,24 @@ export interface FetchLatestBundleResult {
340
352
  * @since 6.6.0
341
353
  */
342
354
  bundleId: string | null;
355
+ /**
356
+ * The name of the channel that the bundle is actually from.
357
+ *
358
+ * This is the resolved channel after applying any forced channel assignment
359
+ * and may differ from the channel set by the Live Update SDK.
360
+ *
361
+ * @since 6.9.0
362
+ */
363
+ channel?: string;
364
+ /**
365
+ * The checksum of the latest bundle if the bundle is self-hosted.
366
+ *
367
+ * If the bundle is hosted on Capawesome Cloud, the checksum will be
368
+ * returned as response header when downloading the bundle.
369
+ *
370
+ * @since 6.8.0
371
+ */
372
+ checksum?: string;
343
373
  /**
344
374
  * The URL of the latest bundle to download.
345
375
  * Pass this URL to the `downloadBundle(...)` method to download the bundle.
@@ -347,6 +377,15 @@ export interface FetchLatestBundleResult {
347
377
  * @since 6.7.0
348
378
  */
349
379
  downloadUrl?: string;
380
+ /**
381
+ * The signature of the latest bundle if the bundle is self-hosted.
382
+ *
383
+ * If the bundle is hosted on Capawesome Cloud, the signature will be
384
+ * returned as response header when downloading the bundle.
385
+ *
386
+ * @since 6.8.0
387
+ */
388
+ signature?: string;
350
389
  }
351
390
  /**
352
391
  * @since 5.0.0
@@ -530,7 +569,10 @@ export interface SetNextBundleOptions {
530
569
  */
531
570
  export interface SyncOptions {
532
571
  /**
533
- * The name of the channel where the latest bundle is fetched from.
572
+ * The preferred channel name from which the latest bundle should be fetched.
573
+ *
574
+ * This is the SDK preference and may be overridden by a forced channel assignment
575
+ * configured in the Capawesome Cloud Console.
534
576
  *
535
577
  * @since 6.7.0
536
578
  */
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * This is **NOT** the same as the app identifier (e.g. `com.example.app`).\n * This is a unique identifier generated by Capawesome Cloud (e.g. `6e351b4f-69a7-415e-a057-4567df7ffe94`).\n *\n * @since 5.0.0\n * @example '6e351b4f-69a7-415e-a057-4567df7ffe94'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * The default channel of the app.\n *\n * @since 6.3.0\n * @example 'production'\n */\n defaultChannel?: string;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The timeout in milliseconds for HTTP requests.\n *\n * @since 6.4.0\n * @default 60000\n */\n httpTimeout?: number;\n /**\n * The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 6.2.0\n * @default 'us'\n * @example 'eu'\n * @deprecated This option will be removed in the future.\n */\n location?: 'us' | 'eu';\n /**\n * The public key to verify the integrity of the bundle.\n *\n * The public key must be a PEM-encoded RSA public key.\n *\n * @since 6.1.0\n * @example '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----'\n */\n publicKey?: string;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Fetch the latest bundle using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Only available on Android and iOS.\n *\n * @since 6.6.0\n */\n fetchLatestBundle(options?: FetchLatestBundleOptions): Promise<FetchLatestBundleResult>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n * @deprecated Use `getCurrentBundle()` instead.\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all identifiers of bundles that have been downloaded.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel that is used for the update.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the bundle identifier of the current bundle.\n * The current bundle is the bundle that is currently used by the app.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n getCurrentBundle(): Promise<GetCurrentBundleResult>;\n /**\n * Get the custom identifier of the device.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the unique device identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the bundle identifier of the next bundle.\n * The next bundle is the bundle that will be used after calling `reload()`\n * or restarting the app.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n getNextBundle(): Promise<GetNextBundleResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * **Attention**: This method should be called as soon as the app is ready to use\n * to prevent the app from being reset to the default bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<void>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n * @deprecated Use `setNextBundle()` instead.\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel to use for the update.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the device.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n setNextBundle(options: SetNextBundleOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(options?: SyncOptions): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The artifact type of the bundle.\n *\n * @since 6.6.0\n * @default 'zip'\n * @example 'manifest'\n */\n artifactType?: 'manifest' | 'zip';\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n /**\n * The checksum of the bundle to verify the integrity of the ZIP file.\n *\n * Must be a SHA-256 hash in base64 format.\n *\n * @since 6.1.0\n * @deprecated The server should return a `X-Checksum` header instead.\n */\n checksum?: string;\n /**\n * The URL of the bundle to download.\n *\n * For the `zip` artifact type, the URL must point to a ZIP file.\n * For the `manifest` artifact type, the URL serves as the base URL\n * to download the individual files. For example, if the URL is\n * `https://example.com/download`, the plugin will download the file\n * with the href `index.html` from `https://example.com/download?href=index.html`.\n *\n * To **verify the integrity** of the file, the server must return\n * a `X-Checksum` header with the SHA-256 hash in base64 format.\n *\n * To **verify the signature** of the file, the server must return\n * a `X-Signature` header with the signed SHA-256 hash in base64 format.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface FetchLatestBundleOptions {\n /**\n * The name of the channel where the latest bundle is fetched from.\n *\n * @since 6.7.0\n */\n channel?: string;\n}\n\n/**\n * @since 6.6.0\n */\nexport interface FetchLatestBundleResult {\n /**\n * The artifact type of the bundle.\n *\n * @since 6.7.0\n */\n artifactType?: 'manifest' | 'zip';\n /**\n * The unique identifier of the latest bundle.\n *\n * If `null`, no bundle is available.\n *\n * @since 6.6.0\n */\n bundleId: string | null;\n /**\n * The URL of the latest bundle to download.\n * Pass this URL to the `downloadBundle(...)` method to download the bundle.\n *\n * @since 6.7.0\n */\n downloadUrl?: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel name.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface GetCurrentBundleResult {\n /**\n * The unique identifier of the current bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 6.7.0\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\n * The value of this property is the same for apps that come from the same vendor running on the same device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface GetNextBundleResult {\n /**\n * The unique identifier of the next bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 6.7.0\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the device.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel name.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the device.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface SetNextBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * Set `null` to use the default bundle (same as calling `reset()`).\n *\n * @since 6.7.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface SyncOptions {\n /**\n * The name of the channel where the latest bundle is fetched from.\n *\n * @since 6.7.0\n */\n channel?: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * This is **NOT** the same as the app identifier (e.g. `com.example.app`).\n * This is a unique identifier generated by Capawesome Cloud (e.g. `6e351b4f-69a7-415e-a057-4567df7ffe94`).\n *\n * @since 5.0.0\n * @example '6e351b4f-69a7-415e-a057-4567df7ffe94'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * The default channel of the app.\n *\n * @since 6.3.0\n * @example 'production'\n */\n defaultChannel?: string;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The timeout in milliseconds for HTTP requests.\n *\n * @since 6.4.0\n * @default 60000\n */\n httpTimeout?: number;\n /**\n * The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 6.2.0\n * @default 'us'\n * @example 'eu'\n * @deprecated This option will be removed in the future.\n */\n location?: 'us' | 'eu';\n /**\n * The public key to verify the integrity of the bundle.\n *\n * The public key must be a PEM-encoded RSA public key.\n *\n * @since 6.1.0\n * @example '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----'\n */\n publicKey?: string;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Fetch the latest bundle using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Only available on Android and iOS.\n *\n * @since 6.6.0\n */\n fetchLatestBundle(options?: FetchLatestBundleOptions): Promise<FetchLatestBundleResult>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n * @deprecated Use `getCurrentBundle()` instead.\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all identifiers of bundles that have been downloaded.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel that is used for the update.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the bundle identifier of the current bundle.\n * The current bundle is the bundle that is currently used by the app.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n getCurrentBundle(): Promise<GetCurrentBundleResult>;\n /**\n * Get the custom identifier of the device.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the unique device identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the bundle identifier of the next bundle.\n * The next bundle is the bundle that will be used after calling `reload()`\n * or restarting the app.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n getNextBundle(): Promise<GetNextBundleResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * **Attention**: This method should be called as soon as the app is ready to use\n * to prevent the app from being reset to the default bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<void>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n * @deprecated Use `setNextBundle()` instead.\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel to use for the update.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the device.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 6.7.0\n */\n setNextBundle(options: SetNextBundleOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(options?: SyncOptions): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The artifact type of the bundle.\n *\n * @since 6.6.0\n * @default 'zip'\n * @example 'manifest'\n */\n artifactType?: 'manifest' | 'zip';\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n /**\n * The checksum of the self-hosted bundle as a SHA-256 hash\n * in base64 format to verify the integrity of the bundle.\n *\n * **Attention**: Only supported for the `zip` artifact type.\n *\n * @since 6.1.0\n */\n checksum?: string;\n /**\n * The signature of the self-hosted bundle as a signed SHA-256 hash\n * in base64 format to verify the integrity of the bundle.\n *\n * **Attention**: Only supported for the `zip` artifact type.\n *\n * @since 6.8.0\n */\n signature?: string;\n /**\n * The URL of the bundle to download.\n *\n * For the `zip` artifact type, the URL must point to a ZIP file.\n * For the `manifest` artifact type, the URL serves as the base URL\n * to download the individual files. For example, if the URL is\n * `https://example.com/download`, the plugin will download the file\n * with the href `index.html` from `https://example.com/download?href=index.html`.\n *\n * To **verify the integrity** of the file, the server must return\n * a `X-Checksum` header with the SHA-256 hash in base64 format.\n *\n * To **verify the signature** of the file, the server must return\n * a `X-Signature` header with the signed SHA-256 hash in base64 format.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface FetchLatestBundleOptions {\n /**\n * The preferred channel name from which the latest bundle should be fetched.\n *\n * This is the SDK preference and may be overridden by a forced channel assignment\n * configured in the Capawesome Cloud Console.\n *\n * @since 6.7.0\n */\n channel?: string;\n}\n\n/**\n * @since 6.6.0\n */\nexport interface FetchLatestBundleResult {\n /**\n * The artifact type of the bundle.\n *\n * @since 6.7.0\n */\n artifactType?: 'manifest' | 'zip';\n /**\n * The unique identifier of the latest bundle.\n *\n * If `null`, no bundle is available.\n *\n * @since 6.6.0\n */\n bundleId: string | null;\n /**\n * The name of the channel that the bundle is actually from.\n *\n * This is the resolved channel after applying any forced channel assignment\n * and may differ from the channel set by the Live Update SDK.\n *\n * @since 6.9.0\n */\n channel?: string;\n /**\n * The checksum of the latest bundle if the bundle is self-hosted.\n *\n * If the bundle is hosted on Capawesome Cloud, the checksum will be\n * returned as response header when downloading the bundle.\n *\n * @since 6.8.0\n */\n checksum?: string;\n /**\n * The URL of the latest bundle to download.\n * Pass this URL to the `downloadBundle(...)` method to download the bundle.\n *\n * @since 6.7.0\n */\n downloadUrl?: string;\n /**\n * The signature of the latest bundle if the bundle is self-hosted.\n *\n * If the bundle is hosted on Capawesome Cloud, the signature will be\n * returned as response header when downloading the bundle.\n *\n * @since 6.8.0\n */\n signature?: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel name.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface GetCurrentBundleResult {\n /**\n * The unique identifier of the current bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 6.7.0\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\n * The value of this property is the same for apps that come from the same vendor running on the same device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface GetNextBundleResult {\n /**\n * The unique identifier of the next bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 6.7.0\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the device.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel name.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the device.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface SetNextBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * Set `null` to use the default bundle (same as calling `reset()`).\n *\n * @since 6.7.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 6.7.0\n */\nexport interface SyncOptions {\n /**\n * The preferred channel name from which the latest bundle should be fetched.\n *\n * This is the SDK preference and may be overridden by a forced channel assignment\n * configured in the Capawesome Cloud Console.\n *\n * @since 6.7.0\n */\n channel?: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
@@ -5,9 +5,10 @@ import Capacitor
5
5
  private var artifactType: ArtifactType
6
6
  private var bundleId: String
7
7
  private var checksum: String?
8
+ private var signature: String?
8
9
  private var url: String
9
10
 
10
- init(artifactType: String, bundleId: String, checksum: String?, url: String) {
11
+ init(artifactType: String, bundleId: String, checksum: String?, signature: String?, url: String) {
11
12
  if artifactType == "manifest" {
12
13
  self.artifactType = .manifest
13
14
  } else {
@@ -15,6 +16,7 @@ import Capacitor
15
16
  }
16
17
  self.bundleId = bundleId
17
18
  self.checksum = checksum
19
+ self.signature = signature
18
20
  self.url = url
19
21
  }
20
22
 
@@ -30,6 +32,10 @@ import Capacitor
30
32
  return checksum
31
33
  }
32
34
 
35
+ func getSignature() -> String? {
36
+ return signature
37
+ }
38
+
33
39
  func getUrl() -> String {
34
40
  return url
35
41
  }
@@ -4,12 +4,18 @@ import Capacitor
4
4
  @objc public class FetchLatestBundleResult: NSObject, Result {
5
5
  private let artifactType: ArtifactType?
6
6
  private let bundleId: String?
7
+ private let channel: String?
8
+ private let checksum: String?
7
9
  private let downloadUrl: String?
10
+ private let signature: String?
8
11
 
9
- init(artifactType: ArtifactType?, bundleId: String?, downloadUrl: String?) {
12
+ init(artifactType: ArtifactType?, bundleId: String?, channel: String?, checksum: String?, downloadUrl: String?, signature: String?) {
10
13
  self.artifactType = artifactType
11
14
  self.bundleId = bundleId
15
+ self.channel = channel
16
+ self.checksum = checksum
12
17
  self.downloadUrl = downloadUrl
18
+ self.signature = signature
13
19
  }
14
20
 
15
21
  public func toJSObject() -> AnyObject {
@@ -20,9 +26,18 @@ import Capacitor
20
26
  result["artifactType"] = "zip"
21
27
  }
22
28
  result["bundleId"] = bundleId == nil ? NSNull() : bundleId
29
+ if let channel = channel {
30
+ result["channel"] = channel
31
+ }
32
+ if let checksum = checksum {
33
+ result["checksum"] = checksum
34
+ }
23
35
  if let downloadUrl = downloadUrl {
24
36
  result["downloadUrl"] = downloadUrl
25
37
  }
38
+ if let signature = signature {
39
+ result["signature"] = signature
40
+ }
26
41
  return result as AnyObject
27
42
  }
28
43
  }
@@ -35,11 +35,12 @@ import CommonCrypto
35
35
 
36
36
  if config.enabled {
37
37
  if wasUpdated() && config.resetOnUpdate {
38
+ CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "App was updated. Resetting to default bundle.")
38
39
  reset()
39
40
  } else {
40
41
  startRollbackTimer()
41
42
  }
42
- saveCurrentBundleVersion()
43
+ saveCurrentBundleShortVersionStringAndBundleVersion()
43
44
  }
44
45
  }
45
46
 
@@ -64,6 +65,7 @@ import CommonCrypto
64
65
  let artifactType = options.getArtifactType()
65
66
  let bundleId = options.getBundleId()
66
67
  let checksum = options.getChecksum()
68
+ let signature = options.getSignature()
67
69
  let url = options.getUrl()
68
70
 
69
71
  // Check if the bundle already exists
@@ -75,13 +77,13 @@ import CommonCrypto
75
77
  if artifactType == .manifest {
76
78
  try await downloadBundleOfTypeManifest(bundleId: bundleId, url: url)
77
79
  } else {
78
- try await downloadBundleOfTypeZip(bundleId: bundleId, url: url, checksum: checksum)
80
+ try await downloadBundleOfTypeZip(bundleId: bundleId, url: url, checksum: checksum, signature: signature)
79
81
  }
80
82
  }
81
83
 
82
84
  @objc public func fetchLatestBundle(_ options: FetchLatestBundleOptions) async throws -> FetchLatestBundleResult {
83
85
  let response: GetLatestBundleResponse? = try await self.fetchLatestBundle(options)
84
- return FetchLatestBundleResult(artifactType: response?.artifactType, bundleId: response?.bundleId, downloadUrl: response?.url)
86
+ return FetchLatestBundleResult(artifactType: response?.artifactType, bundleId: response?.bundleId, channel: response?.channelName, checksum: response?.checksum, downloadUrl: response?.url, signature: response?.signature)
85
87
  }
86
88
 
87
89
  @objc public func getBundle(completion: @escaping (Result?, Error?) -> Void) {
@@ -222,6 +224,8 @@ import CommonCrypto
222
224
  }
223
225
  let artifactType = response.artifactType
224
226
  let latestBundleId = response.bundleId
227
+ let checksum = response.checksum
228
+ let signature = response.signature
225
229
  let downloadUrl = response.url
226
230
  // Check if bundle already exists
227
231
  if hasBundle(bundleId: latestBundleId) {
@@ -238,7 +242,7 @@ import CommonCrypto
238
242
  if artifactType == .manifest {
239
243
  try await downloadBundleOfTypeManifest(bundleId: latestBundleId, url: downloadUrl)
240
244
  } else {
241
- try await downloadBundleOfTypeZip(bundleId: latestBundleId, url: downloadUrl, checksum: nil)
245
+ try await downloadBundleOfTypeZip(bundleId: latestBundleId, url: downloadUrl, checksum: checksum, signature: signature)
242
246
  }
243
247
  // Set the next bundle
244
248
  setNextBundle(bundleId: latestBundleId)
@@ -362,7 +366,7 @@ import CommonCrypto
362
366
  }
363
367
  }
364
368
 
365
- private func downloadAndVerifyFile(url: String, file: URL, checksum: String?) async throws {
369
+ private func downloadAndVerifyFile(url: String, file: URL, checksum: String?, signature: String?) async throws {
366
370
  let destination: DownloadRequest.Destination = { _, _ in
367
371
  return (file, [.createIntermediateDirectories])
368
372
  }
@@ -380,8 +384,8 @@ import CommonCrypto
380
384
  guard let response = result.response else {
381
385
  throw CustomError.unknown
382
386
  }
383
- let checksum = checksum == nil ? LiveUpdateHttpClient.getChecksumFromResponse(response: response) : checksum
384
- let signature = LiveUpdateHttpClient.getSignatureFromResponse(response: response)
387
+ let checksum = checksum ?? LiveUpdateHttpClient.getChecksumFromResponse(response: response)
388
+ let signature = signature ?? LiveUpdateHttpClient.getSignatureFromResponse(response: response)
385
389
  try verifyFile(url: file, checksum: checksum, signature: signature)
386
390
  }
387
391
 
@@ -392,7 +396,7 @@ import CommonCrypto
392
396
  var urlComponents = URLComponents(string: baseUrl)!
393
397
  urlComponents.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
394
398
  let url = urlComponents.string!
395
- try await self.downloadAndVerifyFile(url: url, file: fileURL, checksum: nil)
399
+ try await self.downloadAndVerifyFile(url: url, file: fileURL, checksum: nil, signature: nil)
396
400
  return fileURL
397
401
  }
398
402
 
@@ -433,11 +437,11 @@ import CommonCrypto
433
437
  try await addBundleOfTypeManifest(bundleId: bundleId, directory: temporaryDirectory)
434
438
  }
435
439
 
436
- private func downloadBundleOfTypeZip(bundleId: String, url: String, checksum: String?) async throws {
440
+ private func downloadBundleOfTypeZip(bundleId: String, url: String, checksum: String?, signature: String?) async throws {
437
441
  let timestamp = String(Int(Date().timeIntervalSince1970))
438
442
  let temporaryZipFileUrl = self.cachesDirectoryUrl.appendingPathComponent(timestamp + ".zip")
439
443
  // Download the bundle
440
- try await downloadAndVerifyFile(url: url, file: temporaryZipFileUrl, checksum: checksum)
444
+ try await downloadAndVerifyFile(url: url, file: temporaryZipFileUrl, checksum: checksum, signature: signature)
441
445
  // Add the bundle
442
446
  try await addBundleOfTypeZip(bundleId: bundleId, zipFile: temporaryZipFileUrl)
443
447
  }
@@ -611,10 +615,10 @@ import CommonCrypto
611
615
  setCurrentCapacitorServerPathToDefaultWebAssetDir()
612
616
  }
613
617
 
614
- private func saveCurrentBundleVersion() {
615
- guard let currentBundleVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String else {
616
- return
617
- }
618
+ private func saveCurrentBundleShortVersionStringAndBundleVersion() {
619
+ let currentBundleShortVersionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
620
+ preferences.setLastBundleShortVersionString(currentBundleShortVersionString)
621
+ let currentBundleVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
618
622
  preferences.setLastBundleVersion(currentBundleVersion)
619
623
  }
620
624
 
@@ -786,19 +790,24 @@ import CommonCrypto
786
790
  }
787
791
 
788
792
  private func wasUpdated() -> Bool {
793
+ guard let lastBundleShortVersionString = preferences.getLastBundleShortVersionString() else {
794
+ // If the last bundle short version is not set, the app may have been updated
795
+ return true
796
+ }
789
797
  guard let lastBundleVersionString = preferences.getLastBundleVersion() else {
790
- return false
798
+ // If the last bundle version is not set, the app may have been updated
799
+ return true
791
800
  }
792
- guard let lastBundleVersion = Int(lastBundleVersionString) else {
793
- return false
801
+ guard let currentBundleShortVersionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
802
+ // If the current bundle short version is not set, return true for safety reasons
803
+ return true
794
804
  }
795
805
  guard let currentBundleVersionString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String else {
796
- return false
797
- }
798
- guard let currentBundleVersion = Int(currentBundleVersionString) else {
799
- return false
806
+ // If the current bundle version is not set, return true for safety reasons
807
+ return true
800
808
  }
801
- return currentBundleVersion > lastBundleVersion
809
+ // `CFBundleVersion` is not unique across different versions of the app
810
+ return lastBundleShortVersionString + "_" + lastBundleVersionString != currentBundleShortVersionString + "_" + currentBundleVersionString
802
811
  }
803
812
  }
804
813
 
@@ -8,7 +8,7 @@ import Capacitor
8
8
  @objc(LiveUpdatePlugin)
9
9
  public class LiveUpdatePlugin: CAPPlugin {
10
10
  public static let tag = "LiveUpdate"
11
- public static let version = "6.7.1"
11
+ public static let version = "6.8.0"
12
12
  public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
13
13
 
14
14
  private var config: LiveUpdateConfig?
@@ -46,12 +46,13 @@ public class LiveUpdatePlugin: CAPPlugin {
46
46
  return
47
47
  }
48
48
  let checksum = call.getString("checksum")
49
+ let signature = call.getString("signature")
49
50
  guard let url = call.getString("url") else {
50
51
  call.reject(CustomError.urlMissing.localizedDescription)
51
52
  return
52
53
  }
53
54
 
54
- let options = DownloadBundleOptions(artifactType: artifactType, bundleId: bundleId, checksum: checksum, url: url)
55
+ let options = DownloadBundleOptions(artifactType: artifactType, bundleId: bundleId, checksum: checksum, signature: signature, url: url)
55
56
 
56
57
  try await implementation?.downloadBundle(options)
57
58
  self.resolveCall(call)
@@ -3,6 +3,7 @@ import Foundation
3
3
  public class LiveUpdatePreferences: NSObject {
4
4
  private let channelKey = "channel" // DO NOT CHANGE
5
5
  private let customIdKey = "customId" // DO NOT CHANGE
6
+ private let lastBundleShortVersionStringKey = "lastBundleShortVersionString" // DO NOT CHANGE
6
7
  private let lastBundleVersionKey = "lastBundleVersion" // DO NOT CHANGE
7
8
 
8
9
  public func getChannel() -> String? {
@@ -13,6 +14,10 @@ public class LiveUpdatePreferences: NSObject {
13
14
  return UserDefaults.standard.string(forKey: applyPrefix(to: customIdKey))
14
15
  }
15
16
 
17
+ public func getLastBundleShortVersionString() -> String? {
18
+ return UserDefaults.standard.string(forKey: applyPrefix(to: lastBundleShortVersionStringKey))
19
+ }
20
+
16
21
  public func getLastBundleVersion() -> String? {
17
22
  return UserDefaults.standard.string(forKey: applyPrefix(to: lastBundleVersionKey))
18
23
  }
@@ -31,8 +36,21 @@ public class LiveUpdatePreferences: NSObject {
31
36
  UserDefaults.standard.synchronize()
32
37
  }
33
38
 
34
- public func setLastBundleVersion(_ value: String) {
35
- UserDefaults.standard.set(value, forKey: applyPrefix(to: lastBundleVersionKey))
39
+ public func setLastBundleShortVersionString(_ value: String?) {
40
+ if let value = value {
41
+ UserDefaults.standard.set(value, forKey: applyPrefix(to: lastBundleShortVersionStringKey))
42
+ } else {
43
+ UserDefaults.standard.removeObject(forKey: applyPrefix(to: lastBundleShortVersionStringKey))
44
+ }
45
+ UserDefaults.standard.synchronize()
46
+ }
47
+
48
+ public func setLastBundleVersion(_ value: String?) {
49
+ if let value = value {
50
+ UserDefaults.standard.set(value, forKey: applyPrefix(to: lastBundleVersionKey))
51
+ } else {
52
+ UserDefaults.standard.removeObject(forKey: applyPrefix(to: lastBundleVersionKey))
53
+ }
36
54
  UserDefaults.standard.synchronize()
37
55
  }
38
56
 
@@ -1,5 +1,8 @@
1
1
  public struct GetLatestBundleResponse: Codable {
2
2
  var artifactType: ArtifactType
3
3
  var bundleId: String
4
+ var channelName: String?
5
+ var checksum: String?
6
+ var signature: String?
4
7
  var url: String
5
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capawesome/capacitor-live-update",
3
- "version": "6.7.1",
3
+ "version": "6.8.0-dev.2e2696e1.1773643381",
4
4
  "description": "Capacitor plugin to update your app remotely in real-time.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",