expo-modules-core 2.3.13 → 2.4.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 (35) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +22 -11
  4. package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +9 -1
  5. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +6 -0
  6. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +28 -24
  7. package/android/src/main/java/expo/modules/kotlin/jni/ExpectedType.kt +122 -5
  8. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +6 -1
  9. package/android/src/main/java/expo/modules/kotlin/modules/ModuleConvertersBuilder.kt +50 -0
  10. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +31 -7
  11. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +28 -30
  12. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionData.kt +15 -0
  13. package/android/src/main/java/expo/modules/kotlin/traits/SavableTrait.kt +57 -0
  14. package/android/src/main/java/expo/modules/kotlin/traits/Trait.kt +8 -0
  15. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +9 -0
  16. package/android/src/main/java/expo/modules/kotlin/types/EitherTypeConverter.kt +3 -3
  17. package/android/src/main/java/expo/modules/kotlin/types/ExpoDynamic.kt +57 -0
  18. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterCollection.kt +81 -0
  19. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +18 -3
  20. package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +40 -25
  21. package/ios/Api/Factories/ViewFactories.swift +16 -0
  22. package/ios/Core/Conversions.swift +51 -7
  23. package/ios/Core/Convertibles/Convertibles+Color.swift +1 -1
  24. package/ios/Core/DynamicTypes/DynamicSharedObjectType.swift +25 -14
  25. package/ios/Core/Functions/AsyncFunctionDefinition.swift +1 -1
  26. package/ios/Core/Promise.swift +0 -11
  27. package/ios/Core/Views/ConcreteViewProp.swift +16 -0
  28. package/ios/Core/Views/SwiftUI/Convertibles+SwiftUI.swift +62 -0
  29. package/ios/Core/Views/SwiftUI/SwiftUIHostingView.swift +7 -0
  30. package/ios/DevTools/ExpoRequestInterceptorProtocol.swift +14 -4
  31. package/ios/DevTools/ModuleDefinitionEncoder.swift +182 -0
  32. package/ios/ReactDelegates/ExpoReactDelegate.swift +2 -2
  33. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +1 -1
  34. package/ios/Tests/FunctionSpec.swift +27 -1
  35. package/package.json +2 -2
@@ -0,0 +1,182 @@
1
+ class ModuleDefinitionEncoder: Encodable {
2
+ private let definition: ModuleDefinition
3
+
4
+ init(_ definition: ModuleDefinition) {
5
+ self.definition = definition
6
+ }
7
+
8
+ enum CodingKeys: String, CodingKey {
9
+ case name
10
+ case functions
11
+ case properties
12
+ case constants
13
+ case views
14
+ }
15
+
16
+ func encode(to encoder: Encoder) throws {
17
+ var container = encoder.container(keyedBy: CodingKeys.self)
18
+ try container.encode(definition.name, forKey: .name)
19
+ try container.encode(definition.legacyConstants.map({ LegacyConstantsDefinitionEncoder($0) }), forKey: .constants)
20
+ try container.encode(definition.properties.values.map({ PropertyDefinitionEncoder($0) }), forKey: .properties)
21
+ try container.encode(definition.functions.values.map({ FunctionDefinitionEncoder($0) }), forKey: .functions)
22
+ try container.encode(definition.views.values.map({ ViewDefinitionEncoder($0) }), forKey: .views)
23
+ }
24
+ }
25
+
26
+ public class ModuleRegistryEncoder: Encodable {
27
+ private let registry: ModuleRegistry
28
+
29
+ public init(_ registry: ModuleRegistry) {
30
+ self.registry = registry
31
+ }
32
+
33
+ public func encode(to encoder: Encoder) throws {
34
+ var container = encoder.unkeyedContainer()
35
+ registry.getModuleNames().forEach {
36
+ guard let definition = registry.get(moduleWithName: $0)?.definition() else {
37
+ return
38
+ }
39
+ try? container.encode(ModuleDefinitionEncoder(definition))
40
+ }
41
+ }
42
+ }
43
+
44
+ class FunctionDefinitionEncoder: Encodable {
45
+ private let definition: any AnyFunctionDefinition
46
+
47
+ init(_ definition: any AnyFunctionDefinition) {
48
+ self.definition = definition
49
+ }
50
+
51
+ enum CodingKeys: String, CodingKey {
52
+ case name
53
+ case argumentsCount
54
+ }
55
+
56
+ func encode(to encoder: Encoder) throws {
57
+ var container = encoder.container(keyedBy: CodingKeys.self)
58
+ try container.encode(definition.name, forKey: .name)
59
+ try container.encode(definition.argumentsCount, forKey: .argumentsCount)
60
+ }
61
+ }
62
+
63
+ class ViewDefinitionEncoder: Encodable {
64
+ private let definition: any AnyViewDefinition
65
+
66
+ init(_ definition: any AnyViewDefinition) {
67
+ self.definition = definition
68
+ }
69
+
70
+ enum CodingKeys: String, CodingKey {
71
+ case name
72
+ case props
73
+ }
74
+
75
+ func encode(to encoder: Encoder) throws {
76
+ var container = encoder.container(keyedBy: CodingKeys.self)
77
+ try container.encode(definition.name, forKey: .name)
78
+ try container.encode(definition.props.map({ ViewPropEncoder($0) }), forKey: .props)
79
+ }
80
+ }
81
+
82
+ class ViewPropEncoder: Encodable {
83
+ private let definition: AnyViewProp
84
+
85
+ init(_ definition: AnyViewProp) {
86
+ self.definition = definition
87
+ }
88
+
89
+ enum CodingKeys: String, CodingKey {
90
+ case name
91
+ }
92
+
93
+ func encode(to encoder: Encoder) throws {
94
+ var container = encoder.container(keyedBy: CodingKeys.self)
95
+ try container.encode(definition.name, forKey: .name)
96
+ }
97
+ }
98
+
99
+ class ConstantEncoder: Encodable {
100
+ private let key: String
101
+ private let value: Any?
102
+
103
+ init(_ key: String, value: Any?) {
104
+ self.key = key
105
+ self.value = value
106
+ }
107
+
108
+ enum CodingKeys: String, CodingKey {
109
+ case name
110
+ case value
111
+ case type
112
+ }
113
+
114
+ func encode(to encoder: Encoder) throws {
115
+ var container = encoder.container(keyedBy: CodingKeys.self)
116
+ try container.encode(key, forKey: .name)
117
+ switch value {
118
+ case let value as String:
119
+ try container.encode(value, forKey: .value)
120
+ try container.encode("string", forKey: .type)
121
+ case let value as Bool:
122
+ try container.encode(value, forKey: .value)
123
+ try container.encode("boolean", forKey: .type)
124
+ case let value as Int:
125
+ try container.encode(value, forKey: .value)
126
+ try container.encode("number", forKey: .type)
127
+ case let value as Double:
128
+ try container.encode(value, forKey: .value)
129
+ try container.encode("number", forKey: .type)
130
+ case nil:
131
+ try container.encodeNil(forKey: .value)
132
+ try container.encode("null", forKey: .type)
133
+ case let value as Dictionary<String, Any>:
134
+ try container.encodeNil(forKey: .value)
135
+ try container.encode("object", forKey: .type)
136
+ case let value as Array<Any>:
137
+ try container.encodeNil(forKey: .value)
138
+ try container.encode("array", forKey: .type)
139
+ default:
140
+ try container.encodeNil(forKey: .value)
141
+ try container.encode("unknown", forKey: .type)
142
+ }
143
+ }
144
+ }
145
+
146
+ class LegacyConstantsDefinitionEncoder: Encodable {
147
+ private let definition: ConstantsDefinition
148
+
149
+ init(_ definition: ConstantsDefinition) {
150
+ self.definition = definition
151
+ }
152
+
153
+ enum CodingKeys: String, CodingKey {
154
+ case name
155
+ case value
156
+ }
157
+
158
+ func encode(to encoder: Encoder) throws {
159
+ var container = encoder.unkeyedContainer()
160
+ let constants = definition.body()
161
+ for (key, value) in constants {
162
+ try container.encode(ConstantEncoder(key, value: value))
163
+ }
164
+ }
165
+ }
166
+
167
+ class PropertyDefinitionEncoder: Encodable {
168
+ private let definition: any AnyPropertyDefinition
169
+
170
+ init(_ definition: any AnyPropertyDefinition) {
171
+ self.definition = definition
172
+ }
173
+
174
+ enum CodingKeys: String, CodingKey {
175
+ case name
176
+ }
177
+
178
+ func encode(to encoder: Encoder) throws {
179
+ var container = encoder.container(keyedBy: CodingKeys.self)
180
+ try container.encode(definition.name, forKey: .name)
181
+ }
182
+ }
@@ -17,7 +17,7 @@ public class ExpoReactDelegate: NSObject {
17
17
  initialProperties: [AnyHashable: Any]?,
18
18
  launchOptions: [UIApplication.LaunchOptionsKey: Any]?
19
19
  ) -> UIView {
20
- return self.handlers.lazy
20
+ return self.handlers
21
21
  .compactMap { $0.createReactRootView(reactDelegate: self, moduleName: moduleName, initialProperties: initialProperties, launchOptions: launchOptions) }
22
22
  .first(where: { _ in true })
23
23
  ?? {
@@ -45,7 +45,7 @@ public class ExpoReactDelegate: NSObject {
45
45
  @objc
46
46
  public func createRootViewController() -> UIViewController {
47
47
  return self.handlers.lazy
48
- .compactMap { $0.createRootViewController(reactDelegate: self) }
48
+ .compactMap { $0.createRootViewController() }
49
49
  .first(where: { _ in true }) ?? UIViewController()
50
50
  }
51
51
  }
@@ -35,7 +35,7 @@ open class ExpoReactDelegateHandler: NSObject {
35
35
  Otherwise return nil.
36
36
  */
37
37
  @objc
38
- open func createRootViewController(reactDelegate: ExpoReactDelegate) -> UIViewController? {
38
+ open func createRootViewController() -> UIViewController? {
39
39
  return nil
40
40
  }
41
41
  }
@@ -297,7 +297,11 @@ class FunctionSpec: ExpoSpec {
297
297
  AsyncFunction("withSharedObjectAsync") {
298
298
  return SharedString("Test")
299
299
  }
300
-
300
+
301
+ AsyncFunction("withArrayOfSharedObjectsAsync") {
302
+ return [SharedString("Test1"), SharedString("Test2"), SharedString("Test3")]
303
+ }
304
+
301
305
  AsyncFunction("withSharedObjectPromise") { (p: Promise) in
302
306
  p.resolve(SharedString("Test with Promise"))
303
307
  }
@@ -382,6 +386,28 @@ class FunctionSpec: ExpoSpec {
382
386
  expect(result.getString()) == "Test"
383
387
  }
384
388
 
389
+ it("returns an Array of SharedObjects (async)") {
390
+ try runtime
391
+ .eval(
392
+ "expo.modules.TestModule.withArrayOfSharedObjectsAsync().then((result) => { globalThis.resultArray = result; })"
393
+ )
394
+
395
+ expect(safeBoolEval("globalThis.resultArray != null")).toEventually(beTrue(), timeout: .milliseconds(2000))
396
+ let object = try runtime.eval("object = globalThis.resultArray")
397
+
398
+ expect(object.kind) == .object
399
+ expect(object.getObject().hasProperty("length")) == true
400
+
401
+ let result = object.getArray()
402
+ try result.enumerated().forEach { index, element in
403
+ expect(element.kind) == .object
404
+ expect(element.getObject().hasProperty("value")) == true
405
+ let value = try runtime.eval("object[\(index)].value")
406
+ expect(value.kind) == .string
407
+ expect(value.getString()) == "Test\(index + 1)"
408
+ }
409
+ }
410
+
385
411
  it("returns a SharedObject with Promise") {
386
412
  try runtime
387
413
  .eval(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "2.3.13",
3
+ "version": "2.4.0",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "src/index.ts",
6
6
  "types": "build/index.d.ts",
@@ -44,5 +44,5 @@
44
44
  "@testing-library/react-native": "^13.1.0",
45
45
  "expo-module-scripts": "^4.1.7"
46
46
  },
47
- "gitHead": "49c9d53cf0a9fc8179d1c8f5268beadd141f70ca"
47
+ "gitHead": "7638c800b57fe78f57cc7f129022f58e84a523c5"
48
48
  }