@capawesome/capacitor-live-update 8.4.4 → 8.6.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/README.md +95 -62
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +6 -2
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +1 -1
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePreferences.java +12 -14
- package/dist/docs.json +37 -37
- package/dist/esm/definitions.d.ts +50 -35
- package/dist/esm/definitions.js.map +1 -1
- package/electron/dist/plugin.mjs +213 -0
- package/ios/Plugin/LiveUpdatePlugin.swift +1 -1
- package/package.json +25 -5
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { ElectronPlugin } from '@capawesome/capacitor-electron/plugin';
|
|
2
|
+
import { LiveUpdateEngine } from '@capawesome/electron-live-update/engine';
|
|
3
|
+
import { app, powerMonitor } from 'electron';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
const AUTO_UPDATE_MIN_INTERVAL = 15 * 60 * 1000;
|
|
8
|
+
const CAPACITOR_RUNTIME = 'capacitor';
|
|
9
|
+
// Platform enum of the Capawesome Cloud API: 0 = Android, 1 = iOS, 2 = Electron.
|
|
10
|
+
const ELECTRON_PLATFORM = '2';
|
|
11
|
+
// The built file lives at `electron/dist/plugin.mjs`, so the package root is two levels up.
|
|
12
|
+
const PLUGIN_VERSION = createRequire(import.meta.url)('../../package.json').version;
|
|
13
|
+
class LiveUpdateElectron extends ElectronPlugin {
|
|
14
|
+
static __capacitorElectronPlugin = {
|
|
15
|
+
name: 'LiveUpdate',
|
|
16
|
+
methods: [
|
|
17
|
+
'clearBlockedBundles',
|
|
18
|
+
'deleteBundle',
|
|
19
|
+
'downloadBundle',
|
|
20
|
+
'fetchChannels',
|
|
21
|
+
'fetchLatestBundle',
|
|
22
|
+
'getBlockedBundles',
|
|
23
|
+
'getBundles',
|
|
24
|
+
'getChannel',
|
|
25
|
+
'getConfig',
|
|
26
|
+
'getCurrentBundle',
|
|
27
|
+
'getCustomId',
|
|
28
|
+
'getDeviceId',
|
|
29
|
+
'getDownloadedBundles',
|
|
30
|
+
'getNextBundle',
|
|
31
|
+
'getVersionCode',
|
|
32
|
+
'getVersionName',
|
|
33
|
+
'isSyncing',
|
|
34
|
+
'ready',
|
|
35
|
+
'reload',
|
|
36
|
+
'reset',
|
|
37
|
+
'resetConfig',
|
|
38
|
+
'setChannel',
|
|
39
|
+
'setConfig',
|
|
40
|
+
'setCustomId',
|
|
41
|
+
'setNextBundle',
|
|
42
|
+
'sync',
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
config;
|
|
46
|
+
lastAutoUpdateCheck = 0;
|
|
47
|
+
loadedEngine;
|
|
48
|
+
constructor(context) {
|
|
49
|
+
super(context);
|
|
50
|
+
this.config =
|
|
51
|
+
context.config.plugins?.LiveUpdate ?? {};
|
|
52
|
+
}
|
|
53
|
+
async load() {
|
|
54
|
+
// A failing live update must never prevent the app from booting.
|
|
55
|
+
try {
|
|
56
|
+
this.loadedEngine = this.createEngine();
|
|
57
|
+
await this.loadedEngine.initialize();
|
|
58
|
+
this.context.services.bundles.setActiveBundle(this.loadedEngine.getCurrentBundlePath());
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(`[LiveUpdate] Failed to load, serving the default bundle: ${error}`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (this.config.autoUpdateStrategy === 'background') {
|
|
65
|
+
this.setUpBackgroundAutoUpdate();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async clearBlockedBundles() {
|
|
69
|
+
return this.engine.clearBlockedBundles();
|
|
70
|
+
}
|
|
71
|
+
async deleteBundle(options) {
|
|
72
|
+
return this.engine.deleteBundle(options);
|
|
73
|
+
}
|
|
74
|
+
async downloadBundle(options) {
|
|
75
|
+
const { artifactType } = options;
|
|
76
|
+
if (artifactType === 'manifest') {
|
|
77
|
+
throw new Error('The manifest artifact type is not supported.');
|
|
78
|
+
}
|
|
79
|
+
return this.engine.downloadBundle({ ...options, artifactType });
|
|
80
|
+
}
|
|
81
|
+
async fetchChannels(options) {
|
|
82
|
+
return this.engine.fetchChannels(options);
|
|
83
|
+
}
|
|
84
|
+
async fetchLatestBundle(options) {
|
|
85
|
+
return this.engine.fetchLatestBundle(options);
|
|
86
|
+
}
|
|
87
|
+
async getBlockedBundles() {
|
|
88
|
+
return this.engine.getBlockedBundles();
|
|
89
|
+
}
|
|
90
|
+
async getBundles() {
|
|
91
|
+
return this.getDownloadedBundles();
|
|
92
|
+
}
|
|
93
|
+
async getChannel() {
|
|
94
|
+
return this.engine.getChannel();
|
|
95
|
+
}
|
|
96
|
+
async getConfig() {
|
|
97
|
+
const { appId } = await this.engine.getConfig();
|
|
98
|
+
return {
|
|
99
|
+
appId,
|
|
100
|
+
autoUpdateStrategy: this.config.autoUpdateStrategy ?? 'none',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
async getCurrentBundle() {
|
|
104
|
+
return this.engine.getCurrentBundle();
|
|
105
|
+
}
|
|
106
|
+
async getCustomId() {
|
|
107
|
+
return this.engine.getCustomId();
|
|
108
|
+
}
|
|
109
|
+
async getDeviceId() {
|
|
110
|
+
return this.engine.getDeviceId();
|
|
111
|
+
}
|
|
112
|
+
async getDownloadedBundles() {
|
|
113
|
+
return this.engine.getDownloadedBundles();
|
|
114
|
+
}
|
|
115
|
+
async getNextBundle() {
|
|
116
|
+
return this.engine.getNextBundle();
|
|
117
|
+
}
|
|
118
|
+
async getVersionCode() {
|
|
119
|
+
return this.engine.getVersionCode();
|
|
120
|
+
}
|
|
121
|
+
async getVersionName() {
|
|
122
|
+
return this.engine.getVersionName();
|
|
123
|
+
}
|
|
124
|
+
async isSyncing() {
|
|
125
|
+
return this.engine.isSyncing();
|
|
126
|
+
}
|
|
127
|
+
async ready() {
|
|
128
|
+
return this.engine.ready();
|
|
129
|
+
}
|
|
130
|
+
async reload() {
|
|
131
|
+
await this.engine.applyNextBundle();
|
|
132
|
+
this.reloadCurrentBundle();
|
|
133
|
+
}
|
|
134
|
+
async reset() {
|
|
135
|
+
return this.engine.reset();
|
|
136
|
+
}
|
|
137
|
+
async resetConfig() {
|
|
138
|
+
return this.engine.resetConfig();
|
|
139
|
+
}
|
|
140
|
+
async setChannel(options) {
|
|
141
|
+
return this.engine.setChannel(options);
|
|
142
|
+
}
|
|
143
|
+
async setConfig(options) {
|
|
144
|
+
return this.engine.setConfig(options);
|
|
145
|
+
}
|
|
146
|
+
async setCustomId(options) {
|
|
147
|
+
return this.engine.setCustomId(options);
|
|
148
|
+
}
|
|
149
|
+
async setNextBundle(options) {
|
|
150
|
+
return this.engine.setNextBundle(options);
|
|
151
|
+
}
|
|
152
|
+
async sync(options) {
|
|
153
|
+
return this.engine.sync(options);
|
|
154
|
+
}
|
|
155
|
+
get engine() {
|
|
156
|
+
if (!this.loadedEngine) {
|
|
157
|
+
throw new Error('LiveUpdate failed to load. See the logs for details.');
|
|
158
|
+
}
|
|
159
|
+
return this.loadedEngine;
|
|
160
|
+
}
|
|
161
|
+
createEngine() {
|
|
162
|
+
const engine = new LiveUpdateEngine({
|
|
163
|
+
appId: this.config.appId,
|
|
164
|
+
autoBlockRolledBackBundles: this.config.autoBlockRolledBackBundles,
|
|
165
|
+
autoDeleteBundles: this.config.autoDeleteBundles,
|
|
166
|
+
dataDirectory: join(app.getPath('userData'), 'capawesome-live-update'),
|
|
167
|
+
defaultChannel: this.config.defaultChannel,
|
|
168
|
+
httpTimeout: this.config.httpTimeout,
|
|
169
|
+
osVersion: process.getSystemVersion(),
|
|
170
|
+
platform: ELECTRON_PLATFORM,
|
|
171
|
+
pluginVersion: PLUGIN_VERSION,
|
|
172
|
+
publicKey: this.config.publicKey,
|
|
173
|
+
readyTimeout: this.config.readyTimeout,
|
|
174
|
+
runtime: CAPACITOR_RUNTIME,
|
|
175
|
+
serverDomain: this.config.serverDomain,
|
|
176
|
+
versionCode: app.getVersion(),
|
|
177
|
+
versionName: app.getVersion(),
|
|
178
|
+
});
|
|
179
|
+
engine.on('downloadBundleProgress', event => this.context.notifyListeners('downloadBundleProgress', event));
|
|
180
|
+
engine.on('nextBundleSet', event => this.context.notifyListeners('nextBundleSet', event));
|
|
181
|
+
engine.on('rolledBack', () => {
|
|
182
|
+
try {
|
|
183
|
+
this.reloadCurrentBundle();
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
console.error(`[LiveUpdate] Failed to apply rollback: ${error}`);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return engine;
|
|
190
|
+
}
|
|
191
|
+
reloadCurrentBundle() {
|
|
192
|
+
this.context.services.bundles.setActiveBundle(this.engine.getCurrentBundlePath());
|
|
193
|
+
// Retained so that the freshly reloaded page receives the event.
|
|
194
|
+
this.context.notifyListeners('reloaded', {}, { retain: true });
|
|
195
|
+
}
|
|
196
|
+
setUpBackgroundAutoUpdate() {
|
|
197
|
+
const check = () => {
|
|
198
|
+
const now = Date.now();
|
|
199
|
+
if (now - this.lastAutoUpdateCheck < AUTO_UPDATE_MIN_INTERVAL) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.lastAutoUpdateCheck = now;
|
|
203
|
+
void this.sync().catch(error => console.warn(`[LiveUpdate] Background sync failed: ${error}`));
|
|
204
|
+
};
|
|
205
|
+
void app.whenReady().then(() => {
|
|
206
|
+
check();
|
|
207
|
+
app.on('browser-window-focus', check);
|
|
208
|
+
powerMonitor.on('resume', check);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { LiveUpdateElectron };
|
|
@@ -8,7 +8,7 @@ import Capacitor
|
|
|
8
8
|
@objc(LiveUpdatePlugin)
|
|
9
9
|
public class LiveUpdatePlugin: CAPPlugin, CAPBridgedPlugin {
|
|
10
10
|
public static let tag = "LiveUpdate"
|
|
11
|
-
public static let version = "8.
|
|
11
|
+
public static let version = "8.6.0"
|
|
12
12
|
public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
|
|
13
13
|
|
|
14
14
|
public let identifier = "LiveUpdatePlugin"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capawesome/capacitor-live-update",
|
|
3
|
-
"version": "8.
|
|
4
|
-
"description": "Capacitor plugin to update your app remotely in real-time on Android and
|
|
3
|
+
"version": "8.6.0",
|
|
4
|
+
"description": "Capacitor plugin to update your app remotely in real-time on Android, iOS and Electron.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/esm/index.d.ts",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"android/src/main/",
|
|
11
11
|
"android/build.gradle",
|
|
12
12
|
"dist/",
|
|
13
|
+
"electron/dist/",
|
|
13
14
|
"ios/Plugin/",
|
|
14
15
|
"CapawesomeCapacitorLiveUpdate.podspec",
|
|
15
16
|
"Package.swift"
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"ionic",
|
|
42
43
|
"android",
|
|
43
44
|
"ios",
|
|
45
|
+
"electron",
|
|
44
46
|
"live update",
|
|
45
47
|
"remote update",
|
|
46
48
|
"ota",
|
|
@@ -60,36 +62,51 @@
|
|
|
60
62
|
"verify:web": "npm run build",
|
|
61
63
|
"e2e:android": "npm install --prefix example && npm run build && npm --prefix example run e2e:android",
|
|
62
64
|
"e2e:ios": "npm install --prefix example && npm run build && npm --prefix example run e2e:ios",
|
|
65
|
+
"e2e:electron": "npm install --prefix example && npm run build && npm --prefix example run e2e:electron",
|
|
63
66
|
"lint": "npm run version:check && npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
64
67
|
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
65
68
|
"eslint": "eslint . --ext ts",
|
|
66
69
|
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
67
70
|
"swiftlint": "node-swiftlint",
|
|
68
71
|
"docgen": "docgen --api LiveUpdatePlugin --output-readme README.md --output-json dist/docs.json",
|
|
69
|
-
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
70
|
-
"
|
|
72
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs && npm run build:electron",
|
|
73
|
+
"build:electron": "rollup -c electron/rollup.config.mjs",
|
|
74
|
+
"clean": "rimraf ./dist ./electron/dist",
|
|
71
75
|
"watch": "tsc --watch",
|
|
72
76
|
"version": "node scripts/sync-plugin-version.mjs",
|
|
73
77
|
"version:check": "node scripts/sync-plugin-version.mjs --check",
|
|
74
78
|
"ios:pod:install": "cd ios && pod install --repo-update && cd ..",
|
|
75
79
|
"prepublishOnly": "npm run build"
|
|
76
80
|
},
|
|
81
|
+
"dependencies": {
|
|
82
|
+
"@capawesome/electron-live-update": "^0.1.0"
|
|
83
|
+
},
|
|
77
84
|
"devDependencies": {
|
|
78
85
|
"@capacitor/android": "8.0.0",
|
|
79
86
|
"@capacitor/cli": "8.4.2",
|
|
80
87
|
"@capacitor/core": "8.0.0",
|
|
81
88
|
"@capacitor/docgen": "0.3.1",
|
|
82
89
|
"@capacitor/ios": "8.0.0",
|
|
90
|
+
"@capawesome/capacitor-electron": "0.2.0",
|
|
83
91
|
"@ionic/eslint-config": "0.4.0",
|
|
92
|
+
"@rollup/plugin-typescript": "12.3.0",
|
|
93
|
+
"electron": "44.5.1",
|
|
84
94
|
"eslint": "8.57.0",
|
|
85
95
|
"prettier-plugin-java": "2.9.7",
|
|
86
96
|
"rimraf": "6.1.2",
|
|
87
97
|
"rollup": "4.62.3",
|
|
88
98
|
"swiftlint": "2.0.0",
|
|
99
|
+
"tslib": "2.8.1",
|
|
89
100
|
"typescript": "5.9.3"
|
|
90
101
|
},
|
|
91
102
|
"peerDependencies": {
|
|
92
|
-
"@capacitor/core": ">=8.0.0"
|
|
103
|
+
"@capacitor/core": ">=8.0.0",
|
|
104
|
+
"@capawesome/capacitor-electron": ">=0.2.0"
|
|
105
|
+
},
|
|
106
|
+
"peerDependenciesMeta": {
|
|
107
|
+
"@capawesome/capacitor-electron": {
|
|
108
|
+
"optional": true
|
|
109
|
+
}
|
|
93
110
|
},
|
|
94
111
|
"eslintConfig": {
|
|
95
112
|
"extends": "@ionic/eslint-config/recommended"
|
|
@@ -100,6 +117,9 @@
|
|
|
100
117
|
},
|
|
101
118
|
"android": {
|
|
102
119
|
"src": "android"
|
|
120
|
+
},
|
|
121
|
+
"electron": {
|
|
122
|
+
"src": "electron"
|
|
103
123
|
}
|
|
104
124
|
}
|
|
105
125
|
}
|