@otakit/capacitor-updater 2.0.1 → 2.1.1
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/{UpdatekitUpdater.podspec → OtaKitUpdater.podspec} +1 -1
- package/README.md +165 -130
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/BundleInfo.java +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/BundleStatus.java +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/BundleStore.java +38 -9
- package/android/src/main/java/com/{updatekit → otakit}/updater/DateUtils.java +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/DeviceEventClient.java +3 -4
- package/android/src/main/java/com/{updatekit → otakit}/updater/HashUtils.java +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/HostedManifestKeys.java +1 -1
- package/android/src/main/java/com/{updatekit → otakit}/updater/ManifestClient.java +32 -15
- package/android/src/main/java/com/{updatekit → otakit}/updater/ManifestVerifier.java +1 -1
- package/android/src/main/java/com/otakit/updater/UpdaterCoordinator.java +726 -0
- package/android/src/main/java/com/otakit/updater/UpdaterPlugin.java +1191 -0
- package/android/src/main/java/com/{updatekit → otakit}/updater/ZipUtils.java +1 -1
- package/dist/esm/definitions.d.ts +48 -105
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -60
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +7 -11
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +8 -14
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +14 -74
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +14 -74
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/UpdaterPlugin/BundleStore.swift +28 -6
- package/ios/Sources/UpdaterPlugin/Downloader.swift +1 -1
- package/ios/Sources/UpdaterPlugin/ManifestClient.swift +8 -4
- package/ios/Sources/UpdaterPlugin/UpdaterCoordinator.swift +635 -0
- package/ios/Sources/UpdaterPlugin/UpdaterPlugin.m +3 -5
- package/ios/Sources/UpdaterPlugin/UpdaterPlugin.swift +506 -551
- package/package.json +2 -2
- package/android/src/main/java/com/updatekit/updater/UpdaterPlugin.java +0 -1191
package/dist/plugin.js
CHANGED
|
@@ -34,73 +34,19 @@ var capacitorUpdater = (function (exports, core) {
|
|
|
34
34
|
function normalizeNullable(value) {
|
|
35
35
|
return isEmptyObject(value) ? null : value;
|
|
36
36
|
}
|
|
37
|
-
function toPublicState(value) {
|
|
38
|
-
return {
|
|
39
|
-
current: value.current,
|
|
40
|
-
staged: value.staged,
|
|
41
|
-
builtinVersion: value.builtinVersion,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
async function getState() {
|
|
45
|
-
return toPublicState(await NativeOtaKit.debugGetState());
|
|
46
|
-
}
|
|
47
|
-
async function check() {
|
|
48
|
-
return normalizeNullable(await NativeOtaKit.check());
|
|
49
|
-
}
|
|
50
|
-
async function download() {
|
|
51
|
-
return normalizeNullable(await NativeOtaKit.download());
|
|
52
|
-
}
|
|
53
|
-
function apply() {
|
|
54
|
-
return NativeOtaKit.apply();
|
|
55
|
-
}
|
|
56
|
-
async function update() {
|
|
57
|
-
const state = await getState();
|
|
58
|
-
let latest;
|
|
59
|
-
try {
|
|
60
|
-
latest = await check();
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
if (state.staged) {
|
|
64
|
-
await apply();
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
if (latest) {
|
|
70
|
-
if (latest.downloaded) {
|
|
71
|
-
await apply();
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const bundle = await download();
|
|
75
|
-
if (bundle) {
|
|
76
|
-
await apply();
|
|
77
|
-
}
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (state.staged) {
|
|
81
|
-
await apply();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
37
|
const OtaKit = {
|
|
85
|
-
getState,
|
|
86
|
-
check,
|
|
87
|
-
download,
|
|
88
|
-
apply,
|
|
89
|
-
update,
|
|
38
|
+
getState: () => NativeOtaKit.getState(),
|
|
39
|
+
check: () => NativeOtaKit.check(),
|
|
40
|
+
download: () => NativeOtaKit.download(),
|
|
41
|
+
apply: () => NativeOtaKit.apply(),
|
|
42
|
+
update: () => NativeOtaKit.update(),
|
|
90
43
|
notifyAppReady: () => NativeOtaKit.notifyAppReady(),
|
|
91
|
-
|
|
92
|
-
reset: () => NativeOtaKit.debugReset(),
|
|
93
|
-
listBundles: () => NativeOtaKit.debugListBundles(),
|
|
94
|
-
deleteBundle: (options) => NativeOtaKit.debugDeleteBundle(options),
|
|
95
|
-
getLastFailure: async () => normalizeNullable(await NativeOtaKit.debugGetLastFailure()),
|
|
96
|
-
},
|
|
97
|
-
addListener: NativeOtaKit.addListener.bind(NativeOtaKit),
|
|
98
|
-
removeAllListeners: () => NativeOtaKit.removeAllListeners(),
|
|
44
|
+
getLastFailure: async () => normalizeNullable(await NativeOtaKit.getLastFailure()),
|
|
99
45
|
};
|
|
100
46
|
|
|
101
47
|
/**
|
|
102
48
|
* Web implementation of the native bridge.
|
|
103
|
-
* Most methods are no-ops since OTA updates don't apply to web
|
|
49
|
+
* Most methods are no-ops since OTA updates don't apply to web.
|
|
104
50
|
*/
|
|
105
51
|
class OtaKitWeb extends core.WebPlugin {
|
|
106
52
|
BUILTIN_BUNDLE = {
|
|
@@ -108,7 +54,7 @@ var capacitorUpdater = (function (exports, core) {
|
|
|
108
54
|
version: '0.0.0',
|
|
109
55
|
status: 'builtin',
|
|
110
56
|
};
|
|
111
|
-
async
|
|
57
|
+
async getState() {
|
|
112
58
|
return {
|
|
113
59
|
current: this.BUILTIN_BUNDLE,
|
|
114
60
|
fallback: this.BUILTIN_BUNDLE,
|
|
@@ -118,29 +64,23 @@ var capacitorUpdater = (function (exports, core) {
|
|
|
118
64
|
}
|
|
119
65
|
async check() {
|
|
120
66
|
console.warn('OtaKit.check() is not supported on web');
|
|
121
|
-
return
|
|
67
|
+
return { kind: 'no_update' };
|
|
122
68
|
}
|
|
123
69
|
async download() {
|
|
124
70
|
console.warn('OtaKit.download() is not supported on web');
|
|
125
|
-
return
|
|
71
|
+
return { kind: 'no_update' };
|
|
126
72
|
}
|
|
127
73
|
async apply() {
|
|
128
74
|
console.warn('OtaKit.apply() is not supported on web');
|
|
129
75
|
throw new Error('OtaKit.apply() is not supported on web');
|
|
130
76
|
}
|
|
77
|
+
async update() {
|
|
78
|
+
await this.download();
|
|
79
|
+
}
|
|
131
80
|
async notifyAppReady() {
|
|
132
81
|
// No-op on web, but don't warn - apps should call this unconditionally
|
|
133
82
|
}
|
|
134
|
-
async
|
|
135
|
-
console.warn('OtaKit.debug.reset() is not supported on web');
|
|
136
|
-
}
|
|
137
|
-
async debugListBundles() {
|
|
138
|
-
return { bundles: [] };
|
|
139
|
-
}
|
|
140
|
-
async debugDeleteBundle(_options) {
|
|
141
|
-
console.warn('OtaKit.debug.deleteBundle() is not supported on web');
|
|
142
|
-
}
|
|
143
|
-
async debugGetLastFailure() {
|
|
83
|
+
async getLastFailure() {
|
|
144
84
|
return null;
|
|
145
85
|
}
|
|
146
86
|
}
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * Bundle status enum.\n */\nexport var BundleStatus;\n(function (BundleStatus) {\n /** Factory-installed bundle */\n BundleStatus[\"BUILTIN\"] = \"builtin\";\n /** Downloaded and staged, awaiting activation */\n BundleStatus[\"PENDING\"] = \"pending\";\n /** Active but not yet confirmed */\n BundleStatus[\"TRIAL\"] = \"trial\";\n /** Confirmed working */\n BundleStatus[\"SUCCESS\"] = \"success\";\n /** Failed (hash mismatch, extraction error, rollback) */\n BundleStatus[\"ERROR\"] = \"error\";\n})(BundleStatus || (BundleStatus = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst NativeOtaKit = registerPlugin('OtaKit', {\n web: () => import('./web').then((m) => new m.OtaKitWeb()),\n});\n/**\n * Check if result is an empty object (iOS returns {} instead of null)\n */\nfunction isEmptyObject(obj) {\n return obj !== null && typeof obj === 'object' && Object.keys(obj).length === 0;\n}\n/**\n * Wrapped plugin that normalizes null returns from native code.\n * iOS call.resolve() without arguments returns {} instead of null.\n */\nfunction normalizeNullable(value) {\n return isEmptyObject(value) ? null : value;\n}\
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * Bundle status enum.\n */\nexport var BundleStatus;\n(function (BundleStatus) {\n /** Factory-installed bundle */\n BundleStatus[\"BUILTIN\"] = \"builtin\";\n /** Downloaded and staged, awaiting activation */\n BundleStatus[\"PENDING\"] = \"pending\";\n /** Active but not yet confirmed */\n BundleStatus[\"TRIAL\"] = \"trial\";\n /** Confirmed working */\n BundleStatus[\"SUCCESS\"] = \"success\";\n /** Failed (hash mismatch, extraction error, rollback) */\n BundleStatus[\"ERROR\"] = \"error\";\n})(BundleStatus || (BundleStatus = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst NativeOtaKit = registerPlugin('OtaKit', {\n web: () => import('./web').then((m) => new m.OtaKitWeb()),\n});\n/**\n * Check if result is an empty object (iOS returns {} instead of null)\n */\nfunction isEmptyObject(obj) {\n return obj !== null && typeof obj === 'object' && Object.keys(obj).length === 0;\n}\n/**\n * Wrapped plugin that normalizes null returns from native code.\n * iOS call.resolve() without arguments returns {} instead of null.\n */\nfunction normalizeNullable(value) {\n return isEmptyObject(value) ? null : value;\n}\nconst OtaKit = {\n getState: () => NativeOtaKit.getState(),\n check: () => NativeOtaKit.check(),\n download: () => NativeOtaKit.download(),\n apply: () => NativeOtaKit.apply(),\n update: () => NativeOtaKit.update(),\n notifyAppReady: () => NativeOtaKit.notifyAppReady(),\n getLastFailure: async () => normalizeNullable(await NativeOtaKit.getLastFailure()),\n};\nexport * from './definitions';\nexport { OtaKit };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/**\n * Web implementation of the native bridge.\n * Most methods are no-ops since OTA updates don't apply to web.\n */\nexport class OtaKitWeb extends WebPlugin {\n BUILTIN_BUNDLE = {\n id: 'builtin',\n version: '0.0.0',\n status: 'builtin',\n };\n async getState() {\n return {\n current: this.BUILTIN_BUNDLE,\n fallback: this.BUILTIN_BUNDLE,\n staged: null,\n builtinVersion: this.BUILTIN_BUNDLE.version,\n };\n }\n async check() {\n console.warn('OtaKit.check() is not supported on web');\n return { kind: 'no_update' };\n }\n async download() {\n console.warn('OtaKit.download() is not supported on web');\n return { kind: 'no_update' };\n }\n async apply() {\n console.warn('OtaKit.apply() is not supported on web');\n throw new Error('OtaKit.apply() is not supported on web');\n }\n async update() {\n await this.download();\n }\n async notifyAppReady() {\n // No-op on web, but don't warn - apps should call this unconditionally\n }\n async getLastFailure() {\n return null;\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BundleStatus","registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -5,7 +5,8 @@ final class BundleStore {
|
|
|
5
5
|
static let currentBundleId = "otakit_current_bundle_id"
|
|
6
6
|
static let fallbackBundleId = "otakit_fallback_bundle_id"
|
|
7
7
|
static let stagedBundleId = "otakit_staged_bundle_id"
|
|
8
|
-
static let
|
|
8
|
+
static let lastFailedBundleInfo = "otakit_last_failed_bundle_info"
|
|
9
|
+
static let lastResolvedRuntimeKey = "otakit_last_resolved_runtime_key"
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
private let defaults = UserDefaults.standard
|
|
@@ -142,6 +143,10 @@ final class BundleStore {
|
|
|
142
143
|
return bundle
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
func getCurrentBundleId() -> String? {
|
|
147
|
+
defaults.string(forKey: Keys.currentBundleId)
|
|
148
|
+
}
|
|
149
|
+
|
|
145
150
|
func setCurrentBundleId(_ id: String?) {
|
|
146
151
|
if let id {
|
|
147
152
|
defaults.set(id, forKey: Keys.currentBundleId)
|
|
@@ -160,6 +165,10 @@ final class BundleStore {
|
|
|
160
165
|
return bundle
|
|
161
166
|
}
|
|
162
167
|
|
|
168
|
+
func getFallbackBundleId() -> String? {
|
|
169
|
+
defaults.string(forKey: Keys.fallbackBundleId)
|
|
170
|
+
}
|
|
171
|
+
|
|
163
172
|
func setFallbackBundleId(_ id: String?) {
|
|
164
173
|
if let id {
|
|
165
174
|
defaults.set(id, forKey: Keys.fallbackBundleId)
|
|
@@ -180,23 +189,36 @@ final class BundleStore {
|
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
191
|
|
|
183
|
-
func
|
|
192
|
+
func setLastFailedBundle(_ bundle: BundleInfo?) {
|
|
184
193
|
if let bundle {
|
|
185
194
|
if let data = try? encoder.encode(bundle) {
|
|
186
|
-
defaults.set(data, forKey: Keys.
|
|
195
|
+
defaults.set(data, forKey: Keys.lastFailedBundleInfo)
|
|
187
196
|
}
|
|
188
197
|
} else {
|
|
189
|
-
defaults.removeObject(forKey: Keys.
|
|
198
|
+
defaults.removeObject(forKey: Keys.lastFailedBundleInfo)
|
|
190
199
|
}
|
|
191
200
|
}
|
|
192
201
|
|
|
193
|
-
func
|
|
194
|
-
guard let data = defaults.data(forKey: Keys.
|
|
202
|
+
func getLastFailedBundle() -> BundleInfo? {
|
|
203
|
+
guard let data = defaults.data(forKey: Keys.lastFailedBundleInfo) else {
|
|
195
204
|
return nil
|
|
196
205
|
}
|
|
197
206
|
return try? decoder.decode(BundleInfo.self, from: data)
|
|
198
207
|
}
|
|
199
208
|
|
|
209
|
+
func getLastResolvedRuntimeKey() -> String? {
|
|
210
|
+
defaults.string(forKey: Keys.lastResolvedRuntimeKey)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
func setLastResolvedRuntimeKey(_ runtimeKey: String?) {
|
|
214
|
+
if let runtimeKey {
|
|
215
|
+
defaults.set(runtimeKey, forKey: Keys.lastResolvedRuntimeKey)
|
|
216
|
+
} else {
|
|
217
|
+
// nil clears the key so the next cold start is treated as unresolved again
|
|
218
|
+
defaults.removeObject(forKey: Keys.lastResolvedRuntimeKey)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
200
222
|
func markStatus(bundleId: String, status: BundleStatus) {
|
|
201
223
|
guard var bundle = getBundle(id: bundleId) else {
|
|
202
224
|
return
|
|
@@ -78,7 +78,7 @@ private final class DownloadDelegate: NSObject, URLSessionDownloadDelegate {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
let temporaryZip = FileManager.default.temporaryDirectory
|
|
81
|
-
.appendingPathComponent("
|
|
81
|
+
.appendingPathComponent("otakit-\(UUID().uuidString).zip")
|
|
82
82
|
|
|
83
83
|
do {
|
|
84
84
|
try FileManager.default.moveItem(at: location, to: temporaryZip)
|
|
@@ -59,11 +59,15 @@ enum ManifestClient {
|
|
|
59
59
|
let runtimeKey = runtimeVersion?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty
|
|
60
60
|
?? defaultRuntimeKey
|
|
61
61
|
|
|
62
|
-
guard let
|
|
63
|
-
string: "\(sanitizedBase)/manifests/\(appId)/\(channelKey)/\(runtimeKey)/manifest.json"
|
|
64
|
-
) else {
|
|
62
|
+
guard let baseURL = URL(string: sanitizedBase) else {
|
|
65
63
|
throw ManifestClientError.invalidURL
|
|
66
64
|
}
|
|
65
|
+
let url = baseURL
|
|
66
|
+
.appendingPathComponent("manifests", isDirectory: true)
|
|
67
|
+
.appendingPathComponent(appId, isDirectory: true)
|
|
68
|
+
.appendingPathComponent(channelKey, isDirectory: true)
|
|
69
|
+
.appendingPathComponent(runtimeKey, isDirectory: true)
|
|
70
|
+
.appendingPathComponent("manifest.json", isDirectory: false)
|
|
67
71
|
|
|
68
72
|
try requireHTTPS(url: url, allowInsecure: allowInsecureUrls)
|
|
69
73
|
|
|
@@ -114,7 +118,7 @@ enum ManifestClient {
|
|
|
114
118
|
try requireHTTPS(url: dlURL, allowInsecure: allowInsecureUrls)
|
|
115
119
|
|
|
116
120
|
if manifestKeys.isEmpty {
|
|
117
|
-
print("[
|
|
121
|
+
print("[OtaKit] WARNING: No manifest signing keys configured — signature verification is disabled for this request.")
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
if !manifestKeys.isEmpty {
|