native-update 1.0.0
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/CapacitorNativeUpdate.podspec +18 -0
- package/LICENSE +21 -0
- package/Readme.md +451 -0
- package/android/build.gradle +92 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/android/gradle.properties +17 -0
- package/android/proguard-rules.pro +29 -0
- package/android/settings.gradle +2 -0
- package/android/src/main/AndroidManifest.xml +34 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/AppReviewPlugin.kt +153 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/AppUpdatePlugin.kt +275 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +390 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateManager.kt +46 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdatePlugin.kt +333 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateWorker.kt +251 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/CapacitorNativeUpdatePlugin.kt +265 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +526 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/NotificationActionReceiver.kt +99 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/SecurityManager.kt +249 -0
- package/dist/esm/__tests__/bundle-manager.test.d.ts +1 -0
- package/dist/esm/__tests__/bundle-manager.test.js +123 -0
- package/dist/esm/__tests__/bundle-manager.test.js.map +1 -0
- package/dist/esm/__tests__/config.test.d.ts +1 -0
- package/dist/esm/__tests__/config.test.js +69 -0
- package/dist/esm/__tests__/config.test.js.map +1 -0
- package/dist/esm/__tests__/integration.test.d.ts +1 -0
- package/dist/esm/__tests__/integration.test.js +78 -0
- package/dist/esm/__tests__/integration.test.js.map +1 -0
- package/dist/esm/__tests__/security.test.d.ts +1 -0
- package/dist/esm/__tests__/security.test.js +54 -0
- package/dist/esm/__tests__/security.test.js.map +1 -0
- package/dist/esm/__tests__/version-manager.test.d.ts +1 -0
- package/dist/esm/__tests__/version-manager.test.js +45 -0
- package/dist/esm/__tests__/version-manager.test.js.map +1 -0
- package/dist/esm/app-review/app-review-manager.d.ts +24 -0
- package/dist/esm/app-review/app-review-manager.js +195 -0
- package/dist/esm/app-review/app-review-manager.js.map +1 -0
- package/dist/esm/app-review/index.d.ts +5 -0
- package/dist/esm/app-review/index.js +6 -0
- package/dist/esm/app-review/index.js.map +1 -0
- package/dist/esm/app-review/platform-review-handler.d.ts +20 -0
- package/dist/esm/app-review/platform-review-handler.js +138 -0
- package/dist/esm/app-review/platform-review-handler.js.map +1 -0
- package/dist/esm/app-review/review-conditions-checker.d.ts +22 -0
- package/dist/esm/app-review/review-conditions-checker.js +155 -0
- package/dist/esm/app-review/review-conditions-checker.js.map +1 -0
- package/dist/esm/app-review/review-rate-limiter.d.ts +23 -0
- package/dist/esm/app-review/review-rate-limiter.js +164 -0
- package/dist/esm/app-review/review-rate-limiter.js.map +1 -0
- package/dist/esm/app-review/types.d.ts +41 -0
- package/dist/esm/app-review/types.js +2 -0
- package/dist/esm/app-review/types.js.map +1 -0
- package/dist/esm/app-update/app-update-checker.d.ts +13 -0
- package/dist/esm/app-update/app-update-checker.js +104 -0
- package/dist/esm/app-update/app-update-checker.js.map +1 -0
- package/dist/esm/app-update/app-update-installer.d.ts +19 -0
- package/dist/esm/app-update/app-update-installer.js +123 -0
- package/dist/esm/app-update/app-update-installer.js.map +1 -0
- package/dist/esm/app-update/app-update-manager.d.ts +28 -0
- package/dist/esm/app-update/app-update-manager.js +199 -0
- package/dist/esm/app-update/app-update-manager.js.map +1 -0
- package/dist/esm/app-update/app-update-notifier.d.ts +14 -0
- package/dist/esm/app-update/app-update-notifier.js +100 -0
- package/dist/esm/app-update/app-update-notifier.js.map +1 -0
- package/dist/esm/app-update/index.d.ts +6 -0
- package/dist/esm/app-update/index.js +7 -0
- package/dist/esm/app-update/index.js.map +1 -0
- package/dist/esm/app-update/platform-app-update.d.ts +19 -0
- package/dist/esm/app-update/platform-app-update.js +129 -0
- package/dist/esm/app-update/platform-app-update.js.map +1 -0
- package/dist/esm/app-update/types.d.ts +58 -0
- package/dist/esm/app-update/types.js +12 -0
- package/dist/esm/app-update/types.js.map +1 -0
- package/dist/esm/background-update/background-scheduler.d.ts +17 -0
- package/dist/esm/background-update/background-scheduler.js +195 -0
- package/dist/esm/background-update/background-scheduler.js.map +1 -0
- package/dist/esm/background-update/index.d.ts +3 -0
- package/dist/esm/background-update/index.js +3 -0
- package/dist/esm/background-update/index.js.map +1 -0
- package/dist/esm/background-update/notification-manager.d.ts +29 -0
- package/dist/esm/background-update/notification-manager.js +89 -0
- package/dist/esm/background-update/notification-manager.js.map +1 -0
- package/dist/esm/core/analytics.d.ts +70 -0
- package/dist/esm/core/analytics.js +137 -0
- package/dist/esm/core/analytics.js.map +1 -0
- package/dist/esm/core/cache-manager.d.ts +72 -0
- package/dist/esm/core/cache-manager.js +275 -0
- package/dist/esm/core/cache-manager.js.map +1 -0
- package/dist/esm/core/config.d.ts +48 -0
- package/dist/esm/core/config.js +83 -0
- package/dist/esm/core/config.js.map +1 -0
- package/dist/esm/core/errors.d.ts +51 -0
- package/dist/esm/core/errors.js +80 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/logger.d.ts +21 -0
- package/dist/esm/core/logger.js +109 -0
- package/dist/esm/core/logger.js.map +1 -0
- package/dist/esm/core/performance.d.ts +53 -0
- package/dist/esm/core/performance.js +140 -0
- package/dist/esm/core/performance.js.map +1 -0
- package/dist/esm/core/plugin-manager.d.ts +66 -0
- package/dist/esm/core/plugin-manager.js +148 -0
- package/dist/esm/core/plugin-manager.js.map +1 -0
- package/dist/esm/core/security.d.ts +93 -0
- package/dist/esm/core/security.js +315 -0
- package/dist/esm/core/security.js.map +1 -0
- package/dist/esm/definitions.d.ts +639 -0
- package/dist/esm/definitions.js +103 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/live-update/bundle-manager.d.ts +94 -0
- package/dist/esm/live-update/bundle-manager.js +310 -0
- package/dist/esm/live-update/bundle-manager.js.map +1 -0
- package/dist/esm/live-update/certificate-pinning.d.ts +38 -0
- package/dist/esm/live-update/certificate-pinning.js +78 -0
- package/dist/esm/live-update/certificate-pinning.js.map +1 -0
- package/dist/esm/live-update/download-manager.d.ts +67 -0
- package/dist/esm/live-update/download-manager.js +319 -0
- package/dist/esm/live-update/download-manager.js.map +1 -0
- package/dist/esm/live-update/update-manager.d.ts +52 -0
- package/dist/esm/live-update/update-manager.js +294 -0
- package/dist/esm/live-update/update-manager.js.map +1 -0
- package/dist/esm/live-update/version-manager.d.ts +84 -0
- package/dist/esm/live-update/version-manager.js +335 -0
- package/dist/esm/live-update/version-manager.js.map +1 -0
- package/dist/esm/plugin.d.ts +6 -0
- package/dist/esm/plugin.js +283 -0
- package/dist/esm/plugin.js.map +1 -0
- package/dist/esm/security/crypto.d.ts +25 -0
- package/dist/esm/security/crypto.js +70 -0
- package/dist/esm/security/crypto.js.map +1 -0
- package/dist/esm/security/validator.d.ts +60 -0
- package/dist/esm/security/validator.js +143 -0
- package/dist/esm/security/validator.js.map +1 -0
- package/dist/esm/web.d.ts +74 -0
- package/dist/esm/web.js +595 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +2 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.esm.js +2 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -0
- package/docs/APP_REVIEW_GUIDE.md +768 -0
- package/docs/BUNDLE_SIGNING.md +264 -0
- package/docs/LIVE_UPDATES_GUIDE.md +650 -0
- package/docs/MIGRATION.md +192 -0
- package/docs/NATIVE_UPDATES_GUIDE.md +694 -0
- package/docs/QUICK_START.md +606 -0
- package/docs/README.md +111 -0
- package/docs/REMAINING_FEATURES.md +139 -0
- package/docs/api/app-review-api.md +259 -0
- package/docs/api/app-update-api.md +238 -0
- package/docs/api/events-api.md +451 -0
- package/docs/api/live-update-api.md +265 -0
- package/docs/background-updates.md +392 -0
- package/docs/examples/advanced-scenarios.md +410 -0
- package/docs/examples/basic-usage.md +185 -0
- package/docs/features/app-reviews.md +975 -0
- package/docs/features/app-updates.md +785 -0
- package/docs/features/live-updates.md +633 -0
- package/docs/getting-started/configuration.md +468 -0
- package/docs/getting-started/installation.md +209 -0
- package/docs/getting-started/quick-start.md +379 -0
- package/docs/guides/deployment-guide.md +333 -0
- package/docs/guides/migration-from-codepush.md +142 -0
- package/docs/guides/security-best-practices.md +1057 -0
- package/docs/guides/testing-guide.md +373 -0
- package/docs/production-readiness.md +478 -0
- package/docs/security/certificate-pinning.md +122 -0
- package/docs/server-requirements.md +147 -0
- package/ios/Plugin/AppReview/AppReviewPlugin.swift +158 -0
- package/ios/Plugin/AppUpdate/AppUpdatePlugin.swift +234 -0
- package/ios/Plugin/BackgroundUpdate/BackgroundNotificationManager.swift +329 -0
- package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +396 -0
- package/ios/Plugin/CapacitorNativeUpdatePlugin.m +45 -0
- package/ios/Plugin/CapacitorNativeUpdatePlugin.swift +190 -0
- package/ios/Plugin/Info.plist +43 -0
- package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +689 -0
- package/ios/Plugin/LiveUpdate/WebViewConfiguration.swift +45 -0
- package/ios/Plugin/Security/SecurityManager.swift +289 -0
- package/package.json +90 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PluginConfig } from '../core/config';
|
|
2
|
+
import { ReviewMetrics } from './types';
|
|
3
|
+
import { CanRequestReviewResult } from '../definitions';
|
|
4
|
+
export declare class ReviewRateLimiter {
|
|
5
|
+
private config;
|
|
6
|
+
private logger;
|
|
7
|
+
private storageKey;
|
|
8
|
+
private readonly IOS_MAX_PROMPTS_PER_YEAR;
|
|
9
|
+
private readonly ANDROID_MIN_DAYS_BETWEEN;
|
|
10
|
+
private readonly DEFAULT_MIN_DAYS_BETWEEN;
|
|
11
|
+
constructor(config: PluginConfig);
|
|
12
|
+
canRequestReview(): Promise<CanRequestReviewResult>;
|
|
13
|
+
recordRequest(wasDisplayed?: boolean): Promise<void>;
|
|
14
|
+
reset(): Promise<void>;
|
|
15
|
+
getMetrics(): Promise<ReviewMetrics>;
|
|
16
|
+
private getRateLimitData;
|
|
17
|
+
private saveRateLimitData;
|
|
18
|
+
private getDaysSince;
|
|
19
|
+
private getMinDaysBetweenPrompts;
|
|
20
|
+
private getPlatform;
|
|
21
|
+
private getCurrentVersion;
|
|
22
|
+
private getInstallDate;
|
|
23
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Logger } from '../core/logger';
|
|
2
|
+
export class ReviewRateLimiter {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.storageKey = 'cap_review_rate_limit';
|
|
5
|
+
// Platform-specific limits
|
|
6
|
+
this.IOS_MAX_PROMPTS_PER_YEAR = 3;
|
|
7
|
+
this.ANDROID_MIN_DAYS_BETWEEN = 30; // Recommended
|
|
8
|
+
this.DEFAULT_MIN_DAYS_BETWEEN = 90;
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.logger = new Logger('ReviewRateLimiter');
|
|
11
|
+
}
|
|
12
|
+
async canRequestReview() {
|
|
13
|
+
const data = await this.getRateLimitData();
|
|
14
|
+
const platform = this.getPlatform();
|
|
15
|
+
// Check last request date
|
|
16
|
+
if (data.lastRequestDate) {
|
|
17
|
+
const daysSinceLastRequest = this.getDaysSince(data.lastRequestDate);
|
|
18
|
+
const minDays = this.getMinDaysBetweenPrompts(platform);
|
|
19
|
+
if (daysSinceLastRequest < minDays) {
|
|
20
|
+
return {
|
|
21
|
+
canRequest: false,
|
|
22
|
+
reason: `Only ${daysSinceLastRequest} days since last prompt, need ${minDays}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// iOS-specific: Check yearly limit
|
|
27
|
+
if (platform === 'ios') {
|
|
28
|
+
const currentYear = new Date().getFullYear().toString();
|
|
29
|
+
const requestsThisYear = data.requestsByYear[currentYear] || 0;
|
|
30
|
+
if (requestsThisYear >= this.IOS_MAX_PROMPTS_PER_YEAR) {
|
|
31
|
+
return {
|
|
32
|
+
canRequest: false,
|
|
33
|
+
reason: `iOS limit reached: ${requestsThisYear}/${this.IOS_MAX_PROMPTS_PER_YEAR} prompts this year`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Check version-specific limits
|
|
38
|
+
const currentVersion = await this.getCurrentVersion();
|
|
39
|
+
const requestsThisVersion = data.requestsByVersion[currentVersion] || 0;
|
|
40
|
+
const maxPerVersion = this.config.maxPromptsPerVersion || 1;
|
|
41
|
+
if (requestsThisVersion >= maxPerVersion) {
|
|
42
|
+
return {
|
|
43
|
+
canRequest: false,
|
|
44
|
+
reason: `Version limit reached: ${requestsThisVersion}/${maxPerVersion} prompts for v${currentVersion}`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
canRequest: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async recordRequest(wasDisplayed = true) {
|
|
52
|
+
const data = await this.getRateLimitData();
|
|
53
|
+
const currentVersion = await this.getCurrentVersion();
|
|
54
|
+
const currentYear = new Date().getFullYear().toString();
|
|
55
|
+
// Update counters
|
|
56
|
+
data.totalRequests++;
|
|
57
|
+
data.lastRequestDate = Date.now();
|
|
58
|
+
if (wasDisplayed) {
|
|
59
|
+
data.successfulDisplays++;
|
|
60
|
+
}
|
|
61
|
+
// Update version-specific count
|
|
62
|
+
if (!data.requestsByVersion[currentVersion]) {
|
|
63
|
+
data.requestsByVersion[currentVersion] = 0;
|
|
64
|
+
}
|
|
65
|
+
data.requestsByVersion[currentVersion]++;
|
|
66
|
+
// Update year-specific count (for iOS)
|
|
67
|
+
if (!data.requestsByYear[currentYear]) {
|
|
68
|
+
data.requestsByYear[currentYear] = 0;
|
|
69
|
+
}
|
|
70
|
+
data.requestsByYear[currentYear]++;
|
|
71
|
+
await this.saveRateLimitData(data);
|
|
72
|
+
this.logger.log('Recorded review request', {
|
|
73
|
+
total: data.totalRequests,
|
|
74
|
+
version: currentVersion,
|
|
75
|
+
year: currentYear,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async reset() {
|
|
79
|
+
await this.saveRateLimitData({
|
|
80
|
+
totalRequests: 0,
|
|
81
|
+
successfulDisplays: 0,
|
|
82
|
+
requestsByVersion: {},
|
|
83
|
+
requestsByYear: {},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async getMetrics() {
|
|
87
|
+
const data = await this.getRateLimitData();
|
|
88
|
+
const installDate = await this.getInstallDate();
|
|
89
|
+
return {
|
|
90
|
+
totalRequests: data.totalRequests,
|
|
91
|
+
successfulDisplays: data.successfulDisplays,
|
|
92
|
+
lastRequestDate: data.lastRequestDate
|
|
93
|
+
? new Date(data.lastRequestDate)
|
|
94
|
+
: undefined,
|
|
95
|
+
requestsByVersion: data.requestsByVersion,
|
|
96
|
+
significantEvents: [], // This would come from conditions checker
|
|
97
|
+
appLaunches: 0, // This would come from conditions checker
|
|
98
|
+
installDate: new Date(installDate),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async getRateLimitData() {
|
|
102
|
+
try {
|
|
103
|
+
const stored = localStorage.getItem(this.storageKey);
|
|
104
|
+
if (stored) {
|
|
105
|
+
return JSON.parse(stored);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
this.logger.error('Failed to read rate limit data', error);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
totalRequests: 0,
|
|
113
|
+
successfulDisplays: 0,
|
|
114
|
+
requestsByVersion: {},
|
|
115
|
+
requestsByYear: {},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async saveRateLimitData(data) {
|
|
119
|
+
try {
|
|
120
|
+
localStorage.setItem(this.storageKey, JSON.stringify(data));
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
this.logger.error('Failed to save rate limit data', error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
getDaysSince(timestamp) {
|
|
127
|
+
const msPerDay = 24 * 60 * 60 * 1000;
|
|
128
|
+
return Math.floor((Date.now() - timestamp) / msPerDay);
|
|
129
|
+
}
|
|
130
|
+
getMinDaysBetweenPrompts(platform) {
|
|
131
|
+
if (platform === 'android') {
|
|
132
|
+
return (this.config.minimumDaysSinceLastPrompt || this.ANDROID_MIN_DAYS_BETWEEN);
|
|
133
|
+
}
|
|
134
|
+
return (this.config.minimumDaysSinceLastPrompt || this.DEFAULT_MIN_DAYS_BETWEEN);
|
|
135
|
+
}
|
|
136
|
+
getPlatform() {
|
|
137
|
+
if (typeof window !== 'undefined') {
|
|
138
|
+
const userAgent = window.navigator.userAgent;
|
|
139
|
+
if (/android/i.test(userAgent)) {
|
|
140
|
+
return 'android';
|
|
141
|
+
}
|
|
142
|
+
else if (/iPad|iPhone|iPod/.test(userAgent)) {
|
|
143
|
+
return 'ios';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return 'web';
|
|
147
|
+
}
|
|
148
|
+
async getCurrentVersion() {
|
|
149
|
+
// This would be provided by the platform
|
|
150
|
+
return '1.0.0';
|
|
151
|
+
}
|
|
152
|
+
async getInstallDate() {
|
|
153
|
+
// This would be stored on first app launch
|
|
154
|
+
const installKey = 'cap_app_install_date';
|
|
155
|
+
const stored = localStorage.getItem(installKey);
|
|
156
|
+
if (stored) {
|
|
157
|
+
return parseInt(stored, 10);
|
|
158
|
+
}
|
|
159
|
+
const now = Date.now();
|
|
160
|
+
localStorage.setItem(installKey, now.toString());
|
|
161
|
+
return now;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=review-rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-rate-limiter.js","sourceRoot":"","sources":["../../../src/app-review/review-rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface ReviewRequestResult {
|
|
2
|
+
displayed: boolean;
|
|
3
|
+
reason?: string;
|
|
4
|
+
platform: string;
|
|
5
|
+
lastRequestDate?: number;
|
|
6
|
+
requestCount?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ReviewAvailability {
|
|
9
|
+
canRequest: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
lastRequestDate?: number;
|
|
12
|
+
requestCount?: number;
|
|
13
|
+
daysUntilNext?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ReviewConditions {
|
|
16
|
+
minimumDaysSinceInstall?: number;
|
|
17
|
+
minimumDaysSinceLastPrompt?: number;
|
|
18
|
+
minimumAppLaunches?: number;
|
|
19
|
+
minimumSignificantEvents?: number;
|
|
20
|
+
requirePositiveEvents?: boolean;
|
|
21
|
+
maxPromptsPerVersion?: number;
|
|
22
|
+
customConditions?: Record<string, any>;
|
|
23
|
+
}
|
|
24
|
+
export interface StoreReviewUrl {
|
|
25
|
+
url: string;
|
|
26
|
+
platform: 'ios' | 'android' | 'web';
|
|
27
|
+
}
|
|
28
|
+
export interface ReviewRequestOptions {
|
|
29
|
+
force?: boolean;
|
|
30
|
+
useCustomUI?: boolean;
|
|
31
|
+
customMessage?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ReviewMetrics {
|
|
34
|
+
totalRequests: number;
|
|
35
|
+
successfulDisplays: number;
|
|
36
|
+
lastRequestDate?: Date;
|
|
37
|
+
requestsByVersion: Record<string, number>;
|
|
38
|
+
significantEvents: string[];
|
|
39
|
+
appLaunches: number;
|
|
40
|
+
installDate: Date;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/app-review/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PluginConfig } from '../core/config';
|
|
2
|
+
import { AppUpdateInfo, AppUpdateOptions } from './types';
|
|
3
|
+
export declare class AppUpdateChecker {
|
|
4
|
+
private config;
|
|
5
|
+
private logger;
|
|
6
|
+
constructor(config: PluginConfig);
|
|
7
|
+
checkServerVersion(_?: AppUpdateOptions): Promise<Partial<AppUpdateInfo>>;
|
|
8
|
+
compareVersions(version1: string, version2: string): number;
|
|
9
|
+
isUpdateRequired(currentVersion: string, availableVersion: string, minimumVersion?: string): boolean;
|
|
10
|
+
determineUpdatePriority(versionDiff: string, stalenessDays?: number): number;
|
|
11
|
+
private getCurrentVersion;
|
|
12
|
+
private getPlatform;
|
|
13
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Logger } from '../core/logger';
|
|
2
|
+
export class AppUpdateChecker {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
this.logger = new Logger('AppUpdateChecker');
|
|
6
|
+
}
|
|
7
|
+
async checkServerVersion(_) {
|
|
8
|
+
if (!this.config.updateUrl) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const url = new URL(`${this.config.updateUrl}/app-version`);
|
|
13
|
+
url.searchParams.append('platform', this.getPlatform());
|
|
14
|
+
url.searchParams.append('current', await this.getCurrentVersion());
|
|
15
|
+
if (this.config.channel) {
|
|
16
|
+
url.searchParams.append('channel', this.config.channel);
|
|
17
|
+
}
|
|
18
|
+
const response = await fetch(url.toString(), {
|
|
19
|
+
method: 'GET',
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
'X-App-Version': await this.getCurrentVersion(),
|
|
23
|
+
'X-App-Platform': this.getPlatform(),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`Server returned ${response.status}`);
|
|
28
|
+
}
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
return {
|
|
31
|
+
availableVersion: data.version,
|
|
32
|
+
updatePriority: data.priority,
|
|
33
|
+
releaseNotes: data.releaseNotes,
|
|
34
|
+
updateSize: data.size,
|
|
35
|
+
updateURL: data.downloadUrl,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
this.logger.error('Failed to check server version', error);
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
compareVersions(version1, version2) {
|
|
44
|
+
const v1Parts = version1.split('.').map(Number);
|
|
45
|
+
const v2Parts = version2.split('.').map(Number);
|
|
46
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
47
|
+
const v1Part = v1Parts[i] || 0;
|
|
48
|
+
const v2Part = v2Parts[i] || 0;
|
|
49
|
+
if (v1Part > v2Part)
|
|
50
|
+
return 1;
|
|
51
|
+
if (v1Part < v2Part)
|
|
52
|
+
return -1;
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
isUpdateRequired(currentVersion, availableVersion, minimumVersion) {
|
|
57
|
+
// Check if current version is less than available
|
|
58
|
+
if (this.compareVersions(currentVersion, availableVersion) < 0) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
// Check if current version meets minimum requirement
|
|
62
|
+
if (minimumVersion &&
|
|
63
|
+
this.compareVersions(currentVersion, minimumVersion) < 0) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
determineUpdatePriority(versionDiff, stalenessDays) {
|
|
69
|
+
// Parse version difference
|
|
70
|
+
const [major, minor] = versionDiff.split('.').map(Number);
|
|
71
|
+
// Major version change = IMMEDIATE (priority 5)
|
|
72
|
+
if (major > 0) {
|
|
73
|
+
return 5;
|
|
74
|
+
}
|
|
75
|
+
// Minor version with high staleness = HIGH (priority 4)
|
|
76
|
+
if (minor > 0 && stalenessDays && stalenessDays > 30) {
|
|
77
|
+
return 4;
|
|
78
|
+
}
|
|
79
|
+
// Minor version = MEDIUM (priority 3)
|
|
80
|
+
if (minor > 0) {
|
|
81
|
+
return 3;
|
|
82
|
+
}
|
|
83
|
+
// Patch version = LOW (priority 1)
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
async getCurrentVersion() {
|
|
87
|
+
// This would be implemented by the native platform
|
|
88
|
+
return '1.0.0';
|
|
89
|
+
}
|
|
90
|
+
getPlatform() {
|
|
91
|
+
// Detect platform
|
|
92
|
+
if (typeof window !== 'undefined') {
|
|
93
|
+
const userAgent = window.navigator.userAgent;
|
|
94
|
+
if (/android/i.test(userAgent)) {
|
|
95
|
+
return 'android';
|
|
96
|
+
}
|
|
97
|
+
else if (/iPad|iPhone|iPod/.test(userAgent)) {
|
|
98
|
+
return 'ios';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return 'web';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=app-update-checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-update-checker.js","sourceRoot":"","sources":["../../../src/app-update/app-update-checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PluginConfig } from '../core/config';
|
|
2
|
+
import { AppUpdateProgress, AppUpdateState } from './types';
|
|
3
|
+
export declare class AppUpdateInstaller {
|
|
4
|
+
private logger;
|
|
5
|
+
private progressCallback?;
|
|
6
|
+
private currentState;
|
|
7
|
+
constructor(_: PluginConfig);
|
|
8
|
+
startImmediateUpdate(): Promise<void>;
|
|
9
|
+
startFlexibleUpdate(): Promise<void>;
|
|
10
|
+
completeFlexibleUpdate(): Promise<void>;
|
|
11
|
+
cancelUpdate(): Promise<void>;
|
|
12
|
+
getInstallState(): Promise<AppUpdateState>;
|
|
13
|
+
onProgress(callback: (progress: AppUpdateProgress) => void): void;
|
|
14
|
+
private updateState;
|
|
15
|
+
private simulateFlexibleUpdate;
|
|
16
|
+
private isAndroid;
|
|
17
|
+
private isIOS;
|
|
18
|
+
private isWeb;
|
|
19
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Logger } from '../core/logger';
|
|
2
|
+
import { AppUpdateInstallStatus, } from './types';
|
|
3
|
+
export class AppUpdateInstaller {
|
|
4
|
+
constructor(_) {
|
|
5
|
+
// config parameter is kept for compatibility but not used
|
|
6
|
+
this.logger = new Logger('AppUpdateInstaller');
|
|
7
|
+
this.currentState = {
|
|
8
|
+
installStatus: AppUpdateInstallStatus.UNKNOWN,
|
|
9
|
+
packageName: '',
|
|
10
|
+
availableVersion: '',
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
async startImmediateUpdate() {
|
|
14
|
+
this.logger.log('Starting immediate update installation');
|
|
15
|
+
// Update state
|
|
16
|
+
this.updateState(AppUpdateInstallStatus.PENDING);
|
|
17
|
+
// On Android, this would trigger Play Core immediate update
|
|
18
|
+
// On iOS, this would open App Store
|
|
19
|
+
if (this.isAndroid()) {
|
|
20
|
+
// Android implementation would use Play Core Library
|
|
21
|
+
this.logger.log('Triggering Android immediate update');
|
|
22
|
+
}
|
|
23
|
+
else if (this.isIOS()) {
|
|
24
|
+
// iOS implementation would open App Store
|
|
25
|
+
this.logger.log('Opening iOS App Store for update');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Web fallback
|
|
29
|
+
throw new Error('Immediate updates not supported on web platform');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async startFlexibleUpdate() {
|
|
33
|
+
this.logger.log('Starting flexible update download');
|
|
34
|
+
// Update state
|
|
35
|
+
this.updateState(AppUpdateInstallStatus.DOWNLOADING);
|
|
36
|
+
// Start download simulation for web
|
|
37
|
+
if (this.isWeb()) {
|
|
38
|
+
this.simulateFlexibleUpdate();
|
|
39
|
+
}
|
|
40
|
+
else if (this.isAndroid()) {
|
|
41
|
+
// Android implementation would use Play Core Library
|
|
42
|
+
this.logger.log('Starting Android flexible update');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// iOS doesn't support flexible updates
|
|
46
|
+
throw new Error('Flexible updates not supported on iOS');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async completeFlexibleUpdate() {
|
|
50
|
+
this.logger.log('Completing flexible update installation');
|
|
51
|
+
if (this.currentState.installStatus !== AppUpdateInstallStatus.DOWNLOADED) {
|
|
52
|
+
throw new Error('Update not ready for installation');
|
|
53
|
+
}
|
|
54
|
+
// Update state
|
|
55
|
+
this.updateState(AppUpdateInstallStatus.INSTALLING);
|
|
56
|
+
// Trigger installation
|
|
57
|
+
if (this.isAndroid()) {
|
|
58
|
+
// Android implementation would complete the update
|
|
59
|
+
this.logger.log('Completing Android update installation');
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Simulate completion
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
this.updateState(AppUpdateInstallStatus.INSTALLED);
|
|
65
|
+
}, 1000);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async cancelUpdate() {
|
|
69
|
+
this.logger.log('Cancelling update');
|
|
70
|
+
if (this.currentState.installStatus === AppUpdateInstallStatus.DOWNLOADING) {
|
|
71
|
+
this.updateState(AppUpdateInstallStatus.CANCELED);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async getInstallState() {
|
|
75
|
+
return Object.assign({}, this.currentState);
|
|
76
|
+
}
|
|
77
|
+
onProgress(callback) {
|
|
78
|
+
this.progressCallback = callback;
|
|
79
|
+
}
|
|
80
|
+
updateState(status, errorCode) {
|
|
81
|
+
this.currentState.installStatus = status;
|
|
82
|
+
if (errorCode !== undefined) {
|
|
83
|
+
this.currentState.installErrorCode = errorCode;
|
|
84
|
+
}
|
|
85
|
+
this.logger.log('Update state changed', this.currentState);
|
|
86
|
+
}
|
|
87
|
+
simulateFlexibleUpdate() {
|
|
88
|
+
// Simulate download progress for web platform
|
|
89
|
+
let downloaded = 0;
|
|
90
|
+
const totalSize = 50 * 1024 * 1024; // 50MB
|
|
91
|
+
const chunkSize = 1024 * 1024; // 1MB per tick
|
|
92
|
+
const interval = setInterval(() => {
|
|
93
|
+
downloaded += chunkSize;
|
|
94
|
+
if (downloaded >= totalSize) {
|
|
95
|
+
downloaded = totalSize;
|
|
96
|
+
clearInterval(interval);
|
|
97
|
+
this.updateState(AppUpdateInstallStatus.DOWNLOADED);
|
|
98
|
+
}
|
|
99
|
+
const progress = {
|
|
100
|
+
bytesDownloaded: downloaded,
|
|
101
|
+
totalBytesToDownload: totalSize,
|
|
102
|
+
percentComplete: Math.round((downloaded / totalSize) * 100),
|
|
103
|
+
downloadSpeed: chunkSize, // 1MB/s
|
|
104
|
+
estimatedTime: Math.ceil((totalSize - downloaded) / chunkSize),
|
|
105
|
+
};
|
|
106
|
+
if (this.progressCallback) {
|
|
107
|
+
this.progressCallback(progress);
|
|
108
|
+
}
|
|
109
|
+
}, 1000);
|
|
110
|
+
}
|
|
111
|
+
isAndroid() {
|
|
112
|
+
return (typeof window !== 'undefined' &&
|
|
113
|
+
/android/i.test(window.navigator.userAgent));
|
|
114
|
+
}
|
|
115
|
+
isIOS() {
|
|
116
|
+
return (typeof window !== 'undefined' &&
|
|
117
|
+
/iPad|iPhone|iPod/.test(window.navigator.userAgent));
|
|
118
|
+
}
|
|
119
|
+
isWeb() {
|
|
120
|
+
return !this.isAndroid() && !this.isIOS();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=app-update-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-update-installer.js","sourceRoot":"","sources":["../../../src/app-update/app-update-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PluginConfig } from '../core/config';
|
|
2
|
+
import { AppUpdateInfo, AppUpdateOptions, VersionInfo, MinimumVersionCheck, AppUpdateState } from './types';
|
|
3
|
+
import { AppUpdatePlugin } from '../definitions';
|
|
4
|
+
import { PluginListenerHandle } from '@capacitor/core';
|
|
5
|
+
export declare class AppUpdateManager implements AppUpdatePlugin {
|
|
6
|
+
private config;
|
|
7
|
+
private logger;
|
|
8
|
+
private checker;
|
|
9
|
+
private installer;
|
|
10
|
+
private platformUpdate;
|
|
11
|
+
private listeners;
|
|
12
|
+
constructor(config: PluginConfig);
|
|
13
|
+
checkAppUpdate(options?: AppUpdateOptions): Promise<AppUpdateInfo>;
|
|
14
|
+
startImmediateUpdate(): Promise<void>;
|
|
15
|
+
startFlexibleUpdate(): Promise<void>;
|
|
16
|
+
completeFlexibleUpdate(): Promise<void>;
|
|
17
|
+
getVersionInfo(): Promise<VersionInfo>;
|
|
18
|
+
isMinimumVersionMet(): Promise<MinimumVersionCheck>;
|
|
19
|
+
getAppUpdateInfo(): Promise<AppUpdateInfo>;
|
|
20
|
+
performImmediateUpdate(): Promise<void>;
|
|
21
|
+
openAppStore(_options?: import('../definitions').OpenAppStoreOptions): Promise<void>;
|
|
22
|
+
private getAppStoreUrl;
|
|
23
|
+
getUpdateInstallState(): Promise<AppUpdateState>;
|
|
24
|
+
addListener(eventName: string, listenerFunc: (data: any) => void): PluginListenerHandle;
|
|
25
|
+
removeAllListeners(eventName?: string): Promise<void>;
|
|
26
|
+
private emit;
|
|
27
|
+
private mergeUpdateInfo;
|
|
28
|
+
}
|