@logbrew/react-native 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LogBrewReactNative.podspec +22 -0
- package/README.md +3 -3
- package/android/build.gradle +42 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/co/logbrew/reactnative/FatalRecordStore.java +636 -0
- package/android/src/main/java/co/logbrew/reactnative/FatalStoreModuleImpl.java +225 -0
- package/android/src/main/java/co/logbrew/reactnative/LogBrewReactNativePackage.java +20 -0
- package/android/src/newarch/java/co/logbrew/reactnative/FatalStoreModule.java +39 -0
- package/android/src/oldarch/java/co/logbrew/reactnative/FatalStoreModule.java +41 -0
- package/fatal-replay.cjs +531 -0
- package/global-errors.cjs +51 -3
- package/global-errors.d.cts +72 -4
- package/global-errors.d.ts +72 -4
- package/global-errors.native.js +39 -0
- package/index.native.d.ts +2 -0
- package/index.native.js +3 -0
- package/ios/LBRNFatalRecordStore.h +25 -0
- package/ios/LBRNFatalRecordStore.m +542 -0
- package/ios/LBRNFatalStoreModule.h +4 -0
- package/ios/LBRNFatalStoreModule.mm +147 -0
- package/package.json +33 -4
- package/react-native.config.js +11 -0
- package/src/NativeLogBrewFatalStore.ts +11 -0
package/global-errors.d.cts
CHANGED
|
@@ -10,7 +10,14 @@ export type ReactNativeErrorUtilsLike = {
|
|
|
10
10
|
export type ReactNativeGlobalErrorDiagnosticCode =
|
|
11
11
|
| "capture_failed"
|
|
12
12
|
| "duplicate_capture_suppressed"
|
|
13
|
+
| "fatal_acknowledge_failed"
|
|
13
14
|
| "fatal_capture_requires_sync_store"
|
|
15
|
+
| "fatal_corrupt_record_discarded"
|
|
16
|
+
| "fatal_discard_failed"
|
|
17
|
+
| "fatal_record_dropped"
|
|
18
|
+
| "fatal_replay_failed"
|
|
19
|
+
| "fatal_replay_not_admitted"
|
|
20
|
+
| "fatal_store_failed"
|
|
14
21
|
| "handler_unavailable"
|
|
15
22
|
| "recursive_capture_suppressed";
|
|
16
23
|
|
|
@@ -25,6 +32,8 @@ export type ReactNativeGlobalErrorHealth = Readonly<{
|
|
|
25
32
|
| "capture_failed"
|
|
26
33
|
| "captured"
|
|
27
34
|
| "duplicate_suppressed"
|
|
35
|
+
| "fatal_stored"
|
|
36
|
+
| "fatal_store_failed"
|
|
28
37
|
| "fatal_unsupported"
|
|
29
38
|
| "handler_replaced"
|
|
30
39
|
| "idle"
|
|
@@ -35,22 +44,81 @@ export type ReactNativeGlobalErrorHealth = Readonly<{
|
|
|
35
44
|
suppressedEvents: number;
|
|
36
45
|
}>;
|
|
37
46
|
|
|
47
|
+
export type ReactNativeFatalRecord = Readonly<{
|
|
48
|
+
corruptRecords: number;
|
|
49
|
+
droppedRecords: number;
|
|
50
|
+
errorName: string;
|
|
51
|
+
id: string;
|
|
52
|
+
schemaVersion: 1;
|
|
53
|
+
stackFrames: ReadonlyArray<Readonly<{
|
|
54
|
+
column: number;
|
|
55
|
+
filename: string;
|
|
56
|
+
line: number;
|
|
57
|
+
}>>;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
}>;
|
|
60
|
+
|
|
61
|
+
export type ReactNativeFatalStoreResult = Readonly<{
|
|
62
|
+
corruptRecords?: number;
|
|
63
|
+
droppedRecords?: number;
|
|
64
|
+
record?: ReactNativeFatalRecord;
|
|
65
|
+
recordId?: string;
|
|
66
|
+
status: string;
|
|
67
|
+
}>;
|
|
68
|
+
|
|
69
|
+
export type ReactNativeFatalStoreLike = {
|
|
70
|
+
writeFatalRecord(record: ReactNativeFatalRecord): ReactNativeFatalStoreResult;
|
|
71
|
+
readFatalRecord(): ReactNativeFatalStoreResult;
|
|
72
|
+
acknowledgeFatalRecord(recordId: string): ReactNativeFatalStoreResult;
|
|
73
|
+
discardFatalRecord(): ReactNativeFatalStoreResult;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type ReactNativeFatalReplayHealth = Readonly<{
|
|
77
|
+
acknowledgedRecords: number;
|
|
78
|
+
available: boolean;
|
|
79
|
+
corruptRecords: number;
|
|
80
|
+
droppedRecords: number;
|
|
81
|
+
lastOutcome:
|
|
82
|
+
| "acknowledge_failed"
|
|
83
|
+
| "acknowledged"
|
|
84
|
+
| "corrupt_discarded"
|
|
85
|
+
| "discard_failed"
|
|
86
|
+
| "discarded"
|
|
87
|
+
| "dropped_pending"
|
|
88
|
+
| "empty"
|
|
89
|
+
| "idle"
|
|
90
|
+
| "replay_failed"
|
|
91
|
+
| "replay_not_admitted"
|
|
92
|
+
| "storage_error"
|
|
93
|
+
| "stored"
|
|
94
|
+
| "stored_after_corruption"
|
|
95
|
+
| "unavailable";
|
|
96
|
+
replayedRecords: number;
|
|
97
|
+
storedRecords: number;
|
|
98
|
+
}>;
|
|
99
|
+
|
|
38
100
|
export type InstallLogBrewReactNativeGlobalErrorHandlerOptions = {
|
|
39
|
-
client: Pick<LogBrewClient, "issue"
|
|
101
|
+
client: Pick<LogBrewClient, "issue">
|
|
102
|
+
& Partial<Pick<LogBrewClient, "droppedEvents" | "pendingEvents">>;
|
|
40
103
|
errorUtils?: ReactNativeErrorUtilsLike;
|
|
104
|
+
fatalStore?: ReactNativeFatalStoreLike;
|
|
41
105
|
onDiagnostic?: (diagnostic: ReactNativeGlobalErrorDiagnostic) => void;
|
|
42
106
|
};
|
|
43
107
|
|
|
44
108
|
export type LogBrewReactNativeGlobalErrorHandlerInstallation = Readonly<{
|
|
109
|
+
discardPendingFatalRecord(): boolean;
|
|
110
|
+
fatalHealth(): ReactNativeFatalReplayHealth;
|
|
45
111
|
health(): ReactNativeGlobalErrorHealth;
|
|
46
112
|
remove(): boolean;
|
|
47
113
|
}>;
|
|
48
114
|
|
|
49
115
|
/**
|
|
50
|
-
* Install reversible automatic capture for
|
|
116
|
+
* Install reversible automatic capture for React Native global JavaScript errors.
|
|
51
117
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
118
|
+
* The React Native conditional export injects its synchronous native fatal store by default.
|
|
119
|
+
* Direct Node ESM/CJS callers can inject a compatible store explicitly. Fatal replay is
|
|
120
|
+
* stable-ID at-least-once and acknowledges only after observable local queue admission.
|
|
121
|
+
* This helper does not claim local exactly-once delivery or install Promise rejection handling.
|
|
54
122
|
*/
|
|
55
123
|
export declare function installLogBrewReactNativeGlobalErrorHandler(
|
|
56
124
|
options: InstallLogBrewReactNativeGlobalErrorHandlerOptions
|
package/global-errors.d.ts
CHANGED
|
@@ -10,7 +10,14 @@ export type ReactNativeErrorUtilsLike = {
|
|
|
10
10
|
export type ReactNativeGlobalErrorDiagnosticCode =
|
|
11
11
|
| "capture_failed"
|
|
12
12
|
| "duplicate_capture_suppressed"
|
|
13
|
+
| "fatal_acknowledge_failed"
|
|
13
14
|
| "fatal_capture_requires_sync_store"
|
|
15
|
+
| "fatal_corrupt_record_discarded"
|
|
16
|
+
| "fatal_discard_failed"
|
|
17
|
+
| "fatal_record_dropped"
|
|
18
|
+
| "fatal_replay_failed"
|
|
19
|
+
| "fatal_replay_not_admitted"
|
|
20
|
+
| "fatal_store_failed"
|
|
14
21
|
| "handler_unavailable"
|
|
15
22
|
| "recursive_capture_suppressed";
|
|
16
23
|
|
|
@@ -25,6 +32,8 @@ export type ReactNativeGlobalErrorHealth = Readonly<{
|
|
|
25
32
|
| "capture_failed"
|
|
26
33
|
| "captured"
|
|
27
34
|
| "duplicate_suppressed"
|
|
35
|
+
| "fatal_stored"
|
|
36
|
+
| "fatal_store_failed"
|
|
28
37
|
| "fatal_unsupported"
|
|
29
38
|
| "handler_replaced"
|
|
30
39
|
| "idle"
|
|
@@ -35,22 +44,81 @@ export type ReactNativeGlobalErrorHealth = Readonly<{
|
|
|
35
44
|
suppressedEvents: number;
|
|
36
45
|
}>;
|
|
37
46
|
|
|
47
|
+
export type ReactNativeFatalRecord = Readonly<{
|
|
48
|
+
corruptRecords: number;
|
|
49
|
+
droppedRecords: number;
|
|
50
|
+
errorName: string;
|
|
51
|
+
id: string;
|
|
52
|
+
schemaVersion: 1;
|
|
53
|
+
stackFrames: ReadonlyArray<Readonly<{
|
|
54
|
+
column: number;
|
|
55
|
+
filename: string;
|
|
56
|
+
line: number;
|
|
57
|
+
}>>;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
}>;
|
|
60
|
+
|
|
61
|
+
export type ReactNativeFatalStoreResult = Readonly<{
|
|
62
|
+
corruptRecords?: number;
|
|
63
|
+
droppedRecords?: number;
|
|
64
|
+
record?: ReactNativeFatalRecord;
|
|
65
|
+
recordId?: string;
|
|
66
|
+
status: string;
|
|
67
|
+
}>;
|
|
68
|
+
|
|
69
|
+
export type ReactNativeFatalStoreLike = {
|
|
70
|
+
writeFatalRecord(record: ReactNativeFatalRecord): ReactNativeFatalStoreResult;
|
|
71
|
+
readFatalRecord(): ReactNativeFatalStoreResult;
|
|
72
|
+
acknowledgeFatalRecord(recordId: string): ReactNativeFatalStoreResult;
|
|
73
|
+
discardFatalRecord(): ReactNativeFatalStoreResult;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type ReactNativeFatalReplayHealth = Readonly<{
|
|
77
|
+
acknowledgedRecords: number;
|
|
78
|
+
available: boolean;
|
|
79
|
+
corruptRecords: number;
|
|
80
|
+
droppedRecords: number;
|
|
81
|
+
lastOutcome:
|
|
82
|
+
| "acknowledge_failed"
|
|
83
|
+
| "acknowledged"
|
|
84
|
+
| "corrupt_discarded"
|
|
85
|
+
| "discard_failed"
|
|
86
|
+
| "discarded"
|
|
87
|
+
| "dropped_pending"
|
|
88
|
+
| "empty"
|
|
89
|
+
| "idle"
|
|
90
|
+
| "replay_failed"
|
|
91
|
+
| "replay_not_admitted"
|
|
92
|
+
| "storage_error"
|
|
93
|
+
| "stored"
|
|
94
|
+
| "stored_after_corruption"
|
|
95
|
+
| "unavailable";
|
|
96
|
+
replayedRecords: number;
|
|
97
|
+
storedRecords: number;
|
|
98
|
+
}>;
|
|
99
|
+
|
|
38
100
|
export type InstallLogBrewReactNativeGlobalErrorHandlerOptions = {
|
|
39
|
-
client: Pick<LogBrewClient, "issue"
|
|
101
|
+
client: Pick<LogBrewClient, "issue">
|
|
102
|
+
& Partial<Pick<LogBrewClient, "droppedEvents" | "pendingEvents">>;
|
|
40
103
|
errorUtils?: ReactNativeErrorUtilsLike;
|
|
104
|
+
fatalStore?: ReactNativeFatalStoreLike;
|
|
41
105
|
onDiagnostic?: (diagnostic: ReactNativeGlobalErrorDiagnostic) => void;
|
|
42
106
|
};
|
|
43
107
|
|
|
44
108
|
export type LogBrewReactNativeGlobalErrorHandlerInstallation = Readonly<{
|
|
109
|
+
discardPendingFatalRecord(): boolean;
|
|
110
|
+
fatalHealth(): ReactNativeFatalReplayHealth;
|
|
45
111
|
health(): ReactNativeGlobalErrorHealth;
|
|
46
112
|
remove(): boolean;
|
|
47
113
|
}>;
|
|
48
114
|
|
|
49
115
|
/**
|
|
50
|
-
* Install reversible automatic capture for
|
|
116
|
+
* Install reversible automatic capture for React Native global JavaScript errors.
|
|
51
117
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
118
|
+
* The React Native conditional export injects its synchronous native fatal store by default.
|
|
119
|
+
* Direct Node ESM/CJS callers can inject a compatible store explicitly. Fatal replay is
|
|
120
|
+
* stable-ID at-least-once and acknowledges only after observable local queue admission.
|
|
121
|
+
* This helper does not claim local exactly-once delivery or install Promise rejection handling.
|
|
54
122
|
*/
|
|
55
123
|
export declare function installLogBrewReactNativeGlobalErrorHandler(
|
|
56
124
|
options: InstallLogBrewReactNativeGlobalErrorHandlerOptions
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NativeModules, TurboModuleRegistry } from "react-native";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
installLogBrewReactNativeGlobalErrorHandler as installPlatformNeutralHandler
|
|
5
|
+
} from "./global-errors.js";
|
|
6
|
+
|
|
7
|
+
function defaultFatalStore() {
|
|
8
|
+
try {
|
|
9
|
+
return TurboModuleRegistry?.get?.("LogBrewFatalStore")
|
|
10
|
+
?? NativeModules?.LogBrewFatalStore;
|
|
11
|
+
} catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function installLogBrewReactNativeGlobalErrorHandler(options = {}) {
|
|
17
|
+
let forwarded;
|
|
18
|
+
let hasInjectedStore = false;
|
|
19
|
+
try {
|
|
20
|
+
const input = options !== null
|
|
21
|
+
&& (typeof options === "object" || typeof options === "function")
|
|
22
|
+
? options
|
|
23
|
+
: {};
|
|
24
|
+
hasInjectedStore = Object.prototype.hasOwnProperty.call(input, "fatalStore");
|
|
25
|
+
forwarded = { ...input };
|
|
26
|
+
} catch {
|
|
27
|
+
forwarded = {};
|
|
28
|
+
}
|
|
29
|
+
return installPlatformNeutralHandler({
|
|
30
|
+
...forwarded,
|
|
31
|
+
fatalStore: hasInjectedStore ? forwarded.fatalStore : defaultFatalStore()
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const logBrewReactNativeGlobalErrors = {
|
|
36
|
+
installLogBrewReactNativeGlobalErrorHandler
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default logBrewReactNativeGlobalErrors;
|
package/index.native.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
FOUNDATION_EXPORT NSString *const LBRNFatalRecordFileName;
|
|
6
|
+
FOUNDATION_EXPORT NSString *const LBRNFatalRecordTemporaryFileName;
|
|
7
|
+
|
|
8
|
+
typedef BOOL (^LBRNFatalDirectoryPreparation)(NSURL *directoryURL);
|
|
9
|
+
|
|
10
|
+
@interface LBRNFatalRecordStore : NSObject
|
|
11
|
+
|
|
12
|
+
- (instancetype)initWithDirectoryURL:(NSURL *)directoryURL;
|
|
13
|
+
- (instancetype)initWithDirectoryURL:(NSURL *)directoryURL
|
|
14
|
+
directoryPreparation:(LBRNFatalDirectoryPreparation)directoryPreparation
|
|
15
|
+
NS_DESIGNATED_INITIALIZER;
|
|
16
|
+
- (instancetype)init NS_UNAVAILABLE;
|
|
17
|
+
|
|
18
|
+
- (NSDictionary *)writeRecord:(NSDictionary *)record;
|
|
19
|
+
- (NSDictionary *)readRecord;
|
|
20
|
+
- (NSDictionary *)acknowledgeRecordId:(NSString *)recordId;
|
|
21
|
+
- (NSDictionary *)discardRecord;
|
|
22
|
+
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
NS_ASSUME_NONNULL_END
|