@goliapkg/sentori-react-native 3.1.0 → 5.0.0
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/android/build.gradle +21 -0
- package/android/src/main/java/com/sentori/SentoriCrashHandler.kt +29 -0
- package/android/src/test/java/com/sentori/SentoriCrashHandlerTest.kt +7 -2
- package/android/src/test/resources/robolectric.properties +10 -0
- package/lib/config.d.ts +16 -47
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +3 -0
- package/lib/config.js.map +1 -1
- package/lib/device.d.ts +5 -0
- package/lib/device.d.ts.map +1 -0
- package/lib/device.js +29 -0
- package/lib/device.js.map +1 -0
- package/lib/emit-hooks.d.ts +7 -0
- package/lib/emit-hooks.d.ts.map +1 -0
- package/lib/emit-hooks.js +24 -0
- package/lib/emit-hooks.js.map +1 -0
- package/lib/error-boundary.d.ts.map +1 -1
- package/lib/error-boundary.js +1 -1
- package/lib/error-boundary.js.map +1 -1
- package/lib/feature-flags.d.ts.map +1 -1
- package/lib/handlers/dev-symbolicate.d.ts +1 -1
- package/lib/handlers/dev-symbolicate.d.ts.map +1 -1
- package/lib/handlers/dev-symbolicate.js +2 -0
- package/lib/handlers/dev-symbolicate.js.map +1 -1
- package/lib/handlers/global.js +1 -1
- package/lib/handlers/global.js.map +1 -1
- package/lib/handlers/lifecycle.js +3 -3
- package/lib/handlers/lifecycle.js.map +1 -1
- package/lib/handlers/network.d.ts +2 -2
- package/lib/handlers/network.d.ts.map +1 -1
- package/lib/handlers/network.js +69 -187
- package/lib/handlers/network.js.map +1 -1
- package/lib/handlers/promise.js +1 -1
- package/lib/handlers/promise.js.map +1 -1
- package/lib/handlers/screenshot.d.ts.map +1 -1
- package/lib/handlers/screenshot.js +3 -12
- package/lib/handlers/screenshot.js.map +1 -1
- package/lib/index.d.ts +31 -109
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +51 -103
- package/lib/index.js.map +1 -1
- package/lib/init.d.ts +3 -150
- package/lib/init.d.ts.map +1 -1
- package/lib/init.js +88 -261
- package/lib/init.js.map +1 -1
- package/lib/long-task-monitor.d.ts +1 -7
- package/lib/long-task-monitor.d.ts.map +1 -1
- package/lib/long-task-monitor.js +37 -58
- package/lib/long-task-monitor.js.map +1 -1
- package/lib/mobile-vitals.d.ts +3 -31
- package/lib/mobile-vitals.d.ts.map +1 -1
- package/lib/mobile-vitals.js +22 -61
- package/lib/mobile-vitals.js.map +1 -1
- package/lib/native-pending.d.ts +3 -0
- package/lib/native-pending.d.ts.map +1 -0
- package/lib/native-pending.js +64 -0
- package/lib/native-pending.js.map +1 -0
- package/lib/navigation.d.ts +3 -17
- package/lib/navigation.d.ts.map +1 -1
- package/lib/navigation.js +32 -133
- package/lib/navigation.js.map +1 -1
- package/lib/netinfo.d.ts +1 -1
- package/lib/netinfo.d.ts.map +1 -1
- package/lib/netinfo.js +2 -2
- package/lib/netinfo.js.map +1 -1
- package/lib/push.d.ts.map +1 -1
- package/lib/push.js +2 -4
- package/lib/push.js.map +1 -1
- package/lib/rage-tap.d.ts.map +1 -1
- package/lib/rage-tap.js +28 -23
- package/lib/rage-tap.js.map +1 -1
- package/lib/replay.d.ts.map +1 -1
- package/lib/replay.js +3 -24
- package/lib/replay.js.map +1 -1
- package/lib/scope.d.ts +7 -0
- package/lib/scope.d.ts.map +1 -0
- package/lib/scope.js +41 -0
- package/lib/scope.js.map +1 -0
- package/lib/transport.d.ts +19 -92
- package/lib/transport.d.ts.map +1 -1
- package/lib/transport.js +75 -288
- package/lib/transport.js.map +1 -1
- package/lib/verbs.d.ts +16 -0
- package/lib/verbs.d.ts.map +1 -0
- package/lib/verbs.js +153 -0
- package/lib/verbs.js.map +1 -0
- package/package.json +5 -5
- package/src/__tests__/iron-rule.test.ts +128 -0
- package/src/__tests__/screenshot.test.ts +0 -2
- package/src/__tests__/transport.test.ts +66 -213
- package/src/__tests__/verbs.test.ts +91 -0
- package/src/config.ts +19 -47
- package/src/device.ts +36 -0
- package/src/emit-hooks.ts +30 -0
- package/src/error-boundary.tsx +1 -1
- package/src/handlers/dev-symbolicate.ts +2 -1
- package/src/handlers/global.ts +1 -1
- package/src/handlers/lifecycle.ts +3 -3
- package/src/handlers/network.ts +95 -211
- package/src/handlers/promise.ts +1 -1
- package/src/handlers/screenshot.ts +3 -11
- package/src/index.ts +81 -215
- package/src/init.ts +94 -446
- package/src/long-task-monitor.ts +42 -64
- package/src/mobile-vitals.ts +22 -82
- package/src/native-pending.ts +92 -0
- package/src/navigation.ts +34 -142
- package/src/netinfo.ts +3 -3
- package/src/push.ts +2 -5
- package/src/rage-tap.tsx +29 -26
- package/src/replay.ts +3 -20
- package/src/scope.ts +50 -0
- package/src/transport.ts +84 -371
- package/src/verbs.ts +198 -0
- package/lib/breadcrumbs.d.ts +0 -18
- package/lib/breadcrumbs.d.ts.map +0 -1
- package/lib/breadcrumbs.js +0 -42
- package/lib/breadcrumbs.js.map +0 -1
- package/lib/bundle-info.d.ts +0 -12
- package/lib/bundle-info.d.ts.map +0 -1
- package/lib/bundle-info.js +0 -73
- package/lib/bundle-info.js.map +0 -1
- package/lib/capture.d.ts +0 -140
- package/lib/capture.d.ts.map +0 -1
- package/lib/capture.js +0 -511
- package/lib/capture.js.map +0 -1
- package/lib/compat/sentry.d.ts +0 -126
- package/lib/compat/sentry.d.ts.map +0 -1
- package/lib/compat/sentry.js +0 -332
- package/lib/compat/sentry.js.map +0 -1
- package/lib/control-channel.d.ts +0 -6
- package/lib/control-channel.d.ts.map +0 -1
- package/lib/control-channel.js +0 -96
- package/lib/control-channel.js.map +0 -1
- package/lib/expo-compat.d.ts +0 -270
- package/lib/expo-compat.d.ts.map +0 -1
- package/lib/expo-compat.js +0 -500
- package/lib/expo-compat.js.map +0 -1
- package/lib/feedback-widget.d.ts +0 -35
- package/lib/feedback-widget.d.ts.map +0 -1
- package/lib/feedback-widget.js +0 -193
- package/lib/feedback-widget.js.map +0 -1
- package/lib/feedback.d.ts +0 -2
- package/lib/feedback.d.ts.map +0 -1
- package/lib/feedback.js +0 -17
- package/lib/feedback.js.map +0 -1
- package/lib/heartbeat.d.ts +0 -9
- package/lib/heartbeat.d.ts.map +0 -1
- package/lib/heartbeat.js +0 -138
- package/lib/heartbeat.js.map +0 -1
- package/lib/index.js.bak +0 -64
- package/lib/install-id.d.ts +0 -17
- package/lib/install-id.d.ts.map +0 -1
- package/lib/install-id.js +0 -125
- package/lib/install-id.js.map +0 -1
- package/lib/lifecycle.d.ts +0 -28
- package/lib/lifecycle.d.ts.map +0 -1
- package/lib/lifecycle.js +0 -73
- package/lib/lifecycle.js.map +0 -1
- package/lib/mask.d.ts +0 -16
- package/lib/mask.d.ts.map +0 -1
- package/lib/mask.js +0 -36
- package/lib/mask.js.map +0 -1
- package/lib/measure.d.ts +0 -4
- package/lib/measure.d.ts.map +0 -1
- package/lib/measure.js +0 -25
- package/lib/measure.js.map +0 -1
- package/lib/metrics.d.ts +0 -24
- package/lib/metrics.d.ts.map +0 -1
- package/lib/metrics.js +0 -81
- package/lib/metrics.js.map +0 -1
- package/lib/pre-crash-sentinel.d.ts +0 -12
- package/lib/pre-crash-sentinel.d.ts.map +0 -1
- package/lib/pre-crash-sentinel.js +0 -116
- package/lib/pre-crash-sentinel.js.map +0 -1
- package/lib/report-security.d.ts +0 -40
- package/lib/report-security.d.ts.map +0 -1
- package/lib/report-security.js +0 -159
- package/lib/report-security.js.map +0 -1
- package/lib/runtime-metrics-fps.d.ts +0 -19
- package/lib/runtime-metrics-fps.d.ts.map +0 -1
- package/lib/runtime-metrics-fps.js +0 -128
- package/lib/runtime-metrics-fps.js.map +0 -1
- package/lib/runtime-metrics-heap.d.ts +0 -13
- package/lib/runtime-metrics-heap.d.ts.map +0 -1
- package/lib/runtime-metrics-heap.js +0 -67
- package/lib/runtime-metrics-heap.js.map +0 -1
- package/lib/runtime-metrics-network.d.ts +0 -23
- package/lib/runtime-metrics-network.d.ts.map +0 -1
- package/lib/runtime-metrics-network.js +0 -99
- package/lib/runtime-metrics-network.js.map +0 -1
- package/lib/runtime-metrics.d.ts +0 -43
- package/lib/runtime-metrics.d.ts.map +0 -1
- package/lib/runtime-metrics.js +0 -115
- package/lib/runtime-metrics.js.map +0 -1
- package/lib/sample-profiler.d.ts +0 -21
- package/lib/sample-profiler.d.ts.map +0 -1
- package/lib/sample-profiler.js +0 -152
- package/lib/sample-profiler.js.map +0 -1
- package/lib/sentinel-context.d.ts +0 -4
- package/lib/sentinel-context.d.ts.map +0 -1
- package/lib/sentinel-context.js +0 -52
- package/lib/sentinel-context.js.map +0 -1
- package/lib/session-tracker.d.ts +0 -6
- package/lib/session-tracker.d.ts.map +0 -1
- package/lib/session-tracker.js +0 -50
- package/lib/session-tracker.js.map +0 -1
- package/lib/stack.d.ts +0 -3
- package/lib/stack.d.ts.map +0 -1
- package/lib/stack.js +0 -7
- package/lib/stack.js.map +0 -1
- package/lib/state-snapshots.d.ts +0 -33
- package/lib/state-snapshots.d.ts.map +0 -1
- package/lib/state-snapshots.js +0 -109
- package/lib/state-snapshots.js.map +0 -1
- package/lib/track.d.ts +0 -34
- package/lib/track.d.ts.map +0 -1
- package/lib/track.js +0 -107
- package/lib/track.js.map +0 -1
- package/lib/trail.d.ts +0 -12
- package/lib/trail.d.ts.map +0 -1
- package/lib/trail.js +0 -28
- package/lib/trail.js.map +0 -1
- package/lib/trust-score.d.ts +0 -20
- package/lib/trust-score.d.ts.map +0 -1
- package/lib/trust-score.js +0 -151
- package/lib/trust-score.js.map +0 -1
- package/lib/types.d.ts +0 -2
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -4
- package/lib/types.js.map +0 -1
- package/lib/uuid.d.ts +0 -2
- package/lib/uuid.d.ts.map +0 -1
- package/lib/uuid.js +0 -3
- package/lib/uuid.js.map +0 -1
- package/src/__tests__/before-send.test.ts +0 -72
- package/src/__tests__/breadcrumbs.test.ts +0 -44
- package/src/__tests__/capture-replay.test.ts +0 -150
- package/src/__tests__/compat-sentry.test.ts +0 -121
- package/src/__tests__/control-channel.test.ts +0 -111
- package/src/__tests__/install-id.test.ts +0 -60
- package/src/__tests__/long-task-monitor.test.ts +0 -59
- package/src/__tests__/measure.test.ts +0 -45
- package/src/__tests__/navigation.test.ts +0 -175
- package/src/__tests__/push.test.ts +0 -238
- package/src/__tests__/report-security.test.ts +0 -106
- package/src/__tests__/runtime-metrics-instruments.test.ts +0 -109
- package/src/__tests__/runtime-metrics-network.test.ts +0 -78
- package/src/__tests__/sample-profiler.test.ts +0 -59
- package/src/__tests__/stack.test.ts +0 -45
- package/src/__tests__/state-snapshots.test.ts +0 -119
- package/src/__tests__/tracing.test.ts +0 -201
- package/src/__tests__/track.test.ts +0 -91
- package/src/__tests__/uuid.test.ts +0 -41
- package/src/breadcrumbs.ts +0 -57
- package/src/bundle-info.ts +0 -95
- package/src/capture.ts +0 -660
- package/src/compat/sentry.ts +0 -490
- package/src/control-channel.ts +0 -98
- package/src/expo-compat.ts +0 -698
- package/src/feedback-widget.tsx +0 -316
- package/src/feedback.ts +0 -21
- package/src/heartbeat.ts +0 -157
- package/src/install-id.ts +0 -146
- package/src/lifecycle.ts +0 -76
- package/src/mask.ts +0 -41
- package/src/measure.ts +0 -28
- package/src/metrics.ts +0 -94
- package/src/pre-crash-sentinel.ts +0 -140
- package/src/report-security.ts +0 -165
- package/src/runtime-metrics-fps.ts +0 -137
- package/src/runtime-metrics-heap.ts +0 -78
- package/src/runtime-metrics-network.ts +0 -103
- package/src/runtime-metrics.ts +0 -122
- package/src/sample-profiler.ts +0 -169
- package/src/sentinel-context.ts +0 -60
- package/src/session-tracker.ts +0 -53
- package/src/stack.ts +0 -10
- package/src/state-snapshots.ts +0 -133
- package/src/track.ts +0 -123
- package/src/trail.ts +0 -32
- package/src/trust-score.ts +0 -176
- package/src/types.ts +0 -21
- package/src/uuid.ts +0 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// The five verbs: synchronous, never throw, id out, correct wire.
|
|
2
|
+
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
|
4
|
+
|
|
5
|
+
import { clearSignals } from '@goliapkg/sentori-core';
|
|
6
|
+
|
|
7
|
+
import { __resetForTests as resetConfig, setConfig } from '../config';
|
|
8
|
+
import { __resetForTests as resetScope } from '../scope';
|
|
9
|
+
import {
|
|
10
|
+
__peekAssertStats,
|
|
11
|
+
__peekQueue,
|
|
12
|
+
__resetForTests as resetTransport,
|
|
13
|
+
startTransport,
|
|
14
|
+
} from '../transport';
|
|
15
|
+
import { verbs } from '../verbs';
|
|
16
|
+
|
|
17
|
+
const baseConfig = {
|
|
18
|
+
token: 'st_test',
|
|
19
|
+
ingestUrl: 'http://localhost:18080',
|
|
20
|
+
release: 'app@1.0.0',
|
|
21
|
+
environment: 'test',
|
|
22
|
+
enabled: true,
|
|
23
|
+
detect: { rageTap: true, longFreeze: true, slowColdStart: true, slowApi: false },
|
|
24
|
+
replaySeconds: 30,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe('the five verbs', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
resetTransport();
|
|
30
|
+
resetConfig();
|
|
31
|
+
resetScope();
|
|
32
|
+
clearSignals();
|
|
33
|
+
setConfig(baseConfig);
|
|
34
|
+
startTransport();
|
|
35
|
+
});
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
resetTransport();
|
|
38
|
+
resetConfig();
|
|
39
|
+
resetScope();
|
|
40
|
+
clearSignals();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('error coerces anything and enqueues with a stack', () => {
|
|
44
|
+
const id = verbs.error(new Error('boom'));
|
|
45
|
+
expect(typeof id).toBe('string');
|
|
46
|
+
const q = __peekQueue();
|
|
47
|
+
expect(q.length).toBe(1);
|
|
48
|
+
expect(q[0]?.kind).toBe('error');
|
|
49
|
+
expect(q[0]?.payload.error?.type).toBe('Error');
|
|
50
|
+
expect(q[0]?.payload.error?.message).toBe('boom');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('error serializes Error instances found in data (error-in-data)', () => {
|
|
54
|
+
verbs.warn('pay.retry', { attempt: 2, error: new TypeError('nope') });
|
|
55
|
+
const q = __peekQueue();
|
|
56
|
+
const data = q[0]?.payload.data as { error?: { type?: string } };
|
|
57
|
+
expect(data.error?.type).toBe('TypeError');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('warn carries name; trace quiet stays out of the queue', () => {
|
|
61
|
+
verbs.warn('rage_tap');
|
|
62
|
+
expect(__peekQueue().length).toBe(1);
|
|
63
|
+
verbs.trace('checkout.start', undefined, { quiet: true });
|
|
64
|
+
expect(__peekQueue().length).toBe(1); // unchanged
|
|
65
|
+
verbs.trace('checkout.start');
|
|
66
|
+
expect(__peekQueue().length).toBe(2);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('assert pass aggregates without an event; fail is an event', () => {
|
|
70
|
+
verbs.assert('total-positive', true);
|
|
71
|
+
expect(__peekQueue().length).toBe(0);
|
|
72
|
+
expect(__peekAssertStats()[0]?.passDelta).toBe(1);
|
|
73
|
+
verbs.assert('total-positive', false);
|
|
74
|
+
expect(__peekQueue().length).toBe(1);
|
|
75
|
+
expect(__peekQueue()[0]?.kind).toBe('assert');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('probe never throws and reports the ref as name', () => {
|
|
79
|
+
const id = verbs.probe('SENT-123');
|
|
80
|
+
expect(typeof id).toBe('string');
|
|
81
|
+
expect(__peekQueue()[0]?.kind).toBe('probe');
|
|
82
|
+
expect(__peekQueue()[0]?.name).toBe('SENT-123');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('before init everything is a silent no-op that still returns an id', () => {
|
|
86
|
+
resetConfig();
|
|
87
|
+
const id = verbs.error(new Error('x'));
|
|
88
|
+
expect(typeof id).toBe('string');
|
|
89
|
+
expect(__peekQueue().length).toBe(0);
|
|
90
|
+
});
|
|
91
|
+
});
|
package/src/config.ts
CHANGED
|
@@ -1,58 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
// SDK-internal runtime config, set once by init(). Everything else
|
|
2
|
+
// reads through getConfig() and treats null as "not initialized →
|
|
3
|
+
// every verb is a no-op" (the failure-isolation iron rule).
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
* v2.3 — `ReadyInfo` is shared across SDKs via `@goliapkg/sentori-core`
|
|
5
|
-
* so a host that switches from web to RN reads the same shape. The RN
|
|
6
|
-
* SDK always populates `native` + `coldStartMs`; the core type marks
|
|
7
|
-
* both optional for the web SDK's benefit (web has no native module).
|
|
8
|
-
*/
|
|
9
|
-
export type { ReadyInfo };
|
|
5
|
+
import type { LogLevel, WireEvent } from '@goliapkg/sentori-core';
|
|
10
6
|
|
|
11
7
|
export type Config = {
|
|
12
8
|
token: string;
|
|
9
|
+
ingestUrl: string;
|
|
13
10
|
release: string;
|
|
14
11
|
environment: string;
|
|
15
|
-
ingestUrl: string;
|
|
16
12
|
enabled: boolean;
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* attachment. Defaults to false. */
|
|
29
|
-
sessionTrailEnabled: boolean;
|
|
30
|
-
/** v2.0 W3 — when true, every `track(name, props)` call also
|
|
31
|
-
* pushes a `{ type: 'track', data: { name, props } }` breadcrumb
|
|
32
|
-
* so a subsequent capture carries the customer journey. Defaults
|
|
33
|
-
* to false to preserve v1 customer breadcrumb shape on upgrade. */
|
|
34
|
-
trackAutoBreadcrumb: boolean;
|
|
35
|
-
/** v2.3 — Sentori console output gate.
|
|
36
|
-
*
|
|
37
|
-
* Default `warn`: SDK is silent on host's console unless
|
|
38
|
-
* something is genuinely broken (transport sustained failure,
|
|
39
|
-
* native module not found, internal SDK exception). No
|
|
40
|
-
* per-tick / per-init / per-breadcrumb noise.
|
|
41
|
-
*
|
|
42
|
-
* Set `'silent'` for absolute silence (e.g. CI smoke runs);
|
|
43
|
-
* set `'info'` or `'debug'` when debugging Sentori itself. */
|
|
13
|
+
/** Warn-scenario auto-detection switches (conservative defaults). */
|
|
14
|
+
detect: {
|
|
15
|
+
rageTap: boolean;
|
|
16
|
+
longFreeze: boolean;
|
|
17
|
+
slowColdStart: boolean;
|
|
18
|
+
slowApi: boolean;
|
|
19
|
+
};
|
|
20
|
+
/** B-type replay rolling buffer, seconds. 0 disables. */
|
|
21
|
+
replaySeconds: number;
|
|
22
|
+
/** Sentori console output gate. Default `warn`: silent on the
|
|
23
|
+
* host's console unless something is genuinely broken. */
|
|
44
24
|
logLevel?: LogLevel;
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
* wraps any host-side logging here. */
|
|
49
|
-
onReady?: (info: ReadyInfo) => void;
|
|
50
|
-
/** v2.3 — host-side mutate-or-drop hook called once per event
|
|
51
|
-
* just before transport enqueue. Return the event to send it,
|
|
52
|
-
* `null` to drop. Sync only. If the hook throws or returns a
|
|
53
|
-
* non-event, SDK falls back to the un-mutated event and emits
|
|
54
|
-
* one one-shot warn. */
|
|
55
|
-
beforeSend?: BeforeSendHook;
|
|
25
|
+
/** Host-side mutate-or-drop hook, sync only. Throw / bad return →
|
|
26
|
+
* the un-mutated event ships and one warn is emitted. */
|
|
27
|
+
beforeSend?: (event: WireEvent) => WireEvent | null;
|
|
56
28
|
};
|
|
57
29
|
|
|
58
30
|
let _config: Config | null = null;
|
package/src/device.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Synchronous device snapshot — what the JS layer can know without
|
|
2
|
+
// crossing the bridge. The native module enriches asynchronously via
|
|
3
|
+
// setNativeDeviceInfo at init; until then the JS-visible subset
|
|
4
|
+
// ships (an event with a thin device beats a delayed event).
|
|
5
|
+
|
|
6
|
+
import type { Device } from '@goliapkg/sentori-core';
|
|
7
|
+
|
|
8
|
+
let _native: Partial<Device> | null = null;
|
|
9
|
+
|
|
10
|
+
export const setNativeDeviceInfo = (info: Partial<Device>): void => {
|
|
11
|
+
_native = info;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const collectDevice = (): Device | undefined => {
|
|
15
|
+
let base: Device | undefined;
|
|
16
|
+
try {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
|
+
const RN = require('react-native') as {
|
|
19
|
+
Platform?: { OS?: string; Version?: number | string };
|
|
20
|
+
Dimensions?: { get(dim: string): { width: number; height: number; scale: number } };
|
|
21
|
+
};
|
|
22
|
+
const os = RN.Platform?.OS ?? 'unknown';
|
|
23
|
+
base = { os, osVersion: RN.Platform?.Version?.toString() };
|
|
24
|
+
const win = RN.Dimensions?.get('window');
|
|
25
|
+
if (win) {
|
|
26
|
+
base.screen = { width: win.width, height: win.height, scale: win.scale };
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
return _native ? ({ os: 'unknown', ..._native } as Device) : undefined;
|
|
30
|
+
}
|
|
31
|
+
return _native ? { ...base, ..._native } : base;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const __resetForTests = (): void => {
|
|
35
|
+
_native = null;
|
|
36
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Post-emit hooks — how B-type replay (and future reactions) learn
|
|
2
|
+
// "an event just went out" without the verbs knowing about them.
|
|
3
|
+
//
|
|
4
|
+
// Hooks run inside their own try/catch: a broken subscriber must
|
|
5
|
+
// never take the emit path down with it (failure isolation).
|
|
6
|
+
|
|
7
|
+
import type { WireEvent } from '@goliapkg/sentori-core';
|
|
8
|
+
import { reportInternal } from '@goliapkg/sentori-core';
|
|
9
|
+
|
|
10
|
+
type EmitHook = (event: WireEvent) => void;
|
|
11
|
+
|
|
12
|
+
const hooks: EmitHook[] = [];
|
|
13
|
+
|
|
14
|
+
export const registerEmitHook = (hook: EmitHook): void => {
|
|
15
|
+
hooks.push(hook);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const onEventEmitted = (event: WireEvent): void => {
|
|
19
|
+
for (const hook of hooks) {
|
|
20
|
+
try {
|
|
21
|
+
hook(event);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
reportInternal('emit-hook', e);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const __resetForTests = (): void => {
|
|
29
|
+
hooks.length = 0;
|
|
30
|
+
};
|
package/src/error-boundary.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
import { captureError } from
|
|
3
|
+
import { error as captureError } from "./verbs";
|
|
4
4
|
|
|
5
5
|
export type ErrorBoundaryProps = {
|
|
6
6
|
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// Best-effort and dev-only: any failure (Metro not running, timeout,
|
|
8
8
|
// bad response) leaves the stack untouched. Never throws.
|
|
9
9
|
|
|
10
|
-
import type { Frame, SentoriError } from '
|
|
10
|
+
import type { Frame, SentoriError } from '@goliapkg/sentori-core';
|
|
11
11
|
|
|
12
12
|
const TIMEOUT_MS = 2000;
|
|
13
13
|
|
|
@@ -132,6 +132,7 @@ export async function symbolicateErrorViaMetro(
|
|
|
132
132
|
err: SentoriError,
|
|
133
133
|
opts: { url?: string } = {},
|
|
134
134
|
): Promise<void> {
|
|
135
|
+
if (!err.stack) return;
|
|
135
136
|
const sym = await symbolicateStackViaMetro(err.stack, opts);
|
|
136
137
|
if (sym) err.stack = sym;
|
|
137
138
|
if (err.cause) await symbolicateErrorViaMetro(err.cause, opts);
|
package/src/handlers/global.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* twice". Sentry historically did the opposite (treat inactive as
|
|
13
13
|
* still alive), but that lets a swiped-away session never end.
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { pushSignal } from '@goliapkg/sentori-core';
|
|
16
16
|
|
|
17
17
|
let _installed = false;
|
|
18
18
|
let _subscription: { remove: () => void } | null = null;
|
|
@@ -40,9 +40,9 @@ export const installLifecycleHandler = (): void => {
|
|
|
40
40
|
|
|
41
41
|
_subscription = AppState.addEventListener('change', (state) => {
|
|
42
42
|
if (state === 'active') {
|
|
43
|
-
|
|
43
|
+
pushSignal('lifecycle', { state: 'active' });
|
|
44
44
|
} else if (state === 'background' || state === 'inactive') {
|
|
45
|
-
|
|
45
|
+
pushSignal('lifecycle', { state: 'background' });
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
};
|