expo-manifests 0.5.2 → 0.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/android/build.gradle +2 -2
  3. package/android/src/androidTest/java/expo/modules/manifests/core/NewManifestTest.kt +3 -3
  4. package/android/src/main/java/expo/modules/manifests/core/BaseLegacyManifest.kt +1 -1
  5. package/android/src/main/java/expo/modules/manifests/core/Manifest.kt +6 -2
  6. package/android/src/main/java/expo/modules/manifests/core/NewManifest.kt +6 -1
  7. package/ios/EXManifests/BareManifest.swift +19 -0
  8. package/ios/EXManifests/BaseLegacyManifest.swift +39 -0
  9. package/ios/EXManifests/LegacyManifest.swift +30 -0
  10. package/ios/EXManifests/Manifest.swift +363 -0
  11. package/ios/EXManifests/ManifestFactory.swift +17 -0
  12. package/ios/EXManifests/NewManifest.swift +83 -0
  13. package/ios/EXManifests.podspec +14 -5
  14. package/ios/Tests/BareManifestSpec.swift +69 -0
  15. package/ios/Tests/LegacyManifestSpec.swift +69 -0
  16. package/ios/Tests/NewManifestSpec.swift +97 -0
  17. package/package.json +3 -3
  18. package/ios/EXManifests/EXManifestsBareManifest.h +0 -20
  19. package/ios/EXManifests/EXManifestsBareManifest.m +0 -23
  20. package/ios/EXManifests/EXManifestsBaseLegacyManifest.h +0 -22
  21. package/ios/EXManifests/EXManifestsBaseLegacyManifest.m +0 -50
  22. package/ios/EXManifests/EXManifestsBaseManifest.h +0 -51
  23. package/ios/EXManifests/EXManifestsBaseManifest.m +0 -323
  24. package/ios/EXManifests/EXManifestsLegacyManifest.h +0 -19
  25. package/ios/EXManifests/EXManifestsLegacyManifest.m +0 -33
  26. package/ios/EXManifests/EXManifestsManifest.h +0 -86
  27. package/ios/EXManifests/EXManifestsManifestFactory.h +0 -14
  28. package/ios/EXManifests/EXManifestsManifestFactory.m +0 -22
  29. package/ios/EXManifests/EXManifestsNewManifest.h +0 -33
  30. package/ios/EXManifests/EXManifestsNewManifest.m +0 -89
  31. package/ios/Tests/EXManifestsNewManifestTests.m +0 -50
  32. package/ios/Tests/dummy.swift +0 -4
package/CHANGELOG.md CHANGED
@@ -10,7 +10,17 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 0.5.2 — 2023-02-21
13
+ ## 0.6.0 — 2023-05-08
14
+
15
+ ### 🎉 New features
16
+
17
+ - Support new SDK version field in new manifests. ([#22356](https://github.com/expo/expo/pull/22356) by [@wschurman](https://github.com/wschurman))
18
+
19
+ ### 💡 Others
20
+
21
+ - Convert iOS implementation to Swift. ([#21298](https://github.com/expo/expo/pull/21298), [#21648](https://github.com/expo/expo/pull/21648) by [@wschurman](https://github.com/wschurman))
22
+
23
+ ## 0.5.2 - 2023-02-21
14
24
 
15
25
  ### 🐛 Bug fixes
16
26
 
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.5.2'
6
+ version = '0.6.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -74,7 +74,7 @@ android {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
75
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
76
  versionCode 31
77
- versionName '0.5.2'
77
+ versionName '0.6.0'
78
78
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
79
79
  }
80
80
  lintOptions {
@@ -15,7 +15,7 @@ class NewManifestTest {
15
15
  val manifestJson =
16
16
  "{\"runtimeVersion\":\"$runtimeVersion\"}"
17
17
  val manifest = NewManifest(JSONObject(manifestJson))
18
- Assert.assertEquals(manifest.getSDKVersion(), "39.0.0")
18
+ Assert.assertEquals(manifest.getExpoGoSDKVersion(), "39.0.0")
19
19
  }
20
20
 
21
21
  @Test
@@ -25,7 +25,7 @@ class NewManifestTest {
25
25
  val manifestJson =
26
26
  "{\"runtimeVersion\":\"$runtimeVersion\"}"
27
27
  val manifest = NewManifest(JSONObject(manifestJson))
28
- Assert.assertEquals(manifest.getSDKVersion(), "UNVERSIONED")
28
+ Assert.assertEquals(manifest.getExpoGoSDKVersion(), "UNVERSIONED")
29
29
  }
30
30
 
31
31
  @Test
@@ -43,7 +43,7 @@ class NewManifestTest {
43
43
  val manifestJson =
44
44
  "{\"runtimeVersion\":\"$runtimeVersion\"}"
45
45
  val manifest = NewManifest(JSONObject(manifestJson))
46
- Assert.assertNull(manifest.getSDKVersion())
46
+ Assert.assertNull(manifest.getExpoGoSDKVersion())
47
47
  }
48
48
  }
49
49
  }
@@ -18,7 +18,7 @@ abstract class BaseLegacyManifest(json: JSONObject) : Manifest(json) {
18
18
  @Throws(JSONException::class)
19
19
  override fun getBundleURL(): String = json.require("bundleUrl")
20
20
 
21
- override fun getSDKVersion(): String? = json.getNullable("sdkVersion")
21
+ override fun getExpoGoSDKVersion(): String? = json.getNullable("sdkVersion")
22
22
 
23
23
  override fun getExpoGoConfigRootObject(): JSONObject? {
24
24
  return json
@@ -70,7 +70,11 @@ abstract class Manifest(protected val json: JSONObject) {
70
70
 
71
71
  fun getMetadata(): JSONObject? = json.getNullable("metadata")
72
72
 
73
- abstract fun getSDKVersion(): String?
73
+ /**
74
+ * Get the SDK version that should be attempted to be used in Expo Go. If no SDK version can be
75
+ * determined, returns null
76
+ */
77
+ abstract fun getExpoGoSDKVersion(): String?
74
78
 
75
79
  abstract fun getAssets(): JSONArray?
76
80
 
@@ -172,7 +176,7 @@ abstract class Manifest(protected val json: JSONObject) {
172
176
  var result = expoClientConfig
173
177
  ?.getNullable<JSONObject>("android")?.getNullable<String>("jsEngine") ?: expoClientConfig?.getNullable<String>("jsEngine")
174
178
  if (result == null) {
175
- val sdkVersionComponents = getSDKVersion()?.split(".")
179
+ val sdkVersionComponents = getExpoGoSDKVersion()?.split(".")
176
180
  val sdkMajorVersion = if (sdkVersionComponents?.size == 3) sdkVersionComponents[0].toIntOrNull() else 0
177
181
  result = if (sdkMajorVersion in 1..47) "jsc" else "hermes"
178
182
  }
@@ -33,7 +33,8 @@ class NewManifest(json: JSONObject) : Manifest(json) {
33
33
  @Throws(JSONException::class)
34
34
  override fun getBundleURL(): String = getLaunchAsset().require("url")
35
35
 
36
- override fun getSDKVersion(): String? {
36
+ @Deprecated(message = "exposdk:... runtime version is deprecated")
37
+ private fun getSDKVersionFromRuntimeVersion(): String? {
37
38
  val runtimeVersion = getRuntimeVersion()
38
39
  if (runtimeVersion == "exposdk:UNVERSIONED") {
39
40
  return "UNVERSIONED"
@@ -47,6 +48,10 @@ class NewManifest(json: JSONObject) : Manifest(json) {
47
48
  return null
48
49
  }
49
50
 
51
+ override fun getExpoGoSDKVersion(): String? {
52
+ return getExpoClientConfigRootObject()?.getString("sdkVersion") ?: getSDKVersionFromRuntimeVersion()
53
+ }
54
+
50
55
  @Throws(JSONException::class)
51
56
  fun getLaunchAsset(): JSONObject = json.require("launchAsset")
52
57
 
@@ -0,0 +1,19 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ @objc(EXManifestsBareManifest)
6
+ @objcMembers
7
+ public class BareManifest: BaseLegacyManifest {
8
+ public func rawId() -> String {
9
+ return rawManifestJSON().requiredValue(forKey: "id")
10
+ }
11
+
12
+ public func commitTimeNumber() -> Int {
13
+ return rawManifestJSON().requiredValue(forKey: "commitTime")
14
+ }
15
+
16
+ public func metadata() -> [String: Any]? {
17
+ return rawManifestJSON().optionalValue(forKey: "metadata")
18
+ }
19
+ }
@@ -0,0 +1,39 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ @objc(EXManifestBaseLegacyManifest)
6
+ @objcMembers
7
+ public class BaseLegacyManifest: Manifest {
8
+ override func expoClientConfigRootObject() -> [String: Any]? {
9
+ return rawManifestJSON()
10
+ }
11
+
12
+ override func expoGoConfigRootObject() -> [String: Any]? {
13
+ return rawManifestJSON()
14
+ }
15
+
16
+ public override func stableLegacyId() -> String {
17
+ return rawManifestJSON().optionalValue(forKey: "originalFullName") ?? legacyId()
18
+ }
19
+
20
+ public override func scopeKey() -> String {
21
+ return rawManifestJSON().optionalValue(forKey: "scopeKey") ?? stableLegacyId()
22
+ }
23
+
24
+ public override func easProjectId() -> String? {
25
+ return rawManifestJSON().optionalValue(forKey: "projectId")
26
+ }
27
+
28
+ public override func bundleUrl() -> String {
29
+ return rawManifestJSON().requiredValue(forKey: "bundleUrl")
30
+ }
31
+
32
+ public override func expoGoSDKVersion() -> String? {
33
+ return rawManifestJSON().optionalValue(forKey: "sdkVersion")
34
+ }
35
+
36
+ public func assets() -> [[String: Any]]? {
37
+ return self.rawManifestJSON().optionalValue(forKey: "assets")
38
+ }
39
+ }
@@ -0,0 +1,30 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+ import Foundation
3
+
4
+ @objc(EXManifestsLegacyManifest)
5
+ @objcMembers
6
+ public class LegacyManifest: BaseLegacyManifest {
7
+ public func releaseID() -> String {
8
+ return rawManifestJSON().requiredValue(forKey: "releaseId")
9
+ }
10
+
11
+ public func commitTime() -> String {
12
+ return rawManifestJSON().requiredValue(forKey: "commitTime")
13
+ }
14
+
15
+ public func bundledAssets() -> [Any]? {
16
+ return rawManifestJSON().optionalValue(forKey: "bundledAssets")
17
+ }
18
+
19
+ public func runtimeVersion() -> Any? {
20
+ return rawManifestJSON().optionalValue(forKey: "runtimeVersion")
21
+ }
22
+
23
+ public func bundleKey() -> String? {
24
+ return rawManifestJSON().optionalValue(forKey: "bundleKey")
25
+ }
26
+
27
+ public func assetUrlOverride() -> String? {
28
+ return rawManifestJSON().optionalValue(forKey: "assetUrlOverride")
29
+ }
30
+ }
@@ -0,0 +1,363 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+
3
+ // this uses abstract class patterns
4
+ // swiftlint:disable unavailable_function
5
+
6
+ // swiftlint:disable type_body_length
7
+
8
+ import Foundation
9
+ import UIKit
10
+
11
+ /**
12
+ Uses objective-c NSExceptions for field validation. This is to maintain
13
+ backwards compatibility with the previous objective-c implementation so that we don't need to do
14
+ error handling at every callsite. When all the code is swift, we might be able to use these exceptions.
15
+ */
16
+ public extension Dictionary where Key == String {
17
+ func optionalValue<T>(forKey: String) -> T? {
18
+ guard let value = self[forKey] else {
19
+ return nil
20
+ }
21
+
22
+ if !(value is T) {
23
+ let exception = NSException(
24
+ name: NSExceptionName.internalInconsistencyException,
25
+ reason: "Value for (key = \(forKey)) has incorrect type",
26
+ userInfo: ["key": forKey]
27
+ )
28
+ exception.raise()
29
+ }
30
+ return value as? T
31
+ }
32
+
33
+ func requiredValue<T>(forKey: String) -> T {
34
+ let value = self[forKey]
35
+
36
+ if value == nil {
37
+ let exception = NSException(
38
+ name: NSExceptionName.internalInconsistencyException,
39
+ reason: "Value for (key = \(forKey)) is null",
40
+ userInfo: ["key": forKey]
41
+ )
42
+ exception.raise()
43
+ }
44
+
45
+ if !(value is T) {
46
+ let exception = NSException(
47
+ name: NSExceptionName.internalInconsistencyException,
48
+ reason: "Value for (key = \(forKey)) has incorrect type",
49
+ userInfo: ["key": forKey]
50
+ )
51
+ exception.raise()
52
+ }
53
+
54
+ // exception above will preempt force_cast
55
+ // swiftlint:disable:next force_cast
56
+ return value as! T
57
+ }
58
+ }
59
+
60
+ public extension Optional {
61
+ func `let`<U>(_ transform: (_ it: Wrapped) throws -> U?) rethrows -> U? {
62
+ if let x = self {
63
+ return try transform(x)
64
+ }
65
+ return nil
66
+ }
67
+ }
68
+
69
+ @objc(EXManifestsManifest)
70
+ @objcMembers
71
+ public class Manifest: NSObject {
72
+ private let rawManifestJSONInternal: [String: Any]
73
+
74
+ public required init(rawManifestJSON: [String: Any]) {
75
+ rawManifestJSONInternal = rawManifestJSON
76
+ }
77
+
78
+ public override var debugDescription: String {
79
+ return rawManifestJSONInternal.description
80
+ }
81
+
82
+ public func rawManifestJSON() -> [String: Any] {
83
+ return rawManifestJSONInternal
84
+ }
85
+
86
+ // MARK: - Abstract methods
87
+
88
+ /**
89
+ A best-effort immutable legacy ID for this experience. Stable through project transfers.
90
+ Should be used for calling Expo and EAS APIs during their transition to easProjectId.
91
+ */
92
+ @available(*, deprecated, message: "Prefer scopeKey or easProjectId depending on use case")
93
+ public func stableLegacyId() -> String {
94
+ preconditionFailure("Must override in concrete class")
95
+ }
96
+
97
+ /**
98
+ A stable immutable scoping key for this experience. Should be used for scoping data on the
99
+ client for this project when running in Expo Go.
100
+ */
101
+ public func scopeKey() -> String {
102
+ preconditionFailure("Must override in concrete class")
103
+ }
104
+
105
+ /**
106
+ A stable UUID for this EAS project. Should be used to call EAS APIs.
107
+ */
108
+ public func easProjectId() -> String? {
109
+ preconditionFailure("Must override in concrete class")
110
+ }
111
+
112
+ /**
113
+ Get the SDK version that should be attempted to be used in Expo Go. If no SDK version can be
114
+ determined, returns null
115
+ */
116
+ public func expoGoSDKVersion() -> String? {
117
+ preconditionFailure("Must override in concrete class")
118
+ }
119
+
120
+ public func bundleUrl() -> String {
121
+ preconditionFailure("Must override in concrete class")
122
+ }
123
+
124
+ func expoGoConfigRootObject() -> [String: Any]? {
125
+ preconditionFailure("Must override in concrete class")
126
+ }
127
+
128
+ func expoClientConfigRootObject() -> [String: Any]? {
129
+ preconditionFailure("Must override in concrete class")
130
+ }
131
+
132
+ // MARK: - Field Getters
133
+ /**
134
+ The legacy ID of this experience.
135
+ - For Bare manifests, formatted as a UUID.
136
+ - For Legacy manifests, formatted as @owner/slug. Not stable through project transfers.
137
+ - For New manifests, currently incorrect value is UUID.
138
+ Use this in cases where an identifier of the current manifest is needed (experience loading for example).
139
+ Use scopeKey for cases where a stable key is needed to scope data to this experience.
140
+ Use easProjectId for cases where a stable UUID identifier of the experience is needed to identify over EAS APIs.
141
+ Use stableLegacyId for cases where a stable legacy format identifier of the experience is needed
142
+ (experience scoping for example).
143
+ */
144
+ @available(*, deprecated, message: "Prefer scopeKey or projectId depending on use case")
145
+ public func legacyId() -> String {
146
+ return rawManifestJSONInternal.requiredValue(forKey: "id")
147
+ }
148
+
149
+ public func revisionId() -> String? {
150
+ return expoClientConfigRootObject()?.optionalValue(forKey: "revisionId")
151
+ }
152
+
153
+ public func slug() -> String? {
154
+ return expoClientConfigRootObject()?.optionalValue(forKey: "slug")
155
+ }
156
+
157
+ public func appKey() -> String? {
158
+ return expoClientConfigRootObject()?.optionalValue(forKey: "appKey")
159
+ }
160
+
161
+ public func isVerified() -> Bool {
162
+ return rawManifestJSONInternal.optionalValue(forKey: "isVerified") ?? false
163
+ }
164
+
165
+ public func name() -> String? {
166
+ return expoClientConfigRootObject()?.optionalValue(forKey: "name")
167
+ }
168
+
169
+ public func version() -> String? {
170
+ return expoClientConfigRootObject()?.optionalValue(forKey: "version")
171
+ }
172
+
173
+ public func notificationPreferences() -> [String: Any]? {
174
+ return expoClientConfigRootObject()?.optionalValue(forKey: "notification")
175
+ }
176
+
177
+ public func updatesInfo() -> [String: Any]? {
178
+ return expoClientConfigRootObject()?.optionalValue(forKey: "updates")
179
+ }
180
+
181
+ public func iosConfig() -> [String: Any]? {
182
+ return expoClientConfigRootObject()?.optionalValue(forKey: "ios")
183
+ }
184
+
185
+ public func hostUri() -> String? {
186
+ return expoClientConfigRootObject()?.optionalValue(forKey: "hostUri")
187
+ }
188
+
189
+ public func orientation() -> String? {
190
+ return expoClientConfigRootObject()?.optionalValue(forKey: "orientation")
191
+ }
192
+
193
+ public func experiments() -> [String: Any]? {
194
+ return expoClientConfigRootObject()?.optionalValue(forKey: "experiments")
195
+ }
196
+
197
+ public func developer() -> [String: Any]? {
198
+ return expoGoConfigRootObject()?.optionalValue(forKey: "developer")
199
+ }
200
+
201
+ public func logUrl() -> String? {
202
+ return expoGoConfigRootObject()?.optionalValue(forKey: "logUrl")
203
+ }
204
+
205
+ public func facebookAppId() -> String? {
206
+ return expoClientConfigRootObject()?.optionalValue(forKey: "facebookAppId")
207
+ }
208
+
209
+ public func facebookApplicationName() -> String? {
210
+ return expoClientConfigRootObject()?.optionalValue(forKey: "facebookDisplayName")
211
+ }
212
+
213
+ public func facebookAutoInitEnabled() -> Bool {
214
+ return expoClientConfigRootObject()?.optionalValue(forKey: "facebookAutoInitEnabled") ?? false
215
+ }
216
+
217
+ // MARK: - Derived Methods
218
+ public func isDevelopmentMode() -> Bool {
219
+ guard let expoGoConfigRootObject = expoGoConfigRootObject(),
220
+ let packagerOptsConfig: [String: Any]? = expoGoConfigRootObject.optionalValue(forKey: "packagerOpts"),
221
+ let dev = packagerOptsConfig?["dev"] else {
222
+ return false
223
+ }
224
+
225
+ if developer() == nil {
226
+ return false
227
+ }
228
+
229
+ guard let dev = dev as? Bool else {
230
+ return false
231
+ }
232
+ return dev
233
+ }
234
+
235
+ public func isDevelopmentSilentLaunch() -> Bool {
236
+ guard let expoGoConfigRootObject = expoGoConfigRootObject(),
237
+ let developmentClientSettings: [String: Any]? =
238
+ expoGoConfigRootObject.optionalValue(forKey: "developmentClient"),
239
+ let silentLaunch = developmentClientSettings?["silentLaunch"] else {
240
+ return false
241
+ }
242
+
243
+ guard let silentLaunch = silentLaunch as? Bool else {
244
+ return false
245
+ }
246
+ return silentLaunch
247
+ }
248
+
249
+ public func isUsingDeveloperTool() -> Bool {
250
+ return developer()?["tool"] != nil
251
+ }
252
+
253
+ public func userInterfaceStyle() -> String? {
254
+ return iosConfig()?.optionalValue(forKey: "userInterfaceStyle") ??
255
+ (expoClientConfigRootObject()?.optionalValue(forKey: "userInterfaceStyle"))
256
+ }
257
+
258
+ public func iosOrRootBackgroundColor() -> String? {
259
+ return iosConfig()?.optionalValue(forKey: "backgroundColor") ??
260
+ (expoClientConfigRootObject()?.optionalValue(forKey: "backgroundColor"))
261
+ }
262
+
263
+ public func iosSplashBackgroundColor() -> String? {
264
+ return expoClientConfigRootObject().let { it in
265
+ Manifest.string(fromManifest: it, atPaths: [
266
+ ["ios", "splash", "backgroundColor"],
267
+ ["splash", "backgroundColor"]
268
+ ])
269
+ }
270
+ }
271
+
272
+ public func iosSplashImageUrl() -> String? {
273
+ return expoClientConfigRootObject().let { it in
274
+ Manifest.string(fromManifest: it, atPaths: [
275
+ UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad
276
+ ? ["ios", "splash", "tabletImageUrl"] : [],
277
+ ["ios", "splash", "imageUrl"],
278
+ ["splash", "imageUrl"]
279
+ ])
280
+ }
281
+ }
282
+
283
+ public func iosSplashImageResizeMode() -> String? {
284
+ return expoClientConfigRootObject().let { it in
285
+ Manifest.string(fromManifest: it, atPaths: [
286
+ ["ios", "splash", "resizeMode"],
287
+ ["splash", "resizeMode"]
288
+ ])
289
+ }
290
+ }
291
+
292
+ public func iosGoogleServicesFile() -> String? {
293
+ return iosConfig()?.optionalValue(forKey: "googleServicesFile")
294
+ }
295
+
296
+ public func supportsRTL() -> Bool {
297
+ guard let expoClientConfigRootObject = expoClientConfigRootObject(),
298
+ let extra: [String: Any]? = expoClientConfigRootObject.optionalValue(forKey: "extra"),
299
+ let supportsRTL: Bool = extra?.optionalValue(forKey: "supportsRTL") else {
300
+ return false
301
+ }
302
+
303
+ return supportsRTL
304
+ }
305
+
306
+ public func jsEngine() -> String {
307
+ let jsEngine = expoClientConfigRootObject().let { it in
308
+ Manifest.string(fromManifest: it, atPaths: [
309
+ ["ios", "jsEngine"],
310
+ ["jsEngine"]
311
+ ])
312
+ }
313
+
314
+ guard let jsEngine = jsEngine else {
315
+ let sdkMajorVersion = expoGoSDKMajorVersion()
316
+ if sdkMajorVersion > 0 && sdkMajorVersion < 48 {
317
+ return "jsc"
318
+ } else {
319
+ return "hermes"
320
+ }
321
+ }
322
+ return jsEngine
323
+ }
324
+
325
+ private func expoGoSDKMajorVersion() -> Int {
326
+ let sdkVersion = expoGoSDKVersion()
327
+ let components = sdkVersion?.components(separatedBy: ".")
328
+ guard let components = components else {
329
+ return 0
330
+ }
331
+ if components.count == 3 {
332
+ return Int(components[0]) ?? 0
333
+ }
334
+ return 0
335
+ }
336
+
337
+ private static func string(fromManifest: [String: Any], atPaths: [[String]]) -> String? {
338
+ for path in atPaths {
339
+ if let result = string(fromManifest: fromManifest, atPath: path) {
340
+ return result
341
+ }
342
+ }
343
+ return nil
344
+ }
345
+
346
+ private static func string(fromManifest: [String: Any], atPath: [String]) -> String? {
347
+ var json = fromManifest
348
+ for i in 0..<atPath.count {
349
+ let isLastKey = i == atPath.count - 1
350
+ let key = atPath[i]
351
+ let value = json[key]
352
+ if isLastKey, let value = value as? String {
353
+ return value
354
+ }
355
+ guard let newJson = value else {
356
+ return nil
357
+ }
358
+ // swiftlint:disable:next force_cast
359
+ json = newJson as! [String: Any]
360
+ }
361
+ return nil
362
+ }
363
+ }
@@ -0,0 +1,17 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ @objc(EXManifestsManifestFactory)
6
+ @objcMembers
7
+ public class ManifestFactory: NSObject {
8
+ public static func manifest(forManifestJSON: [String: Any]) -> Manifest {
9
+ if forManifestJSON["releaseId"] != nil {
10
+ return LegacyManifest(rawManifestJSON: forManifestJSON)
11
+ } else if forManifestJSON["metadata"] != nil {
12
+ return NewManifest(rawManifestJSON: forManifestJSON)
13
+ } else {
14
+ return BareManifest(rawManifestJSON: forManifestJSON)
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,83 @@
1
+ // Copyright © 2021 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ @objc(EXManifestsNewManifest)
6
+ @objcMembers
7
+ public class NewManifest: Manifest {
8
+ public func rawId() -> String {
9
+ return rawManifestJSON().requiredValue(forKey: "id")
10
+ }
11
+
12
+ public override func stableLegacyId() -> String {
13
+ return rawId()
14
+ }
15
+
16
+ public override func scopeKey() -> String {
17
+ let extra: [String: Any] = rawManifestJSON().requiredValue(forKey: "extra")
18
+ return extra.requiredValue(forKey: "scopeKey")
19
+ }
20
+
21
+ private func extra() -> [String: Any]? {
22
+ return rawManifestJSON().optionalValue(forKey: "extra")
23
+ }
24
+
25
+ public override func easProjectId() -> String? {
26
+ guard let easConfig: [String: Any] = extra()?.optionalValue(forKey: "eas") else {
27
+ return nil
28
+ }
29
+ return easConfig.optionalValue(forKey: "projectId")
30
+ }
31
+
32
+ public func createdAt() -> String {
33
+ return rawManifestJSON().requiredValue(forKey: "createdAt")
34
+ }
35
+
36
+ public func runtimeVersion() -> String {
37
+ return rawManifestJSON().requiredValue(forKey: "runtimeVersion")
38
+ }
39
+
40
+ private func getSDKVersionFromRuntimeVersion() -> String? {
41
+ let runtimeVersion = runtimeVersion()
42
+ if runtimeVersion == "exposdk:UNVERSIONED" {
43
+ return "UNVERSIONED"
44
+ }
45
+
46
+ // The pattern is valid, so it'll never throw
47
+ // swiftlint:disable:next force_try
48
+ let regex = try! NSRegularExpression(pattern: "^exposdk:(\\d+\\.\\d+\\.\\d+)$", options: [])
49
+ guard let match = regex.firstMatch(
50
+ in: runtimeVersion,
51
+ options: [],
52
+ range: NSRange(runtimeVersion.startIndex..<runtimeVersion.endIndex, in: runtimeVersion)
53
+ ),
54
+ let range = Range(match.range(at: 1), in: runtimeVersion) else {
55
+ return nil
56
+ }
57
+ return String(runtimeVersion[range])
58
+ }
59
+
60
+ public override func expoGoSDKVersion() -> String? {
61
+ return expoClientConfigRootObject()?.optionalValue(forKey: "sdkVersion") ?? getSDKVersionFromRuntimeVersion()
62
+ }
63
+
64
+ public func launchAsset() -> [String: Any] {
65
+ return rawManifestJSON().requiredValue(forKey: "launchAsset")
66
+ }
67
+
68
+ public func assets() -> [[String: Any]]? {
69
+ return rawManifestJSON().optionalValue(forKey: "assets")
70
+ }
71
+
72
+ public override func bundleUrl() -> String {
73
+ return launchAsset().requiredValue(forKey: "url")
74
+ }
75
+
76
+ override func expoClientConfigRootObject() -> [String: Any]? {
77
+ return extra()?.optionalValue(forKey: "expoClient")
78
+ }
79
+
80
+ override func expoGoConfigRootObject() -> [String: Any]? {
81
+ return extra()?.optionalValue(forKey: "expoGo")
82
+ }
83
+ }