UNPKG

@capgo/capacitor-updater

Version:
1,063 lines 92.9 kB
import type { PluginListenerHandle } from '@capacitor/core'; declare module '@capacitor/cli' { interface PluginsConfig { /** * CapacitorUpdater can be configured with these options: */ CapacitorUpdater?: { /** * Configure the number of milliseconds the native plugin should wait before considering an update 'failed'. * * Only available for Android and iOS. * * @default 10000 // (10 seconds) * @example 1000 // (1 second, minimum 1000) */ appReadyTimeout?: number; /** * Configure the number of seconds the native plugin should wait before considering API timeout. * * Only available for Android and iOS. * * @default 20 // (20 second) * @example 10 // (10 second) */ responseTimeout?: number; /** * Configure whether the plugin should use automatically delete failed bundles. * * Only available for Android and iOS. * * @default true * @example false */ autoDeleteFailed?: boolean; /** * Configure whether the plugin should use automatically delete previous bundles after a successful update. * * Only available for Android and iOS. * * @default true * @example false */ autoDeletePrevious?: boolean; /** * Configure how the plugin should use Auto Update via an update server. * * Boolean values keep their existing behavior: * - `true`: Same as `"atBackground"`. * - `false`: Same as `"off"`. * * String values merge the previous Auto Update and Direct Update configuration: * - `"off"`: Disable Auto Update. * - `"atBackground"`: Check and download updates automatically, then apply them the next time the app moves to background. * - `"atInstall"`: Direct install only after app install or native app update, otherwise use `"atBackground"` behavior. * - `"onLaunch"`: Direct install on app launch, otherwise use `"atBackground"` behavior after the first launch attempt. * - `"always"`: Direct install whenever Auto Update runs. * - `"onlyDownload"`: Check and download updates automatically, emit `updateAvailable`, but never direct install or set the next bundle automatically. * * Only available for Android and iOS. * * @default true * @example "onlyDownload" */ autoUpdate?: boolean | 'off' | 'atBackground' | 'atInstall' | 'onLaunch' | 'always' | 'onlyDownload'; /** * Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device. * Setting this to false can broke the auto update flow if the user download from the store a native app bundle that is older than the current downloaded bundle. Upload will be prevented by channel setting downgrade_under_native. * Only available for Android and iOS. * * @default true * @example false */ resetWhenUpdate?: boolean; /** * Configure the URL / endpoint to which update checks are sent. * * Only available for Android and iOS. * * @default https://plugin.capgo.app/updates * @example https://example.com/api/auto_update */ updateUrl?: string; /** * Configure the URL / endpoint for channel operations. * * Only available for Android and iOS. * * @default https://plugin.capgo.app/channel_self * @example https://example.com/api/channel */ channelUrl?: string; /** * Configure the URL / endpoint to which update statistics are sent. * * Only available for Android and iOS. Set to "" to disable stats reporting. * Native stats include update lifecycle events, app health signals such as crashes, * Android ANRs, low-memory exits, iOS memory warnings, and WebView health signals * such as JavaScript errors, unhandled promise rejections, resource load failures, * WebView renderer exits, and unclean WebView restarts when available. * * @default https://plugin.capgo.app/stats * @example https://example.com/api/stats */ statsUrl?: string; /** * Configure the public key for end to end live update encryption Version 2 * * Only available for Android and iOS. * * @default undefined * @since 6.2.0 */ publicKey?: string; /** * 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. * * @default undefined * @since 4.17.48 */ version?: string; /** * Configure when the plugin should direct install updates. Only for autoUpdate mode. * * @deprecated Use {@link PluginsConfig.CapacitorUpdater.autoUpdate} string modes instead. * Works well for apps less than 10MB and with uploads done using --delta 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 * * Activate this flag will automatically make the CLI upload delta in CICD envs and will ask for confirmation in local uploads. * Only available for Android and iOS. * * @default false * @since 5.1.0 */ directUpdate?: boolean | 'atInstall' | 'always' | 'onLaunch'; /** * 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 autoUpdate is set to "atInstall", "always", or "onLaunch", or when the deprecated directUpdate option is set to "atInstall", "always", "onLaunch", or true. * Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. * Requires Auto Update and Direct Update behavior to be enabled. * * Only available for Android and iOS. * * @default false * @since 7.6.0 */ autoSplashscreen?: boolean; /** * 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. * * @default false * @since 7.19.0 */ autoSplashscreenLoader?: boolean; /** * 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. * * @default 10000 // (10 seconds) * @since 7.19.0 */ autoSplashscreenTimeout?: number; /** * 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). * * @default 0 (disabled) * @example 3600 (1 hour) * @example 86400 (24 hours) */ periodCheckDelay?: number; /** * Configure the CLI to use a local server for testing or self-hosted update server. * * * @default undefined * @since 4.17.48 */ localS3?: boolean; /** * Configure the CLI to use a local server for testing or self-hosted update server. * * * @default undefined * @since 4.17.48 */ localHost?: string; /** * Configure the CLI to use a local server for testing or self-hosted update server. * * * @default undefined * @since 4.17.48 */ localWebHost?: string; /** * Configure the CLI to use a local server for testing or self-hosted update server. * * * @default undefined * @since 4.17.48 */ localSupa?: string; /** * Configure the CLI to use a local server for testing. * * * @default undefined * @since 4.17.48 */ localSupaAnon?: string; /** * Configure the CLI to use a local api for testing. * * * @default undefined * @since 6.3.3 */ localApi?: string; /** * Configure the CLI to use a local file api for testing. * * * @default undefined * @since 6.3.3 */ localApiFiles?: string; /** * Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side. * * * @default false * @since 5.4.0 */ allowModifyUrl?: boolean; /** * Allow the plugin to modify the appId dynamically from the JavaScript side. * * * @default false * @since 7.14.0 */ allowModifyAppId?: boolean; /** * Allow marking bundles as errored from JavaScript while using manual update flows. * When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`. * * @default false * @since 7.20.0 */ allowManualBundleError?: boolean; /** * Allow JavaScript to start a native preview session and temporarily request updates for another app id. * This is intended for trusted container apps that implement Expo Go-style preview flows. * * Only available for Android and iOS. * * @default false * @since 8.47.0 */ allowPreview?: boolean; /** * Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts. * * Only available for Android and iOS. * * @default false (will be true by default in a future major release v8.x.x) * @since 7.17.3 */ persistCustomId?: boolean; /** * 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. * * @default false * @since 7.20.0 */ persistModifyUrl?: boolean; /** * Allow or disallow the {@link CapacitorUpdaterPlugin.setChannel} method to modify the defaultChannel. * When set to `false`, calling `setChannel()` will return an error with code `disabled_by_config`. * * @default true * @since 7.34.0 */ allowSetDefaultChannel?: boolean; /** * 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 * * * @default undefined * @since 5.5.0 */ defaultChannel?: string; /** * Configure the app id for the app in the config. * * @default undefined * @since 6.0.0 */ appId?: string; /** * Configure the plugin to keep the URL path after a reload. * WARNING: When a reload is triggered, 'window.history' will be cleared. * * @default false * @since 6.8.0 */ keepUrlPathAfterReload?: boolean; /** * 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 * * @default false * @since 7.3.0 */ disableJSLogging?: boolean; /** * Enable OS-level logging. When enabled, logs are written to the system log which can be inspected in production builds. * * - **iOS**: Uses os_log instead of Swift.print, logs accessible via Console.app or Instruments * - **Android**: Logs to Logcat (android.util.Log) * * When set to false, system logging is disabled on both platforms (only JavaScript console logging will occur if enabled). * * This is useful for debugging production apps (App Store/TestFlight builds on iOS, or production APKs on Android). * * @default true * @since 8.42.0 */ osLogging?: boolean; /** * Enable shake gesture to show update menu for debugging/testing purposes * * @default false * @since 7.5.0 */ shakeMenu?: boolean; /** * Enable the shake gesture to show a channel selector menu for switching between update channels. * When enabled AND `shakeMenu` is true, the shake gesture shows a channel selector * instead of the default debug menu (Go Home/Reload/Close). * * After selecting a channel, the app automatically checks for updates and downloads if available. * Only works if channels have `allow_self_set` enabled on the backend. * * Only available for Android and iOS. * * @default false * @since 8.43.0 */ allowShakeChannelSelector?: boolean; }; } } export interface CapacitorUpdaterPlugin { /** * Notify the native layer that JavaScript initialized successfully. * * **CRITICAL: You must call this method on every app launch to prevent automatic rollback.** * * This is a simple notification to confirm that your bundle's JavaScript loaded and executed. * The native web server successfully served the bundle files and your JS runtime started. * That's all it checks - nothing more complex. * * **What triggers rollback:** * - NOT calling this method within the timeout (default: 10 seconds) * - Complete JavaScript failure (bundle won't load at all) * * **What does NOT trigger rollback:** * - Runtime errors after initialization (API failures, crashes, etc.) * - Network request failures * - Application logic errors * * **IMPORTANT: Call this BEFORE any network requests.** * Don't wait for APIs, data loading, or async operations. Call it as soon as your * JavaScript bundle starts executing to confirm the bundle itself is valid. * * Best practices: * - Call immediately in your app entry point (main.js, app component mount, etc.) * - Don't put it after network calls or heavy initialization * - Don't wrap it in try/catch with conditions * - Adjust {@link PluginsConfig.CapacitorUpdater.appReadyTimeout} if you need more time * * @returns {Promise<AppReadyResult>} Always resolves successfully with current bundle info. This method never fails. */ notifyAppReady(): Promise<AppReadyResult>; /** * Set the update URL for the app dynamically at runtime. * * This overrides the {@link PluginsConfig.CapacitorUpdater.updateUrl} config value. * Requires {@link PluginsConfig.CapacitorUpdater.allowModifyUrl} to be set to `true`. * * Use {@link PluginsConfig.CapacitorUpdater.persistModifyUrl} to persist this value across app restarts. * Otherwise, the URL will reset to the config value on next app launch. * * @param options Contains the URL to use for checking for updates. * @returns {Promise<void>} Resolves when the URL is successfully updated. * @throws {Error} If `allowModifyUrl` is false or if the operation fails. * @since 5.4.0 */ setUpdateUrl(options: UpdateUrl): Promise<void>; /** * Set the statistics URL for the app dynamically at runtime. * * This overrides the {@link PluginsConfig.CapacitorUpdater.statsUrl} config value. * Requires {@link PluginsConfig.CapacitorUpdater.allowModifyUrl} to be set to `true`. * * Pass an empty string to disable statistics gathering entirely. * Use {@link PluginsConfig.CapacitorUpdater.persistModifyUrl} to persist this value across app restarts. * * @param options Contains the URL to use for sending statistics, or an empty string to disable. * @returns {Promise<void>} Resolves when the URL is successfully updated. * @throws {Error} If `allowModifyUrl` is false or if the operation fails. * @since 5.4.0 */ setStatsUrl(options: StatsUrl): Promise<void>; /** * Set the channel URL for the app dynamically at runtime. * * This overrides the {@link PluginsConfig.CapacitorUpdater.channelUrl} config value. * Requires {@link PluginsConfig.CapacitorUpdater.allowModifyUrl} to be set to `true`. * * Use {@link PluginsConfig.CapacitorUpdater.persistModifyUrl} to persist this value across app restarts. * Otherwise, the URL will reset to the config value on next app launch. * * @param options Contains the URL to use for channel operations. * @returns {Promise<void>} Resolves when the URL is successfully updated. * @throws {Error} If `allowModifyUrl` is false or if the operation fails. * @since 5.4.0 */ setChannelUrl(options: ChannelUrl): Promise<void>; /** * Download a new bundle from the provided URL for later installation. * * The downloaded bundle is stored locally but not activated. To use it: * - Call {@link next} to set it for installation on next app backgrounding/restart * - Call {@link set} to activate it immediately (destroys current JavaScript context) * * The URL should point to a zip file containing either: * - Your app files directly in the zip root, or * - A single folder containing all your app files * * The bundle must include an `index.html` file at the root level. * * For encrypted bundles, provide the `sessionKey` and `checksum` parameters. * For multi-file delta updates, provide the `manifest` array. * * @example * const bundle = await CapacitorUpdater.download({ * url: `https://example.com/versions/${version}/dist.zip`, * version: version * }); * // Bundle is downloaded but not active yet * await CapacitorUpdater.next({ id: bundle.id }); // Will activate on next background * * @param options The {@link DownloadOptions} for downloading a new bundle zip. * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the downloaded bundle. * @throws {Error} If the download fails or the bundle is invalid. */ download(options: DownloadOptions): Promise<BundleInfo>; /** * Set the next bundle to be activated when the app backgrounds or restarts. * * This is the recommended way to apply updates as it doesn't interrupt the user's current session. * The bundle will be activated when: * - The app is backgrounded (user switches away), or * - The app is killed and relaunched, or * - {@link reload} is called manually * * Unlike {@link set}, this method does NOT destroy the current JavaScript context immediately. * Your app continues running normally until one of the above events occurs. * * Use {@link setMultiDelay} to add additional conditions before the update is applied. * * @param options Contains the ID of the bundle to set as next. Use {@link BundleInfo.id} from a downloaded bundle. * @returns {Promise<BundleInfo>} The {@link BundleInfo} for the specified bundle. * @throws {Error} When there is no index.html file inside the bundle folder or the bundle doesn't exist. */ next(options: BundleId): Promise<BundleInfo>; /** * Set the current bundle and immediately reloads the app. * * **IMPORTANT: This is a terminal operation that destroys the current JavaScript context.** * * When you call this method: * - The entire JavaScript context is immediately destroyed * - The app reloads from a different folder with different files * - NO code after this call will execute * - NO promises will resolve * - NO callbacks will fire * - Event listeners registered after this call are unreliable and may never fire * * The reload happens automatically - you don't need to do anything else. * If you need to preserve state like the current URL path, use the {@link PluginsConfig.CapacitorUpdater.keepUrlPathAfterReload} config option. * For other state preservation needs, save your data before calling this method (e.g., to localStorage). * * **Do not** try to execute additional logic after calling `set()` - it won't work as expected. * * @param options A {@link BundleId} object containing the new bundle id to set as current. * @returns {Promise<void>} A promise that will never resolve because the JavaScript context is destroyed. * @throws {Error} When there is no index.html file inside the bundle folder. */ set(options: BundleId): Promise<void>; /** * Start a temporary preview/testing session. * * This stores the currently active bundle as the pending fallback, enables the * native shake menu, and makes the next applied bundle show a native notice * explaining that shaking the device can reload or leave the preview. * Requires {@link PluginsConfig.CapacitorUpdater.allowPreview} to be `true`. * When `appId` is provided, the preview session temporarily uses that app id * for update checks until the user leaves the preview. Native updater stats are * skipped while the preview session is active. * * Use this before calling {@link set} for Expo Go-style preview flows. * * @param options Optional preview session options. * @returns {Promise<void>} Resolves when preview session state is prepared. * @since 8.47.0 */ startPreviewSession(options?: StartPreviewSessionOptions): Promise<void>; /** * Delete a bundle from local storage to free up disk space. * * You cannot delete: * - The currently active bundle * - The `builtin` bundle (the version shipped with your app) * - The bundle set as `next` (call {@link next} with a different bundle first) * * Use {@link list} to get all available bundle IDs. * * **Note:** The bundle ID is NOT the same as the version name. * Use the `id` field from {@link BundleInfo}, not the `version` field. * * @param options A {@link BundleId} object containing the bundle ID to delete. * @returns {Promise<void>} Resolves when the bundle is successfully deleted. * @throws {Error} If the bundle is currently in use or doesn't exist. */ delete(options: BundleId): Promise<void>; /** * Manually mark a bundle as failed/errored in manual update mode. * * This is useful when you detect that a bundle has critical issues and want to prevent * it from being used again. The bundle status will be changed to `error` and the plugin * will avoid using this bundle in the future. * * **Requirements:** * - {@link PluginsConfig.CapacitorUpdater.allowManualBundleError} must be set to `true` * - Only works in manual update mode (when autoUpdate is disabled) * * Common use case: After downloading and testing a bundle, you discover it has critical * bugs and want to mark it as failed so it won't be retried. * * @param options A {@link BundleId} object containing the bundle ID to mark as errored. * @returns {Promise<BundleInfo>} The updated {@link BundleInfo} with status set to `error`. * @throws {Error} When the bundle does not exist or `allowManualBundleError` is false. * @since 7.20.0 */ setBundleError(options: BundleId): Promise<BundleInfo>; /** * Get all locally downloaded bundles stored in your app. * * This returns all bundles that have been downloaded and are available locally, including: * - The currently active bundle * - The `builtin` bundle (shipped with your app) * - Any downloaded bundles waiting to be activated * - Failed bundles (with `error` status) * * Use this to: * - Check available disk space by counting bundles * - Delete old bundles with {@link delete} * - Monitor bundle download status * * @param options The {@link ListOptions} for customizing the bundle list output. * @returns {Promise<BundleListResult>} A promise containing the array of {@link BundleInfo} objects. * @throws {Error} If the operation fails. */ list(options?: ListOptions): Promise<BundleListResult>; /** * Reset the app to a known good bundle. * * This method helps recover from problematic updates by reverting to either: * - The `builtin` bundle (the original version shipped with your app to App Store/Play Store) * - The last successfully loaded bundle (most recent bundle that worked correctly) * * **IMPORTANT: This triggers an immediate app reload, destroying the current JavaScript context.** * See {@link set} for details on the implications of this operation. * * Use cases: * - Emergency recovery when an update causes critical issues * - Testing rollback functionality * - Providing users a "reset to factory" option * * @param options {@link ResetOptions} to control reset behavior. * If `toLastSuccessful` is `false` (or omitted), resets to builtin. * If `true`, resets to last successful bundle. * If `usePendingBundle` is `true`, applies the pending bundle set via {@link next} and clears it. * @returns {Promise<void>} A promise that may never resolve because the app will be reloaded. * @throws {Error} If the reset operation fails. */ reset(options?: ResetOptions): Promise<void>; /** * Get information about the currently active bundle. * * Returns: * - `bundle`: The currently active bundle information * - `native`: The version of the builtin bundle (the original app version from App/Play Store) * * If no updates have been applied, `bundle.id` will be `"builtin"`, indicating the app * is running the original version shipped with the native app. * * Use this to: * - Display the current version to users * - Check if an update is currently active * - Compare against available updates * - Log the active bundle for debugging * * @returns {Promise<CurrentBundleResult>} A promise with the current bundle and native version info. * @throws {Error} If the operation fails. */ current(): Promise<CurrentBundleResult>; /** * Manually reload the app to apply a pending update. * * This triggers the same reload behavior that happens automatically when the app backgrounds. * If you've called {@link next} to queue an update, calling `reload()` will apply it immediately. * * **IMPORTANT: This destroys the current JavaScript context immediately.** * See {@link set} for details on the implications of this operation. * * Common use cases: * - Applying an update immediately after download instead of waiting for backgrounding * - Providing a "Restart now" button to users after an update is ready * - Testing update flows during development * * If no update is pending (no call to {@link next}), this simply reloads the current bundle. * * @returns {Promise<void>} A promise that may never resolve because the app will be reloaded. * @throws {Error} If the reload operation fails. */ reload(): Promise<void>; /** * Configure conditions that must be met before a pending update is applied. * * After calling {@link next} to queue an update, use this method to control when it gets applied. * The update will only be installed after ALL specified conditions are satisfied. * * Available condition types: * - `background`: Wait for the app to be backgrounded. Optionally specify duration in milliseconds. * - `kill`: Wait for the app to be killed and relaunched (**Note:** Current behavior triggers update immediately on kill, not on next background. This will be fixed in v8.) * - `date`: Wait until a specific date/time (ISO 8601 format) * - `nativeVersion`: Wait until the native app is updated to a specific version * * Condition value formats: * - `background`: Number in milliseconds (e.g., `"300000"` for 5 minutes), or omit for immediate * - `kill`: No value needed * - `date`: ISO 8601 date string (e.g., `"2025-12-31T23:59:59Z"`) * - `nativeVersion`: Version string (e.g., `"2.0.0"`) * * @example * // Update after user kills app OR after 5 minutes in background * await CapacitorUpdater.setMultiDelay({ * delayConditions: [ * { kind: 'kill' }, * { kind: 'background', value: '300000' } * ] * }); * * @example * // Update after a specific date * await CapacitorUpdater.setMultiDelay({ * delayConditions: [{ kind: 'date', value: '2025-12-31T23:59:59Z' }] * }); * * @example * // Default behavior: update on next background * await CapacitorUpdater.setMultiDelay({ * delayConditions: [{ kind: 'background' }] * }); * * @param options Contains the {@link MultiDelayConditions} array of conditions. * @returns {Promise<void>} Resolves when the delay conditions are set. * @throws {Error} If the operation fails or conditions are invalid. * @since 4.3.0 */ setMultiDelay(options: MultiDelayConditions): Promise<void>; /** * Cancel all delay conditions and apply the pending update immediately. * * If you've set delay conditions with {@link setMultiDelay}, this method clears them * and triggers the pending update to be applied on the next app background or restart. * * This is useful when: * - User manually requests to update now (e.g., clicks "Update now" button) * - Your app detects it's a good time to update (e.g., user finished critical task) * - You want to override a time-based delay early * * @returns {Promise<void>} Resolves when the delay conditions are cleared. * @throws {Error} If the operation fails. * @since 4.0.0 */ cancelDelay(): Promise<void>; /** * Trigger the native auto-update check/download pipeline immediately. * * This starts the same background update flow used when the app moves to the * foreground with auto-update enabled. It is useful for native integrations * such as a silent push notification asking the app to check for a Capgo * bundle without reimplementing the update protocol in JavaScript. * * The promise resolves after the native background work has been queued, not * after the update has been downloaded or installed. Listen to updater events * such as `updateAvailable`, `downloadComplete`, `downloadFailed`, and * `noNeedUpdate` for the final result. * * Native support is available on iOS and Android. On Web, this method returns * a result with `status: 'unavailable'`. Native platforms also return * `unavailable` when the native auto-update system is disabled. * * @returns {Promise<TriggerUpdateCheckResult>} Whether a native update check was queued. */ triggerUpdateCheck(): Promise<TriggerUpdateCheckResult>; /** * Check the update server for the latest available bundle version. * * This queries your configured update URL (or Capgo backend) to see if a newer bundle * is available for download. It does NOT download the bundle automatically. * * The response includes: * - `version`: The latest available version identifier * - `url`: Download URL for the bundle (if available) * - `breaking`: Whether this update is marked as incompatible (requires native app update) * - `message`: Optional message from the server * - `manifest`: File list for delta updates (if using multi-file downloads) * * After receiving the latest version info, you can: * 1. Compare it with your current version * 2. Download it using {@link download} * 3. Apply it using {@link next} or {@link set} * * **Important: Handling "no new version available"** * * When the device's current version matches the latest version on the server (i.e., the device is already * up-to-date), the server returns a 200 response with `error: "no_new_version_available"` and * `message: "No new version available"`. This is a normal, expected condition and resolves with * `kind: "up_to_date"` when the backend provides that classification. * * You should check `kind` and `error` before attempting to download: * * ```typescript * const latest = await CapacitorUpdater.getLatest(); * if (latest.kind === 'up_to_date') { * console.log('Already up to date'); * } else if (latest.kind === 'blocked') { * console.log('Update is blocked:', latest.error); * } else if (latest.url) { * // New version is available, proceed with download * } * ``` * * In this scenario, the server: * - Logs the request with a "No new version available" message * - Sends a "noNew" stat action to track that the device checked for updates but was already current (done on the backend) * * @param options Optional {@link GetLatestOptions} to specify which channel to check. * @returns {Promise<LatestVersion>} Information about the latest available bundle version. * @throws {Error} Throws for failed update checks or transport/request failures. * @since 4.0.0 */ getLatest(options?: GetLatestOptions): Promise<LatestVersion>; /** * Return the manifest entries that still need to be downloaded for a partial update. * * Pass the result from {@link getLatest} directly when it includes a `manifest`. * The native plugin compares each manifest entry with the files already available * in the builtin bundle and the local delta cache. Entries that can be reused are * omitted from the returned `missing` list. * * For encrypted manifests, pass the `sessionKey` returned by {@link getLatest} so * encrypted file hashes can be checked against local files. * * ```typescript * const latest = await CapacitorUpdater.getLatest(); * const missing = await CapacitorUpdater.getMissingBundleFiles(latest); * ``` * * @param options A {@link GetMissingBundleFilesOptions} object, or a {@link LatestVersion} response containing `manifest`. * @returns {Promise<GetMissingBundleFilesResult>} The manifest entries that require network download. * @throws {Error} If the manifest is missing or invalid. * @since 8.47.0 */ getMissingBundleFiles(options: GetMissingBundleFilesOptions): Promise<GetMissingBundleFilesResult>; /** * Estimate the download size for manifest entries before downloading them. * * This method sends the provided manifest entries to the Capgo update endpoint * once and reads the stored manifest `file_size` metadata. It does not perform * per-file `HEAD` requests from the app. * * Use this after {@link getMissingBundleFiles} to estimate only the files this * device still needs: * * ```typescript * const latest = await CapacitorUpdater.getLatest(); * const missing = await CapacitorUpdater.getMissingBundleFiles(latest); * const size = await CapacitorUpdater.getBundleDownloadSize({ * version: latest.version, * manifest: missing.missing, * }); * ``` * * @param options A {@link GetBundleDownloadSizeOptions} object containing manifest entries. * @returns {Promise<GetBundleDownloadSizeResult>} Known byte totals and per-file size results. * @throws {Error} If the manifest is missing or invalid. * @since 8.47.0 */ getBundleDownloadSize(options: GetBundleDownloadSizeOptions): Promise<GetBundleDownloadSizeResult>; /** * Assign this device to a specific update channel at runtime. * * Channels allow you to distribute different bundle versions to different groups of users * (e.g., "production", "beta", "staging"). This method switches the device to a new channel. * * **Requirements:** * - The target channel must allow self-assignment (configured in your Capgo dashboard or backend) * - The backend may accept or reject the request based on channel settings * * **When to use:** * - After the app is ready and the user has interacted (e.g., opted into beta program) * - To implement in-app channel switching (beta toggle, tester access, etc.) * - For user-driven channel changes * * **When NOT to use:** * - At app boot/initialization - use {@link PluginsConfig.CapacitorUpdater.defaultChannel} config instead * - Before user interaction * * **Important: Listen for the `channelPrivate` event** * * When a user attempts to set a channel that doesn't allow device self-assignment, the method will * throw an error AND fire a {@link addListener}('channelPrivate') event. You should listen to this event * to provide appropriate feedback to users: * * ```typescript * CapacitorUpdater.addListener('channelPrivate', (data) => { * console.warn(`Cannot access channel "${data.channel}": ${data.message}`); * // Show user-friendly message * }); * ``` * * This sends a request to the Capgo backend linking your device ID to the specified channel. * * @param options The {@link SetChannelOptions} containing the channel name and optional auto-update trigger. * @returns {Promise<ChannelRes>} Channel operation result with status and optional error/message. * @throws {Error} If the channel doesn't exist or doesn't allow self-assignment. * @since 4.7.0 */ setChannel(options: SetChannelOptions): Promise<ChannelRes>; /** * Remove the device's channel assignment and return to the default channel. * * This unlinks the device from any specifically assigned channel, causing it to fall back to: * - The {@link PluginsConfig.CapacitorUpdater.defaultChannel} if configured, or * - Your backend's default channel for this app * * Use this when: * - Users opt out of beta/testing programs * - You want to reset a device to standard update distribution * - Testing channel switching behavior * * @param options {@link UnsetChannelOptions} containing optional auto-update trigger. * @returns {Promise<void>} Resolves when the channel is successfully unset. * @throws {Error} If the operation fails. * @since 4.7.0 */ unsetChannel(options: UnsetChannelOptions): Promise<void>; /** * Get the current channel assigned to this device. * * Returns information about: * - `channel`: The currently assigned channel name (if any) * - `allowSet`: Whether the channel allows self-assignment * - `status`: Operation status * - `error`/`message`: Additional information (if applicable) * * Use this to: * - Display current channel to users (e.g., "You're on the Beta channel") * - Check if a device is on a specific channel before showing features * - Verify channel assignment after calling {@link setChannel} * * @returns {Promise<GetChannelRes>} The current channel information. * @throws {Error} If the operation fails. * @since 4.8.0 */ getChannel(): Promise<GetChannelRes>; /** * Get a list of all channels available for this device to self-assign to. * * Only returns channels where `allow_self_set` is `true`. These are channels that * users can switch to using {@link setChannel} without backend administrator intervention. * * Each channel includes: * - `id`: Unique channel identifier * - `name`: Human-readable channel name * - `public`: Whether the channel is publicly visible * - `allow_self_set`: Always `true` in results (filtered to only self-assignable channels) * * Use this to: * - Build a channel selector UI for users (e.g., "Join Beta" button) * - Show available testing/preview channels * - Implement channel discovery features * * @returns {Promise<ListChannelsResult>} List of channels the device can self-assign to. * @throws {Error} If the operation fails or the request to the backend fails. * @since 7.5.0 */ listChannels(): Promise<ListChannelsResult>; /** * Set a custom identifier for this device. * * This allows you to identify devices by your own custom ID (user ID, account ID, etc.) * instead of or in addition to the device's unique hardware ID. The custom ID is sent * to your update server and can be used for: * - Targeting specific users for updates * - Analytics and user tracking * - Debugging and support (correlating devices with users) * - A/B testing or feature flagging * * **Persistence:** * - When {@link PluginsConfig.CapacitorUpdater.persistCustomId} is `true`, the ID persists across app restarts * - When `false`, the ID is only kept for the current session * * **Clearing the custom ID:** * - Pass an empty string `""` to remove any stored custom ID * * @param options The {@link SetCustomIdOptions} containing the custom identifier string. * @returns {Promise<void>} Resolves immediately (synchronous operation). * @throws {Error} If the operation fails. * @since 4.9.0 */ setCustomId(options: SetCustomIdOptions): Promise<void>; /** * Get the builtin bundle version (the original version shipped with your native app). * * This returns the version of the bundle that was included when the app was installed * from the App Store or Play Store. This is NOT the currently active bundle version - * use {@link current} for that. * * Returns: * - The {@link PluginsConfig.CapacitorUpdater.version} config value if set, or * - The native app version from platform configs (package.json, Info.plist, build.gradle) * * Use this to: * - Display the "factory" version to users * - Compare against downloaded bundle versions * - Determine if any updates have been applied * - Debugging version mismatches * * @returns {Promise<BuiltinVersion>} The builtin bundle version string. * @since 5.2.0 */ getBuiltinVersion(): Promise<BuiltinVersion>; /** * Get the unique, privacy-friendly identifier for this device. * * This ID is used to identify the device when communicating with update servers. * It's automatically generated and stored securely by the plugin. * * **Privacy & Security characteristics:** * - Generated as a UUID (not based on hardware identifiers) * - Stored securely in platform-specific secure storage * - Android: Android Keystore (persists across app reinstalls on API 23+) * - iOS: Keychain with `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` * - Not synced to cloud (iOS) * - Follows Apple and Google privacy best practices * - Users can clear it via system settings (Android) or keychain access (iOS) * * **Persistence:** * The device ID persists across app reinstalls to maintain consistent device identity * for update tracking and analytics. * * Use this to: * - Debug update delivery issues (check what ID the server sees) * - Implement device-specific features * - Correlate server logs with specific devices * * @returns {Promise<DeviceId>} The unique device identifier string. * @throws {Error} If the operation fails. */ getDeviceId(): Promise<DeviceId>; /** * Get the version of the Capacitor Updater plugin installed in your app. * * This returns the version of the native plugin code (Android/iOS), which is sent * to the update server with each request. This is NOT your app version or bundle version. * * Use this to: * - Debug plugin-specific issues (when reporting bugs) * - Verify plugin installation and version * - Check compatibility with backend features * - Display in debug/about screens * * @returns {Promise<PluginVersion>} The Capacitor Updater plugin version string. * @throws {Error} If the operation fails. */ getPluginVersion(): Promise<PluginVersion>; /** * Check if automatic updates are currently enabled. * * Returns `true` if {@link PluginsConfig.CapacitorUpdater.autoUpdate} is enabled, * meaning the plugin will automatically check for, download, and apply updates. * * Returns `false` if in manual mode, where you control the update flow using * {@link getLatest}, {@link download}, {@link next}, and {@link set}. * * Use this to: * - Determine which update flow your app is using * - Show/hide manual update UI based on mode * - Debug update behavior * * @returns {Promise<AutoUpdateEnabled>} `true` if auto-update is enabled, `false` if in manual mode. * @throws {Error} If the operation fails. */ isAutoUpdateEnabled(): Promise<AutoUpdateEnabled>; /** * Remove all event listeners registered for this plugin. * * This unregisters all listeners added via {@link addListener} for all event types: * - `download` * - `noNeedUpdate` * - `updateCheckResult` * - `updateAvailable` * - `downloadComplete` * - `downloadFailed` * - `breakingAvailable` / `majorAvailable` * - `updateFailed` * - `appReloaded` * - `appReady` * * Use this during cleanup (e.g., when unmounting components or closing screens) * to prevent m