UNPKG

brick-module

Version:

Better React Native native module development

106 lines (104 loc) 3.72 kB
import { BrickError } from "./BrickError.js"; import { TurboModuleRegistry } from "react-native"; //#region src/BrickModule.ts const moduleCache = /* @__PURE__ */ new Map(); let nativeModule = null; /** * Gets the native TurboModule instance * @private */ function getNativeModule() { if (!nativeModule) nativeModule = TurboModuleRegistry.getEnforcing("BrickModule"); return nativeModule; } /** * Gets a typed module instance by name with explicit type parameter * @param moduleName - The exact name of the module as defined in its spec * @returns Typed module interface with all methods, constants, and event listeners */ function get(moduleName) { const cacheKey = moduleName; if (moduleCache.has(cacheKey)) return moduleCache.get(cacheKey); const nativeModuleInstance = getNativeModule(); let constantsCache = null; const moduleProxy = new Proxy({}, { get: (_target, property) => { if (typeof property !== "string") return; if (property.startsWith("on") && property.length > 2 && property[2] === property[2].toUpperCase()) return (listener) => { const nativeEventMethod = `${moduleName}_${property}`; const nativeFn = nativeModuleInstance[nativeEventMethod]; if (typeof nativeFn === "function") return nativeFn(listener); throw new Error(`${nativeEventMethod} is not available. Did you run RN codegen?`); }; if (property === "getConstants") return () => { if (constantsCache !== null) return constantsCache; const allConstants = nativeModuleInstance?.getConstants?.() ?? {}; const moduleConstants = {}; const constantPrefix = `${moduleName}_`; for (const key in allConstants) if (key.startsWith(constantPrefix)) { const propName = key.substring(constantPrefix.length); moduleConstants[propName] = allConstants[key]; } constantsCache = moduleConstants; return moduleConstants; }; return (...args) => { const methodKey = `${moduleName}_${property}`; if (typeof nativeModuleInstance[methodKey] === "function") { const result = nativeModuleInstance[methodKey](...args); if (result && typeof result === "object" && result["~sync"] === true) if (result.success === true) return result.value; else { const errorInfo = result.error || {}; const message = errorInfo.message || errorInfo.errorMessage || "Unknown error"; const code = errorInfo.code || errorInfo.errorCode || "BRICK_ERROR"; const userInfo = { code }; for (const key of Object.keys(errorInfo)) if (key !== "code" && key !== "message" && key !== "errorCode" && key !== "errorMessage") userInfo[key] = errorInfo[key]; throw new BrickError(message, code, userInfo, moduleName); } if (result && typeof result.then === "function") return result.catch((error) => { throw BrickError.from(error, moduleName); }); return result; } throw new Error(`Method ${methodKey} not found`); }; }, has: (_target, property) => { return typeof property === "string"; }, ownKeys: (_target) => { return []; } }); moduleCache.set(cacheKey, moduleProxy); return moduleProxy; } /** * Gets list of all registered modules * @returns Promise resolving to array of module names */ function getRegisteredModules() { return getNativeModule()?.getRegisteredModules() ?? []; } /** * Clears the module cache (useful for testing or hot reloading) * @internal */ function clearCache() { moduleCache.clear(); } /** * Main Brick Module API object * Provides type-safe access to native modules */ const BrickModule = { get, getRegisteredModules, clearCache }; /** * Default export for convenience */ var BrickModule_default = BrickModule; //#endregion export { BrickModule_default as default };