@kirz/react-native-toolkit
Version:
Toolkit to speed up React Native development
213 lines (211 loc) • 11.1 kB
JavaScript
;
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