1 import UIKit
2 
3 /**
4  Extends all modules with the functions used to build a module definition.
5  Unfortunately they need to be scoped here, but hopefully this proposal
6  https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md#builder-scoped-name-lookup
7  will be implemented in the future.
8  */
9 extension AnyModule {
10   // MARK: - Module name
11 
12   /**
13    Sets the name of the module that is exported to the JavaScript world.
14    */
15   public func name(_ name: String) -> AnyDefinition {
16     return ModuleNameDefinition(name: name)
17   }
18 
19   // MARK: - Constants
20 
21   /**
22    Definition function setting the module's constants to export.
23    */
24   public func constants(_ closure: () -> [String : Any?]) -> AnyDefinition {
25     return ConstantsDefinition(constants: closure())
26   }
27 
28   // MARK: - Methods
29 
30   /**
31    Factory function for methods without arguments.
32    */
33   public func method<R>(
34     _ name: String,
35     _ closure: @escaping () -> R
36   ) -> AnyMethod {
37     return ConcreteMethod(
38       name,
39       argTypes: [],
40       closure
41     )
42   }
43 
44   /**
45    Factory function for methods with one argument.
46    */
47   public func method<R, A0: AnyMethodArgument>(
48     _ name: String,
49     _ closure: @escaping (A0) -> R
50   ) -> AnyMethod {
51     return ConcreteMethod(
52       name,
53       argTypes: [AnyArgumentType(A0.self)],
54       closure
55     )
56   }
57 
58   /**
59    Factory function for methods with 2 arguments.
60    */
61   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument>(
62     _ name: String,
63     _ closure: @escaping (A0, A1) -> R
64   ) -> AnyMethod {
65     return ConcreteMethod(
66       name,
67       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self)],
68       closure
69     )
70   }
71 
72   /**
73    Factory function for methods with 3 arguments.
74    */
75   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument>(
76     _ name: String,
77     _ closure: @escaping (A0, A1, A2) -> R
78   ) -> AnyMethod {
79     return ConcreteMethod(
80       name,
81       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self)],
82       closure
83     )
84   }
85 
86   /**
87    Factory function for methods with 4 arguments.
88    */
89   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument, A3: AnyMethodArgument>(
90     _ name: String,
91     _ closure: @escaping (A0, A1, A2, A3) -> R
92   ) -> AnyMethod {
93     return ConcreteMethod(
94       name,
95       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self), AnyArgumentType(A3.self)],
96       closure
97     )
98   }
99 
100   /**
101    Factory function for methods with 5 arguments.
102    */
103   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument, A3: AnyMethodArgument, A4: AnyMethodArgument>(
104     _ name: String,
105     _ closure: @escaping (A0, A1, A2, A3, A4) -> R
106   ) -> AnyMethod {
107     return ConcreteMethod(
108       name,
109       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self), AnyArgumentType(A3.self), AnyArgumentType(A4.self)],
110       closure
111     )
112   }
113 
114   /**
115    Factory function for methods with 6 arguments.
116    */
117   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument, A3: AnyMethodArgument, A4: AnyMethodArgument, A5: AnyMethodArgument>(
118     _ name: String,
119     _ closure: @escaping (A0, A1, A2, A3, A4, A5) -> R
120   ) -> AnyMethod {
121     return ConcreteMethod(
122       name,
123       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self), AnyArgumentType(A3.self), AnyArgumentType(A4.self), AnyArgumentType(A5.self)],
124       closure
125     )
126   }
127 
128   /**
129    Factory function for methods with 7 arguments.
130    */
131   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument, A3: AnyMethodArgument, A4: AnyMethodArgument, A5: AnyMethodArgument, A6: AnyMethodArgument>(
132     _ name: String,
133     _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) -> R
134   ) -> AnyMethod {
135     return ConcreteMethod(
136       name,
137       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self), AnyArgumentType(A3.self), AnyArgumentType(A4.self), AnyArgumentType(A5.self), AnyArgumentType(A6.self)],
138       closure
139     )
140   }
141 
142   /**
143    Factory function for methods with 8 arguments.
144    */
145   public func method<R, A0: AnyMethodArgument, A1: AnyMethodArgument, A2: AnyMethodArgument, A3: AnyMethodArgument, A4: AnyMethodArgument, A5: AnyMethodArgument, A6: AnyMethodArgument, A7: AnyMethodArgument>(
146     _ name: String,
147     _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) -> R
148   ) -> AnyMethod {
149     return ConcreteMethod(
150       name,
151       argTypes: [AnyArgumentType(A0.self), AnyArgumentType(A1.self), AnyArgumentType(A2.self), AnyArgumentType(A3.self), AnyArgumentType(A4.self), AnyArgumentType(A5.self), AnyArgumentType(A6.self), AnyArgumentType(A7.self)],
152       closure
153     )
154   }
155 
156   // MARK: - Module's lifecycle
157 
158   /**
159    Creates module's lifecycle listener that is called right after module initialization.
160    */
161   public func onCreate(_ closure: @escaping () -> Void) -> AnyDefinition {
162     return EventListener(.moduleCreate, closure)
163   }
164 
165   /**
166    Creates module's lifecycle listener that is called when the module is about to be deallocated.
167    */
168   public func onDestroy(_ closure: @escaping () -> Void) -> AnyDefinition {
169     return EventListener(.moduleDestroy, closure)
170   }
171 
172   /**
173    Creates module's lifecycle listener that is called when the app context owning the module is about to be deallocated.
174    */
175   public func onAppContextDestroys(_ closure: @escaping () -> Void) -> AnyDefinition {
176     return EventListener(.appContextDestroys, closure)
177   }
178 
179   /**
180    Creates a listener that is called when the app is about to enter the foreground mode.
181    */
182   public func onAppEntersForeground(_ closure: @escaping () -> Void) -> AnyDefinition {
183     return EventListener(.appEntersForeground, closure)
184   }
185 
186   /**
187    Creates a listener that is called when the app becomes active again.
188    */
189   public func onAppBecomesActive(_ closure: @escaping () -> Void) -> AnyDefinition {
190     return EventListener(.appBecomesActive, closure)
191   }
192 
193   /**
194    Creates a listener that is called when the app enters the background mode.
195    */
196   public func onAppEntersBackground(_ closure: @escaping () -> Void) -> AnyDefinition {
197     return EventListener(.appEntersBackground, closure)
198   }
199 
200   // MARK: - View Manager
201 
202   /**
203    Creates the view manager definition that scopes other view-related definitions.
204    */
205   public func viewManager(@ViewManagerDefinitionBuilder _ closure: @escaping () -> ViewManagerDefinition) -> AnyDefinition {
206     return closure()
207   }
208 
209   // MARK: - Events
210 
211   /**
212    Defines event names that this module can send to JavaScript.
213    */
214   public func events(_ names: String...) -> AnyDefinition {
215     return EventsDefinition(names: names)
216   }
217 
218   /**
219    Method that is invoked when the first event listener is added.
220    */
221   public func onStartObserving(_ body: @escaping () -> ()) -> AnyMethod {
222     return ConcreteMethod("startObserving", argTypes: [], body)
223   }
224 
225   /**
226    Method that is invoked when all event listeners are removed.
227    */
228   public func onStopObserving(_ body: @escaping () -> ()) -> AnyMethod {
229     return ConcreteMethod("stopObserving", argTypes: [], body)
230   }
231 }
232 
233 /**
234  Defines the factory creating a native view when the module is used as a view.
235  */
236 public func view(_ closure: @escaping () -> UIView) -> AnyDefinition {
237   return ViewFactory(closure)
238 }
239 
240 /**
241  Creates a view prop that defines its name and setter.
242  */
243 public func prop<ViewType: UIView, PropType>(_ name: String, _ setter: @escaping (ViewType, PropType) -> Void) -> AnyDefinition {
244   return ConcreteViewProp(name, setter)
245 }
246