@goliapkg/sentori-react-native 4.0.0 → 5.1.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 (308) hide show
  1. package/MIGRATION.md +131 -0
  2. package/README.md +40 -30
  3. package/android/build.gradle +21 -0
  4. package/android/src/main/java/com/sentori/SentoriCrashHandler.kt +29 -0
  5. package/android/src/main/java/com/sentori/SentoriModule.kt +8 -0
  6. package/android/src/main/java/com/sentori/SentoriScreenshotCapture.kt +36 -4
  7. package/android/src/test/java/com/sentori/SentoriCrashHandlerTest.kt +7 -2
  8. package/android/src/test/resources/robolectric.properties +10 -0
  9. package/ios/SentoriCrashHandler.swift +48 -4
  10. package/ios/SentoriModule.swift +12 -0
  11. package/ios/SentoriScreenshotCapture.swift +34 -3
  12. package/lib/config.d.ts +17 -47
  13. package/lib/config.d.ts.map +1 -1
  14. package/lib/config.js +3 -0
  15. package/lib/config.js.map +1 -1
  16. package/lib/device.d.ts +5 -0
  17. package/lib/device.d.ts.map +1 -0
  18. package/lib/device.js +29 -0
  19. package/lib/device.js.map +1 -0
  20. package/lib/emit-hooks.d.ts +7 -0
  21. package/lib/emit-hooks.d.ts.map +1 -0
  22. package/lib/emit-hooks.js +24 -0
  23. package/lib/emit-hooks.js.map +1 -0
  24. package/lib/error-boundary.d.ts.map +1 -1
  25. package/lib/error-boundary.js +1 -1
  26. package/lib/error-boundary.js.map +1 -1
  27. package/lib/feature-flags.d.ts.map +1 -1
  28. package/lib/handlers/dev-symbolicate.d.ts +1 -1
  29. package/lib/handlers/dev-symbolicate.d.ts.map +1 -1
  30. package/lib/handlers/dev-symbolicate.js +2 -0
  31. package/lib/handlers/dev-symbolicate.js.map +1 -1
  32. package/lib/handlers/global.js +1 -1
  33. package/lib/handlers/global.js.map +1 -1
  34. package/lib/handlers/lifecycle.js +3 -3
  35. package/lib/handlers/lifecycle.js.map +1 -1
  36. package/lib/handlers/network.d.ts +2 -2
  37. package/lib/handlers/network.d.ts.map +1 -1
  38. package/lib/handlers/network.js +69 -187
  39. package/lib/handlers/network.js.map +1 -1
  40. package/lib/handlers/promise.js +1 -1
  41. package/lib/handlers/promise.js.map +1 -1
  42. package/lib/handlers/screenshot.d.ts.map +1 -1
  43. package/lib/handlers/screenshot.js +3 -12
  44. package/lib/handlers/screenshot.js.map +1 -1
  45. package/lib/index.d.ts +32 -109
  46. package/lib/index.d.ts.map +1 -1
  47. package/lib/index.js +54 -103
  48. package/lib/index.js.map +1 -1
  49. package/lib/init.d.ts +3 -150
  50. package/lib/init.d.ts.map +1 -1
  51. package/lib/init.js +100 -261
  52. package/lib/init.js.map +1 -1
  53. package/lib/long-task-monitor.d.ts +1 -7
  54. package/lib/long-task-monitor.d.ts.map +1 -1
  55. package/lib/long-task-monitor.js +37 -58
  56. package/lib/long-task-monitor.js.map +1 -1
  57. package/lib/mask.d.ts +5 -13
  58. package/lib/mask.d.ts.map +1 -1
  59. package/lib/mask.js +29 -30
  60. package/lib/mask.js.map +1 -1
  61. package/lib/mobile-vitals.d.ts +3 -31
  62. package/lib/mobile-vitals.d.ts.map +1 -1
  63. package/lib/mobile-vitals.js +22 -61
  64. package/lib/mobile-vitals.js.map +1 -1
  65. package/lib/native-pending.d.ts +3 -0
  66. package/lib/native-pending.d.ts.map +1 -0
  67. package/lib/native-pending.js +64 -0
  68. package/lib/native-pending.js.map +1 -0
  69. package/lib/native.d.ts +4 -11
  70. package/lib/native.d.ts.map +1 -1
  71. package/lib/native.js +23 -0
  72. package/lib/native.js.map +1 -1
  73. package/lib/navigation.d.ts +3 -17
  74. package/lib/navigation.d.ts.map +1 -1
  75. package/lib/navigation.js +32 -133
  76. package/lib/navigation.js.map +1 -1
  77. package/lib/netinfo.d.ts +1 -1
  78. package/lib/netinfo.d.ts.map +1 -1
  79. package/lib/netinfo.js +2 -2
  80. package/lib/netinfo.js.map +1 -1
  81. package/lib/push.d.ts.map +1 -1
  82. package/lib/push.js +2 -4
  83. package/lib/push.js.map +1 -1
  84. package/lib/rage-tap.d.ts.map +1 -1
  85. package/lib/rage-tap.js +56 -23
  86. package/lib/rage-tap.js.map +1 -1
  87. package/lib/replay-screens.d.ts +15 -0
  88. package/lib/replay-screens.d.ts.map +1 -0
  89. package/lib/replay-screens.js +87 -0
  90. package/lib/replay-screens.js.map +1 -0
  91. package/lib/replay.d.ts.map +1 -1
  92. package/lib/replay.js +3 -24
  93. package/lib/replay.js.map +1 -1
  94. package/lib/responsiveness-detector.d.ts +18 -0
  95. package/lib/responsiveness-detector.d.ts.map +1 -0
  96. package/lib/responsiveness-detector.js +55 -0
  97. package/lib/responsiveness-detector.js.map +1 -0
  98. package/lib/scope.d.ts +7 -0
  99. package/lib/scope.d.ts.map +1 -0
  100. package/lib/scope.js +41 -0
  101. package/lib/scope.js.map +1 -0
  102. package/lib/transport.d.ts +19 -92
  103. package/lib/transport.d.ts.map +1 -1
  104. package/lib/transport.js +75 -288
  105. package/lib/transport.js.map +1 -1
  106. package/lib/verbs.d.ts +16 -0
  107. package/lib/verbs.d.ts.map +1 -0
  108. package/lib/verbs.js +153 -0
  109. package/lib/verbs.js.map +1 -0
  110. package/package.json +4 -3
  111. package/src/__tests__/iron-rule.test.ts +128 -0
  112. package/src/__tests__/replay-screens.test.ts +63 -0
  113. package/src/__tests__/responsiveness-detector.test.ts +74 -0
  114. package/src/__tests__/screenshot.test.ts +0 -2
  115. package/src/__tests__/transport.test.ts +66 -213
  116. package/src/__tests__/verbs.test.ts +91 -0
  117. package/src/config.ts +20 -47
  118. package/src/device.ts +36 -0
  119. package/src/emit-hooks.ts +30 -0
  120. package/src/error-boundary.tsx +1 -1
  121. package/src/handlers/dev-symbolicate.ts +2 -1
  122. package/src/handlers/global.ts +1 -1
  123. package/src/handlers/lifecycle.ts +3 -3
  124. package/src/handlers/network.ts +95 -211
  125. package/src/handlers/promise.ts +1 -1
  126. package/src/handlers/screenshot.ts +3 -11
  127. package/src/index.ts +84 -215
  128. package/src/init.ts +115 -449
  129. package/src/long-task-monitor.ts +42 -64
  130. package/src/mask.ts +29 -31
  131. package/src/mobile-vitals.ts +22 -82
  132. package/src/native-pending.ts +92 -0
  133. package/src/native.ts +33 -0
  134. package/src/navigation.ts +34 -142
  135. package/src/netinfo.ts +3 -3
  136. package/src/push.ts +2 -5
  137. package/src/rage-tap.tsx +72 -25
  138. package/src/replay-screens.ts +95 -0
  139. package/src/replay.ts +3 -20
  140. package/src/responsiveness-detector.ts +66 -0
  141. package/src/scope.ts +50 -0
  142. package/src/transport.ts +84 -371
  143. package/src/verbs.ts +198 -0
  144. package/lib/breadcrumbs.d.ts +0 -18
  145. package/lib/breadcrumbs.d.ts.map +0 -1
  146. package/lib/breadcrumbs.js +0 -42
  147. package/lib/breadcrumbs.js.map +0 -1
  148. package/lib/bundle-info.d.ts +0 -12
  149. package/lib/bundle-info.d.ts.map +0 -1
  150. package/lib/bundle-info.js +0 -73
  151. package/lib/bundle-info.js.map +0 -1
  152. package/lib/capture.d.ts +0 -140
  153. package/lib/capture.d.ts.map +0 -1
  154. package/lib/capture.js +0 -511
  155. package/lib/capture.js.map +0 -1
  156. package/lib/compat/sentry.d.ts +0 -126
  157. package/lib/compat/sentry.d.ts.map +0 -1
  158. package/lib/compat/sentry.js +0 -332
  159. package/lib/compat/sentry.js.map +0 -1
  160. package/lib/control-channel.d.ts +0 -6
  161. package/lib/control-channel.d.ts.map +0 -1
  162. package/lib/control-channel.js +0 -96
  163. package/lib/control-channel.js.map +0 -1
  164. package/lib/expo-compat.d.ts +0 -270
  165. package/lib/expo-compat.d.ts.map +0 -1
  166. package/lib/expo-compat.js +0 -500
  167. package/lib/expo-compat.js.map +0 -1
  168. package/lib/feedback-widget.d.ts +0 -35
  169. package/lib/feedback-widget.d.ts.map +0 -1
  170. package/lib/feedback-widget.js +0 -193
  171. package/lib/feedback-widget.js.map +0 -1
  172. package/lib/feedback.d.ts +0 -2
  173. package/lib/feedback.d.ts.map +0 -1
  174. package/lib/feedback.js +0 -17
  175. package/lib/feedback.js.map +0 -1
  176. package/lib/heartbeat.d.ts +0 -9
  177. package/lib/heartbeat.d.ts.map +0 -1
  178. package/lib/heartbeat.js +0 -138
  179. package/lib/heartbeat.js.map +0 -1
  180. package/lib/index.js.bak +0 -64
  181. package/lib/install-id.d.ts +0 -17
  182. package/lib/install-id.d.ts.map +0 -1
  183. package/lib/install-id.js +0 -125
  184. package/lib/install-id.js.map +0 -1
  185. package/lib/lifecycle.d.ts +0 -28
  186. package/lib/lifecycle.d.ts.map +0 -1
  187. package/lib/lifecycle.js +0 -73
  188. package/lib/lifecycle.js.map +0 -1
  189. package/lib/measure.d.ts +0 -4
  190. package/lib/measure.d.ts.map +0 -1
  191. package/lib/measure.js +0 -25
  192. package/lib/measure.js.map +0 -1
  193. package/lib/metrics.d.ts +0 -24
  194. package/lib/metrics.d.ts.map +0 -1
  195. package/lib/metrics.js +0 -81
  196. package/lib/metrics.js.map +0 -1
  197. package/lib/pre-crash-sentinel.d.ts +0 -12
  198. package/lib/pre-crash-sentinel.d.ts.map +0 -1
  199. package/lib/pre-crash-sentinel.js +0 -116
  200. package/lib/pre-crash-sentinel.js.map +0 -1
  201. package/lib/report-security.d.ts +0 -40
  202. package/lib/report-security.d.ts.map +0 -1
  203. package/lib/report-security.js +0 -159
  204. package/lib/report-security.js.map +0 -1
  205. package/lib/runtime-metrics-fps.d.ts +0 -19
  206. package/lib/runtime-metrics-fps.d.ts.map +0 -1
  207. package/lib/runtime-metrics-fps.js +0 -128
  208. package/lib/runtime-metrics-fps.js.map +0 -1
  209. package/lib/runtime-metrics-heap.d.ts +0 -13
  210. package/lib/runtime-metrics-heap.d.ts.map +0 -1
  211. package/lib/runtime-metrics-heap.js +0 -67
  212. package/lib/runtime-metrics-heap.js.map +0 -1
  213. package/lib/runtime-metrics-network.d.ts +0 -23
  214. package/lib/runtime-metrics-network.d.ts.map +0 -1
  215. package/lib/runtime-metrics-network.js +0 -99
  216. package/lib/runtime-metrics-network.js.map +0 -1
  217. package/lib/runtime-metrics.d.ts +0 -43
  218. package/lib/runtime-metrics.d.ts.map +0 -1
  219. package/lib/runtime-metrics.js +0 -115
  220. package/lib/runtime-metrics.js.map +0 -1
  221. package/lib/sample-profiler.d.ts +0 -21
  222. package/lib/sample-profiler.d.ts.map +0 -1
  223. package/lib/sample-profiler.js +0 -152
  224. package/lib/sample-profiler.js.map +0 -1
  225. package/lib/sentinel-context.d.ts +0 -4
  226. package/lib/sentinel-context.d.ts.map +0 -1
  227. package/lib/sentinel-context.js +0 -52
  228. package/lib/sentinel-context.js.map +0 -1
  229. package/lib/session-tracker.d.ts +0 -6
  230. package/lib/session-tracker.d.ts.map +0 -1
  231. package/lib/session-tracker.js +0 -50
  232. package/lib/session-tracker.js.map +0 -1
  233. package/lib/stack.d.ts +0 -3
  234. package/lib/stack.d.ts.map +0 -1
  235. package/lib/stack.js +0 -7
  236. package/lib/stack.js.map +0 -1
  237. package/lib/state-snapshots.d.ts +0 -33
  238. package/lib/state-snapshots.d.ts.map +0 -1
  239. package/lib/state-snapshots.js +0 -109
  240. package/lib/state-snapshots.js.map +0 -1
  241. package/lib/track.d.ts +0 -34
  242. package/lib/track.d.ts.map +0 -1
  243. package/lib/track.js +0 -107
  244. package/lib/track.js.map +0 -1
  245. package/lib/trail.d.ts +0 -12
  246. package/lib/trail.d.ts.map +0 -1
  247. package/lib/trail.js +0 -28
  248. package/lib/trail.js.map +0 -1
  249. package/lib/trust-score.d.ts +0 -20
  250. package/lib/trust-score.d.ts.map +0 -1
  251. package/lib/trust-score.js +0 -151
  252. package/lib/trust-score.js.map +0 -1
  253. package/lib/types.d.ts +0 -2
  254. package/lib/types.d.ts.map +0 -1
  255. package/lib/types.js +0 -4
  256. package/lib/types.js.map +0 -1
  257. package/lib/uuid.d.ts +0 -2
  258. package/lib/uuid.d.ts.map +0 -1
  259. package/lib/uuid.js +0 -3
  260. package/lib/uuid.js.map +0 -1
  261. package/src/__tests__/before-send.test.ts +0 -72
  262. package/src/__tests__/breadcrumbs.test.ts +0 -44
  263. package/src/__tests__/capture-replay.test.ts +0 -150
  264. package/src/__tests__/compat-sentry.test.ts +0 -121
  265. package/src/__tests__/control-channel.test.ts +0 -111
  266. package/src/__tests__/install-id.test.ts +0 -60
  267. package/src/__tests__/long-task-monitor.test.ts +0 -59
  268. package/src/__tests__/measure.test.ts +0 -45
  269. package/src/__tests__/navigation.test.ts +0 -175
  270. package/src/__tests__/push.test.ts +0 -238
  271. package/src/__tests__/report-security.test.ts +0 -106
  272. package/src/__tests__/runtime-metrics-instruments.test.ts +0 -109
  273. package/src/__tests__/runtime-metrics-network.test.ts +0 -78
  274. package/src/__tests__/sample-profiler.test.ts +0 -59
  275. package/src/__tests__/stack.test.ts +0 -45
  276. package/src/__tests__/state-snapshots.test.ts +0 -119
  277. package/src/__tests__/tracing.test.ts +0 -201
  278. package/src/__tests__/track.test.ts +0 -91
  279. package/src/__tests__/uuid.test.ts +0 -41
  280. package/src/breadcrumbs.ts +0 -57
  281. package/src/bundle-info.ts +0 -95
  282. package/src/capture.ts +0 -660
  283. package/src/compat/sentry.ts +0 -490
  284. package/src/control-channel.ts +0 -98
  285. package/src/expo-compat.ts +0 -698
  286. package/src/feedback-widget.tsx +0 -316
  287. package/src/feedback.ts +0 -21
  288. package/src/heartbeat.ts +0 -157
  289. package/src/install-id.ts +0 -146
  290. package/src/lifecycle.ts +0 -76
  291. package/src/measure.ts +0 -28
  292. package/src/metrics.ts +0 -94
  293. package/src/pre-crash-sentinel.ts +0 -140
  294. package/src/report-security.ts +0 -165
  295. package/src/runtime-metrics-fps.ts +0 -137
  296. package/src/runtime-metrics-heap.ts +0 -78
  297. package/src/runtime-metrics-network.ts +0 -103
  298. package/src/runtime-metrics.ts +0 -122
  299. package/src/sample-profiler.ts +0 -169
  300. package/src/sentinel-context.ts +0 -60
  301. package/src/session-tracker.ts +0 -53
  302. package/src/stack.ts +0 -10
  303. package/src/state-snapshots.ts +0 -133
  304. package/src/track.ts +0 -123
  305. package/src/trail.ts +0 -32
  306. package/src/trust-score.ts +0 -176
  307. package/src/types.ts +0 -21
  308. package/src/uuid.ts +0 -2
package/lib/trail.js DELETED
@@ -1,28 +0,0 @@
1
- // Phase 46 — singleton TrailBuffer for the RN SDK.
2
- //
3
- // Kept in its own module so callers (including navigation.ts, which
4
- // is intentionally lightweight) can record steps without pulling in
5
- // capture.ts → handlers/screenshot.ts → react-native. The buffer is
6
- // drained inside capture.ts when an event captures and
7
- // `sessionTrailEnabled` is on.
8
- import { TrailBuffer } from '@goliapkg/sentori-core';
9
- const _trail = new TrailBuffer(30);
10
- /**
11
- * Phase 46 — record a step into the session-trail buffer. The buffer
12
- * is a fixed-size FIFO (default 30 steps); pushing past capacity
13
- * drops the oldest entry. Steps are only uploaded if
14
- * `init({ capture: { sessionTrail: true } })` is on AND a
15
- * `captureException` follows.
16
- */
17
- export const captureStep = (label, opts) => {
18
- _trail.push({
19
- ts: Date.now(),
20
- label,
21
- ...(opts ?? {}),
22
- });
23
- };
24
- export const getTrailBuffer = () => _trail;
25
- export const __resetTrailForTests = () => {
26
- _trail.clear();
27
- };
28
- //# sourceMappingURL=trail.js.map
package/lib/trail.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"trail.js","sourceRoot":"","sources":["../src/trail.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,oEAAoE;AACpE,uDAAuD;AACvD,+BAA+B;AAE/B,OAAO,EAAE,WAAW,EAAkB,MAAM,wBAAwB,CAAC;AAErE,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,IAAyB,EAAQ,EAAE;IAC5E,MAAM,CAAC,IAAI,CAAC;QACV,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;QACd,KAAK;QACL,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;KAChB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAgB,EAAE,CAAC,MAAM,CAAC;AAExD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAS,EAAE;IAC7C,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC,CAAC"}
@@ -1,20 +0,0 @@
1
- export type TrustSignal = {
2
- count: number;
3
- kind: string;
4
- weight: number;
5
- };
6
- export type TrustScore = {
7
- computedAt: string;
8
- installId: string;
9
- score: number;
10
- signals: TrustSignal[];
11
- };
12
- /**
13
- * Resolve the device's trust score. Always resolves — never throws,
14
- * never rejects. The two-layer cache means the first call after cold
15
- * start usually serves a < 1 ms result while a background refresh
16
- * keeps the value current.
17
- */
18
- export declare function queryTrustScore(): Promise<TrustScore>;
19
- export declare function __resetTrustScoreForTests(): void;
20
- //# sourceMappingURL=trust-score.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trust-score.d.ts","sourceRoot":"","sources":["../src/trust-score.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAqFF;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,CAuC3D;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD"}
@@ -1,151 +0,0 @@
1
- // v1.1 chunk S3 — `sentori.queryTrustScore()` for the host app.
2
- //
3
- // Returns the device's current trust score (0–100, higher = healthier)
4
- // plus the per-kind signal mix that produced it. The host app uses
5
- // this to decide whether to step up authentication, decline a
6
- // purchase, or simply log a soft warning.
7
- //
8
- // Caching:
9
- // L1 — process-memory, ~30 s. Same process should not re-fetch on
10
- // every screen render; the score moves on a "minutes" cadence.
11
- // L2 — install-id-derived AsyncStorage entry, ~5 minutes. Lets the
12
- // host paint a cached score on cold start without waiting for
13
- // the network. Stale entries are still served; the SDK
14
- // re-fetches in the background.
15
- //
16
- // Fail-soft posture: if the network's down or the SDK isn't
17
- // initialised, returns the cached value (if any), else the safe
18
- // default (score = 100). The host should never see a thrown error
19
- // from this call — the score system is supposed to be invisible.
20
- import { isAnyNativeModuleLinked } from './native-loader';
21
- import { getConfig, isInitialized } from './config';
22
- import { getInstallId } from './install-id';
23
- const SDK_VERSION = '0.0.0';
24
- const STORAGE_KEY = '@sentori/trust-score';
25
- const L1_TTL_MS = 30_000;
26
- const L2_TTL_MS = 5 * 60_000;
27
- let _l1 = null;
28
- let _inflight = null;
29
- function loadAsyncStorage() {
30
- if (!isAnyNativeModuleLinked(['RNCAsyncStorage', 'AsyncStorageModule']))
31
- return null;
32
- try {
33
- // eslint-disable-next-line @typescript-eslint/no-require-imports
34
- const mod = require('@react-native-async-storage/async-storage');
35
- return mod.default ?? mod;
36
- }
37
- catch {
38
- return null;
39
- }
40
- }
41
- function safeDefault(installId) {
42
- return {
43
- computedAt: new Date().toISOString(),
44
- installId,
45
- score: 100,
46
- signals: [],
47
- };
48
- }
49
- async function readL2() {
50
- const storage = loadAsyncStorage();
51
- if (!storage)
52
- return null;
53
- try {
54
- const raw = await storage.getItem(STORAGE_KEY);
55
- if (!raw)
56
- return null;
57
- const parsed = JSON.parse(raw);
58
- if (typeof parsed?.fetchedAt !== 'number' ||
59
- typeof parsed?.score?.score !== 'number') {
60
- return null;
61
- }
62
- return parsed;
63
- }
64
- catch {
65
- return null;
66
- }
67
- }
68
- async function writeL2(entry) {
69
- const storage = loadAsyncStorage();
70
- if (!storage)
71
- return;
72
- try {
73
- await storage.setItem(STORAGE_KEY, JSON.stringify(entry));
74
- }
75
- catch {
76
- // best-effort
77
- }
78
- }
79
- async function fetchFresh(installId) {
80
- const config = getConfig();
81
- if (!config)
82
- return safeDefault(installId);
83
- try {
84
- const resp = await fetch(`${config.ingestUrl}/v1/security/score?installId=${encodeURIComponent(installId)}`, {
85
- headers: {
86
- Authorization: `Bearer ${config.token}`,
87
- 'Sentori-Sdk': `react-native/${SDK_VERSION}`,
88
- },
89
- method: 'GET',
90
- });
91
- if (!resp.ok)
92
- return safeDefault(installId);
93
- const parsed = (await resp.json());
94
- return parsed;
95
- }
96
- catch {
97
- return safeDefault(installId);
98
- }
99
- }
100
- /**
101
- * Resolve the device's trust score. Always resolves — never throws,
102
- * never rejects. The two-layer cache means the first call after cold
103
- * start usually serves a < 1 ms result while a background refresh
104
- * keeps the value current.
105
- */
106
- export async function queryTrustScore() {
107
- if (!isInitialized()) {
108
- const id = await getInstallId();
109
- return safeDefault(id);
110
- }
111
- // L1 hit
112
- const now = Date.now();
113
- if (_l1 && now - _l1.fetchedAt < L1_TTL_MS) {
114
- return _l1.score;
115
- }
116
- // Coalesce concurrent calls onto the same inflight fetch.
117
- if (_inflight)
118
- return _inflight;
119
- _inflight = (async () => {
120
- try {
121
- const installId = await getInstallId();
122
- // L2 hit — serve immediately, kick off background refresh
123
- const l2 = await readL2();
124
- if (l2 && now - l2.fetchedAt < L2_TTL_MS && l2.score.installId === installId) {
125
- _l1 = l2;
126
- // background refresh (don't block caller)
127
- void (async () => {
128
- const fresh = await fetchFresh(installId);
129
- const entry = { fetchedAt: Date.now(), score: fresh };
130
- _l1 = entry;
131
- await writeL2(entry);
132
- })();
133
- return l2.score;
134
- }
135
- const fresh = await fetchFresh(installId);
136
- const entry = { fetchedAt: Date.now(), score: fresh };
137
- _l1 = entry;
138
- await writeL2(entry);
139
- return fresh;
140
- }
141
- finally {
142
- _inflight = null;
143
- }
144
- })();
145
- return _inflight;
146
- }
147
- export function __resetTrustScoreForTests() {
148
- _l1 = null;
149
- _inflight = null;
150
- }
151
- //# sourceMappingURL=trust-score.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trust-score.js","sourceRoot":"","sources":["../src/trust-score.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export type { App, AttachmentKind, AttachmentMeta, AttachmentSource, Breadcrumb, BreadcrumbType, CaptureExtras, Device, DeviceOS, Event, EventKind, Frame, Platform, SentoriError, Tags, User, } from '@goliapkg/sentori-core';
2
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,GAAG,EACH,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,aAAa,EACb,MAAM,EACN,QAAQ,EACR,KAAK,EACL,SAAS,EACT,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,IAAI,GACL,MAAM,wBAAwB,CAAA"}
package/lib/types.js DELETED
@@ -1,4 +0,0 @@
1
- // Phase 21: wire-format types moved to @goliapkg/sentori-core. Re-
2
- // exported here so existing relative imports keep working.
3
- export {};
4
- //# sourceMappingURL=types.js.map
package/lib/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,2DAA2D"}
package/lib/uuid.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { uuidV7 } from '@goliapkg/sentori-core';
2
- //# sourceMappingURL=uuid.d.ts.map
package/lib/uuid.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA"}
package/lib/uuid.js DELETED
@@ -1,3 +0,0 @@
1
- // Phase 21: moved to @goliapkg/sentori-core.
2
- export { uuidV7 } from '@goliapkg/sentori-core';
3
- //# sourceMappingURL=uuid.js.map
package/lib/uuid.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA"}
@@ -1,72 +0,0 @@
1
- /**
2
- * v2.3 — beforeSend hook unit coverage for the RN SDK.
3
- *
4
- * We exercise the dispatcher directly via the
5
- * `__applyBeforeSendForTests` test hook rather than running the full
6
- * captureException pipeline. The behaviour-level coverage of
7
- * captureException's enqueue path lives in the JS SDK's `sdk.test.ts`
8
- * (which mocks fetch); the dispatcher itself is the only RN-specific
9
- * piece (RN uses the same NEVER-rule policy as JS, but the
10
- * one-shot warn flag is per-SDK so we verify it in both).
11
- */
12
- import { describe, expect, test } from 'bun:test';
13
-
14
- import { __applyBeforeSendForTests as applyBeforeSend } from '../capture';
15
- import type { Event } from '../types';
16
-
17
- function freshEvent(message: string): Event {
18
- return {
19
- id: '019eaa00-0000-7000-8000-000000000001',
20
- timestamp: '2026-06-03T07:00:00.000Z',
21
- kind: 'message',
22
- platform: 'javascript',
23
- release: 'app@1.0.0+1',
24
- environment: 'test',
25
- device: { os: 'ios' },
26
- app: { version: '1.0.0', build: '1' },
27
- user: null,
28
- tags: {},
29
- breadcrumbs: [],
30
- message,
31
- } as Event;
32
- }
33
-
34
- describe('applyBeforeSend (RN, v2.3)', () => {
35
- test('no hook → returns event unchanged', () => {
36
- const ev = freshEvent('passthrough');
37
- expect(applyBeforeSend(ev, undefined)).toBe(ev);
38
- });
39
-
40
- test('hook mutates: returned event is what the caller sees', () => {
41
- const ev = freshEvent('please scrub');
42
- const out = applyBeforeSend(ev, (e) => ({
43
- ...e,
44
- tags: { ...e.tags, scrubbed: '1' },
45
- }));
46
- expect(out).not.toBeNull();
47
- expect(out!.tags?.scrubbed).toBe('1');
48
- });
49
-
50
- test('hook returns null → dispatcher returns null (caller drops)', () => {
51
- const ev = freshEvent('drop me');
52
- expect(applyBeforeSend(ev, () => null)).toBeNull();
53
- });
54
-
55
- test('hook throws → dispatcher returns the original event (NEVER rule)', () => {
56
- const ev = freshEvent('survives bad hook');
57
- const out = applyBeforeSend(ev, () => {
58
- throw new Error('hook boom');
59
- });
60
- expect(out).toBe(ev);
61
- });
62
-
63
- test('hook returns non-event garbage → dispatcher returns the original event', () => {
64
- const ev = freshEvent('survives bad return');
65
- const out = applyBeforeSend(
66
- ev,
67
- // @ts-expect-error — host returns garbage; v2.3 contract is "fall back unmodified"
68
- () => 42,
69
- );
70
- expect(out).toBe(ev);
71
- });
72
- });
@@ -1,44 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'bun:test';
2
-
3
- import {
4
- addBreadcrumb,
5
- getBreadcrumbs,
6
- __resetForTests,
7
- } from '../breadcrumbs';
8
-
9
- describe('breadcrumbs', () => {
10
- beforeEach(() => {
11
- __resetForTests();
12
- });
13
-
14
- it('adds and retrieves a breadcrumb', () => {
15
- addBreadcrumb({ type: 'log', data: { level: 'info', message: 'hi' } });
16
- const crumbs = getBreadcrumbs();
17
- expect(crumbs).toHaveLength(1);
18
- expect(crumbs[0]?.type).toBe('log');
19
- expect(crumbs[0]?.data.message).toBe('hi');
20
- });
21
-
22
- it('auto-generates ISO 8601 timestamp when not provided', () => {
23
- addBreadcrumb({ type: 'nav', data: { from: 'a', to: 'b' } });
24
- const crumbs = getBreadcrumbs();
25
- expect(crumbs[0]?.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
26
- });
27
-
28
- it('caps at 100 entries (oldest discarded)', () => {
29
- for (let i = 0; i < 150; i++) {
30
- addBreadcrumb({ type: 'custom', data: { i } });
31
- }
32
- const crumbs = getBreadcrumbs();
33
- expect(crumbs).toHaveLength(100);
34
- expect(crumbs[0]?.data.i).toBe(50);
35
- expect(crumbs[99]?.data.i).toBe(149);
36
- });
37
-
38
- it('returns a fresh copy on each getBreadcrumbs call', () => {
39
- addBreadcrumb({ type: 'log', data: {} });
40
- const a = getBreadcrumbs();
41
- const b = getBreadcrumbs();
42
- expect(a).not.toBe(b);
43
- });
44
- });
@@ -1,150 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
2
-
3
- import { __captureAndAttachReplayForTests } from '../capture';
4
- import { setConfig, __resetForTests as resetConfig } from '../config';
5
- import type { Event } from '../types';
6
-
7
- // Insight 2026-05-18 rc.3 verify: walker is healthy, ticks land
8
- // deep wireframe JSON with TextView text, but the `replay` kind
9
- // never reaches `event.attachments`. Root cause was the inline
10
- // `btoa(ndjson)` upload path — spec-compliant Hermes / Bun btoa
11
- // throws `InvalidCharacterError` on any code point > 0xFF, and the
12
- // surrounding catch swallowed the throw silently. rc.4 routes
13
- // through `base64Utf8`, fixing both Latin-1 and UTF-8 inputs.
14
- //
15
- // These tests run the actual captureAndAttachReplay function the
16
- // captureException pipeline runs. fetch is mocked at the
17
- // transport.ts boundary so the upload landing isn't tested here
18
- // (covered separately in screenshot.test.ts); what we care about
19
- // is "does event.attachments grow when the input contains
20
- // non-Latin-1 text?".
21
-
22
- const origFetch = globalThis.fetch;
23
-
24
- beforeEach(() => {
25
- setConfig({
26
- enabled: true,
27
- environment: 'test',
28
- errorSampleRate: null,
29
- ingestUrl: 'http://localhost:18080',
30
- release: 'app@1.0.0+1',
31
- screenshotsEnabled: true,
32
- sessionTrailEnabled: true,
33
- token: 'st_pk_test',
34
- traceSampleRate: null,
35
- });
36
- });
37
-
38
- afterEach(() => {
39
- globalThis.fetch = origFetch;
40
- resetConfig();
41
- });
42
-
43
- function makeEvent(): Event {
44
- return {
45
- id: '019eaa00-0000-7000-8000-000000000001',
46
- timestamp: '2026-05-18T05:15:24.000Z',
47
- kind: 'error',
48
- platform: 'javascript',
49
- release: 'app@1.0.0+1',
50
- environment: 'test',
51
- device: { os: 'android', osVersion: '36' },
52
- app: {
53
- version: '1.0.0',
54
- build: '1',
55
- framework: { name: 'react-native', version: '0.80.0' },
56
- },
57
- user: null,
58
- tags: undefined,
59
- breadcrumbs: [],
60
- error: { type: 'Error', message: 'boom', stack: [], cause: null },
61
- fingerprint: undefined,
62
- };
63
- }
64
-
65
- function mockUploadSuccess(): { calls: { url: string; body: unknown }[] } {
66
- const calls: { url: string; body: unknown }[] = [];
67
- globalThis.fetch = mock(async (url: Request | string | URL, init?: RequestInit) => {
68
- let body: unknown = undefined;
69
- try {
70
- body = init?.body ? JSON.parse(String(init.body)) : undefined;
71
- } catch {
72
- body = init?.body;
73
- }
74
- calls.push({ url: String(url), body });
75
- return new Response(
76
- JSON.stringify({
77
- kind: 'replay',
78
- mediaType: 'application/x-ndjson',
79
- refId: '019e3000-7000-7000-8000-00000000aaaa',
80
- sizeBytes: 200,
81
- }),
82
- { headers: { 'content-type': 'application/json' }, status: 201 },
83
- );
84
- }) as typeof fetch;
85
- return { calls };
86
- }
87
-
88
- describe('captureAndAttachReplay — Insight rc.3 regression', () => {
89
- test('Latin-1 ndjson attaches replay kind (control)', async () => {
90
- const { calls } = mockUploadSuccess();
91
- const event = makeEvent();
92
- const ndjson =
93
- '{"ts":1700000000,"width":390,"height":844,"nodes":[' +
94
- '{"kind":"text","x":10,"y":20,"w":100,"h":20,"text":"Settings"}]}';
95
- await __captureAndAttachReplayForTests(event, ndjson);
96
- expect(calls.length).toBe(1);
97
- expect(event.attachments?.length).toBe(1);
98
- expect(event.attachments?.[0]?.kind).toBe('replay');
99
- });
100
-
101
- test('UTF-8 ndjson attaches replay kind (the rc.3 Android crash repro)', async () => {
102
- // This is the bug: pre-rc.4 `btoa(ndjson)` threw on the
103
- // Japanese characters below, the catch swallowed it, the
104
- // attachment silently never landed. Post-rc.4 the helper
105
- // handles UTF-8 and the attachment lands normally.
106
- const { calls } = mockUploadSuccess();
107
- const event = makeEvent();
108
- const ndjson =
109
- '{"ts":1700000000,"width":390,"height":844,"nodes":[' +
110
- '{"kind":"text","x":10,"y":20,"w":100,"h":20,"text":"設定"},' +
111
- '{"kind":"text","x":10,"y":50,"w":100,"h":20,"text":"ログアウト"}]}';
112
- await __captureAndAttachReplayForTests(event, ndjson);
113
- expect(calls.length).toBe(1);
114
- expect(event.attachments?.length).toBe(1);
115
- expect(event.attachments?.[0]?.kind).toBe('replay');
116
- });
117
-
118
- test('mixed em-dash / smart-quote / emoji attaches replay kind', async () => {
119
- const { calls } = mockUploadSuccess();
120
- const event = makeEvent();
121
- const ndjson =
122
- '{"ts":1,"width":390,"height":844,"nodes":[' +
123
- '{"kind":"text","x":0,"y":0,"w":50,"h":20,"text":"hello — world"},' +
124
- '{"kind":"text","x":0,"y":30,"w":50,"h":20,"text":"\\"quoted\\""},' +
125
- '{"kind":"text","x":0,"y":60,"w":50,"h":20,"text":"🎉"}]}';
126
- await __captureAndAttachReplayForTests(event, ndjson);
127
- expect(calls.length).toBe(1);
128
- expect(event.attachments?.length).toBe(1);
129
- expect(event.attachments?.[0]?.kind).toBe('replay');
130
- });
131
-
132
- test('upload returns null → no attachment, no throw', async () => {
133
- globalThis.fetch = (async () =>
134
- new Response('{"error":"tooLarge"}', { status: 413 })) as typeof fetch;
135
- const event = makeEvent();
136
- const ndjson = '{"ts":1,"nodes":[]}';
137
- await __captureAndAttachReplayForTests(event, ndjson);
138
- expect(event.attachments).toBeUndefined();
139
- });
140
-
141
- test('fetch throws (offline) → no attachment, no throw out of the function', async () => {
142
- globalThis.fetch = (async () => {
143
- throw new TypeError('Network request failed');
144
- }) as typeof fetch;
145
- const event = makeEvent();
146
- const ndjson = '{"ts":1,"nodes":[]}';
147
- await __captureAndAttachReplayForTests(event, ndjson);
148
- expect(event.attachments).toBeUndefined();
149
- });
150
- });
@@ -1,121 +0,0 @@
1
- /**
2
- * v2.3 W6.3 — Sentry-compat translation layer coverage.
3
- *
4
- * We exercise the pure-function pieces directly via the test hooks
5
- * exported from the compat module (parseDsn, mapCategoryToType,
6
- * mapLevel). The stateful pieces — init / captureException /
7
- * setUser dispatching to the native init + scope — are covered by
8
- * the upstream Sentori-native tests (sdk.test, before-send.test);
9
- * the compat layer only re-shapes the call arguments before
10
- * delegating, so testing the re-shape is enough.
11
- */
12
- import { describe, expect, test } from 'bun:test';
13
-
14
- import {
15
- __mapCategoryToTypeForTests,
16
- __mapLevelForTests,
17
- __parseDsnForTests,
18
- Severity,
19
- } from '../compat/sentry';
20
-
21
- describe('parseDsn', () => {
22
- test('extracts token + ingestUrl from a Sentori DSN', () => {
23
- const r = __parseDsnForTests(
24
- 'https://st_pk_testabcdef@ingest.sentori.golia.jp/1',
25
- );
26
- expect(r.token).toBe('st_pk_testabcdef');
27
- expect(r.ingestUrl).toBe('https://ingest.sentori.golia.jp');
28
- });
29
-
30
- test('honours custom port + host', () => {
31
- const r = __parseDsnForTests('https://st_pk_x@self-hosted.example.com:8443/42');
32
- expect(r.token).toBe('st_pk_x');
33
- expect(r.ingestUrl).toBe('https://self-hosted.example.com:8443');
34
- });
35
-
36
- test('rejects non-Sentori token prefix with a clear pointer', () => {
37
- expect(() =>
38
- __parseDsnForTests('https://abcd1234@sentry.io/12345'),
39
- ).toThrow(/st_pk_/);
40
- });
41
-
42
- test('rejects DSN without user-info (no token)', () => {
43
- expect(() => __parseDsnForTests('https://sentry.io/12345')).toThrow();
44
- });
45
-
46
- test('rejects malformed URL', () => {
47
- expect(() => __parseDsnForTests('not-a-url')).toThrow(/not a valid URL/);
48
- });
49
- });
50
-
51
- describe('mapCategoryToType', () => {
52
- test('user-interaction categories → user', () => {
53
- for (const c of ['auth', 'click', 'gesture', 'input', 'touch', 'ui']) {
54
- expect(__mapCategoryToTypeForTests(c)).toBe('user');
55
- }
56
- });
57
-
58
- test('network categories → net', () => {
59
- for (const c of ['fetch', 'http', 'xhr']) {
60
- expect(__mapCategoryToTypeForTests(c)).toBe('net');
61
- }
62
- });
63
-
64
- test('navigation categories → nav', () => {
65
- for (const c of ['nav', 'navigation', 'route']) {
66
- expect(__mapCategoryToTypeForTests(c)).toBe('nav');
67
- }
68
- });
69
-
70
- test('log-shaped categories → log', () => {
71
- for (const c of ['console', 'log', 'sentry']) {
72
- expect(__mapCategoryToTypeForTests(c)).toBe('log');
73
- }
74
- });
75
-
76
- test('unknown category → custom', () => {
77
- expect(__mapCategoryToTypeForTests('whatever')).toBe('custom');
78
- });
79
-
80
- test('undefined → undefined (pass-through to native default)', () => {
81
- expect(__mapCategoryToTypeForTests(undefined)).toBeUndefined();
82
- });
83
- });
84
-
85
- describe('mapLevel', () => {
86
- test("Sentry's 'critical' maps to Sentori's 'fatal'", () => {
87
- expect(__mapLevelForTests('critical')).toBe('fatal');
88
- });
89
-
90
- test("Sentry's 'log' maps to Sentori's 'info' (no separate Log level)", () => {
91
- expect(__mapLevelForTests('log')).toBe('info');
92
- });
93
-
94
- test('5-level syslog names pass through unchanged', () => {
95
- expect(__mapLevelForTests('fatal')).toBe('fatal');
96
- expect(__mapLevelForTests('error')).toBe('error');
97
- expect(__mapLevelForTests('warning')).toBe('warning');
98
- expect(__mapLevelForTests('info')).toBe('info');
99
- expect(__mapLevelForTests('debug')).toBe('debug');
100
- });
101
-
102
- test('undefined → undefined', () => {
103
- expect(__mapLevelForTests(undefined)).toBeUndefined();
104
- });
105
- });
106
-
107
- describe('Severity export', () => {
108
- test('Critical collapses onto fatal', () => {
109
- expect(Severity.Critical).toBe('fatal');
110
- });
111
- test('Log collapses onto info', () => {
112
- expect(Severity.Log).toBe('info');
113
- });
114
- test('standard levels are themselves', () => {
115
- expect(Severity.Fatal).toBe('fatal');
116
- expect(Severity.Error).toBe('error');
117
- expect(Severity.Warning).toBe('warning');
118
- expect(Severity.Info).toBe('info');
119
- expect(Severity.Debug).toBe('debug');
120
- });
121
- });