@logbrew/react-native 0.1.2 → 0.1.3

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.
@@ -0,0 +1,225 @@
1
+ package co.logbrew.reactnative;
2
+
3
+ import com.facebook.react.bridge.Arguments;
4
+ import com.facebook.react.bridge.ReactApplicationContext;
5
+ import com.facebook.react.bridge.ReadableArray;
6
+ import com.facebook.react.bridge.ReadableMap;
7
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
8
+ import com.facebook.react.bridge.ReadableType;
9
+ import com.facebook.react.bridge.WritableArray;
10
+ import com.facebook.react.bridge.WritableMap;
11
+ import java.io.File;
12
+ import java.util.ArrayList;
13
+ import java.util.Arrays;
14
+ import java.util.HashSet;
15
+ import java.util.List;
16
+ import java.util.Set;
17
+
18
+ final class FatalStoreModuleImpl {
19
+ static final String NAME = "LogBrewFatalStore";
20
+
21
+ private static final Set<String> RECORD_KEYS =
22
+ new HashSet<>(
23
+ Arrays.asList(
24
+ "schemaVersion",
25
+ "id",
26
+ "timestamp",
27
+ "errorName",
28
+ "stackFrames",
29
+ "droppedRecords",
30
+ "corruptRecords"));
31
+ private static final Set<String> FRAME_KEYS =
32
+ new HashSet<>(Arrays.asList("filename", "line", "column"));
33
+
34
+ private final FatalRecordStore store;
35
+
36
+ FatalStoreModuleImpl(ReactApplicationContext context) {
37
+ File root = context.getNoBackupFilesDir();
38
+ store = root == null ? null : new FatalRecordStore(new File(root, "logbrew-fatal-js"));
39
+ }
40
+
41
+ WritableMap writeFatalRecord(ReadableMap input) {
42
+ if (store == null) {
43
+ return status("storage_error");
44
+ }
45
+ try {
46
+ FatalRecordStore.Record record = readRecord(input);
47
+ return record == null ? status("invalid_record") : resultMap(store.write(record));
48
+ } catch (RuntimeException error) {
49
+ return status("storage_error");
50
+ }
51
+ }
52
+
53
+ WritableMap readFatalRecord() {
54
+ if (store == null) {
55
+ return status("storage_error");
56
+ }
57
+ try {
58
+ return resultMap(store.read());
59
+ } catch (RuntimeException error) {
60
+ return status("storage_error");
61
+ }
62
+ }
63
+
64
+ WritableMap acknowledgeFatalRecord(String recordId) {
65
+ if (store == null) {
66
+ return status("storage_error");
67
+ }
68
+ try {
69
+ return resultMap(store.acknowledge(recordId));
70
+ } catch (RuntimeException error) {
71
+ return status("storage_error");
72
+ }
73
+ }
74
+
75
+ WritableMap discardFatalRecord() {
76
+ if (store == null) {
77
+ return status("storage_error");
78
+ }
79
+ try {
80
+ return resultMap(store.discard());
81
+ } catch (RuntimeException error) {
82
+ return status("storage_error");
83
+ }
84
+ }
85
+
86
+ private static FatalRecordStore.Record readRecord(ReadableMap input) {
87
+ if (input == null
88
+ || !hasExactKeys(input, RECORD_KEYS)
89
+ || !hasType(input, "schemaVersion", ReadableType.Number)
90
+ || !hasType(input, "id", ReadableType.String)
91
+ || !hasType(input, "timestamp", ReadableType.String)
92
+ || !hasType(input, "errorName", ReadableType.String)
93
+ || !hasType(input, "stackFrames", ReadableType.Array)
94
+ || !hasType(input, "droppedRecords", ReadableType.Number)
95
+ || !hasType(input, "corruptRecords", ReadableType.Number)) {
96
+ return null;
97
+ }
98
+ Integer schemaVersion = integer(input, "schemaVersion");
99
+ Integer droppedRecords = integer(input, "droppedRecords");
100
+ Integer corruptRecords = integer(input, "corruptRecords");
101
+ if (schemaVersion == null || droppedRecords == null || corruptRecords == null) {
102
+ return null;
103
+ }
104
+
105
+ ReadableArray values = input.getArray("stackFrames");
106
+ if (values == null) {
107
+ return null;
108
+ }
109
+ List<FatalRecordStore.Frame> frames = new ArrayList<>(values.size());
110
+ for (int index = 0; index < values.size(); index += 1) {
111
+ if (values.getType(index) != ReadableType.Map) {
112
+ return null;
113
+ }
114
+ ReadableMap value = values.getMap(index);
115
+ FatalRecordStore.Frame frame = readFrame(value);
116
+ if (frame == null) {
117
+ return null;
118
+ }
119
+ frames.add(frame);
120
+ }
121
+ return new FatalRecordStore.Record(
122
+ schemaVersion,
123
+ input.getString("id"),
124
+ input.getString("timestamp"),
125
+ input.getString("errorName"),
126
+ frames,
127
+ droppedRecords,
128
+ corruptRecords);
129
+ }
130
+
131
+ private static FatalRecordStore.Frame readFrame(ReadableMap input) {
132
+ if (input == null
133
+ || !hasExactKeys(input, FRAME_KEYS)
134
+ || !hasType(input, "filename", ReadableType.String)
135
+ || !hasType(input, "line", ReadableType.Number)
136
+ || !hasType(input, "column", ReadableType.Number)) {
137
+ return null;
138
+ }
139
+ Integer line = integer(input, "line");
140
+ Integer column = integer(input, "column");
141
+ String filename = input.getString("filename");
142
+ if (line == null || column == null || filename == null) {
143
+ return null;
144
+ }
145
+ if (filename.startsWith("/")
146
+ && filename.indexOf('/', 1) < 0
147
+ && filename.length() > 1) {
148
+ filename = filename.substring(1);
149
+ }
150
+ return new FatalRecordStore.Frame(filename, line, column);
151
+ }
152
+
153
+ private static boolean hasType(ReadableMap map, String key, ReadableType type) {
154
+ return map.hasKey(key) && !map.isNull(key) && map.getType(key) == type;
155
+ }
156
+
157
+ private static boolean hasExactKeys(ReadableMap map, Set<String> expected) {
158
+ Set<String> observed = new HashSet<>();
159
+ ReadableMapKeySetIterator iterator = map.keySetIterator();
160
+ while (iterator.hasNextKey()) {
161
+ observed.add(iterator.nextKey());
162
+ }
163
+ return observed.equals(expected);
164
+ }
165
+
166
+ private static Integer integer(ReadableMap map, String key) {
167
+ double value = map.getDouble(key);
168
+ return Double.isFinite(value)
169
+ && value >= 0
170
+ && value <= Integer.MAX_VALUE
171
+ && value == Math.rint(value)
172
+ ? (int) value
173
+ : null;
174
+ }
175
+
176
+ private static WritableMap resultMap(FatalRecordStore.Result result) {
177
+ if (result == null || result.status == null) {
178
+ return status("storage_error");
179
+ }
180
+ WritableMap output = status(result.status);
181
+ if (result.recordId != null) {
182
+ output.putString("recordId", result.recordId);
183
+ }
184
+ if (result.droppedRecords > 0) {
185
+ output.putInt("droppedRecords", result.droppedRecords);
186
+ }
187
+ if (result.corruptRecords > 0) {
188
+ output.putInt("corruptRecords", result.corruptRecords);
189
+ }
190
+ if (result.record != null) {
191
+ output.putMap("record", recordMap(result.record));
192
+ }
193
+ return output;
194
+ }
195
+
196
+ private static WritableMap recordMap(FatalRecordStore.Record record) {
197
+ WritableMap output = Arguments.createMap();
198
+ output.putInt("schemaVersion", record.schemaVersion);
199
+ output.putString("id", record.id);
200
+ output.putString("timestamp", record.timestamp);
201
+ output.putString("errorName", record.errorName);
202
+ output.putArray("stackFrames", frameMaps(record.stackFrames));
203
+ output.putInt("droppedRecords", record.droppedRecords);
204
+ output.putInt("corruptRecords", record.corruptRecords);
205
+ return output;
206
+ }
207
+
208
+ private static WritableArray frameMaps(List<FatalRecordStore.Frame> frames) {
209
+ WritableArray output = Arguments.createArray();
210
+ for (FatalRecordStore.Frame frame : frames) {
211
+ WritableMap value = Arguments.createMap();
212
+ value.putString("filename", frame.filename);
213
+ value.putInt("line", frame.line);
214
+ value.putInt("column", frame.column);
215
+ output.pushMap(value);
216
+ }
217
+ return output;
218
+ }
219
+
220
+ private static WritableMap status(String value) {
221
+ WritableMap output = Arguments.createMap();
222
+ output.putString("status", value);
223
+ return output;
224
+ }
225
+ }
@@ -0,0 +1,20 @@
1
+ package co.logbrew.reactnative;
2
+
3
+ import com.facebook.react.ReactPackage;
4
+ import com.facebook.react.bridge.NativeModule;
5
+ import com.facebook.react.bridge.ReactApplicationContext;
6
+ import com.facebook.react.uimanager.ViewManager;
7
+ import java.util.Collections;
8
+ import java.util.List;
9
+
10
+ public final class LogBrewReactNativePackage implements ReactPackage {
11
+ @Override
12
+ public List<NativeModule> createNativeModules(ReactApplicationContext context) {
13
+ return Collections.singletonList(new FatalStoreModule(context));
14
+ }
15
+
16
+ @Override
17
+ public List<ViewManager> createViewManagers(ReactApplicationContext context) {
18
+ return Collections.emptyList();
19
+ }
20
+ }
@@ -0,0 +1,39 @@
1
+ package co.logbrew.reactnative;
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext;
4
+ import com.facebook.react.bridge.ReadableMap;
5
+ import com.facebook.react.bridge.WritableMap;
6
+
7
+ final class FatalStoreModule extends NativeLogBrewFatalStoreSpec {
8
+ private final FatalStoreModuleImpl implementation;
9
+
10
+ FatalStoreModule(ReactApplicationContext context) {
11
+ super(context);
12
+ implementation = new FatalStoreModuleImpl(context);
13
+ }
14
+
15
+ @Override
16
+ public String getName() {
17
+ return FatalStoreModuleImpl.NAME;
18
+ }
19
+
20
+ @Override
21
+ public WritableMap writeFatalRecord(ReadableMap record) {
22
+ return implementation.writeFatalRecord(record);
23
+ }
24
+
25
+ @Override
26
+ public WritableMap readFatalRecord() {
27
+ return implementation.readFatalRecord();
28
+ }
29
+
30
+ @Override
31
+ public WritableMap acknowledgeFatalRecord(String recordId) {
32
+ return implementation.acknowledgeFatalRecord(recordId);
33
+ }
34
+
35
+ @Override
36
+ public WritableMap discardFatalRecord() {
37
+ return implementation.discardFatalRecord();
38
+ }
39
+ }
@@ -0,0 +1,41 @@
1
+ package co.logbrew.reactnative;
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext;
4
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
5
+ import com.facebook.react.bridge.ReactMethod;
6
+ import com.facebook.react.bridge.ReadableMap;
7
+ import com.facebook.react.bridge.WritableMap;
8
+
9
+ final class FatalStoreModule extends ReactContextBaseJavaModule {
10
+ private final FatalStoreModuleImpl implementation;
11
+
12
+ FatalStoreModule(ReactApplicationContext context) {
13
+ super(context);
14
+ implementation = new FatalStoreModuleImpl(context);
15
+ }
16
+
17
+ @Override
18
+ public String getName() {
19
+ return FatalStoreModuleImpl.NAME;
20
+ }
21
+
22
+ @ReactMethod(isBlockingSynchronousMethod = true)
23
+ public WritableMap writeFatalRecord(ReadableMap record) {
24
+ return implementation.writeFatalRecord(record);
25
+ }
26
+
27
+ @ReactMethod(isBlockingSynchronousMethod = true)
28
+ public WritableMap readFatalRecord() {
29
+ return implementation.readFatalRecord();
30
+ }
31
+
32
+ @ReactMethod(isBlockingSynchronousMethod = true)
33
+ public WritableMap acknowledgeFatalRecord(String recordId) {
34
+ return implementation.acknowledgeFatalRecord(recordId);
35
+ }
36
+
37
+ @ReactMethod(isBlockingSynchronousMethod = true)
38
+ public WritableMap discardFatalRecord() {
39
+ return implementation.discardFatalRecord();
40
+ }
41
+ }