@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.
Files changed (284) hide show
  1. package/android/build.gradle +21 -0
  2. package/android/src/main/java/com/sentori/SentoriCrashHandler.kt +29 -0
  3. package/android/src/test/java/com/sentori/SentoriCrashHandlerTest.kt +7 -2
  4. package/android/src/test/resources/robolectric.properties +10 -0
  5. package/lib/config.d.ts +16 -47
  6. package/lib/config.d.ts.map +1 -1
  7. package/lib/config.js +3 -0
  8. package/lib/config.js.map +1 -1
  9. package/lib/device.d.ts +5 -0
  10. package/lib/device.d.ts.map +1 -0
  11. package/lib/device.js +29 -0
  12. package/lib/device.js.map +1 -0
  13. package/lib/emit-hooks.d.ts +7 -0
  14. package/lib/emit-hooks.d.ts.map +1 -0
  15. package/lib/emit-hooks.js +24 -0
  16. package/lib/emit-hooks.js.map +1 -0
  17. package/lib/error-boundary.d.ts.map +1 -1
  18. package/lib/error-boundary.js +1 -1
  19. package/lib/error-boundary.js.map +1 -1
  20. package/lib/feature-flags.d.ts.map +1 -1
  21. package/lib/handlers/dev-symbolicate.d.ts +1 -1
  22. package/lib/handlers/dev-symbolicate.d.ts.map +1 -1
  23. package/lib/handlers/dev-symbolicate.js +2 -0
  24. package/lib/handlers/dev-symbolicate.js.map +1 -1
  25. package/lib/handlers/global.js +1 -1
  26. package/lib/handlers/global.js.map +1 -1
  27. package/lib/handlers/lifecycle.js +3 -3
  28. package/lib/handlers/lifecycle.js.map +1 -1
  29. package/lib/handlers/network.d.ts +2 -2
  30. package/lib/handlers/network.d.ts.map +1 -1
  31. package/lib/handlers/network.js +69 -187
  32. package/lib/handlers/network.js.map +1 -1
  33. package/lib/handlers/promise.js +1 -1
  34. package/lib/handlers/promise.js.map +1 -1
  35. package/lib/handlers/screenshot.d.ts.map +1 -1
  36. package/lib/handlers/screenshot.js +3 -12
  37. package/lib/handlers/screenshot.js.map +1 -1
  38. package/lib/index.d.ts +31 -109
  39. package/lib/index.d.ts.map +1 -1
  40. package/lib/index.js +51 -103
  41. package/lib/index.js.map +1 -1
  42. package/lib/init.d.ts +3 -150
  43. package/lib/init.d.ts.map +1 -1
  44. package/lib/init.js +88 -261
  45. package/lib/init.js.map +1 -1
  46. package/lib/long-task-monitor.d.ts +1 -7
  47. package/lib/long-task-monitor.d.ts.map +1 -1
  48. package/lib/long-task-monitor.js +37 -58
  49. package/lib/long-task-monitor.js.map +1 -1
  50. package/lib/mobile-vitals.d.ts +3 -31
  51. package/lib/mobile-vitals.d.ts.map +1 -1
  52. package/lib/mobile-vitals.js +22 -61
  53. package/lib/mobile-vitals.js.map +1 -1
  54. package/lib/native-pending.d.ts +3 -0
  55. package/lib/native-pending.d.ts.map +1 -0
  56. package/lib/native-pending.js +64 -0
  57. package/lib/native-pending.js.map +1 -0
  58. package/lib/navigation.d.ts +3 -17
  59. package/lib/navigation.d.ts.map +1 -1
  60. package/lib/navigation.js +32 -133
  61. package/lib/navigation.js.map +1 -1
  62. package/lib/netinfo.d.ts +1 -1
  63. package/lib/netinfo.d.ts.map +1 -1
  64. package/lib/netinfo.js +2 -2
  65. package/lib/netinfo.js.map +1 -1
  66. package/lib/push.d.ts.map +1 -1
  67. package/lib/push.js +2 -4
  68. package/lib/push.js.map +1 -1
  69. package/lib/rage-tap.d.ts.map +1 -1
  70. package/lib/rage-tap.js +28 -23
  71. package/lib/rage-tap.js.map +1 -1
  72. package/lib/replay.d.ts.map +1 -1
  73. package/lib/replay.js +3 -24
  74. package/lib/replay.js.map +1 -1
  75. package/lib/scope.d.ts +7 -0
  76. package/lib/scope.d.ts.map +1 -0
  77. package/lib/scope.js +41 -0
  78. package/lib/scope.js.map +1 -0
  79. package/lib/transport.d.ts +19 -92
  80. package/lib/transport.d.ts.map +1 -1
  81. package/lib/transport.js +75 -288
  82. package/lib/transport.js.map +1 -1
  83. package/lib/verbs.d.ts +16 -0
  84. package/lib/verbs.d.ts.map +1 -0
  85. package/lib/verbs.js +153 -0
  86. package/lib/verbs.js.map +1 -0
  87. package/package.json +5 -5
  88. package/src/__tests__/iron-rule.test.ts +128 -0
  89. package/src/__tests__/screenshot.test.ts +0 -2
  90. package/src/__tests__/transport.test.ts +66 -213
  91. package/src/__tests__/verbs.test.ts +91 -0
  92. package/src/config.ts +19 -47
  93. package/src/device.ts +36 -0
  94. package/src/emit-hooks.ts +30 -0
  95. package/src/error-boundary.tsx +1 -1
  96. package/src/handlers/dev-symbolicate.ts +2 -1
  97. package/src/handlers/global.ts +1 -1
  98. package/src/handlers/lifecycle.ts +3 -3
  99. package/src/handlers/network.ts +95 -211
  100. package/src/handlers/promise.ts +1 -1
  101. package/src/handlers/screenshot.ts +3 -11
  102. package/src/index.ts +81 -215
  103. package/src/init.ts +94 -446
  104. package/src/long-task-monitor.ts +42 -64
  105. package/src/mobile-vitals.ts +22 -82
  106. package/src/native-pending.ts +92 -0
  107. package/src/navigation.ts +34 -142
  108. package/src/netinfo.ts +3 -3
  109. package/src/push.ts +2 -5
  110. package/src/rage-tap.tsx +29 -26
  111. package/src/replay.ts +3 -20
  112. package/src/scope.ts +50 -0
  113. package/src/transport.ts +84 -371
  114. package/src/verbs.ts +198 -0
  115. package/lib/breadcrumbs.d.ts +0 -18
  116. package/lib/breadcrumbs.d.ts.map +0 -1
  117. package/lib/breadcrumbs.js +0 -42
  118. package/lib/breadcrumbs.js.map +0 -1
  119. package/lib/bundle-info.d.ts +0 -12
  120. package/lib/bundle-info.d.ts.map +0 -1
  121. package/lib/bundle-info.js +0 -73
  122. package/lib/bundle-info.js.map +0 -1
  123. package/lib/capture.d.ts +0 -140
  124. package/lib/capture.d.ts.map +0 -1
  125. package/lib/capture.js +0 -511
  126. package/lib/capture.js.map +0 -1
  127. package/lib/compat/sentry.d.ts +0 -126
  128. package/lib/compat/sentry.d.ts.map +0 -1
  129. package/lib/compat/sentry.js +0 -332
  130. package/lib/compat/sentry.js.map +0 -1
  131. package/lib/control-channel.d.ts +0 -6
  132. package/lib/control-channel.d.ts.map +0 -1
  133. package/lib/control-channel.js +0 -96
  134. package/lib/control-channel.js.map +0 -1
  135. package/lib/expo-compat.d.ts +0 -270
  136. package/lib/expo-compat.d.ts.map +0 -1
  137. package/lib/expo-compat.js +0 -500
  138. package/lib/expo-compat.js.map +0 -1
  139. package/lib/feedback-widget.d.ts +0 -35
  140. package/lib/feedback-widget.d.ts.map +0 -1
  141. package/lib/feedback-widget.js +0 -193
  142. package/lib/feedback-widget.js.map +0 -1
  143. package/lib/feedback.d.ts +0 -2
  144. package/lib/feedback.d.ts.map +0 -1
  145. package/lib/feedback.js +0 -17
  146. package/lib/feedback.js.map +0 -1
  147. package/lib/heartbeat.d.ts +0 -9
  148. package/lib/heartbeat.d.ts.map +0 -1
  149. package/lib/heartbeat.js +0 -138
  150. package/lib/heartbeat.js.map +0 -1
  151. package/lib/index.js.bak +0 -64
  152. package/lib/install-id.d.ts +0 -17
  153. package/lib/install-id.d.ts.map +0 -1
  154. package/lib/install-id.js +0 -125
  155. package/lib/install-id.js.map +0 -1
  156. package/lib/lifecycle.d.ts +0 -28
  157. package/lib/lifecycle.d.ts.map +0 -1
  158. package/lib/lifecycle.js +0 -73
  159. package/lib/lifecycle.js.map +0 -1
  160. package/lib/mask.d.ts +0 -16
  161. package/lib/mask.d.ts.map +0 -1
  162. package/lib/mask.js +0 -36
  163. package/lib/mask.js.map +0 -1
  164. package/lib/measure.d.ts +0 -4
  165. package/lib/measure.d.ts.map +0 -1
  166. package/lib/measure.js +0 -25
  167. package/lib/measure.js.map +0 -1
  168. package/lib/metrics.d.ts +0 -24
  169. package/lib/metrics.d.ts.map +0 -1
  170. package/lib/metrics.js +0 -81
  171. package/lib/metrics.js.map +0 -1
  172. package/lib/pre-crash-sentinel.d.ts +0 -12
  173. package/lib/pre-crash-sentinel.d.ts.map +0 -1
  174. package/lib/pre-crash-sentinel.js +0 -116
  175. package/lib/pre-crash-sentinel.js.map +0 -1
  176. package/lib/report-security.d.ts +0 -40
  177. package/lib/report-security.d.ts.map +0 -1
  178. package/lib/report-security.js +0 -159
  179. package/lib/report-security.js.map +0 -1
  180. package/lib/runtime-metrics-fps.d.ts +0 -19
  181. package/lib/runtime-metrics-fps.d.ts.map +0 -1
  182. package/lib/runtime-metrics-fps.js +0 -128
  183. package/lib/runtime-metrics-fps.js.map +0 -1
  184. package/lib/runtime-metrics-heap.d.ts +0 -13
  185. package/lib/runtime-metrics-heap.d.ts.map +0 -1
  186. package/lib/runtime-metrics-heap.js +0 -67
  187. package/lib/runtime-metrics-heap.js.map +0 -1
  188. package/lib/runtime-metrics-network.d.ts +0 -23
  189. package/lib/runtime-metrics-network.d.ts.map +0 -1
  190. package/lib/runtime-metrics-network.js +0 -99
  191. package/lib/runtime-metrics-network.js.map +0 -1
  192. package/lib/runtime-metrics.d.ts +0 -43
  193. package/lib/runtime-metrics.d.ts.map +0 -1
  194. package/lib/runtime-metrics.js +0 -115
  195. package/lib/runtime-metrics.js.map +0 -1
  196. package/lib/sample-profiler.d.ts +0 -21
  197. package/lib/sample-profiler.d.ts.map +0 -1
  198. package/lib/sample-profiler.js +0 -152
  199. package/lib/sample-profiler.js.map +0 -1
  200. package/lib/sentinel-context.d.ts +0 -4
  201. package/lib/sentinel-context.d.ts.map +0 -1
  202. package/lib/sentinel-context.js +0 -52
  203. package/lib/sentinel-context.js.map +0 -1
  204. package/lib/session-tracker.d.ts +0 -6
  205. package/lib/session-tracker.d.ts.map +0 -1
  206. package/lib/session-tracker.js +0 -50
  207. package/lib/session-tracker.js.map +0 -1
  208. package/lib/stack.d.ts +0 -3
  209. package/lib/stack.d.ts.map +0 -1
  210. package/lib/stack.js +0 -7
  211. package/lib/stack.js.map +0 -1
  212. package/lib/state-snapshots.d.ts +0 -33
  213. package/lib/state-snapshots.d.ts.map +0 -1
  214. package/lib/state-snapshots.js +0 -109
  215. package/lib/state-snapshots.js.map +0 -1
  216. package/lib/track.d.ts +0 -34
  217. package/lib/track.d.ts.map +0 -1
  218. package/lib/track.js +0 -107
  219. package/lib/track.js.map +0 -1
  220. package/lib/trail.d.ts +0 -12
  221. package/lib/trail.d.ts.map +0 -1
  222. package/lib/trail.js +0 -28
  223. package/lib/trail.js.map +0 -1
  224. package/lib/trust-score.d.ts +0 -20
  225. package/lib/trust-score.d.ts.map +0 -1
  226. package/lib/trust-score.js +0 -151
  227. package/lib/trust-score.js.map +0 -1
  228. package/lib/types.d.ts +0 -2
  229. package/lib/types.d.ts.map +0 -1
  230. package/lib/types.js +0 -4
  231. package/lib/types.js.map +0 -1
  232. package/lib/uuid.d.ts +0 -2
  233. package/lib/uuid.d.ts.map +0 -1
  234. package/lib/uuid.js +0 -3
  235. package/lib/uuid.js.map +0 -1
  236. package/src/__tests__/before-send.test.ts +0 -72
  237. package/src/__tests__/breadcrumbs.test.ts +0 -44
  238. package/src/__tests__/capture-replay.test.ts +0 -150
  239. package/src/__tests__/compat-sentry.test.ts +0 -121
  240. package/src/__tests__/control-channel.test.ts +0 -111
  241. package/src/__tests__/install-id.test.ts +0 -60
  242. package/src/__tests__/long-task-monitor.test.ts +0 -59
  243. package/src/__tests__/measure.test.ts +0 -45
  244. package/src/__tests__/navigation.test.ts +0 -175
  245. package/src/__tests__/push.test.ts +0 -238
  246. package/src/__tests__/report-security.test.ts +0 -106
  247. package/src/__tests__/runtime-metrics-instruments.test.ts +0 -109
  248. package/src/__tests__/runtime-metrics-network.test.ts +0 -78
  249. package/src/__tests__/sample-profiler.test.ts +0 -59
  250. package/src/__tests__/stack.test.ts +0 -45
  251. package/src/__tests__/state-snapshots.test.ts +0 -119
  252. package/src/__tests__/tracing.test.ts +0 -201
  253. package/src/__tests__/track.test.ts +0 -91
  254. package/src/__tests__/uuid.test.ts +0 -41
  255. package/src/breadcrumbs.ts +0 -57
  256. package/src/bundle-info.ts +0 -95
  257. package/src/capture.ts +0 -660
  258. package/src/compat/sentry.ts +0 -490
  259. package/src/control-channel.ts +0 -98
  260. package/src/expo-compat.ts +0 -698
  261. package/src/feedback-widget.tsx +0 -316
  262. package/src/feedback.ts +0 -21
  263. package/src/heartbeat.ts +0 -157
  264. package/src/install-id.ts +0 -146
  265. package/src/lifecycle.ts +0 -76
  266. package/src/mask.ts +0 -41
  267. package/src/measure.ts +0 -28
  268. package/src/metrics.ts +0 -94
  269. package/src/pre-crash-sentinel.ts +0 -140
  270. package/src/report-security.ts +0 -165
  271. package/src/runtime-metrics-fps.ts +0 -137
  272. package/src/runtime-metrics-heap.ts +0 -78
  273. package/src/runtime-metrics-network.ts +0 -103
  274. package/src/runtime-metrics.ts +0 -122
  275. package/src/sample-profiler.ts +0 -169
  276. package/src/sentinel-context.ts +0 -60
  277. package/src/session-tracker.ts +0 -53
  278. package/src/stack.ts +0 -10
  279. package/src/state-snapshots.ts +0 -133
  280. package/src/track.ts +0 -123
  281. package/src/trail.ts +0 -32
  282. package/src/trust-score.ts +0 -176
  283. package/src/types.ts +0 -21
  284. package/src/uuid.ts +0 -2
package/src/rage-tap.tsx CHANGED
@@ -1,22 +1,24 @@
1
- // v0.9.0 #12 — rage-tap / multi-click detection.
1
+ // rage_tap — the first detected warn scenario (design.md §3,
2
+ // category A: 「我按了没反应/反复按」).
2
3
  //
3
- // Wrap your app root (typically next to ErrorBoundary) with
4
- // `<sentori.RageTapCapture>{children}</sentori.RageTapCapture>`.
5
- // We listen to bubble-phase `onTouchEnd` and emit a `ui.multiClick`
6
- // breadcrumb when the same native target receives ≥ 3 taps within
7
- // 800 ms. Pure observation — no event capture, no gesture
8
- // interference; existing Touchables / Pressables / GestureHandler
9
- // continue to fire normally.
4
+ // Wrap the app root (next to ErrorBoundary) with
5
+ // `<RageTapCapture>{children}</RageTapCapture>`. Bubble-phase
6
+ // `onTouchEnd` only — pure observation, no gesture interference.
7
+ //
8
+ // Mini-spec: ≥3 taps on the same native target within 800 ms ⇒ one
9
+ // `warn` event, scenario `rage_tap`, surface = current screen +
10
+ // target id, plus a signal-ring entry. Per-target cooldown resets
11
+ // after firing so a frustrated 10-tap burst is one event, not four.
10
12
 
11
13
  import React, { useCallback, useRef } from 'react';
12
14
  import { View, type GestureResponderEvent, type ViewProps } from 'react-native';
13
15
 
14
- import { addBreadcrumb } from './breadcrumbs';
15
- import {
16
- RAGE_THRESHOLD,
17
- RAGE_WINDOW_MS,
18
- recordTap,
19
- } from './rage-tap-detector';
16
+ import { pushSignal } from '@goliapkg/sentori-core';
17
+
18
+ import { getConfig } from './config';
19
+ import { currentScreen } from './navigation';
20
+ import { RAGE_THRESHOLD, RAGE_WINDOW_MS, recordTap } from './rage-tap-detector';
21
+ import { warnDetected } from './verbs';
20
22
 
21
23
  export function RageTapCapture({
22
24
  children,
@@ -25,18 +27,19 @@ export function RageTapCapture({
25
27
  const recent = useRef<Map<number, number[]>>(new Map());
26
28
 
27
29
  const onTouchEnd = useCallback((e: GestureResponderEvent) => {
28
- const target = e.nativeEvent?.target;
29
- if (typeof target !== 'number') return;
30
- if (recordTap(recent.current, target, Date.now())) {
31
- addBreadcrumb({
32
- type: 'user',
33
- data: {
34
- kind: 'ui.multiClick',
35
- target: String(target),
36
- taps: RAGE_THRESHOLD,
37
- windowMs: RAGE_WINDOW_MS,
38
- },
39
- });
30
+ try {
31
+ const target = e.nativeEvent?.target;
32
+ if (typeof target !== 'number') return;
33
+ pushSignal('tap', { target });
34
+ if (!recordTap(recent.current, target, Date.now())) return;
35
+ if (getConfig()?.detect.rageTap === false) return;
36
+ warnDetected(
37
+ 'rage_tap',
38
+ { screen: currentScreen(), element: String(target) },
39
+ { taps: RAGE_THRESHOLD, windowMs: RAGE_WINDOW_MS },
40
+ );
41
+ } catch {
42
+ // A detector bug must never reach the host's touch pipeline.
40
43
  }
41
44
  }, []);
42
45
 
package/src/replay.ts CHANGED
@@ -15,9 +15,8 @@
15
15
  //
16
16
  // Wire schema: docs/replay-encoding-v2.md.
17
17
 
18
- import { logger, startSpan } from '@goliapkg/sentori-core';
18
+ import { logger } from '@goliapkg/sentori-core';
19
19
 
20
- import { getRegisteredMaskQuery } from './mask';
21
20
  import { describeWireframeNative } from './native';
22
21
 
23
22
  declare const __DEV__: boolean | undefined;
@@ -153,18 +152,11 @@ function captureTick(): void {
153
152
  logger.debug('replay', 'tick: first invocation');
154
153
  _firstTickLogged = true;
155
154
  }
156
- let tickSpan: ReturnType<typeof startSpan> | null = null;
157
- try {
158
- tickSpan = startSpan('sentori.replay.tick', { name: 'tick' });
159
- } catch {
160
- // never fatal
161
- }
162
155
  try {
163
156
  const maskIds = readMaskIds();
164
157
  const snapshotJson = _nativeMod?.captureWireframe?.(maskIds);
165
158
  if (typeof snapshotJson !== 'string' || snapshotJson.length === 0) {
166
159
  handleEmptyTick(snapshotJson);
167
- tickSpan?.finish({ status: 'ok' });
168
160
  return;
169
161
  }
170
162
 
@@ -173,7 +165,6 @@ function captureTick(): void {
173
165
  snapshot = JSON.parse(snapshotJson) as NativeFrame;
174
166
  } catch (e) {
175
167
  logger.warn('replay', 'tick: native JSON parse failed', e);
176
- tickSpan?.finish({ status: 'error' });
177
168
  return;
178
169
  }
179
170
 
@@ -185,10 +176,7 @@ function captureTick(): void {
185
176
  if (typeof __DEV__ !== 'undefined' && __DEV__) {
186
177
  diagnosticForTick(snapshot, snapshotJson.length);
187
178
  }
188
- tickSpan?.finish({ status: 'ok' });
189
179
  } catch (e) {
190
- if (e instanceof Error) tickSpan?.setTag('error.message', e.message);
191
- tickSpan?.finish({ status: 'error' });
192
180
  logger.warn('replay', 'tick threw', e);
193
181
  }
194
182
  }
@@ -326,13 +314,8 @@ function diagnosticForTick(snapshot: NativeFrame, snapshotBytes: number): void {
326
314
  }
327
315
 
328
316
  function readMaskIds(): string[] {
329
- const q = getRegisteredMaskQuery();
330
- if (!q) return [];
331
- try {
332
- return q();
333
- } catch {
334
- return [];
335
- }
317
+ // Masking returns with a v1 privacy pass; nothing masks today.
318
+ return [];
336
319
  }
337
320
 
338
321
  type ReplayNativeModule = {
package/src/scope.ts ADDED
@@ -0,0 +1,50 @@
1
+ // Ambient scope: the current user and the context patch, attached
2
+ // to every outgoing event. Two verbs own this state (user() and
3
+ // context()); everything else reads it.
4
+
5
+ import { hashIdentities, safeFn } from '@goliapkg/sentori-core';
6
+ import type { User } from '@goliapkg/sentori-core';
7
+
8
+ let _user: User | null = null;
9
+ let _userKey: string | undefined;
10
+ let _context: Record<string, unknown> = {};
11
+ let _hashGeneration = 0;
12
+
13
+ export const setUser = safeFn('user', function setUser(u: User | null): void {
14
+ _user = u;
15
+ _userKey = undefined;
16
+ const generation = ++_hashGeneration;
17
+ if (u === null) return;
18
+ // The wire carries only a salted hash — raw identity never leaves
19
+ // the device (breadth × depth needs distinctness, not identity).
20
+ // Hashing is async (WebCrypto); the verb stays synchronous and the
21
+ // key lands a tick later. Events sent in that gap simply carry no
22
+ // userKey, which only under-counts breadth briefly.
23
+ void hashIdentities({ email: u.email, id: u.id })
24
+ .then((hashes) => {
25
+ if (generation === _hashGeneration) {
26
+ _userKey = hashes.id ?? hashes.email;
27
+ }
28
+ })
29
+ .catch(() => {
30
+ // NEVER rule: no key beats a raw identity on the wire.
31
+ });
32
+ });
33
+
34
+ export const patchContext = safeFn('context', function patchContext(
35
+ patch: Record<string, unknown>,
36
+ ): void {
37
+ _context = { ..._context, ...patch };
38
+ });
39
+
40
+ export const currentUserKey = (): string | undefined => _userKey;
41
+
42
+ export const currentContext = (): Record<string, unknown> | undefined =>
43
+ Object.keys(_context).length > 0 ? { ..._context } : undefined;
44
+
45
+ export const __resetForTests = (): void => {
46
+ _user = null;
47
+ _userKey = undefined;
48
+ _context = {};
49
+ _hashGeneration++;
50
+ };