expo-manifests 0.6.0 → 0.7.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/CHANGELOG.md CHANGED
@@ -10,6 +10,20 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.7.0 — 2023-06-21
14
+
15
+ ### 📚 3rd party library updates
16
+
17
+ - Updated `junit` to `4.13.2`. ([#22395](https://github.com/expo/expo/pull/22395) by [@josephyanks](https://github.com/josephyanks))
18
+
19
+ ### 🎉 New features
20
+
21
+ - Added `Manifests.getPluginProperties()` helper to query dedicated package's properties inside the `plugins` config. ([#22701](https://github.com/expo/expo/pull/22701) by [@kudo](https://github.com/kudo))
22
+
23
+ ### 🐛 Bug fixes
24
+
25
+ - Fixed Android build warnings for Gradle version 8. ([#22537](https://github.com/expo/expo/pull/22537), [#22609](https://github.com/expo/expo/pull/22609) by [@kudo](https://github.com/kudo))
26
+
13
27
  ## 0.6.0 — 2023-05-08
14
28
 
15
29
  ### 🎉 New features
@@ -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.6.0'
6
+ version = '0.7.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -35,19 +35,11 @@ buildscript {
35
35
  }
36
36
  }
37
37
 
38
- // Creating sources with comments
39
- task androidSourcesJar(type: Jar) {
40
- classifier = 'sources'
41
- from android.sourceSets.main.java.srcDirs
42
- }
43
-
44
38
  afterEvaluate {
45
39
  publishing {
46
40
  publications {
47
41
  release(MavenPublication) {
48
42
  from components.release
49
- // Add additional sourcesJar to artifacts
50
- artifact(androidSourcesJar)
51
43
  }
52
44
  }
53
45
  repositories {
@@ -70,11 +62,12 @@ android {
70
62
  jvmTarget = JavaVersion.VERSION_11.majorVersion
71
63
  }
72
64
 
65
+ namespace "expo.modules.manifests"
73
66
  defaultConfig {
74
67
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
68
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
69
  versionCode 31
77
- versionName '0.6.0'
70
+ versionName '0.7.0'
78
71
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
79
72
  }
80
73
  lintOptions {
@@ -86,21 +79,22 @@ android {
86
79
  sourceSets {
87
80
  androidTest.assets.srcDirs += files("$projectDir/src/androidTest/schemas".toString())
88
81
  }
82
+ publishing {
83
+ singleVariant("release") {
84
+ withSourcesJar()
85
+ }
86
+ }
89
87
  }
90
88
 
91
89
  dependencies {
92
90
  implementation project(':expo-json-utils')
93
91
 
94
- testImplementation 'junit:junit:4.12'
95
- testImplementation 'androidx.test:core:1.4.0'
96
- testImplementation 'org.mockito:mockito-core:1.10.19'
97
- testImplementation 'io.mockk:mockk:1.12.3'
98
-
99
- androidTestImplementation 'androidx.test:runner:1.4.0'
100
- androidTestImplementation 'androidx.test:core:1.4.0'
101
- androidTestImplementation 'androidx.test:rules:1.4.0'
102
- androidTestImplementation 'org.mockito:mockito-android:3.7.7'
103
- androidTestImplementation 'io.mockk:mockk-android:1.12.3'
92
+ testImplementation 'junit:junit:4.13.2'
93
+ testImplementation 'androidx.test:core:1.5.0'
94
+ testImplementation 'org.mockito:mockito-core:4.0.0'
95
+ testImplementation 'io.mockk:mockk:1.13.5'
96
+ testImplementation 'org.json:json:20230227'
97
+ testImplementation "com.google.truth:truth:1.1.2"
104
98
 
105
99
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
106
100
  }
@@ -1,3 +1,2 @@
1
- <manifest package="expo.modules.manifests"
2
- xmlns:android="http://schemas.android.com/apk/res/android">
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
2
  </manifest>
@@ -0,0 +1,17 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ package expo.modules.manifests.core
4
+
5
+ import org.json.JSONObject
6
+
7
+ /**
8
+ * Convert a [JSONObject] to Map<String, Any> recursively
9
+ */
10
+ fun JSONObject.toMap(): Map<String, Any> {
11
+ return keys().asSequence().associateWith {
12
+ when (val value = this@toMap[it]) {
13
+ is JSONObject -> value.toMap()
14
+ else -> value
15
+ }
16
+ }
17
+ }
@@ -230,6 +230,18 @@ abstract class Manifest(protected val json: JSONObject) {
230
230
  @Throws(JSONException::class)
231
231
  fun getFacebookAutoInitEnabled(): Boolean = getExpoClientConfigRootObject()!!.require("facebookAutoInitEnabled")
232
232
 
233
+ /**
234
+ * Queries the dedicated package properties in `plugins`
235
+ */
236
+ @Throws(JSONException::class, IllegalArgumentException::class)
237
+ fun getPluginProperties(packageName: String): Map<String, Any>? {
238
+ val pluginsRawValue = getExpoClientConfigRootObject()?.getNullable<JSONArray>("plugins") ?: return null
239
+ val plugins = PluginType.fromRawArrayValue(pluginsRawValue) ?: return null
240
+ return plugins.filterIsInstance<PluginType.WithProps>()
241
+ .firstOrNull { it.plugin.first == packageName }
242
+ ?.plugin?.second
243
+ }
244
+
233
245
  companion object {
234
246
  @JvmStatic fun fromManifestJson(manifestJson: JSONObject): Manifest {
235
247
  return when {
@@ -246,3 +258,41 @@ abstract class Manifest(protected val json: JSONObject) {
246
258
  }
247
259
  }
248
260
  }
261
+
262
+ internal typealias PluginWithProps = Pair<String, Map<String, Any>>
263
+ internal typealias PluginWithoutProps = String
264
+ internal sealed class PluginType {
265
+ data class WithProps(val plugin: PluginWithProps) : PluginType()
266
+ data class WithoutProps(val plugin: PluginWithoutProps) : PluginType()
267
+
268
+ companion object {
269
+ @Throws(IllegalArgumentException::class)
270
+ private fun fromRawValue(value: Any): PluginType? {
271
+ return when (value) {
272
+ is JSONArray -> {
273
+ if (value.length() != 2) {
274
+ throw IllegalArgumentException("Value for (key = plugins) has incorrect type")
275
+ }
276
+ val name = value.get(0) as? String ?: return null
277
+ val props = value.get(1) as? JSONObject ?: return null
278
+ WithProps(name to props.toMap())
279
+ }
280
+ is String -> {
281
+ WithoutProps(value)
282
+ }
283
+ else -> throw IllegalArgumentException("Value for (key = plugins) has incorrect type")
284
+ }
285
+ }
286
+
287
+ @Throws(IllegalArgumentException::class)
288
+ fun fromRawArrayValue(value: JSONArray): List<PluginType> {
289
+ return mutableListOf<PluginType>().apply {
290
+ for (i in 0 until value.length()) {
291
+ fromRawValue(value.get(i))?.let {
292
+ add(it)
293
+ }
294
+ }
295
+ }
296
+ }
297
+ }
298
+ }
@@ -0,0 +1,59 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ package expo.modules.manifests.core
4
+
5
+ import com.google.common.truth.Truth
6
+ import org.json.JSONObject
7
+ import org.junit.Test
8
+
9
+ class ManifestTest {
10
+ @Test
11
+ fun getPluginProperties_emptyManifest_returnsNull() {
12
+ val manifestJson = JSONObject(emptyMap<String, Any>())
13
+ val manifest = Manifest.fromManifestJson(manifestJson)
14
+ Truth.assertThat(manifest.getPluginProperties("test")).isNull()
15
+ }
16
+
17
+ @Test
18
+ fun getPluginProperties_emptyPlugins_returnsNull() {
19
+ val manifestJson = JSONObject(mapOf<String, Any>("plugins" to emptyArray<Any>()))
20
+ val manifest = Manifest.fromManifestJson(manifestJson)
21
+ Truth.assertThat(manifest.getPluginProperties("test")).isNull()
22
+ }
23
+
24
+ @Test
25
+ fun getPluginProperties_nonMatchedPlugins_returnsNull() {
26
+ val manifestJson = JSONObject(mapOf<String, Any>("plugins" to arrayOf("hello")))
27
+ val manifest = Manifest.fromManifestJson(manifestJson)
28
+ Truth.assertThat(manifest.getPluginProperties("test")).isNull()
29
+ }
30
+
31
+ @Test
32
+ fun getPluginProperties_matchedPluginWithoutProps_returnsNull() {
33
+ val manifestJson = JSONObject(mapOf<String, Any>("plugins" to arrayOf("test")))
34
+ val manifest = Manifest.fromManifestJson(manifestJson)
35
+ Truth.assertThat(manifest.getPluginProperties("test")).isNull()
36
+ }
37
+
38
+ @Test
39
+ fun getPluginProperties_matchedPluginWithProps_returnsProps() {
40
+ val props = mapOf<String, Any>("foo" to "bar")
41
+ val pluginWithProp = arrayOf("test", props)
42
+ val manifestJson = JSONObject(mapOf<String, Any>("plugins" to arrayOf(pluginWithProp)))
43
+ val manifest = Manifest.fromManifestJson(manifestJson)
44
+ val result = manifest.getPluginProperties("test")
45
+ Truth.assertThat(result).isNotNull()
46
+ Truth.assertThat(result).containsExactlyEntriesIn(props)
47
+ }
48
+
49
+ @Test
50
+ fun getPluginProperties_matchedPluginWithNestedProps_returnsNestedProps() {
51
+ val props = mapOf<String, Any>("nested" to mapOf<String, Any>("insideNested" to true))
52
+ val pluginWithProp = arrayOf("test", props)
53
+ val manifestJson = JSONObject(mapOf<String, Any>("plugins" to arrayOf(pluginWithProp)))
54
+ val manifest = Manifest.fromManifestJson(manifestJson)
55
+ val result = manifest.getPluginProperties("test")
56
+ Truth.assertThat(result).isNotNull()
57
+ Truth.assertThat(result).containsExactlyEntriesIn(props)
58
+ }
59
+ }
@@ -1,12 +1,9 @@
1
1
  package expo.modules.manifests.core
2
2
 
3
- import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
4
3
  import org.json.JSONObject
5
4
  import org.junit.Assert
6
5
  import org.junit.Test
7
- import org.junit.runner.RunWith
8
6
 
9
- @RunWith(AndroidJUnit4ClassRunner::class)
10
7
  class NewManifestTest {
11
8
  @Test
12
9
  @Throws(Exception::class)
@@ -3,7 +3,7 @@
3
3
  // this uses abstract class patterns
4
4
  // swiftlint:disable unavailable_function
5
5
 
6
- // swiftlint:disable type_body_length
6
+ // swiftlint:disable type_body_length file_length
7
7
 
8
8
  import Foundation
9
9
  import UIKit
@@ -322,6 +322,56 @@ public class Manifest: NSObject {
322
322
  return jsEngine
323
323
  }
324
324
 
325
+ /**
326
+ Queries the dedicated package properties in `plugins`
327
+ */
328
+ public func getPluginProperties(packageName: String) -> [String: Any]? {
329
+ typealias PluginWithProps = (String, [String: Any])
330
+ typealias PluginWithoutProps = String
331
+ enum PluginType {
332
+ case withProps (PluginWithProps)
333
+ case withoutProps (PluginWithoutProps)
334
+
335
+ private static func fromRawValue(_ optionalValue: Any?) -> PluginType? {
336
+ guard let value = optionalValue else {
337
+ return nil
338
+ }
339
+ if let valueArray = value as? [Any],
340
+ let name = valueArray[0] as? String, let props = valueArray[1] as? [String: Any] {
341
+ return .withProps((name, props))
342
+ }
343
+ if let value = value as? String {
344
+ return .withoutProps(value)
345
+ }
346
+ let exception = NSException(
347
+ name: NSExceptionName.internalInconsistencyException,
348
+ reason: "Value for (key = plugins) has incorrect type",
349
+ userInfo: ["key": "plugins"]
350
+ )
351
+ exception.raise()
352
+ return nil
353
+ }
354
+
355
+ static func fromRawArrayValue(_ value: [Any]) -> [PluginType]? {
356
+ return value.compactMap { fromRawValue($0) }
357
+ }
358
+ }
359
+
360
+ guard let pluginsRawValue = expoClientConfigRootObject()?.optionalValue(forKey: "plugins") as [Any]?,
361
+ let plugins = PluginType.fromRawArrayValue(pluginsRawValue) else {
362
+ return nil
363
+ }
364
+
365
+ let firstMatchedPlugin = plugins.compactMap { item in
366
+ if case .withProps(let tuple) = item, tuple.0 == packageName {
367
+ return tuple
368
+ }
369
+ return nil
370
+ }.first
371
+
372
+ return firstMatchedPlugin?.1
373
+ }
374
+
325
375
  private func expoGoSDKMajorVersion() -> Int {
326
376
  let sdkVersion = expoGoSDKVersion()
327
377
  let components = sdkVersion?.components(separatedBy: ".")
@@ -0,0 +1,38 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesTestCore
4
+
5
+ @testable import EXManifests
6
+
7
+ final class ManifestSpec: ExpoSpec {
8
+ override func spec() {
9
+ describe("getPluginProperties") {
10
+ it("should return nil when plugin is not matched") {
11
+ var manifestJson: [String: Any] = [:]
12
+ var manifest = ManifestFactory.manifest(forManifestJSON: manifestJson)
13
+ expect(manifest.getPluginProperties(packageName: "test")).to(beNil())
14
+
15
+ manifestJson = ["plugins": []]
16
+ manifest = ManifestFactory.manifest(forManifestJSON: manifestJson)
17
+ expect(manifest.getPluginProperties(packageName: "test")).to(beNil())
18
+
19
+ manifestJson = ["plugins": ["hello"]]
20
+ manifest = ManifestFactory.manifest(forManifestJSON: manifestJson)
21
+ expect(manifest.getPluginProperties(packageName: "test")).to(beNil())
22
+ }
23
+
24
+ it("should return nil when the matched plugin has no properties") {
25
+ let manifestJson = ["plugins": ["test"]]
26
+ let manifest = ManifestFactory.manifest(forManifestJSON: manifestJson)
27
+ expect(manifest.getPluginProperties(packageName: "test")).to(beNil())
28
+ }
29
+
30
+ it("should return matched plugin properties") {
31
+ let manifestJson = ["plugins": [["test", ["foo": "bar"]]]]
32
+ let manifest = ManifestFactory.manifest(forManifestJSON: manifestJson)
33
+ let props = manifest.getPluginProperties(packageName: "test")
34
+ expect(props as? [String: String]) == ["foo": "bar"]
35
+ }
36
+ }
37
+ }
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-manifests",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Code to parse and use Expo and Expo Updates manifests.",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "homepage": "https://docs.expo.dev/versions/latest/sdk/module-template",
22
22
  "dependencies": {
23
- "expo-json-utils": "~0.6.0"
23
+ "expo-json-utils": "~0.7.0"
24
24
  },
25
- "gitHead": "4ba50c428c8369bb6b3a51a860d4898ad4ccbe78"
25
+ "gitHead": "fa5ecca8251986b9f197cc14074eec0ab6dfb6db"
26
26
  }