137917d47SŁukasz Kosmatyimport { NativeModules } from 'react-native';
237917d47SŁukasz Kosmaty
3*bd0cffe7STomasz Sapetaimport { ProxyNativeModule } from './NativeModulesProxy.types';
437917d47SŁukasz Kosmaty
537917d47SŁukasz Kosmatyconst NativeProxy = NativeModules.NativeUnimoduleProxy;
637917d47SŁukasz Kosmatyconst modulesConstantsKey = 'modulesConstants';
737917d47SŁukasz Kosmatyconst exportedMethodsKey = 'exportedMethods';
837917d47SŁukasz Kosmaty
937917d47SŁukasz Kosmatyconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};
1037917d47SŁukasz Kosmaty
1137917d47SŁukasz Kosmatyif (NativeProxy) {
1235f78160SBartosz Kaszubowski  Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
1337917d47SŁukasz Kosmaty    NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
1435f78160SBartosz Kaszubowski    NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {
1537917d47SŁukasz Kosmaty      NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {
1637917d47SŁukasz Kosmaty        const { key, argumentsCount } = methodInfo;
1737917d47SŁukasz Kosmaty        if (argumentsCount !== args.length) {
1837917d47SŁukasz Kosmaty          return Promise.reject(
1937917d47SŁukasz Kosmaty            new Error(
2037917d47SŁukasz Kosmaty              `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${
2137917d47SŁukasz Kosmaty                argumentsCount === 1 ? 'argument' : 'arguments'
2237917d47SŁukasz Kosmaty              } but received ${args.length}`
2337917d47SŁukasz Kosmaty            )
2437917d47SŁukasz Kosmaty          );
2537917d47SŁukasz Kosmaty        }
2637917d47SŁukasz Kosmaty        return NativeProxy.callMethod(moduleName, key, args);
2737917d47SŁukasz Kosmaty      };
2837917d47SŁukasz Kosmaty    });
2937917d47SŁukasz Kosmaty
3037917d47SŁukasz Kosmaty    // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)
3137917d47SŁukasz Kosmaty    // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.
3237917d47SŁukasz Kosmaty    //
3337917d47SŁukasz Kosmaty    // On Android only {start,stop}Observing are called on the native module
3437917d47SŁukasz Kosmaty    // and these should be exported as Expo methods.
351036dd0aSŁukasz Kosmaty    //
361036dd0aSŁukasz Kosmaty    // Before the RN 65, addListener/removeListeners weren't called on Android. However, it no longer stays true.
371036dd0aSŁukasz Kosmaty    // See https://github.com/facebook/react-native/commit/f5502fbda9fe271ff6e1d0da773a3a8ee206a453.
381036dd0aSŁukasz Kosmaty    // That's why, we check if the `EXReactNativeEventEmitter` exists and only if yes, we use it in the listener implementation.
391036dd0aSŁukasz Kosmaty    // Otherwise, those methods are NOOP.
401036dd0aSŁukasz Kosmaty    if (NativeModules.EXReactNativeEventEmitter) {
4137917d47SŁukasz Kosmaty      NativeModulesProxy[moduleName].addListener = (...args) =>
4270c51132SKudo Chien        NativeModules.EXReactNativeEventEmitter.addProxiedListener(moduleName, ...args);
4337917d47SŁukasz Kosmaty      NativeModulesProxy[moduleName].removeListeners = (...args) =>
4470c51132SKudo Chien        NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);
451036dd0aSŁukasz Kosmaty    } else {
461036dd0aSŁukasz Kosmaty      // Fixes on Android:
471036dd0aSŁukasz Kosmaty      // WARN  `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.
481036dd0aSŁukasz Kosmaty      // WARN  `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.
491036dd0aSŁukasz Kosmaty      NativeModulesProxy[moduleName].addListener = () => {};
501036dd0aSŁukasz Kosmaty      NativeModulesProxy[moduleName].removeListeners = () => {};
511036dd0aSŁukasz Kosmaty    }
5237917d47SŁukasz Kosmaty  });
5337917d47SŁukasz Kosmaty} else {
5437917d47SŁukasz Kosmaty  console.warn(
55e7f22797STomasz Sapeta    `The "EXNativeModulesProxy" native module is not exported through NativeModules; verify that expo-modules-core's native code is linked properly`
5637917d47SŁukasz Kosmaty  );
5737917d47SŁukasz Kosmaty}
5837917d47SŁukasz Kosmaty
5937917d47SŁukasz Kosmatyexport default NativeModulesProxy;
60