@otakit/capacitor-updater 1.2.0 → 2.0.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/README.md +23 -18
- package/android/src/main/java/com/updatekit/updater/{StatsClient.java → DeviceEventClient.java} +30 -19
- package/android/src/main/java/com/updatekit/updater/HostedManifestKeys.java +5 -6
- package/android/src/main/java/com/updatekit/updater/ManifestClient.java +33 -47
- package/android/src/main/java/com/updatekit/updater/ManifestVerifier.java +1 -75
- package/android/src/main/java/com/updatekit/updater/UpdaterPlugin.java +160 -99
- package/dist/esm/definitions.d.ts +9 -25
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +0 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +0 -4
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +0 -8
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +0 -10
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +0 -10
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/UpdaterPlugin/{StatsClient.swift → DeviceEventClient.swift} +21 -21
- package/ios/Sources/UpdaterPlugin/HostedManifestKeys.swift +5 -5
- package/ios/Sources/UpdaterPlugin/ManifestClient.swift +32 -52
- package/ios/Sources/UpdaterPlugin/ManifestVerifier.swift +2 -56
- package/ios/Sources/UpdaterPlugin/UpdaterPlugin.m +0 -2
- package/ios/Sources/UpdaterPlugin/UpdaterPlugin.swift +139 -99
- package/package.json +1 -1
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.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}\nfunction toPublicState(value) {\n return {\n current: value.current,\n staged: value.staged,\n builtinVersion: value.builtinVersion,\n };\n}\nasync function getState() {\n return toPublicState(await NativeOtaKit.debugGetState());\n}\nasync function check() {\n return normalizeNullable(await NativeOtaKit.check());\n}\nasync function download() {\n return normalizeNullable(await NativeOtaKit.download());\n}\nfunction apply() {\n return NativeOtaKit.apply();\n}\nasync function update() {\n const state = await getState();\n let latest;\n try {\n latest = await check();\n }\n catch (error) {\n if (state.staged) {\n await apply();\n return;\n }\n throw error;\n }\n if (latest) {\n if (latest.downloaded) {\n await apply();\n return;\n }\n const bundle = await download();\n if (bundle) {\n await apply();\n }\n return;\n }\n if (state.staged) {\n await apply();\n }\n}\nconst OtaKit = {\n getState,\n check,\n download,\n apply,\n update,\n notifyAppReady: () => NativeOtaKit.notifyAppReady(),\n debug: {\n
|
|
1
|
+
{"version":3,"file":"plugin.cjs.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}\nfunction toPublicState(value) {\n return {\n current: value.current,\n staged: value.staged,\n builtinVersion: value.builtinVersion,\n };\n}\nasync function getState() {\n return toPublicState(await NativeOtaKit.debugGetState());\n}\nasync function check() {\n return normalizeNullable(await NativeOtaKit.check());\n}\nasync function download() {\n return normalizeNullable(await NativeOtaKit.download());\n}\nfunction apply() {\n return NativeOtaKit.apply();\n}\nasync function update() {\n const state = await getState();\n let latest;\n try {\n latest = await check();\n }\n catch (error) {\n if (state.staged) {\n await apply();\n return;\n }\n throw error;\n }\n if (latest) {\n if (latest.downloaded) {\n await apply();\n return;\n }\n const bundle = await download();\n if (bundle) {\n await apply();\n }\n return;\n }\n if (state.staged) {\n await apply();\n }\n}\nconst OtaKit = {\n getState,\n check,\n download,\n apply,\n update,\n notifyAppReady: () => NativeOtaKit.notifyAppReady(),\n debug: {\n reset: () => NativeOtaKit.debugReset(),\n listBundles: () => NativeOtaKit.debugListBundles(),\n deleteBundle: (options) => NativeOtaKit.debugDeleteBundle(options),\n getLastFailure: async () => normalizeNullable(await NativeOtaKit.debugGetLastFailure()),\n },\n addListener: NativeOtaKit.addListener.bind(NativeOtaKit),\n removeAllListeners: () => NativeOtaKit.removeAllListeners(),\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 debugGetState() {\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 null;\n }\n async download() {\n console.warn('OtaKit.download() is not supported on web');\n return null;\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 notifyAppReady() {\n // No-op on web, but don't warn - apps should call this unconditionally\n }\n async debugReset() {\n console.warn('OtaKit.debug.reset() is not supported on web');\n }\n async debugListBundles() {\n return { bundles: [] };\n }\n async debugDeleteBundle(_options) {\n console.warn('OtaKit.debug.deleteBundle() is not supported on web');\n }\n async debugGetLastFailure() {\n return null;\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BundleStatus","registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -89,8 +89,6 @@ var capacitorUpdater = (function (exports, core) {
|
|
|
89
89
|
update,
|
|
90
90
|
notifyAppReady: () => NativeOtaKit.notifyAppReady(),
|
|
91
91
|
debug: {
|
|
92
|
-
check: async (options) => normalizeNullable(await NativeOtaKit.debugCheck(options)),
|
|
93
|
-
download: async (options) => normalizeNullable(await NativeOtaKit.debugDownload(options)),
|
|
94
92
|
reset: () => NativeOtaKit.debugReset(),
|
|
95
93
|
listBundles: () => NativeOtaKit.debugListBundles(),
|
|
96
94
|
deleteBundle: (options) => NativeOtaKit.debugDeleteBundle(options),
|
|
@@ -130,14 +128,6 @@ var capacitorUpdater = (function (exports, core) {
|
|
|
130
128
|
console.warn('OtaKit.apply() is not supported on web');
|
|
131
129
|
throw new Error('OtaKit.apply() is not supported on web');
|
|
132
130
|
}
|
|
133
|
-
async debugCheck() {
|
|
134
|
-
console.warn('OtaKit.debug.check() is not supported on web');
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
async debugDownload(_options) {
|
|
138
|
-
console.warn('OtaKit.debug.download() is not supported on web');
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
131
|
async notifyAppReady() {
|
|
142
132
|
// No-op on web, but don't warn - apps should call this unconditionally
|
|
143
133
|
}
|
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}\nfunction toPublicState(value) {\n return {\n current: value.current,\n staged: value.staged,\n builtinVersion: value.builtinVersion,\n };\n}\nasync function getState() {\n return toPublicState(await NativeOtaKit.debugGetState());\n}\nasync function check() {\n return normalizeNullable(await NativeOtaKit.check());\n}\nasync function download() {\n return normalizeNullable(await NativeOtaKit.download());\n}\nfunction apply() {\n return NativeOtaKit.apply();\n}\nasync function update() {\n const state = await getState();\n let latest;\n try {\n latest = await check();\n }\n catch (error) {\n if (state.staged) {\n await apply();\n return;\n }\n throw error;\n }\n if (latest) {\n if (latest.downloaded) {\n await apply();\n return;\n }\n const bundle = await download();\n if (bundle) {\n await apply();\n }\n return;\n }\n if (state.staged) {\n await apply();\n }\n}\nconst OtaKit = {\n getState,\n check,\n download,\n apply,\n update,\n notifyAppReady: () => NativeOtaKit.notifyAppReady(),\n debug: {\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}\nfunction toPublicState(value) {\n return {\n current: value.current,\n staged: value.staged,\n builtinVersion: value.builtinVersion,\n };\n}\nasync function getState() {\n return toPublicState(await NativeOtaKit.debugGetState());\n}\nasync function check() {\n return normalizeNullable(await NativeOtaKit.check());\n}\nasync function download() {\n return normalizeNullable(await NativeOtaKit.download());\n}\nfunction apply() {\n return NativeOtaKit.apply();\n}\nasync function update() {\n const state = await getState();\n let latest;\n try {\n latest = await check();\n }\n catch (error) {\n if (state.staged) {\n await apply();\n return;\n }\n throw error;\n }\n if (latest) {\n if (latest.downloaded) {\n await apply();\n return;\n }\n const bundle = await download();\n if (bundle) {\n await apply();\n }\n return;\n }\n if (state.staged) {\n await apply();\n }\n}\nconst OtaKit = {\n getState,\n check,\n download,\n apply,\n update,\n notifyAppReady: () => NativeOtaKit.notifyAppReady(),\n debug: {\n reset: () => NativeOtaKit.debugReset(),\n listBundles: () => NativeOtaKit.debugListBundles(),\n deleteBundle: (options) => NativeOtaKit.debugDeleteBundle(options),\n getLastFailure: async () => normalizeNullable(await NativeOtaKit.debugGetLastFailure()),\n },\n addListener: NativeOtaKit.addListener.bind(NativeOtaKit),\n removeAllListeners: () => NativeOtaKit.removeAllListeners(),\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 debugGetState() {\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 null;\n }\n async download() {\n console.warn('OtaKit.download() is not supported on web');\n return null;\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 notifyAppReady() {\n // No-op on web, but don't warn - apps should call this unconditionally\n }\n async debugReset() {\n console.warn('OtaKit.debug.reset() is not supported on web');\n }\n async debugListBundles() {\n return { bundles: [] };\n }\n async debugDeleteBundle(_options) {\n console.warn('OtaKit.debug.deleteBundle() is not supported on web');\n }\n async debugGetLastFailure() {\n return null;\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BundleStatus","registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
|
-
enum
|
|
3
|
+
enum DeviceEventAction: String {
|
|
4
4
|
case downloaded
|
|
5
5
|
case applied
|
|
6
6
|
case downloadError = "download_error"
|
|
7
7
|
case rollback
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
enum
|
|
10
|
+
enum DeviceEventClient {
|
|
11
11
|
static func send(
|
|
12
|
-
|
|
12
|
+
ingestUrl: String,
|
|
13
13
|
appId: String,
|
|
14
14
|
platform: String,
|
|
15
|
-
action:
|
|
16
|
-
bundleVersion: String
|
|
15
|
+
action: DeviceEventAction,
|
|
16
|
+
bundleVersion: String,
|
|
17
17
|
channel: String?,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
runtimeVersion: String?,
|
|
19
|
+
releaseId: String,
|
|
20
|
+
nativeBuild: String,
|
|
21
|
+
detail: String?
|
|
21
22
|
) {
|
|
22
|
-
let sanitizedBase =
|
|
23
|
+
let sanitizedBase = ingestUrl.replacingOccurrences(
|
|
23
24
|
of: "/+$",
|
|
24
25
|
with: "",
|
|
25
26
|
options: .regularExpression
|
|
26
27
|
)
|
|
27
28
|
|
|
28
|
-
guard let url = URL(string: "\(sanitizedBase)/
|
|
29
|
+
guard let url = URL(string: "\(sanitizedBase)/events") else {
|
|
29
30
|
return
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
var payload: [String: Any] = [
|
|
34
|
+
"eventId": UUID().uuidString.lowercased(),
|
|
35
|
+
"sentAt": ISO8601DateFormatter().string(from: Date()),
|
|
33
36
|
"platform": platform,
|
|
34
37
|
"action": action.rawValue,
|
|
38
|
+
"bundleVersion": bundleVersion,
|
|
39
|
+
"releaseId": releaseId,
|
|
40
|
+
"nativeBuild": nativeBuild,
|
|
35
41
|
]
|
|
36
|
-
if let bundleVersion {
|
|
37
|
-
payload["bundleVersion"] = bundleVersion
|
|
38
|
-
}
|
|
39
42
|
if let channel, !channel.isEmpty {
|
|
40
43
|
payload["channel"] = channel
|
|
41
44
|
}
|
|
42
|
-
if let
|
|
43
|
-
payload["
|
|
44
|
-
}
|
|
45
|
-
if let nativeBuild {
|
|
46
|
-
payload["nativeBuild"] = nativeBuild
|
|
45
|
+
if let runtimeVersion, !runtimeVersion.isEmpty {
|
|
46
|
+
payload["runtimeVersion"] = runtimeVersion
|
|
47
47
|
}
|
|
48
|
-
if let
|
|
49
|
-
payload["
|
|
48
|
+
if let detail {
|
|
49
|
+
payload["detail"] = String(detail.prefix(500))
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
guard let body = try? JSONSerialization.data(withJSONObject: payload) else {
|
|
@@ -60,7 +60,7 @@ enum StatsClient {
|
|
|
60
60
|
request.httpBody = body
|
|
61
61
|
request.timeoutInterval = 10
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// Device events are best-effort and should never block the update flow.
|
|
64
64
|
URLSession.shared.dataTask(with: request).resume()
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
enum HostedManifestKeys {
|
|
4
|
-
static let
|
|
4
|
+
static let managedCdnURL = "https://cdn.otakit.app"
|
|
5
5
|
|
|
6
6
|
static let defaults: [(kid: String, key: Data)] = [
|
|
7
7
|
(
|
|
@@ -12,12 +12,12 @@ enum HostedManifestKeys {
|
|
|
12
12
|
)
|
|
13
13
|
]
|
|
14
14
|
|
|
15
|
-
static func
|
|
16
|
-
let normalized =
|
|
15
|
+
static func matchesManagedManifestURL(_ cdnUrl: String) -> Bool {
|
|
16
|
+
let normalized = cdnUrl
|
|
17
17
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
18
18
|
.replacingOccurrences(of: "/+$", with: "", options: .regularExpression)
|
|
19
19
|
.lowercased()
|
|
20
|
-
return normalized ==
|
|
21
|
-
|| normalized == "https://otakit.app
|
|
20
|
+
return normalized == managedCdnURL
|
|
21
|
+
|| normalized == "https://www.otakit.app"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
|
+
private let baseChannelKey = "__base__"
|
|
4
|
+
private let defaultRuntimeKey = "__default__"
|
|
5
|
+
|
|
3
6
|
struct LatestManifest {
|
|
4
7
|
let version: String
|
|
5
8
|
let url: String
|
|
6
9
|
let sha256: String
|
|
7
10
|
let size: Int
|
|
8
11
|
let runtimeVersion: String?
|
|
9
|
-
let releaseId: String
|
|
12
|
+
let releaseId: String
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
struct ManifestSignature {
|
|
@@ -38,43 +41,34 @@ enum ManifestClient {
|
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
static func fetchLatest(
|
|
41
|
-
|
|
44
|
+
cdnUrl: String,
|
|
42
45
|
appId: String,
|
|
43
46
|
channel: String?,
|
|
44
|
-
currentVersion: String,
|
|
45
|
-
currentReleaseId: String?,
|
|
46
47
|
runtimeVersion: String?,
|
|
47
|
-
platform: String,
|
|
48
48
|
allowInsecureUrls: Bool = false,
|
|
49
49
|
manifestKeys: [ManifestKey] = []
|
|
50
50
|
) async throws -> LatestManifest? {
|
|
51
|
-
let sanitizedBase =
|
|
51
|
+
let sanitizedBase = cdnUrl.replacingOccurrences(
|
|
52
52
|
of: "/+$",
|
|
53
53
|
with: "",
|
|
54
54
|
options: .regularExpression
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
let channelKey = channel?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty
|
|
58
|
+
?? baseChannelKey
|
|
59
|
+
let runtimeKey = runtimeVersion?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty
|
|
60
|
+
?? defaultRuntimeKey
|
|
61
|
+
|
|
62
|
+
guard let url = URL(
|
|
63
|
+
string: "\(sanitizedBase)/manifests/\(appId)/\(channelKey)/\(runtimeKey)/manifest.json"
|
|
64
|
+
) else {
|
|
58
65
|
throw ManifestClientError.invalidURL
|
|
59
66
|
}
|
|
60
|
-
let url = baseURL.appendingPathComponent("manifest")
|
|
61
67
|
|
|
62
68
|
try requireHTTPS(url: url, allowInsecure: allowInsecureUrls)
|
|
63
69
|
|
|
64
70
|
var request = URLRequest(url: url)
|
|
65
71
|
request.httpMethod = "GET"
|
|
66
|
-
request.setValue(appId, forHTTPHeaderField: "X-App-Id")
|
|
67
|
-
request.setValue(platform, forHTTPHeaderField: "X-Platform")
|
|
68
|
-
if let channel, !channel.isEmpty {
|
|
69
|
-
request.setValue(channel, forHTTPHeaderField: "X-Channel")
|
|
70
|
-
}
|
|
71
|
-
request.setValue(currentVersion, forHTTPHeaderField: "X-Current-Version")
|
|
72
|
-
if let currentReleaseId, !currentReleaseId.isEmpty {
|
|
73
|
-
request.setValue(currentReleaseId, forHTTPHeaderField: "X-Release-Id")
|
|
74
|
-
}
|
|
75
|
-
if let runtimeVersion, !runtimeVersion.isEmpty {
|
|
76
|
-
request.setValue(runtimeVersion, forHTTPHeaderField: "X-Runtime-Version")
|
|
77
|
-
}
|
|
78
72
|
request.timeoutInterval = 30
|
|
79
73
|
|
|
80
74
|
let (data, response) = try await URLSession.shared.data(for: request)
|
|
@@ -82,7 +76,7 @@ enum ManifestClient {
|
|
|
82
76
|
throw ManifestClientError.invalidResponse
|
|
83
77
|
}
|
|
84
78
|
|
|
85
|
-
if httpResponse.statusCode == 204 {
|
|
79
|
+
if httpResponse.statusCode == 404 || httpResponse.statusCode == 204 {
|
|
86
80
|
return nil
|
|
87
81
|
}
|
|
88
82
|
|
|
@@ -108,11 +102,12 @@ enum ManifestClient {
|
|
|
108
102
|
.nilIfEmpty
|
|
109
103
|
|
|
110
104
|
let signature = parseSignature(object["signature"])
|
|
111
|
-
let
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
guard let releaseId = (object["releaseId"] as? String)?
|
|
106
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
107
|
+
.nilIfEmpty else {
|
|
108
|
+
throw ManifestClientError.invalidResponse
|
|
109
|
+
}
|
|
114
110
|
|
|
115
|
-
// Validate download URL scheme
|
|
116
111
|
guard let dlURL = URL(string: downloadUrl) else {
|
|
117
112
|
throw ManifestClientError.invalidURL
|
|
118
113
|
}
|
|
@@ -122,36 +117,21 @@ enum ManifestClient {
|
|
|
122
117
|
print("[UpdateKit] WARNING: No manifest signing keys configured — signature verification is disabled for this request.")
|
|
123
118
|
}
|
|
124
119
|
|
|
125
|
-
// Verify manifest signature if signing keys are configured.
|
|
126
|
-
// New manifests carry signatureV2 with runtimeVersion in the signed payload.
|
|
127
|
-
// Older servers only return the legacy signature field.
|
|
128
120
|
if !manifestKeys.isEmpty {
|
|
129
|
-
|
|
130
|
-
try ManifestVerifier.verify(
|
|
131
|
-
appId: appId,
|
|
132
|
-
channel: channel,
|
|
133
|
-
platform: platform,
|
|
134
|
-
version: version,
|
|
135
|
-
sha256: sha256,
|
|
136
|
-
size: size,
|
|
137
|
-
runtimeVersion: runtimeVersion,
|
|
138
|
-
signature: sigV2,
|
|
139
|
-
trustedKeys: manifestKeys
|
|
140
|
-
)
|
|
141
|
-
} else if let sig = signature {
|
|
142
|
-
try ManifestVerifier.verifyLegacy(
|
|
143
|
-
appId: appId,
|
|
144
|
-
channel: channel,
|
|
145
|
-
platform: platform,
|
|
146
|
-
version: version,
|
|
147
|
-
sha256: sha256,
|
|
148
|
-
size: size,
|
|
149
|
-
signature: sig,
|
|
150
|
-
trustedKeys: manifestKeys
|
|
151
|
-
)
|
|
152
|
-
} else {
|
|
121
|
+
guard let signature else {
|
|
153
122
|
throw ManifestVerifierError.missingSignature
|
|
154
123
|
}
|
|
124
|
+
|
|
125
|
+
try ManifestVerifier.verify(
|
|
126
|
+
appId: appId,
|
|
127
|
+
channel: channel,
|
|
128
|
+
version: version,
|
|
129
|
+
sha256: sha256,
|
|
130
|
+
size: size,
|
|
131
|
+
runtimeVersion: runtimeVersion,
|
|
132
|
+
signature: signature,
|
|
133
|
+
trustedKeys: manifestKeys
|
|
134
|
+
)
|
|
155
135
|
}
|
|
156
136
|
|
|
157
137
|
return LatestManifest(
|
|
@@ -18,7 +18,7 @@ enum ManifestVerifier {
|
|
|
18
18
|
/// Verify a manifest signature using ES256 (ECDSA P-256 + SHA-256).
|
|
19
19
|
///
|
|
20
20
|
/// - Parameters:
|
|
21
|
-
/// - appId, channel
|
|
21
|
+
/// - appId, channel: Request context (known by plugin).
|
|
22
22
|
/// - version, sha256, size, runtimeVersion: Response fields.
|
|
23
23
|
/// - signature: The signature object from the manifest response.
|
|
24
24
|
/// - trustedKeys: Array of verification keys configured in the plugin.
|
|
@@ -27,7 +27,6 @@ enum ManifestVerifier {
|
|
|
27
27
|
static func verify(
|
|
28
28
|
appId: String,
|
|
29
29
|
channel: String?,
|
|
30
|
-
platform: String,
|
|
31
30
|
version: String,
|
|
32
31
|
sha256: String,
|
|
33
32
|
size: Int,
|
|
@@ -38,7 +37,6 @@ enum ManifestVerifier {
|
|
|
38
37
|
let payload = buildCanonicalPayload(
|
|
39
38
|
appId: appId,
|
|
40
39
|
channel: channel,
|
|
41
|
-
platform: platform,
|
|
42
40
|
version: version,
|
|
43
41
|
sha256: sha256,
|
|
44
42
|
size: size,
|
|
@@ -50,30 +48,6 @@ enum ManifestVerifier {
|
|
|
50
48
|
try verifyPayload(payload, signature: signature, trustedKeys: trustedKeys)
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
static func verifyLegacy(
|
|
54
|
-
appId: String,
|
|
55
|
-
channel: String?,
|
|
56
|
-
platform: String,
|
|
57
|
-
version: String,
|
|
58
|
-
sha256: String,
|
|
59
|
-
size: Int,
|
|
60
|
-
signature: ManifestSignature,
|
|
61
|
-
trustedKeys: [ManifestKey]
|
|
62
|
-
) throws {
|
|
63
|
-
let payload = buildLegacyCanonicalPayload(
|
|
64
|
-
appId: appId,
|
|
65
|
-
channel: channel,
|
|
66
|
-
platform: platform,
|
|
67
|
-
version: version,
|
|
68
|
-
sha256: sha256,
|
|
69
|
-
size: size,
|
|
70
|
-
kid: signature.kid,
|
|
71
|
-
iat: signature.iat,
|
|
72
|
-
exp: signature.exp
|
|
73
|
-
)
|
|
74
|
-
try verifyPayload(payload, signature: signature, trustedKeys: trustedKeys)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
51
|
private static func verifyPayload(
|
|
78
52
|
_ payload: String,
|
|
79
53
|
signature: ManifestSignature,
|
|
@@ -107,7 +81,6 @@ enum ManifestVerifier {
|
|
|
107
81
|
private static func buildCanonicalPayload(
|
|
108
82
|
appId: String,
|
|
109
83
|
channel: String?,
|
|
110
|
-
platform: String,
|
|
111
84
|
version: String,
|
|
112
85
|
sha256: String,
|
|
113
86
|
size: Int,
|
|
@@ -117,10 +90,9 @@ enum ManifestVerifier {
|
|
|
117
90
|
exp: Int
|
|
118
91
|
) -> String {
|
|
119
92
|
return [
|
|
120
|
-
"
|
|
93
|
+
"MANIFEST",
|
|
121
94
|
"appId:\(appId)",
|
|
122
95
|
"channel:\(channel ?? "null")",
|
|
123
|
-
"platform:\(platform)",
|
|
124
96
|
"version:\(version)",
|
|
125
97
|
"sha256:\(sha256)",
|
|
126
98
|
"size:\(size)",
|
|
@@ -131,32 +103,6 @@ enum ManifestVerifier {
|
|
|
131
103
|
].joined(separator: "\n")
|
|
132
104
|
}
|
|
133
105
|
|
|
134
|
-
private static func buildLegacyCanonicalPayload(
|
|
135
|
-
appId: String,
|
|
136
|
-
channel: String?,
|
|
137
|
-
platform: String,
|
|
138
|
-
version: String,
|
|
139
|
-
sha256: String,
|
|
140
|
-
size: Int,
|
|
141
|
-
kid: String,
|
|
142
|
-
iat: Int,
|
|
143
|
-
exp: Int
|
|
144
|
-
) -> String {
|
|
145
|
-
return [
|
|
146
|
-
"MANIFEST_V1",
|
|
147
|
-
"appId:\(appId)",
|
|
148
|
-
"channel:\(channel ?? "null")",
|
|
149
|
-
"platform:\(platform)",
|
|
150
|
-
"version:\(version)",
|
|
151
|
-
"sha256:\(sha256)",
|
|
152
|
-
"size:\(size)",
|
|
153
|
-
"minNativeBuild:null",
|
|
154
|
-
"kid:\(kid)",
|
|
155
|
-
"iat:\(iat)",
|
|
156
|
-
"exp:\(exp)",
|
|
157
|
-
].joined(separator: "\n")
|
|
158
|
-
}
|
|
159
|
-
|
|
160
106
|
private static func base64UrlDecode(_ string: String) -> Data? {
|
|
161
107
|
var base64 = string
|
|
162
108
|
.replacingOccurrences(of: "-", with: "+")
|
|
@@ -5,8 +5,6 @@ CAP_PLUGIN(UpdaterPlugin, "OtaKit",
|
|
|
5
5
|
CAP_PLUGIN_METHOD(download, CAPPluginReturnPromise);
|
|
6
6
|
CAP_PLUGIN_METHOD(apply, CAPPluginReturnPromise);
|
|
7
7
|
CAP_PLUGIN_METHOD(debugGetState, CAPPluginReturnPromise);
|
|
8
|
-
CAP_PLUGIN_METHOD(debugCheck, CAPPluginReturnPromise);
|
|
9
|
-
CAP_PLUGIN_METHOD(debugDownload, CAPPluginReturnPromise);
|
|
10
8
|
CAP_PLUGIN_METHOD(notifyAppReady, CAPPluginReturnPromise);
|
|
11
9
|
CAP_PLUGIN_METHOD(debugReset, CAPPluginReturnPromise);
|
|
12
10
|
CAP_PLUGIN_METHOD(debugListBundles, CAPPluginReturnPromise);
|