native-update
Version:
Foundation package for building a comprehensive update system for Capacitor apps. Provides architecture and interfaces but requires backend implementation.
697 lines (696 loc) • 18.3 kB
TypeScript
/**
* Live Update Plugin Interface
*/
export interface LiveUpdatePlugin {
/**
* Sync with update server and apply updates if available
*/
sync(options?: SyncOptions): Promise<SyncResult>;
/**
* Download a specific bundle version
*/
download(options: DownloadOptions): Promise<BundleInfo>;
/**
* Set the active bundle
*/
set(bundle: BundleInfo): Promise<void>;
/**
* Reload the app with current bundle
*/
reload(): Promise<void>;
/**
* Reset to original bundle
*/
reset(): Promise<void>;
/**
* Get current bundle info
*/
current(): Promise<BundleInfo>;
/**
* List all downloaded bundles
*/
list(): Promise<BundleInfo[]>;
/**
* Delete bundles
*/
delete(options: DeleteOptions): Promise<void>;
/**
* Notify app is ready after update
*/
notifyAppReady(): Promise<void>;
/**
* Check for latest version
*/
getLatest(): Promise<LatestVersion>;
/**
* Switch update channel
*/
setChannel(channel: string): Promise<void>;
/**
* Set update server URL
*/
setUpdateUrl(url: string): Promise<void>;
/**
* Validate an update bundle
*/
validateUpdate(options: ValidateOptions): Promise<ValidationResult>;
}
/**
* App Update Plugin Interface
*/
export interface AppUpdatePlugin {
/**
* Get app update information
*/
getAppUpdateInfo(): Promise<AppUpdateInfo>;
/**
* Perform immediate update
*/
performImmediateUpdate(): Promise<void>;
/**
* Start flexible update
*/
startFlexibleUpdate(): Promise<void>;
/**
* Complete flexible update
*/
completeFlexibleUpdate(): Promise<void>;
/**
* Open app store page
*/
openAppStore(options?: OpenAppStoreOptions): Promise<void>;
}
/**
* App Review Plugin Interface
*/
export interface AppReviewPlugin {
/**
* Request in-app review
*/
requestReview(): Promise<ReviewResult>;
/**
* Check if review can be requested
*/
canRequestReview(): Promise<CanRequestReviewResult>;
}
/**
* Background Update Plugin Interface
*/
export interface BackgroundUpdatePlugin {
/**
* Enable background update checking
*/
enableBackgroundUpdates(config: BackgroundUpdateConfig): Promise<void>;
/**
* Disable background update checking
*/
disableBackgroundUpdates(): Promise<void>;
/**
* Get current background update status
*/
getBackgroundUpdateStatus(): Promise<BackgroundUpdateStatus>;
/**
* Schedule background update check with specific interval
*/
scheduleBackgroundCheck(interval: number): Promise<void>;
/**
* Manually trigger background update check
*/
triggerBackgroundCheck(): Promise<BackgroundCheckResult>;
/**
* Configure notification preferences
*/
setNotificationPreferences(preferences: NotificationPreferences): Promise<void>;
/**
* Get notification permissions status
*/
getNotificationPermissions(): Promise<NotificationPermissionStatus>;
/**
* Request notification permissions
*/
requestNotificationPermissions(): Promise<boolean>;
}
/**
* Combined plugin interface
*/
export interface NativeUpdateCombinedPlugin extends LiveUpdatePlugin, AppUpdatePlugin, AppReviewPlugin, BackgroundUpdatePlugin {
/**
* Configure the plugin with initial settings
*/
configure(config: UpdateConfig | {
config: PluginInitConfig;
}): Promise<void>;
/**
* Get current security configuration
*/
getSecurityInfo(): Promise<SecurityInfo>;
}
/**
* Configuration Types
*/
export interface PluginConfig {
serverUrl?: string;
channel?: string;
autoCheck?: boolean;
autoUpdate?: boolean;
updateStrategy?: UpdateStrategy;
publicKey?: string;
requireSignature?: boolean;
checksumAlgorithm?: ChecksumAlgorithm;
checkInterval?: number;
security?: SecurityConfig;
}
export interface UpdateConfig {
liveUpdate?: LiveUpdateConfig;
appUpdate?: AppUpdateConfig;
appReview?: AppReviewConfig;
backgroundUpdate?: BackgroundUpdateConfig;
security?: SecurityConfig;
}
export interface LiveUpdateConfig {
appId: string;
serverUrl: string;
channel?: string;
autoUpdate?: boolean;
updateStrategy?: UpdateStrategy;
publicKey?: string;
requireSignature?: boolean;
checksumAlgorithm?: ChecksumAlgorithm;
checkInterval?: number;
allowEmulator?: boolean;
mandatoryInstallMode?: InstallMode;
optionalInstallMode?: InstallMode;
maxBundleSize?: number;
allowedHosts?: string[];
}
export interface AppUpdateConfig {
minimumVersion?: string;
updatePriority?: number;
storeUrl?: {
android?: string;
ios?: string;
};
checkOnAppStart?: boolean;
allowDowngrade?: boolean;
}
export interface AppReviewConfig {
minimumDaysSinceInstall?: number;
minimumDaysSinceLastPrompt?: number;
minimumLaunchCount?: number;
customTriggers?: string[];
debugMode?: boolean;
}
export interface BackgroundUpdateConfig {
enabled: boolean;
checkInterval: number;
updateTypes: BackgroundUpdateType[];
autoInstall?: boolean;
notificationPreferences?: NotificationPreferences;
respectBatteryOptimization?: boolean;
allowMeteredConnection?: boolean;
minimumBatteryLevel?: number;
requireWifi?: boolean;
maxRetries?: number;
retryDelay?: number;
taskIdentifier?: string;
}
export interface SecurityConfig {
enforceHttps?: boolean;
certificatePinning?: CertificatePinning;
validateInputs?: boolean;
secureStorage?: boolean;
logSecurityEvents?: boolean;
}
export interface CertificatePinning {
enabled: boolean;
pins: CertificatePin[];
}
export interface CertificatePin {
hostname: string;
sha256: string[];
}
/**
* Live Update Types
*/
export interface SyncOptions {
channel?: string;
updateMode?: UpdateMode;
}
export interface SyncResult {
status: SyncStatus;
version?: string;
description?: string;
mandatory?: boolean;
error?: UpdateError;
}
export interface DownloadOptions {
url: string;
version: string;
checksum: string;
signature?: string;
maxRetries?: number;
timeout?: number;
}
export interface BundleInfo {
bundleId: string;
version: string;
path: string;
downloadTime: number;
size: number;
status: BundleStatus;
checksum: string;
signature?: string;
verified: boolean;
metadata?: Record<string, unknown>;
}
export interface DeleteOptions {
bundleId?: string;
keepVersions?: number;
olderThan?: number;
}
export interface UpdateOptions {
allowDowngrade?: boolean;
cleanupOldBundles?: boolean;
keepBundleCount?: number;
}
export interface LatestVersion {
available: boolean;
version?: string;
url?: string;
mandatory?: boolean;
notes?: string;
size?: number;
}
export interface ValidateOptions {
bundlePath: string;
checksum: string;
signature?: string;
maxSize?: number;
}
export interface ValidationResult {
isValid: boolean;
error?: string;
details?: {
checksumValid?: boolean;
signatureValid?: boolean;
sizeValid?: boolean;
versionValid?: boolean;
};
}
/**
* App Update Types
*/
export interface AppUpdateInfo {
updateAvailable: boolean;
currentVersion: string;
availableVersion?: string;
updatePriority?: number;
immediateUpdateAllowed?: boolean;
flexibleUpdateAllowed?: boolean;
clientVersionStalenessDays?: number;
installStatus?: InstallStatus;
bytesDownloaded?: number;
totalBytesToDownload?: number;
}
export interface OpenAppStoreOptions {
appId?: string;
}
/**
* App Review Types
*/
export interface ReviewResult {
displayed: boolean;
error?: string;
reason?: string;
}
export interface CanRequestReviewResult {
canRequest: boolean;
reason?: string;
}
/**
* Background Update Types
*/
export interface BackgroundUpdateStatus {
enabled: boolean;
lastCheckTime?: number;
nextCheckTime?: number;
lastUpdateTime?: number;
currentTaskId?: string;
isRunning: boolean;
checkCount: number;
failureCount: number;
lastError?: UpdateError;
}
export interface BackgroundCheckResult {
success: boolean;
updatesFound: boolean;
appUpdate?: AppUpdateInfo;
liveUpdate?: LatestVersion;
notificationSent: boolean;
error?: UpdateError;
}
export interface NotificationPreferences {
title?: string;
description?: string;
iconName?: string;
soundEnabled?: boolean;
vibrationEnabled?: boolean;
showActions?: boolean;
actionLabels?: {
updateNow?: string;
updateLater?: string;
dismiss?: string;
};
channelId?: string;
channelName?: string;
priority?: NotificationPriority;
}
export interface NotificationPermissionStatus {
granted: boolean;
canRequest: boolean;
shouldShowRationale?: boolean;
}
/**
* Security Types
*/
export interface SecurityInfo {
enforceHttps: boolean;
certificatePinning: CertificatePinning;
validateInputs: boolean;
secureStorage: boolean;
}
/**
* Error Types
*/
export interface UpdateError {
code: UpdateErrorCode;
message: string;
details?: unknown;
}
/**
* Enums
*/
export declare enum BackgroundUpdateType {
APP_UPDATE = "app_update",
LIVE_UPDATE = "live_update",
BOTH = "both"
}
export declare enum NotificationPriority {
MIN = "min",
LOW = "low",
DEFAULT = "default",
HIGH = "high",
MAX = "max"
}
export declare enum UpdateStrategy {
IMMEDIATE = "immediate",
BACKGROUND = "background",
MANUAL = "manual"
}
export declare enum UpdateMode {
IMMEDIATE = "immediate",
ON_NEXT_RESTART = "on_next_restart",
ON_NEXT_RESUME = "on_next_resume"
}
export declare enum InstallMode {
IMMEDIATE = "immediate",
ON_NEXT_RESTART = "on_next_restart",
ON_NEXT_RESUME = "on_next_resume"
}
export declare enum ChecksumAlgorithm {
SHA256 = "SHA-256",
SHA512 = "SHA-512"
}
export declare enum SyncStatus {
UP_TO_DATE = "UP_TO_DATE",
UPDATE_AVAILABLE = "UPDATE_AVAILABLE",
UPDATE_INSTALLED = "UPDATE_INSTALLED",
ERROR = "ERROR"
}
export declare enum BundleStatus {
PENDING = "PENDING",
DOWNLOADING = "DOWNLOADING",
READY = "READY",
ACTIVE = "ACTIVE",
FAILED = "FAILED"
}
export declare enum InstallStatus {
UNKNOWN = "UNKNOWN",
PENDING = "PENDING",
DOWNLOADING = "DOWNLOADING",
DOWNLOADED = "DOWNLOADED",
INSTALLING = "INSTALLING",
INSTALLED = "INSTALLED",
FAILED = "FAILED",
CANCELED = "CANCELED"
}
export declare enum UpdateErrorCode {
NETWORK_ERROR = "NETWORK_ERROR",
SERVER_ERROR = "SERVER_ERROR",
TIMEOUT_ERROR = "TIMEOUT_ERROR",
DOWNLOAD_ERROR = "DOWNLOAD_ERROR",
STORAGE_ERROR = "STORAGE_ERROR",
SIZE_LIMIT_EXCEEDED = "SIZE_LIMIT_EXCEEDED",
VERIFICATION_ERROR = "VERIFICATION_ERROR",
CHECKSUM_ERROR = "CHECKSUM_ERROR",
SIGNATURE_ERROR = "SIGNATURE_ERROR",
INSECURE_URL = "INSECURE_URL",
INVALID_CERTIFICATE = "INVALID_CERTIFICATE",
PATH_TRAVERSAL = "PATH_TRAVERSAL",
INSTALL_ERROR = "INSTALL_ERROR",
ROLLBACK_ERROR = "ROLLBACK_ERROR",
VERSION_MISMATCH = "VERSION_MISMATCH",
PERMISSION_DENIED = "PERMISSION_DENIED",
UPDATE_NOT_AVAILABLE = "UPDATE_NOT_AVAILABLE",
UPDATE_IN_PROGRESS = "UPDATE_IN_PROGRESS",
UPDATE_CANCELLED = "UPDATE_CANCELLED",
PLATFORM_NOT_SUPPORTED = "PLATFORM_NOT_SUPPORTED",
REVIEW_NOT_SUPPORTED = "REVIEW_NOT_SUPPORTED",
QUOTA_EXCEEDED = "QUOTA_EXCEEDED",
CONDITIONS_NOT_MET = "CONDITIONS_NOT_MET",
INVALID_CONFIG = "INVALID_CONFIG",
UNKNOWN_ERROR = "UNKNOWN_ERROR"
}
/**
* Event Types
*/
export interface DownloadProgressEvent {
percent: number;
bytesDownloaded: number;
totalBytes: number;
bundleId: string;
}
export interface UpdateStateChangedEvent {
status: BundleStatus;
bundleId: string;
version: string;
}
export interface BackgroundUpdateProgressEvent {
type: BackgroundUpdateType;
status: 'checking' | 'downloading' | 'installing' | 'completed' | 'failed';
percent?: number;
error?: UpdateError;
}
export interface BackgroundUpdateNotificationEvent {
type: BackgroundUpdateType;
updateAvailable: boolean;
version?: string;
action?: 'shown' | 'tapped' | 'dismissed';
}
/**
* App Update Events
*/
export interface AppUpdateStateChangedEvent {
status: InstallStatus;
installErrorCode?: number;
}
export interface AppUpdateProgressEvent {
percent: number;
bytesDownloaded: number;
totalBytes: number;
}
export interface AppUpdateAvailableEvent {
currentVersion: string;
availableVersion: string;
updatePriority: number;
updateSize?: number;
releaseNotes?: string[];
storeUrl?: string;
}
export interface AppUpdateReadyEvent {
message: string;
}
export interface AppUpdateFailedEvent {
error: string;
code: string;
}
export interface AppUpdateNotificationClickedEvent {
}
export interface AppUpdateInstallClickedEvent {
}
/**
* Plugin Events
*/
export interface PluginListenerHandle {
remove: () => Promise<void>;
}
export interface NativeUpdateListeners {
/**
* Listen for download progress
*/
addListener(eventName: 'downloadProgress', listenerFunc: (event: DownloadProgressEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for update state changes
*/
addListener(eventName: 'updateStateChanged', listenerFunc: (event: UpdateStateChangedEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for background update progress
*/
addListener(eventName: 'backgroundUpdateProgress', listenerFunc: (event: BackgroundUpdateProgressEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for background update notifications
*/
addListener(eventName: 'backgroundUpdateNotification', listenerFunc: (event: BackgroundUpdateNotificationEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update state changes
*/
addListener(eventName: 'appUpdateStateChanged', listenerFunc: (event: AppUpdateStateChangedEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update progress
*/
addListener(eventName: 'appUpdateProgress', listenerFunc: (event: AppUpdateProgressEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update available
*/
addListener(eventName: 'appUpdateAvailable', listenerFunc: (event: AppUpdateAvailableEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update ready
*/
addListener(eventName: 'appUpdateReady', listenerFunc: (event: AppUpdateReadyEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update failed
*/
addListener(eventName: 'appUpdateFailed', listenerFunc: (event: AppUpdateFailedEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update notification clicked
*/
addListener(eventName: 'appUpdateNotificationClicked', listenerFunc: (event: AppUpdateNotificationClickedEvent) => void): Promise<PluginListenerHandle>;
/**
* Listen for app update install clicked
*/
addListener(eventName: 'appUpdateInstallClicked', listenerFunc: (event: AppUpdateInstallClickedEvent) => void): Promise<PluginListenerHandle>;
/**
* Remove all listeners
*/
removeAllListeners(): Promise<void>;
}
/**
* Plugin initialization configuration options
*/
export interface PluginInitConfig {
/**
* Capacitor Filesystem instance (required)
*/
filesystem?: typeof import('@capacitor/filesystem').Filesystem;
/**
* Capacitor Preferences instance (required)
*/
preferences?: typeof import('@capacitor/preferences').Preferences;
/**
* Base URL for update server
*/
baseUrl?: string;
/**
* List of allowed hosts for security
*/
allowedHosts?: string[];
/**
* Maximum bundle size in bytes (default: 100MB)
*/
maxBundleSize?: number;
/**
* Download timeout in milliseconds (default: 30000)
*/
downloadTimeout?: number;
/**
* Number of retry attempts for failed downloads (default: 3)
*/
retryAttempts?: number;
/**
* Delay between retry attempts in milliseconds (default: 1000)
*/
retryDelay?: number;
/**
* Enable bundle signature validation (default: true)
*/
enableSignatureValidation?: boolean;
/**
* Public key for signature validation
*/
publicKey?: string;
/**
* Cache expiration time in milliseconds (default: 24 hours)
*/
cacheExpiration?: number;
/**
* Enable debug logging (default: false)
*/
enableLogging?: boolean;
/**
* Server URL for update checks
*/
serverUrl?: string;
/**
* Update channel
*/
channel?: string;
/**
* Enable automatic update checking
*/
autoCheck?: boolean;
/**
* Enable automatic updates
*/
autoUpdate?: boolean;
/**
* Update strategy
*/
updateStrategy?: UpdateStrategy;
/**
* Require bundle signatures
*/
requireSignature?: boolean;
/**
* Checksum algorithm to use
*/
checksumAlgorithm?: ChecksumAlgorithm;
/**
* Update check interval in milliseconds
*/
checkInterval?: number;
/**
* Security configuration
*/
security?: SecurityConfig;
}
/**
* Main plugin interface with initialization
*/
export interface NativeUpdatePlugin extends NativeUpdateCombinedPlugin, NativeUpdateListeners {
/**
* Initialize the plugin with configuration
*/
initialize(config: PluginInitConfig): Promise<void>;
/**
* Check if plugin is initialized
*/
isInitialized(): boolean;
/**
* Reset plugin state
*/
reset(): Promise<void>;
/**
* Clean up resources
*/
cleanup(): Promise<void>;
}