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(_ body: @escaping () -> [String: Any?]) -> AnyDefinition {
25     return ConstantsDefinition(body: body)
26   }
27 
28   /**
29    Definition function setting the module's constants to export.
30    */
31   public func constants(_ body: @autoclosure @escaping () -> [String: Any?]) -> AnyDefinition {
32     return ConstantsDefinition(body: body)
33   }
34 
35   // MARK: - Functions
36 
37   /**
38    Function without arguments.
39    */
40   public func function<R>(
41     _ name: String,
42     _ closure: @escaping () -> R
43   ) -> AnyFunction {
44     return ConcreteFunction(
45       name,
46       argTypes: [],
47       closure
48     )
49   }
50 
51   /**
52    Function with one argument.
53    */
54   public func function<R, A0: AnyArgument>(
55     _ name: String,
56     _ closure: @escaping (A0) -> R
57   ) -> AnyFunction {
58     return ConcreteFunction(
59       name,
60       argTypes: [ArgumentType(A0.self)],
61       closure
62     )
63   }
64 
65   /**
66    Function with two arguments.
67    */
68   public func function<R, A0: AnyArgument, A1: AnyArgument>(
69     _ name: String,
70     _ closure: @escaping (A0, A1) -> R
71   ) -> AnyFunction {
72     return ConcreteFunction(
73       name,
74       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
75       closure
76     )
77   }
78 
79   /**
80    Function with three arguments.
81    */
82   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
83     _ name: String,
84     _ closure: @escaping (A0, A1, A2) -> R
85   ) -> AnyFunction {
86     return ConcreteFunction(
87       name,
88       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self)],
89       closure
90     )
91   }
92 
93   /**
94    Function with four arguments.
95    */
96   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
97     _ name: String,
98     _ closure: @escaping (A0, A1, A2, A3) -> R
99   ) -> AnyFunction {
100     return ConcreteFunction(
101       name,
102       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self)],
103       closure
104     )
105   }
106 
107   /**
108    Function with five arguments.
109    */
110   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
111     _ name: String,
112     _ closure: @escaping (A0, A1, A2, A3, A4) -> R
113   ) -> AnyFunction {
114     return ConcreteFunction(
115       name,
116       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self)],
117       closure
118     )
119   }
120 
121   /**
122    Function with six arguments.
123    */
124   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
125     _ name: String,
126     _ closure: @escaping (A0, A1, A2, A3, A4, A5) -> R
127   ) -> AnyFunction {
128     return ConcreteFunction(
129       name,
130       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self)],
131       closure
132     )
133   }
134 
135   /**
136    Function with seven arguments.
137    */
138   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument>(
139     _ name: String,
140     _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) -> R
141   ) -> AnyFunction {
142     return ConcreteFunction(
143       name,
144       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self), ArgumentType(A6.self)],
145       closure
146     )
147   }
148 
149   /**
150    Function with eight arguments.
151    */
152   public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument, A7: AnyArgument>(
153     _ name: String,
154     _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) -> R
155   ) -> AnyFunction {
156     return ConcreteFunction(
157       name,
158       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self), ArgumentType(A6.self), ArgumentType(A7.self)],
159       closure
160     )
161   }
162 
163   // MARK: - Module's lifecycle
164 
165   /**
166    Creates module's lifecycle listener that is called right after module initialization.
167    */
168   public func onCreate(_ closure: @escaping () -> Void) -> AnyDefinition {
169     return EventListener(.moduleCreate, closure)
170   }
171 
172   /**
173    Creates module's lifecycle listener that is called when the module is about to be deallocated.
174    */
175   public func onDestroy(_ closure: @escaping () -> Void) -> AnyDefinition {
176     return EventListener(.moduleDestroy, closure)
177   }
178 
179   /**
180    Creates module's lifecycle listener that is called when the app context owning the module is about to be deallocated.
181    */
182   public func onAppContextDestroys(_ closure: @escaping () -> Void) -> AnyDefinition {
183     return EventListener(.appContextDestroys, closure)
184   }
185 
186   /**
187    Creates a listener that is called when the app is about to enter the foreground mode.
188    */
189   public func onAppEntersForeground(_ closure: @escaping () -> Void) -> AnyDefinition {
190     return EventListener(.appEntersForeground, closure)
191   }
192 
193   /**
194    Creates a listener that is called when the app becomes active again.
195    */
196   public func onAppBecomesActive(_ closure: @escaping () -> Void) -> AnyDefinition {
197     return EventListener(.appBecomesActive, closure)
198   }
199 
200   /**
201    Creates a listener that is called when the app enters the background mode.
202    */
203   public func onAppEntersBackground(_ closure: @escaping () -> Void) -> AnyDefinition {
204     return EventListener(.appEntersBackground, closure)
205   }
206 
207   // MARK: - View Manager
208 
209   /**
210    Creates the view manager definition that scopes other view-related definitions.
211    */
212   public func viewManager(@ViewManagerDefinitionBuilder _ closure: @escaping () -> ViewManagerDefinition) -> AnyDefinition {
213     return closure()
214   }
215 
216   // MARK: - Events
217 
218   /**
219    Defines event names that this module can send to JavaScript.
220    */
221   public func events(_ names: String...) -> AnyDefinition {
222     return EventsDefinition(names: names)
223   }
224 
225   /**
226    Function that is invoked when the first event listener is added.
227    */
228   public func onStartObserving(_ body: @escaping () -> ()) -> AnyFunction {
229     return ConcreteFunction("startObserving", argTypes: [], body)
230   }
231 
232   /**
233    Function that is invoked when all event listeners are removed.
234    */
235   public func onStopObserving(_ body: @escaping () -> ()) -> AnyFunction {
236     return ConcreteFunction("stopObserving", argTypes: [], body)
237   }
238 }
239 
240 /**
241  Defines the factory creating a native view when the module is used as a view.
242  */
243 public func view(_ closure: @escaping () -> UIView) -> AnyDefinition {
244   return ViewFactory(closure)
245 }
246 
247 /**
248  Creates a view prop that defines its name and setter.
249  */
250 public func prop<ViewType: UIView, PropType: AnyArgument>(
251   _ name: String,
252   _ setter: @escaping (ViewType, PropType) -> Void
253 ) -> AnyDefinition {
254   return ConcreteViewProp(
255     name: name,
256     propType: ArgumentType(PropType.self),
257     setter: setter
258   )
259 }
260 
261 // TODO: - Remove deprecated `method` component once SDK44 is out.
262 public extension AnyModule {
263   /**
264    Function without arguments.
265    */
266   @available(*, deprecated, renamed: "function")
267   func method<R>(
268     _ name: String,
269     _ closure: @escaping () -> R
270   ) -> AnyFunction {
271     return ConcreteFunction(
272       name,
273       argTypes: [],
274       closure
275     )
276   }
277 
278   /**
279    Function with one argument.
280    */
281   @available(*, deprecated, renamed: "function")
282   func method<R, A0: AnyArgument>(
283     _ name: String,
284     _ closure: @escaping (A0) -> R
285   ) -> AnyFunction {
286     return ConcreteFunction(
287       name,
288       argTypes: [ArgumentType(A0.self)],
289       closure
290     )
291   }
292 
293   /**
294    Function with two arguments.
295    */
296   @available(*, deprecated, renamed: "function")
297   func method<R, A0: AnyArgument, A1: AnyArgument>(
298     _ name: String,
299     _ closure: @escaping (A0, A1) -> R
300   ) -> AnyFunction {
301     return ConcreteFunction(
302       name,
303       argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
304       closure
305     )
306   }
307 }
308