UNPKG

@kirz/react-native-toolkit

Version:

Toolkit to speed up React Native development

213 lines (211 loc) 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppBootstrapper = AppBootstrapper; var _portal = require("@gorhom/portal"); var _chalk = _interopRequireDefault(require("chalk")); var _pQueue = _interopRequireDefault(require("p-queue")); var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _useAsyncEffect = require("use-async-effect"); var _AppSplashScreen = require("../components/AppSplashScreen"); var _DropDownContext = require("../contexts/DropDownContext"); var _InAppPurchaseContext = require("../contexts/InAppPurchaseContext"); var _PluginsBundleContext = require("../contexts/PluginsBundleContext"); var _index = require("../index"); var _Plugin = require("../plugins/Plugin"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const chalkCtx = new _chalk.default.Instance({ level: 3 }); function AppBootstrapper(_ref) { let { children, plugins, splashScreenProps } = _ref; const [isInitialized, setIsInitialized] = (0, _react.useState)(false); const [isRetrying, setIsRetrying] = (0, _react.useState)(false); const [initializationError, setInitializationError] = (0, _react.useState)(null); const [pluginsBundle, setPluginsBundle] = (0, _react.useState)(new _Plugin.PluginsBundle([])); const initializedPlugins = (0, _react.useRef)([]); const ErrorFallbackScreen = (0, _react.useRef)(null); const isInitializedRef = (0, _react.useRef)(false); const initialize = (0, _react.useCallback)(async function () { let async = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (!plugins) { return; } const initializePlugin = async (plugin, getBundle, group, id) => { const initializationStartTime = new Date().valueOf(); if ('dependsOn' in plugin && plugin.dependsOn && plugin.dependsOn.length) { await _index.PromiseUtils.waitUntil(() => !plugin.dependsOn.find(x => !initializedPlugins.current.find(y => y.plugin.name === x))); } try { if ('useValue' in plugin) { await (0, _index.timeout)(plugin.useValue.initialize(getBundle()), plugin.timeout === null ? null : plugin.timeout ?? plugin.useValue.initializationTimeout, `${plugin.useValue.name} timeout error`); initializedPlugins.current.push({ plugin: plugin.useValue, id }); } else if ('useFactory' in plugin) { const initializedPlugin = await (0, _index.timeout)(plugin.useFactory(getBundle()), plugin.timeout === null ? null : plugin.timeout, `${plugin.name} timeout error`); if (initializedPlugin) { await (0, _index.timeout)(initializedPlugin.initialize(getBundle()), plugin.timeout === null ? null : plugin.timeout ?? initializedPlugin.initializationTimeout, `${initializedPlugin.name} timeout error`); initializedPlugins.current.push({ plugin: initializedPlugin, id }); } } else if ('useDeferredFactory' in plugin) { const promise = new _index.ControlledPromise(); const pluginName = plugin.name ?? 'DeferredPlugin'; const initializedPlugin = await (0, _index.timeout)(plugin.useDeferredFactory(getBundle(), promise.resolve, promise.reject), plugin.timeout, `${pluginName} timeout error`); const [, additionalData] = await (0, _index.timeout)(Promise.all([initializedPlugin === null || initializedPlugin === void 0 ? void 0 : initializedPlugin.initialize(getBundle()), promise.wait()]), plugin.timeout === null ? null : plugin.timeout ?? (initializedPlugin === null || initializedPlugin === void 0 ? void 0 : initializedPlugin.initializationTimeout), `${pluginName} timeout error`); if (initializedPlugin) { initializedPlugin.payload = additionalData; initializedPlugins.current.push({ plugin: initializedPlugin, id }); } } else { initializedPlugins.current.push({ plugin, id }); } const lastPlugin = initializedPlugins.current[initializedPlugins.current.length - 1].plugin; console.info([chalkCtx[group ? 'blue' : 'yellow'](`[${lastPlugin.name}]`), chalkCtx.green(`Plugin${group ? ` {group: ${group}} ` : ' '}initialized`), chalkCtx[group ? 'blue' : 'yellow'](`+${(new Date().valueOf() - initializationStartTime).toFixed(0)}ms`)].join(' ')); } catch (err) { if (err) { const errorMessage = err instanceof Error ? err.message : err.toString(); if (errorMessage.includes('timeout error')) { const pluginName = errorMessage.replace(' timeout error', ''); console.error([chalkCtx[group ? 'blue' : 'yellow'](`[${pluginName}]`), chalkCtx.red(`Plugin${group ? ` {group: ${group}} ` : ' '}initialization timeout`), chalkCtx[group ? 'blue' : 'yellow'](`+${(new Date().valueOf() - initializationStartTime).toFixed(0)}ms`)].join(' ')); } // eslint-disable-next-line @typescript-eslint/no-throw-literal throw err; } throw err; } }; const asyncQueue = {}; for (let i = 0; i < plugins.length; i += 1) { const plugin = plugins[i]; const id = i; if (initializedPlugins.current.find(y => y.id === id)) { continue; } try { if ('group' in plugin && plugin.group && async) { if (!asyncQueue[plugin.group]) { asyncQueue[plugin.group] = new _pQueue.default({ concurrency: 1 }); } const queue = asyncQueue[plugin.group]; queue.add(async () => { try { await initializePlugin(plugin, () => new _Plugin.PluginsBundle(initializedPlugins.current.map(x => x.plugin)), plugin.group, id); } catch { // no-op } if (isInitializedRef.current && !queue.size) { setPluginsBundle(new _Plugin.PluginsBundle(initializedPlugins.current.map(x => x.plugin))); } }); continue; } await initializePlugin(plugin, () => new _Plugin.PluginsBundle(initializedPlugins.current.map(x => x.plugin)), null, id); } catch (err) { if ('optional' in plugin && plugin.optional) { continue; } const errorMessage = err instanceof Error ? err.message : err.toString(); if (errorMessage.includes('timeout error')) { // no-op } else { console.error(errorMessage); } ErrorFallbackScreen.current = 'fallbackScreen' in plugin ? plugin.fallbackScreen : null; setInitializationError(errorMessage); throw new Error(errorMessage); } } setPluginsBundle(new _Plugin.PluginsBundle(initializedPlugins.current.map(x => x.plugin))); isInitializedRef.current = true; }, [plugins]); const retryInitialization = (0, _react.useCallback)(async () => { try { setIsRetrying(true); await initialize(false); setInitializationError(null); } catch (err) { _reactNative.Alert.alert('Error', err.message); } finally { setIsRetrying(false); } }, [initialize]); (0, _useAsyncEffect.useAsyncEffect)(async () => { try { await initialize(true); } catch { // no-op } finally { setIsInitialized(true); } }, []); const renderError = (0, _react.useCallback)(() => { if (!initializationError) { return null; } if (ErrorFallbackScreen.current) { return /*#__PURE__*/_react.default.createElement(ErrorFallbackScreen.current, { error: initializationError, isRetrying: isRetrying, retry: retryInitialization }); } return /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { flex: 1, alignItems: 'center', justifyContent: 'center' } }, /*#__PURE__*/_react.default.createElement(_reactNative.StatusBar, { barStyle: "dark-content" }), /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: { fontSize: (0, _index.scaleX)(20), marginBottom: (0, _index.scaleY)(5) } }, initializationError), /*#__PURE__*/_react.default.createElement(_reactNative.Button, { disabled: isRetrying, onPress: retryInitialization, title: "Retry" })); }, [initializationError, ErrorFallbackScreen, isRetrying, retryInitialization]); return /*#__PURE__*/_react.default.createElement(_AppSplashScreen.AppSplashScreen, _extends({ visible: !isInitialized }, splashScreenProps), !initializationError ? /*#__PURE__*/_react.default.createElement(_portal.PortalProvider, null, /*#__PURE__*/_react.default.createElement(_PluginsBundleContext.PluginsBundleProvider, { bundle: pluginsBundle, retryInitialization: retryInitialization }, /*#__PURE__*/_react.default.createElement(_index.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_DropDownContext.DropDownProvider, null, /*#__PURE__*/_react.default.createElement(_InAppPurchaseContext.InAppPurchaseProvider, null, children, /*#__PURE__*/_react.default.createElement(_reactNative.View, { pointerEvents: "box-none", style: { position: 'absolute', left: 0, top: 0, bottom: 0, right: 0 } }, /*#__PURE__*/_react.default.createElement(_portal.PortalHost, { name: "ModalHost" }))))))) : renderError()); } //# sourceMappingURL=AppBootstrapper.js.map