@capgo/capacitor-updater 6.25.3 → 6.25.5

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
@@ -24,11 +24,24 @@ Capacitor plugin to update your app remotely in real-time.
24
24
 
25
25
  Open-source Alternative to Appflow, Codepush or Capawesome
26
26
 
27
+ ## Why Capacitor Updater?
28
+
29
+ App store review processes can take days or weeks, blocking critical bug fixes and updates from reaching your users. Capacitor Updater solves this by:
30
+
31
+ - **Instant updates** - Push JavaScript/HTML/CSS updates directly to users without app store review
32
+ - **Delta updates** - Only download changed files, making updates ultra-fast
33
+ - **Rollback protection** - Automatically revert broken updates to keep your app stable
34
+ - **Open source** - Self-host or use Capgo Cloud, with full control over your update infrastructure
35
+ - **Battle-tested** - Used by 3000+ production apps with proven reliability
36
+ - **Most stared** - Capacitor updater is the most stared Capacitor plugin on GitHub
37
+
38
+ Perfect for fixing bugs immediately, A/B testing features, and maintaining control over your release schedule.
39
+
27
40
  ## Features
28
41
 
29
42
  - ☁️ Cloud / Self hosted Support: Use our [Cloud](https://capgo.app/) to manage your app updates or yours.
30
43
  - 📦 Bundle Management: Download, assign to channel, rollback.
31
- - 📺 Channel Support: Use channels to manage different environements.
44
+ - 📺 Channel Support: Use channels to manage different environments.
32
45
  - 🎯 Set Channel to specific device to do QA or debug one user.
33
46
  - 🔄 Auto Update: Automatically download and set the latest bundle for the app.
34
47
  - 🛟 Rollback: Reset the app to last working bundle if an incompatible bundle has been set.
@@ -63,7 +76,7 @@ Join the [discord](https://discord.gg/VnYRvBfgA6) to get help.
63
76
  | Plugin version | Capacitor compatibility | Maintained |
64
77
  | -------------- | ----------------------- | ----------------- |
65
78
  | v7.\*.\* | v7.\*.\* | ✅ |
66
- | v6.\*.\* | v6.\*.\* | ✅ |
79
+ | v6.\*.\* | v6.\*.\* | ✅ |
67
80
  | v5.\*.\* | v5.\*.\* | ⚠️ Deprecated |
68
81
  | v4.\*.\* | v4.\*.\* | ⚠️ Deprecated |
69
82
  | v3.\*.\* | v3.\*.\* | ⚠️ Deprecated |
@@ -111,7 +124,7 @@ npx cap sync
111
124
 
112
125
  ## Auto-update setup
113
126
 
114
- Create your account in [capgo.app](https://capgo.app) and get your [API key](https://web.capgo.app/dashboard/apikeys)
127
+ Create your account in [capgo.app](https://capgo.app) and get your [API key](https://console.capgo.app/dashboard/apikeys)
115
128
  - Login to CLI `npx @capgo/cli@latest init API_KEY`
116
129
  And follow the steps by step to setup your app.
117
130
 
@@ -140,7 +153,7 @@ Download update distribution zipfiles from a custom URL. Manually control the en
140
153
  import { CapacitorUpdater } from '@capgo/capacitor-updater'
141
154
  CapacitorUpdater.notifyAppReady()
142
155
  ```
143
- This informs Capacitor Updater that the current update bundle has loaded succesfully. Failing to call this method will cause your application to be rolled back to the previously successful version (or built-in bundle).
156
+ This informs Capacitor Updater that the current update bundle has loaded successfully. Failing to call this method will cause your application to be rolled back to the previously successful version (or built-in bundle).
144
157
  - Add this to your application.
145
158
  ```javascript
146
159
  const version = await CapacitorUpdater.download({
@@ -228,42 +241,42 @@ Capacitor Updater works by unzipping a compiled app bundle to the native device
228
241
 
229
242
  CapacitorUpdater can be configured with these options:
230
243
 
231
- | Prop | Type | Description | Default | Since |
232
- | ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
233
- | **`appReadyTimeout`** | <code>number</code> | Configure the number of milliseconds the native plugin should wait before considering an update 'failed'. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | |
234
- | **`responseTimeout`** | <code>number</code> | Configure the number of seconds the native plugin should wait before considering API timeout. Only available for Android and iOS. | <code>20 // (20 second)</code> | |
235
- | **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
236
- | **`autoDeletePrevious`** | <code>boolean</code> | Configure whether the plugin should use automatically delete previous bundles after a successful update. Only available for Android and iOS. | <code>true</code> | |
237
- | **`autoUpdate`** | <code>boolean</code> | Configure whether the plugin should use Auto Update via an update server. Only available for Android and iOS. | <code>true</code> | |
238
- | **`resetWhenUpdate`** | <code>boolean</code> | Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device. Only available for Android and iOS. | <code>true</code> | |
239
- | **`updateUrl`** | <code>string</code> | Configure the URL / endpoint to which update checks are sent. Only available for Android and iOS. | <code>https://plugin.capgo.app/updates</code> | |
240
- | **`channelUrl`** | <code>string</code> | Configure the URL / endpoint for channel operations. Only available for Android and iOS. | <code>https://plugin.capgo.app/channel_self</code> | |
241
- | **`statsUrl`** | <code>string</code> | Configure the URL / endpoint to which update statistics are sent. Only available for Android and iOS. Set to "" to disable stats reporting. | <code>https://plugin.capgo.app/stats</code> | |
242
- | **`privateKey`** | <code>string</code> | Configure the private key for end to end live update encryption. Only available for Android and iOS. Deprecated in version 6.2.0 in favor of publicKey. Still supported for backwards compatibility. | <code>undefined</code> | |
243
- | **`publicKey`** | <code>string</code> | Configure the public key for end to end live update encryption Version 2 Only available for Android and iOS. | <code>undefined</code> | 6.2.0 |
244
- | **`version`** | <code>string</code> | Configure the current version of the app. This will be used for the first update request. If not set, the plugin will get the version from the native code. Only available for Android and iOS. | <code>undefined</code> | 4.17.48 |
245
- | **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. Works well for apps less than 10MB and with uploads done using --partial flag. Zip or apps more than 10MB will be relatively slow for users to update. - false: Never do direct updates (default behavior) - atInstall: Direct update only when app is installed/updated from store, otherwise use normal background update - always: Always do direct updates immediately when available (including when returning from background) - onLaunch: Direct update only on app launch (first foreground after app starts), not when returning from background - true: (deprecated) Same as "always" for backward compatibility Only available for Android and iOS. | <code>false</code> | 5.1.0 |
246
- | **`autoSplashscreen`** | <code>boolean</code> | Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed. This removes the need to manually listen for appReady events and call SplashScreen.hide(). Only works when directUpdate is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires autoUpdate and directUpdate to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
247
- | **`autoSplashscreenLoader`** | <code>boolean</code> | Display a native loading indicator on top of the splashscreen while automatic direct updates are running. Only takes effect when {@link autoSplashscreen} is enabled. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Only available for Android and iOS. | <code>false</code> | 7.19.0 |
248
- | **`autoSplashscreenTimeout`** | <code>number</code> | Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates. If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed. Set to `0` (zero) to disable the timeout. When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch. Requires {@link autoSplashscreen} to be enabled. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | 7.19.0 |
249
- | **`periodCheckDelay`** | <code>number</code> | Configure the delay period for period update check. the unit is in seconds. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
250
- | **`localS3`** | <code>boolean</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
251
- | **`localHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
252
- | **`localWebHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
253
- | **`localSupa`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
254
- | **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
255
- | **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
256
- | **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
257
- | **`allowModifyUrl`** | <code>boolean</code> | Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side. | <code>false</code> | 5.4.0 |
258
- | **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
259
- | **`allowManualBundleError`** | <code>boolean</code> | Allow marking bundles as errored from JavaScript while using manual update flows. When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`. | <code>false</code> | 7.20.0 |
260
- | **`persistCustomId`** | <code>boolean</code> | Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts. Only available for Android and iOS. | <code>false (will be true by default in a future major release v8.x.x)</code> | 7.17.3 |
261
- | **`persistModifyUrl`** | <code>boolean</code> | Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl}, {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts. Only available for Android and iOS. | <code>false</code> | 7.20.0 |
262
- | **`defaultChannel`** | <code>string</code> | Set the default channel for the app in the config. Case sensitive. This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud. This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options | <code>undefined</code> | 5.5.0 |
263
- | **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
264
- | **`keepUrlPathAfterReload`** | <code>boolean</code> | Configure the plugin to keep the URL path after a reload. WARNING: When a reload is triggered, 'window.history' will be cleared. | <code>false</code> | 6.8.0 |
265
- | **`disableJSLogging`** | <code>boolean</code> | Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done | <code>false</code> | 7.3.0 |
266
- | **`shakeMenu`** | <code>boolean</code> | Enable shake gesture to show update menu for debugging/testing purposes | <code>false</code> | 7.5.0 |
244
+ | Prop | Type | Description | Default | Since |
245
+ | ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
246
+ | **`appReadyTimeout`** | <code>number</code> | Configure the number of milliseconds the native plugin should wait before considering an update 'failed'. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | |
247
+ | **`responseTimeout`** | <code>number</code> | Configure the number of seconds the native plugin should wait before considering API timeout. Only available for Android and iOS. | <code>20 // (20 second)</code> | |
248
+ | **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
249
+ | **`autoDeletePrevious`** | <code>boolean</code> | Configure whether the plugin should use automatically delete previous bundles after a successful update. Only available for Android and iOS. | <code>true</code> | |
250
+ | **`autoUpdate`** | <code>boolean</code> | Configure whether the plugin should use Auto Update via an update server. Only available for Android and iOS. | <code>true</code> | |
251
+ | **`resetWhenUpdate`** | <code>boolean</code> | Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device. Only available for Android and iOS. | <code>true</code> | |
252
+ | **`updateUrl`** | <code>string</code> | Configure the URL / endpoint to which update checks are sent. Only available for Android and iOS. | <code>https://plugin.capgo.app/updates</code> | |
253
+ | **`channelUrl`** | <code>string</code> | Configure the URL / endpoint for channel operations. Only available for Android and iOS. | <code>https://plugin.capgo.app/channel_self</code> | |
254
+ | **`statsUrl`** | <code>string</code> | Configure the URL / endpoint to which update statistics are sent. Only available for Android and iOS. Set to "" to disable stats reporting. | <code>https://plugin.capgo.app/stats</code> | |
255
+ | **`privateKey`** | <code>string</code> | Configure the private key for end to end live update encryption. Only available for Android and iOS. Deprecated in version 6.2.0 in favor of publicKey. Still supported for backwards compatibility. | <code>undefined</code> | |
256
+ | **`publicKey`** | <code>string</code> | Configure the public key for end to end live update encryption Version 2 Only available for Android and iOS. | <code>undefined</code> | 6.2.0 |
257
+ | **`version`** | <code>string</code> | Configure the current version of the app. This will be used for the first update request. If not set, the plugin will get the version from the native code. Only available for Android and iOS. | <code>undefined</code> | 4.17.48 |
258
+ | **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. Works well for apps less than 10MB and with uploads done using --partial flag. Zip or apps more than 10MB will be relatively slow for users to update. - false: Never do direct updates (use default behavior: download at start, set when backgrounded) - atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false - onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false - always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false - true: (deprecated) Same as "always" for backward compatibility Only available for Android and iOS. | <code>false</code> | 5.1.0 |
259
+ | **`autoSplashscreen`** | <code>boolean</code> | Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed. This removes the need to manually listen for appReady events and call SplashScreen.hide(). Only works when directUpdate is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires autoUpdate and directUpdate to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
260
+ | **`autoSplashscreenLoader`** | <code>boolean</code> | Display a native loading indicator on top of the splashscreen while automatic direct updates are running. Only takes effect when {@link autoSplashscreen} is enabled. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Only available for Android and iOS. | <code>false</code> | 7.19.0 |
261
+ | **`autoSplashscreenTimeout`** | <code>number</code> | Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates. If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed. Set to `0` (zero) to disable the timeout. When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch. Requires {@link autoSplashscreen} to be enabled. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | 7.19.0 |
262
+ | **`periodCheckDelay`** | <code>number</code> | Configure the delay period for period update check. the unit is in seconds. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
263
+ | **`localS3`** | <code>boolean</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
264
+ | **`localHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
265
+ | **`localWebHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
266
+ | **`localSupa`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
267
+ | **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
268
+ | **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
269
+ | **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
270
+ | **`allowModifyUrl`** | <code>boolean</code> | Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side. | <code>false</code> | 5.4.0 |
271
+ | **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
272
+ | **`allowManualBundleError`** | <code>boolean</code> | Allow marking bundles as errored from JavaScript while using manual update flows. When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`. | <code>false</code> | 7.20.0 |
273
+ | **`persistCustomId`** | <code>boolean</code> | Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts. Only available for Android and iOS. | <code>false (will be true by default in a future major release v8.x.x)</code> | 7.17.3 |
274
+ | **`persistModifyUrl`** | <code>boolean</code> | Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl}, {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts. Only available for Android and iOS. | <code>false</code> | 7.20.0 |
275
+ | **`defaultChannel`** | <code>string</code> | Set the default channel for the app in the config. Case sensitive. This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud. This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options | <code>undefined</code> | 5.5.0 |
276
+ | **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
277
+ | **`keepUrlPathAfterReload`** | <code>boolean</code> | Configure the plugin to keep the URL path after a reload. WARNING: When a reload is triggered, 'window.history' will be cleared. | <code>false</code> | 6.8.0 |
278
+ | **`disableJSLogging`** | <code>boolean</code> | Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done | <code>false</code> | 7.3.0 |
279
+ | **`shakeMenu`** | <code>boolean</code> | Enable shake gesture to show update menu for debugging/testing purposes | <code>false</code> | 7.5.0 |
267
280
 
268
281
  ### Examples
269
282
 
@@ -638,7 +651,7 @@ For the `date` kind, the value should be an iso8601 date string.
638
651
  For the `background` kind, the value should be a number in milliseconds.
639
652
  For the `nativeVersion` kind, the value should be the version number.
640
653
  For the `kill` kind, the value is not used.
641
- The function has unconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.
654
+ The function has inconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.
642
655
 
643
656
  | Param | Type | Description |
644
657
  | ------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
@@ -1201,7 +1214,7 @@ Set the App ID for the app (requires allowModifyAppId to be true in config)
1201
1214
 
1202
1215
  ##### DownloadOptions
1203
1216
 
1204
- This URL and versions are used to download the bundle from the server, If you use backend all information will be gived by the method getLatest.
1217
+ This URL and versions are used to download the bundle from the server, If you use backend all information will be given by the method getLatest.
1205
1218
  If you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.
1206
1219
 
1207
1220
  | Prop | Type | Description | Default | Since |
@@ -49,9 +49,9 @@ repositories {
49
49
 
50
50
 
51
51
  dependencies {
52
- def work_version = "2.10.5"
52
+ def work_version = "2.11.0"
53
53
  implementation "androidx.work:work-runtime:$work_version"
54
- implementation "com.google.android.gms:play-services-tasks:18.2.1"
54
+ implementation "com.google.android.gms:play-services-tasks:18.4.0"
55
55
  implementation "com.google.guava:guava:33.4.8-android"
56
56
  implementation fileTree(dir: 'libs', include: ['*.jar'])
57
57
  implementation project(':capacitor-android')
@@ -71,7 +71,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
71
71
  private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
72
72
  private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
73
73
 
74
- private final String pluginVersion = "6.25.3";
74
+ private final String pluginVersion = "6.25.5";
75
75
  private static final String DELAY_CONDITION_PREFERENCES = "";
76
76
 
77
77
  private SharedPreferences.Editor editor;
@@ -226,23 +226,31 @@ public class CapacitorUpdaterPlugin extends Plugin {
226
226
  // Handle directUpdate configuration - support string values and backward compatibility
227
227
  String directUpdateConfig = this.getConfig().getString("directUpdate", null);
228
228
  if (directUpdateConfig != null) {
229
- this.directUpdateMode = directUpdateConfig;
230
- this.implementation.directUpdate =
231
- directUpdateConfig.equals("always") || directUpdateConfig.equals("atInstall") || directUpdateConfig.equals("onLaunch");
232
- // Validate directUpdate value
233
- if (
234
- !directUpdateConfig.equals("false") &&
235
- !directUpdateConfig.equals("always") &&
236
- !directUpdateConfig.equals("atInstall") &&
237
- !directUpdateConfig.equals("onLaunch")
238
- ) {
239
- logger.error(
240
- "Invalid directUpdate value: \"" +
241
- directUpdateConfig +
242
- "\". Supported values are: false, \"always\", \"atInstall\", \"onLaunch\". Defaulting to false."
243
- );
244
- this.directUpdateMode = "false";
245
- this.implementation.directUpdate = false;
229
+ // Handle backward compatibility for boolean true
230
+ if (directUpdateConfig.equals("true")) {
231
+ this.directUpdateMode = "always";
232
+ this.implementation.directUpdate = true;
233
+ } else {
234
+ this.directUpdateMode = directUpdateConfig;
235
+ this.implementation.directUpdate =
236
+ directUpdateConfig.equals("always") ||
237
+ directUpdateConfig.equals("atInstall") ||
238
+ directUpdateConfig.equals("onLaunch");
239
+ // Validate directUpdate value
240
+ if (
241
+ !directUpdateConfig.equals("false") &&
242
+ !directUpdateConfig.equals("always") &&
243
+ !directUpdateConfig.equals("atInstall") &&
244
+ !directUpdateConfig.equals("onLaunch")
245
+ ) {
246
+ logger.error(
247
+ "Invalid directUpdate value: \"" +
248
+ directUpdateConfig +
249
+ "\". Supported values are: \"false\", \"true\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to \"false\"."
250
+ );
251
+ this.directUpdateMode = "false";
252
+ this.implementation.directUpdate = false;
253
+ }
246
254
  }
247
255
  } else {
248
256
  Boolean directUpdateBool = this.getConfig().getBoolean("directUpdate", false);
@@ -378,6 +386,10 @@ public class CapacitorUpdaterPlugin extends Plugin {
378
386
  this.cleanupObsoleteVersions();
379
387
  }
380
388
 
389
+ // Check for 'kill' delay condition on app launch
390
+ // This handles cases where the app was killed by the system (onDestroy is not reliable)
391
+ this.delayUpdateUtils.checkCancelDelay(DelayUpdateUtils.CancelDelaySource.KILLED);
392
+
381
393
  this.checkForUpdateAfterDelay();
382
394
  }
383
395
 
@@ -652,7 +664,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
652
664
  logger.error(
653
665
  "Invalid directUpdateMode: \"" +
654
666
  this.directUpdateMode +
655
- "\". Supported values are: \"false\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to false behavior."
667
+ "\". Supported values are: \"false\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to \"false\" behavior."
656
668
  );
657
669
  return false;
658
670
  }
@@ -1305,6 +1317,9 @@ public class CapacitorUpdaterPlugin extends Plugin {
1305
1317
  CapacitorUpdaterPlugin.this.implementation.getLatest(CapacitorUpdaterPlugin.this.updateUrl, channel, (res) -> {
1306
1318
  JSObject jsRes = mapToJSObject(res);
1307
1319
  if (jsRes.has("error")) {
1320
+ String error = jsRes.getString("error");
1321
+ String errorMessage = jsRes.has("message") ? jsRes.getString("message") : "server did not provide a message";
1322
+ logger.error("getLatest failed with error: " + error + ", message: " + errorMessage);
1308
1323
  call.reject(jsRes.getString("error"));
1309
1324
  return;
1310
1325
  } else if (jsRes.has("message")) {
@@ -1410,7 +1425,11 @@ public class CapacitorUpdaterPlugin extends Plugin {
1410
1425
  CapacitorUpdaterPlugin.this.implementation.getLatest(CapacitorUpdaterPlugin.this.updateUrl, null, (res) -> {
1411
1426
  JSObject jsRes = mapToJSObject(res);
1412
1427
  if (jsRes.has("error")) {
1413
- logger.error(Objects.requireNonNull(jsRes.getString("error")));
1428
+ String error = jsRes.getString("error");
1429
+ String errorMessage = jsRes.has("message")
1430
+ ? jsRes.getString("message")
1431
+ : "server did not provide a message";
1432
+ logger.error("getLatest failed with error: " + error + ", message: " + errorMessage);
1414
1433
  } else if (jsRes.has("version")) {
1415
1434
  String newVersion = jsRes.getString("version");
1416
1435
  String currentVersion = String.valueOf(CapacitorUpdaterPlugin.this.implementation.getCurrentBundle());
@@ -1614,49 +1633,20 @@ public class CapacitorUpdaterPlugin extends Plugin {
1614
1633
  // Handle network errors and other failures first
1615
1634
  if (jsRes.has("error")) {
1616
1635
  String error = jsRes.getString("error");
1617
- logger.error("getLatest failed with error: " + error);
1636
+ String errorMessage = jsRes.has("message") ? jsRes.getString("message") : "server did not provide a message";
1637
+ logger.error("getLatest failed with error: " + error + ", message: " + errorMessage);
1618
1638
  String latestVersion = jsRes.has("version") ? jsRes.getString("version") : current.getVersionName();
1619
- if ("response_error".equals(error)) {
1620
- CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif(
1621
- "Network error: " + error,
1622
- latestVersion,
1623
- current,
1624
- true,
1625
- plannedDirectUpdate
1626
- );
1627
- } else {
1628
- CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif(
1629
- error,
1630
- latestVersion,
1631
- current,
1632
- true,
1633
- plannedDirectUpdate,
1634
- "backend_refusal",
1635
- "backendRefused"
1636
- );
1637
- }
1639
+ CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif(
1640
+ errorMessage,
1641
+ latestVersion,
1642
+ current,
1643
+ true,
1644
+ plannedDirectUpdate
1645
+ );
1638
1646
  return;
1639
1647
  }
1640
1648
 
1641
1649
  try {
1642
- if (jsRes.has("message")) {
1643
- logger.info("API message: " + jsRes.get("message"));
1644
- if (jsRes.has("version") && (jsRes.has("breaking") || jsRes.has("major"))) {
1645
- CapacitorUpdaterPlugin.this.notifyBreakingEvents(jsRes.getString("version"));
1646
- }
1647
- String latestVersion = jsRes.has("version") ? jsRes.getString("version") : current.getVersionName();
1648
- CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif(
1649
- jsRes.getString("message"),
1650
- latestVersion,
1651
- current,
1652
- true,
1653
- plannedDirectUpdate,
1654
- "backend_refusal",
1655
- "backendRefused"
1656
- );
1657
- return;
1658
- }
1659
-
1660
1650
  final String latestVersionName = jsRes.getString("version");
1661
1651
 
1662
1652
  if ("builtin".equals(latestVersionName)) {
@@ -1831,10 +1821,10 @@ public class CapacitorUpdaterPlugin extends Plugin {
1831
1821
  logger.info("No need to update, " + current.getId() + " is the latest bundle.");
1832
1822
  CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif("No need to update", latestVersionName, current, false);
1833
1823
  }
1834
- } catch (final JSONException e) {
1835
- logger.error("error parsing JSON " + e.getMessage());
1824
+ } catch (final Exception e) {
1825
+ logger.error("error in update check " + e.getMessage());
1836
1826
  CapacitorUpdaterPlugin.this.endBackGroundTaskWithNotif(
1837
- "Error parsing JSON",
1827
+ "Error in update check",
1838
1828
  current.getVersionName(),
1839
1829
  current,
1840
1830
  true,
@@ -895,8 +895,12 @@ public class CapgoUpdater {
895
895
  // Check for server-side errors first
896
896
  if (jsonResponse.has("error")) {
897
897
  Map<String, Object> retError = new HashMap<>();
898
- retError.put("message", jsonResponse.getString("error"));
899
- retError.put("error", "server_error");
898
+ retError.put("error", jsonResponse.getString("error"));
899
+ if (jsonResponse.has("message")) {
900
+ retError.put("message", jsonResponse.getString("message"));
901
+ } else {
902
+ retError.put("message", "server did not provide a message");
903
+ }
900
904
  callback.callback(retError);
901
905
  return;
902
906
  }
@@ -1023,8 +1027,12 @@ public class CapgoUpdater {
1023
1027
  // Check for server-side errors first
1024
1028
  if (jsonResponse.has("error")) {
1025
1029
  Map<String, Object> retError = new HashMap<>();
1026
- retError.put("message", jsonResponse.getString("error"));
1027
- retError.put("error", "server_error");
1030
+ retError.put("error", jsonResponse.getString("error"));
1031
+ if (jsonResponse.has("message")) {
1032
+ retError.put("message", jsonResponse.getString("message"));
1033
+ } else {
1034
+ retError.put("message", "server did not provide a message");
1035
+ }
1028
1036
  callback.callback(retError);
1029
1037
  return;
1030
1038
  }
@@ -1176,8 +1184,12 @@ public class CapgoUpdater {
1176
1184
  // Check for server-side errors first
1177
1185
  if (jsonResponse.has("error")) {
1178
1186
  Map<String, Object> retError = new HashMap<>();
1179
- retError.put("message", jsonResponse.getString("error"));
1180
- retError.put("error", "server_error");
1187
+ retError.put("error", jsonResponse.getString("error"));
1188
+ if (jsonResponse.has("message")) {
1189
+ retError.put("message", jsonResponse.getString("message"));
1190
+ } else {
1191
+ retError.put("message", "server did not provide a message");
1192
+ }
1181
1193
  callback.callback(retError);
1182
1194
  return;
1183
1195
  }
@@ -1304,8 +1316,12 @@ public class CapgoUpdater {
1304
1316
  JSONObject json = new JSONObject(data);
1305
1317
  if (json.has("error")) {
1306
1318
  Map<String, Object> retError = new HashMap<>();
1307
- retError.put("message", json.getString("error"));
1308
- retError.put("error", "server_error");
1319
+ retError.put("error", json.getString("error"));
1320
+ if (json.has("message")) {
1321
+ retError.put("message", json.getString("message"));
1322
+ } else {
1323
+ retError.put("message", "server did not provide a message");
1324
+ }
1309
1325
  callback.callback(retError);
1310
1326
  return;
1311
1327
  }
@@ -142,7 +142,7 @@ public class CryptoCipherV2 {
142
142
 
143
143
  public static void decryptFile(final File file, final String publicKey, final String ivSessionKey) throws IOException {
144
144
  if (publicKey.isEmpty() || ivSessionKey == null || ivSessionKey.isEmpty() || ivSessionKey.split(":").length != 2) {
145
- logger.info("Encryption not set, no public key or seesion, ignored");
145
+ logger.info("Encryption not set, no public key or session, ignored");
146
146
  return;
147
147
  }
148
148
  if (!publicKey.startsWith("-----BEGIN RSA PUBLIC KEY-----")) {
package/dist/docs.json CHANGED
@@ -431,7 +431,7 @@
431
431
  "text": "4.3.0"
432
432
  }
433
433
  ],
434
- "docs": "Sets a {@link DelayCondition} array containing conditions that the Plugin will use to delay the update.\nAfter all conditions are met, the update process will run start again as usual, so update will be installed after a backgrounding or killing the app.\nFor the `date` kind, the value should be an iso8601 date string.\nFor the `background` kind, the value should be a number in milliseconds.\nFor the `nativeVersion` kind, the value should be the version number.\nFor the `kill` kind, the value is not used.\nThe function has unconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.",
434
+ "docs": "Sets a {@link DelayCondition} array containing conditions that the Plugin will use to delay the update.\nAfter all conditions are met, the update process will run start again as usual, so update will be installed after a backgrounding or killing the app.\nFor the `date` kind, the value should be an iso8601 date string.\nFor the `background` kind, the value should be a number in milliseconds.\nFor the `nativeVersion` kind, the value should be the version number.\nFor the `kill` kind, the value is not used.\nThe function has inconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.",
435
435
  "complexTypes": [
436
436
  "MultiDelayConditions"
437
437
  ],
@@ -1343,7 +1343,7 @@
1343
1343
  {
1344
1344
  "name": "DownloadOptions",
1345
1345
  "slug": "downloadoptions",
1346
- "docs": "This URL and versions are used to download the bundle from the server, If you use backend all information will be gived by the method getLatest.\nIf you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.",
1346
+ "docs": "This URL and versions are used to download the bundle from the server, If you use backend all information will be given by the method getLatest.\nIf you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.",
1347
1347
  "tags": [],
1348
1348
  "methods": [],
1349
1349
  "properties": [
@@ -2575,7 +2575,7 @@
2575
2575
  "name": "since"
2576
2576
  }
2577
2577
  ],
2578
- "docs": "Configure when the plugin should direct install updates. Only for autoUpdate mode.\nWorks well for apps less than 10MB and with uploads done using --partial flag.\nZip or apps more than 10MB will be relatively slow for users to update.\n- false: Never do direct updates (default behavior)\n- atInstall: Direct update only when app is installed/updated from store, otherwise use normal background update\n- always: Always do direct updates immediately when available (including when returning from background)\n- onLaunch: Direct update only on app launch (first foreground after app starts), not when returning from background\n- true: (deprecated) Same as \"always\" for backward compatibility\n\nOnly available for Android and iOS.",
2578
+ "docs": "Configure when the plugin should direct install updates. Only for autoUpdate mode.\nWorks well for apps less than 10MB and with uploads done using --partial flag.\nZip or apps more than 10MB will be relatively slow for users to update.\n- false: Never do direct updates (use default behavior: download at start, set when backgrounded)\n- atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false\n- onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false\n- always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false\n- true: (deprecated) Same as \"always\" for backward compatibility\n\nOnly available for Android and iOS.",
2579
2579
  "complexTypes": [],
2580
2580
  "type": "boolean | 'always' | 'atInstall' | 'onLaunch' | undefined"
2581
2581
  },
@@ -119,10 +119,10 @@ declare module '@capacitor/cli' {
119
119
  * Configure when the plugin should direct install updates. Only for autoUpdate mode.
120
120
  * Works well for apps less than 10MB and with uploads done using --partial flag.
121
121
  * Zip or apps more than 10MB will be relatively slow for users to update.
122
- * - false: Never do direct updates (default behavior)
123
- * - atInstall: Direct update only when app is installed/updated from store, otherwise use normal background update
124
- * - always: Always do direct updates immediately when available (including when returning from background)
125
- * - onLaunch: Direct update only on app launch (first foreground after app starts), not when returning from background
122
+ * - false: Never do direct updates (use default behavior: download at start, set when backgrounded)
123
+ * - atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false
124
+ * - onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false
125
+ * - always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false
126
126
  * - true: (deprecated) Same as "always" for backward compatibility
127
127
  *
128
128
  * Only available for Android and iOS.
@@ -435,7 +435,7 @@ export interface CapacitorUpdaterPlugin {
435
435
  * For the `background` kind, the value should be a number in milliseconds.
436
436
  * For the `nativeVersion` kind, the value should be the version number.
437
437
  * For the `kill` kind, the value is not used.
438
- * The function has unconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.
438
+ * The function has inconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.
439
439
  *
440
440
  * @example
441
441
  * // Delay the update after the user kills the app or after a background of 300000 ms (5 minutes)
@@ -907,7 +907,7 @@ export interface ChannelUrl {
907
907
  url: string;
908
908
  }
909
909
  /**
910
- * This URL and versions are used to download the bundle from the server, If you use backend all information will be gived by the method getLatest.
910
+ * This URL and versions are used to download the bundle from the server, If you use backend all information will be given by the method getLatest.
911
911
  * If you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.
912
912
  */
913
913
  export interface DownloadOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n\n/// <reference types=\"@capacitor/cli\" />\n\nimport type { PluginListenerHandle } from '@capacitor/core';\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n /**\n * CapacitorUpdater can be configured with these options:\n */\n CapacitorUpdater?: {\n /**\n * Configure the number of milliseconds the native plugin should wait before considering an update 'failed'.\n *\n * Only available for Android and iOS.\n *\n * @default 10000 // (10 seconds)\n * @example 1000 // (1 second)\n */\n appReadyTimeout?: number;\n /**\n * Configure the number of seconds the native plugin should wait before considering API timeout.\n *\n * Only available for Android and iOS.\n *\n * @default 20 // (20 second)\n * @example 10 // (10 second)\n */\n responseTimeout?: number;\n /**\n * Configure whether the plugin should use automatically delete failed bundles.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoDeleteFailed?: boolean;\n\n /**\n * Configure whether the plugin should use automatically delete previous bundles after a successful update.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoDeletePrevious?: boolean;\n\n /**\n * Configure whether the plugin should use Auto Update via an update server.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoUpdate?: boolean;\n\n /**\n * Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n resetWhenUpdate?: boolean;\n\n /**\n * Configure the URL / endpoint to which update checks are sent.\n *\n * Only available for Android and iOS.\n *\n * @default https://plugin.capgo.app/updates\n * @example https://example.com/api/auto_update\n */\n updateUrl?: string;\n\n /**\n * Configure the URL / endpoint for channel operations.\n *\n * Only available for Android and iOS.\n *\n * @default https://plugin.capgo.app/channel_self\n * @example https://example.com/api/channel\n */\n channelUrl?: string;\n\n /**\n * Configure the URL / endpoint to which update statistics are sent.\n *\n * Only available for Android and iOS. Set to \"\" to disable stats reporting.\n *\n * @default https://plugin.capgo.app/stats\n * @example https://example.com/api/stats\n */\n statsUrl?: string;\n /**\n * Configure the private key for end to end live update encryption.\n *\n * Only available for Android and iOS. Deprecated in version 6.2.0 in favor of publicKey.\n * Still supported for backwards compatibility.\n *\n * @default undefined\n * @deprecated Use publicKey instead\n */\n privateKey?: string;\n /**\n * Configure the public key for end to end live update encryption Version 2\n *\n * Only available for Android and iOS.\n *\n * @default undefined\n * @since 6.2.0\n */\n publicKey?: string;\n\n /**\n * Configure the current version of the app. This will be used for the first update request.\n * If not set, the plugin will get the version from the native code.\n *\n * Only available for Android and iOS.\n *\n * @default undefined\n * @since 4.17.48\n */\n version?: string;\n /**\n * Configure when the plugin should direct install updates. Only for autoUpdate mode.\n * Works well for apps less than 10MB and with uploads done using --partial flag.\n * Zip or apps more than 10MB will be relatively slow for users to update.\n * - false: Never do direct updates (default behavior)\n * - atInstall: Direct update only when app is installed/updated from store, otherwise use normal background update\n * - always: Always do direct updates immediately when available (including when returning from background)\n * - onLaunch: Direct update only on app launch (first foreground after app starts), not when returning from background\n * - true: (deprecated) Same as \"always\" for backward compatibility\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 5.1.0\n */\n directUpdate?: boolean | 'atInstall' | 'always' | 'onLaunch';\n\n /**\n * Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed.\n * This removes the need to manually listen for appReady events and call SplashScreen.hide().\n * Only works when directUpdate is set to \"atInstall\", \"always\", \"onLaunch\", or true.\n * Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false.\n * Requires autoUpdate and directUpdate to be enabled.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.6.0\n */\n autoSplashscreen?: boolean;\n\n /**\n * Display a native loading indicator on top of the splashscreen while automatic direct updates are running.\n * Only takes effect when {@link autoSplashscreen} is enabled.\n * Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.19.0\n */\n autoSplashscreenLoader?: boolean;\n\n /**\n * Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates.\n * If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed.\n * Set to `0` (zero) to disable the timeout.\n * When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch.\n * Requires {@link autoSplashscreen} to be enabled.\n *\n * Only available for Android and iOS.\n *\n * @default 10000 // (10 seconds)\n * @since 7.19.0\n */\n autoSplashscreenTimeout?: number;\n\n /**\n * Configure the delay period for period update check. the unit is in seconds.\n *\n * Only available for Android and iOS.\n * Cannot be less than 600 seconds (10 minutes).\n *\n * @default 0 (disabled)\n * @example 3600 (1 hour)\n * @example 86400 (24 hours)\n */\n periodCheckDelay?: number;\n\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localS3?: boolean;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localHost?: string;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localWebHost?: string;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localSupa?: string;\n /**\n * Configure the CLI to use a local server for testing.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localSupaAnon?: string;\n /**\n * Configure the CLI to use a local api for testing.\n *\n *\n * @default undefined\n * @since 6.3.3\n */\n localApi?: string;\n /**\n * Configure the CLI to use a local file api for testing.\n *\n *\n * @default undefined\n * @since 6.3.3\n */\n localApiFiles?: string;\n /**\n * Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side.\n *\n *\n * @default false\n * @since 5.4.0\n */\n allowModifyUrl?: boolean;\n\n /**\n * Allow the plugin to modify the appId dynamically from the JavaScript side.\n *\n *\n * @default false\n * @since 7.14.0\n */\n allowModifyAppId?: boolean;\n\n /**\n * Allow marking bundles as errored from JavaScript while using manual update flows.\n * When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`.\n *\n * @default false\n * @since 7.20.0\n */\n allowManualBundleError?: boolean;\n\n /**\n * Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts.\n *\n * Only available for Android and iOS.\n *\n * @default false (will be true by default in a future major release v8.x.x)\n * @since 7.17.3\n */\n persistCustomId?: boolean;\n\n /**\n * Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl},\n * {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.20.0\n */\n persistModifyUrl?: boolean;\n\n /**\n * Set the default channel for the app in the config. Case sensitive.\n * This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud.\n * This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options\n *\n *\n * @default undefined\n * @since 5.5.0\n */\n defaultChannel?: string;\n /**\n * Configure the app id for the app in the config.\n *\n * @default undefined\n * @since 6.0.0\n */\n appId?: string;\n\n /**\n * Configure the plugin to keep the URL path after a reload.\n * WARNING: When a reload is triggered, 'window.history' will be cleared.\n *\n * @default false\n * @since 6.8.0\n */\n keepUrlPathAfterReload?: boolean;\n /**\n * Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done\n *\n * @default false\n * @since 7.3.0\n */\n disableJSLogging?: boolean;\n /**\n * Enable shake gesture to show update menu for debugging/testing purposes\n *\n * @default false\n * @since 7.5.0\n */\n shakeMenu?: boolean;\n };\n }\n}\n\nexport interface CapacitorUpdaterPlugin {\n /**\n * Notify Capacitor Updater that the current bundle is working (a rollback will occur if this method is not called on every app launch)\n * By default this method should be called in the first 10 sec after app launch, otherwise a rollback will occur.\n * Change this behaviour with {@link appReadyTimeout}\n *\n * @returns {Promise<AppReadyResult>} an Promise resolved directly\n * @throws {Error}\n */\n notifyAppReady(): Promise<AppReadyResult>;\n\n /**\n * Set the updateUrl for the app, this will be used to check for updates.\n *\n * @param options contains the URL to use for checking for updates.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setUpdateUrl(options: UpdateUrl): Promise<void>;\n\n /**\n * Set the statsUrl for the app, this will be used to send statistics. Passing an empty string will disable statistics gathering.\n *\n * @param options contains the URL to use for sending statistics.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setStatsUrl(options: StatsUrl): Promise<void>;\n\n /**\n * Set the channelUrl for the app, this will be used to set the channel.\n *\n * @param options contains the URL to use for setting the channel.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setChannelUrl(options: ChannelUrl): Promise<void>;\n\n /**\n * Download a new bundle from the provided URL, it should be a zip file, with files inside or with a unique id inside with all your files\n *\n * @example const bundle = await CapacitorUpdater.download({ url: `https://example.com/versions/${version}/dist.zip`, version });\n * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the specified bundle.\n * @param options The {@link DownloadOptions} for downloading a new bundle zip.\n */\n download(options: DownloadOptions): Promise<BundleInfo>;\n\n /**\n * Set the next bundle to be used when the app is reloaded.\n *\n * @param options Contains the ID of the next Bundle to set on next app launch. {@link BundleInfo.id}\n * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the specified bundle id.\n * @throws {Error} When there is no index.html file inside the bundle folder.\n */\n next(options: BundleId): Promise<BundleInfo>;\n\n /**\n * Set the current bundle and immediately reloads the app.\n *\n * @param options A {@link BundleId} object containing the new bundle id to set as current.\n * @returns {Promise<void>}\n * @throws {Error} When there are is no index.html file inside the bundle folder.\n */\n set(options: BundleId): Promise<void>;\n\n /**\n * Deletes the specified bundle from the native app storage. Use with {@link list} to get the stored Bundle IDs.\n *\n * @param options A {@link BundleId} object containing the ID of a bundle to delete (note, this is the bundle id, NOT the version name)\n * @returns {Promise<void>} When the bundle is deleted\n * @throws {Error}\n */\n delete(options: BundleId): Promise<void>;\n\n /**\n * Mark an installed bundle as errored. Only available when {@link PluginsConfig.CapacitorUpdater.allowManualBundleError} is true.\n *\n * @param options A {@link BundleId} object containing the bundle id to mark as errored.\n * @returns {Promise<BundleInfo>} The updated {@link BundleInfo} for the bundle.\n * @throws {Error} When the bundle does not exist or the feature is disabled.\n * @since 7.20.0\n */\n setBundleError(options: BundleId): Promise<BundleInfo>;\n\n /**\n * Get all locally downloaded bundles in your app\n *\n * @returns {Promise<BundleListResult>} A Promise containing the {@link BundleListResult.bundles}\n * @param options The {@link ListOptions} for listing bundles\n * @throws {Error}\n */\n list(options?: ListOptions): Promise<BundleListResult>;\n\n /**\n * Reset the app to the `builtin` bundle (the one sent to Apple App Store / Google Play Store ) or the last successfully loaded bundle.\n *\n * @param options Containing {@link ResetOptions.toLastSuccessful}, `true` resets to the builtin bundle and `false` will reset to the last successfully loaded bundle.\n * @returns {Promise<void>}\n * @throws {Error}\n */\n reset(options?: ResetOptions): Promise<void>;\n\n /**\n * Get the current bundle, if none are set it returns `builtin`. currentNative is the original bundle installed on the device\n *\n * @returns {Promise<CurrentBundleResult>} A Promise evaluating to the {@link CurrentBundleResult}\n * @throws {Error}\n */\n current(): Promise<CurrentBundleResult>;\n\n /**\n * Reload the view\n *\n * @returns {Promise<void>} A Promise which is resolved when the view is reloaded\n * @throws {Error}\n */\n reload(): Promise<void>;\n\n /**\n * Sets a {@link DelayCondition} array containing conditions that the Plugin will use to delay the update.\n * After all conditions are met, the update process will run start again as usual, so update will be installed after a backgrounding or killing the app.\n * For the `date` kind, the value should be an iso8601 date string.\n * For the `background` kind, the value should be a number in milliseconds.\n * For the `nativeVersion` kind, the value should be the version number.\n * For the `kill` kind, the value is not used.\n * The function has unconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.\n *\n * @example\n * // Delay the update after the user kills the app or after a background of 300000 ms (5 minutes)\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'kill' }, { kind: 'background', value: '300000' }] })\n * @example\n * // Delay the update after the specific iso8601 date is expired\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'date', value: '2022-09-14T06:14:11.920Z' }] })\n * @example\n * // Delay the update after the first background (default behaviour without setting delay)\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'background' }] })\n * @param options Containing the {@link MultiDelayConditions} array of conditions to set\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 4.3.0\n */\n setMultiDelay(options: MultiDelayConditions): Promise<void>;\n\n /**\n * Cancels a {@link DelayCondition} to process an update immediately.\n *\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 4.0.0\n */\n cancelDelay(): Promise<void>;\n\n /**\n * Get Latest bundle available from update Url\n *\n * @returns {Promise<LatestVersion>} A Promise resolved when url is loaded\n * @throws {Error}\n * @since 4.0.0\n */\n getLatest(options?: GetLatestOptions): Promise<LatestVersion>;\n\n /**\n * Sets the channel for this device. The channel has to allow for self assignment for this to work.\n * Do not use this method to set the channel at boot.\n * This method is to set the channel after the app is ready, and user interacted.\n * If you want to set the channel at boot, use the {@link PluginsConfig} to set the default channel.\n * This methods send to Capgo backend a request to link the device ID to the channel. Capgo can accept or refuse depending of the setting of your channel.\n *\n *\n *\n * @param options Is the {@link SetChannelOptions} channel to set\n * @returns {Promise<ChannelRes>} A Promise which is resolved when the new channel is set\n * @throws {Error}\n * @since 4.7.0\n */\n setChannel(options: SetChannelOptions): Promise<ChannelRes>;\n\n /**\n * Unset the channel for this device. The device will then return to the default channel\n *\n * @returns {Promise<ChannelRes>} A Promise resolved when channel is set\n * @throws {Error}\n * @since 4.7.0\n */\n unsetChannel(options: UnsetChannelOptions): Promise<void>;\n\n /**\n * Get the channel for this device\n *\n * @returns {Promise<ChannelRes>} A Promise that resolves with the channel info\n * @throws {Error}\n * @since 4.8.0\n */\n getChannel(): Promise<GetChannelRes>;\n\n /**\n * List all channels available for this device that allow self-assignment\n *\n * @returns {Promise<ListChannelsResult>} A Promise that resolves with the available channels\n * @throws {Error}\n * @since 7.5.0\n */\n listChannels(): Promise<ListChannelsResult>;\n\n /**\n * Set a custom ID for this device\n *\n * When {@link PluginsConfig.CapacitorUpdater.persistCustomId} is true, the value will be stored natively and restored on the next app launch.\n * Pass an empty string to remove any previously stored customId.\n *\n * @param options is the {@link SetCustomIdOptions} customId to set\n * @returns {Promise<void>} an Promise resolved instantly\n * @throws {Error}\n * @since 4.9.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n\n /**\n * Get the native app version or the builtin version if set in config\n *\n * @returns {Promise<BuiltinVersion>} A Promise with version for this device\n * @since 5.2.0\n */\n getBuiltinVersion(): Promise<BuiltinVersion>;\n\n /**\n * Get unique ID used to identify device (sent to auto update server).\n *\n * This ID is privacy-friendly and follows Apple and Google best practices:\n * - Generated as a UUID and stored securely\n * - Android: Uses Android Keystore (persists across reinstalls on API 23+)\n * - iOS: Uses Keychain with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly (persists across reinstalls)\n * - Data stays on device (not synced to cloud on iOS)\n * - Can be cleared by user via system settings (Android) or keychain access (iOS)\n *\n * The device ID now persists between app reinstalls to maintain consistent device identity.\n *\n * @returns {Promise<DeviceId>} A Promise with id for this device\n * @throws {Error}\n */\n getDeviceId(): Promise<DeviceId>;\n\n /**\n * Get the native Capacitor Updater plugin version (sent to auto update server)\n *\n * @returns {Promise<PluginVersion>} A Promise with Plugin version\n * @throws {Error}\n */\n getPluginVersion(): Promise<PluginVersion>;\n\n /**\n * Get the state of auto update config.\n *\n * @returns {Promise<AutoUpdateEnabled>} The status for auto update. Evaluates to `false` in manual mode.\n * @throws {Error}\n */\n isAutoUpdateEnabled(): Promise<AutoUpdateEnabled>;\n\n /**\n * Remove all listeners for this plugin.\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Listen for bundle download event in the App. Fires once a download has started, during downloading and when finished.\n * This will return you all download percent during the download\n *\n * @since 2.0.11\n */\n addListener(eventName: 'download', listenerFunc: (state: DownloadEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for no need to update event, useful when you want force check every time the app is launched\n *\n * @since 4.0.0\n */\n addListener(eventName: 'noNeedUpdate', listenerFunc: (state: NoNeedEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for available update event, useful when you want to force check every time the app is launched\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'updateAvailable',\n listenerFunc: (state: UpdateAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for downloadComplete events.\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'downloadComplete',\n listenerFunc: (state: DownloadCompleteEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for breaking update events when the backend flags an update as incompatible with the current app.\n * Emits the same payload as the legacy `majorAvailable` listener.\n *\n * @since 7.22.0\n */\n addListener(\n eventName: 'breakingAvailable',\n listenerFunc: (state: BreakingAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for Major update event in the App, let you know when major update is blocked by setting disableAutoUpdateBreaking\n *\n * @deprecated Deprecated alias for {@link addListener} with `breakingAvailable`. Emits the same payload. will be removed in v8\n * @since 2.3.0\n */\n addListener(\n eventName: 'majorAvailable',\n listenerFunc: (state: MajorAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for update fail event in the App, let you know when update has fail to install at next app start\n *\n * @since 2.3.0\n */\n addListener(\n eventName: 'updateFailed',\n listenerFunc: (state: UpdateFailedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for download fail event in the App, let you know when a bundle download has failed\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'downloadFailed',\n listenerFunc: (state: DownloadFailedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for reload event in the App, let you know when reload has happened\n *\n * @since 4.3.0\n */\n addListener(eventName: 'appReloaded', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for app ready event in the App, let you know when app is ready to use, this event is retain till consumed.\n *\n * @since 5.1.0\n */\n addListener(eventName: 'appReady', listenerFunc: (state: AppReadyEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Get if auto update is available (not disabled by serverUrl).\n *\n * @returns {Promise<AutoUpdateAvailable>} The availability status for auto update. Evaluates to `false` when serverUrl is set.\n * @throws {Error}\n */\n isAutoUpdateAvailable(): Promise<AutoUpdateAvailable>;\n\n /**\n * Get the next bundle that will be used when the app reloads.\n * Returns null if no next bundle is set.\n *\n * @returns {Promise<BundleInfo | null>} A Promise that resolves with the next bundle information or null\n * @throws {Error}\n * @since 6.8.0\n */\n getNextBundle(): Promise<BundleInfo | null>;\n\n /**\n * Get the most recent update that failed to install, if any. The stored value is cleared after it is retrieved once.\n *\n * @returns {Promise<UpdateFailedEvent | null>} The last failed update or null when no failure has been recorded. Value is cleared after it is returned once.\n * @throws {Error}\n * @since 7.22.0\n */\n getFailedUpdate(): Promise<UpdateFailedEvent | null>;\n\n /**\n * Enable or disable the shake menu for debugging/testing purposes\n *\n * @param options Contains enabled boolean to enable or disable shake menu\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 7.5.0\n */\n setShakeMenu(options: SetShakeMenuOptions): Promise<void>;\n\n /**\n * Get the current state of the shake menu\n *\n * @returns {Promise<ShakeMenuEnabled>} The current state of shake menu\n * @throws {Error}\n * @since 7.5.0\n */\n isShakeMenuEnabled(): Promise<ShakeMenuEnabled>;\n\n /**\n * Get the configured App ID\n *\n * @returns {Promise<GetAppIdRes>} The current App ID\n * @throws {Error}\n * @since 7.14.0\n */\n getAppId(): Promise<GetAppIdRes>;\n\n /**\n * Set the App ID for the app (requires allowModifyAppId to be true in config)\n *\n * @param options The new App ID to set\n * @returns {Promise<void>}\n * @throws {Error} If allowModifyAppId is false or if the operation fails\n * @since 7.14.0\n */\n setAppId(options: SetAppIdOptions): Promise<void>;\n}\n\n/**\n * pending: The bundle is pending to be **SET** as the next bundle.\n * downloading: The bundle is being downloaded.\n * success: The bundle has been downloaded and is ready to be **SET** as the next bundle.\n * error: The bundle has failed to download.\n */\nexport type BundleStatus = 'success' | 'error' | 'pending' | 'downloading';\n\nexport type DelayUntilNext = 'background' | 'kill' | 'nativeVersion' | 'date';\n\nexport interface NoNeedEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface UpdateAvailableEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface ChannelRes {\n /**\n * Current status of set channel\n *\n * @since 4.7.0\n */\n status: string;\n error?: string;\n message?: string;\n}\n\nexport interface GetChannelRes {\n /**\n * Current status of get channel\n *\n * @since 4.8.0\n */\n channel?: string;\n error?: string;\n message?: string;\n status?: string;\n allowSet?: boolean;\n}\n\nexport interface ChannelInfo {\n /**\n * The channel ID\n *\n * @since 7.5.0\n */\n id: string;\n /**\n * The channel name\n *\n * @since 7.5.0\n */\n name: string;\n /**\n * Whether this is a public channel\n *\n * @since 7.5.0\n */\n public: boolean;\n /**\n * Whether devices can self-assign to this channel\n *\n * @since 7.5.0\n */\n allow_self_set: boolean;\n}\n\nexport interface ListChannelsResult {\n /**\n * List of available channels\n *\n * @since 7.5.0\n */\n channels: ChannelInfo[];\n}\n\nexport interface DownloadEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n percent: number;\n bundle: BundleInfo;\n}\n\nexport interface MajorAvailableEvent {\n /**\n * Emit when a breaking update is available.\n *\n * @deprecated Deprecated alias for {@link BreakingAvailableEvent}. Receives the same payload.\n * @since 4.0.0\n */\n version: string;\n}\n\n/**\n * Payload emitted by {@link CapacitorUpdaterPlugin.addListener} with `breakingAvailable`.\n *\n * @since 7.22.0\n */\nexport type BreakingAvailableEvent = MajorAvailableEvent;\n\nexport interface DownloadFailedEvent {\n /**\n * Emit when a download fail.\n *\n * @since 4.0.0\n */\n version: string;\n}\n\nexport interface DownloadCompleteEvent {\n /**\n * Emit when a new update is available.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface UpdateFailedEvent {\n /**\n * Emit when a update failed to install.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface AppReadyEvent {\n /**\n * Emitted when the app is ready to use.\n *\n * @since 5.2.0\n */\n bundle: BundleInfo;\n status: string;\n}\n\nexport interface ManifestEntry {\n file_name: string | null;\n file_hash: string | null;\n download_url: string | null;\n}\n\nexport interface LatestVersion {\n /**\n * Result of getLatest method\n *\n * @since 4.0.0\n */\n version: string;\n /**\n * @since 6\n */\n checksum?: string;\n /**\n * Indicates whether the update was flagged as breaking by the backend.\n *\n * @since 7.22.0\n */\n breaking?: boolean;\n /**\n * @deprecated Use {@link LatestVersion.breaking} instead.\n */\n major?: boolean;\n message?: string;\n sessionKey?: string;\n error?: string;\n old?: string;\n url?: string;\n /**\n * @since 6.1\n */\n manifest?: ManifestEntry[];\n}\n\nexport interface BundleInfo {\n id: string;\n version: string;\n downloaded: string;\n checksum: string;\n status: BundleStatus;\n}\n\nexport interface SetChannelOptions {\n channel: string;\n triggerAutoUpdate?: boolean;\n}\n\nexport interface UnsetChannelOptions {\n triggerAutoUpdate?: boolean;\n}\n\nexport interface SetCustomIdOptions {\n /**\n * Custom identifier to associate with the device. Use an empty string to clear any saved value.\n */\n customId: string;\n}\n\nexport interface DelayCondition {\n /**\n * Set up delay conditions in setMultiDelay\n * @param value is useless for @param kind \"kill\", optional for \"background\" (default value: \"0\") and required for \"nativeVersion\" and \"date\"\n */\n kind: DelayUntilNext;\n value?: string;\n}\n\nexport interface GetLatestOptions {\n /**\n * The channel to get the latest version for\n * The channel must allow 'self_assign' for this to work\n * @since 6.8.0\n * @default undefined\n */\n channel?: string;\n}\n\nexport interface AppReadyResult {\n bundle: BundleInfo;\n}\n\nexport interface UpdateUrl {\n url: string;\n}\n\nexport interface StatsUrl {\n url: string;\n}\n\nexport interface ChannelUrl {\n url: string;\n}\n\n/**\n * This URL and versions are used to download the bundle from the server, If you use backend all information will be gived by the method getLatest.\n * If you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.\n */\nexport interface DownloadOptions {\n /**\n * The URL of the bundle zip file (e.g: dist.zip) to be downloaded. (This can be any URL. E.g: Amazon S3, a GitHub tag, any other place you've hosted your bundle.)\n */\n url: string;\n /**\n * The version code/name of this bundle/version\n */\n version: string;\n /**\n * The session key for the update, when the bundle is encrypted with a session key\n * @since 4.0.0\n * @default undefined\n */\n sessionKey?: string;\n /**\n * The checksum for the update, it should be in sha256 and encrypted with private key if the bundle is encrypted\n * @since 4.0.0\n * @default undefined\n */\n checksum?: string;\n /**\n * The manifest for multi-file downloads\n * @since 6.1.0\n * @default undefined\n */\n manifest?: ManifestEntry[];\n}\n\nexport interface BundleId {\n id: string;\n}\n\nexport interface BundleListResult {\n bundles: BundleInfo[];\n}\n\nexport interface ResetOptions {\n toLastSuccessful: boolean;\n}\n\nexport interface ListOptions {\n /**\n * Whether to return the raw bundle list or the manifest. If true, the list will attempt to read the internal database instead of files on disk.\n * @since 6.14.0\n * @default false\n */\n raw?: boolean;\n}\n\nexport interface CurrentBundleResult {\n bundle: BundleInfo;\n native: string;\n}\n\nexport interface MultiDelayConditions {\n delayConditions: DelayCondition[];\n}\n\nexport interface BuiltinVersion {\n version: string;\n}\n\nexport interface DeviceId {\n deviceId: string;\n}\n\nexport interface PluginVersion {\n version: string;\n}\n\nexport interface AutoUpdateEnabled {\n enabled: boolean;\n}\n\nexport interface AutoUpdateAvailable {\n available: boolean;\n}\n\nexport interface SetShakeMenuOptions {\n enabled: boolean;\n}\n\nexport interface ShakeMenuEnabled {\n enabled: boolean;\n}\n\nexport interface GetAppIdRes {\n appId: string;\n}\n\nexport interface SetAppIdOptions {\n appId: string;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n\n/// <reference types=\"@capacitor/cli\" />\n\nimport type { PluginListenerHandle } from '@capacitor/core';\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n /**\n * CapacitorUpdater can be configured with these options:\n */\n CapacitorUpdater?: {\n /**\n * Configure the number of milliseconds the native plugin should wait before considering an update 'failed'.\n *\n * Only available for Android and iOS.\n *\n * @default 10000 // (10 seconds)\n * @example 1000 // (1 second)\n */\n appReadyTimeout?: number;\n /**\n * Configure the number of seconds the native plugin should wait before considering API timeout.\n *\n * Only available for Android and iOS.\n *\n * @default 20 // (20 second)\n * @example 10 // (10 second)\n */\n responseTimeout?: number;\n /**\n * Configure whether the plugin should use automatically delete failed bundles.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoDeleteFailed?: boolean;\n\n /**\n * Configure whether the plugin should use automatically delete previous bundles after a successful update.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoDeletePrevious?: boolean;\n\n /**\n * Configure whether the plugin should use Auto Update via an update server.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n autoUpdate?: boolean;\n\n /**\n * Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device.\n *\n * Only available for Android and iOS.\n *\n * @default true\n * @example false\n */\n resetWhenUpdate?: boolean;\n\n /**\n * Configure the URL / endpoint to which update checks are sent.\n *\n * Only available for Android and iOS.\n *\n * @default https://plugin.capgo.app/updates\n * @example https://example.com/api/auto_update\n */\n updateUrl?: string;\n\n /**\n * Configure the URL / endpoint for channel operations.\n *\n * Only available for Android and iOS.\n *\n * @default https://plugin.capgo.app/channel_self\n * @example https://example.com/api/channel\n */\n channelUrl?: string;\n\n /**\n * Configure the URL / endpoint to which update statistics are sent.\n *\n * Only available for Android and iOS. Set to \"\" to disable stats reporting.\n *\n * @default https://plugin.capgo.app/stats\n * @example https://example.com/api/stats\n */\n statsUrl?: string;\n /**\n * Configure the private key for end to end live update encryption.\n *\n * Only available for Android and iOS. Deprecated in version 6.2.0 in favor of publicKey.\n * Still supported for backwards compatibility.\n *\n * @default undefined\n * @deprecated Use publicKey instead\n */\n privateKey?: string;\n /**\n * Configure the public key for end to end live update encryption Version 2\n *\n * Only available for Android and iOS.\n *\n * @default undefined\n * @since 6.2.0\n */\n publicKey?: string;\n\n /**\n * Configure the current version of the app. This will be used for the first update request.\n * If not set, the plugin will get the version from the native code.\n *\n * Only available for Android and iOS.\n *\n * @default undefined\n * @since 4.17.48\n */\n version?: string;\n /**\n * Configure when the plugin should direct install updates. Only for autoUpdate mode.\n * Works well for apps less than 10MB and with uploads done using --partial flag.\n * Zip or apps more than 10MB will be relatively slow for users to update.\n * - false: Never do direct updates (use default behavior: download at start, set when backgrounded)\n * - atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false\n * - onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false\n * - always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false\n * - true: (deprecated) Same as \"always\" for backward compatibility\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 5.1.0\n */\n directUpdate?: boolean | 'atInstall' | 'always' | 'onLaunch';\n\n /**\n * Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed.\n * This removes the need to manually listen for appReady events and call SplashScreen.hide().\n * Only works when directUpdate is set to \"atInstall\", \"always\", \"onLaunch\", or true.\n * Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false.\n * Requires autoUpdate and directUpdate to be enabled.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.6.0\n */\n autoSplashscreen?: boolean;\n\n /**\n * Display a native loading indicator on top of the splashscreen while automatic direct updates are running.\n * Only takes effect when {@link autoSplashscreen} is enabled.\n * Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.19.0\n */\n autoSplashscreenLoader?: boolean;\n\n /**\n * Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates.\n * If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed.\n * Set to `0` (zero) to disable the timeout.\n * When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch.\n * Requires {@link autoSplashscreen} to be enabled.\n *\n * Only available for Android and iOS.\n *\n * @default 10000 // (10 seconds)\n * @since 7.19.0\n */\n autoSplashscreenTimeout?: number;\n\n /**\n * Configure the delay period for period update check. the unit is in seconds.\n *\n * Only available for Android and iOS.\n * Cannot be less than 600 seconds (10 minutes).\n *\n * @default 0 (disabled)\n * @example 3600 (1 hour)\n * @example 86400 (24 hours)\n */\n periodCheckDelay?: number;\n\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localS3?: boolean;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localHost?: string;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localWebHost?: string;\n /**\n * Configure the CLI to use a local server for testing or self-hosted update server.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localSupa?: string;\n /**\n * Configure the CLI to use a local server for testing.\n *\n *\n * @default undefined\n * @since 4.17.48\n */\n localSupaAnon?: string;\n /**\n * Configure the CLI to use a local api for testing.\n *\n *\n * @default undefined\n * @since 6.3.3\n */\n localApi?: string;\n /**\n * Configure the CLI to use a local file api for testing.\n *\n *\n * @default undefined\n * @since 6.3.3\n */\n localApiFiles?: string;\n /**\n * Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side.\n *\n *\n * @default false\n * @since 5.4.0\n */\n allowModifyUrl?: boolean;\n\n /**\n * Allow the plugin to modify the appId dynamically from the JavaScript side.\n *\n *\n * @default false\n * @since 7.14.0\n */\n allowModifyAppId?: boolean;\n\n /**\n * Allow marking bundles as errored from JavaScript while using manual update flows.\n * When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`.\n *\n * @default false\n * @since 7.20.0\n */\n allowManualBundleError?: boolean;\n\n /**\n * Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts.\n *\n * Only available for Android and iOS.\n *\n * @default false (will be true by default in a future major release v8.x.x)\n * @since 7.17.3\n */\n persistCustomId?: boolean;\n\n /**\n * Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl},\n * {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts.\n *\n * Only available for Android and iOS.\n *\n * @default false\n * @since 7.20.0\n */\n persistModifyUrl?: boolean;\n\n /**\n * Set the default channel for the app in the config. Case sensitive.\n * This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud.\n * This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options\n *\n *\n * @default undefined\n * @since 5.5.0\n */\n defaultChannel?: string;\n /**\n * Configure the app id for the app in the config.\n *\n * @default undefined\n * @since 6.0.0\n */\n appId?: string;\n\n /**\n * Configure the plugin to keep the URL path after a reload.\n * WARNING: When a reload is triggered, 'window.history' will be cleared.\n *\n * @default false\n * @since 6.8.0\n */\n keepUrlPathAfterReload?: boolean;\n /**\n * Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done\n *\n * @default false\n * @since 7.3.0\n */\n disableJSLogging?: boolean;\n /**\n * Enable shake gesture to show update menu for debugging/testing purposes\n *\n * @default false\n * @since 7.5.0\n */\n shakeMenu?: boolean;\n };\n }\n}\n\nexport interface CapacitorUpdaterPlugin {\n /**\n * Notify Capacitor Updater that the current bundle is working (a rollback will occur if this method is not called on every app launch)\n * By default this method should be called in the first 10 sec after app launch, otherwise a rollback will occur.\n * Change this behaviour with {@link appReadyTimeout}\n *\n * @returns {Promise<AppReadyResult>} an Promise resolved directly\n * @throws {Error}\n */\n notifyAppReady(): Promise<AppReadyResult>;\n\n /**\n * Set the updateUrl for the app, this will be used to check for updates.\n *\n * @param options contains the URL to use for checking for updates.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setUpdateUrl(options: UpdateUrl): Promise<void>;\n\n /**\n * Set the statsUrl for the app, this will be used to send statistics. Passing an empty string will disable statistics gathering.\n *\n * @param options contains the URL to use for sending statistics.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setStatsUrl(options: StatsUrl): Promise<void>;\n\n /**\n * Set the channelUrl for the app, this will be used to set the channel.\n *\n * @param options contains the URL to use for setting the channel.\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 5.4.0\n */\n setChannelUrl(options: ChannelUrl): Promise<void>;\n\n /**\n * Download a new bundle from the provided URL, it should be a zip file, with files inside or with a unique id inside with all your files\n *\n * @example const bundle = await CapacitorUpdater.download({ url: `https://example.com/versions/${version}/dist.zip`, version });\n * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the specified bundle.\n * @param options The {@link DownloadOptions} for downloading a new bundle zip.\n */\n download(options: DownloadOptions): Promise<BundleInfo>;\n\n /**\n * Set the next bundle to be used when the app is reloaded.\n *\n * @param options Contains the ID of the next Bundle to set on next app launch. {@link BundleInfo.id}\n * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the specified bundle id.\n * @throws {Error} When there is no index.html file inside the bundle folder.\n */\n next(options: BundleId): Promise<BundleInfo>;\n\n /**\n * Set the current bundle and immediately reloads the app.\n *\n * @param options A {@link BundleId} object containing the new bundle id to set as current.\n * @returns {Promise<void>}\n * @throws {Error} When there are is no index.html file inside the bundle folder.\n */\n set(options: BundleId): Promise<void>;\n\n /**\n * Deletes the specified bundle from the native app storage. Use with {@link list} to get the stored Bundle IDs.\n *\n * @param options A {@link BundleId} object containing the ID of a bundle to delete (note, this is the bundle id, NOT the version name)\n * @returns {Promise<void>} When the bundle is deleted\n * @throws {Error}\n */\n delete(options: BundleId): Promise<void>;\n\n /**\n * Mark an installed bundle as errored. Only available when {@link PluginsConfig.CapacitorUpdater.allowManualBundleError} is true.\n *\n * @param options A {@link BundleId} object containing the bundle id to mark as errored.\n * @returns {Promise<BundleInfo>} The updated {@link BundleInfo} for the bundle.\n * @throws {Error} When the bundle does not exist or the feature is disabled.\n * @since 7.20.0\n */\n setBundleError(options: BundleId): Promise<BundleInfo>;\n\n /**\n * Get all locally downloaded bundles in your app\n *\n * @returns {Promise<BundleListResult>} A Promise containing the {@link BundleListResult.bundles}\n * @param options The {@link ListOptions} for listing bundles\n * @throws {Error}\n */\n list(options?: ListOptions): Promise<BundleListResult>;\n\n /**\n * Reset the app to the `builtin` bundle (the one sent to Apple App Store / Google Play Store ) or the last successfully loaded bundle.\n *\n * @param options Containing {@link ResetOptions.toLastSuccessful}, `true` resets to the builtin bundle and `false` will reset to the last successfully loaded bundle.\n * @returns {Promise<void>}\n * @throws {Error}\n */\n reset(options?: ResetOptions): Promise<void>;\n\n /**\n * Get the current bundle, if none are set it returns `builtin`. currentNative is the original bundle installed on the device\n *\n * @returns {Promise<CurrentBundleResult>} A Promise evaluating to the {@link CurrentBundleResult}\n * @throws {Error}\n */\n current(): Promise<CurrentBundleResult>;\n\n /**\n * Reload the view\n *\n * @returns {Promise<void>} A Promise which is resolved when the view is reloaded\n * @throws {Error}\n */\n reload(): Promise<void>;\n\n /**\n * Sets a {@link DelayCondition} array containing conditions that the Plugin will use to delay the update.\n * After all conditions are met, the update process will run start again as usual, so update will be installed after a backgrounding or killing the app.\n * For the `date` kind, the value should be an iso8601 date string.\n * For the `background` kind, the value should be a number in milliseconds.\n * For the `nativeVersion` kind, the value should be the version number.\n * For the `kill` kind, the value is not used.\n * The function has inconsistent behavior the option kill do trigger the update after the first kill and not after the next background like other options. This will be fixed in a future major release.\n *\n * @example\n * // Delay the update after the user kills the app or after a background of 300000 ms (5 minutes)\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'kill' }, { kind: 'background', value: '300000' }] })\n * @example\n * // Delay the update after the specific iso8601 date is expired\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'date', value: '2022-09-14T06:14:11.920Z' }] })\n * @example\n * // Delay the update after the first background (default behaviour without setting delay)\n * await CapacitorUpdater.setMultiDelay({ delayConditions: [{ kind: 'background' }] })\n * @param options Containing the {@link MultiDelayConditions} array of conditions to set\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 4.3.0\n */\n setMultiDelay(options: MultiDelayConditions): Promise<void>;\n\n /**\n * Cancels a {@link DelayCondition} to process an update immediately.\n *\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 4.0.0\n */\n cancelDelay(): Promise<void>;\n\n /**\n * Get Latest bundle available from update Url\n *\n * @returns {Promise<LatestVersion>} A Promise resolved when url is loaded\n * @throws {Error}\n * @since 4.0.0\n */\n getLatest(options?: GetLatestOptions): Promise<LatestVersion>;\n\n /**\n * Sets the channel for this device. The channel has to allow for self assignment for this to work.\n * Do not use this method to set the channel at boot.\n * This method is to set the channel after the app is ready, and user interacted.\n * If you want to set the channel at boot, use the {@link PluginsConfig} to set the default channel.\n * This methods send to Capgo backend a request to link the device ID to the channel. Capgo can accept or refuse depending of the setting of your channel.\n *\n *\n *\n * @param options Is the {@link SetChannelOptions} channel to set\n * @returns {Promise<ChannelRes>} A Promise which is resolved when the new channel is set\n * @throws {Error}\n * @since 4.7.0\n */\n setChannel(options: SetChannelOptions): Promise<ChannelRes>;\n\n /**\n * Unset the channel for this device. The device will then return to the default channel\n *\n * @returns {Promise<ChannelRes>} A Promise resolved when channel is set\n * @throws {Error}\n * @since 4.7.0\n */\n unsetChannel(options: UnsetChannelOptions): Promise<void>;\n\n /**\n * Get the channel for this device\n *\n * @returns {Promise<ChannelRes>} A Promise that resolves with the channel info\n * @throws {Error}\n * @since 4.8.0\n */\n getChannel(): Promise<GetChannelRes>;\n\n /**\n * List all channels available for this device that allow self-assignment\n *\n * @returns {Promise<ListChannelsResult>} A Promise that resolves with the available channels\n * @throws {Error}\n * @since 7.5.0\n */\n listChannels(): Promise<ListChannelsResult>;\n\n /**\n * Set a custom ID for this device\n *\n * When {@link PluginsConfig.CapacitorUpdater.persistCustomId} is true, the value will be stored natively and restored on the next app launch.\n * Pass an empty string to remove any previously stored customId.\n *\n * @param options is the {@link SetCustomIdOptions} customId to set\n * @returns {Promise<void>} an Promise resolved instantly\n * @throws {Error}\n * @since 4.9.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n\n /**\n * Get the native app version or the builtin version if set in config\n *\n * @returns {Promise<BuiltinVersion>} A Promise with version for this device\n * @since 5.2.0\n */\n getBuiltinVersion(): Promise<BuiltinVersion>;\n\n /**\n * Get unique ID used to identify device (sent to auto update server).\n *\n * This ID is privacy-friendly and follows Apple and Google best practices:\n * - Generated as a UUID and stored securely\n * - Android: Uses Android Keystore (persists across reinstalls on API 23+)\n * - iOS: Uses Keychain with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly (persists across reinstalls)\n * - Data stays on device (not synced to cloud on iOS)\n * - Can be cleared by user via system settings (Android) or keychain access (iOS)\n *\n * The device ID now persists between app reinstalls to maintain consistent device identity.\n *\n * @returns {Promise<DeviceId>} A Promise with id for this device\n * @throws {Error}\n */\n getDeviceId(): Promise<DeviceId>;\n\n /**\n * Get the native Capacitor Updater plugin version (sent to auto update server)\n *\n * @returns {Promise<PluginVersion>} A Promise with Plugin version\n * @throws {Error}\n */\n getPluginVersion(): Promise<PluginVersion>;\n\n /**\n * Get the state of auto update config.\n *\n * @returns {Promise<AutoUpdateEnabled>} The status for auto update. Evaluates to `false` in manual mode.\n * @throws {Error}\n */\n isAutoUpdateEnabled(): Promise<AutoUpdateEnabled>;\n\n /**\n * Remove all listeners for this plugin.\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Listen for bundle download event in the App. Fires once a download has started, during downloading and when finished.\n * This will return you all download percent during the download\n *\n * @since 2.0.11\n */\n addListener(eventName: 'download', listenerFunc: (state: DownloadEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for no need to update event, useful when you want force check every time the app is launched\n *\n * @since 4.0.0\n */\n addListener(eventName: 'noNeedUpdate', listenerFunc: (state: NoNeedEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for available update event, useful when you want to force check every time the app is launched\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'updateAvailable',\n listenerFunc: (state: UpdateAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for downloadComplete events.\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'downloadComplete',\n listenerFunc: (state: DownloadCompleteEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for breaking update events when the backend flags an update as incompatible with the current app.\n * Emits the same payload as the legacy `majorAvailable` listener.\n *\n * @since 7.22.0\n */\n addListener(\n eventName: 'breakingAvailable',\n listenerFunc: (state: BreakingAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for Major update event in the App, let you know when major update is blocked by setting disableAutoUpdateBreaking\n *\n * @deprecated Deprecated alias for {@link addListener} with `breakingAvailable`. Emits the same payload. will be removed in v8\n * @since 2.3.0\n */\n addListener(\n eventName: 'majorAvailable',\n listenerFunc: (state: MajorAvailableEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for update fail event in the App, let you know when update has fail to install at next app start\n *\n * @since 2.3.0\n */\n addListener(\n eventName: 'updateFailed',\n listenerFunc: (state: UpdateFailedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for download fail event in the App, let you know when a bundle download has failed\n *\n * @since 4.0.0\n */\n addListener(\n eventName: 'downloadFailed',\n listenerFunc: (state: DownloadFailedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for reload event in the App, let you know when reload has happened\n *\n * @since 4.3.0\n */\n addListener(eventName: 'appReloaded', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for app ready event in the App, let you know when app is ready to use, this event is retain till consumed.\n *\n * @since 5.1.0\n */\n addListener(eventName: 'appReady', listenerFunc: (state: AppReadyEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Get if auto update is available (not disabled by serverUrl).\n *\n * @returns {Promise<AutoUpdateAvailable>} The availability status for auto update. Evaluates to `false` when serverUrl is set.\n * @throws {Error}\n */\n isAutoUpdateAvailable(): Promise<AutoUpdateAvailable>;\n\n /**\n * Get the next bundle that will be used when the app reloads.\n * Returns null if no next bundle is set.\n *\n * @returns {Promise<BundleInfo | null>} A Promise that resolves with the next bundle information or null\n * @throws {Error}\n * @since 6.8.0\n */\n getNextBundle(): Promise<BundleInfo | null>;\n\n /**\n * Get the most recent update that failed to install, if any. The stored value is cleared after it is retrieved once.\n *\n * @returns {Promise<UpdateFailedEvent | null>} The last failed update or null when no failure has been recorded. Value is cleared after it is returned once.\n * @throws {Error}\n * @since 7.22.0\n */\n getFailedUpdate(): Promise<UpdateFailedEvent | null>;\n\n /**\n * Enable or disable the shake menu for debugging/testing purposes\n *\n * @param options Contains enabled boolean to enable or disable shake menu\n * @returns {Promise<void>}\n * @throws {Error}\n * @since 7.5.0\n */\n setShakeMenu(options: SetShakeMenuOptions): Promise<void>;\n\n /**\n * Get the current state of the shake menu\n *\n * @returns {Promise<ShakeMenuEnabled>} The current state of shake menu\n * @throws {Error}\n * @since 7.5.0\n */\n isShakeMenuEnabled(): Promise<ShakeMenuEnabled>;\n\n /**\n * Get the configured App ID\n *\n * @returns {Promise<GetAppIdRes>} The current App ID\n * @throws {Error}\n * @since 7.14.0\n */\n getAppId(): Promise<GetAppIdRes>;\n\n /**\n * Set the App ID for the app (requires allowModifyAppId to be true in config)\n *\n * @param options The new App ID to set\n * @returns {Promise<void>}\n * @throws {Error} If allowModifyAppId is false or if the operation fails\n * @since 7.14.0\n */\n setAppId(options: SetAppIdOptions): Promise<void>;\n}\n\n/**\n * pending: The bundle is pending to be **SET** as the next bundle.\n * downloading: The bundle is being downloaded.\n * success: The bundle has been downloaded and is ready to be **SET** as the next bundle.\n * error: The bundle has failed to download.\n */\nexport type BundleStatus = 'success' | 'error' | 'pending' | 'downloading';\n\nexport type DelayUntilNext = 'background' | 'kill' | 'nativeVersion' | 'date';\n\nexport interface NoNeedEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface UpdateAvailableEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface ChannelRes {\n /**\n * Current status of set channel\n *\n * @since 4.7.0\n */\n status: string;\n error?: string;\n message?: string;\n}\n\nexport interface GetChannelRes {\n /**\n * Current status of get channel\n *\n * @since 4.8.0\n */\n channel?: string;\n error?: string;\n message?: string;\n status?: string;\n allowSet?: boolean;\n}\n\nexport interface ChannelInfo {\n /**\n * The channel ID\n *\n * @since 7.5.0\n */\n id: string;\n /**\n * The channel name\n *\n * @since 7.5.0\n */\n name: string;\n /**\n * Whether this is a public channel\n *\n * @since 7.5.0\n */\n public: boolean;\n /**\n * Whether devices can self-assign to this channel\n *\n * @since 7.5.0\n */\n allow_self_set: boolean;\n}\n\nexport interface ListChannelsResult {\n /**\n * List of available channels\n *\n * @since 7.5.0\n */\n channels: ChannelInfo[];\n}\n\nexport interface DownloadEvent {\n /**\n * Current status of download, between 0 and 100.\n *\n * @since 4.0.0\n */\n percent: number;\n bundle: BundleInfo;\n}\n\nexport interface MajorAvailableEvent {\n /**\n * Emit when a breaking update is available.\n *\n * @deprecated Deprecated alias for {@link BreakingAvailableEvent}. Receives the same payload.\n * @since 4.0.0\n */\n version: string;\n}\n\n/**\n * Payload emitted by {@link CapacitorUpdaterPlugin.addListener} with `breakingAvailable`.\n *\n * @since 7.22.0\n */\nexport type BreakingAvailableEvent = MajorAvailableEvent;\n\nexport interface DownloadFailedEvent {\n /**\n * Emit when a download fail.\n *\n * @since 4.0.0\n */\n version: string;\n}\n\nexport interface DownloadCompleteEvent {\n /**\n * Emit when a new update is available.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface UpdateFailedEvent {\n /**\n * Emit when a update failed to install.\n *\n * @since 4.0.0\n */\n bundle: BundleInfo;\n}\n\nexport interface AppReadyEvent {\n /**\n * Emitted when the app is ready to use.\n *\n * @since 5.2.0\n */\n bundle: BundleInfo;\n status: string;\n}\n\nexport interface ManifestEntry {\n file_name: string | null;\n file_hash: string | null;\n download_url: string | null;\n}\n\nexport interface LatestVersion {\n /**\n * Result of getLatest method\n *\n * @since 4.0.0\n */\n version: string;\n /**\n * @since 6\n */\n checksum?: string;\n /**\n * Indicates whether the update was flagged as breaking by the backend.\n *\n * @since 7.22.0\n */\n breaking?: boolean;\n /**\n * @deprecated Use {@link LatestVersion.breaking} instead.\n */\n major?: boolean;\n message?: string;\n sessionKey?: string;\n error?: string;\n old?: string;\n url?: string;\n /**\n * @since 6.1\n */\n manifest?: ManifestEntry[];\n}\n\nexport interface BundleInfo {\n id: string;\n version: string;\n downloaded: string;\n checksum: string;\n status: BundleStatus;\n}\n\nexport interface SetChannelOptions {\n channel: string;\n triggerAutoUpdate?: boolean;\n}\n\nexport interface UnsetChannelOptions {\n triggerAutoUpdate?: boolean;\n}\n\nexport interface SetCustomIdOptions {\n /**\n * Custom identifier to associate with the device. Use an empty string to clear any saved value.\n */\n customId: string;\n}\n\nexport interface DelayCondition {\n /**\n * Set up delay conditions in setMultiDelay\n * @param value is useless for @param kind \"kill\", optional for \"background\" (default value: \"0\") and required for \"nativeVersion\" and \"date\"\n */\n kind: DelayUntilNext;\n value?: string;\n}\n\nexport interface GetLatestOptions {\n /**\n * The channel to get the latest version for\n * The channel must allow 'self_assign' for this to work\n * @since 6.8.0\n * @default undefined\n */\n channel?: string;\n}\n\nexport interface AppReadyResult {\n bundle: BundleInfo;\n}\n\nexport interface UpdateUrl {\n url: string;\n}\n\nexport interface StatsUrl {\n url: string;\n}\n\nexport interface ChannelUrl {\n url: string;\n}\n\n/**\n * This URL and versions are used to download the bundle from the server, If you use backend all information will be given by the method getLatest.\n * If you don't use backend, you need to provide the URL and version of the bundle. Checksum and sessionKey are required if you encrypted the bundle with the CLI command encrypt, you should receive them as result of the command.\n */\nexport interface DownloadOptions {\n /**\n * The URL of the bundle zip file (e.g: dist.zip) to be downloaded. (This can be any URL. E.g: Amazon S3, a GitHub tag, any other place you've hosted your bundle.)\n */\n url: string;\n /**\n * The version code/name of this bundle/version\n */\n version: string;\n /**\n * The session key for the update, when the bundle is encrypted with a session key\n * @since 4.0.0\n * @default undefined\n */\n sessionKey?: string;\n /**\n * The checksum for the update, it should be in sha256 and encrypted with private key if the bundle is encrypted\n * @since 4.0.0\n * @default undefined\n */\n checksum?: string;\n /**\n * The manifest for multi-file downloads\n * @since 6.1.0\n * @default undefined\n */\n manifest?: ManifestEntry[];\n}\n\nexport interface BundleId {\n id: string;\n}\n\nexport interface BundleListResult {\n bundles: BundleInfo[];\n}\n\nexport interface ResetOptions {\n toLastSuccessful: boolean;\n}\n\nexport interface ListOptions {\n /**\n * Whether to return the raw bundle list or the manifest. If true, the list will attempt to read the internal database instead of files on disk.\n * @since 6.14.0\n * @default false\n */\n raw?: boolean;\n}\n\nexport interface CurrentBundleResult {\n bundle: BundleInfo;\n native: string;\n}\n\nexport interface MultiDelayConditions {\n delayConditions: DelayCondition[];\n}\n\nexport interface BuiltinVersion {\n version: string;\n}\n\nexport interface DeviceId {\n deviceId: string;\n}\n\nexport interface PluginVersion {\n version: string;\n}\n\nexport interface AutoUpdateEnabled {\n enabled: boolean;\n}\n\nexport interface AutoUpdateAvailable {\n available: boolean;\n}\n\nexport interface SetShakeMenuOptions {\n enabled: boolean;\n}\n\nexport interface ShakeMenuEnabled {\n enabled: boolean;\n}\n\nexport interface GetAppIdRes {\n appId: string;\n}\n\nexport interface SetAppIdOptions {\n appId: string;\n}\n"]}
@@ -54,7 +54,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
54
54
  CAPPluginMethod(name: "isShakeMenuEnabled", returnType: CAPPluginReturnPromise)
55
55
  ]
56
56
  public var implementation = CapgoUpdater()
57
- private let pluginVersion: String = "6.25.3"
57
+ private let pluginVersion: String = "6.25.5"
58
58
  static let updateUrlDefault = "https://plugin.capgo.app/updates"
59
59
  static let statsUrlDefault = "https://plugin.capgo.app/stats"
60
60
  static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
@@ -147,13 +147,19 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
147
147
 
148
148
  // Handle directUpdate configuration - support string values and backward compatibility
149
149
  if let directUpdateString = getConfig().getString("directUpdate") {
150
- directUpdateMode = directUpdateString
151
- directUpdate = directUpdateString == "always" || directUpdateString == "atInstall" || directUpdateString == "onLaunch"
152
- // Validate directUpdate value
153
- if directUpdateString != "false" && directUpdateString != "always" && directUpdateString != "atInstall" && directUpdateString != "onLaunch" {
154
- logger.error("Invalid directUpdate value: \"\(directUpdateString)\". Supported values are: false, \"always\", \"atInstall\", \"onLaunch\". Defaulting to false.")
155
- directUpdateMode = "false"
156
- directUpdate = false
150
+ // Handle backward compatibility for boolean true
151
+ if directUpdateString == "true" {
152
+ directUpdateMode = "always"
153
+ directUpdate = true
154
+ } else {
155
+ directUpdateMode = directUpdateString
156
+ directUpdate = directUpdateString == "always" || directUpdateString == "atInstall" || directUpdateString == "onLaunch"
157
+ // Validate directUpdate value
158
+ if directUpdateString != "false" && directUpdateString != "always" && directUpdateString != "atInstall" && directUpdateString != "onLaunch" {
159
+ logger.error("Invalid directUpdate value: \"\(directUpdateString)\". Supported values are: \"false\", \"true\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to \"false\".")
160
+ directUpdateMode = "false"
161
+ directUpdate = false
162
+ }
157
163
  }
158
164
  } else {
159
165
  let directUpdateBool = getConfig().getBoolean("directUpdate", false)
@@ -238,7 +244,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
238
244
  // This is very much swift specific, android does not do that
239
245
  // In android we depend on the serverBasePath capacitor property
240
246
  // In IOS we do not. Instead during the plugin initialization we try to call setServerBasePath
241
- // The idea is to prevent having to store the bundle in 2 locations for hot reload and persisten storage
247
+ // The idea is to prevent having to store the bundle in 2 locations for hot reload and persistent storage
242
248
  // According to martin it is not possible to use serverBasePath on ios in a way that allows us to store the bundle once
243
249
 
244
250
  if !self.initialLoad() {
@@ -1208,7 +1214,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1208
1214
  }
1209
1215
  return false
1210
1216
  default:
1211
- logger.error("Invalid directUpdateMode: \"\(self.directUpdateMode)\". Supported values are: \"false\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to false behavior.")
1217
+ logger.error("Invalid directUpdateMode: \"\(self.directUpdateMode)\". Supported values are: \"false\", \"always\", \"atInstall\", \"onLaunch\". Defaulting to \"false\" behavior.")
1212
1218
  return false
1213
1219
  }
1214
1220
  }
@@ -1259,38 +1265,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1259
1265
  // Handle network errors and other failures first
1260
1266
  if let backendError = res.error, !backendError.isEmpty {
1261
1267
  self.logger.error("getLatest failed with error: \(backendError)")
1262
- if backendError == "response_error" {
1263
- self.endBackGroundTaskWithNotif(
1264
- msg: "Network error: \(backendError)",
1265
- latestVersionName: res.version,
1266
- current: current,
1267
- error: true
1268
- )
1269
- } else {
1270
- self.endBackGroundTaskWithNotif(
1271
- msg: backendError,
1272
- latestVersionName: res.version,
1273
- current: current,
1274
- error: true,
1275
- failureAction: "backend_refusal",
1276
- failureEvent: "backendRefused"
1277
- )
1278
- }
1279
- return
1280
- }
1281
-
1282
- if let message = res.message, !message.isEmpty {
1283
- self.logger.info("API message: \(message)")
1284
- if res.breaking == true || res.major == true {
1285
- self.notifyBreakingEvents(version: res.version)
1286
- }
1287
1268
  self.endBackGroundTaskWithNotif(
1288
- msg: message,
1269
+ msg: res.message ?? backendError,
1289
1270
  latestVersionName: res.version,
1290
1271
  current: current,
1291
- error: true,
1292
- failureAction: "backend_refusal",
1293
- failureEvent: "backendRefused"
1272
+ error: true
1294
1273
  )
1295
1274
  return
1296
1275
  }
@@ -102,7 +102,11 @@ import UIKit
102
102
  // Only send once to prevent infinite loop if the stat request itself gets rate limited
103
103
  if !CapgoUpdater.rateLimitExceeded && !CapgoUpdater.rateLimitStatisticSent {
104
104
  CapgoUpdater.rateLimitStatisticSent = true
105
- self.sendRateLimitStatistic()
105
+
106
+ // Dispatch to background queue to avoid blocking the main thread
107
+ DispatchQueue.global(qos: .utility).async {
108
+ self.sendRateLimitStatistic()
109
+ }
106
110
  }
107
111
  CapgoUpdater.rateLimitExceeded = true
108
112
  logger.warn("Rate limit exceeded (429). Stopping all stats and channel requests until app restart.")
@@ -113,6 +117,8 @@ import UIKit
113
117
 
114
118
  /**
115
119
  * Send a synchronous statistic about rate limiting
120
+ * Note: This method uses a semaphore to block until the request completes.
121
+ * It MUST be called from a background queue to avoid blocking the main thread.
116
122
  */
117
123
  private func sendRateLimitStatistic() {
118
124
  guard !statsUrl.isEmpty else {
@@ -125,7 +131,7 @@ import UIKit
125
131
  parameters.version_name = current.getVersionName()
126
132
  parameters.old_version_name = ""
127
133
 
128
- // Send synchronously to ensure it goes out before the flag is set
134
+ // Send synchronously using semaphore (safe because we're on a background queue)
129
135
  let semaphore = DispatchSemaphore(value: 0)
130
136
  self.alamofireSession.request(
131
137
  self.statsUrl,
@@ -100,7 +100,7 @@ public struct CryptoCipherV2 {
100
100
 
101
101
  public static func decryptFile(filePath: URL, publicKey: String, sessionKey: String, version: String) throws {
102
102
  if publicKey.isEmpty || sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
103
- logger.info("Encryption not set, no public key or seesion, ignored")
103
+ logger.info("Encryption not set, no public key or session, ignored")
104
104
  return
105
105
  }
106
106
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "6.25.3",
3
+ "version": "6.25.5",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",