Skip to content

Commit 43081df

Browse files
refactor(crashlytics): migrate to TypeScript. (#8814)
1 parent a2844d4 commit 43081df

File tree

18 files changed

+490
-655
lines changed

18 files changed

+490
-655
lines changed

packages/analytics/lib/namespaced.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ const ReservedEventNames: readonly string[] = [
116116
'user_engagement',
117117
] as const;
118118

119-
const statics: Statics = {};
119+
const statics: Partial<Statics> = {};
120120

121121
const namespace = 'analytics';
122122

packages/analytics/lib/types/analytics.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,9 @@ export interface EventParams {
713713
// search_term: string;
714714
// }
715715

716-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
717-
export interface Statics {}
716+
export interface Statics {
717+
SDK_VERSION: string;
718+
}
718719

719720
/**
720721
* Analytics instance initialization options. Web only.

packages/analytics/tsconfig.json

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,6 @@
11
{
2+
"extends": "../../tsconfig.packages.base.json",
23
"compilerOptions": {
3-
"allowUnreachableCode": false,
4-
"allowUnusedLabels": false,
5-
"esModuleInterop": true,
6-
"forceConsistentCasingInFileNames": true,
7-
"jsx": "react-jsx",
8-
"lib": ["ESNext"],
9-
"module": "ESNext",
10-
"moduleResolution": "bundler",
11-
"noFallthroughCasesInSwitch": true,
12-
"noImplicitReturns": true,
13-
"noImplicitUseStrict": false,
14-
"noStrictGenericChecks": false,
15-
"noUncheckedIndexedAccess": true,
16-
"noUnusedLocals": true,
17-
"noUnusedParameters": true,
18-
"resolveJsonModule": true,
19-
"skipLibCheck": true,
20-
"strict": true,
21-
"target": "ESNext",
22-
"verbatimModuleSyntax": true,
234
"baseUrl": ".",
245
"rootDir": ".",
256
"paths": {

packages/app/lib/internal/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ export * from './registry/namespace';
2525
export * from './registry/nativeModule';
2626
export { default as SharedEventEmitter } from './SharedEventEmitter';
2727
export { Logger } from './logger';
28+
export type { ModuleConfig } from '../types/internal';

packages/app/tsconfig.json

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,9 @@
11
{
2+
"extends": "../../tsconfig.packages.base.json",
23
"compilerOptions": {
3-
"allowUnreachableCode": false,
4-
"allowUnusedLabels": false,
5-
"esModuleInterop": true,
6-
"forceConsistentCasingInFileNames": true,
7-
"jsx": "react-jsx",
8-
"lib": ["ESNext", "DOM"],
9-
"module": "ESNext",
10-
"moduleResolution": "bundler",
11-
"noFallthroughCasesInSwitch": true,
12-
"noImplicitReturns": true,
13-
"noImplicitUseStrict": false,
14-
"noStrictGenericChecks": false,
15-
"noUncheckedIndexedAccess": true,
16-
"noUnusedLocals": true,
17-
"noUnusedParameters": true,
18-
"resolveJsonModule": true,
19-
"skipLibCheck": true,
20-
"strict": true,
21-
"target": "ESNext",
22-
"verbatimModuleSyntax": true,
234
"baseUrl": ".",
24-
"rootDir": "."
5+
"rootDir": ".",
6+
"lib": ["ESNext", "DOM"]
257
},
268
"include": ["lib/**/*"],
279
"exclude": ["node_modules", "dist", "__tests__", "**/*.test.ts"]
Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,48 @@
1515
*
1616
*/
1717

18-
import { firebase } from '@react-native-firebase/app';
18+
import { firebase } from '.';
1919
import { isError, once } from '@react-native-firebase/app/lib/common';
20+
// @ts-ignore - No declaration file for promise/setimmediate/rejection-tracking
2021
import tracking from 'promise/setimmediate/rejection-tracking';
2122
import StackTrace from 'stacktrace-js';
22-
2323
export const FATAL_FLAG = 'com.firebase.crashlytics.reactnative.fatal';
2424

25-
export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, jsErrorName) {
26-
const nativeObj = {};
25+
interface NativeErrorFrame {
26+
src: string;
27+
line: number;
28+
col: number;
29+
fn: string;
30+
file: string;
31+
}
32+
33+
interface NativeErrorObj {
34+
message: string;
35+
isUnhandledRejection: boolean;
36+
frames: NativeErrorFrame[];
37+
}
2738

28-
nativeObj.message = `${error.message}`;
29-
nativeObj.isUnhandledRejection = isUnhandledRejection;
39+
interface NativeModule {
40+
isCrashlyticsCollectionEnabled: boolean;
41+
isErrorGenerationOnJSCrashEnabled: boolean;
42+
isCrashlyticsJavascriptExceptionHandlerChainingEnabled: boolean;
43+
logPromise(message: string): Promise<void>;
44+
setAttribute(name: string, value: string): Promise<void>;
45+
recordErrorPromise(errorObj: NativeErrorObj): Promise<void>;
46+
crashWithStackPromise(errorObj: NativeErrorObj): Promise<void>;
47+
}
3048

31-
nativeObj.frames = [];
49+
export function createNativeErrorObj(
50+
error: Error,
51+
stackFrames: StackTrace.StackFrame[],
52+
isUnhandledRejection: boolean,
53+
jsErrorName?: string,
54+
): NativeErrorObj {
55+
const nativeObj: NativeErrorObj = {
56+
message: `${error.message}`,
57+
isUnhandledRejection,
58+
frames: [],
59+
};
3260

3361
if (jsErrorName) {
3462
// Option to fix crashlytics display and alerting. You can add an error name to the recordError function
@@ -42,7 +70,10 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
4270
}
4371

4472
for (let i = 0; i < stackFrames.length; i++) {
45-
const { columnNumber, lineNumber, fileName, functionName, source } = stackFrames[i];
73+
const frame = stackFrames[i];
74+
if (!frame) continue;
75+
76+
const { columnNumber, lineNumber, fileName, functionName, source } = frame;
4677
let fileNameParsed = '<unknown>';
4778
if (fileName) {
4879
const subStrLen = fileName.indexOf('?');
@@ -54,7 +85,7 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
5485
}
5586

5687
nativeObj.frames.push({
57-
src: source,
88+
src: source || '<unknown>',
5889
line: lineNumber || 0,
5990
col: columnNumber || 0,
6091
fn: functionName || '<unknown>',
@@ -65,10 +96,10 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
6596
return nativeObj;
6697
}
6798

68-
export const setGlobalErrorHandler = once(nativeModule => {
99+
export const setGlobalErrorHandler = once((nativeModule: NativeModule) => {
69100
const originalHandler = ErrorUtils.getGlobalHandler();
70101

71-
async function handler(error, fatal) {
102+
async function handler(error: unknown, fatal?: boolean) {
72103
// If collection is disabled, just forward to the original handler
73104
if (!nativeModule.isCrashlyticsCollectionEnabled) {
74105
return originalHandler(error, fatal);
@@ -89,7 +120,7 @@ export const setGlobalErrorHandler = once(nativeModule => {
89120
// For that reason we always round up (`.ceil`) and add a second in case of latency
90121
//
91122
// Time is specified as seconds since start of Unix epoch as a baseline, as a string
92-
const fatalTime = Math.ceil(new Date() / 1000) + 1 + '';
123+
const fatalTime = Math.ceil(new Date().getTime() / 1000) + 1 + '';
93124

94125
// Flag the Crashlytics backend that we have a fatal error, they will transform it
95126
await nativeModule.setAttribute(FATAL_FLAG, fatalTime);
@@ -107,6 +138,7 @@ export const setGlobalErrorHandler = once(nativeModule => {
107138
// Did not matter if I did named imports above or dynamic require here.
108139
// So temporarily reverting and silencing warnings instead
109140
globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true;
141+
// @ts-ignore - analytics types not available in crashlytics
110142
await firebase.app().analytics().logEvent(
111143
'app_exception', // 'app_exception' is reserved but we make an exception for JS->fatal transforms
112144
{
@@ -143,8 +175,8 @@ export const setGlobalErrorHandler = once(nativeModule => {
143175
return handler;
144176
});
145177

146-
export const setOnUnhandledPromiseRejectionHandler = once(nativeModule => {
147-
async function onUnhandled(_id, error) {
178+
export const setOnUnhandledPromiseRejectionHandler = once((nativeModule: NativeModule) => {
179+
async function onUnhandled(_id: number, error: Error) {
148180
if (!__DEV__) {
149181
// TODO(salakar): Option to disable
150182
try {

0 commit comments

Comments
 (0)