core-native
Version:
A lightweight framework based on React Native + Redux + Redux Saga, in strict TypeScript.
94 lines • 4.02 kB
JavaScript
import { __awaiter } from "tslib";
import React from "react";
import { AppRegistry, AppState } from "react-native";
import { Provider } from "react-redux";
import { app } from "../app";
import { call, delay } from "../typed-saga";
import { ErrorBoundary } from "../util/ErrorBoundary";
import { ajax } from "../util/network";
import { APIException } from "../Exception";
import { captureError } from "../util/error-util";
const LOGGER_ACTION = "@@framework/logger";
export function startApp(config) {
setupGlobalErrorHandler(config.errorListener);
runBackgroundLoop(config.loggerConfig);
renderRoot(config.registeredAppName, config.componentType, config.beforeRendering);
}
function setupGlobalErrorHandler(errorListener) {
app.errorHandler = errorListener.onError.bind(errorListener);
ErrorUtils.setGlobalHandler((error, isFatal) => captureError(error, "@@framework/global", isFatal ? { severity: "fatal" } : undefined));
}
function renderRoot(registeredAppName, EntryComponent, beforeRendering) {
class WrappedAppComponent extends React.PureComponent {
constructor(props) {
super(props);
this.onAppStateChange = (nextAppState) => {
const { appState } = this.state;
if (["inactive", "background"].includes(appState) && nextAppState === "active") {
app.logger.info({ action: "@@ACTIVE", info: { prevState: appState } });
}
else if (appState === "active" && ["inactive", "background"].includes(nextAppState)) {
app.logger.info({ action: "@@INACTIVE", info: { nextState: nextAppState } });
sendEventLogs();
}
this.setState({ appState: nextAppState });
};
this.state = { initialized: false, appState: AppState.currentState };
}
componentDidMount() {
return __awaiter(this, void 0, void 0, function* () {
if (beforeRendering) {
yield beforeRendering();
}
this.setState({ initialized: true });
AppState.addEventListener("change", this.onAppStateChange);
});
}
componentWillUnmount() {
AppState.removeEventListener("change", this.onAppStateChange);
}
render() {
return (this.state.initialized && (<Provider store={app.store}>
<ErrorBoundary>
<EntryComponent />
</ErrorBoundary>
</Provider>));
}
}
AppRegistry.registerComponent(registeredAppName, () => WrappedAppComponent);
}
function runBackgroundLoop(loggerConfig) {
app.logger.info({ action: "@@ENTER" });
app.loggerConfig = loggerConfig || null;
app.sagaMiddleware.run(function* () {
while (true) {
// Loop on every 15 second
yield delay(15000);
// Send collected log to event server
yield* call(sendEventLogs);
}
});
}
export function sendEventLogs() {
return __awaiter(this, void 0, void 0, function* () {
if (app.loggerConfig) {
const logs = app.logger.collect(200);
const logLength = logs.length;
if (logLength > 0) {
try {
yield ajax("POST", app.loggerConfig.serverURL, {}, { events: logs }, true);
app.logger.emptyLastCollection();
}
catch (e) {
if (e instanceof APIException) {
// For APIException, retry always leads to same error, so have to give up
// Do not log network exceptions
app.logger.emptyLastCollection();
app.logger.exception(e, { droppedLogs: logLength.toString() }, LOGGER_ACTION);
}
}
}
}
});
}
//# sourceMappingURL=bootstrap.js.map