@nathanclaire/edge-telemetry-sdk 3.0.0 → 4.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 (298) hide show
  1. package/README.md +831 -186
  2. package/dist/appLifecycle-CECgRVu_.cjs +2 -0
  3. package/dist/appLifecycle-CECgRVu_.cjs.map +1 -0
  4. package/dist/appLifecycle-DQErzJIR.js +22 -0
  5. package/dist/appLifecycle-DQErzJIR.js.map +1 -0
  6. package/dist/batch-CwoO7noL.js +56 -0
  7. package/dist/batch-CwoO7noL.js.map +1 -0
  8. package/dist/batch-DNu8Xr9T.cjs +2 -0
  9. package/dist/batch-DNu8Xr9T.cjs.map +1 -0
  10. package/dist/crashCapture-BOJ8nSAZ.cjs +4 -0
  11. package/dist/crashCapture-BOJ8nSAZ.cjs.map +1 -0
  12. package/dist/crashCapture-BW8WuyaU.js +70 -0
  13. package/dist/crashCapture-BW8WuyaU.js.map +1 -0
  14. package/dist/crashHandler.web-8F_k2veo.js +29 -0
  15. package/dist/crashHandler.web-8F_k2veo.js.map +1 -0
  16. package/dist/crashHandler.web-CWmF56mJ.cjs +2 -0
  17. package/dist/crashHandler.web-CWmF56mJ.cjs.map +1 -0
  18. package/dist/crashHandlerNative.native-C2kSikDt.cjs +2 -0
  19. package/dist/crashHandlerNative.native-C2kSikDt.cjs.map +1 -0
  20. package/dist/crashHandlerNative.native-FupMnr1U.js +39 -0
  21. package/dist/crashHandlerNative.native-FupMnr1U.js.map +1 -0
  22. package/dist/deviceInfo.native-BJ-3Jj1T.js +53 -0
  23. package/dist/deviceInfo.native-BJ-3Jj1T.js.map +1 -0
  24. package/dist/deviceInfo.native-BoeTZcD6.cjs +2 -0
  25. package/dist/deviceInfo.native-BoeTZcD6.cjs.map +1 -0
  26. package/dist/deviceInfo.web-3L3IDQQA.cjs +2 -0
  27. package/dist/deviceInfo.web-3L3IDQQA.cjs.map +1 -0
  28. package/dist/deviceInfo.web-BFB1-pcA.js +41 -0
  29. package/dist/deviceInfo.web-BFB1-pcA.js.map +1 -0
  30. package/dist/frameTracker-CHG6sIx9.cjs +2 -0
  31. package/dist/frameTracker-CHG6sIx9.cjs.map +1 -0
  32. package/dist/frameTracker-DdB8W_kC.js +54 -0
  33. package/dist/frameTracker-DdB8W_kC.js.map +1 -0
  34. package/dist/httpAttributes-BrrtM8zh.js +70 -0
  35. package/dist/httpAttributes-BrrtM8zh.js.map +1 -0
  36. package/dist/httpAttributes-D0m6UID7.cjs +2 -0
  37. package/dist/httpAttributes-D0m6UID7.cjs.map +1 -0
  38. package/dist/index-BtLlV1HA.js +57 -0
  39. package/dist/index-BtLlV1HA.js.map +1 -0
  40. package/dist/{deviceInfo.native-D2k0LDhI.js → index-C2XQ-EYw.js} +362 -411
  41. package/dist/index-C2XQ-EYw.js.map +1 -0
  42. package/dist/index-CXsVZY35.cjs +2 -0
  43. package/dist/index-CXsVZY35.cjs.map +1 -0
  44. package/dist/index-DLquF88M.cjs +2 -0
  45. package/dist/index-DLquF88M.cjs.map +1 -0
  46. package/dist/index.native.cjs +1 -1
  47. package/dist/index.native.cjs.map +1 -1
  48. package/dist/index.native.js +94 -59
  49. package/dist/index.native.js.map +1 -1
  50. package/dist/index.web.cjs +1 -1
  51. package/dist/index.web.cjs.map +1 -1
  52. package/dist/index.web.js +88 -33
  53. package/dist/index.web.js.map +1 -1
  54. package/dist/interactionWeb.web-Bl_cZlgh.cjs +2 -0
  55. package/dist/interactionWeb.web-Bl_cZlgh.cjs.map +1 -0
  56. package/dist/interactionWeb.web-CJAviVQ7.js +109 -0
  57. package/dist/interactionWeb.web-CJAviVQ7.js.map +1 -0
  58. package/dist/interceptFetchWeb.web-T88kO-bE.cjs +2 -0
  59. package/dist/interceptFetchWeb.web-T88kO-bE.cjs.map +1 -0
  60. package/dist/interceptFetchWeb.web-UXC2Lb6X.js +61 -0
  61. package/dist/interceptFetchWeb.web-UXC2Lb6X.js.map +1 -0
  62. package/dist/interceptHttpNative.native-BVpFuoNB.cjs +2 -0
  63. package/dist/interceptHttpNative.native-BVpFuoNB.cjs.map +1 -0
  64. package/dist/interceptHttpNative.native-rX-lPNST.js +18 -0
  65. package/dist/interceptHttpNative.native-rX-lPNST.js.map +1 -0
  66. package/dist/loadingTime-Bhomd9qq.cjs +2 -0
  67. package/dist/loadingTime-Bhomd9qq.cjs.map +1 -0
  68. package/dist/loadingTime-ZkYvFijA.js +70 -0
  69. package/dist/loadingTime-ZkYvFijA.js.map +1 -0
  70. package/dist/memoryNative.native-C42h9SjK.js +54 -0
  71. package/dist/memoryNative.native-C42h9SjK.js.map +1 -0
  72. package/dist/memoryNative.native-CA-7w9w1.cjs +2 -0
  73. package/dist/memoryNative.native-CA-7w9w1.cjs.map +1 -0
  74. package/dist/memoryStore-BIGZmmfD.cjs +2 -0
  75. package/dist/memoryStore-BIGZmmfD.cjs.map +1 -0
  76. package/dist/memoryStore-F5I-GQKM.js +193 -0
  77. package/dist/memoryStore-F5I-GQKM.js.map +1 -0
  78. package/dist/nativeSender-CfQaRuDK.cjs +2 -0
  79. package/dist/nativeSender-CfQaRuDK.cjs.map +1 -0
  80. package/dist/nativeSender-pgVSIv-X.js +59 -0
  81. package/dist/nativeSender-pgVSIv-X.js.map +1 -0
  82. package/dist/navigationRef-BzYbs8cm.js +28 -0
  83. package/dist/navigationRef-BzYbs8cm.js.map +1 -0
  84. package/dist/navigationRef-C-_qhb43.cjs +2 -0
  85. package/dist/navigationRef-C-_qhb43.cjs.map +1 -0
  86. package/dist/{navigationTracker-Cts68dgG.js → navigationTracker-BmywA_Bg.js} +4 -4
  87. package/dist/navigationTracker-BmywA_Bg.js.map +1 -0
  88. package/dist/navigationTracker-HkwVyywz.cjs +2 -0
  89. package/dist/navigationTracker-HkwVyywz.cjs.map +1 -0
  90. package/dist/navigationWeb.web-CW_z7Ca4.cjs +2 -0
  91. package/dist/navigationWeb.web-CW_z7Ca4.cjs.map +1 -0
  92. package/dist/navigationWeb.web-CcwgKuIZ.js +55 -0
  93. package/dist/navigationWeb.web-CcwgKuIZ.js.map +1 -0
  94. package/dist/{networkInfo.native-BK5fpAOL.js → networkInfo.native-CGrx9cnH.js} +15 -15
  95. package/dist/{networkInfo.native-BK5fpAOL.js.map → networkInfo.native-CGrx9cnH.js.map} +1 -1
  96. package/dist/{networkInfo.native-cxuw93Uy.cjs → networkInfo.native-YVySdv3S.cjs} +2 -2
  97. package/dist/{networkInfo.native-cxuw93Uy.cjs.map → networkInfo.native-YVySdv3S.cjs.map} +1 -1
  98. package/dist/{networkInfo.web-twcNn_hc.js → networkInfo.web-B2YlLNsI.js} +3 -3
  99. package/dist/networkInfo.web-B2YlLNsI.js.map +1 -0
  100. package/dist/networkInfo.web-PltJTHsy.cjs +2 -0
  101. package/dist/networkInfo.web-PltJTHsy.cjs.map +1 -0
  102. package/dist/runtimeReady.native-Bh7EcYmK.js +14 -0
  103. package/dist/runtimeReady.native-Bh7EcYmK.js.map +1 -0
  104. package/dist/runtimeReady.native-jUmuE1lV.cjs +2 -0
  105. package/dist/runtimeReady.native-jUmuE1lV.cjs.map +1 -0
  106. package/dist/runtimeReady.web-C8fdIbVR.js +25 -0
  107. package/dist/runtimeReady.web-C8fdIbVR.js.map +1 -0
  108. package/dist/runtimeReady.web-DHW682RN.cjs +2 -0
  109. package/dist/runtimeReady.web-DHW682RN.cjs.map +1 -0
  110. package/dist/seedRuntimeReady-BKwkBEAF.cjs +2 -0
  111. package/dist/seedRuntimeReady-BKwkBEAF.cjs.map +1 -0
  112. package/dist/seedRuntimeReady-Cz8nOKoo.js +10 -0
  113. package/dist/seedRuntimeReady-Cz8nOKoo.js.map +1 -0
  114. package/dist/src/adapters/appLifecycle.d.ts +8 -1
  115. package/dist/src/adapters/batch.d.ts +2 -0
  116. package/dist/src/adapters/crashCapture.d.ts +38 -9
  117. package/dist/src/adapters/failedEvents.d.ts +43 -0
  118. package/dist/src/adapters/frameAggregate.d.ts +8 -3
  119. package/dist/src/adapters/frameTracker.d.ts +30 -0
  120. package/dist/src/adapters/httpAttributes.d.ts +18 -0
  121. package/dist/src/adapters/loadingTime.d.ts +67 -0
  122. package/dist/src/adapters/native/interceptHttpNative.native.d.ts +18 -0
  123. package/dist/src/adapters/native/memoryNative.native.d.ts +15 -11
  124. package/dist/src/adapters/native/runtimeReady.native.d.ts +1 -0
  125. package/dist/src/adapters/native/store.native.d.ts +10 -0
  126. package/dist/src/adapters/nativeSender.d.ts +2 -2
  127. package/dist/src/adapters/navigationRef.d.ts +21 -0
  128. package/dist/src/adapters/navigationTracker.d.ts +1 -1
  129. package/dist/src/adapters/screenTiming.d.ts +8 -2
  130. package/dist/src/adapters/seedRuntimeReady.d.ts +8 -0
  131. package/dist/src/adapters/traceHeader.d.ts +33 -0
  132. package/dist/src/adapters/traceManager.d.ts +131 -0
  133. package/dist/src/adapters/uiInteraction.d.ts +111 -0
  134. package/dist/src/adapters/viewManager.d.ts +161 -0
  135. package/dist/src/adapters/viewport.d.ts +15 -0
  136. package/dist/src/adapters/web/interactionWeb.web.d.ts +36 -0
  137. package/dist/src/adapters/web/interceptFetchWeb.web.d.ts +3 -11
  138. package/dist/src/adapters/web/navigationWeb.web.d.ts +10 -0
  139. package/dist/src/adapters/web/runtimeReady.web.d.ts +5 -0
  140. package/dist/src/adapters/web/store.web.d.ts +12 -0
  141. package/dist/src/adapters/web/webVitals.web.d.ts +49 -0
  142. package/dist/src/adapters/webSender.d.ts +2 -2
  143. package/dist/src/adapters/webVitals.d.ts +25 -0
  144. package/dist/src/adapters/xhrIntercept.d.ts +53 -0
  145. package/dist/src/core/beforeSend.d.ts +20 -0
  146. package/dist/src/core/debug.d.ts +7 -0
  147. package/dist/src/core/memoryStore.d.ts +23 -0
  148. package/dist/src/core/store.d.ts +41 -0
  149. package/dist/src/core/telemetry.d.ts +305 -35
  150. package/dist/src/core/userProfile.d.ts +12 -0
  151. package/dist/src/core/utils/json.d.ts +7 -0
  152. package/dist/src/core/utils/uuid.d.ts +10 -1
  153. package/dist/src/createTelemetry.native.d.ts +7 -0
  154. package/dist/src/createTelemetry.web.d.ts +7 -0
  155. package/dist/src/index.base.d.ts +17 -1
  156. package/dist/src/index.native.d.ts +46 -9
  157. package/dist/src/index.web.d.ts +33 -2
  158. package/dist/store.native-BYBJcy6o.js +32 -0
  159. package/dist/store.native-BYBJcy6o.js.map +1 -0
  160. package/dist/store.native-TPqXngmF.cjs +2 -0
  161. package/dist/store.native-TPqXngmF.cjs.map +1 -0
  162. package/dist/store.web-CvqqN-_Z.cjs +2 -0
  163. package/dist/store.web-CvqqN-_Z.cjs.map +1 -0
  164. package/dist/store.web-DJAlN0nc.js +31 -0
  165. package/dist/store.web-DJAlN0nc.js.map +1 -0
  166. package/dist/telemetry-ByDJIz_9.js +1280 -0
  167. package/dist/telemetry-ByDJIz_9.js.map +1 -0
  168. package/dist/telemetry-CrU7i1Jc.cjs +2 -0
  169. package/dist/telemetry-CrU7i1Jc.cjs.map +1 -0
  170. package/dist/uiInteraction-CdzvEI1p.cjs +2 -0
  171. package/dist/uiInteraction-CdzvEI1p.cjs.map +1 -0
  172. package/dist/uiInteraction-DAqxxz0q.js +104 -0
  173. package/dist/uiInteraction-DAqxxz0q.js.map +1 -0
  174. package/dist/viewport-Dd85GUNO.cjs +2 -0
  175. package/dist/viewport-Dd85GUNO.cjs.map +1 -0
  176. package/dist/viewport-Dzmt5QwK.js +15 -0
  177. package/dist/viewport-Dzmt5QwK.js.map +1 -0
  178. package/dist/web-vitals.attribution-CVCPiX-h.cjs +2 -0
  179. package/dist/web-vitals.attribution-CVCPiX-h.cjs.map +1 -0
  180. package/dist/web-vitals.attribution-xw9N5MKQ.js +488 -0
  181. package/dist/web-vitals.attribution-xw9N5MKQ.js.map +1 -0
  182. package/dist/webSender-BIwslfpT.js +63 -0
  183. package/dist/webSender-BIwslfpT.js.map +1 -0
  184. package/dist/webSender-CVtE4sOF.cjs +2 -0
  185. package/dist/webSender-CVtE4sOF.cjs.map +1 -0
  186. package/dist/webVitals.web-CNIpsKlA.js +85 -0
  187. package/dist/webVitals.web-CNIpsKlA.js.map +1 -0
  188. package/dist/webVitals.web-DpWJ-iYp.cjs +2 -0
  189. package/dist/webVitals.web-DpWJ-iYp.cjs.map +1 -0
  190. package/dist/xhrIntercept-BADex6Cq.cjs +2 -0
  191. package/dist/xhrIntercept-BADex6Cq.cjs.map +1 -0
  192. package/dist/xhrIntercept-BNiA41Mj.js +53 -0
  193. package/dist/xhrIntercept-BNiA41Mj.js.map +1 -0
  194. package/docs/migration-v4.md +190 -0
  195. package/package.json +12 -4
  196. package/dist/appLifecycle-Cynw0kAv.js +0 -14
  197. package/dist/appLifecycle-Cynw0kAv.js.map +0 -1
  198. package/dist/appLifecycle-DvJIt7ym.cjs +0 -2
  199. package/dist/appLifecycle-DvJIt7ym.cjs.map +0 -1
  200. package/dist/batch-CLBFgYPC.cjs +0 -2
  201. package/dist/batch-CLBFgYPC.cjs.map +0 -1
  202. package/dist/batch-DLG_gtOm.js +0 -12
  203. package/dist/batch-DLG_gtOm.js.map +0 -1
  204. package/dist/crashCapture-BYTM4FLC.cjs +0 -2
  205. package/dist/crashCapture-BYTM4FLC.cjs.map +0 -1
  206. package/dist/crashCapture-D_rkkBVa.js +0 -31
  207. package/dist/crashCapture-D_rkkBVa.js.map +0 -1
  208. package/dist/crashHandler.web-BSxDpFTo.cjs +0 -2
  209. package/dist/crashHandler.web-BSxDpFTo.cjs.map +0 -1
  210. package/dist/crashHandler.web-D59bmhg9.js +0 -32
  211. package/dist/crashHandler.web-D59bmhg9.js.map +0 -1
  212. package/dist/crashHandlerNative.native-DeAFze4E.cjs +0 -2
  213. package/dist/crashHandlerNative.native-DeAFze4E.cjs.map +0 -1
  214. package/dist/crashHandlerNative.native-d7qJkzA6.js +0 -41
  215. package/dist/crashHandlerNative.native-d7qJkzA6.js.map +0 -1
  216. package/dist/debug-DsvQ9y3W.js +0 -68
  217. package/dist/debug-DsvQ9y3W.js.map +0 -1
  218. package/dist/debug-rnOOxFpN.cjs +0 -2
  219. package/dist/debug-rnOOxFpN.cjs.map +0 -1
  220. package/dist/deviceInfo.native-7hbRYixR.cjs +0 -2
  221. package/dist/deviceInfo.native-7hbRYixR.cjs.map +0 -1
  222. package/dist/deviceInfo.native-D2k0LDhI.js.map +0 -1
  223. package/dist/deviceInfo.web-ByNAlEJh.cjs +0 -2
  224. package/dist/deviceInfo.web-ByNAlEJh.cjs.map +0 -1
  225. package/dist/deviceInfo.web-DzQyEku6.js +0 -40
  226. package/dist/deviceInfo.web-DzQyEku6.js.map +0 -1
  227. package/dist/frameAggregate-C_HoVFcK.cjs +0 -2
  228. package/dist/frameAggregate-C_HoVFcK.cjs.map +0 -1
  229. package/dist/frameAggregate-Cwh1juw1.js +0 -17
  230. package/dist/frameAggregate-Cwh1juw1.js.map +0 -1
  231. package/dist/frameDropsNative.native-CP7zrXDf.js +0 -23
  232. package/dist/frameDropsNative.native-CP7zrXDf.js.map +0 -1
  233. package/dist/frameDropsNative.native-DKqEDqip.cjs +0 -2
  234. package/dist/frameDropsNative.native-DKqEDqip.cjs.map +0 -1
  235. package/dist/frameDropsWeb.web-C9Lt3Fuj.js +0 -22
  236. package/dist/frameDropsWeb.web-C9Lt3Fuj.js.map +0 -1
  237. package/dist/frameDropsWeb.web-azpwQCUz.cjs +0 -2
  238. package/dist/frameDropsWeb.web-azpwQCUz.cjs.map +0 -1
  239. package/dist/httpAttributes-BV50UKQU.js +0 -19
  240. package/dist/httpAttributes-BV50UKQU.js.map +0 -1
  241. package/dist/httpAttributes-xXOD9trQ.cjs +0 -2
  242. package/dist/httpAttributes-xXOD9trQ.cjs.map +0 -1
  243. package/dist/interaction-CH8yoY5-.js +0 -23
  244. package/dist/interaction-CH8yoY5-.js.map +0 -1
  245. package/dist/interaction-DcNFBW7a.cjs +0 -2
  246. package/dist/interaction-DcNFBW7a.cjs.map +0 -1
  247. package/dist/interceptFetchNative.native-VlhtMG-U.js +0 -49
  248. package/dist/interceptFetchNative.native-VlhtMG-U.js.map +0 -1
  249. package/dist/interceptFetchNative.native-jEAldH14.cjs +0 -2
  250. package/dist/interceptFetchNative.native-jEAldH14.cjs.map +0 -1
  251. package/dist/interceptFetchWeb.web-DFzZliik.cjs +0 -2
  252. package/dist/interceptFetchWeb.web-DFzZliik.cjs.map +0 -1
  253. package/dist/interceptFetchWeb.web-DfsMfoRP.js +0 -77
  254. package/dist/interceptFetchWeb.web-DfsMfoRP.js.map +0 -1
  255. package/dist/memoryNative.native-BWLh2S9L.js +0 -48
  256. package/dist/memoryNative.native-BWLh2S9L.js.map +0 -1
  257. package/dist/memoryNative.native-DCXSOd4Q.cjs +0 -2
  258. package/dist/memoryNative.native-DCXSOd4Q.cjs.map +0 -1
  259. package/dist/memoryWeb.web-B3YuV-cB.js +0 -48
  260. package/dist/memoryWeb.web-B3YuV-cB.js.map +0 -1
  261. package/dist/memoryWeb.web-CheXAcJn.cjs +0 -2
  262. package/dist/memoryWeb.web-CheXAcJn.cjs.map +0 -1
  263. package/dist/nativeSender-BE_mzw_S.js +0 -70
  264. package/dist/nativeSender-BE_mzw_S.js.map +0 -1
  265. package/dist/nativeSender-DyAUGY7c.cjs +0 -2
  266. package/dist/nativeSender-DyAUGY7c.cjs.map +0 -1
  267. package/dist/navigationNative.native-3tO5JxSd.cjs +0 -2
  268. package/dist/navigationNative.native-3tO5JxSd.cjs.map +0 -1
  269. package/dist/navigationNative.native-BUCGPQX2.js +0 -25
  270. package/dist/navigationNative.native-BUCGPQX2.js.map +0 -1
  271. package/dist/navigationTracker-B2GMwyKk.cjs +0 -2
  272. package/dist/navigationTracker-B2GMwyKk.cjs.map +0 -1
  273. package/dist/navigationTracker-Cts68dgG.js.map +0 -1
  274. package/dist/navigationWeb.web-B0necr5j.cjs +0 -2
  275. package/dist/navigationWeb.web-B0necr5j.cjs.map +0 -1
  276. package/dist/navigationWeb.web-CORzE_Id.js +0 -46
  277. package/dist/navigationWeb.web-CORzE_Id.js.map +0 -1
  278. package/dist/networkInfo.web-DJmw1sNK.cjs +0 -2
  279. package/dist/networkInfo.web-DJmw1sNK.cjs.map +0 -1
  280. package/dist/networkInfo.web-twcNn_hc.js.map +0 -1
  281. package/dist/src/adapters/interaction.d.ts +0 -17
  282. package/dist/src/adapters/native/frameDropsNative.native.d.ts +0 -16
  283. package/dist/src/adapters/native/interceptFetchNative.native.d.ts +0 -23
  284. package/dist/src/adapters/native/navigationNative.native.d.ts +0 -12
  285. package/dist/src/adapters/web/frameDropsWeb.web.d.ts +0 -16
  286. package/dist/src/adapters/web/memoryWeb.web.d.ts +0 -26
  287. package/dist/telemetry-Co4MYdwa.cjs +0 -2
  288. package/dist/telemetry-Co4MYdwa.cjs.map +0 -1
  289. package/dist/telemetry-KI0x4gzC.js +0 -389
  290. package/dist/telemetry-KI0x4gzC.js.map +0 -1
  291. package/dist/v4-BysszJq8.js +0 -31
  292. package/dist/v4-BysszJq8.js.map +0 -1
  293. package/dist/v4-CqdK_b8Y.cjs +0 -2
  294. package/dist/v4-CqdK_b8Y.cjs.map +0 -1
  295. package/dist/webSender-B27tmT1w.js +0 -42
  296. package/dist/webSender-B27tmT1w.js.map +0 -1
  297. package/dist/webSender-BWi4x1df.cjs +0 -2
  298. package/dist/webSender-BWi4x1df.cjs.map +0 -1
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class r{constructor(e){this.telemetry=e}async onState(e){const t=this.active;this.active=e,!(t===void 0||t===e)&&(await this.telemetry.log("app_lifecycle",{"app_lifecycle.state":e?"foreground":"background"}),e?this.telemetry.views.foreground():(await this.telemetry.views.background(),this.telemetry.trace.clear()))}}exports.AppLifecycleEmitter=r;
2
+ //# sourceMappingURL=appLifecycle-CECgRVu_.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appLifecycle-CECgRVu_.cjs","sources":["../src/adapters/appLifecycle.ts"],"sourcesContent":["import { Telemetry } from \"../core/telemetry\";\n\n/**\n * Shared foreground/background emitter — the single source of truth so the native\n * (RN AppState) and web (visibilitychange) lifecycle adapters stay in lockstep on the\n * v3 `app_lifecycle` contract (#30).\n *\n * Feed it the current active state via `onState(isActive)`. It emits `app_lifecycle` only\n * on a transition, carrying the direction as `app_lifecycle.state` (foreground|background).\n */\nexport class AppLifecycleEmitter {\n private active?: boolean;\n\n constructor(private telemetry: Telemetry) {}\n\n /**\n * Returns once the transition's rows are enqueued — **await it before flushing**. The\n * background boundary's `view` row is the one most likely to be lost to an OS kill, and\n * the whole point of §4.5's background boundary is that it flushes while the app is still\n * reliably alive. A caller that fires the flush on the next line instead sends the batch\n * before the row exists.\n */\n async onState(isActive: boolean): Promise<void> {\n const previous = this.active;\n this.active = isActive;\n if (previous === undefined || previous === isActive) return;\n\n // Chained, not fired alongside, so the `app_lifecycle` row lands in the view it happened\n // in — awaited because a consumer-supplied double may return a plain value.\n await this.telemetry.log(\"app_lifecycle\", {\n \"app_lifecycle.state\": isActive ? \"foreground\" : \"background\",\n });\n // The view ends and emits, and the successor's clock starts paused so a night spent\n // backgrounded is not charged as dwell to the screen the user left open.\n if (isActive) this.telemetry.views.foreground();\n else {\n await this.telemetry.views.background();\n // Background clears the live root on both builds (§6.2), so a resumed app's first\n // fetch mints its own root rather than joining an action from before the user left.\n // *After* the view boundary, not before: the successor view is minted in there, and\n // clearing first would leave its freshly-minted `navigation` root as the carrier the\n // resumed app then joins.\n this.telemetry.trace.clear();\n }\n }\n}\n"],"names":["AppLifecycleEmitter","telemetry","isActive","previous"],"mappings":"gFAUO,MAAMA,CAAoB,CAG/B,YAAoBC,EAAsB,CAAtB,KAAA,UAAAA,CAAuB,CAS3C,MAAM,QAAQC,EAAkC,CAC9C,MAAMC,EAAW,KAAK,OACtB,KAAK,OAASD,EACV,EAAAC,IAAa,QAAaA,IAAaD,KAI3C,MAAM,KAAK,UAAU,IAAI,gBAAiB,CACxC,sBAAuBA,EAAW,aAAe,YAAA,CAClD,EAGGA,EAAU,KAAK,UAAU,MAAM,WAAA,GAEjC,MAAM,KAAK,UAAU,MAAM,WAAA,EAM3B,KAAK,UAAU,MAAM,MAAA,GAEzB,CACF"}
@@ -0,0 +1,22 @@
1
+ class a {
2
+ constructor(e) {
3
+ this.telemetry = e;
4
+ }
5
+ /**
6
+ * Returns once the transition's rows are enqueued — **await it before flushing**. The
7
+ * background boundary's `view` row is the one most likely to be lost to an OS kill, and
8
+ * the whole point of §4.5's background boundary is that it flushes while the app is still
9
+ * reliably alive. A caller that fires the flush on the next line instead sends the batch
10
+ * before the row exists.
11
+ */
12
+ async onState(e) {
13
+ const t = this.active;
14
+ this.active = e, !(t === void 0 || t === e) && (await this.telemetry.log("app_lifecycle", {
15
+ "app_lifecycle.state": e ? "foreground" : "background"
16
+ }), e ? this.telemetry.views.foreground() : (await this.telemetry.views.background(), this.telemetry.trace.clear()));
17
+ }
18
+ }
19
+ export {
20
+ a as AppLifecycleEmitter
21
+ };
22
+ //# sourceMappingURL=appLifecycle-DQErzJIR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appLifecycle-DQErzJIR.js","sources":["../src/adapters/appLifecycle.ts"],"sourcesContent":["import { Telemetry } from \"../core/telemetry\";\n\n/**\n * Shared foreground/background emitter — the single source of truth so the native\n * (RN AppState) and web (visibilitychange) lifecycle adapters stay in lockstep on the\n * v3 `app_lifecycle` contract (#30).\n *\n * Feed it the current active state via `onState(isActive)`. It emits `app_lifecycle` only\n * on a transition, carrying the direction as `app_lifecycle.state` (foreground|background).\n */\nexport class AppLifecycleEmitter {\n private active?: boolean;\n\n constructor(private telemetry: Telemetry) {}\n\n /**\n * Returns once the transition's rows are enqueued — **await it before flushing**. The\n * background boundary's `view` row is the one most likely to be lost to an OS kill, and\n * the whole point of §4.5's background boundary is that it flushes while the app is still\n * reliably alive. A caller that fires the flush on the next line instead sends the batch\n * before the row exists.\n */\n async onState(isActive: boolean): Promise<void> {\n const previous = this.active;\n this.active = isActive;\n if (previous === undefined || previous === isActive) return;\n\n // Chained, not fired alongside, so the `app_lifecycle` row lands in the view it happened\n // in — awaited because a consumer-supplied double may return a plain value.\n await this.telemetry.log(\"app_lifecycle\", {\n \"app_lifecycle.state\": isActive ? \"foreground\" : \"background\",\n });\n // The view ends and emits, and the successor's clock starts paused so a night spent\n // backgrounded is not charged as dwell to the screen the user left open.\n if (isActive) this.telemetry.views.foreground();\n else {\n await this.telemetry.views.background();\n // Background clears the live root on both builds (§6.2), so a resumed app's first\n // fetch mints its own root rather than joining an action from before the user left.\n // *After* the view boundary, not before: the successor view is minted in there, and\n // clearing first would leave its freshly-minted `navigation` root as the carrier the\n // resumed app then joins.\n this.telemetry.trace.clear();\n }\n }\n}\n"],"names":["AppLifecycleEmitter","telemetry","isActive","previous"],"mappings":"AAUO,MAAMA,EAAoB;AAAA,EAG/B,YAAoBC,GAAsB;AAAtB,SAAA,YAAAA;AAAA,EAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3C,MAAM,QAAQC,GAAkC;AAC9C,UAAMC,IAAW,KAAK;AAEtB,IADA,KAAK,SAASD,GACV,EAAAC,MAAa,UAAaA,MAAaD,OAI3C,MAAM,KAAK,UAAU,IAAI,iBAAiB;AAAA,MACxC,uBAAuBA,IAAW,eAAe;AAAA,IAAA,CAClD,GAGGA,IAAU,KAAK,UAAU,MAAM,WAAA,KAEjC,MAAM,KAAK,UAAU,MAAM,WAAA,GAM3B,KAAK,UAAU,MAAM,MAAA;AAAA,EAEzB;AACF;"}
@@ -0,0 +1,56 @@
1
+ import { evictIndex as a } from "./telemetry-ByDJIz_9.js";
2
+ const p = "telemetry_failed_events";
3
+ function y(e) {
4
+ if (e.status !== "hit") return [];
5
+ try {
6
+ const n = JSON.parse(e.value);
7
+ return Array.isArray(n) ? n : [];
8
+ } catch {
9
+ return [];
10
+ }
11
+ }
12
+ const l = 500, d = 1e6, u = (e) => typeof TextEncoder < "u" ? new TextEncoder().encode(e).length : e.length;
13
+ function g(e, n) {
14
+ const t = [...e, ...n];
15
+ let r = 0;
16
+ for (; t.length > l; )
17
+ t.splice(a(t), 1), r++;
18
+ const o = t.map((i) => u(JSON.stringify(i)));
19
+ let s = o.reduce((i, c) => i + c, 0) + Math.max(t.length - 1, 0) + 2;
20
+ for (; s > d && t.length > 0; ) {
21
+ const i = a(t);
22
+ s -= o[i] + (t.length > 1 ? 1 : 0), o.splice(i, 1), t.splice(i, 1), r++;
23
+ }
24
+ return { json: JSON.stringify(t), dropped: r };
25
+ }
26
+ function f(e) {
27
+ let n;
28
+ return () => n ??= e().finally(() => {
29
+ n = void 0;
30
+ });
31
+ }
32
+ function E(e) {
33
+ return JSON.stringify({
34
+ type: "telemetry_batch",
35
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
36
+ batch_size: e.length,
37
+ events: e
38
+ });
39
+ }
40
+ function S(e) {
41
+ return {
42
+ "Content-Type": "application/json",
43
+ ...e ? { "X-API-Key": e, Authorization: `Bearer ${e}` } : {}
44
+ };
45
+ }
46
+ const _ = "https://your.telemetry.endpoint/telemetry";
47
+ export {
48
+ _ as D,
49
+ p as F,
50
+ S as a,
51
+ E as b,
52
+ y as d,
53
+ g as e,
54
+ f as g
55
+ };
56
+ //# sourceMappingURL=batch-CwoO7noL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-CwoO7noL.js","sources":["../src/adapters/failedEvents.ts","../src/adapters/batch.ts"],"sourcesContent":["import type { StoreRead } from \"../core/store\";\nimport { evictIndex, type TelemetryEvent } from \"../core/telemetry\";\n\n// The offline queue's shared, platform-agnostic half (#89). Both senders keep failed\n// batches under one key; only the Store underneath them differs, so the decoding rules\n// live here once and stay in lockstep.\n\nexport const FAILED_EVENTS_KEY = \"telemetry_failed_events\";\n\n/**\n * Decode a stored batch.\n *\n * The Store port never throws, and neither does this. An unavailable store, a key that\n * was never written, a half-written payload and a non-array JSON value all mean the\n * same thing to a caller — nothing replayable — so they all return `[]`. Before the\n * port, this was a bare `JSON.parse(... || \"[]\")` that threw straight through\n * `replayFailed()` on any corrupt payload and took startup with it.\n */\nexport function decodeFailed(read: StoreRead): TelemetryEvent[] {\n if (read.status !== \"hit\") return [];\n try {\n const parsed = JSON.parse(read.value);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/**\n * The offline store's cap (§9.4). Real numbers, not chosen ones: Android caps AsyncStorage\n * at 6 MB for the whole app and web `localStorage` is the *host app's* ~5 MB — an\n * append-only telemetry queue inside either is a slow eviction of the consumer's own data.\n */\nexport const STORE_MAX_EVENTS = 500;\nexport const STORE_MAX_BYTES = 1_000_000;\n\n/** UTF-8 length where the runtime offers it. RN (Hermes) and every browser do; be safe anyway. */\nconst byteLength = (s: string): number =>\n typeof TextEncoder !== \"undefined\" ? new TextEncoder().encode(s).length : s.length;\n\n/**\n * Encode the queue after appending `incoming`, oldest first, capped per §9.4 and\n * reporting how many rows the cap cost.\n *\n * The caller books the count as `sdk.drop_reason = \"store_full\"`; returning it rather\n * than counting in here keeps this module free of the Telemetry instance it would\n * otherwise need a handle on.\n */\nexport function encodeFailed(\n existing: TelemetryEvent[],\n incoming: TelemetryEvent[],\n): { json: string; dropped: number } {\n const kept = [...existing, ...incoming];\n let dropped = 0;\n\n while (kept.length > STORE_MAX_EVENTS) { kept.splice(evictIndex(kept), 1); dropped++; }\n\n // Sized once per event, not once per eviction: a 500-event backlog of 100 KiB events\n // (the collector's per-event ceiling) would otherwise re-stringify ~50 MB per drop.\n // 2 for the brackets, 1 per separating comma.\n const sizes = kept.map(e => byteLength(JSON.stringify(e)));\n let total = sizes.reduce((a, b) => a + b, 0) + Math.max(kept.length - 1, 0) + 2;\n while (total > STORE_MAX_BYTES && kept.length > 0) {\n const i = evictIndex(kept);\n total -= sizes[i] + (kept.length > 1 ? 1 : 0); // no separating comma to reclaim on the last row\n sizes.splice(i, 1);\n kept.splice(i, 1);\n dropped++;\n }\n\n return { json: JSON.stringify(kept), dropped };\n}\n\n/**\n * One drain per sender, however many callers there are (#113).\n *\n * `takeFailed()` clears the key before the send is attempted, so a *single* drain can\n * never double-send. Two concurrent drains can: both read the payload before either\n * removes it, and the recovered batch goes out twice — worst exactly when the network\n * was bad, which is when the data mattered. Returning the in-flight promise makes the\n * second caller a no-op that still awaits the first, and the guard is per-sender rather\n * than per-module so two `Telemetry` instances in one process keep their own.\n */\nexport function guardedDrain(drain: () => Promise<void>): () => Promise<void> {\n let inFlight: Promise<void> | undefined;\n return () => (inFlight ??= drain().finally(() => { inFlight = undefined; }));\n}\n","import type { TelemetryEvent } from \"../core/telemetry\";\n\n// v3 wire envelope. Shared by both senders so the web and native POST bodies\n// stay byte-identical to the EdgeRum telemetry_batch contract.\nexport function buildBatch(events: TelemetryEvent[]): string {\n return JSON.stringify({\n type: \"telemetry_batch\",\n timestamp: new Date().toISOString(),\n batch_size: events.length,\n events,\n });\n}\n\n// Auth (#90, contract §11.1). The collector's credentialFromRequest reads Authorization under\n// AUTH_MODE=jwt and X-API-Key otherwise — exactly one, never both. Sending both, always, with\n// the same value makes one build work in the shared and the segmented (bank / on-prem)\n// topologies with no mode flag. Do not sniff the credential's shape to pick a header.\nexport function buildHeaders(credential: string | undefined): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n ...(credential ? { \"X-API-Key\": credential, \"Authorization\": `Bearer ${credential}` } : {}),\n };\n}\n\n// Placeholder host — always pass a real `endpoint`. The path is the collector's real one:\n// it terminates POST /telemetry (contract §11.1). Shared so the two senders cannot drift.\nexport const DEFAULT_ENDPOINT = \"https://your.telemetry.endpoint/telemetry\";\n"],"names":["FAILED_EVENTS_KEY","decodeFailed","read","parsed","STORE_MAX_EVENTS","STORE_MAX_BYTES","byteLength","s","encodeFailed","existing","incoming","kept","dropped","evictIndex","sizes","e","total","a","b","guardedDrain","drain","inFlight","buildBatch","events","buildHeaders","credential","DEFAULT_ENDPOINT"],"mappings":";AAOO,MAAMA,IAAoB;AAW1B,SAASC,EAAaC,GAAmC;AAC5D,MAAIA,EAAK,WAAW,MAAO,QAAO,CAAA;AAClC,MAAI;AACA,UAAMC,IAAS,KAAK,MAAMD,EAAK,KAAK;AACpC,WAAO,MAAM,QAAQC,CAAM,IAAIA,IAAS,CAAA;AAAA,EAC5C,QAAQ;AACJ,WAAO,CAAA;AAAA,EACX;AACJ;AAOO,MAAMC,IAAmB,KACnBC,IAAkB,KAGzBC,IAAa,CAACC,MAChB,OAAO,cAAgB,MAAc,IAAI,YAAA,EAAc,OAAOA,CAAC,EAAE,SAASA,EAAE;AAUzE,SAASC,EACZC,GACAC,GACiC;AACjC,QAAMC,IAAO,CAAC,GAAGF,GAAU,GAAGC,CAAQ;AACtC,MAAIE,IAAU;AAEd,SAAOD,EAAK,SAASP;AAAoB,IAAAO,EAAK,OAAOE,EAAWF,CAAI,GAAG,CAAC,GAAGC;AAK3E,QAAME,IAAQH,EAAK,IAAI,CAAAI,MAAKT,EAAW,KAAK,UAAUS,CAAC,CAAC,CAAC;AACzD,MAAIC,IAAQF,EAAM,OAAO,CAACG,GAAGC,MAAMD,IAAIC,GAAG,CAAC,IAAI,KAAK,IAAIP,EAAK,SAAS,GAAG,CAAC,IAAI;AAC9E,SAAOK,IAAQX,KAAmBM,EAAK,SAAS,KAAG;AAC/C,UAAM,IAAIE,EAAWF,CAAI;AACzB,IAAAK,KAASF,EAAM,CAAC,KAAKH,EAAK,SAAS,IAAI,IAAI,IAC3CG,EAAM,OAAO,GAAG,CAAC,GACjBH,EAAK,OAAO,GAAG,CAAC,GAChBC;AAAA,EACJ;AAEA,SAAO,EAAE,MAAM,KAAK,UAAUD,CAAI,GAAG,SAAAC,EAAA;AACzC;AAYO,SAASO,EAAaC,GAAiD;AAC1E,MAAIC;AACJ,SAAO,MAAOA,MAAaD,EAAA,EAAQ,QAAQ,MAAM;AAAE,IAAAC,IAAW;AAAA,EAAW,CAAC;AAC9E;AClFO,SAASC,EAAWC,GAAkC;AACzD,SAAO,KAAK,UAAU;AAAA,IAClB,MAAM;AAAA,IACN,YAAW,oBAAI,KAAA,GAAO,YAAA;AAAA,IACtB,YAAYA,EAAO;AAAA,IACnB,QAAAA;AAAA,EAAA,CACH;AACL;AAMO,SAASC,EAAaC,GAAwD;AACjF,SAAO;AAAA,IACH,gBAAgB;AAAA,IAChB,GAAIA,IAAa,EAAE,aAAaA,GAAY,eAAiB,UAAUA,CAAU,OAAO,CAAA;AAAA,EAAC;AAEjG;AAIO,MAAMC,IAAmB;"}
@@ -0,0 +1,2 @@
1
+ "use strict";const l=require("./telemetry-CrU7i1Jc.cjs"),s="telemetry_failed_events";function a(e){if(e.status!=="hit")return[];try{const n=JSON.parse(e.value);return Array.isArray(n)?n:[]}catch{return[]}}const u=500,h=1e6,E=e=>typeof TextEncoder<"u"?new TextEncoder().encode(e).length:e.length;function y(e,n){const t=[...e,...n];let r=0;for(;t.length>u;)t.splice(l.evictIndex(t),1),r++;const o=t.map(i=>E(JSON.stringify(i)));let c=o.reduce((i,d)=>i+d,0)+Math.max(t.length-1,0)+2;for(;c>h&&t.length>0;){const i=l.evictIndex(t);c-=o[i]+(t.length>1?1:0),o.splice(i,1),t.splice(i,1),r++}return{json:JSON.stringify(t),dropped:r}}function p(e){let n;return()=>n??=e().finally(()=>{n=void 0})}function g(e){return JSON.stringify({type:"telemetry_batch",timestamp:new Date().toISOString(),batch_size:e.length,events:e})}function _(e){return{"Content-Type":"application/json",...e?{"X-API-Key":e,Authorization:`Bearer ${e}`}:{}}}const f="https://your.telemetry.endpoint/telemetry";exports.DEFAULT_ENDPOINT=f;exports.FAILED_EVENTS_KEY=s;exports.buildBatch=g;exports.buildHeaders=_;exports.decodeFailed=a;exports.encodeFailed=y;exports.guardedDrain=p;
2
+ //# sourceMappingURL=batch-DNu8Xr9T.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-DNu8Xr9T.cjs","sources":["../src/adapters/failedEvents.ts","../src/adapters/batch.ts"],"sourcesContent":["import type { StoreRead } from \"../core/store\";\nimport { evictIndex, type TelemetryEvent } from \"../core/telemetry\";\n\n// The offline queue's shared, platform-agnostic half (#89). Both senders keep failed\n// batches under one key; only the Store underneath them differs, so the decoding rules\n// live here once and stay in lockstep.\n\nexport const FAILED_EVENTS_KEY = \"telemetry_failed_events\";\n\n/**\n * Decode a stored batch.\n *\n * The Store port never throws, and neither does this. An unavailable store, a key that\n * was never written, a half-written payload and a non-array JSON value all mean the\n * same thing to a caller — nothing replayable — so they all return `[]`. Before the\n * port, this was a bare `JSON.parse(... || \"[]\")` that threw straight through\n * `replayFailed()` on any corrupt payload and took startup with it.\n */\nexport function decodeFailed(read: StoreRead): TelemetryEvent[] {\n if (read.status !== \"hit\") return [];\n try {\n const parsed = JSON.parse(read.value);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/**\n * The offline store's cap (§9.4). Real numbers, not chosen ones: Android caps AsyncStorage\n * at 6 MB for the whole app and web `localStorage` is the *host app's* ~5 MB — an\n * append-only telemetry queue inside either is a slow eviction of the consumer's own data.\n */\nexport const STORE_MAX_EVENTS = 500;\nexport const STORE_MAX_BYTES = 1_000_000;\n\n/** UTF-8 length where the runtime offers it. RN (Hermes) and every browser do; be safe anyway. */\nconst byteLength = (s: string): number =>\n typeof TextEncoder !== \"undefined\" ? new TextEncoder().encode(s).length : s.length;\n\n/**\n * Encode the queue after appending `incoming`, oldest first, capped per §9.4 and\n * reporting how many rows the cap cost.\n *\n * The caller books the count as `sdk.drop_reason = \"store_full\"`; returning it rather\n * than counting in here keeps this module free of the Telemetry instance it would\n * otherwise need a handle on.\n */\nexport function encodeFailed(\n existing: TelemetryEvent[],\n incoming: TelemetryEvent[],\n): { json: string; dropped: number } {\n const kept = [...existing, ...incoming];\n let dropped = 0;\n\n while (kept.length > STORE_MAX_EVENTS) { kept.splice(evictIndex(kept), 1); dropped++; }\n\n // Sized once per event, not once per eviction: a 500-event backlog of 100 KiB events\n // (the collector's per-event ceiling) would otherwise re-stringify ~50 MB per drop.\n // 2 for the brackets, 1 per separating comma.\n const sizes = kept.map(e => byteLength(JSON.stringify(e)));\n let total = sizes.reduce((a, b) => a + b, 0) + Math.max(kept.length - 1, 0) + 2;\n while (total > STORE_MAX_BYTES && kept.length > 0) {\n const i = evictIndex(kept);\n total -= sizes[i] + (kept.length > 1 ? 1 : 0); // no separating comma to reclaim on the last row\n sizes.splice(i, 1);\n kept.splice(i, 1);\n dropped++;\n }\n\n return { json: JSON.stringify(kept), dropped };\n}\n\n/**\n * One drain per sender, however many callers there are (#113).\n *\n * `takeFailed()` clears the key before the send is attempted, so a *single* drain can\n * never double-send. Two concurrent drains can: both read the payload before either\n * removes it, and the recovered batch goes out twice — worst exactly when the network\n * was bad, which is when the data mattered. Returning the in-flight promise makes the\n * second caller a no-op that still awaits the first, and the guard is per-sender rather\n * than per-module so two `Telemetry` instances in one process keep their own.\n */\nexport function guardedDrain(drain: () => Promise<void>): () => Promise<void> {\n let inFlight: Promise<void> | undefined;\n return () => (inFlight ??= drain().finally(() => { inFlight = undefined; }));\n}\n","import type { TelemetryEvent } from \"../core/telemetry\";\n\n// v3 wire envelope. Shared by both senders so the web and native POST bodies\n// stay byte-identical to the EdgeRum telemetry_batch contract.\nexport function buildBatch(events: TelemetryEvent[]): string {\n return JSON.stringify({\n type: \"telemetry_batch\",\n timestamp: new Date().toISOString(),\n batch_size: events.length,\n events,\n });\n}\n\n// Auth (#90, contract §11.1). The collector's credentialFromRequest reads Authorization under\n// AUTH_MODE=jwt and X-API-Key otherwise — exactly one, never both. Sending both, always, with\n// the same value makes one build work in the shared and the segmented (bank / on-prem)\n// topologies with no mode flag. Do not sniff the credential's shape to pick a header.\nexport function buildHeaders(credential: string | undefined): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n ...(credential ? { \"X-API-Key\": credential, \"Authorization\": `Bearer ${credential}` } : {}),\n };\n}\n\n// Placeholder host — always pass a real `endpoint`. The path is the collector's real one:\n// it terminates POST /telemetry (contract §11.1). Shared so the two senders cannot drift.\nexport const DEFAULT_ENDPOINT = \"https://your.telemetry.endpoint/telemetry\";\n"],"names":["FAILED_EVENTS_KEY","decodeFailed","read","parsed","STORE_MAX_EVENTS","STORE_MAX_BYTES","byteLength","s","encodeFailed","existing","incoming","kept","dropped","evictIndex","sizes","e","total","a","b","guardedDrain","drain","inFlight","buildBatch","events","buildHeaders","credential","DEFAULT_ENDPOINT"],"mappings":"yDAOaA,EAAoB,0BAW1B,SAASC,EAAaC,EAAmC,CAC5D,GAAIA,EAAK,SAAW,MAAO,MAAO,CAAA,EAClC,GAAI,CACA,MAAMC,EAAS,KAAK,MAAMD,EAAK,KAAK,EACpC,OAAO,MAAM,QAAQC,CAAM,EAAIA,EAAS,CAAA,CAC5C,MAAQ,CACJ,MAAO,CAAA,CACX,CACJ,CAOO,MAAMC,EAAmB,IACnBC,EAAkB,IAGzBC,EAAcC,GAChB,OAAO,YAAgB,IAAc,IAAI,YAAA,EAAc,OAAOA,CAAC,EAAE,OAASA,EAAE,OAUzE,SAASC,EACZC,EACAC,EACiC,CACjC,MAAMC,EAAO,CAAC,GAAGF,EAAU,GAAGC,CAAQ,EACtC,IAAIE,EAAU,EAEd,KAAOD,EAAK,OAASP,GAAoBO,EAAK,OAAOE,EAAAA,WAAWF,CAAI,EAAG,CAAC,EAAGC,IAK3E,MAAME,EAAQH,EAAK,IAAII,GAAKT,EAAW,KAAK,UAAUS,CAAC,CAAC,CAAC,EACzD,IAAIC,EAAQF,EAAM,OAAO,CAACG,EAAGC,IAAMD,EAAIC,EAAG,CAAC,EAAI,KAAK,IAAIP,EAAK,OAAS,EAAG,CAAC,EAAI,EAC9E,KAAOK,EAAQX,GAAmBM,EAAK,OAAS,GAAG,CAC/C,MAAM,EAAIE,EAAAA,WAAWF,CAAI,EACzBK,GAASF,EAAM,CAAC,GAAKH,EAAK,OAAS,EAAI,EAAI,GAC3CG,EAAM,OAAO,EAAG,CAAC,EACjBH,EAAK,OAAO,EAAG,CAAC,EAChBC,GACJ,CAEA,MAAO,CAAE,KAAM,KAAK,UAAUD,CAAI,EAAG,QAAAC,CAAA,CACzC,CAYO,SAASO,EAAaC,EAAiD,CAC1E,IAAIC,EACJ,MAAO,IAAOA,IAAaD,EAAA,EAAQ,QAAQ,IAAM,CAAEC,EAAW,MAAW,CAAC,CAC9E,CClFO,SAASC,EAAWC,EAAkC,CACzD,OAAO,KAAK,UAAU,CAClB,KAAM,kBACN,UAAW,IAAI,KAAA,EAAO,YAAA,EACtB,WAAYA,EAAO,OACnB,OAAAA,CAAA,CACH,CACL,CAMO,SAASC,EAAaC,EAAwD,CACjF,MAAO,CACH,eAAgB,mBAChB,GAAIA,EAAa,CAAE,YAAaA,EAAY,cAAiB,UAAUA,CAAU,IAAO,CAAA,CAAC,CAEjG,CAIO,MAAMC,EAAmB"}
@@ -0,0 +1,4 @@
1
+ "use strict";const d=require("./memoryStore-BIGZmmfD.cjs"),m=255,p=1e3,y=2e3,E=200,u=`
2
+ … [truncated]`;function c(e,r,t=!1){if(e.length<=r)return e;let n=e.slice(0,r-u.length);if(t){const o=n.lastIndexOf(`
3
+ `);o>0&&(n=n.slice(0,o))}return n+u}function S(e){const r=e?.name;return typeof r=="string"&&r!==""?r:"Error"}function h(e,r){if(typeof e=="string"&&e!=="")return e;const t=e?.message;if(typeof t=="string"&&t!=="")return t;if(!(r==null||r===""))return String(r)}let f=!1;function A(){f||!d.isDev()||(f=!0,console.warn("[edge-telemetry] Error.stackTraceLimit is the engine default (10 frames on V8), which truncates crash stacks well before the SDK's 2000-char cap. Set `Error.stackTraceLimit = 50` in your app's entry file — the SDK will not set it for you."))}function g(e,r,t={}){const n={"error.type":c(S(r),m),"error.source":e},o=h(r,t.fallbackMessage);o!==void 0&&(n["error.message"]=c(o,p));const i=r?.stack;return typeof i=="string"&&i!==""&&(n["error.stacktrace"]=c(i,y,!0),A()),t.fatal!==void 0&&(n["error.fatal"]=t.fatal),n}function w(e,r=console){const t=r.error.bind(r),n=r.warn.bind(r);let o=!1;const i=(s,l)=>(...a)=>{if(!o){o=!0;try{s(a.map(String).join(" "))}finally{o=!1}}l(...a)};return r.error=i(s=>e.captureError(s,void 0,"console"),t),r.warn=i(s=>e.addBreadcrumb("console.warn",{message:c(s,E)}),n),()=>{r.error=t,r.warn=n}}exports.buildErrorAttributes=g;exports.captureConsole=w;
4
+ //# sourceMappingURL=crashCapture-BOJ8nSAZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashCapture-BOJ8nSAZ.cjs","sources":["../src/adapters/crashCapture.ts"],"sourcesContent":["/**\n * §4.7 — the error surface. Two event names, not one: `app.crash` is unhandled /\n * fatal-ish, `app.error` is handled or non-fatal, so\n * `COUNT(event_name='app.crash') / sessions` is a crash-free rate with no `WHERE`\n * clause anyone can forget. All five v3 `crash.*` keys are retired for dotted\n * `error.*`, and both explicit wire nulls go with them. #100\n */\n\nimport { isDev } from \"../core/debug\";\n\n/** `error.source` — a full re-cut of v3's `crash.cause`, not a rename. 5 values. */\nexport type ErrorSource =\n | \"global_handler\"\n | \"unhandled_rejection\"\n | \"cross_origin\" // web only: window.onerror with error === undefined\n | \"console\" // now on app.error\n | \"reported\"; // captureError()\n\n// §4.7 caps. The stacktrace's 2000 is a tuning knob, not a contractual constant —\n// it may be tight for Hermes, where the bytecode offset is the whole signal.\nconst TYPE_MAX = 255;\nconst MESSAGE_MAX = 1000;\nconst STACK_MAX = 2000;\n/** Breadcrumb text is not an error payload — 20 of these ride every `app.crash`. */\nconst CRUMB_MAX = 200;\n\n/** Marked inline: no key, countable with a `LIKE`, zero schema. */\nconst TRUNCATED = \"\\n… [truncated]\";\n\n/**\n * Drops the tail, never the head — the top frames *are* the grouping input.\n *\n * ⚠ `frameBoundary` is not cosmetic. On Hermes `line` is a constant 1 and the bytecode\n * offset carries the location, so a cut mid-frame turns `at p (address at bundle:1:132161)`\n * into `…bundle:1:13` — which resolves to a **different, wrong** place rather than failing.\n */\nfunction cap(value: string, max: number, frameBoundary = false): string {\n if (value.length <= max) return value;\n let cut = value.slice(0, max - TRUNCATED.length);\n if (frameBoundary) {\n const nl = cut.lastIndexOf(\"\\n\");\n if (nl > 0) cut = cut.slice(0, nl);\n }\n return cut + TRUNCATED;\n}\n\n/**\n * `error.type` is read from `error.name` **only, never `constructor.name`**: RN production\n * bundles minify class names, so `class PaymentError extends Error {}` would report as `\"a\"`\n * — not merely unreadable but *unstable across builds*, refragmenting grouping on every\n * deploy. `error.name` is a string literal in the author's source. Un-named classes report\n * `\"Error\"`: low cardinality, but honest.\n */\nexport function errorType(error: unknown): string {\n const name = (error as any)?.name;\n return typeof name === \"string\" && name !== \"\" ? name : \"Error\";\n}\n\n/**\n * Half of real `catch` blocks receive a string or an axios rejection object, not an Error, so\n * `fallbackMessage` is consulted **only** when the thrown value carries nothing usable.\n */\nfunction errorMessage(error: unknown, fallbackMessage?: unknown): string | undefined {\n if (typeof error === \"string\" && error !== \"\") return error;\n const m = (error as any)?.message;\n if (typeof m === \"string\" && m !== \"\") return m;\n if (fallbackMessage === undefined || fallbackMessage === null || fallbackMessage === \"\") return undefined;\n return String(fallbackMessage);\n}\n\n/**\n * §4.8's second consumer wiring step, said **once per process and only in dev**.\n *\n * RN 0.81.4 sets `Error.stackTraceLimit` nowhere, so V8's default of **10 frames** governs —\n * not the 2000-char cap, which holds ~26. Ten frames of an `unhandledrejection` can be\n * entirely library internals.\n *\n * ⚠ The SDK **never assigns it**. Raising it globally is an invisible mutation of the\n * consumer's runtime that makes every `new Error()` in their app more expensive and\n * unattributable to us — so this is an advisory, and the consumer's own line of code.\n *\n * Not behind `debug()`: a consumer who has not wired this up is precisely a consumer who\n * has not set `debug: true`. Same reasoning as §6.4's dev throw, one rung quieter — and the\n * one carve-out from the no-bare-console rule, recorded as such in CLAUDE.md.\n */\nlet advised = false;\nfunction adviseStackTraceLimit(): void {\n // The flag is set only when the advice is actually *said*: burning it on a call made\n // before `__DEV__` is defined would silence a dev app for the rest of the process.\n if (advised || !isDev()) return;\n advised = true;\n console.warn(\n \"[edge-telemetry] Error.stackTraceLimit is the engine default (10 frames on V8), which \" +\n \"truncates crash stacks well before the SDK's 2000-char cap. Set `Error.stackTraceLimit = 50` \" +\n \"in your app's entry file — the SDK will not set it for you.\",\n );\n}\n\n/**\n * The `error.*` block for both event names. `error.handled` does not exist — the event name\n * carries that bit, and carrying both is a denormalization that can disagree. `error.fatal`\n * is passed only by the native build (§4.7: on web nothing is fatal).\n */\nexport function buildErrorAttributes(\n source: ErrorSource,\n error: unknown,\n opts: { fallbackMessage?: unknown; fatal?: boolean } = {},\n): Record<string, any> {\n const attrs: Record<string, any> = {\n \"error.type\": cap(errorType(error), TYPE_MAX),\n \"error.source\": source,\n };\n\n const message = errorMessage(error, opts.fallbackMessage);\n if (message !== undefined) attrs[\"error.message\"] = cap(message, MESSAGE_MAX);\n\n const stack = (error as any)?.stack;\n if (typeof stack === \"string\" && stack !== \"\") {\n attrs[\"error.stacktrace\"] = cap(stack, STACK_MAX, true);\n // Here rather than at init: this is the one chokepoint every captured stack passes\n // through, so the advice arrives when a dev has a real, already-truncated stack in front\n // of them — and #23's \"construct → log → flush is silent by default\" stays intact.\n adviseStackTraceLimit();\n }\n\n if (opts.fatal !== undefined) attrs[\"error.fatal\"] = opts.fatal;\n return attrs;\n}\n\n/** What `captureConsole` needs of a `Telemetry` — structural. */\ntype ErrorSink = {\n captureError(error: unknown, context?: Record<string, any>, source?: ErrorSource): unknown;\n addBreadcrumb(name: string, data?: Record<string, any>): void;\n};\n\n/**\n * Patch console.error → `app.error` (source `console`) and console.warn → a **breadcrumb**.\n * `ConsoleWarn` is deleted outright: React's own dev-mode warnings were the dominant\n * contributor to v3's crash count, which is what made \"is my app crashing more?\"\n * unanswerable. Opt-*in* now — `captureConsole` defaults off (§4.7).\n *\n * Returns a restore fn. A reentrancy guard keeps the SDK's own console writes during\n * logging from re-capturing.\n */\nexport function captureConsole(\n telemetry: ErrorSink,\n target: Pick<Console, \"error\" | \"warn\"> = console,\n): () => void {\n const origError = target.error.bind(target);\n const origWarn = target.warn.bind(target);\n let inside = false;\n\n const guarded = (emit: (text: string) => void, orig: (...a: any[]) => void) =>\n (...args: any[]) => {\n if (!inside) {\n inside = true;\n try {\n emit(args.map(String).join(\" \"));\n } finally {\n inside = false;\n }\n }\n orig(...args);\n };\n\n // Through captureError, not log(), so the `error.fatal` platform rule stays in one place.\n target.error = guarded(\n (text) => telemetry.captureError(text, undefined, \"console\"),\n origError,\n );\n target.warn = guarded(\n // Capped here, not at the ring: 20 uncapped React warnings would put kilobytes of\n // `error.breadcrumbs` on every `app.crash`, which is the budget this split exists to protect.\n (text) => telemetry.addBreadcrumb(\"console.warn\", { message: cap(text, CRUMB_MAX) }),\n origWarn,\n );\n\n return () => { target.error = origError; target.warn = origWarn; };\n}\n"],"names":["TYPE_MAX","MESSAGE_MAX","STACK_MAX","CRUMB_MAX","TRUNCATED","cap","value","max","frameBoundary","cut","nl","errorType","error","name","errorMessage","fallbackMessage","m","advised","adviseStackTraceLimit","isDev","buildErrorAttributes","source","opts","attrs","message","stack","captureConsole","telemetry","target","origError","origWarn","inside","guarded","emit","orig","args","text"],"mappings":"2DAoBMA,EAAW,IACXC,EAAc,IACdC,EAAY,IAEZC,EAAY,IAGZC,EAAY;AAAA,eASlB,SAASC,EAAIC,EAAeC,EAAaC,EAAgB,GAAe,CACtE,GAAIF,EAAM,QAAUC,EAAK,OAAOD,EAChC,IAAIG,EAAMH,EAAM,MAAM,EAAGC,EAAMH,EAAU,MAAM,EAC/C,GAAII,EAAe,CACjB,MAAME,EAAKD,EAAI,YAAY;AAAA,CAAI,EAC3BC,EAAK,IAAGD,EAAMA,EAAI,MAAM,EAAGC,CAAE,EACnC,CACA,OAAOD,EAAML,CACf,CASO,SAASO,EAAUC,EAAwB,CAChD,MAAMC,EAAQD,GAAe,KAC7B,OAAO,OAAOC,GAAS,UAAYA,IAAS,GAAKA,EAAO,OAC1D,CAMA,SAASC,EAAaF,EAAgBG,EAA+C,CACnF,GAAI,OAAOH,GAAU,UAAYA,IAAU,GAAI,OAAOA,EACtD,MAAMI,EAAKJ,GAAe,QAC1B,GAAI,OAAOI,GAAM,UAAYA,IAAM,GAAI,OAAOA,EAC9C,GAAI,EAAiCD,GAAoB,MAAQA,IAAoB,IACrF,OAAO,OAAOA,CAAe,CAC/B,CAiBA,IAAIE,EAAU,GACd,SAASC,GAA8B,CAGjCD,GAAW,CAACE,EAAAA,UAChBF,EAAU,GACV,QAAQ,KACN,gPAAA,EAIJ,CAOO,SAASG,EACdC,EACAT,EACAU,EAAuD,CAAA,EAClC,CACrB,MAAMC,EAA6B,CACjC,aAAclB,EAAIM,EAAUC,CAAK,EAAGZ,CAAQ,EAC5C,eAAgBqB,CAAA,EAGZG,EAAUV,EAAaF,EAAOU,EAAK,eAAe,EACpDE,IAAY,SAAWD,EAAM,eAAe,EAAIlB,EAAImB,EAASvB,CAAW,GAE5E,MAAMwB,EAASb,GAAe,MAC9B,OAAI,OAAOa,GAAU,UAAYA,IAAU,KACzCF,EAAM,kBAAkB,EAAIlB,EAAIoB,EAAOvB,EAAW,EAAI,EAItDgB,EAAA,GAGEI,EAAK,QAAU,SAAWC,EAAM,aAAa,EAAID,EAAK,OACnDC,CACT,CAiBO,SAASG,EACdC,EACAC,EAA0C,QAC9B,CACZ,MAAMC,EAAYD,EAAO,MAAM,KAAKA,CAAM,EACpCE,EAAWF,EAAO,KAAK,KAAKA,CAAM,EACxC,IAAIG,EAAS,GAEb,MAAMC,EAAU,CAACC,EAA8BC,IAC7C,IAAIC,IAAgB,CAClB,GAAI,CAACJ,EAAQ,CACXA,EAAS,GACT,GAAI,CACFE,EAAKE,EAAK,IAAI,MAAM,EAAE,KAAK,GAAG,CAAC,CACjC,QAAA,CACEJ,EAAS,EACX,CACF,CACAG,EAAK,GAAGC,CAAI,CACd,EAGF,OAAAP,EAAO,MAAQI,EACZI,GAAST,EAAU,aAAaS,EAAM,OAAW,SAAS,EAC3DP,CAAA,EAEFD,EAAO,KAAOI,EAGXI,GAAST,EAAU,cAAc,eAAgB,CAAE,QAAStB,EAAI+B,EAAMjC,CAAS,EAAG,EACnF2B,CAAA,EAGK,IAAM,CAAEF,EAAO,MAAQC,EAAWD,EAAO,KAAOE,CAAU,CACnE"}
@@ -0,0 +1,70 @@
1
+ import { i as d } from "./memoryStore-F5I-GQKM.js";
2
+ const m = 255, p = 1e3, y = 2e3, E = 200, f = `
3
+ … [truncated]`;
4
+ function c(e, r, n = !1) {
5
+ if (e.length <= r) return e;
6
+ let t = e.slice(0, r - f.length);
7
+ if (n) {
8
+ const o = t.lastIndexOf(`
9
+ `);
10
+ o > 0 && (t = t.slice(0, o));
11
+ }
12
+ return t + f;
13
+ }
14
+ function h(e) {
15
+ const r = e?.name;
16
+ return typeof r == "string" && r !== "" ? r : "Error";
17
+ }
18
+ function S(e, r) {
19
+ if (typeof e == "string" && e !== "") return e;
20
+ const n = e?.message;
21
+ if (typeof n == "string" && n !== "") return n;
22
+ if (!(r == null || r === ""))
23
+ return String(r);
24
+ }
25
+ let u = !1;
26
+ function g() {
27
+ u || !d() || (u = !0, console.warn(
28
+ "[edge-telemetry] Error.stackTraceLimit is the engine default (10 frames on V8), which truncates crash stacks well before the SDK's 2000-char cap. Set `Error.stackTraceLimit = 50` in your app's entry file — the SDK will not set it for you."
29
+ ));
30
+ }
31
+ function A(e, r, n = {}) {
32
+ const t = {
33
+ "error.type": c(h(r), m),
34
+ "error.source": e
35
+ }, o = S(r, n.fallbackMessage);
36
+ o !== void 0 && (t["error.message"] = c(o, p));
37
+ const i = r?.stack;
38
+ return typeof i == "string" && i !== "" && (t["error.stacktrace"] = c(i, y, !0), g()), n.fatal !== void 0 && (t["error.fatal"] = n.fatal), t;
39
+ }
40
+ function T(e, r = console) {
41
+ const n = r.error.bind(r), t = r.warn.bind(r);
42
+ let o = !1;
43
+ const i = (s, l) => (...a) => {
44
+ if (!o) {
45
+ o = !0;
46
+ try {
47
+ s(a.map(String).join(" "));
48
+ } finally {
49
+ o = !1;
50
+ }
51
+ }
52
+ l(...a);
53
+ };
54
+ return r.error = i(
55
+ (s) => e.captureError(s, void 0, "console"),
56
+ n
57
+ ), r.warn = i(
58
+ // Capped here, not at the ring: 20 uncapped React warnings would put kilobytes of
59
+ // `error.breadcrumbs` on every `app.crash`, which is the budget this split exists to protect.
60
+ (s) => e.addBreadcrumb("console.warn", { message: c(s, E) }),
61
+ t
62
+ ), () => {
63
+ r.error = n, r.warn = t;
64
+ };
65
+ }
66
+ export {
67
+ A as b,
68
+ T as c
69
+ };
70
+ //# sourceMappingURL=crashCapture-BW8WuyaU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashCapture-BW8WuyaU.js","sources":["../src/adapters/crashCapture.ts"],"sourcesContent":["/**\n * §4.7 — the error surface. Two event names, not one: `app.crash` is unhandled /\n * fatal-ish, `app.error` is handled or non-fatal, so\n * `COUNT(event_name='app.crash') / sessions` is a crash-free rate with no `WHERE`\n * clause anyone can forget. All five v3 `crash.*` keys are retired for dotted\n * `error.*`, and both explicit wire nulls go with them. #100\n */\n\nimport { isDev } from \"../core/debug\";\n\n/** `error.source` — a full re-cut of v3's `crash.cause`, not a rename. 5 values. */\nexport type ErrorSource =\n | \"global_handler\"\n | \"unhandled_rejection\"\n | \"cross_origin\" // web only: window.onerror with error === undefined\n | \"console\" // now on app.error\n | \"reported\"; // captureError()\n\n// §4.7 caps. The stacktrace's 2000 is a tuning knob, not a contractual constant —\n// it may be tight for Hermes, where the bytecode offset is the whole signal.\nconst TYPE_MAX = 255;\nconst MESSAGE_MAX = 1000;\nconst STACK_MAX = 2000;\n/** Breadcrumb text is not an error payload — 20 of these ride every `app.crash`. */\nconst CRUMB_MAX = 200;\n\n/** Marked inline: no key, countable with a `LIKE`, zero schema. */\nconst TRUNCATED = \"\\n… [truncated]\";\n\n/**\n * Drops the tail, never the head — the top frames *are* the grouping input.\n *\n * ⚠ `frameBoundary` is not cosmetic. On Hermes `line` is a constant 1 and the bytecode\n * offset carries the location, so a cut mid-frame turns `at p (address at bundle:1:132161)`\n * into `…bundle:1:13` — which resolves to a **different, wrong** place rather than failing.\n */\nfunction cap(value: string, max: number, frameBoundary = false): string {\n if (value.length <= max) return value;\n let cut = value.slice(0, max - TRUNCATED.length);\n if (frameBoundary) {\n const nl = cut.lastIndexOf(\"\\n\");\n if (nl > 0) cut = cut.slice(0, nl);\n }\n return cut + TRUNCATED;\n}\n\n/**\n * `error.type` is read from `error.name` **only, never `constructor.name`**: RN production\n * bundles minify class names, so `class PaymentError extends Error {}` would report as `\"a\"`\n * — not merely unreadable but *unstable across builds*, refragmenting grouping on every\n * deploy. `error.name` is a string literal in the author's source. Un-named classes report\n * `\"Error\"`: low cardinality, but honest.\n */\nexport function errorType(error: unknown): string {\n const name = (error as any)?.name;\n return typeof name === \"string\" && name !== \"\" ? name : \"Error\";\n}\n\n/**\n * Half of real `catch` blocks receive a string or an axios rejection object, not an Error, so\n * `fallbackMessage` is consulted **only** when the thrown value carries nothing usable.\n */\nfunction errorMessage(error: unknown, fallbackMessage?: unknown): string | undefined {\n if (typeof error === \"string\" && error !== \"\") return error;\n const m = (error as any)?.message;\n if (typeof m === \"string\" && m !== \"\") return m;\n if (fallbackMessage === undefined || fallbackMessage === null || fallbackMessage === \"\") return undefined;\n return String(fallbackMessage);\n}\n\n/**\n * §4.8's second consumer wiring step, said **once per process and only in dev**.\n *\n * RN 0.81.4 sets `Error.stackTraceLimit` nowhere, so V8's default of **10 frames** governs —\n * not the 2000-char cap, which holds ~26. Ten frames of an `unhandledrejection` can be\n * entirely library internals.\n *\n * ⚠ The SDK **never assigns it**. Raising it globally is an invisible mutation of the\n * consumer's runtime that makes every `new Error()` in their app more expensive and\n * unattributable to us — so this is an advisory, and the consumer's own line of code.\n *\n * Not behind `debug()`: a consumer who has not wired this up is precisely a consumer who\n * has not set `debug: true`. Same reasoning as §6.4's dev throw, one rung quieter — and the\n * one carve-out from the no-bare-console rule, recorded as such in CLAUDE.md.\n */\nlet advised = false;\nfunction adviseStackTraceLimit(): void {\n // The flag is set only when the advice is actually *said*: burning it on a call made\n // before `__DEV__` is defined would silence a dev app for the rest of the process.\n if (advised || !isDev()) return;\n advised = true;\n console.warn(\n \"[edge-telemetry] Error.stackTraceLimit is the engine default (10 frames on V8), which \" +\n \"truncates crash stacks well before the SDK's 2000-char cap. Set `Error.stackTraceLimit = 50` \" +\n \"in your app's entry file — the SDK will not set it for you.\",\n );\n}\n\n/**\n * The `error.*` block for both event names. `error.handled` does not exist — the event name\n * carries that bit, and carrying both is a denormalization that can disagree. `error.fatal`\n * is passed only by the native build (§4.7: on web nothing is fatal).\n */\nexport function buildErrorAttributes(\n source: ErrorSource,\n error: unknown,\n opts: { fallbackMessage?: unknown; fatal?: boolean } = {},\n): Record<string, any> {\n const attrs: Record<string, any> = {\n \"error.type\": cap(errorType(error), TYPE_MAX),\n \"error.source\": source,\n };\n\n const message = errorMessage(error, opts.fallbackMessage);\n if (message !== undefined) attrs[\"error.message\"] = cap(message, MESSAGE_MAX);\n\n const stack = (error as any)?.stack;\n if (typeof stack === \"string\" && stack !== \"\") {\n attrs[\"error.stacktrace\"] = cap(stack, STACK_MAX, true);\n // Here rather than at init: this is the one chokepoint every captured stack passes\n // through, so the advice arrives when a dev has a real, already-truncated stack in front\n // of them — and #23's \"construct → log → flush is silent by default\" stays intact.\n adviseStackTraceLimit();\n }\n\n if (opts.fatal !== undefined) attrs[\"error.fatal\"] = opts.fatal;\n return attrs;\n}\n\n/** What `captureConsole` needs of a `Telemetry` — structural. */\ntype ErrorSink = {\n captureError(error: unknown, context?: Record<string, any>, source?: ErrorSource): unknown;\n addBreadcrumb(name: string, data?: Record<string, any>): void;\n};\n\n/**\n * Patch console.error → `app.error` (source `console`) and console.warn → a **breadcrumb**.\n * `ConsoleWarn` is deleted outright: React's own dev-mode warnings were the dominant\n * contributor to v3's crash count, which is what made \"is my app crashing more?\"\n * unanswerable. Opt-*in* now — `captureConsole` defaults off (§4.7).\n *\n * Returns a restore fn. A reentrancy guard keeps the SDK's own console writes during\n * logging from re-capturing.\n */\nexport function captureConsole(\n telemetry: ErrorSink,\n target: Pick<Console, \"error\" | \"warn\"> = console,\n): () => void {\n const origError = target.error.bind(target);\n const origWarn = target.warn.bind(target);\n let inside = false;\n\n const guarded = (emit: (text: string) => void, orig: (...a: any[]) => void) =>\n (...args: any[]) => {\n if (!inside) {\n inside = true;\n try {\n emit(args.map(String).join(\" \"));\n } finally {\n inside = false;\n }\n }\n orig(...args);\n };\n\n // Through captureError, not log(), so the `error.fatal` platform rule stays in one place.\n target.error = guarded(\n (text) => telemetry.captureError(text, undefined, \"console\"),\n origError,\n );\n target.warn = guarded(\n // Capped here, not at the ring: 20 uncapped React warnings would put kilobytes of\n // `error.breadcrumbs` on every `app.crash`, which is the budget this split exists to protect.\n (text) => telemetry.addBreadcrumb(\"console.warn\", { message: cap(text, CRUMB_MAX) }),\n origWarn,\n );\n\n return () => { target.error = origError; target.warn = origWarn; };\n}\n"],"names":["TYPE_MAX","MESSAGE_MAX","STACK_MAX","CRUMB_MAX","TRUNCATED","cap","value","max","frameBoundary","cut","nl","errorType","error","name","errorMessage","fallbackMessage","m","advised","adviseStackTraceLimit","isDev","buildErrorAttributes","source","opts","attrs","message","stack","captureConsole","telemetry","target","origError","origWarn","inside","guarded","emit","orig","args","text"],"mappings":";AAoBA,MAAMA,IAAW,KACXC,IAAc,KACdC,IAAY,KAEZC,IAAY,KAGZC,IAAY;AAAA;AASlB,SAASC,EAAIC,GAAeC,GAAaC,IAAgB,IAAe;AACtE,MAAIF,EAAM,UAAUC,EAAK,QAAOD;AAChC,MAAIG,IAAMH,EAAM,MAAM,GAAGC,IAAMH,EAAU,MAAM;AAC/C,MAAII,GAAe;AACjB,UAAME,IAAKD,EAAI,YAAY;AAAA,CAAI;AAC/B,IAAIC,IAAK,MAAGD,IAAMA,EAAI,MAAM,GAAGC,CAAE;AAAA,EACnC;AACA,SAAOD,IAAML;AACf;AASO,SAASO,EAAUC,GAAwB;AAChD,QAAMC,IAAQD,GAAe;AAC7B,SAAO,OAAOC,KAAS,YAAYA,MAAS,KAAKA,IAAO;AAC1D;AAMA,SAASC,EAAaF,GAAgBG,GAA+C;AACnF,MAAI,OAAOH,KAAU,YAAYA,MAAU,GAAI,QAAOA;AACtD,QAAMI,IAAKJ,GAAe;AAC1B,MAAI,OAAOI,KAAM,YAAYA,MAAM,GAAI,QAAOA;AAC9C,MAAI,EAAiCD,KAAoB,QAAQA,MAAoB;AACrF,WAAO,OAAOA,CAAe;AAC/B;AAiBA,IAAIE,IAAU;AACd,SAASC,IAA8B;AAGrC,EAAID,KAAW,CAACE,QAChBF,IAAU,IACV,QAAQ;AAAA,IACN;AAAA,EAAA;AAIJ;AAOO,SAASG,EACdC,GACAT,GACAU,IAAuD,CAAA,GAClC;AACrB,QAAMC,IAA6B;AAAA,IACjC,cAAclB,EAAIM,EAAUC,CAAK,GAAGZ,CAAQ;AAAA,IAC5C,gBAAgBqB;AAAA,EAAA,GAGZG,IAAUV,EAAaF,GAAOU,EAAK,eAAe;AACxD,EAAIE,MAAY,WAAWD,EAAM,eAAe,IAAIlB,EAAImB,GAASvB,CAAW;AAE5E,QAAMwB,IAASb,GAAe;AAC9B,SAAI,OAAOa,KAAU,YAAYA,MAAU,OACzCF,EAAM,kBAAkB,IAAIlB,EAAIoB,GAAOvB,GAAW,EAAI,GAItDgB,EAAA,IAGEI,EAAK,UAAU,WAAWC,EAAM,aAAa,IAAID,EAAK,QACnDC;AACT;AAiBO,SAASG,EACdC,GACAC,IAA0C,SAC9B;AACZ,QAAMC,IAAYD,EAAO,MAAM,KAAKA,CAAM,GACpCE,IAAWF,EAAO,KAAK,KAAKA,CAAM;AACxC,MAAIG,IAAS;AAEb,QAAMC,IAAU,CAACC,GAA8BC,MAC7C,IAAIC,MAAgB;AAClB,QAAI,CAACJ,GAAQ;AACX,MAAAA,IAAS;AACT,UAAI;AACF,QAAAE,EAAKE,EAAK,IAAI,MAAM,EAAE,KAAK,GAAG,CAAC;AAAA,MACjC,UAAA;AACE,QAAAJ,IAAS;AAAA,MACX;AAAA,IACF;AACA,IAAAG,EAAK,GAAGC,CAAI;AAAA,EACd;AAGF,SAAAP,EAAO,QAAQI;AAAA,IACb,CAACI,MAAST,EAAU,aAAaS,GAAM,QAAW,SAAS;AAAA,IAC3DP;AAAA,EAAA,GAEFD,EAAO,OAAOI;AAAA;AAAA;AAAA,IAGZ,CAACI,MAAST,EAAU,cAAc,gBAAgB,EAAE,SAAStB,EAAI+B,GAAMjC,CAAS,GAAG;AAAA,IACnF2B;AAAA,EAAA,GAGK,MAAM;AAAE,IAAAF,EAAO,QAAQC,GAAWD,EAAO,OAAOE;AAAA,EAAU;AACnE;"}
@@ -0,0 +1,29 @@
1
+ import { b as t, c } from "./crashCapture-BW8WuyaU.js";
2
+ class p {
3
+ constructor(r) {
4
+ this.telemetry = r;
5
+ }
6
+ // Lockstep with native: JS errors and unhandled rejections become `app.crash`;
7
+ // console.error becomes `app.error` and console.warn a breadcrumb, both opt-in. §4.7, #100
8
+ attach(r = {}) {
9
+ const { captureConsole: s = !1 } = r;
10
+ return new Promise((a, l) => {
11
+ try {
12
+ window.onerror = (e, h, d, u, o) => {
13
+ const n = o ? "global_handler" : "cross_origin";
14
+ this.telemetry.log("app.crash", t(n, o, { fallbackMessage: e }));
15
+ }, window.onunhandledrejection = (e) => {
16
+ this.telemetry.log("app.crash", t("unhandled_rejection", e.reason, {
17
+ fallbackMessage: "Unhandled Promise Rejection"
18
+ }));
19
+ }, s && c(this.telemetry), a();
20
+ } catch (e) {
21
+ l(e);
22
+ }
23
+ });
24
+ }
25
+ }
26
+ export {
27
+ p as CrashHandler
28
+ };
29
+ //# sourceMappingURL=crashHandler.web-8F_k2veo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashHandler.web-8F_k2veo.js","sources":["../src/adapters/web/crashHandler.web.ts"],"sourcesContent":["import { Telemetry } from \"../../core/telemetry\";\nimport { buildErrorAttributes, captureConsole } from \"../crashCapture\";\n\nexport type CrashHandlerOptions = { captureConsole?: boolean };\n\nexport class CrashHandler {\n constructor(private telemetry: Telemetry) { }\n\n // Lockstep with native: JS errors and unhandled rejections become `app.crash`;\n // console.error becomes `app.error` and console.warn a breadcrumb, both opt-in. §4.7, #100\n attach(options: CrashHandlerOptions = {}): Promise<void> {\n const { captureConsole: consoleEnabled = false } = options;\n return new Promise((resolve, reject) => {\n try {\n window.onerror = (msg, _url, _line, _col, error) => {\n // ⚠ `error === undefined` is the cross-origin instrumentation gap, not a\n // mystery Error: a bundle served from a CDN without CORS headers yields the\n // classic \"Script error.\" with no stack. Naming it beats collapsing it.\n const source = error ? \"global_handler\" : \"cross_origin\";\n // No `fatal` on web — nothing here is fatal, the page keeps running (§4.7).\n this.telemetry.log(\"app.crash\", buildErrorAttributes(source, error, { fallbackMessage: msg }));\n };\n\n window.onunhandledrejection = (event) => {\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"unhandled_rejection\", event.reason, {\n fallbackMessage: \"Unhandled Promise Rejection\",\n }));\n };\n\n if (consoleEnabled) captureConsole(this.telemetry);\n\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["CrashHandler","telemetry","options","consoleEnabled","resolve","reject","msg","_url","_line","_col","error","source","buildErrorAttributes","event","captureConsole"],"mappings":";AAKO,MAAMA,EAAa;AAAA,EACtB,YAAoBC,GAAsB;AAAtB,SAAA,YAAAA;AAAA,EAAwB;AAAA;AAAA;AAAA,EAI5C,OAAOC,IAA+B,IAAmB;AACrD,UAAM,EAAE,gBAAgBC,IAAiB,GAAA,IAAUD;AACnD,WAAO,IAAI,QAAQ,CAACE,GAASC,MAAW;AACpC,UAAI;AACA,eAAO,UAAU,CAACC,GAAKC,GAAMC,GAAOC,GAAMC,MAAU;AAIhD,gBAAMC,IAASD,IAAQ,mBAAmB;AAE1C,eAAK,UAAU,IAAI,aAAaE,EAAqBD,GAAQD,GAAO,EAAE,iBAAiBJ,EAAA,CAAK,CAAC;AAAA,QACjG,GAEA,OAAO,uBAAuB,CAACO,MAAU;AACrC,eAAK,UAAU,IAAI,aAAaD,EAAqB,uBAAuBC,EAAM,QAAQ;AAAA,YACtF,iBAAiB;AAAA,UAAA,CACpB,CAAC;AAAA,QACN,GAEIV,KAAgBW,EAAe,KAAK,SAAS,GAEjDV,EAAA;AAAA,MACJ,SAASM,GAAO;AACZ,QAAAL,EAAOK,CAAK;AAAA,MAChB;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./crashCapture-BOJ8nSAZ.cjs");class c{constructor(r){this.telemetry=r}attach(r={}){const{captureConsole:s=!1}=r;return new Promise((a,l)=>{try{window.onerror=(e,u,d,h,o)=>{const n=o?"global_handler":"cross_origin";this.telemetry.log("app.crash",t.buildErrorAttributes(n,o,{fallbackMessage:e}))},window.onunhandledrejection=e=>{this.telemetry.log("app.crash",t.buildErrorAttributes("unhandled_rejection",e.reason,{fallbackMessage:"Unhandled Promise Rejection"}))},s&&t.captureConsole(this.telemetry),a()}catch(e){l(e)}})}}exports.CrashHandler=c;
2
+ //# sourceMappingURL=crashHandler.web-CWmF56mJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashHandler.web-CWmF56mJ.cjs","sources":["../src/adapters/web/crashHandler.web.ts"],"sourcesContent":["import { Telemetry } from \"../../core/telemetry\";\nimport { buildErrorAttributes, captureConsole } from \"../crashCapture\";\n\nexport type CrashHandlerOptions = { captureConsole?: boolean };\n\nexport class CrashHandler {\n constructor(private telemetry: Telemetry) { }\n\n // Lockstep with native: JS errors and unhandled rejections become `app.crash`;\n // console.error becomes `app.error` and console.warn a breadcrumb, both opt-in. §4.7, #100\n attach(options: CrashHandlerOptions = {}): Promise<void> {\n const { captureConsole: consoleEnabled = false } = options;\n return new Promise((resolve, reject) => {\n try {\n window.onerror = (msg, _url, _line, _col, error) => {\n // ⚠ `error === undefined` is the cross-origin instrumentation gap, not a\n // mystery Error: a bundle served from a CDN without CORS headers yields the\n // classic \"Script error.\" with no stack. Naming it beats collapsing it.\n const source = error ? \"global_handler\" : \"cross_origin\";\n // No `fatal` on web — nothing here is fatal, the page keeps running (§4.7).\n this.telemetry.log(\"app.crash\", buildErrorAttributes(source, error, { fallbackMessage: msg }));\n };\n\n window.onunhandledrejection = (event) => {\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"unhandled_rejection\", event.reason, {\n fallbackMessage: \"Unhandled Promise Rejection\",\n }));\n };\n\n if (consoleEnabled) captureConsole(this.telemetry);\n\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["CrashHandler","telemetry","options","consoleEnabled","resolve","reject","msg","_url","_line","_col","error","source","buildErrorAttributes","event","captureConsole"],"mappings":"+HAKO,MAAMA,CAAa,CACtB,YAAoBC,EAAsB,CAAtB,KAAA,UAAAA,CAAwB,CAI5C,OAAOC,EAA+B,GAAmB,CACrD,KAAM,CAAE,eAAgBC,EAAiB,EAAA,EAAUD,EACnD,OAAO,IAAI,QAAQ,CAACE,EAASC,IAAW,CACpC,GAAI,CACA,OAAO,QAAU,CAACC,EAAKC,EAAMC,EAAOC,EAAMC,IAAU,CAIhD,MAAMC,EAASD,EAAQ,iBAAmB,eAE1C,KAAK,UAAU,IAAI,YAAaE,EAAAA,qBAAqBD,EAAQD,EAAO,CAAE,gBAAiBJ,CAAA,CAAK,CAAC,CACjG,EAEA,OAAO,qBAAwBO,GAAU,CACrC,KAAK,UAAU,IAAI,YAAaD,EAAAA,qBAAqB,sBAAuBC,EAAM,OAAQ,CACtF,gBAAiB,6BAAA,CACpB,CAAC,CACN,EAEIV,GAAgBW,EAAAA,eAAe,KAAK,SAAS,EAEjDV,EAAA,CACJ,OAASM,EAAO,CACZL,EAAOK,CAAK,CAChB,CACJ,CAAC,CACL,CACJ"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./crashCapture-BOJ8nSAZ.cjs");class d{constructor(l){this.telemetry=l}attach(l={}){const{captureConsole:o=!1}=l;return new Promise((s,i)=>{try{if(typeof ErrorUtils<"u"&&ErrorUtils.setGlobalHandler){const e=ErrorUtils.getGlobalHandler?.();ErrorUtils.setGlobalHandler((a,t)=>{this.telemetry.log("app.crash",n.buildErrorAttributes("global_handler",a,{fatal:!!t})),e&&e(a,t)})}const r=e=>{this.telemetry.log("app.crash",n.buildErrorAttributes("unhandled_rejection",e?.reason,{fallbackMessage:"Unhandled Promise Rejection",fatal:!1}))};globalThis.addEventListener?globalThis.addEventListener("unhandledrejection",r):require("promise/setimmediate/rejection-tracking").enable({allRejections:!0,onUnhandled:(a,t)=>r({reason:t})}),o&&n.captureConsole(this.telemetry),s()}catch(r){i(r)}})}}exports.CrashHandlerNative=d;
2
+ //# sourceMappingURL=crashHandlerNative.native-C2kSikDt.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashHandlerNative.native-C2kSikDt.cjs","sources":["../src/adapters/native/crashHandlerNative.native.ts"],"sourcesContent":["import { Telemetry } from \"../../core/telemetry\";\nimport { buildErrorAttributes, captureConsole } from \"../crashCapture\";\n\nexport type CrashHandlerOptions = { captureConsole?: boolean };\n\nexport class CrashHandlerNative {\n constructor(private telemetry: Telemetry) { }\n\n // JS errors and unhandled rejections become `app.crash`; console.error becomes\n // `app.error` and console.warn a breadcrumb, both opt-in (default off). §4.7, #100\n attach(options: CrashHandlerOptions = {}): Promise<void> {\n const { captureConsole: consoleEnabled = false } = options;\n return new Promise((resolve, reject) => {\n try {\n if (typeof ErrorUtils !== \"undefined\" && ErrorUtils.setGlobalHandler) {\n const defaultHandler = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: any, isFatal?: boolean) => {\n // `error.fatal` is native-only — the web build never passes it (§4.7).\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"global_handler\", error, {\n fatal: !!isFatal,\n }));\n if (defaultHandler) defaultHandler(error, isFatal); // keep RN red screen in dev\n });\n }\n\n const onRejection = (event: any) => {\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"unhandled_rejection\", event?.reason, {\n fallbackMessage: \"Unhandled Promise Rejection\",\n fatal: false,\n }));\n };\n\n if (globalThis.addEventListener) {\n globalThis.addEventListener(\"unhandledrejection\", onRejection);\n } else {\n const tracking = require(\"promise/setimmediate/rejection-tracking\");\n tracking.enable({\n allRejections: true,\n onUnhandled: (_id: any, error: any) =>\n onRejection({ reason: error }),\n });\n }\n\n if (consoleEnabled) captureConsole(this.telemetry);\n\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["CrashHandlerNative","telemetry","options","consoleEnabled","resolve","reject","defaultHandler","error","isFatal","buildErrorAttributes","onRejection","event","_id","captureConsole"],"mappings":"+HAKO,MAAMA,CAAmB,CAC5B,YAAoBC,EAAsB,CAAtB,KAAA,UAAAA,CAAwB,CAI5C,OAAOC,EAA+B,GAAmB,CACrD,KAAM,CAAE,eAAgBC,EAAiB,EAAA,EAAUD,EACnD,OAAO,IAAI,QAAQ,CAACE,EAASC,IAAW,CACpC,GAAI,CACA,GAAI,OAAO,WAAe,KAAe,WAAW,iBAAkB,CAClE,MAAMC,EAAiB,WAAW,mBAAA,EAClC,WAAW,iBAAiB,CAACC,EAAYC,IAAsB,CAE3D,KAAK,UAAU,IAAI,YAAaC,EAAAA,qBAAqB,iBAAkBF,EAAO,CAC1E,MAAO,CAAC,CAACC,CAAA,CACZ,CAAC,EACEF,GAAgBA,EAAeC,EAAOC,CAAO,CACrD,CAAC,CACL,CAEA,MAAME,EAAeC,GAAe,CAChC,KAAK,UAAU,IAAI,YAAaF,EAAAA,qBAAqB,sBAAuBE,GAAO,OAAQ,CACvF,gBAAiB,8BACjB,MAAO,EAAA,CACV,CAAC,CACN,EAEI,WAAW,iBACX,WAAW,iBAAiB,qBAAsBD,CAAW,EAE5C,QAAQ,yCAAyC,EACzD,OAAO,CACZ,cAAe,GACf,YAAa,CAACE,EAAUL,IACpBG,EAAY,CAAE,OAAQH,EAAO,CAAA,CACpC,EAGDJ,GAAgBU,EAAAA,eAAe,KAAK,SAAS,EAEjDT,EAAA,CACJ,OAASG,EAAO,CACZF,EAAOE,CAAK,CAChB,CACJ,CAAC,CACL,CACJ"}
@@ -0,0 +1,39 @@
1
+ import { b as n, c } from "./crashCapture-BW8WuyaU.js";
2
+ class f {
3
+ constructor(l) {
4
+ this.telemetry = l;
5
+ }
6
+ // JS errors and unhandled rejections become `app.crash`; console.error becomes
7
+ // `app.error` and console.warn a breadcrumb, both opt-in (default off). §4.7, #100
8
+ attach(l = {}) {
9
+ const { captureConsole: o = !1 } = l;
10
+ return new Promise((s, i) => {
11
+ try {
12
+ if (typeof ErrorUtils < "u" && ErrorUtils.setGlobalHandler) {
13
+ const e = ErrorUtils.getGlobalHandler?.();
14
+ ErrorUtils.setGlobalHandler((a, r) => {
15
+ this.telemetry.log("app.crash", n("global_handler", a, {
16
+ fatal: !!r
17
+ })), e && e(a, r);
18
+ });
19
+ }
20
+ const t = (e) => {
21
+ this.telemetry.log("app.crash", n("unhandled_rejection", e?.reason, {
22
+ fallbackMessage: "Unhandled Promise Rejection",
23
+ fatal: !1
24
+ }));
25
+ };
26
+ globalThis.addEventListener ? globalThis.addEventListener("unhandledrejection", t) : require("promise/setimmediate/rejection-tracking").enable({
27
+ allRejections: !0,
28
+ onUnhandled: (a, r) => t({ reason: r })
29
+ }), o && c(this.telemetry), s();
30
+ } catch (t) {
31
+ i(t);
32
+ }
33
+ });
34
+ }
35
+ }
36
+ export {
37
+ f as CrashHandlerNative
38
+ };
39
+ //# sourceMappingURL=crashHandlerNative.native-FupMnr1U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashHandlerNative.native-FupMnr1U.js","sources":["../src/adapters/native/crashHandlerNative.native.ts"],"sourcesContent":["import { Telemetry } from \"../../core/telemetry\";\nimport { buildErrorAttributes, captureConsole } from \"../crashCapture\";\n\nexport type CrashHandlerOptions = { captureConsole?: boolean };\n\nexport class CrashHandlerNative {\n constructor(private telemetry: Telemetry) { }\n\n // JS errors and unhandled rejections become `app.crash`; console.error becomes\n // `app.error` and console.warn a breadcrumb, both opt-in (default off). §4.7, #100\n attach(options: CrashHandlerOptions = {}): Promise<void> {\n const { captureConsole: consoleEnabled = false } = options;\n return new Promise((resolve, reject) => {\n try {\n if (typeof ErrorUtils !== \"undefined\" && ErrorUtils.setGlobalHandler) {\n const defaultHandler = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: any, isFatal?: boolean) => {\n // `error.fatal` is native-only — the web build never passes it (§4.7).\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"global_handler\", error, {\n fatal: !!isFatal,\n }));\n if (defaultHandler) defaultHandler(error, isFatal); // keep RN red screen in dev\n });\n }\n\n const onRejection = (event: any) => {\n this.telemetry.log(\"app.crash\", buildErrorAttributes(\"unhandled_rejection\", event?.reason, {\n fallbackMessage: \"Unhandled Promise Rejection\",\n fatal: false,\n }));\n };\n\n if (globalThis.addEventListener) {\n globalThis.addEventListener(\"unhandledrejection\", onRejection);\n } else {\n const tracking = require(\"promise/setimmediate/rejection-tracking\");\n tracking.enable({\n allRejections: true,\n onUnhandled: (_id: any, error: any) =>\n onRejection({ reason: error }),\n });\n }\n\n if (consoleEnabled) captureConsole(this.telemetry);\n\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["CrashHandlerNative","telemetry","options","consoleEnabled","resolve","reject","defaultHandler","error","isFatal","buildErrorAttributes","onRejection","event","_id","captureConsole"],"mappings":";AAKO,MAAMA,EAAmB;AAAA,EAC5B,YAAoBC,GAAsB;AAAtB,SAAA,YAAAA;AAAA,EAAwB;AAAA;AAAA;AAAA,EAI5C,OAAOC,IAA+B,IAAmB;AACrD,UAAM,EAAE,gBAAgBC,IAAiB,GAAA,IAAUD;AACnD,WAAO,IAAI,QAAQ,CAACE,GAASC,MAAW;AACpC,UAAI;AACA,YAAI,OAAO,aAAe,OAAe,WAAW,kBAAkB;AAClE,gBAAMC,IAAiB,WAAW,mBAAA;AAClC,qBAAW,iBAAiB,CAACC,GAAYC,MAAsB;AAE3D,iBAAK,UAAU,IAAI,aAAaC,EAAqB,kBAAkBF,GAAO;AAAA,cAC1E,OAAO,CAAC,CAACC;AAAA,YAAA,CACZ,CAAC,GACEF,KAAgBA,EAAeC,GAAOC,CAAO;AAAA,UACrD,CAAC;AAAA,QACL;AAEA,cAAME,IAAc,CAACC,MAAe;AAChC,eAAK,UAAU,IAAI,aAAaF,EAAqB,uBAAuBE,GAAO,QAAQ;AAAA,YACvF,iBAAiB;AAAA,YACjB,OAAO;AAAA,UAAA,CACV,CAAC;AAAA,QACN;AAEA,QAAI,WAAW,mBACX,WAAW,iBAAiB,sBAAsBD,CAAW,IAE5C,QAAQ,yCAAyC,EACzD,OAAO;AAAA,UACZ,eAAe;AAAA,UACf,aAAa,CAACE,GAAUL,MACpBG,EAAY,EAAE,QAAQH,GAAO;AAAA,QAAA,CACpC,GAGDJ,KAAgBU,EAAe,KAAK,SAAS,GAEjDT,EAAA;AAAA,MACJ,SAASG,GAAO;AACZ,QAAAF,EAAOE,CAAK;AAAA,MAChB;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;"}
@@ -0,0 +1,53 @@
1
+ import { Platform as t, Dimensions as _, PixelRatio as b } from "react-native";
2
+ import { D as a } from "./index-C2XQ-EYw.js";
3
+ import { v as N } from "./viewport-Dzmt5QwK.js";
4
+ class V {
5
+ // private telemetry: Telemetry;
6
+ // constructor(telemetry?: Telemetry) {
7
+ // this.telemetry = telemetry || new Telemetry();
8
+ // }
9
+ constructor() {
10
+ }
11
+ // device.id is NOT collected here (#91): it is self-minted and persisted by core.
12
+ // getUniqueId() carries two lifetimes on RN alone — ANDROID_ID survives reinstall,
13
+ // identifierForVendor does not — so one identity column would mean two things.
14
+ async collect() {
15
+ const e = await a.getApplicationName() || "UnknownApp", n = await a.getVersion() || "0.0.0", s = await a.getBuildNumber() || "0", r = await a.getBundleId() || "unknown.package", c = await a.getBrand(), d = await a.getManufacturer() || "", m = await a.getModel() || "", o = await a.getSystemVersion() || "", p = await a.getSystemName() || "", i = t.OS === "android" ? await a.getApiLevel() : void 0, w = t.OS === "android" ? await a.getHardware?.() : void 0, g = t.OS === "android" ? await a.getProduct?.() : void 0, l = t.OS === "ios" ? p : void 0, u = (await a.supportedAbis?.())?.[0], v = await a.isLowRamDevice?.(), { width: f, height: y } = _.get("window"), S = N(f, y, b.get());
16
+ return {
17
+ app: {
18
+ name: e,
19
+ version: n,
20
+ build_number: s,
21
+ package_name: r
22
+ },
23
+ device: {
24
+ platform: t.OS,
25
+ platform_version: o,
26
+ model: m,
27
+ manufacturer: d,
28
+ brand: c,
29
+ // Android fields
30
+ android_sdk: i ? String(i) : void 0,
31
+ android_release: t.OS === "android" ? o : void 0,
32
+ hardware: w,
33
+ product: g,
34
+ cpu_abi: u,
35
+ low_ram: v,
36
+ // iOS fields
37
+ ios_system_name: l,
38
+ // Viewport — both builds, never null (§3.3)
39
+ ...S
40
+ }
41
+ };
42
+ }
43
+ /**
44
+ * Context-only adapter. collect() feeds the Context block on every event;
45
+ * start() emits no standalone device_info event (ADR-0002).
46
+ */
47
+ async start(e) {
48
+ }
49
+ }
50
+ export {
51
+ V as DeviceInfoTrackerNative
52
+ };
53
+ //# sourceMappingURL=deviceInfo.native-BJ-3Jj1T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceInfo.native-BJ-3Jj1T.js","sources":["../src/adapters/native/deviceInfo.native.ts"],"sourcesContent":["// adapters/native/deviceInfoNative.native.ts\nimport { Dimensions, PixelRatio, Platform } from \"react-native\";\nimport DeviceInfoLib from \"react-native-device-info\";\nimport { Telemetry } from \"../../core/telemetry\";\nimport { DeviceInfo } from \"../../core/telemetry\";\nimport { viewportKeys } from \"../viewport\";\n\nexport class DeviceInfoTrackerNative {\n // private telemetry: Telemetry;\n\n // constructor(telemetry?: Telemetry) {\n // this.telemetry = telemetry || new Telemetry();\n // }\n\n constructor() {\n }\n\n // device.id is NOT collected here (#91): it is self-minted and persisted by core.\n // getUniqueId() carries two lifetimes on RN alone — ANDROID_ID survives reinstall,\n // identifierForVendor does not — so one identity column would mean two things.\n async collect(): Promise<DeviceInfo> {\n // 🔹 App metadata\n const appName = (await DeviceInfoLib.getApplicationName()) || \"UnknownApp\";\n const appVersion = (await DeviceInfoLib.getVersion()) || \"0.0.0\";\n const buildNumber = (await DeviceInfoLib.getBuildNumber()) || \"0\";\n const packageName = (await DeviceInfoLib.getBundleId()) || \"unknown.package\";\n\n // 🔹 Common Device metadata\n const brand = await DeviceInfoLib.getBrand();\n const manufacturer = (await DeviceInfoLib.getManufacturer()) || \"\";\n const model = (await DeviceInfoLib.getModel()) || \"\";\n const systemVersion = (await DeviceInfoLib.getSystemVersion()) || \"\";\n const systemName = (await DeviceInfoLib.getSystemName()) || \"\"; // iOS: \"iOS\", Android: \"Android\"\n\n // 🔹 Android-only fields\n const sdk = Platform.OS === \"android\" ? await DeviceInfoLib.getApiLevel() : undefined;\n const hardware = Platform.OS === \"android\" ? await DeviceInfoLib.getHardware?.() : undefined;\n const product = Platform.OS === \"android\" ? await DeviceInfoLib.getProduct?.() : undefined;\n\n // 🔹 iOS-only fields\n // ⚠ `getDeviceName()` — the user's own name for their phone — is deliberately NOT\n // read any more (§3.4): real PII, no column, no reader. `getFingerprint()` went with\n // it — a build string that merges handsets, which *repairs* device identity (§1.2).\n const iosSystemName = Platform.OS === \"ios\" ? systemName : undefined;\n\n // 🔹 §3.3 ✱ — device capability (native only) and viewport (both builds).\n const cpuAbi = (await DeviceInfoLib.supportedAbis?.())?.[0];\n const lowRam = await DeviceInfoLib.isLowRamDevice?.();\n\n // Read on every collect(), not cached: a device rotates mid-session, and §3.1 puts\n // `device.orientation` and device state on the log-time side of the freeze. The\n // *shaping* is shared with web (`adapters/viewport.ts`) so one column cannot come to\n // mean physical pixels on one build and dp on the other.\n const { width, height } = Dimensions.get(\"window\");\n const viewport = viewportKeys(width, height, PixelRatio.get());\n\n const info: DeviceInfo = {\n app: {\n name: appName,\n version: appVersion,\n build_number: buildNumber,\n package_name: packageName,\n },\n device: {\n platform: Platform.OS,\n platform_version: systemVersion,\n model,\n manufacturer,\n brand,\n\n // Android fields\n android_sdk: sdk ? String(sdk) : undefined,\n android_release: Platform.OS === \"android\" ? systemVersion : undefined,\n hardware,\n product,\n cpu_abi: cpuAbi,\n low_ram: lowRam,\n\n // iOS fields\n ios_system_name: iosSystemName,\n\n // Viewport — both builds, never null (§3.3)\n ...viewport,\n },\n };\n\n return info;\n }\n\n /**\n * Context-only adapter. collect() feeds the Context block on every event;\n * start() emits no standalone device_info event (ADR-0002).\n */\n async start(_telemetry: Telemetry): Promise<void> {\n // no-op: device metadata rides as attributes on every event\n }\n}\n"],"names":["DeviceInfoTrackerNative","appName","DeviceInfoLib","appVersion","buildNumber","packageName","brand","manufacturer","model","systemVersion","systemName","sdk","Platform","hardware","product","iosSystemName","cpuAbi","lowRam","width","height","Dimensions","viewport","viewportKeys","PixelRatio","_telemetry"],"mappings":";;;AAOO,MAAMA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjC,cAAc;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA+B;AAEjC,UAAMC,IAAW,MAAMC,EAAc,mBAAA,KAAyB,cACxDC,IAAc,MAAMD,EAAc,WAAA,KAAiB,SACnDE,IAAe,MAAMF,EAAc,eAAA,KAAqB,KACxDG,IAAe,MAAMH,EAAc,YAAA,KAAkB,mBAGrDI,IAAQ,MAAMJ,EAAc,SAAA,GAC5BK,IAAgB,MAAML,EAAc,gBAAA,KAAsB,IAC1DM,IAAS,MAAMN,EAAc,SAAA,KAAe,IAC5CO,IAAiB,MAAMP,EAAc,iBAAA,KAAuB,IAC5DQ,IAAc,MAAMR,EAAc,cAAA,KAAoB,IAGtDS,IAAMC,EAAS,OAAO,YAAY,MAAMV,EAAc,gBAAgB,QACtEW,IAAWD,EAAS,OAAO,YAAY,MAAMV,EAAc,kBAAkB,QAC7EY,IAAUF,EAAS,OAAO,YAAY,MAAMV,EAAc,iBAAiB,QAM3Ea,IAAgBH,EAAS,OAAO,QAAQF,IAAa,QAGrDM,KAAU,MAAMd,EAAc,gBAAA,KAAqB,CAAC,GACpDe,IAAS,MAAMf,EAAc,iBAAA,GAM7B,EAAE,OAAAgB,GAAO,QAAAC,EAAA,IAAWC,EAAW,IAAI,QAAQ,GAC3CC,IAAWC,EAAaJ,GAAOC,GAAQI,EAAW,KAAK;AAgC7D,WA9ByB;AAAA,MACrB,KAAK;AAAA,QACD,MAAMtB;AAAA,QACN,SAASE;AAAA,QACT,cAAcC;AAAA,QACd,cAAcC;AAAA,MAAA;AAAA,MAElB,QAAQ;AAAA,QACJ,UAAUO,EAAS;AAAA,QACnB,kBAAkBH;AAAA,QAClB,OAAAD;AAAA,QACA,cAAAD;AAAA,QACA,OAAAD;AAAA;AAAA,QAGA,aAAaK,IAAM,OAAOA,CAAG,IAAI;AAAA,QACjC,iBAAiBC,EAAS,OAAO,YAAYH,IAAgB;AAAA,QAC7D,UAAAI;AAAA,QACA,SAAAC;AAAA,QACA,SAASE;AAAA,QACT,SAASC;AAAA;AAAA,QAGT,iBAAiBF;AAAA;AAAA,QAGjB,GAAGM;AAAA,MAAA;AAAA,IACP;AAAA,EAIR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAMG,GAAsC;AAAA,EAElD;AACJ;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react-native"),e=require("./index-CXsVZY35.cjs"),y=require("./viewport-Dd85GUNO.cjs");class S{constructor(){}async collect(){const t=await e.DeviceInfo.getApplicationName()||"UnknownApp",n=await e.DeviceInfo.getVersion()||"0.0.0",r=await e.DeviceInfo.getBuildNumber()||"0",c=await e.DeviceInfo.getBundleId()||"unknown.package",s=await e.DeviceInfo.getBrand(),d=await e.DeviceInfo.getManufacturer()||"",m=await e.DeviceInfo.getModel()||"",a=await e.DeviceInfo.getSystemVersion()||"",v=await e.DeviceInfo.getSystemName()||"",i=o.Platform.OS==="android"?await e.DeviceInfo.getApiLevel():void 0,f=o.Platform.OS==="android"?await e.DeviceInfo.getHardware?.():void 0,l=o.Platform.OS==="android"?await e.DeviceInfo.getProduct?.():void 0,w=o.Platform.OS==="ios"?v:void 0,u=(await e.DeviceInfo.supportedAbis?.())?.[0],p=await e.DeviceInfo.isLowRamDevice?.(),{width:g,height:D}=o.Dimensions.get("window"),I=y.viewportKeys(g,D,o.PixelRatio.get());return{app:{name:t,version:n,build_number:r,package_name:c},device:{platform:o.Platform.OS,platform_version:a,model:m,manufacturer:d,brand:s,android_sdk:i?String(i):void 0,android_release:o.Platform.OS==="android"?a:void 0,hardware:f,product:l,cpu_abi:u,low_ram:p,ios_system_name:w,...I}}}async start(t){}}exports.DeviceInfoTrackerNative=S;
2
+ //# sourceMappingURL=deviceInfo.native-BoeTZcD6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceInfo.native-BoeTZcD6.cjs","sources":["../src/adapters/native/deviceInfo.native.ts"],"sourcesContent":["// adapters/native/deviceInfoNative.native.ts\nimport { Dimensions, PixelRatio, Platform } from \"react-native\";\nimport DeviceInfoLib from \"react-native-device-info\";\nimport { Telemetry } from \"../../core/telemetry\";\nimport { DeviceInfo } from \"../../core/telemetry\";\nimport { viewportKeys } from \"../viewport\";\n\nexport class DeviceInfoTrackerNative {\n // private telemetry: Telemetry;\n\n // constructor(telemetry?: Telemetry) {\n // this.telemetry = telemetry || new Telemetry();\n // }\n\n constructor() {\n }\n\n // device.id is NOT collected here (#91): it is self-minted and persisted by core.\n // getUniqueId() carries two lifetimes on RN alone — ANDROID_ID survives reinstall,\n // identifierForVendor does not — so one identity column would mean two things.\n async collect(): Promise<DeviceInfo> {\n // 🔹 App metadata\n const appName = (await DeviceInfoLib.getApplicationName()) || \"UnknownApp\";\n const appVersion = (await DeviceInfoLib.getVersion()) || \"0.0.0\";\n const buildNumber = (await DeviceInfoLib.getBuildNumber()) || \"0\";\n const packageName = (await DeviceInfoLib.getBundleId()) || \"unknown.package\";\n\n // 🔹 Common Device metadata\n const brand = await DeviceInfoLib.getBrand();\n const manufacturer = (await DeviceInfoLib.getManufacturer()) || \"\";\n const model = (await DeviceInfoLib.getModel()) || \"\";\n const systemVersion = (await DeviceInfoLib.getSystemVersion()) || \"\";\n const systemName = (await DeviceInfoLib.getSystemName()) || \"\"; // iOS: \"iOS\", Android: \"Android\"\n\n // 🔹 Android-only fields\n const sdk = Platform.OS === \"android\" ? await DeviceInfoLib.getApiLevel() : undefined;\n const hardware = Platform.OS === \"android\" ? await DeviceInfoLib.getHardware?.() : undefined;\n const product = Platform.OS === \"android\" ? await DeviceInfoLib.getProduct?.() : undefined;\n\n // 🔹 iOS-only fields\n // ⚠ `getDeviceName()` — the user's own name for their phone — is deliberately NOT\n // read any more (§3.4): real PII, no column, no reader. `getFingerprint()` went with\n // it — a build string that merges handsets, which *repairs* device identity (§1.2).\n const iosSystemName = Platform.OS === \"ios\" ? systemName : undefined;\n\n // 🔹 §3.3 ✱ — device capability (native only) and viewport (both builds).\n const cpuAbi = (await DeviceInfoLib.supportedAbis?.())?.[0];\n const lowRam = await DeviceInfoLib.isLowRamDevice?.();\n\n // Read on every collect(), not cached: a device rotates mid-session, and §3.1 puts\n // `device.orientation` and device state on the log-time side of the freeze. The\n // *shaping* is shared with web (`adapters/viewport.ts`) so one column cannot come to\n // mean physical pixels on one build and dp on the other.\n const { width, height } = Dimensions.get(\"window\");\n const viewport = viewportKeys(width, height, PixelRatio.get());\n\n const info: DeviceInfo = {\n app: {\n name: appName,\n version: appVersion,\n build_number: buildNumber,\n package_name: packageName,\n },\n device: {\n platform: Platform.OS,\n platform_version: systemVersion,\n model,\n manufacturer,\n brand,\n\n // Android fields\n android_sdk: sdk ? String(sdk) : undefined,\n android_release: Platform.OS === \"android\" ? systemVersion : undefined,\n hardware,\n product,\n cpu_abi: cpuAbi,\n low_ram: lowRam,\n\n // iOS fields\n ios_system_name: iosSystemName,\n\n // Viewport — both builds, never null (§3.3)\n ...viewport,\n },\n };\n\n return info;\n }\n\n /**\n * Context-only adapter. collect() feeds the Context block on every event;\n * start() emits no standalone device_info event (ADR-0002).\n */\n async start(_telemetry: Telemetry): Promise<void> {\n // no-op: device metadata rides as attributes on every event\n }\n}\n"],"names":["DeviceInfoTrackerNative","appName","DeviceInfoLib","appVersion","buildNumber","packageName","brand","manufacturer","model","systemVersion","systemName","sdk","Platform","hardware","product","iosSystemName","cpuAbi","lowRam","width","height","Dimensions","viewport","viewportKeys","PixelRatio","_telemetry"],"mappings":"uLAOO,MAAMA,CAAwB,CAOjC,aAAc,CACd,CAKA,MAAM,SAA+B,CAEjC,MAAMC,EAAW,MAAMC,aAAc,mBAAA,GAAyB,aACxDC,EAAc,MAAMD,aAAc,WAAA,GAAiB,QACnDE,EAAe,MAAMF,aAAc,eAAA,GAAqB,IACxDG,EAAe,MAAMH,aAAc,YAAA,GAAkB,kBAGrDI,EAAQ,MAAMJ,EAAAA,WAAc,SAAA,EAC5BK,EAAgB,MAAML,aAAc,gBAAA,GAAsB,GAC1DM,EAAS,MAAMN,aAAc,SAAA,GAAe,GAC5CO,EAAiB,MAAMP,aAAc,iBAAA,GAAuB,GAC5DQ,EAAc,MAAMR,aAAc,cAAA,GAAoB,GAGtDS,EAAMC,EAAAA,SAAS,KAAO,UAAY,MAAMV,EAAAA,WAAc,cAAgB,OACtEW,EAAWD,EAAAA,SAAS,KAAO,UAAY,MAAMV,EAAAA,WAAc,gBAAkB,OAC7EY,EAAUF,EAAAA,SAAS,KAAO,UAAY,MAAMV,EAAAA,WAAc,eAAiB,OAM3Ea,EAAgBH,EAAAA,SAAS,KAAO,MAAQF,EAAa,OAGrDM,GAAU,MAAMd,EAAAA,WAAc,gBAAA,KAAqB,CAAC,EACpDe,EAAS,MAAMf,EAAAA,WAAc,iBAAA,EAM7B,CAAE,MAAAgB,EAAO,OAAAC,CAAA,EAAWC,EAAAA,WAAW,IAAI,QAAQ,EAC3CC,EAAWC,EAAAA,aAAaJ,EAAOC,EAAQI,EAAAA,WAAW,KAAK,EAgC7D,MA9ByB,CACrB,IAAK,CACD,KAAMtB,EACN,QAASE,EACT,aAAcC,EACd,aAAcC,CAAA,EAElB,OAAQ,CACJ,SAAUO,EAAAA,SAAS,GACnB,iBAAkBH,EAClB,MAAAD,EACA,aAAAD,EACA,MAAAD,EAGA,YAAaK,EAAM,OAAOA,CAAG,EAAI,OACjC,gBAAiBC,EAAAA,SAAS,KAAO,UAAYH,EAAgB,OAC7D,SAAAI,EACA,QAAAC,EACA,QAASE,EACT,QAASC,EAGT,gBAAiBF,EAGjB,GAAGM,CAAA,CACP,CAIR,CAMA,MAAM,MAAMG,EAAsC,CAElD,CACJ"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./viewport-Dd85GUNO.cjs");class i{constructor(){}async collect(){const e=navigator.userAgent,o=typeof devicePixelRatio=="number"?devicePixelRatio:1,r=n.viewportKeys(window.innerWidth??0,window.innerHeight??0,o);return{app:{name:document.title||"WebApp",version:process.env.APP_VERSION||"1.0.0",build_number:process.env.BUILD_NUMBER,package_name:window.location.hostname},device:{platform:"web",platform_version:navigator.appVersion,model:e,manufacturer:"browser",brand:navigator.vendor||"unknown",android_sdk:void 0,android_release:void 0,hardware:void 0,product:void 0,ios_system_name:void 0,...r}}}async start(e){this.telemetry=e}}exports.DeviceInfoTrackerWeb=i;
2
+ //# sourceMappingURL=deviceInfo.web-3L3IDQQA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceInfo.web-3L3IDQQA.cjs","sources":["../src/adapters/web/deviceInfo.web.ts"],"sourcesContent":["// adapters/web/deviceInfoWeb.web.ts\nimport { DeviceInfo, Telemetry } from \"../../core/telemetry\";\nimport { viewportKeys } from \"../viewport\";\n\nexport class DeviceInfoTrackerWeb {\n private telemetry?: Telemetry;\n\n\n constructor() {\n }\n // device.id is NOT collected here (#91): core self-mints and persists it via the Store.\n async collect(): Promise<DeviceInfo> {\n const ua = navigator.userAgent;\n\n // §3.3 ✱ — viewport, read on every collect() because a browser window resizes and a\n // phone rotates; §3.1 keeps device state on the log-time side of the freeze. The\n // *viewport*, not `screen.*`: that is the quantity CLS and LCP scale with. Shaped by\n // the shared `adapters/viewport.ts`, so the key means the same thing native ships.\n const dpr = typeof devicePixelRatio === \"number\" ? devicePixelRatio : 1;\n const viewport = viewportKeys(window.innerWidth ?? 0, window.innerHeight ?? 0, dpr);\n\n return {\n app: {\n name: document.title || \"WebApp\",\n version: process.env.APP_VERSION || \"1.0.0\",\n build_number: process.env.BUILD_NUMBER,\n package_name: window.location.hostname,\n },\n device: {\n platform: \"web\",\n platform_version: navigator.appVersion,\n model: ua,\n manufacturer: \"browser\",\n brand: navigator.vendor || \"unknown\",\n\n // Android placeholders\n android_sdk: undefined,\n android_release: undefined,\n hardware: undefined,\n product: undefined,\n\n // iOS placeholders\n ios_system_name: undefined,\n\n // `cpu_abi` / `low_ram` are native-only (§3.3's `N`) — a browser exposes\n // neither, and a fabricated value is worse than an absent key.\n ...viewport,\n },\n };\n }\n\n async start(telemetry: Telemetry): Promise<void> {\n // context-only adapter — collect() feeds the Context block on every event;\n // no standalone device_info event (ADR-0002)\n this.telemetry = telemetry;\n }\n}\n"],"names":["DeviceInfoTrackerWeb","ua","dpr","viewport","viewportKeys","telemetry"],"mappings":"2HAIO,MAAMA,CAAqB,CAI9B,aAAc,CACd,CAEA,MAAM,SAA+B,CACjC,MAAMC,EAAK,UAAU,UAMfC,EAAM,OAAO,kBAAqB,SAAW,iBAAmB,EAChEC,EAAWC,eAAa,OAAO,YAAc,EAAG,OAAO,aAAe,EAAGF,CAAG,EAElF,MAAO,CACH,IAAK,CACD,KAAM,SAAS,OAAS,SACxB,QAAS,QAAQ,IAAI,aAAe,QACpC,aAAc,QAAQ,IAAI,aAC1B,aAAc,OAAO,SAAS,QAAA,EAElC,OAAQ,CACJ,SAAU,MACV,iBAAkB,UAAU,WAC5B,MAAOD,EACP,aAAc,UACd,MAAO,UAAU,QAAU,UAG3B,YAAa,OACb,gBAAiB,OACjB,SAAU,OACV,QAAS,OAGT,gBAAiB,OAIjB,GAAGE,CAAA,CACP,CAER,CAEA,MAAM,MAAME,EAAqC,CAG7C,KAAK,UAAYA,CACrB,CACJ"}
@@ -0,0 +1,41 @@
1
+ import { v as n } from "./viewport-Dzmt5QwK.js";
2
+ class a {
3
+ constructor() {
4
+ }
5
+ // device.id is NOT collected here (#91): core self-mints and persists it via the Store.
6
+ async collect() {
7
+ const e = navigator.userAgent, o = typeof devicePixelRatio == "number" ? devicePixelRatio : 1, r = n(window.innerWidth ?? 0, window.innerHeight ?? 0, o);
8
+ return {
9
+ app: {
10
+ name: document.title || "WebApp",
11
+ version: process.env.APP_VERSION || "1.0.0",
12
+ build_number: process.env.BUILD_NUMBER,
13
+ package_name: window.location.hostname
14
+ },
15
+ device: {
16
+ platform: "web",
17
+ platform_version: navigator.appVersion,
18
+ model: e,
19
+ manufacturer: "browser",
20
+ brand: navigator.vendor || "unknown",
21
+ // Android placeholders
22
+ android_sdk: void 0,
23
+ android_release: void 0,
24
+ hardware: void 0,
25
+ product: void 0,
26
+ // iOS placeholders
27
+ ios_system_name: void 0,
28
+ // `cpu_abi` / `low_ram` are native-only (§3.3's `N`) — a browser exposes
29
+ // neither, and a fabricated value is worse than an absent key.
30
+ ...r
31
+ }
32
+ };
33
+ }
34
+ async start(e) {
35
+ this.telemetry = e;
36
+ }
37
+ }
38
+ export {
39
+ a as DeviceInfoTrackerWeb
40
+ };
41
+ //# sourceMappingURL=deviceInfo.web-BFB1-pcA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceInfo.web-BFB1-pcA.js","sources":["../src/adapters/web/deviceInfo.web.ts"],"sourcesContent":["// adapters/web/deviceInfoWeb.web.ts\nimport { DeviceInfo, Telemetry } from \"../../core/telemetry\";\nimport { viewportKeys } from \"../viewport\";\n\nexport class DeviceInfoTrackerWeb {\n private telemetry?: Telemetry;\n\n\n constructor() {\n }\n // device.id is NOT collected here (#91): core self-mints and persists it via the Store.\n async collect(): Promise<DeviceInfo> {\n const ua = navigator.userAgent;\n\n // §3.3 ✱ — viewport, read on every collect() because a browser window resizes and a\n // phone rotates; §3.1 keeps device state on the log-time side of the freeze. The\n // *viewport*, not `screen.*`: that is the quantity CLS and LCP scale with. Shaped by\n // the shared `adapters/viewport.ts`, so the key means the same thing native ships.\n const dpr = typeof devicePixelRatio === \"number\" ? devicePixelRatio : 1;\n const viewport = viewportKeys(window.innerWidth ?? 0, window.innerHeight ?? 0, dpr);\n\n return {\n app: {\n name: document.title || \"WebApp\",\n version: process.env.APP_VERSION || \"1.0.0\",\n build_number: process.env.BUILD_NUMBER,\n package_name: window.location.hostname,\n },\n device: {\n platform: \"web\",\n platform_version: navigator.appVersion,\n model: ua,\n manufacturer: \"browser\",\n brand: navigator.vendor || \"unknown\",\n\n // Android placeholders\n android_sdk: undefined,\n android_release: undefined,\n hardware: undefined,\n product: undefined,\n\n // iOS placeholders\n ios_system_name: undefined,\n\n // `cpu_abi` / `low_ram` are native-only (§3.3's `N`) — a browser exposes\n // neither, and a fabricated value is worse than an absent key.\n ...viewport,\n },\n };\n }\n\n async start(telemetry: Telemetry): Promise<void> {\n // context-only adapter — collect() feeds the Context block on every event;\n // no standalone device_info event (ADR-0002)\n this.telemetry = telemetry;\n }\n}\n"],"names":["DeviceInfoTrackerWeb","ua","dpr","viewport","viewportKeys","telemetry"],"mappings":";AAIO,MAAMA,EAAqB;AAAA,EAI9B,cAAc;AAAA,EACd;AAAA;AAAA,EAEA,MAAM,UAA+B;AACjC,UAAMC,IAAK,UAAU,WAMfC,IAAM,OAAO,oBAAqB,WAAW,mBAAmB,GAChEC,IAAWC,EAAa,OAAO,cAAc,GAAG,OAAO,eAAe,GAAGF,CAAG;AAElF,WAAO;AAAA,MACH,KAAK;AAAA,QACD,MAAM,SAAS,SAAS;AAAA,QACxB,SAAS,QAAQ,IAAI,eAAe;AAAA,QACpC,cAAc,QAAQ,IAAI;AAAA,QAC1B,cAAc,OAAO,SAAS;AAAA,MAAA;AAAA,MAElC,QAAQ;AAAA,QACJ,UAAU;AAAA,QACV,kBAAkB,UAAU;AAAA,QAC5B,OAAOD;AAAA,QACP,cAAc;AAAA,QACd,OAAO,UAAU,UAAU;AAAA;AAAA,QAG3B,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,UAAU;AAAA,QACV,SAAS;AAAA;AAAA,QAGT,iBAAiB;AAAA;AAAA;AAAA,QAIjB,GAAGE;AAAA,MAAA;AAAA,IACP;AAAA,EAER;AAAA,EAEA,MAAM,MAAME,GAAqC;AAG7C,SAAK,YAAYA;AAAA,EACrB;AACJ;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=[60,90,120];function d(a){const t=a.filter(s=>s>0);if(t.length===0)return 60;const r=1e3/(t[Math.ceil(.05*t.length)-1]??t[0]);return c.reduce((s,i)=>Math.abs(i-r)<Math.abs(s-r)?i:s)}function u(a,t,e){const r=[...a].sort((o,l)=>o-l),s=d(r),i=1e3/s,m=r[r.length-1],n=r[Math.ceil(.95*r.length)-1],h=a.filter(o=>o>i*2).length;return{value:n,attributes:{"frame.max_ms":m,"frame.p95_ms":n,"frame.dropped_count":h,"frame.target_fps":s,"frame.window_duration_ms":Math.round(Math.max(0,t)),"frame.source":e}}}class f{constructor(t,e=1e4){this.telemetry=t,this.windowMs=e,this.lastFrameTime=performance.now(),this.windowStart=this.lastFrameTime,this.deltas=[],this.started=!1}start(){if(this.started)return Promise.resolve();this.started=!0,this.telemetry.views.onBoundary(()=>this.emitWindow(performance.now()));const t=()=>{const e=performance.now();this.deltas.push(e-this.lastFrameTime),this.lastFrameTime=e,e-this.windowStart>=this.windowMs&&this.emitWindow(e),requestAnimationFrame(t)};return requestAnimationFrame(t),Promise.resolve()}async emitWindow(t){const e=t-this.windowStart;if(this.windowStart=t,this.deltas.length===0)return;const{value:r,attributes:s}=u(this.deltas,e,"requestAnimationFrame");this.deltas=[],await this.telemetry.logMetric("frame_render_time",r,s)}}exports.FrameDropTracker=f;
2
+ //# sourceMappingURL=frameTracker-CHG6sIx9.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameTracker-CHG6sIx9.cjs","sources":["../src/adapters/frameAggregate.ts","../src/adapters/frameTracker.ts"],"sourcesContent":["// Aggregate a window of frame deltas (ms) into the `frame_render_time` metric (§5.1).\n// Shared by both builds so the percentile math and the refresh-rate measurement live once.\n\nexport interface FrameAggregate {\n value: number; // metric value = p95 frame time (representative render time)\n attributes: {\n \"frame.max_ms\": number;\n \"frame.p95_ms\": number;\n \"frame.dropped_count\": number; // frames slower than 2x budget\n \"frame.target_fps\": number;\n \"frame.window_duration_ms\": number;\n \"frame.source\": string;\n };\n}\n\n/**\n * §5.1 fixes the domain at three values. A 144 Hz panel therefore snaps to 120 — the\n * point of the key is the dropped-frame budget, not a display census.\n */\nconst REFRESH_RATES = [60, 90, 120];\n\n/**\n * The refresh rate, **measured** rather than assumed (§5.1). rAF cannot fire faster than the\n * display, so the floor of the window's deltas *is* the refresh interval — no new platform\n * API is involved.\n *\n * ⚠ The floor is the **5th percentile, not the minimum**. A single spurious short delta — a\n * double-dispatched callback, a clock adjustment — would snap a 60 Hz device to 120 and double\n * its `frame.dropped_count`, reintroducing the wrong-budget defect this key exists to fix. A\n * real 120 Hz display produces short deltas by the hundred, so p5 finds them and one artefact\n * cannot. Snapping to the three-value domain absorbs whatever jitter is left.\n *\n * ponytail: a window with no positive delta falls back to 60, which is also v3's constant.\n */\nfunction measureTargetFps(sorted: number[]): number {\n const positive = sorted.filter((d) => d > 0);\n if (positive.length === 0) return 60;\n const floor = positive[Math.ceil(0.05 * positive.length) - 1] ?? positive[0];\n const fps = 1000 / floor;\n return REFRESH_RATES.reduce((a, b) => (Math.abs(b - fps) < Math.abs(a - fps) ? b : a));\n}\n\n/**\n * `deltas` must be non-empty. Percentile is nearest-rank on the sorted deltas.\n * `windowMs` is the *actual* elapsed window — variable-length since §5.1's view-boundary\n * reset, which is exactly why `frame.window_duration_ms` is required on the wire.\n */\nexport function aggregateFrames(deltas: number[], windowMs: number, source: string): FrameAggregate {\n const sorted = [...deltas].sort((a, b) => a - b);\n const targetFps = measureTargetFps(sorted);\n const budget = 1000 / targetFps;\n const max = sorted[sorted.length - 1];\n const p95 = sorted[Math.ceil(0.95 * sorted.length) - 1];\n const dropped = deltas.filter((d) => d > budget * 2).length;\n\n return {\n value: p95,\n attributes: {\n \"frame.max_ms\": max,\n \"frame.p95_ms\": p95,\n \"frame.dropped_count\": dropped,\n \"frame.target_fps\": targetFps,\n \"frame.window_duration_ms\": Math.round(Math.max(0, windowMs)),\n \"frame.source\": source,\n },\n };\n}\n","// The rAF sampling loop behind `frame_render_time` (§5.1), shared by both builds: rAF and\n// `performance.now()` are globals RN polyfills and the browser ships, so there is nothing\n// platform-specific left to split. Web and native therefore cannot drift on window length,\n// on the refresh-rate measurement or on the boundary reset.\n\nimport { aggregateFrames } from \"./frameAggregate\";\n\n/**\n * All this tracker needs of core. Structural, so it is testable without a `Telemetry`.\n */\ntype FrameEmitter = {\n logMetric(name: string, value: number, data?: Record<string, any>): unknown;\n views: { onBoundary(fn: () => unknown): () => void };\n};\n\nexport class FrameDropTracker {\n private lastFrameTime = performance.now();\n private windowStart = this.lastFrameTime;\n private deltas: number[] = [];\n private started = false;\n\n constructor(private telemetry: FrameEmitter, private windowMs = 10000) { }\n\n /** Idempotent in full: a second call must not start a second rAF loop double-counting frames. */\n start(): Promise<void> {\n if (this.started) return Promise.resolve();\n this.started = true;\n this.telemetry.views.onBoundary(() => this.emitWindow(performance.now()));\n\n const loop = () => {\n const now = performance.now();\n this.deltas.push(now - this.lastFrameTime);\n this.lastFrameTime = now;\n // ponytail: first window includes the startup delta; acceptable noise, not worth gating.\n if (now - this.windowStart >= this.windowMs) void this.emitWindow(now);\n requestAnimationFrame(loop);\n };\n\n requestAnimationFrame(loop);\n return Promise.resolve();\n }\n\n /**\n * Close the open window and ship it. `ViewManager` **awaits** this at a boundary and\n * before the successor mints, which is what lands a route change's dropped frames on the\n * departing `view.id` rather than the arriving one (§5.1).\n *\n * An empty window emits nothing — a p95 over no samples is not a number — but it still\n * resets the clock, so `frame.window_duration_ms` always describes the samples it carries.\n */\n private async emitWindow(now: number): Promise<void> {\n const elapsed = now - this.windowStart;\n this.windowStart = now;\n if (this.deltas.length === 0) return;\n\n const { value, attributes } = aggregateFrames(this.deltas, elapsed, \"requestAnimationFrame\");\n this.deltas = [];\n await this.telemetry.logMetric(\"frame_render_time\", value, attributes);\n }\n}\n"],"names":["REFRESH_RATES","measureTargetFps","sorted","positive","d","fps","a","b","aggregateFrames","deltas","windowMs","source","targetFps","budget","max","p95","dropped","FrameDropTracker","telemetry","loop","now","elapsed","value","attributes"],"mappings":"gFAmBA,MAAMA,EAAgB,CAAC,GAAI,GAAI,GAAG,EAelC,SAASC,EAAiBC,EAA0B,CAChD,MAAMC,EAAWD,EAAO,OAAQE,GAAMA,EAAI,CAAC,EAC3C,GAAID,EAAS,SAAW,EAAG,MAAO,IAElC,MAAME,EAAM,KADEF,EAAS,KAAK,KAAK,IAAOA,EAAS,MAAM,EAAI,CAAC,GAAKA,EAAS,CAAC,GAE3E,OAAOH,EAAc,OAAO,CAACM,EAAGC,IAAO,KAAK,IAAIA,EAAIF,CAAG,EAAI,KAAK,IAAIC,EAAID,CAAG,EAAIE,EAAID,CAAE,CACzF,CAOO,SAASE,EAAgBC,EAAkBC,EAAkBC,EAAgC,CAChG,MAAMT,EAAS,CAAC,GAAGO,CAAM,EAAE,KAAK,CAACH,EAAGC,IAAMD,EAAIC,CAAC,EACzCK,EAAYX,EAAiBC,CAAM,EACnCW,EAAS,IAAOD,EAChBE,EAAMZ,EAAOA,EAAO,OAAS,CAAC,EAC9Ba,EAAMb,EAAO,KAAK,KAAK,IAAOA,EAAO,MAAM,EAAI,CAAC,EAChDc,EAAUP,EAAO,OAAQL,GAAMA,EAAIS,EAAS,CAAC,EAAE,OAErD,MAAO,CACH,MAAOE,EACP,WAAY,CACR,eAAgBD,EAChB,eAAgBC,EAChB,sBAAuBC,EACvB,mBAAoBJ,EACpB,2BAA4B,KAAK,MAAM,KAAK,IAAI,EAAGF,CAAQ,CAAC,EAC5D,eAAgBC,CAAA,CACpB,CAER,CCnDO,MAAMM,CAAiB,CAM1B,YAAoBC,EAAiCR,EAAW,IAAO,CAAnD,KAAA,UAAAQ,EAAiC,KAAA,SAAAR,EALrD,KAAQ,cAAgB,YAAY,IAAA,EACpC,KAAQ,YAAc,KAAK,cAC3B,KAAQ,OAAmB,CAAA,EAC3B,KAAQ,QAAU,EAEuD,CAGzE,OAAuB,CACnB,GAAI,KAAK,QAAS,OAAO,QAAQ,QAAA,EACjC,KAAK,QAAU,GACf,KAAK,UAAU,MAAM,WAAW,IAAM,KAAK,WAAW,YAAY,IAAA,CAAK,CAAC,EAExE,MAAMS,EAAO,IAAM,CACf,MAAMC,EAAM,YAAY,IAAA,EACxB,KAAK,OAAO,KAAKA,EAAM,KAAK,aAAa,EACzC,KAAK,cAAgBA,EAEjBA,EAAM,KAAK,aAAe,KAAK,UAAe,KAAK,WAAWA,CAAG,EACrE,sBAAsBD,CAAI,CAC9B,EAEA,6BAAsBA,CAAI,EACnB,QAAQ,QAAA,CACnB,CAUA,MAAc,WAAWC,EAA4B,CACjD,MAAMC,EAAUD,EAAM,KAAK,YAE3B,GADA,KAAK,YAAcA,EACf,KAAK,OAAO,SAAW,EAAG,OAE9B,KAAM,CAAE,MAAAE,EAAO,WAAAC,GAAef,EAAgB,KAAK,OAAQa,EAAS,uBAAuB,EAC3F,KAAK,OAAS,CAAA,EACd,MAAM,KAAK,UAAU,UAAU,oBAAqBC,EAAOC,CAAU,CACzE,CACJ"}