tempest-react-sdk 0.77.0 → 0.79.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 (1623) hide show
  1. package/README.md +6 -6
  2. package/bin/lib/alias/collect.mjs +20 -3
  3. package/bin/lib/alias/index.mjs +12 -1
  4. package/bin/lib/alias/index.test.mjs +24 -0
  5. package/bin/lib/css/analyze.test.mjs +21 -1
  6. package/bin/lib/css/collect.mjs +14 -0
  7. package/bin/lib/css/extract.mjs +63 -5
  8. package/bin/lib/css/extract.test.mjs +110 -1
  9. package/bin/lib/css/fix.e2e.test.mjs +50 -0
  10. package/bin/lib/css/index.mjs +6 -1
  11. package/bin/lib/fs/contain.mjs +50 -0
  12. package/bin/lib/icons/generate.mjs +28 -3
  13. package/bin/lib/icons/generate.test.mjs +57 -1
  14. package/bin/lib/openapi/escape.mjs +20 -6
  15. package/bin/lib/openapi/generate.encode.test.mjs +120 -0
  16. package/bin/lib/openapi/generate.hostile.test.mjs +38 -9
  17. package/bin/lib/openapi/generate.mjs +203 -64
  18. package/bin/lib/openapi/generate.pagination.test.mjs +3 -2
  19. package/bin/lib/openapi/generate.test.mjs +270 -3
  20. package/bin/lib/openapi/schema-to-zod.mjs +5 -3
  21. package/bin/tempest-gen.test.mjs +188 -0
  22. package/bin/tempest.mjs +120 -44
  23. package/dist/access/Can.cjs.map +1 -1
  24. package/dist/access/Can.js.map +1 -1
  25. package/dist/access/access-control-context.cjs.map +1 -1
  26. package/dist/access/access-control-context.js.map +1 -1
  27. package/dist/access/create-role-access-control.cjs.map +1 -1
  28. package/dist/access/create-role-access-control.js.map +1 -1
  29. package/dist/access/permissions-from-token.cjs.map +1 -1
  30. package/dist/access/permissions-from-token.js.map +1 -1
  31. package/dist/access/use-can.cjs.map +1 -1
  32. package/dist/access/use-can.js.map +1 -1
  33. package/dist/app/AppProviders.cjs.map +1 -1
  34. package/dist/app/AppProviders.js.map +1 -1
  35. package/dist/audio/audio-bus.cjs.map +1 -1
  36. package/dist/audio/audio-bus.js.map +1 -1
  37. package/dist/audio/audio-output.cjs.map +1 -1
  38. package/dist/audio/audio-output.js.map +1 -1
  39. package/dist/audio/audio-player.cjs.map +1 -1
  40. package/dist/audio/audio-player.js.map +1 -1
  41. package/dist/audio/audio-recorder.cjs.map +1 -1
  42. package/dist/audio/audio-recorder.js.map +1 -1
  43. package/dist/audio/duration.cjs.map +1 -1
  44. package/dist/audio/duration.js.map +1 -1
  45. package/dist/audio/level-meter.cjs.map +1 -1
  46. package/dist/audio/level-meter.js.map +1 -1
  47. package/dist/audio/media-access.cjs.map +1 -1
  48. package/dist/audio/media-access.js.map +1 -1
  49. package/dist/audio/noise-floor.cjs.map +1 -1
  50. package/dist/audio/noise-floor.js.map +1 -1
  51. package/dist/audio/sfx-pool.cjs.map +1 -1
  52. package/dist/audio/sfx-pool.js.map +1 -1
  53. package/dist/audio/use-audio-bus.cjs.map +1 -1
  54. package/dist/audio/use-audio-bus.js.map +1 -1
  55. package/dist/audio/use-audio-recorder.cjs.map +1 -1
  56. package/dist/audio/use-audio-recorder.js.map +1 -1
  57. package/dist/audio/use-audio.cjs.map +1 -1
  58. package/dist/audio/use-audio.js.map +1 -1
  59. package/dist/audio/use-microphone.cjs +1 -1
  60. package/dist/audio/use-microphone.cjs.map +1 -1
  61. package/dist/audio/use-microphone.js +1 -5
  62. package/dist/audio/use-microphone.js.map +1 -1
  63. package/dist/audio/use-sfx-pool.cjs.map +1 -1
  64. package/dist/audio/use-sfx-pool.js.map +1 -1
  65. package/dist/audio/voice-activity.cjs.map +1 -1
  66. package/dist/audio/voice-activity.js.map +1 -1
  67. package/dist/audio/voice-chain-stages.cjs.map +1 -1
  68. package/dist/audio/voice-chain-stages.js.map +1 -1
  69. package/dist/audio/voice-chain.cjs.map +1 -1
  70. package/dist/audio/voice-chain.js.map +1 -1
  71. package/dist/audio/wav.cjs.map +1 -1
  72. package/dist/audio/wav.js.map +1 -1
  73. package/dist/auth/AuthGuard.cjs.map +1 -1
  74. package/dist/auth/AuthGuard.js.map +1 -1
  75. package/dist/auth/create-auth-store.cjs.map +1 -1
  76. package/dist/auth/create-auth-store.js.map +1 -1
  77. package/dist/auth/create-tempest-auth.cjs +1 -1
  78. package/dist/auth/create-tempest-auth.cjs.map +1 -1
  79. package/dist/auth/create-tempest-auth.js +185 -114
  80. package/dist/auth/create-tempest-auth.js.map +1 -1
  81. package/dist/auth/jwt.cjs.map +1 -1
  82. package/dist/auth/jwt.js.map +1 -1
  83. package/dist/auth/lazy-with-retry.cjs.map +1 -1
  84. package/dist/auth/lazy-with-retry.js.map +1 -1
  85. package/dist/auth/passkey.cjs.map +1 -1
  86. package/dist/auth/passkey.js.map +1 -1
  87. package/dist/auth/refresh-queue.cjs.map +1 -1
  88. package/dist/auth/refresh-queue.js.map +1 -1
  89. package/dist/auth/use-passkey.cjs +1 -1
  90. package/dist/auth/use-passkey.cjs.map +1 -1
  91. package/dist/auth/use-passkey.js +1 -1
  92. package/dist/auth/use-passkey.js.map +1 -1
  93. package/dist/br/BrazilMap.cjs.map +1 -1
  94. package/dist/br/BrazilMap.js.map +1 -1
  95. package/dist/br/BrazilMap.module.cjs.map +1 -1
  96. package/dist/br/BrazilMap.module.js.map +1 -1
  97. package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
  98. package/dist/br/BrazilStateCitySelect.js.map +1 -1
  99. package/dist/br/BrazilStateMap.cjs.map +1 -1
  100. package/dist/br/BrazilStateMap.js.map +1 -1
  101. package/dist/br/MapLegend.cjs.map +1 -1
  102. package/dist/br/MapLegend.js.map +1 -1
  103. package/dist/br/MapLegend.module.cjs.map +1 -1
  104. package/dist/br/MapLegend.module.js.map +1 -1
  105. package/dist/br/MapMarkers.cjs.map +1 -1
  106. package/dist/br/MapMarkers.js.map +1 -1
  107. package/dist/br/MapTooltip.cjs.map +1 -1
  108. package/dist/br/MapTooltip.js.map +1 -1
  109. package/dist/br/MunicipalitySearch.cjs +1 -1
  110. package/dist/br/MunicipalitySearch.cjs.map +1 -1
  111. package/dist/br/MunicipalitySearch.js +2 -5
  112. package/dist/br/MunicipalitySearch.js.map +1 -1
  113. package/dist/br/MunicipalitySearch.module.cjs.map +1 -1
  114. package/dist/br/MunicipalitySearch.module.js.map +1 -1
  115. package/dist/br/PixQRCode.cjs.map +1 -1
  116. package/dist/br/PixQRCode.js.map +1 -1
  117. package/dist/br/PixQRCode.module.cjs.map +1 -1
  118. package/dist/br/PixQRCode.module.js.map +1 -1
  119. package/dist/br/boleto.cjs.map +1 -1
  120. package/dist/br/boleto.js.map +1 -1
  121. package/dist/br/br-geo.cjs.map +1 -1
  122. package/dist/br/br-geo.js.map +1 -1
  123. package/dist/br/data/br-centroids.cjs.map +1 -1
  124. package/dist/br/data/br-centroids.js.map +1 -1
  125. package/dist/br/data/br-locations.cjs.map +1 -1
  126. package/dist/br/data/br-locations.js.map +1 -1
  127. package/dist/br/data/br-uf-geo.cjs.map +1 -1
  128. package/dist/br/data/br-uf-geo.js.map +1 -1
  129. package/dist/br/data/mun/AC.cjs.map +1 -1
  130. package/dist/br/data/mun/AC.js.map +1 -1
  131. package/dist/br/data/mun/AL.cjs.map +1 -1
  132. package/dist/br/data/mun/AL.js.map +1 -1
  133. package/dist/br/data/mun/AM.cjs.map +1 -1
  134. package/dist/br/data/mun/AM.js.map +1 -1
  135. package/dist/br/data/mun/AP.cjs.map +1 -1
  136. package/dist/br/data/mun/AP.js.map +1 -1
  137. package/dist/br/data/mun/BA.cjs.map +1 -1
  138. package/dist/br/data/mun/BA.js.map +1 -1
  139. package/dist/br/data/mun/CE.cjs.map +1 -1
  140. package/dist/br/data/mun/CE.js.map +1 -1
  141. package/dist/br/data/mun/DF.cjs.map +1 -1
  142. package/dist/br/data/mun/DF.js.map +1 -1
  143. package/dist/br/data/mun/ES.cjs.map +1 -1
  144. package/dist/br/data/mun/ES.js.map +1 -1
  145. package/dist/br/data/mun/GO.cjs.map +1 -1
  146. package/dist/br/data/mun/GO.js.map +1 -1
  147. package/dist/br/data/mun/MA.cjs.map +1 -1
  148. package/dist/br/data/mun/MA.js.map +1 -1
  149. package/dist/br/data/mun/MG.cjs.map +1 -1
  150. package/dist/br/data/mun/MG.js.map +1 -1
  151. package/dist/br/data/mun/MS.cjs.map +1 -1
  152. package/dist/br/data/mun/MS.js.map +1 -1
  153. package/dist/br/data/mun/MT.cjs.map +1 -1
  154. package/dist/br/data/mun/MT.js.map +1 -1
  155. package/dist/br/data/mun/PA.cjs.map +1 -1
  156. package/dist/br/data/mun/PA.js.map +1 -1
  157. package/dist/br/data/mun/PB.cjs.map +1 -1
  158. package/dist/br/data/mun/PB.js.map +1 -1
  159. package/dist/br/data/mun/PE.cjs.map +1 -1
  160. package/dist/br/data/mun/PE.js.map +1 -1
  161. package/dist/br/data/mun/PI.cjs.map +1 -1
  162. package/dist/br/data/mun/PI.js.map +1 -1
  163. package/dist/br/data/mun/PR.cjs.map +1 -1
  164. package/dist/br/data/mun/PR.js.map +1 -1
  165. package/dist/br/data/mun/RJ.cjs.map +1 -1
  166. package/dist/br/data/mun/RJ.js.map +1 -1
  167. package/dist/br/data/mun/RN.cjs.map +1 -1
  168. package/dist/br/data/mun/RN.js.map +1 -1
  169. package/dist/br/data/mun/RO.cjs.map +1 -1
  170. package/dist/br/data/mun/RO.js.map +1 -1
  171. package/dist/br/data/mun/RR.cjs.map +1 -1
  172. package/dist/br/data/mun/RR.js.map +1 -1
  173. package/dist/br/data/mun/RS.cjs.map +1 -1
  174. package/dist/br/data/mun/RS.js.map +1 -1
  175. package/dist/br/data/mun/SC.cjs.map +1 -1
  176. package/dist/br/data/mun/SC.js.map +1 -1
  177. package/dist/br/data/mun/SE.cjs.map +1 -1
  178. package/dist/br/data/mun/SE.js.map +1 -1
  179. package/dist/br/data/mun/SP.cjs.map +1 -1
  180. package/dist/br/data/mun/SP.js.map +1 -1
  181. package/dist/br/data/mun/TO.cjs.map +1 -1
  182. package/dist/br/data/mun/TO.js.map +1 -1
  183. package/dist/br/geocode.cjs.map +1 -1
  184. package/dist/br/geocode.js.map +1 -1
  185. package/dist/br/holidays.cjs.map +1 -1
  186. package/dist/br/holidays.js.map +1 -1
  187. package/dist/br/locations.cjs.map +1 -1
  188. package/dist/br/locations.js.map +1 -1
  189. package/dist/br/nfe.cjs.map +1 -1
  190. package/dist/br/nfe.js.map +1 -1
  191. package/dist/br/pix.cjs +1 -1
  192. package/dist/br/pix.cjs.map +1 -1
  193. package/dist/br/pix.js +108 -71
  194. package/dist/br/pix.js.map +1 -1
  195. package/dist/br/regions.cjs.map +1 -1
  196. package/dist/br/regions.js.map +1 -1
  197. package/dist/br/scales.cjs.map +1 -1
  198. package/dist/br/scales.js.map +1 -1
  199. package/dist/br/state-geo.cjs.map +1 -1
  200. package/dist/br/state-geo.js.map +1 -1
  201. package/dist/br/svg-utils.cjs.map +1 -1
  202. package/dist/br/svg-utils.js.map +1 -1
  203. package/dist/br/use-map-hover.cjs.map +1 -1
  204. package/dist/br/use-map-hover.js.map +1 -1
  205. package/dist/br/use-map-zoom.cjs.map +1 -1
  206. package/dist/br/use-map-zoom.js.map +1 -1
  207. package/dist/br/whatsapp.cjs.map +1 -1
  208. package/dist/br/whatsapp.js.map +1 -1
  209. package/dist/br.cjs.map +1 -1
  210. package/dist/br.d.ts +16 -5
  211. package/dist/br.js.map +1 -1
  212. package/dist/capture/barcode.cjs.map +1 -1
  213. package/dist/capture/barcode.js.map +1 -1
  214. package/dist/capture/media-recorder.cjs.map +1 -1
  215. package/dist/capture/media-recorder.js.map +1 -1
  216. package/dist/capture/use-barcode-scanner.cjs.map +1 -1
  217. package/dist/capture/use-barcode-scanner.js.map +1 -1
  218. package/dist/capture/use-screen-capture.cjs +1 -1
  219. package/dist/capture/use-screen-capture.cjs.map +1 -1
  220. package/dist/capture/use-screen-capture.js +1 -7
  221. package/dist/capture/use-screen-capture.js.map +1 -1
  222. package/dist/capture/use-speech-recognition.cjs +1 -1
  223. package/dist/capture/use-speech-recognition.cjs.map +1 -1
  224. package/dist/capture/use-speech-recognition.js +35 -36
  225. package/dist/capture/use-speech-recognition.js.map +1 -1
  226. package/dist/capture/use-torch.cjs.map +1 -1
  227. package/dist/capture/use-torch.js.map +1 -1
  228. package/dist/capture/use-video-recorder.cjs.map +1 -1
  229. package/dist/capture/use-video-recorder.js.map +1 -1
  230. package/dist/capture/video-recorder.cjs.map +1 -1
  231. package/dist/capture/video-recorder.js.map +1 -1
  232. package/dist/charts/AreaChart.cjs.map +1 -1
  233. package/dist/charts/AreaChart.js.map +1 -1
  234. package/dist/charts/BarChart.cjs.map +1 -1
  235. package/dist/charts/BarChart.js.map +1 -1
  236. package/dist/charts/LineChart.cjs.map +1 -1
  237. package/dist/charts/LineChart.js.map +1 -1
  238. package/dist/charts/PieChart.cjs.map +1 -1
  239. package/dist/charts/PieChart.js.map +1 -1
  240. package/dist/charts/RadarChart.cjs.map +1 -1
  241. package/dist/charts/RadarChart.js.map +1 -1
  242. package/dist/charts/palette.cjs.map +1 -1
  243. package/dist/charts/palette.js.map +1 -1
  244. package/dist/charts/scales.cjs.map +1 -1
  245. package/dist/charts/scales.js.map +1 -1
  246. package/dist/charts/types.cjs.map +1 -1
  247. package/dist/charts/types.js.map +1 -1
  248. package/dist/charts/use-chart-colors.cjs.map +1 -1
  249. package/dist/charts/use-chart-colors.js.map +1 -1
  250. package/dist/components/AIChat/AIChat.cjs +1 -1
  251. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  252. package/dist/components/AIChat/AIChat.js +1 -5
  253. package/dist/components/AIChat/AIChat.js.map +1 -1
  254. package/dist/components/AIChat/AIChat.module.cjs.map +1 -1
  255. package/dist/components/AIChat/AIChat.module.js.map +1 -1
  256. package/dist/components/AIChat/AIChatComposer.cjs +1 -1
  257. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  258. package/dist/components/AIChat/AIChatComposer.js +1 -7
  259. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  260. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  261. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  262. package/dist/components/AIChat/ai-chat-turns.cjs.map +1 -1
  263. package/dist/components/AIChat/ai-chat-turns.js.map +1 -1
  264. package/dist/components/Accordion/Accordion.cjs.map +1 -1
  265. package/dist/components/Accordion/Accordion.js.map +1 -1
  266. package/dist/components/Accordion/Accordion.module.cjs.map +1 -1
  267. package/dist/components/Accordion/Accordion.module.js.map +1 -1
  268. package/dist/components/Alert/Alert.cjs.map +1 -1
  269. package/dist/components/Alert/Alert.js.map +1 -1
  270. package/dist/components/Alert/Alert.module.cjs.map +1 -1
  271. package/dist/components/Alert/Alert.module.js.map +1 -1
  272. package/dist/components/AppBar/AppBar.cjs.map +1 -1
  273. package/dist/components/AppBar/AppBar.js.map +1 -1
  274. package/dist/components/AppBar/AppBar.module.cjs.map +1 -1
  275. package/dist/components/AppBar/AppBar.module.js.map +1 -1
  276. package/dist/components/AppBar/use-sticky-body-warning.cjs +1 -1
  277. package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
  278. package/dist/components/AppBar/use-sticky-body-warning.js +1 -1
  279. package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
  280. package/dist/components/AppShell/AppShell.cjs.map +1 -1
  281. package/dist/components/AppShell/AppShell.js.map +1 -1
  282. package/dist/components/AppShell/AppShell.module.cjs.map +1 -1
  283. package/dist/components/AppShell/AppShell.module.js.map +1 -1
  284. package/dist/components/AspectRatio/AspectRatio.cjs.map +1 -1
  285. package/dist/components/AspectRatio/AspectRatio.js.map +1 -1
  286. package/dist/components/AspectRatio/AspectRatio.module.cjs.map +1 -1
  287. package/dist/components/AspectRatio/AspectRatio.module.js.map +1 -1
  288. package/dist/components/AudioPlayer/AudioPlayer.cjs +1 -1
  289. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
  290. package/dist/components/AudioPlayer/AudioPlayer.js +1 -7
  291. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
  292. package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -1
  293. package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -1
  294. package/dist/components/AudioRecorder/AudioRecorder.cjs +1 -1
  295. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
  296. package/dist/components/AudioRecorder/AudioRecorder.js +16 -21
  297. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
  298. package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -1
  299. package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -1
  300. package/dist/components/Avatar/Avatar.cjs.map +1 -1
  301. package/dist/components/Avatar/Avatar.js.map +1 -1
  302. package/dist/components/Avatar/Avatar.module.cjs.map +1 -1
  303. package/dist/components/Avatar/Avatar.module.js.map +1 -1
  304. package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
  305. package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
  306. package/dist/components/AvatarGroup/AvatarGroup.module.cjs.map +1 -1
  307. package/dist/components/AvatarGroup/AvatarGroup.module.js.map +1 -1
  308. package/dist/components/Badge/Badge.cjs.map +1 -1
  309. package/dist/components/Badge/Badge.js.map +1 -1
  310. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  311. package/dist/components/Badge/Badge.module.js.map +1 -1
  312. package/dist/components/Banner/Banner.cjs.map +1 -1
  313. package/dist/components/Banner/Banner.js.map +1 -1
  314. package/dist/components/Banner/Banner.module.cjs.map +1 -1
  315. package/dist/components/Banner/Banner.module.js.map +1 -1
  316. package/dist/components/BarList/BarList.cjs.map +1 -1
  317. package/dist/components/BarList/BarList.js.map +1 -1
  318. package/dist/components/BarList/BarList.module.cjs.map +1 -1
  319. package/dist/components/BarList/BarList.module.js.map +1 -1
  320. package/dist/components/BarList/bar-list-model.cjs.map +1 -1
  321. package/dist/components/BarList/bar-list-model.js.map +1 -1
  322. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
  323. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
  324. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -1
  325. package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -1
  326. package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
  327. package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
  328. package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
  329. package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
  330. package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
  331. package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
  332. package/dist/components/BottomSheet/BottomSheet.module.cjs.map +1 -1
  333. package/dist/components/BottomSheet/BottomSheet.module.js.map +1 -1
  334. package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
  335. package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
  336. package/dist/components/Breadcrumbs/Breadcrumbs.module.cjs.map +1 -1
  337. package/dist/components/Breadcrumbs/Breadcrumbs.module.js.map +1 -1
  338. package/dist/components/Button/Button.cjs.map +1 -1
  339. package/dist/components/Button/Button.js.map +1 -1
  340. package/dist/components/Button/Button.module.cjs.map +1 -1
  341. package/dist/components/Button/Button.module.js.map +1 -1
  342. package/dist/components/Button/ButtonContent.cjs.map +1 -1
  343. package/dist/components/Button/ButtonContent.js.map +1 -1
  344. package/dist/components/Button/ButtonSlot.cjs.map +1 -1
  345. package/dist/components/Button/ButtonSlot.js.map +1 -1
  346. package/dist/components/Button/button-class.cjs.map +1 -1
  347. package/dist/components/Button/button-class.js.map +1 -1
  348. package/dist/components/Button/link-rel.cjs.map +1 -1
  349. package/dist/components/Button/link-rel.js.map +1 -1
  350. package/dist/components/Button/slot.cjs.map +1 -1
  351. package/dist/components/Button/slot.js.map +1 -1
  352. package/dist/components/Calendar/Calendar.cjs.map +1 -1
  353. package/dist/components/Calendar/Calendar.js.map +1 -1
  354. package/dist/components/Calendar/Calendar.module.cjs.map +1 -1
  355. package/dist/components/Calendar/Calendar.module.js.map +1 -1
  356. package/dist/components/Card/Card.cjs.map +1 -1
  357. package/dist/components/Card/Card.js.map +1 -1
  358. package/dist/components/Card/Card.module.cjs.map +1 -1
  359. package/dist/components/Card/Card.module.js.map +1 -1
  360. package/dist/components/Carousel/Carousel.cjs.map +1 -1
  361. package/dist/components/Carousel/Carousel.js.map +1 -1
  362. package/dist/components/Carousel/Carousel.module.cjs.map +1 -1
  363. package/dist/components/Carousel/Carousel.module.js.map +1 -1
  364. package/dist/components/Center/Center.cjs.map +1 -1
  365. package/dist/components/Center/Center.js.map +1 -1
  366. package/dist/components/Center/Center.module.cjs.map +1 -1
  367. package/dist/components/Center/Center.module.js.map +1 -1
  368. package/dist/components/Chat/Chat.cjs.map +1 -1
  369. package/dist/components/Chat/Chat.js.map +1 -1
  370. package/dist/components/Chat/Chat.module.cjs.map +1 -1
  371. package/dist/components/Chat/Chat.module.js.map +1 -1
  372. package/dist/components/Chat/ChatActionsMenu.cjs.map +1 -1
  373. package/dist/components/Chat/ChatActionsMenu.js.map +1 -1
  374. package/dist/components/Chat/ChatAttachments.cjs.map +1 -1
  375. package/dist/components/Chat/ChatAttachments.js.map +1 -1
  376. package/dist/components/Chat/ChatBubble.cjs.map +1 -1
  377. package/dist/components/Chat/ChatBubble.js.map +1 -1
  378. package/dist/components/Chat/ChatComposer.cjs.map +1 -1
  379. package/dist/components/Chat/ChatComposer.js.map +1 -1
  380. package/dist/components/Chat/chat-groups.cjs +1 -1
  381. package/dist/components/Chat/chat-groups.cjs.map +1 -1
  382. package/dist/components/Chat/chat-groups.js +2 -6
  383. package/dist/components/Chat/chat-groups.js.map +1 -1
  384. package/dist/components/Chat/chat-receipt.cjs.map +1 -1
  385. package/dist/components/Chat/chat-receipt.js.map +1 -1
  386. package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
  387. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  388. package/dist/components/Checkbox/Checkbox.module.cjs.map +1 -1
  389. package/dist/components/Checkbox/Checkbox.module.js.map +1 -1
  390. package/dist/components/ChipInput/ChipInput.cjs +1 -1
  391. package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
  392. package/dist/components/ChipInput/ChipInput.js +2 -12
  393. package/dist/components/ChipInput/ChipInput.js.map +1 -1
  394. package/dist/components/ChipInput/ChipInput.module.cjs.map +1 -1
  395. package/dist/components/ChipInput/ChipInput.module.js.map +1 -1
  396. package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
  397. package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
  398. package/dist/components/CodeBlock/CodeBlock.cjs +1 -1
  399. package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
  400. package/dist/components/CodeBlock/CodeBlock.js +1 -1
  401. package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
  402. package/dist/components/CodeBlock/CodeBlock.module.cjs.map +1 -1
  403. package/dist/components/CodeBlock/CodeBlock.module.js.map +1 -1
  404. package/dist/components/CodeBlock/tokenize.cjs +1 -1
  405. package/dist/components/CodeBlock/tokenize.cjs.map +1 -1
  406. package/dist/components/CodeBlock/tokenize.js +54 -25
  407. package/dist/components/CodeBlock/tokenize.js.map +1 -1
  408. package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
  409. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  410. package/dist/components/Collapsible/Collapsible.module.cjs.map +1 -1
  411. package/dist/components/Collapsible/Collapsible.module.js.map +1 -1
  412. package/dist/components/Combobox/Combobox.cjs.map +1 -1
  413. package/dist/components/Combobox/Combobox.js.map +1 -1
  414. package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
  415. package/dist/components/Combobox/Combobox.module.js.map +1 -1
  416. package/dist/components/Combobox/use-listbox-dismiss.cjs.map +1 -1
  417. package/dist/components/Combobox/use-listbox-dismiss.js.map +1 -1
  418. package/dist/components/Command/Command.cjs +1 -1
  419. package/dist/components/Command/Command.cjs.map +1 -1
  420. package/dist/components/Command/Command.js +4 -11
  421. package/dist/components/Command/Command.js.map +1 -1
  422. package/dist/components/Command/Command.module.cjs.map +1 -1
  423. package/dist/components/Command/Command.module.js.map +1 -1
  424. package/dist/components/ConditionalWrapper/ConditionalWrapper.cjs.map +1 -1
  425. package/dist/components/ConditionalWrapper/ConditionalWrapper.js.map +1 -1
  426. package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
  427. package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
  428. package/dist/components/ContextMenu/ContextMenu.cjs +1 -1
  429. package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
  430. package/dist/components/ContextMenu/ContextMenu.js +1 -1
  431. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  432. package/dist/components/ContextMenu/ContextMenu.module.cjs.map +1 -1
  433. package/dist/components/ContextMenu/ContextMenu.module.js.map +1 -1
  434. package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
  435. package/dist/components/CopyButton/CopyButton.js.map +1 -1
  436. package/dist/components/CopyButton/CopyButton.module.cjs.map +1 -1
  437. package/dist/components/CopyButton/CopyButton.module.js.map +1 -1
  438. package/dist/components/DataList/DataList.cjs.map +1 -1
  439. package/dist/components/DataList/DataList.js.map +1 -1
  440. package/dist/components/DataList/DataList.module.cjs.map +1 -1
  441. package/dist/components/DataList/DataList.module.js.map +1 -1
  442. package/dist/components/DataTable/DataTable.cjs +1 -1
  443. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  444. package/dist/components/DataTable/DataTable.js +6 -14
  445. package/dist/components/DataTable/DataTable.js.map +1 -1
  446. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  447. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  448. package/dist/components/DataTable/EditableCell.cjs +1 -1
  449. package/dist/components/DataTable/EditableCell.cjs.map +1 -1
  450. package/dist/components/DataTable/EditableCell.js +1 -9
  451. package/dist/components/DataTable/EditableCell.js.map +1 -1
  452. package/dist/components/DataTable/LoadingRows.cjs.map +1 -1
  453. package/dist/components/DataTable/LoadingRows.js.map +1 -1
  454. package/dist/components/DataTable/edit-labels.cjs.map +1 -1
  455. package/dist/components/DataTable/edit-labels.js.map +1 -1
  456. package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
  457. package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
  458. package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
  459. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  460. package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
  461. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  462. package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
  463. package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
  464. package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
  465. package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
  466. package/dist/components/DescriptionList/DescriptionList.module.cjs.map +1 -1
  467. package/dist/components/DescriptionList/DescriptionList.module.js.map +1 -1
  468. package/dist/components/Divider/Divider.cjs.map +1 -1
  469. package/dist/components/Divider/Divider.js.map +1 -1
  470. package/dist/components/Divider/Divider.module.cjs.map +1 -1
  471. package/dist/components/Divider/Divider.module.js.map +1 -1
  472. package/dist/components/Drawer/Drawer.cjs.map +1 -1
  473. package/dist/components/Drawer/Drawer.js.map +1 -1
  474. package/dist/components/Drawer/Drawer.module.cjs.map +1 -1
  475. package/dist/components/Drawer/Drawer.module.js.map +1 -1
  476. package/dist/components/DropdownMenu/DropdownMenu.cjs +1 -1
  477. package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  478. package/dist/components/DropdownMenu/DropdownMenu.js +2 -14
  479. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  480. package/dist/components/DropdownMenu/DropdownMenu.module.cjs.map +1 -1
  481. package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -1
  482. package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
  483. package/dist/components/Dropzone/Dropzone.js.map +1 -1
  484. package/dist/components/Dropzone/Dropzone.module.cjs.map +1 -1
  485. package/dist/components/Dropzone/Dropzone.module.js.map +1 -1
  486. package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
  487. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  488. package/dist/components/EmptyState/EmptyState.module.cjs.map +1 -1
  489. package/dist/components/EmptyState/EmptyState.module.js.map +1 -1
  490. package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
  491. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  492. package/dist/components/ErrorState/ErrorState.module.cjs.map +1 -1
  493. package/dist/components/ErrorState/ErrorState.module.js.map +1 -1
  494. package/dist/components/ErrorText/ErrorText.cjs.map +1 -1
  495. package/dist/components/ErrorText/ErrorText.js.map +1 -1
  496. package/dist/components/ErrorText/ErrorText.module.cjs.map +1 -1
  497. package/dist/components/ErrorText/ErrorText.module.js.map +1 -1
  498. package/dist/components/FileUpload/FileUpload.cjs +1 -1
  499. package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
  500. package/dist/components/FileUpload/FileUpload.js +7 -17
  501. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  502. package/dist/components/FileUpload/FileUpload.module.cjs.map +1 -1
  503. package/dist/components/FileUpload/FileUpload.module.js.map +1 -1
  504. package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
  505. package/dist/components/FilterBar/FilterBar.js.map +1 -1
  506. package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -1
  507. package/dist/components/FilterBar/FilterBar.module.js.map +1 -1
  508. package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
  509. package/dist/components/FilterBar/filter-apply.js.map +1 -1
  510. package/dist/components/FilterBar/filter-model.cjs.map +1 -1
  511. package/dist/components/FilterBar/filter-model.js.map +1 -1
  512. package/dist/components/FilterBar/filter-query.cjs +1 -1
  513. package/dist/components/FilterBar/filter-query.cjs.map +1 -1
  514. package/dist/components/FilterBar/filter-query.js +2 -5
  515. package/dist/components/FilterBar/filter-query.js.map +1 -1
  516. package/dist/components/FilterPanel/FilterPanel.cjs.map +1 -1
  517. package/dist/components/FilterPanel/FilterPanel.js.map +1 -1
  518. package/dist/components/FilterPanel/FilterPanel.module.cjs.map +1 -1
  519. package/dist/components/FilterPanel/FilterPanel.module.js.map +1 -1
  520. package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
  521. package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
  522. package/dist/components/FloatingActionButton/FloatingActionButton.module.cjs.map +1 -1
  523. package/dist/components/FloatingActionButton/FloatingActionButton.module.js.map +1 -1
  524. package/dist/components/For/For.cjs.map +1 -1
  525. package/dist/components/For/For.js.map +1 -1
  526. package/dist/components/Form/Form.cjs.map +1 -1
  527. package/dist/components/Form/Form.js.map +1 -1
  528. package/dist/components/Form/Form.module.cjs.map +1 -1
  529. package/dist/components/Form/Form.module.js.map +1 -1
  530. package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
  531. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  532. package/dist/components/HoverCard/HoverCard.module.cjs.map +1 -1
  533. package/dist/components/HoverCard/HoverCard.module.js.map +1 -1
  534. package/dist/components/Image/Image.cjs.map +1 -1
  535. package/dist/components/Image/Image.js.map +1 -1
  536. package/dist/components/Image/Image.module.cjs.map +1 -1
  537. package/dist/components/Image/Image.module.js.map +1 -1
  538. package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
  539. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
  540. package/dist/components/ImageCropper/ImageCropper.js +4 -8
  541. package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
  542. package/dist/components/ImageCropper/ImageCropper.module.cjs.map +1 -1
  543. package/dist/components/ImageCropper/ImageCropper.module.js.map +1 -1
  544. package/dist/components/ImageCropper/crop-geometry.cjs.map +1 -1
  545. package/dist/components/ImageCropper/crop-geometry.js.map +1 -1
  546. package/dist/components/Input/Input.cjs.map +1 -1
  547. package/dist/components/Input/Input.js.map +1 -1
  548. package/dist/components/Input/Input.module.cjs.map +1 -1
  549. package/dist/components/Input/Input.module.js.map +1 -1
  550. package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
  551. package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
  552. package/dist/components/InstallBanner/InstallBanner.module.cjs.map +1 -1
  553. package/dist/components/InstallBanner/InstallBanner.module.js.map +1 -1
  554. package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
  555. package/dist/components/InstallButton/InstallButton.js.map +1 -1
  556. package/dist/components/InstallButton/InstallButton.module.cjs.map +1 -1
  557. package/dist/components/InstallButton/InstallButton.module.js.map +1 -1
  558. package/dist/components/InstallButton/install-hints.cjs.map +1 -1
  559. package/dist/components/InstallButton/install-hints.js.map +1 -1
  560. package/dist/components/Kanban/Kanban.cjs.map +1 -1
  561. package/dist/components/Kanban/Kanban.js.map +1 -1
  562. package/dist/components/Kanban/Kanban.module.cjs.map +1 -1
  563. package/dist/components/Kanban/Kanban.module.js.map +1 -1
  564. package/dist/components/Kbd/Kbd.cjs.map +1 -1
  565. package/dist/components/Kbd/Kbd.js.map +1 -1
  566. package/dist/components/Kbd/Kbd.module.cjs.map +1 -1
  567. package/dist/components/Kbd/Kbd.module.js.map +1 -1
  568. package/dist/components/Label/Label.cjs.map +1 -1
  569. package/dist/components/Label/Label.js.map +1 -1
  570. package/dist/components/Label/Label.module.cjs.map +1 -1
  571. package/dist/components/Label/Label.module.js.map +1 -1
  572. package/dist/components/Layout/Layout.cjs.map +1 -1
  573. package/dist/components/Layout/Layout.js.map +1 -1
  574. package/dist/components/Layout/Layout.module.cjs.map +1 -1
  575. package/dist/components/Layout/Layout.module.js.map +1 -1
  576. package/dist/components/Lightbox/Lightbox.cjs +1 -1
  577. package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
  578. package/dist/components/Lightbox/Lightbox.js +1 -1
  579. package/dist/components/Lightbox/Lightbox.js.map +1 -1
  580. package/dist/components/Lightbox/Lightbox.module.cjs.map +1 -1
  581. package/dist/components/Lightbox/Lightbox.module.js.map +1 -1
  582. package/dist/components/ListTile/ListTile.cjs.map +1 -1
  583. package/dist/components/ListTile/ListTile.js.map +1 -1
  584. package/dist/components/ListTile/ListTile.module.cjs.map +1 -1
  585. package/dist/components/ListTile/ListTile.module.js.map +1 -1
  586. package/dist/components/Markdown/Markdown.cjs.map +1 -1
  587. package/dist/components/Markdown/Markdown.js.map +1 -1
  588. package/dist/components/Markdown/Markdown.module.cjs.map +1 -1
  589. package/dist/components/Markdown/Markdown.module.js.map +1 -1
  590. package/dist/components/Markdown/markdown-parse.cjs +6 -6
  591. package/dist/components/Markdown/markdown-parse.cjs.map +1 -1
  592. package/dist/components/Markdown/markdown-parse.js +94 -96
  593. package/dist/components/Markdown/markdown-parse.js.map +1 -1
  594. package/dist/components/Masonry/Masonry.cjs.map +1 -1
  595. package/dist/components/Masonry/Masonry.js.map +1 -1
  596. package/dist/components/Masonry/Masonry.module.cjs.map +1 -1
  597. package/dist/components/Masonry/Masonry.module.js.map +1 -1
  598. package/dist/components/Masonry/masonry-layout.cjs.map +1 -1
  599. package/dist/components/Masonry/masonry-layout.js.map +1 -1
  600. package/dist/components/Menubar/Menubar.cjs.map +1 -1
  601. package/dist/components/Menubar/Menubar.js.map +1 -1
  602. package/dist/components/Menubar/Menubar.module.cjs.map +1 -1
  603. package/dist/components/Menubar/Menubar.module.js.map +1 -1
  604. package/dist/components/Modal/Modal.cjs.map +1 -1
  605. package/dist/components/Modal/Modal.js.map +1 -1
  606. package/dist/components/Modal/Modal.module.cjs.map +1 -1
  607. package/dist/components/Modal/Modal.module.js.map +1 -1
  608. package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
  609. package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
  610. package/dist/components/ModalsManager/ModalsManager.module.cjs.map +1 -1
  611. package/dist/components/ModalsManager/ModalsManager.module.js.map +1 -1
  612. package/dist/components/Money/Money.cjs.map +1 -1
  613. package/dist/components/Money/Money.js.map +1 -1
  614. package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
  615. package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
  616. package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
  617. package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
  618. package/dist/components/NProgress/NProgress.cjs.map +1 -1
  619. package/dist/components/NProgress/NProgress.js.map +1 -1
  620. package/dist/components/NProgress/NProgress.module.cjs.map +1 -1
  621. package/dist/components/NProgress/NProgress.module.js.map +1 -1
  622. package/dist/components/Navbar/Navbar.cjs.map +1 -1
  623. package/dist/components/Navbar/Navbar.js.map +1 -1
  624. package/dist/components/Navbar/Navbar.module.cjs.map +1 -1
  625. package/dist/components/Navbar/Navbar.module.js.map +1 -1
  626. package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
  627. package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
  628. package/dist/components/NavigationMenu/NavigationMenu.module.cjs.map +1 -1
  629. package/dist/components/NavigationMenu/NavigationMenu.module.js.map +1 -1
  630. package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
  631. package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
  632. package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
  633. package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
  634. package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
  635. package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
  636. package/dist/components/NotificationCenter/NotificationCenter.module.cjs.map +1 -1
  637. package/dist/components/NotificationCenter/NotificationCenter.module.js.map +1 -1
  638. package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
  639. package/dist/components/NotificationCenter/use-notification-inbox.js.map +1 -1
  640. package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
  641. package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
  642. package/dist/components/OfflineIndicator/OfflineIndicator.module.cjs.map +1 -1
  643. package/dist/components/OfflineIndicator/OfflineIndicator.module.js.map +1 -1
  644. package/dist/components/Page/Page.cjs.map +1 -1
  645. package/dist/components/Page/Page.js.map +1 -1
  646. package/dist/components/Page/Page.module.cjs.map +1 -1
  647. package/dist/components/Page/Page.module.js.map +1 -1
  648. package/dist/components/Pagination/Pagination.cjs.map +1 -1
  649. package/dist/components/Pagination/Pagination.js.map +1 -1
  650. package/dist/components/Pagination/Pagination.module.cjs.map +1 -1
  651. package/dist/components/Pagination/Pagination.module.js.map +1 -1
  652. package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
  653. package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
  654. package/dist/components/PasswordInput/PasswordInput.module.cjs.map +1 -1
  655. package/dist/components/PasswordInput/PasswordInput.module.js.map +1 -1
  656. package/dist/components/PinInput/PinInput.cjs.map +1 -1
  657. package/dist/components/PinInput/PinInput.js.map +1 -1
  658. package/dist/components/PinInput/PinInput.module.cjs.map +1 -1
  659. package/dist/components/PinInput/PinInput.module.js.map +1 -1
  660. package/dist/components/Popover/Popover.cjs.map +1 -1
  661. package/dist/components/Popover/Popover.js.map +1 -1
  662. package/dist/components/Popover/Popover.module.cjs.map +1 -1
  663. package/dist/components/Popover/Popover.module.js.map +1 -1
  664. package/dist/components/Portal/Portal.cjs.map +1 -1
  665. package/dist/components/Portal/Portal.js.map +1 -1
  666. package/dist/components/Portal/anchor-position.cjs.map +1 -1
  667. package/dist/components/Portal/anchor-position.js.map +1 -1
  668. package/dist/components/Portal/escape-layer.cjs.map +1 -1
  669. package/dist/components/Portal/escape-layer.js.map +1 -1
  670. package/dist/components/Portal/portal-host.cjs.map +1 -1
  671. package/dist/components/Portal/portal-host.js.map +1 -1
  672. package/dist/components/Portal/tab-bridge.cjs +1 -1
  673. package/dist/components/Portal/tab-bridge.cjs.map +1 -1
  674. package/dist/components/Portal/tab-bridge.js +1 -5
  675. package/dist/components/Portal/tab-bridge.js.map +1 -1
  676. package/dist/components/Progress/Progress.cjs.map +1 -1
  677. package/dist/components/Progress/Progress.js.map +1 -1
  678. package/dist/components/Progress/Progress.module.cjs.map +1 -1
  679. package/dist/components/Progress/Progress.module.js.map +1 -1
  680. package/dist/components/QRCode/QRCode.cjs.map +1 -1
  681. package/dist/components/QRCode/QRCode.js.map +1 -1
  682. package/dist/components/QRCode/QRCode.module.cjs.map +1 -1
  683. package/dist/components/QRCode/QRCode.module.js.map +1 -1
  684. package/dist/components/QRCode/qr-encode.cjs +1 -1
  685. package/dist/components/QRCode/qr-encode.cjs.map +1 -1
  686. package/dist/components/QRCode/qr-encode.js +7 -13
  687. package/dist/components/QRCode/qr-encode.js.map +1 -1
  688. package/dist/components/QRCode/qr-tables.cjs.map +1 -1
  689. package/dist/components/QRCode/qr-tables.js.map +1 -1
  690. package/dist/components/Radio/Radio.cjs.map +1 -1
  691. package/dist/components/Radio/Radio.js.map +1 -1
  692. package/dist/components/Radio/Radio.module.cjs.map +1 -1
  693. package/dist/components/Radio/Radio.module.js.map +1 -1
  694. package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
  695. package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
  696. package/dist/components/RangeSlider/RangeSlider.module.cjs.map +1 -1
  697. package/dist/components/RangeSlider/RangeSlider.module.js.map +1 -1
  698. package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
  699. package/dist/components/RatingStars/RatingStars.js.map +1 -1
  700. package/dist/components/RatingStars/RatingStars.module.cjs.map +1 -1
  701. package/dist/components/RatingStars/RatingStars.module.js.map +1 -1
  702. package/dist/components/RefreshIndicator/RefreshIndicator.cjs +1 -1
  703. package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
  704. package/dist/components/RefreshIndicator/RefreshIndicator.js +10 -18
  705. package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
  706. package/dist/components/RefreshIndicator/RefreshIndicator.module.cjs.map +1 -1
  707. package/dist/components/RefreshIndicator/RefreshIndicator.module.js.map +1 -1
  708. package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
  709. package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
  710. package/dist/components/Resizable/Resizable.cjs +1 -1
  711. package/dist/components/Resizable/Resizable.cjs.map +1 -1
  712. package/dist/components/Resizable/Resizable.js +1 -9
  713. package/dist/components/Resizable/Resizable.js.map +1 -1
  714. package/dist/components/Resizable/Resizable.module.cjs.map +1 -1
  715. package/dist/components/Resizable/Resizable.module.js.map +1 -1
  716. package/dist/components/Responsive/Responsive.cjs.map +1 -1
  717. package/dist/components/Responsive/Responsive.js.map +1 -1
  718. package/dist/components/Reveal/Reveal.cjs.map +1 -1
  719. package/dist/components/Reveal/Reveal.js.map +1 -1
  720. package/dist/components/Reveal/Reveal.module.cjs.map +1 -1
  721. package/dist/components/Reveal/Reveal.module.js.map +1 -1
  722. package/dist/components/Reveal/reveal-threshold.cjs.map +1 -1
  723. package/dist/components/Reveal/reveal-threshold.js.map +1 -1
  724. package/dist/components/SafeArea/SafeArea.cjs.map +1 -1
  725. package/dist/components/SafeArea/SafeArea.js.map +1 -1
  726. package/dist/components/SafeArea/SafeArea.module.cjs.map +1 -1
  727. package/dist/components/SafeArea/SafeArea.module.js.map +1 -1
  728. package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
  729. package/dist/components/Scheduler/Scheduler.js.map +1 -1
  730. package/dist/components/Scheduler/Scheduler.module.cjs.map +1 -1
  731. package/dist/components/Scheduler/Scheduler.module.js.map +1 -1
  732. package/dist/components/Scheduler/scheduler-layout.cjs.map +1 -1
  733. package/dist/components/Scheduler/scheduler-layout.js.map +1 -1
  734. package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
  735. package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
  736. package/dist/components/ScrollArea/ScrollArea.module.cjs.map +1 -1
  737. package/dist/components/ScrollArea/ScrollArea.module.js.map +1 -1
  738. package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
  739. package/dist/components/SearchBar/SearchBar.js.map +1 -1
  740. package/dist/components/SearchBar/SearchBar.module.cjs.map +1 -1
  741. package/dist/components/SearchBar/SearchBar.module.js.map +1 -1
  742. package/dist/components/SectionHeader/SectionHeader.cjs.map +1 -1
  743. package/dist/components/SectionHeader/SectionHeader.js.map +1 -1
  744. package/dist/components/SectionHeader/SectionHeader.module.cjs.map +1 -1
  745. package/dist/components/SectionHeader/SectionHeader.module.js.map +1 -1
  746. package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
  747. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  748. package/dist/components/SegmentedControl/SegmentedControl.module.cjs.map +1 -1
  749. package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -1
  750. package/dist/components/Select/CaretIcon.cjs.map +1 -1
  751. package/dist/components/Select/CaretIcon.js.map +1 -1
  752. package/dist/components/Select/Select.cjs.map +1 -1
  753. package/dist/components/Select/Select.js.map +1 -1
  754. package/dist/components/Select/Select.module.cjs.map +1 -1
  755. package/dist/components/Select/Select.module.js.map +1 -1
  756. package/dist/components/Select/options.cjs.map +1 -1
  757. package/dist/components/Select/options.js.map +1 -1
  758. package/dist/components/Sidebar/Sidebar.cjs +1 -1
  759. package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
  760. package/dist/components/Sidebar/Sidebar.js +13 -23
  761. package/dist/components/Sidebar/Sidebar.js.map +1 -1
  762. package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
  763. package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
  764. package/dist/components/Sidebar/SidebarEntry.cjs.map +1 -1
  765. package/dist/components/Sidebar/SidebarEntry.js.map +1 -1
  766. package/dist/components/Sidebar/active-nav-key.cjs.map +1 -1
  767. package/dist/components/Sidebar/active-nav-key.js.map +1 -1
  768. package/dist/components/SignaturePad/SignaturePad.cjs +1 -1
  769. package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
  770. package/dist/components/SignaturePad/SignaturePad.js +1 -5
  771. package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
  772. package/dist/components/SignaturePad/SignaturePad.module.cjs.map +1 -1
  773. package/dist/components/SignaturePad/SignaturePad.module.js.map +1 -1
  774. package/dist/components/Skeleton/Skeleton.cjs.map +1 -1
  775. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  776. package/dist/components/Skeleton/Skeleton.module.cjs.map +1 -1
  777. package/dist/components/Skeleton/Skeleton.module.js.map +1 -1
  778. package/dist/components/Slider/Slider.cjs.map +1 -1
  779. package/dist/components/Slider/Slider.js.map +1 -1
  780. package/dist/components/Slider/Slider.module.cjs.map +1 -1
  781. package/dist/components/Slider/Slider.module.js.map +1 -1
  782. package/dist/components/Spacer/Spacer.cjs.map +1 -1
  783. package/dist/components/Spacer/Spacer.js.map +1 -1
  784. package/dist/components/Spacer/Spacer.module.cjs.map +1 -1
  785. package/dist/components/Spacer/Spacer.module.js.map +1 -1
  786. package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
  787. package/dist/components/Sparkline/Sparkline.js.map +1 -1
  788. package/dist/components/Sparkline/Sparkline.module.cjs.map +1 -1
  789. package/dist/components/Sparkline/Sparkline.module.js.map +1 -1
  790. package/dist/components/Sparkline/sparkline-geometry.cjs.map +1 -1
  791. package/dist/components/Sparkline/sparkline-geometry.js.map +1 -1
  792. package/dist/components/Spinner/Spinner.cjs.map +1 -1
  793. package/dist/components/Spinner/Spinner.js.map +1 -1
  794. package/dist/components/Spinner/Spinner.module.cjs.map +1 -1
  795. package/dist/components/Spinner/Spinner.module.js.map +1 -1
  796. package/dist/components/Stat/Stat.cjs.map +1 -1
  797. package/dist/components/Stat/Stat.js.map +1 -1
  798. package/dist/components/Stat/Stat.module.cjs.map +1 -1
  799. package/dist/components/Stat/Stat.module.js.map +1 -1
  800. package/dist/components/Stepper/Stepper.cjs.map +1 -1
  801. package/dist/components/Stepper/Stepper.js.map +1 -1
  802. package/dist/components/Stepper/Stepper.module.cjs.map +1 -1
  803. package/dist/components/Stepper/Stepper.module.js.map +1 -1
  804. package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
  805. package/dist/components/StepperInput/StepperInput.js.map +1 -1
  806. package/dist/components/StepperInput/StepperInput.module.cjs.map +1 -1
  807. package/dist/components/StepperInput/StepperInput.module.js.map +1 -1
  808. package/dist/components/Switch/Switch.cjs.map +1 -1
  809. package/dist/components/Switch/Switch.js.map +1 -1
  810. package/dist/components/Switch/Switch.module.cjs.map +1 -1
  811. package/dist/components/Switch/Switch.module.js.map +1 -1
  812. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
  813. package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
  814. package/dist/components/SyncStatusBadge/SyncStatusBadge.module.cjs.map +1 -1
  815. package/dist/components/SyncStatusBadge/SyncStatusBadge.module.js.map +1 -1
  816. package/dist/components/Table/Table.cjs.map +1 -1
  817. package/dist/components/Table/Table.js.map +1 -1
  818. package/dist/components/Table/Table.module.cjs.map +1 -1
  819. package/dist/components/Table/Table.module.js.map +1 -1
  820. package/dist/components/Tabs/Tabs.cjs.map +1 -1
  821. package/dist/components/Tabs/Tabs.js.map +1 -1
  822. package/dist/components/Tabs/Tabs.module.cjs.map +1 -1
  823. package/dist/components/Tabs/Tabs.module.js.map +1 -1
  824. package/dist/components/Tag/Tag.cjs.map +1 -1
  825. package/dist/components/Tag/Tag.js.map +1 -1
  826. package/dist/components/Tag/Tag.module.cjs.map +1 -1
  827. package/dist/components/Tag/Tag.module.js.map +1 -1
  828. package/dist/components/Textarea/Textarea.cjs.map +1 -1
  829. package/dist/components/Textarea/Textarea.js.map +1 -1
  830. package/dist/components/Textarea/Textarea.module.cjs.map +1 -1
  831. package/dist/components/Textarea/Textarea.module.js.map +1 -1
  832. package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
  833. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  834. package/dist/components/TimePicker/TimePicker.module.cjs.map +1 -1
  835. package/dist/components/TimePicker/TimePicker.module.js.map +1 -1
  836. package/dist/components/Timeline/Timeline.cjs.map +1 -1
  837. package/dist/components/Timeline/Timeline.js.map +1 -1
  838. package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
  839. package/dist/components/Timeline/Timeline.module.js.map +1 -1
  840. package/dist/components/Toast/Toast.module.cjs.map +1 -1
  841. package/dist/components/Toast/Toast.module.js.map +1 -1
  842. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  843. package/dist/components/Toast/ToastProvider.js.map +1 -1
  844. package/dist/components/Toggle/Toggle.cjs.map +1 -1
  845. package/dist/components/Toggle/Toggle.js.map +1 -1
  846. package/dist/components/Toggle/Toggle.module.cjs.map +1 -1
  847. package/dist/components/Toggle/Toggle.module.js.map +1 -1
  848. package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
  849. package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
  850. package/dist/components/ToggleGroup/ToggleGroup.module.cjs.map +1 -1
  851. package/dist/components/ToggleGroup/ToggleGroup.module.js.map +1 -1
  852. package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
  853. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  854. package/dist/components/Tooltip/Tooltip.module.cjs.map +1 -1
  855. package/dist/components/Tooltip/Tooltip.module.js.map +1 -1
  856. package/dist/components/Tour/Tour.cjs +1 -1
  857. package/dist/components/Tour/Tour.cjs.map +1 -1
  858. package/dist/components/Tour/Tour.js +1 -5
  859. package/dist/components/Tour/Tour.js.map +1 -1
  860. package/dist/components/Tour/Tour.module.cjs.map +1 -1
  861. package/dist/components/Tour/Tour.module.js.map +1 -1
  862. package/dist/components/Tour/tour-position.cjs.map +1 -1
  863. package/dist/components/Tour/tour-position.js.map +1 -1
  864. package/dist/components/Transfer/Transfer.cjs.map +1 -1
  865. package/dist/components/Transfer/Transfer.js.map +1 -1
  866. package/dist/components/Transfer/Transfer.module.cjs.map +1 -1
  867. package/dist/components/Transfer/Transfer.module.js.map +1 -1
  868. package/dist/components/Transfer/transfer-state.cjs.map +1 -1
  869. package/dist/components/Transfer/transfer-state.js.map +1 -1
  870. package/dist/components/TreeView/TreeView.cjs.map +1 -1
  871. package/dist/components/TreeView/TreeView.js.map +1 -1
  872. package/dist/components/TreeView/TreeView.module.cjs.map +1 -1
  873. package/dist/components/TreeView/TreeView.module.js.map +1 -1
  874. package/dist/components/TruncateText/TruncateText.cjs.map +1 -1
  875. package/dist/components/TruncateText/TruncateText.js.map +1 -1
  876. package/dist/components/TruncateText/TruncateText.module.cjs.map +1 -1
  877. package/dist/components/TruncateText/TruncateText.module.js.map +1 -1
  878. package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
  879. package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
  880. package/dist/components/UpdatePrompt/UpdatePrompt.module.cjs.map +1 -1
  881. package/dist/components/UpdatePrompt/UpdatePrompt.module.js.map +1 -1
  882. package/dist/components/VideoPlayer/VideoPlayer.cjs +1 -1
  883. package/dist/components/VideoPlayer/VideoPlayer.cjs.map +1 -1
  884. package/dist/components/VideoPlayer/VideoPlayer.js +1 -7
  885. package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -1
  886. package/dist/components/VideoPlayer/VideoPlayer.module.cjs.map +1 -1
  887. package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -1
  888. package/dist/components/VideoPlayer/playback-rates.cjs.map +1 -1
  889. package/dist/components/VideoPlayer/playback-rates.js.map +1 -1
  890. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  891. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  892. package/dist/components/VirtualList/VirtualList.module.cjs.map +1 -1
  893. package/dist/components/VirtualList/VirtualList.module.js.map +1 -1
  894. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  895. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  896. package/dist/components/VirtualTable/VirtualTable.module.cjs.map +1 -1
  897. package/dist/components/VirtualTable/VirtualTable.module.js.map +1 -1
  898. package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
  899. package/dist/components/VisuallyHidden/VisuallyHidden.js.map +1 -1
  900. package/dist/components/VisuallyHidden/VisuallyHidden.module.cjs.map +1 -1
  901. package/dist/components/VisuallyHidden/VisuallyHidden.module.js.map +1 -1
  902. package/dist/components/Wizard/Wizard.cjs +1 -1
  903. package/dist/components/Wizard/Wizard.cjs.map +1 -1
  904. package/dist/components/Wizard/Wizard.js +4 -11
  905. package/dist/components/Wizard/Wizard.js.map +1 -1
  906. package/dist/components/Wizard/Wizard.module.cjs.map +1 -1
  907. package/dist/components/Wizard/Wizard.module.js.map +1 -1
  908. package/dist/data/create-data-provider.cjs.map +1 -1
  909. package/dist/data/create-data-provider.js.map +1 -1
  910. package/dist/data/data-provider-context.cjs.map +1 -1
  911. package/dist/data/data-provider-context.js.map +1 -1
  912. package/dist/data/use-resource.cjs.map +1 -1
  913. package/dist/data/use-resource.js.map +1 -1
  914. package/dist/editor/RichTextEditor.cjs.map +1 -1
  915. package/dist/editor/RichTextEditor.js.map +1 -1
  916. package/dist/editor/RichTextEditor.module.cjs.map +1 -1
  917. package/dist/editor/RichTextEditor.module.js.map +1 -1
  918. package/dist/editor.js +1 -2
  919. package/dist/error-boundary/ErrorBoundary.cjs.map +1 -1
  920. package/dist/error-boundary/ErrorBoundary.js.map +1 -1
  921. package/dist/error-boundary/use-error-handler.cjs.map +1 -1
  922. package/dist/error-boundary/use-error-handler.js.map +1 -1
  923. package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
  924. package/dist/feature-flags/FeatureFlagsProvider.js.map +1 -1
  925. package/dist/feature-flags/growthbook-adapter.cjs.map +1 -1
  926. package/dist/feature-flags/growthbook-adapter.js.map +1 -1
  927. package/dist/feature-flags/in-memory-adapter.cjs.map +1 -1
  928. package/dist/feature-flags/in-memory-adapter.js.map +1 -1
  929. package/dist/feature-flags/launchdarkly-adapter.cjs.map +1 -1
  930. package/dist/feature-flags/launchdarkly-adapter.js.map +1 -1
  931. package/dist/forms/FormField.cjs.map +1 -1
  932. package/dist/forms/FormField.js.map +1 -1
  933. package/dist/forms/br-validators.cjs.map +1 -1
  934. package/dist/forms/br-validators.js.map +1 -1
  935. package/dist/forms/masked-inputs.cjs.map +1 -1
  936. package/dist/forms/masked-inputs.js.map +1 -1
  937. package/dist/forms/use-viacep.cjs.map +1 -1
  938. package/dist/forms/use-viacep.js.map +1 -1
  939. package/dist/forms/use-zod-form.cjs.map +1 -1
  940. package/dist/forms/use-zod-form.js.map +1 -1
  941. package/dist/forms/validate-form.cjs.map +1 -1
  942. package/dist/forms/validate-form.js.map +1 -1
  943. package/dist/forms/zod-resolver.cjs.map +1 -1
  944. package/dist/forms/zod-resolver.js.map +1 -1
  945. package/dist/geo/TrajectoryMap.cjs.map +1 -1
  946. package/dist/geo/TrajectoryMap.js.map +1 -1
  947. package/dist/geo/TrajectoryMap.module.cjs.map +1 -1
  948. package/dist/geo/TrajectoryMap.module.js.map +1 -1
  949. package/dist/geo/bounds.cjs.map +1 -1
  950. package/dist/geo/bounds.js.map +1 -1
  951. package/dist/geo/create-position-tracker.cjs +1 -1
  952. package/dist/geo/create-position-tracker.cjs.map +1 -1
  953. package/dist/geo/create-position-tracker.js +1 -7
  954. package/dist/geo/create-position-tracker.js.map +1 -1
  955. package/dist/geo/distance.cjs.map +1 -1
  956. package/dist/geo/distance.js.map +1 -1
  957. package/dist/geo/estimate.cjs.map +1 -1
  958. package/dist/geo/estimate.js.map +1 -1
  959. package/dist/geo/leaflet-map.cjs.map +1 -1
  960. package/dist/geo/leaflet-map.js.map +1 -1
  961. package/dist/geo/projection.cjs.map +1 -1
  962. package/dist/geo/projection.js.map +1 -1
  963. package/dist/geo/routing.cjs.map +1 -1
  964. package/dist/geo/routing.js.map +1 -1
  965. package/dist/geo/types.cjs.map +1 -1
  966. package/dist/geo/types.js.map +1 -1
  967. package/dist/geo/use-position-tracker.cjs.map +1 -1
  968. package/dist/geo/use-position-tracker.js.map +1 -1
  969. package/dist/hooks/pwa-env.cjs.map +1 -1
  970. package/dist/hooks/pwa-env.js.map +1 -1
  971. package/dist/hooks/tab-sequence.cjs.map +1 -1
  972. package/dist/hooks/tab-sequence.js.map +1 -1
  973. package/dist/hooks/use-announce.cjs +1 -1
  974. package/dist/hooks/use-announce.cjs.map +1 -1
  975. package/dist/hooks/use-announce.js +2 -2
  976. package/dist/hooks/use-announce.js.map +1 -1
  977. package/dist/hooks/use-async.cjs.map +1 -1
  978. package/dist/hooks/use-async.js.map +1 -1
  979. package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
  980. package/dist/hooks/use-before-install-prompt.js.map +1 -1
  981. package/dist/hooks/use-breakpoint.cjs.map +1 -1
  982. package/dist/hooks/use-breakpoint.js.map +1 -1
  983. package/dist/hooks/use-click-outside.cjs.map +1 -1
  984. package/dist/hooks/use-click-outside.js.map +1 -1
  985. package/dist/hooks/use-client-filter.cjs.map +1 -1
  986. package/dist/hooks/use-client-filter.js.map +1 -1
  987. package/dist/hooks/use-clipboard.cjs.map +1 -1
  988. package/dist/hooks/use-clipboard.js.map +1 -1
  989. package/dist/hooks/use-countdown.cjs.map +1 -1
  990. package/dist/hooks/use-countdown.js.map +1 -1
  991. package/dist/hooks/use-counter.cjs.map +1 -1
  992. package/dist/hooks/use-counter.js.map +1 -1
  993. package/dist/hooks/use-debounce.cjs.map +1 -1
  994. package/dist/hooks/use-debounce.js.map +1 -1
  995. package/dist/hooks/use-deep-memo.cjs.map +1 -1
  996. package/dist/hooks/use-deep-memo.js.map +1 -1
  997. package/dist/hooks/use-disclosure.cjs.map +1 -1
  998. package/dist/hooks/use-disclosure.js.map +1 -1
  999. package/dist/hooks/use-document-title.cjs.map +1 -1
  1000. package/dist/hooks/use-document-title.js.map +1 -1
  1001. package/dist/hooks/use-document-visibility.cjs.map +1 -1
  1002. package/dist/hooks/use-document-visibility.js.map +1 -1
  1003. package/dist/hooks/use-draft-filters.cjs.map +1 -1
  1004. package/dist/hooks/use-draft-filters.js.map +1 -1
  1005. package/dist/hooks/use-event-listener.cjs.map +1 -1
  1006. package/dist/hooks/use-event-listener.js.map +1 -1
  1007. package/dist/hooks/use-favicon.cjs.map +1 -1
  1008. package/dist/hooks/use-favicon.js.map +1 -1
  1009. package/dist/hooks/use-focus-trap.cjs.map +1 -1
  1010. package/dist/hooks/use-focus-trap.js.map +1 -1
  1011. package/dist/hooks/use-fullscreen-element.cjs.map +1 -1
  1012. package/dist/hooks/use-fullscreen-element.js.map +1 -1
  1013. package/dist/hooks/use-fullscreen.cjs +1 -1
  1014. package/dist/hooks/use-fullscreen.cjs.map +1 -1
  1015. package/dist/hooks/use-fullscreen.js +7 -23
  1016. package/dist/hooks/use-fullscreen.js.map +1 -1
  1017. package/dist/hooks/use-geolocation.cjs.map +1 -1
  1018. package/dist/hooks/use-geolocation.js.map +1 -1
  1019. package/dist/hooks/use-hover.cjs.map +1 -1
  1020. package/dist/hooks/use-hover.js.map +1 -1
  1021. package/dist/hooks/use-idle.cjs.map +1 -1
  1022. package/dist/hooks/use-idle.js.map +1 -1
  1023. package/dist/hooks/use-install-prompt.cjs +1 -1
  1024. package/dist/hooks/use-install-prompt.cjs.map +1 -1
  1025. package/dist/hooks/use-install-prompt.js +1 -1
  1026. package/dist/hooks/use-install-prompt.js.map +1 -1
  1027. package/dist/hooks/use-intersection-observer.cjs.map +1 -1
  1028. package/dist/hooks/use-intersection-observer.js.map +1 -1
  1029. package/dist/hooks/use-interval.cjs.map +1 -1
  1030. package/dist/hooks/use-interval.js.map +1 -1
  1031. package/dist/hooks/use-is-first-render.cjs.map +1 -1
  1032. package/dist/hooks/use-is-first-render.js.map +1 -1
  1033. package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
  1034. package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
  1035. package/dist/hooks/use-latest-ref.cjs.map +1 -1
  1036. package/dist/hooks/use-latest-ref.js.map +1 -1
  1037. package/dist/hooks/use-list-state.cjs.map +1 -1
  1038. package/dist/hooks/use-list-state.js.map +1 -1
  1039. package/dist/hooks/use-local-storage.cjs +1 -1
  1040. package/dist/hooks/use-local-storage.cjs.map +1 -1
  1041. package/dist/hooks/use-local-storage.js +2 -5
  1042. package/dist/hooks/use-local-storage.js.map +1 -1
  1043. package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
  1044. package/dist/hooks/use-long-press-handlers.js.map +1 -1
  1045. package/dist/hooks/use-long-press.cjs.map +1 -1
  1046. package/dist/hooks/use-long-press.js.map +1 -1
  1047. package/dist/hooks/use-map.cjs.map +1 -1
  1048. package/dist/hooks/use-map.js.map +1 -1
  1049. package/dist/hooks/use-media-devices.cjs.map +1 -1
  1050. package/dist/hooks/use-media-devices.js.map +1 -1
  1051. package/dist/hooks/use-media-permission.cjs +1 -1
  1052. package/dist/hooks/use-media-permission.cjs.map +1 -1
  1053. package/dist/hooks/use-media-permission.js +2 -5
  1054. package/dist/hooks/use-media-permission.js.map +1 -1
  1055. package/dist/hooks/use-media-query.cjs.map +1 -1
  1056. package/dist/hooks/use-media-query.js.map +1 -1
  1057. package/dist/hooks/use-object-url.cjs.map +1 -1
  1058. package/dist/hooks/use-object-url.js.map +1 -1
  1059. package/dist/hooks/use-online.cjs.map +1 -1
  1060. package/dist/hooks/use-online.js.map +1 -1
  1061. package/dist/hooks/use-pagination.cjs.map +1 -1
  1062. package/dist/hooks/use-pagination.js.map +1 -1
  1063. package/dist/hooks/use-previous.cjs.map +1 -1
  1064. package/dist/hooks/use-previous.js.map +1 -1
  1065. package/dist/hooks/use-push-to-talk.cjs.map +1 -1
  1066. package/dist/hooks/use-push-to-talk.js.map +1 -1
  1067. package/dist/hooks/use-queue.cjs.map +1 -1
  1068. package/dist/hooks/use-queue.js.map +1 -1
  1069. package/dist/hooks/use-resize-observer.cjs.map +1 -1
  1070. package/dist/hooks/use-resize-observer.js.map +1 -1
  1071. package/dist/hooks/use-scroll-lock.cjs.map +1 -1
  1072. package/dist/hooks/use-scroll-lock.js.map +1 -1
  1073. package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
  1074. package/dist/hooks/use-scroll-overflow.js.map +1 -1
  1075. package/dist/hooks/use-service-worker-update.cjs.map +1 -1
  1076. package/dist/hooks/use-service-worker-update.js.map +1 -1
  1077. package/dist/hooks/use-set.cjs.map +1 -1
  1078. package/dist/hooks/use-set.js.map +1 -1
  1079. package/dist/hooks/use-sortable.cjs.map +1 -1
  1080. package/dist/hooks/use-sortable.js.map +1 -1
  1081. package/dist/hooks/use-stable-callback.cjs.map +1 -1
  1082. package/dist/hooks/use-stable-callback.js.map +1 -1
  1083. package/dist/hooks/use-storage-estimate.cjs.map +1 -1
  1084. package/dist/hooks/use-storage-estimate.js.map +1 -1
  1085. package/dist/hooks/use-throttle.cjs.map +1 -1
  1086. package/dist/hooks/use-throttle.js.map +1 -1
  1087. package/dist/hooks/use-timeout.cjs.map +1 -1
  1088. package/dist/hooks/use-timeout.js.map +1 -1
  1089. package/dist/hooks/use-toggle.cjs.map +1 -1
  1090. package/dist/hooks/use-toggle.js.map +1 -1
  1091. package/dist/hooks/use-typewriter.cjs.map +1 -1
  1092. package/dist/hooks/use-typewriter.js.map +1 -1
  1093. package/dist/hooks/use-window-size.cjs.map +1 -1
  1094. package/dist/hooks/use-window-size.js.map +1 -1
  1095. package/dist/http/api-client.cjs.map +1 -1
  1096. package/dist/http/api-client.js.map +1 -1
  1097. package/dist/http/build-url.cjs.map +1 -1
  1098. package/dist/http/build-url.js.map +1 -1
  1099. package/dist/http/credential-scope.cjs.map +1 -1
  1100. package/dist/http/credential-scope.js.map +1 -1
  1101. package/dist/http/csrf.cjs.map +1 -1
  1102. package/dist/http/csrf.js.map +1 -1
  1103. package/dist/http/decode-response.cjs.map +1 -1
  1104. package/dist/http/decode-response.js.map +1 -1
  1105. package/dist/http/describe-api-error.cjs.map +1 -1
  1106. package/dist/http/describe-api-error.js.map +1 -1
  1107. package/dist/http/errors.cjs.map +1 -1
  1108. package/dist/http/errors.js.map +1 -1
  1109. package/dist/http/idempotency.cjs.map +1 -1
  1110. package/dist/http/idempotency.js.map +1 -1
  1111. package/dist/http/parse-response.cjs.map +1 -1
  1112. package/dist/http/parse-response.js.map +1 -1
  1113. package/dist/http/resumable-upload.cjs +1 -1
  1114. package/dist/http/resumable-upload.cjs.map +1 -1
  1115. package/dist/http/resumable-upload.js +141 -105
  1116. package/dist/http/resumable-upload.js.map +1 -1
  1117. package/dist/http/retry.cjs +1 -1
  1118. package/dist/http/retry.cjs.map +1 -1
  1119. package/dist/http/retry.js +5 -6
  1120. package/dist/http/retry.js.map +1 -1
  1121. package/dist/http/timeout.cjs.map +1 -1
  1122. package/dist/http/timeout.js.map +1 -1
  1123. package/dist/http/upload-with-progress.cjs +1 -1
  1124. package/dist/http/upload-with-progress.cjs.map +1 -1
  1125. package/dist/http/upload-with-progress.js +2 -7
  1126. package/dist/http/upload-with-progress.js.map +1 -1
  1127. package/dist/http/use-describe-api-error.cjs.map +1 -1
  1128. package/dist/http/use-describe-api-error.js.map +1 -1
  1129. package/dist/http/use-poll.cjs +1 -1
  1130. package/dist/http/use-poll.cjs.map +1 -1
  1131. package/dist/http/use-poll.js +2 -5
  1132. package/dist/http/use-poll.js.map +1 -1
  1133. package/dist/i18n/I18nProvider.cjs.map +1 -1
  1134. package/dist/i18n/I18nProvider.js.map +1 -1
  1135. package/dist/i18n/create-i18n.cjs.map +1 -1
  1136. package/dist/i18n/create-i18n.js.map +1 -1
  1137. package/dist/icons/Icon.cjs.map +1 -1
  1138. package/dist/icons/Icon.js.map +1 -1
  1139. package/dist/icons/IconPicker.cjs.map +1 -1
  1140. package/dist/icons/IconPicker.js.map +1 -1
  1141. package/dist/icons/IconPicker.module.cjs.map +1 -1
  1142. package/dist/icons/IconPicker.module.js.map +1 -1
  1143. package/dist/icons/IconProvider.cjs.map +1 -1
  1144. package/dist/icons/IconProvider.js.map +1 -1
  1145. package/dist/icons/alias.cjs.map +1 -1
  1146. package/dist/icons/alias.js.map +1 -1
  1147. package/dist/icons/generated/aliases.cjs.map +1 -1
  1148. package/dist/icons/generated/aliases.js.map +1 -1
  1149. package/dist/icons/generated/icon-names.cjs.map +1 -1
  1150. package/dist/icons/generated/icon-names.js.map +1 -1
  1151. package/dist/icons/generated/loaders.cjs.map +1 -1
  1152. package/dist/icons/generated/loaders.js.map +1 -1
  1153. package/dist/icons/generated/shard-00.cjs.map +1 -1
  1154. package/dist/icons/generated/shard-00.js.map +1 -1
  1155. package/dist/icons/generated/shard-01.cjs.map +1 -1
  1156. package/dist/icons/generated/shard-01.js.map +1 -1
  1157. package/dist/icons/generated/shard-02.cjs.map +1 -1
  1158. package/dist/icons/generated/shard-02.js.map +1 -1
  1159. package/dist/icons/generated/shard-03.cjs.map +1 -1
  1160. package/dist/icons/generated/shard-03.js.map +1 -1
  1161. package/dist/icons/generated/shard-04.cjs.map +1 -1
  1162. package/dist/icons/generated/shard-04.js.map +1 -1
  1163. package/dist/icons/generated/shard-05.cjs.map +1 -1
  1164. package/dist/icons/generated/shard-05.js.map +1 -1
  1165. package/dist/icons/generated/shard-06.cjs.map +1 -1
  1166. package/dist/icons/generated/shard-06.js.map +1 -1
  1167. package/dist/icons/generated/shard-07.cjs.map +1 -1
  1168. package/dist/icons/generated/shard-07.js.map +1 -1
  1169. package/dist/icons/generated/shard-08.cjs.map +1 -1
  1170. package/dist/icons/generated/shard-08.js.map +1 -1
  1171. package/dist/icons/generated/shard-09.cjs.map +1 -1
  1172. package/dist/icons/generated/shard-09.js.map +1 -1
  1173. package/dist/icons/generated/shard-10.cjs.map +1 -1
  1174. package/dist/icons/generated/shard-10.js.map +1 -1
  1175. package/dist/icons/generated/shard-11.cjs.map +1 -1
  1176. package/dist/icons/generated/shard-11.js.map +1 -1
  1177. package/dist/icons/generated/shard-12.cjs.map +1 -1
  1178. package/dist/icons/generated/shard-12.js.map +1 -1
  1179. package/dist/icons/generated/shard-13.cjs.map +1 -1
  1180. package/dist/icons/generated/shard-13.js.map +1 -1
  1181. package/dist/icons/generated/shard-14.cjs.map +1 -1
  1182. package/dist/icons/generated/shard-14.js.map +1 -1
  1183. package/dist/icons/generated/shard-15.cjs.map +1 -1
  1184. package/dist/icons/generated/shard-15.js.map +1 -1
  1185. package/dist/icons/generated/shard-16.cjs.map +1 -1
  1186. package/dist/icons/generated/shard-16.js.map +1 -1
  1187. package/dist/icons/generated/shard-17.cjs.map +1 -1
  1188. package/dist/icons/generated/shard-17.js.map +1 -1
  1189. package/dist/icons/generated/shard-18.cjs.map +1 -1
  1190. package/dist/icons/generated/shard-18.js.map +1 -1
  1191. package/dist/icons/generated/shard-19.cjs.map +1 -1
  1192. package/dist/icons/generated/shard-19.js.map +1 -1
  1193. package/dist/icons/generated/shard-20.cjs.map +1 -1
  1194. package/dist/icons/generated/shard-20.js.map +1 -1
  1195. package/dist/icons/generated/shard-21.cjs.map +1 -1
  1196. package/dist/icons/generated/shard-21.js.map +1 -1
  1197. package/dist/icons/generated/shard-22.cjs.map +1 -1
  1198. package/dist/icons/generated/shard-22.js.map +1 -1
  1199. package/dist/icons/generated/shard-23.cjs.map +1 -1
  1200. package/dist/icons/generated/shard-23.js.map +1 -1
  1201. package/dist/icons/generated/shard-24.cjs.map +1 -1
  1202. package/dist/icons/generated/shard-24.js.map +1 -1
  1203. package/dist/icons/generated/shard-25.cjs.map +1 -1
  1204. package/dist/icons/generated/shard-25.js.map +1 -1
  1205. package/dist/icons/generated/shard-26.cjs.map +1 -1
  1206. package/dist/icons/generated/shard-26.js.map +1 -1
  1207. package/dist/icons/generated/shard-27.cjs.map +1 -1
  1208. package/dist/icons/generated/shard-27.js.map +1 -1
  1209. package/dist/icons/generated/shard-28.cjs.map +1 -1
  1210. package/dist/icons/generated/shard-28.js.map +1 -1
  1211. package/dist/icons/generated/shard-29.cjs.map +1 -1
  1212. package/dist/icons/generated/shard-29.js.map +1 -1
  1213. package/dist/icons/generated/shard-30.cjs.map +1 -1
  1214. package/dist/icons/generated/shard-30.js.map +1 -1
  1215. package/dist/icons/generated/shard-31.cjs.map +1 -1
  1216. package/dist/icons/generated/shard-31.js.map +1 -1
  1217. package/dist/icons/generated/shard-32.cjs.map +1 -1
  1218. package/dist/icons/generated/shard-32.js.map +1 -1
  1219. package/dist/icons/generated/shard-33.cjs.map +1 -1
  1220. package/dist/icons/generated/shard-33.js.map +1 -1
  1221. package/dist/icons/generated/shard-34.cjs.map +1 -1
  1222. package/dist/icons/generated/shard-34.js.map +1 -1
  1223. package/dist/icons/generated/shard-35.cjs.map +1 -1
  1224. package/dist/icons/generated/shard-35.js.map +1 -1
  1225. package/dist/icons/generated/shard-36.cjs.map +1 -1
  1226. package/dist/icons/generated/shard-36.js.map +1 -1
  1227. package/dist/icons/generated/shard-37.cjs.map +1 -1
  1228. package/dist/icons/generated/shard-37.js.map +1 -1
  1229. package/dist/icons/generated/shard-38.cjs.map +1 -1
  1230. package/dist/icons/generated/shard-38.js.map +1 -1
  1231. package/dist/icons/generated/shard-39.cjs.map +1 -1
  1232. package/dist/icons/generated/shard-39.js.map +1 -1
  1233. package/dist/icons/generated/shard-40.cjs.map +1 -1
  1234. package/dist/icons/generated/shard-40.js.map +1 -1
  1235. package/dist/icons/generated/shard-41.cjs.map +1 -1
  1236. package/dist/icons/generated/shard-41.js.map +1 -1
  1237. package/dist/icons/generated/shard-42.cjs.map +1 -1
  1238. package/dist/icons/generated/shard-42.js.map +1 -1
  1239. package/dist/icons/generated/shard-43.cjs.map +1 -1
  1240. package/dist/icons/generated/shard-43.js.map +1 -1
  1241. package/dist/icons/generated/shard-44.cjs.map +1 -1
  1242. package/dist/icons/generated/shard-44.js.map +1 -1
  1243. package/dist/icons/generated/shard-45.cjs.map +1 -1
  1244. package/dist/icons/generated/shard-45.js.map +1 -1
  1245. package/dist/icons/icon-context.cjs.map +1 -1
  1246. package/dist/icons/icon-context.js.map +1 -1
  1247. package/dist/icons/is-icon-name.cjs.map +1 -1
  1248. package/dist/icons/is-icon-name.js.map +1 -1
  1249. package/dist/icons/material-symbols.cjs.map +1 -1
  1250. package/dist/icons/material-symbols.js.map +1 -1
  1251. package/dist/icons/normalize-icon-name.cjs.map +1 -1
  1252. package/dist/icons/normalize-icon-name.js.map +1 -1
  1253. package/dist/icons/shard-cache.cjs +1 -1
  1254. package/dist/icons/shard-cache.cjs.map +1 -1
  1255. package/dist/icons/shard-cache.js +2 -5
  1256. package/dist/icons/shard-cache.js.map +1 -1
  1257. package/dist/icons/use-icon.cjs.map +1 -1
  1258. package/dist/icons/use-icon.js.map +1 -1
  1259. package/dist/icons/validate-icon-name.cjs.map +1 -1
  1260. package/dist/icons/validate-icon-name.js.map +1 -1
  1261. package/dist/icons-virtual.cjs.map +1 -1
  1262. package/dist/icons-virtual.js.map +1 -1
  1263. package/dist/imaging/canvas.cjs.map +1 -1
  1264. package/dist/imaging/canvas.js.map +1 -1
  1265. package/dist/imaging/compress.cjs.map +1 -1
  1266. package/dist/imaging/compress.js.map +1 -1
  1267. package/dist/imaging/decode.cjs.map +1 -1
  1268. package/dist/imaging/decode.js.map +1 -1
  1269. package/dist/imaging/encode.cjs.map +1 -1
  1270. package/dist/imaging/encode.js.map +1 -1
  1271. package/dist/imaging/exceptions.cjs.map +1 -1
  1272. package/dist/imaging/exceptions.js.map +1 -1
  1273. package/dist/imaging/frame.cjs.map +1 -1
  1274. package/dist/imaging/frame.js.map +1 -1
  1275. package/dist/imaging/thumbnails.cjs.map +1 -1
  1276. package/dist/imaging/thumbnails.js.map +1 -1
  1277. package/dist/imaging/transform.cjs.map +1 -1
  1278. package/dist/imaging/transform.js.map +1 -1
  1279. package/dist/imaging/use-image-processing.cjs.map +1 -1
  1280. package/dist/imaging/use-image-processing.js.map +1 -1
  1281. package/dist/logger/logger.cjs.map +1 -1
  1282. package/dist/logger/logger.js.map +1 -1
  1283. package/dist/neural.cjs.map +1 -1
  1284. package/dist/neural.js.map +1 -1
  1285. package/dist/oauth/GoogleSignIn.cjs +1 -1
  1286. package/dist/oauth/GoogleSignIn.cjs.map +1 -1
  1287. package/dist/oauth/GoogleSignIn.js +6 -9
  1288. package/dist/oauth/GoogleSignIn.js.map +1 -1
  1289. package/dist/oauth/callback.cjs.map +1 -1
  1290. package/dist/oauth/callback.js.map +1 -1
  1291. package/dist/oauth/use-oauth-callback.cjs.map +1 -1
  1292. package/dist/oauth/use-oauth-callback.js.map +1 -1
  1293. package/dist/offline/conflict.cjs.map +1 -1
  1294. package/dist/offline/conflict.js.map +1 -1
  1295. package/dist/offline/create-offline-database.cjs.map +1 -1
  1296. package/dist/offline/create-offline-database.js.map +1 -1
  1297. package/dist/offline/create-offline-store.cjs +1 -1
  1298. package/dist/offline/create-offline-store.cjs.map +1 -1
  1299. package/dist/offline/create-offline-store.js +1 -5
  1300. package/dist/offline/create-offline-store.js.map +1 -1
  1301. package/dist/offline/create-offline-sync.cjs +1 -1
  1302. package/dist/offline/create-offline-sync.cjs.map +1 -1
  1303. package/dist/offline/create-offline-sync.js +9 -14
  1304. package/dist/offline/create-offline-sync.js.map +1 -1
  1305. package/dist/offline/use-offline-sync.cjs.map +1 -1
  1306. package/dist/offline/use-offline-sync.js.map +1 -1
  1307. package/dist/perf/cache-size.cjs.map +1 -1
  1308. package/dist/perf/cache-size.js.map +1 -1
  1309. package/dist/perf/device.cjs.map +1 -1
  1310. package/dist/perf/device.js.map +1 -1
  1311. package/dist/perf/format.cjs.map +1 -1
  1312. package/dist/perf/format.js.map +1 -1
  1313. package/dist/perf/profiler.cjs.map +1 -1
  1314. package/dist/perf/profiler.js.map +1 -1
  1315. package/dist/push/use-push-subscription.cjs.map +1 -1
  1316. package/dist/push/use-push-subscription.js.map +1 -1
  1317. package/dist/push/utils.cjs.map +1 -1
  1318. package/dist/push/utils.js.map +1 -1
  1319. package/dist/push/web-push-client.cjs.map +1 -1
  1320. package/dist/push/web-push-client.js.map +1 -1
  1321. package/dist/query/QueryProvider.cjs.map +1 -1
  1322. package/dist/query/QueryProvider.js.map +1 -1
  1323. package/dist/query/constants.cjs.map +1 -1
  1324. package/dist/query/constants.js.map +1 -1
  1325. package/dist/query/create-query-keys.cjs.map +1 -1
  1326. package/dist/query/create-query-keys.js.map +1 -1
  1327. package/dist/query/foreign-client-warning.cjs.map +1 -1
  1328. package/dist/query/foreign-client-warning.js.map +1 -1
  1329. package/dist/query/offline-persistence.cjs +1 -1
  1330. package/dist/query/offline-persistence.cjs.map +1 -1
  1331. package/dist/query/offline-persistence.js +2 -10
  1332. package/dist/query/offline-persistence.js.map +1 -1
  1333. package/dist/query/optimistic.cjs.map +1 -1
  1334. package/dist/query/optimistic.js.map +1 -1
  1335. package/dist/query/pagination.cjs.map +1 -1
  1336. package/dist/query/pagination.js.map +1 -1
  1337. package/dist/query/retry-policy.cjs.map +1 -1
  1338. package/dist/query/retry-policy.js.map +1 -1
  1339. package/dist/query/use-cursor-query.cjs.map +1 -1
  1340. package/dist/query/use-cursor-query.js.map +1 -1
  1341. package/dist/query/use-offline-mutation.cjs.map +1 -1
  1342. package/dist/query/use-offline-mutation.js.map +1 -1
  1343. package/dist/query/use-paginated-query.cjs.map +1 -1
  1344. package/dist/query/use-paginated-query.js.map +1 -1
  1345. package/dist/router/AppRouter.cjs.map +1 -1
  1346. package/dist/router/AppRouter.js.map +1 -1
  1347. package/dist/router/RouteGuard.cjs.map +1 -1
  1348. package/dist/router/RouteGuard.js.map +1 -1
  1349. package/dist/router/index.js +2 -2
  1350. package/dist/share/share-or-download.cjs.map +1 -1
  1351. package/dist/share/share-or-download.js.map +1 -1
  1352. package/dist/share/share.cjs.map +1 -1
  1353. package/dist/share/share.js.map +1 -1
  1354. package/dist/sse/create-event-stream.cjs.map +1 -1
  1355. package/dist/sse/create-event-stream.js.map +1 -1
  1356. package/dist/sse/use-event-stream.cjs.map +1 -1
  1357. package/dist/sse/use-event-stream.js.map +1 -1
  1358. package/dist/store/create-selectors.cjs.map +1 -1
  1359. package/dist/store/create-selectors.js.map +1 -1
  1360. package/dist/store/create-store.cjs.map +1 -1
  1361. package/dist/store/create-store.js.map +1 -1
  1362. package/dist/sw/background-sync.cjs +1 -1
  1363. package/dist/sw/background-sync.cjs.map +1 -1
  1364. package/dist/sw/background-sync.js +32 -31
  1365. package/dist/sw/background-sync.js.map +1 -1
  1366. package/dist/sw/cache-inspect.cjs.map +1 -1
  1367. package/dist/sw/cache-inspect.js.map +1 -1
  1368. package/dist/sw/cache.cjs +1 -1
  1369. package/dist/sw/cache.cjs.map +1 -1
  1370. package/dist/sw/cache.js +2 -6
  1371. package/dist/sw/cache.js.map +1 -1
  1372. package/dist/sw/create-push-handler.cjs.map +1 -1
  1373. package/dist/sw/create-push-handler.js.map +1 -1
  1374. package/dist/sw/credential-headers.cjs.map +1 -1
  1375. package/dist/sw/credential-headers.js.map +1 -1
  1376. package/dist/sw/periodic-sync.cjs.map +1 -1
  1377. package/dist/sw/periodic-sync.js.map +1 -1
  1378. package/dist/sw/register-service-worker.cjs.map +1 -1
  1379. package/dist/sw/register-service-worker.js.map +1 -1
  1380. package/dist/sw/session-data.cjs.map +1 -1
  1381. package/dist/sw/session-data.js.map +1 -1
  1382. package/dist/sw.d.ts +46 -8
  1383. package/dist/tabular/assets.cjs.map +1 -1
  1384. package/dist/tabular/assets.js.map +1 -1
  1385. package/dist/tabular/cache.cjs.map +1 -1
  1386. package/dist/tabular/cache.js.map +1 -1
  1387. package/dist/tabular/compact.cjs.map +1 -1
  1388. package/dist/tabular/compact.js.map +1 -1
  1389. package/dist/tabular/exceptions.cjs.map +1 -1
  1390. package/dist/tabular/exceptions.js.map +1 -1
  1391. package/dist/tabular/manifest.cjs.map +1 -1
  1392. package/dist/tabular/manifest.js.map +1 -1
  1393. package/dist/tabular/predictor.cjs.map +1 -1
  1394. package/dist/tabular/predictor.js.map +1 -1
  1395. package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
  1396. package/dist/tabular/use-tabular-predictor.js.map +1 -1
  1397. package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
  1398. package/dist/telemetry/TelemetryProvider.js.map +1 -1
  1399. package/dist/telemetry/app-error-adapter.cjs.map +1 -1
  1400. package/dist/telemetry/app-error-adapter.js.map +1 -1
  1401. package/dist/telemetry/app-error-queue.cjs.map +1 -1
  1402. package/dist/telemetry/app-error-queue.js.map +1 -1
  1403. package/dist/telemetry/app-error-reporter.cjs +1 -1
  1404. package/dist/telemetry/app-error-reporter.cjs.map +1 -1
  1405. package/dist/telemetry/app-error-reporter.js +1 -1
  1406. package/dist/telemetry/app-error-reporter.js.map +1 -1
  1407. package/dist/telemetry/app-error-schema.cjs.map +1 -1
  1408. package/dist/telemetry/app-error-schema.js.map +1 -1
  1409. package/dist/telemetry/app-error-transport.cjs.map +1 -1
  1410. package/dist/telemetry/app-error-transport.js.map +1 -1
  1411. package/dist/telemetry/console-adapter.cjs.map +1 -1
  1412. package/dist/telemetry/console-adapter.js.map +1 -1
  1413. package/dist/telemetry/describe-app-error.cjs.map +1 -1
  1414. package/dist/telemetry/describe-app-error.js.map +1 -1
  1415. package/dist/telemetry/posthog-adapter.cjs +1 -1
  1416. package/dist/telemetry/posthog-adapter.cjs.map +1 -1
  1417. package/dist/telemetry/posthog-adapter.js +1 -5
  1418. package/dist/telemetry/posthog-adapter.js.map +1 -1
  1419. package/dist/telemetry/sentry-adapter.cjs.map +1 -1
  1420. package/dist/telemetry/sentry-adapter.js.map +1 -1
  1421. package/dist/tempest-react-sdk.cjs +1 -1
  1422. package/dist/tempest-react-sdk.d.ts +448 -15
  1423. package/dist/tempest-react-sdk.js +119 -119
  1424. package/dist/testing/create-mock-handlers.cjs.map +1 -1
  1425. package/dist/testing/create-mock-handlers.js.map +1 -1
  1426. package/dist/testing.js +1 -2
  1427. package/dist/theme/ThemeProvider.cjs.map +1 -1
  1428. package/dist/theme/ThemeProvider.js.map +1 -1
  1429. package/dist/theme/apply-theme.cjs.map +1 -1
  1430. package/dist/theme/apply-theme.js.map +1 -1
  1431. package/dist/theme/color.cjs.map +1 -1
  1432. package/dist/theme/color.js.map +1 -1
  1433. package/dist/theme/create-theme.cjs.map +1 -1
  1434. package/dist/theme/create-theme.js.map +1 -1
  1435. package/dist/theme/data-viz-ramps.cjs.map +1 -1
  1436. package/dist/theme/data-viz-ramps.js.map +1 -1
  1437. package/dist/theme/initial-theme.cjs.map +1 -1
  1438. package/dist/theme/initial-theme.js.map +1 -1
  1439. package/dist/theme/inverse-render.cjs.map +1 -1
  1440. package/dist/theme/inverse-render.js.map +1 -1
  1441. package/dist/theme/inverse-restore.cjs.map +1 -1
  1442. package/dist/theme/inverse-restore.js.map +1 -1
  1443. package/dist/theme/inverse-surface.cjs.map +1 -1
  1444. package/dist/theme/inverse-surface.js.map +1 -1
  1445. package/dist/theme/status-tokens.cjs.map +1 -1
  1446. package/dist/theme/status-tokens.js.map +1 -1
  1447. package/dist/theme/theme-presets.cjs.map +1 -1
  1448. package/dist/theme/theme-presets.js.map +1 -1
  1449. package/dist/utils/absent.cjs.map +1 -1
  1450. package/dist/utils/absent.js.map +1 -1
  1451. package/dist/utils/arrays.cjs.map +1 -1
  1452. package/dist/utils/arrays.js.map +1 -1
  1453. package/dist/utils/base64.cjs.map +1 -1
  1454. package/dist/utils/base64.js.map +1 -1
  1455. package/dist/utils/cn.cjs.map +1 -1
  1456. package/dist/utils/cn.js.map +1 -1
  1457. package/dist/utils/compare-values.cjs.map +1 -1
  1458. package/dist/utils/compare-values.js.map +1 -1
  1459. package/dist/utils/compressed-storage.cjs.map +1 -1
  1460. package/dist/utils/compressed-storage.js.map +1 -1
  1461. package/dist/utils/csv.cjs +3 -3
  1462. package/dist/utils/csv.cjs.map +1 -1
  1463. package/dist/utils/csv.js +11 -10
  1464. package/dist/utils/csv.js.map +1 -1
  1465. package/dist/utils/dev-mode.cjs.map +1 -1
  1466. package/dist/utils/dev-mode.js.map +1 -1
  1467. package/dist/utils/duplicate-instance.cjs.map +1 -1
  1468. package/dist/utils/duplicate-instance.js.map +1 -1
  1469. package/dist/utils/format.cjs.map +1 -1
  1470. package/dist/utils/format.js.map +1 -1
  1471. package/dist/utils/functions.cjs +1 -1
  1472. package/dist/utils/functions.cjs.map +1 -1
  1473. package/dist/utils/functions.js +1 -1
  1474. package/dist/utils/functions.js.map +1 -1
  1475. package/dist/utils/guards.cjs.map +1 -1
  1476. package/dist/utils/guards.js.map +1 -1
  1477. package/dist/utils/ids.cjs.map +1 -1
  1478. package/dist/utils/ids.js.map +1 -1
  1479. package/dist/utils/intl-cache.cjs.map +1 -1
  1480. package/dist/utils/intl-cache.js.map +1 -1
  1481. package/dist/utils/json-frame.cjs.map +1 -1
  1482. package/dist/utils/json-frame.js.map +1 -1
  1483. package/dist/utils/numbers.cjs.map +1 -1
  1484. package/dist/utils/numbers.js.map +1 -1
  1485. package/dist/utils/objects.cjs.map +1 -1
  1486. package/dist/utils/objects.js.map +1 -1
  1487. package/dist/{telemetry/app-error-owner.cjs → utils/owner-fingerprint.cjs} +2 -2
  1488. package/dist/utils/owner-fingerprint.cjs.map +1 -0
  1489. package/dist/{telemetry/app-error-owner.js → utils/owner-fingerprint.js} +3 -3
  1490. package/dist/utils/owner-fingerprint.js.map +1 -0
  1491. package/dist/utils/promises.cjs.map +1 -1
  1492. package/dist/utils/promises.js.map +1 -1
  1493. package/dist/utils/relative-time.cjs.map +1 -1
  1494. package/dist/utils/relative-time.js.map +1 -1
  1495. package/dist/utils/safe-url.cjs.map +1 -1
  1496. package/dist/utils/safe-url.js.map +1 -1
  1497. package/dist/utils/schema-like.cjs.map +1 -1
  1498. package/dist/utils/schema-like.js.map +1 -1
  1499. package/dist/utils/storage.cjs +1 -1
  1500. package/dist/utils/storage.cjs.map +1 -1
  1501. package/dist/utils/storage.js +2 -2
  1502. package/dist/utils/storage.js.map +1 -1
  1503. package/dist/utils/strings.cjs.map +1 -1
  1504. package/dist/utils/strings.js.map +1 -1
  1505. package/dist/utils/xlsx.cjs.map +1 -1
  1506. package/dist/utils/xlsx.js.map +1 -1
  1507. package/dist/vision/core/canvas.cjs.map +1 -1
  1508. package/dist/vision/core/canvas.js.map +1 -1
  1509. package/dist/vision/core/dtypes.cjs.map +1 -1
  1510. package/dist/vision/core/dtypes.js.map +1 -1
  1511. package/dist/vision/core/exceptions.cjs.map +1 -1
  1512. package/dist/vision/core/exceptions.js.map +1 -1
  1513. package/dist/vision/core/graph.cjs.map +1 -1
  1514. package/dist/vision/core/graph.js.map +1 -1
  1515. package/dist/vision/core/metadata.cjs +1 -1
  1516. package/dist/vision/core/metadata.cjs.map +1 -1
  1517. package/dist/vision/core/metadata.js +9 -26
  1518. package/dist/vision/core/metadata.js.map +1 -1
  1519. package/dist/vision/core/providers.cjs.map +1 -1
  1520. package/dist/vision/core/providers.js.map +1 -1
  1521. package/dist/vision/core/session.cjs.map +1 -1
  1522. package/dist/vision/core/session.js.map +1 -1
  1523. package/dist/vision/core/timing.cjs.map +1 -1
  1524. package/dist/vision/core/timing.js.map +1 -1
  1525. package/dist/vision/fusion.cjs.map +1 -1
  1526. package/dist/vision/fusion.js.map +1 -1
  1527. package/dist/vision/index.cjs.map +1 -1
  1528. package/dist/vision/index.js.map +1 -1
  1529. package/dist/vision/io/image.cjs.map +1 -1
  1530. package/dist/vision/io/image.js.map +1 -1
  1531. package/dist/vision/labels.cjs.map +1 -1
  1532. package/dist/vision/labels.js.map +1 -1
  1533. package/dist/vision/luminance.cjs.map +1 -1
  1534. package/dist/vision/luminance.js.map +1 -1
  1535. package/dist/vision/normalization.cjs.map +1 -1
  1536. package/dist/vision/normalization.js.map +1 -1
  1537. package/dist/vision/postprocess/classification.cjs.map +1 -1
  1538. package/dist/vision/postprocess/classification.js.map +1 -1
  1539. package/dist/vision/postprocess/detection.cjs.map +1 -1
  1540. package/dist/vision/postprocess/detection.js.map +1 -1
  1541. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  1542. package/dist/vision/postprocess/segmentation.js.map +1 -1
  1543. package/dist/vision/preprocess/image.cjs.map +1 -1
  1544. package/dist/vision/preprocess/image.js.map +1 -1
  1545. package/dist/vision/preprocess/pipeline.cjs.map +1 -1
  1546. package/dist/vision/preprocess/pipeline.js.map +1 -1
  1547. package/dist/vision/results.cjs.map +1 -1
  1548. package/dist/vision/results.js.map +1 -1
  1549. package/dist/vision/tasks/base.cjs.map +1 -1
  1550. package/dist/vision/tasks/base.js.map +1 -1
  1551. package/dist/vision/tasks/classifier.cjs.map +1 -1
  1552. package/dist/vision/tasks/classifier.js.map +1 -1
  1553. package/dist/vision/tasks/detectClassify.cjs.map +1 -1
  1554. package/dist/vision/tasks/detectClassify.js.map +1 -1
  1555. package/dist/vision/tasks/detector.cjs.map +1 -1
  1556. package/dist/vision/tasks/detector.js.map +1 -1
  1557. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  1558. package/dist/vision/tasks/segmenter.js.map +1 -1
  1559. package/dist/vision/types.cjs.map +1 -1
  1560. package/dist/vision/types.js.map +1 -1
  1561. package/dist/vision/use-camera-stream.cjs +1 -1
  1562. package/dist/vision/use-camera-stream.cjs.map +1 -1
  1563. package/dist/vision/use-camera-stream.js +3 -9
  1564. package/dist/vision/use-camera-stream.js.map +1 -1
  1565. package/dist/vision/use-live-luminance.cjs +1 -1
  1566. package/dist/vision/use-live-luminance.cjs.map +1 -1
  1567. package/dist/vision/use-live-luminance.js +1 -5
  1568. package/dist/vision/use-live-luminance.js.map +1 -1
  1569. package/dist/vite/base-url.cjs.map +1 -1
  1570. package/dist/vite/base-url.js.map +1 -1
  1571. package/dist/vite/create-vite-config.cjs.map +1 -1
  1572. package/dist/vite/create-vite-config.js.map +1 -1
  1573. package/dist/vite/narrow-tokens.cjs.map +1 -1
  1574. package/dist/vite/narrow-tokens.js.map +1 -1
  1575. package/dist/vite/tempest-csp.cjs +2 -2
  1576. package/dist/vite/tempest-csp.cjs.map +1 -1
  1577. package/dist/vite/tempest-csp.js +69 -66
  1578. package/dist/vite/tempest-csp.js.map +1 -1
  1579. package/dist/vite/tempest-icons.cjs.map +1 -1
  1580. package/dist/vite/tempest-icons.js.map +1 -1
  1581. package/dist/vite/tempest-pwa-dev-sw.cjs +1 -1
  1582. package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
  1583. package/dist/vite/tempest-pwa-dev-sw.js +9 -16
  1584. package/dist/vite/tempest-pwa-dev-sw.js.map +1 -1
  1585. package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
  1586. package/dist/vite/tempest-pwa-icons.js.map +1 -1
  1587. package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
  1588. package/dist/vite/tempest-pwa-manifest.js.map +1 -1
  1589. package/dist/vite/tempest-styles.cjs.map +1 -1
  1590. package/dist/vite/tempest-styles.js.map +1 -1
  1591. package/dist/vite/tempest-vitest.cjs.map +1 -1
  1592. package/dist/vite/tempest-vitest.js.map +1 -1
  1593. package/dist/vite.d.ts +5 -3
  1594. package/dist/webrtc/link-stats.cjs.map +1 -1
  1595. package/dist/webrtc/link-stats.js.map +1 -1
  1596. package/dist/webrtc/mesh-quality.cjs.map +1 -1
  1597. package/dist/webrtc/mesh-quality.js.map +1 -1
  1598. package/dist/webrtc/opus-sdp.cjs.map +1 -1
  1599. package/dist/webrtc/opus-sdp.js.map +1 -1
  1600. package/dist/webrtc/peer-link.cjs +1 -1
  1601. package/dist/webrtc/peer-link.cjs.map +1 -1
  1602. package/dist/webrtc/peer-link.js +2 -5
  1603. package/dist/webrtc/peer-link.js.map +1 -1
  1604. package/dist/webrtc/peer-mesh.cjs +1 -1
  1605. package/dist/webrtc/peer-mesh.cjs.map +1 -1
  1606. package/dist/webrtc/peer-mesh.js +8 -24
  1607. package/dist/webrtc/peer-mesh.js.map +1 -1
  1608. package/dist/webrtc/sender-bitrate.cjs.map +1 -1
  1609. package/dist/webrtc/sender-bitrate.js.map +1 -1
  1610. package/dist/webrtc/use-link-stats.cjs.map +1 -1
  1611. package/dist/webrtc/use-link-stats.js.map +1 -1
  1612. package/dist/ws/create-web-socket.cjs +1 -1
  1613. package/dist/ws/create-web-socket.cjs.map +1 -1
  1614. package/dist/ws/create-web-socket.js +4 -22
  1615. package/dist/ws/create-web-socket.js.map +1 -1
  1616. package/dist/ws/resilience.cjs.map +1 -1
  1617. package/dist/ws/resilience.js.map +1 -1
  1618. package/dist/ws/use-web-socket.cjs.map +1 -1
  1619. package/dist/ws/use-web-socket.js.map +1 -1
  1620. package/package.json +9 -6
  1621. package/template/package.json +1 -1
  1622. package/dist/telemetry/app-error-owner.cjs.map +0 -1
  1623. package/dist/telemetry/app-error-owner.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-typewriter.js","names":[],"sources":["../../src/hooks/use-typewriter.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\nimport { useInterval } from \"./use-interval\";\n\n/** State returned by {@link useTypewriter}. */\nexport interface UseTypewriterResult {\n /** The prefix of `text` revealed so far. */\n displayedText: string;\n /** `true` once the whole string is on screen. */\n isComplete: boolean;\n /** Reveal the rest immediately — wire it to a tap or a key press. */\n skip: () => void;\n}\n\n/**\n * Reveals a string one character at a time.\n *\n * Changing `text` restarts the reveal. The reset happens during render rather\n * than in an effect, so the new string never flashes in full for one frame\n * before the animation takes over.\n *\n * Always give the reader a way out: an animation that cannot be skipped is a\n * tax on anyone re-reading or moving fast, which is what `skip` is for.\n *\n * How far the reveal got is derived rather than stored: a `speedMs` of `0` reads\n * as \"all of it\" without a state write, and `useInterval` pausing on a `null`\n * delay is what stops the timer at the end. Both used to need an effect that\n * cleared its own interval from inside a state updater.\n *\n * @param text - The full string to reveal. Nullish is treated as empty.\n * @param speedMs - Delay between characters. `0` or less renders instantly,\n * which is the hook-safe way to honour `prefers-reduced-motion`.\n * @returns The revealed prefix, whether it finished, and a `skip` action.\n *\n * @example\n * const reduced = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n * const { displayedText, isComplete, skip } = useTypewriter(line, reduced ? 0 : 30);\n *\n * return <p onClick={skip}>{displayedText}{isComplete ? \"\" : \"▌\"}</p>;\n */\nexport function useTypewriter(text: string, speedMs: number): UseTypewriterResult {\n const safeText = text ?? \"\";\n const initialCount = speedMs > 0 ? 0 : safeText.length;\n\n const [renderedText, setRenderedText] = useState(safeText);\n const [count, setCount] = useState(initialCount);\n\n if (renderedText !== safeText) {\n setRenderedText(safeText);\n setCount(initialCount);\n }\n\n const revealed = speedMs > 0 ? Math.min(count, safeText.length) : safeText.length;\n\n useInterval(\n () => setCount((current) => current + 1),\n speedMs > 0 && revealed < safeText.length ? speedMs : null,\n );\n\n const skip = useCallback(() => setCount(safeText.length), [safeText.length]);\n\n return {\n displayedText: safeText.slice(0, revealed),\n isComplete: revealed >= safeText.length,\n skip,\n };\n}\n"],"mappings":";;;AAuCA,SAAgB,EAAc,GAAc,GAAsC;CAC9E,IAAM,IAAW,KAAQ,IACnB,IAAe,IAAU,IAAI,IAAI,EAAS,QAE1C,CAAC,GAAc,KAAmB,EAAS,CAAQ,GACnD,CAAC,GAAO,KAAY,EAAS,CAAY;CAE/C,AAAI,MAAiB,MACjB,EAAgB,CAAQ,GACxB,EAAS,CAAY;CAGzB,IAAM,IAAW,IAAU,IAAI,KAAK,IAAI,GAAO,EAAS,MAAM,IAAI,EAAS;CAE3E,QACU,GAAU,MAAY,IAAU,CAAC,GACvC,IAAU,KAAK,IAAW,EAAS,SAAS,IAAU,IAC1D;CAEA,IAAM,IAAO,QAAkB,EAAS,EAAS,MAAM,GAAG,CAAC,EAAS,MAAM,CAAC;CAE3E,OAAO;EACH,eAAe,EAAS,MAAM,GAAG,CAAQ;EACzC,YAAY,KAAY,EAAS;EACjC;CACJ;AACJ"}
1
+ {"version":3,"file":"use-typewriter.js","names":["useTypewriter","safeText","text","initialCount","speedMs","renderedText","setRenderedText","useState","count","setCount","revealed","current","skip","useCallback"],"sources":["../../src/hooks/use-typewriter.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\nimport { useInterval } from \"./use-interval\";\n\n/** State returned by {@link useTypewriter}. */\nexport interface UseTypewriterResult {\n /** The prefix of `text` revealed so far. */\n displayedText: string;\n /** `true` once the whole string is on screen. */\n isComplete: boolean;\n /** Reveal the rest immediately — wire it to a tap or a key press. */\n skip: () => void;\n}\n\n/**\n * Reveals a string one character at a time.\n *\n * Changing `text` restarts the reveal. The reset happens during render rather\n * than in an effect, so the new string never flashes in full for one frame\n * before the animation takes over.\n *\n * Always give the reader a way out: an animation that cannot be skipped is a\n * tax on anyone re-reading or moving fast, which is what `skip` is for.\n *\n * How far the reveal got is derived rather than stored: a `speedMs` of `0` reads\n * as \"all of it\" without a state write, and `useInterval` pausing on a `null`\n * delay is what stops the timer at the end. Both used to need an effect that\n * cleared its own interval from inside a state updater.\n *\n * @param text - The full string to reveal. Nullish is treated as empty.\n * @param speedMs - Delay between characters. `0` or less renders instantly,\n * which is the hook-safe way to honour `prefers-reduced-motion`.\n * @returns The revealed prefix, whether it finished, and a `skip` action.\n *\n * @example\n * const reduced = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n * const { displayedText, isComplete, skip } = useTypewriter(line, reduced ? 0 : 30);\n *\n * return <p onClick={skip}>{displayedText}{isComplete ? \"\" : \"▌\"}</p>;\n */\nexport function useTypewriter(text: string, speedMs: number): UseTypewriterResult {\n const safeText = text ?? \"\";\n const initialCount = speedMs > 0 ? 0 : safeText.length;\n\n const [renderedText, setRenderedText] = useState(safeText);\n const [count, setCount] = useState(initialCount);\n\n if (renderedText !== safeText) {\n setRenderedText(safeText);\n setCount(initialCount);\n }\n\n const revealed = speedMs > 0 ? Math.min(count, safeText.length) : safeText.length;\n\n useInterval(\n () => setCount((current) => current + 1),\n speedMs > 0 && revealed < safeText.length ? speedMs : null,\n );\n\n const skip = useCallback(() => setCount(safeText.length), [safeText.length]);\n\n return {\n displayedText: safeText.slice(0, revealed),\n isComplete: revealed >= safeText.length,\n skip,\n };\n}\n"],"mappings":";;;AAuCA,SAAgBA,EAAc,GAAc,GAAsC;CAC9E,IAAMC,IAAWC,KAAQ,IACnBC,IAAeC,IAAU,IAAI,IAAIH,EAAS,QAE1C,CAACI,GAAcC,KAAmBC,EAASN,CAAQ,GACnD,CAACO,GAAOC,KAAYF,EAASJ,CAAY;CAE/C,AAAIE,MAAiBJ,MACjBK,EAAgBL,CAAQ,GACxBQ,EAASN,CAAY;CAGzB,IAAMO,IAAWN,IAAU,IAAI,KAAK,IAAII,GAAOP,EAAS,MAAM,IAAIA,EAAS;CAE3E,QACUQ,GAAU,MAAYE,IAAU,CAAC,GACvCP,IAAU,KAAKM,IAAWT,EAAS,SAASG,IAAU,IAC1D;CAEA,IAAMQ,IAAOC,QAAkBJ,EAASR,EAAS,MAAM,GAAG,CAACA,EAAS,MAAM,CAAC;CAE3E,OAAO;EACH,eAAeA,EAAS,MAAM,GAAGS,CAAQ;EACzC,YAAYA,KAAYT,EAAS;EACjC;CACJ;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-window-size.cjs","names":[],"sources":["../../src/hooks/use-window-size.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\n/**\n * Reactive window dimensions. SSR-safe — returns `{ width: 0, height: 0 }`\n * until the first client render.\n *\n * @example\n * const { width, height } = useWindowSize();\n * const columns = width < 640 ? 1 : width < 1024 ? 2 : 3;\n */\nexport function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() =>\n typeof window === \"undefined\"\n ? { width: 0, height: 0 }\n : { width: window.innerWidth, height: window.innerHeight },\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onResize = (): void =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n"],"mappings":"uBAeA,SAAgB,GAA4B,CACxC,GAAM,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,KACpB,OAAO,OAAW,IACZ,CAAE,MAAO,EAAG,OAAQ,CAAE,EACtB,CAAE,MAAO,OAAO,WAAY,OAAQ,OAAO,WAAY,CACjE,EAWA,OATA,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,OAAO,OAAW,IAAa,OACnC,IAAM,MACF,EAAQ,CAAE,MAAO,OAAO,WAAY,OAAQ,OAAO,WAAY,CAAC,EAGpE,OAFA,EAAS,EACT,OAAO,iBAAiB,SAAU,EAAU,CAAE,QAAS,EAAK,CAAC,MAChD,OAAO,oBAAoB,SAAU,CAAQ,CAC9D,EAAG,CAAC,CAAC,EAEE,CACX"}
1
+ {"version":3,"file":"use-window-size.cjs","names":["useState","react","useWindowSize","size","setSize","onResize"],"sources":["../../src/hooks/use-window-size.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\n/**\n * Reactive window dimensions. SSR-safe — returns `{ width: 0, height: 0 }`\n * until the first client render.\n *\n * @example\n * const { width, height } = useWindowSize();\n * const columns = width < 640 ? 1 : width < 1024 ? 2 : 3;\n */\nexport function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() =>\n typeof window === \"undefined\"\n ? { width: 0, height: 0 }\n : { width: window.innerWidth, height: window.innerHeight },\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onResize = (): void =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n"],"mappings":"A,uBAeA,SAAgBE,GAA4B,CACxC,GAAM,CAACC,EAAMC,IAAA,EAAWJ,EAAAA,SAAAA,KACpB,OAAO,OAAW,IACZ,CAAE,MAAO,EAAG,OAAQ,CAAE,EACtB,CAAE,MAAO,OAAO,WAAY,OAAQ,OAAO,WAAY,CACjE,EAWA,OATA,EAAAC,EAAA,UAAA,KAAgB,CACZ,GAAI,OAAO,OAAW,IAAa,OACnC,IAAMI,MACFD,EAAQ,CAAE,MAAO,OAAO,WAAY,OAAQ,OAAO,WAAY,CAAC,EAGpE,OAFAC,EAAS,EACT,OAAO,iBAAiB,SAAUA,EAAU,CAAE,QAAS,EAAK,CAAC,MAChD,OAAO,oBAAoB,SAAUA,CAAQ,CAC9D,EAAG,CAAC,CAAC,EAEEF,CACX,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-window-size.js","names":[],"sources":["../../src/hooks/use-window-size.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\n/**\n * Reactive window dimensions. SSR-safe — returns `{ width: 0, height: 0 }`\n * until the first client render.\n *\n * @example\n * const { width, height } = useWindowSize();\n * const columns = width < 640 ? 1 : width < 1024 ? 2 : 3;\n */\nexport function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() =>\n typeof window === \"undefined\"\n ? { width: 0, height: 0 }\n : { width: window.innerWidth, height: window.innerHeight },\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onResize = (): void =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n"],"mappings":";;AAeA,SAAgB,IAA4B;CACxC,IAAM,CAAC,GAAM,KAAW,QACpB,OAAO,SAAW,MACZ;EAAE,OAAO;EAAG,QAAQ;CAAE,IACtB;EAAE,OAAO,OAAO;EAAY,QAAQ,OAAO;CAAY,CACjE;CAWA,OATA,QAAgB;EACZ,IAAI,OAAO,SAAW,KAAa;EACnC,IAAM,UACF,EAAQ;GAAE,OAAO,OAAO;GAAY,QAAQ,OAAO;EAAY,CAAC;EAGpE,OAFA,EAAS,GACT,OAAO,iBAAiB,UAAU,GAAU,EAAE,SAAS,GAAK,CAAC,SAChD,OAAO,oBAAoB,UAAU,CAAQ;CAC9D,GAAG,CAAC,CAAC,GAEE;AACX"}
1
+ {"version":3,"file":"use-window-size.js","names":["useWindowSize","size","setSize","useState","useEffect","onResize"],"sources":["../../src/hooks/use-window-size.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\n/**\n * Reactive window dimensions. SSR-safe — returns `{ width: 0, height: 0 }`\n * until the first client render.\n *\n * @example\n * const { width, height } = useWindowSize();\n * const columns = width < 640 ? 1 : width < 1024 ? 2 : 3;\n */\nexport function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() =>\n typeof window === \"undefined\"\n ? { width: 0, height: 0 }\n : { width: window.innerWidth, height: window.innerHeight },\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onResize = (): void =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n"],"mappings":";;AAeA,SAAgBA,IAA4B;CACxC,IAAM,CAACC,GAAMC,KAAWC,QACpB,OAAO,SAAW,MACZ;EAAE,OAAO;EAAG,QAAQ;CAAE,IACtB;EAAE,OAAO,OAAO;EAAY,QAAQ,OAAO;CAAY,CACjE;CAWA,OATAC,QAAgB;EACZ,IAAI,OAAO,SAAW,KAAa;EACnC,IAAMC,UACFH,EAAQ;GAAE,OAAO,OAAO;GAAY,QAAQ,OAAO;EAAY,CAAC;EAGpE,OAFAG,EAAS,GACT,OAAO,iBAAiB,UAAUA,GAAU,EAAE,SAAS,GAAK,CAAC,SAChD,OAAO,oBAAoB,UAAUA,CAAQ;CAC9D,GAAG,CAAC,CAAC,GAEEJ;AACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.cjs","names":[],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\nimport { csrfHeaders } from \"./csrf\";\nimport { decodeByContentType } from \"./decode-response\";\nimport type { ResponseDecoder } from \"./decode-response\";\nimport {\n buildApiError,\n SessionSupersededError,\n TempestApiError,\n isRetriableStatus,\n} from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestAuthContext, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Binary bodies** have their own methods — `blob()` and `arrayBuffer()` — which\n * run the same pipeline and skip the parse. `request()` no longer decodes an\n * unknown `Content-Type` as text either: it returns a `Blob` and says so once in\n * a development build, because reading `image/jpeg` as UTF-8 destroyed the bytes\n * on the way in.\n *\n * **The bearer token is scoped to `baseURL`'s origin** since 0.66.0. A path may\n * be an absolute URL, which overrides the base entirely, so without a scope the\n * destination of a credentialed request could come from a value read off the\n * network. A request to another origin still goes out; it goes without the\n * header, and a development build says so once. Declare the exceptions in\n * {@link ApiClientConfig.trustedOrigins}.\n *\n * **CSRF** is off unless you set `csrf`. With it, every unsafe request (anything\n * but `GET`/`HEAD`/`OPTIONS`/`TRACE`) echoes the `csrf_token` cookie in an\n * `X-CSRF-Token` header — the double-submit contract of `tempest-fastapi-sdk`'s\n * `CSRFMiddleware` — scoped to the same origins as the bearer token and sent on\n * `skipAuth` requests too. See {@link ApiClientConfig.csrf}.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write. A single call overrides it\n * with {@link RequestOptions.retry}, and opts out of auth entirely with\n * {@link RequestOptions.skipAuth}.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`blob`/\n * `arrayBuffer`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n /**\n * The `Authorization` header for a request, or nothing.\n *\n * Takes the resolved URL rather than reading `config.baseURL`, because an\n * absolute path overrides the base entirely (see `buildApiUrl`) and the\n * credential is scoped to an origin, not to a client.\n *\n * @param url - The absolute URL the request is going to.\n * @param skipAuth - Whether the caller opted this request out of auth.\n * @returns The header, or an empty object.\n */\n function authHeaders(url: string, skipAuth: boolean): Record<string, string> {\n if (skipAuth) return {};\n const token = config.getToken?.();\n if (!token) return {};\n if (!isTrustedCredentialTarget(url, config.baseURL, config.trustedOrigins)) {\n reportSuppressedCredential(url, config.baseURL);\n return {};\n }\n return { Authorization: `Bearer ${token}` };\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId: string | undefined,\n skipAuth: boolean,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n\n const callerHeaders = headers as Record<string, string> | undefined;\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(url, skipAuth),\n ...csrfHeaders({\n method: rest.method ?? \"GET\",\n url,\n reference: config.baseURL,\n csrf: config.csrf,\n trustedOrigins: config.trustedOrigins,\n headers: { ...config.headers, ...callerHeaders },\n }),\n ...callerHeaders,\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n skipAuth: boolean,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId, skipAuth);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId, skipAuth);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n /**\n * Call `onUnauthorized`, keeping the request's own error unless the hook\n * says the attempt belongs to an ended session.\n *\n * @param response - The `401` that ended the attempt.\n * @param requestId - Correlation id for the log.\n * @param context - The credential and session the attempt left with.\n * @throws {SessionSupersededError} When `onUnauthorized` threw it.\n */\n async function notifyUnauthorized(\n response: Response,\n requestId: string,\n context: RequestAuthContext,\n ): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response, context);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n /**\n * The credential and session an attempt leaves with, read just before it is\n * sent.\n *\n * @param skipAuth - Whether the attempt goes out without credentials.\n * @returns The context handed to `refresh` and `onUnauthorized`.\n */\n function authContext(skipAuth: boolean): RequestAuthContext {\n return {\n token: skipAuth ? null : (config.getToken?.() ?? null),\n epoch: config.getSessionEpoch?.() ?? null,\n };\n }\n\n async function attempt<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { skipAuth = false, skipAuthRetry = false, ...init } = options;\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (init.method ?? \"GET\").toUpperCase();\n const sent = authContext(skipAuth);\n let response = await send(path, init, requestId, method, skipAuth);\n\n if (response.status === 401 && !skipAuth && !skipAuthRetry) {\n if (config.refresh) {\n let replayed: RequestAuthContext;\n try {\n await config.refresh(sent);\n replayed = authContext(skipAuth);\n response = await send(path, init, requestId, method, skipAuth);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n await notifyUnauthorized(response, requestId, sent);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId, replayed);\n }\n } else {\n await notifyUnauthorized(response, requestId, sent);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n return decode(response);\n }\n\n async function run<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { retry: perRequest, ...rest } = options;\n const retryOptions = resolveRetry(perRequest !== undefined ? perRequest : config.retry);\n if (!retryOptions) return attempt<T>(path, rest, decode);\n\n const method = (rest.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, rest, decode), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return run<T>(path, options, decodeByContentType);\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n blob: (path: string, options?: RequestOptions) =>\n run<Blob>(path, { ...options }, (response) => response.blob()),\n arrayBuffer: (path: string, options?: RequestOptions) =>\n run<ArrayBuffer>(path, { ...options }, (response) => response.arrayBuffer()),\n upload,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-client.cjs","names":["TempestApiError","isRetriableStatus","buildApiError","isTrustedCredentialTarget","buildApiUrl","csrfHeaders","withTimeout","SessionSupersededError","randomId","retryWithBackoff","decodeByContentType","require_ids","require_build_url","require_credential_scope","require_csrf","require_decode_response","require_errors","require_retry","require_timeout","IDEMPOTENT_METHODS","isRetriableFailure","method","error","resolveRetry","config","DEFAULT_TIMEOUT","DEFAULT_UPLOAD_TIMEOUT","isFormData","body","elapsedMs","startedAt","parseError","response","sentRequestId","createApiClient","fetcher","authHeaders","skipAuth","token","url","rawRequest","rest","options","isForm","configured","limit","timeout","path","callerHeaders","headers","finalHeaders","requestId","timed","signal","init","cause","send","log","entry","line","notifyUnauthorized","context","authContext","attempt","sent","skipAuthRetry","replayed","decode","run","perRequest","retryOptions","request","upload","formData"],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\nimport { csrfHeaders } from \"./csrf\";\nimport { decodeByContentType } from \"./decode-response\";\nimport type { ResponseDecoder } from \"./decode-response\";\nimport {\n buildApiError,\n SessionSupersededError,\n TempestApiError,\n isRetriableStatus,\n} from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestAuthContext, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Binary bodies** have their own methods — `blob()` and `arrayBuffer()` — which\n * run the same pipeline and skip the parse. `request()` no longer decodes an\n * unknown `Content-Type` as text either: it returns a `Blob` and says so once in\n * a development build, because reading `image/jpeg` as UTF-8 destroyed the bytes\n * on the way in.\n *\n * **The bearer token is scoped to `baseURL`'s origin** since 0.66.0. A path may\n * be an absolute URL, which overrides the base entirely, so without a scope the\n * destination of a credentialed request could come from a value read off the\n * network. A request to another origin still goes out; it goes without the\n * header, and a development build says so once. Declare the exceptions in\n * {@link ApiClientConfig.trustedOrigins}.\n *\n * **CSRF** is off unless you set `csrf`. With it, every unsafe request (anything\n * but `GET`/`HEAD`/`OPTIONS`/`TRACE`) echoes the `csrf_token` cookie in an\n * `X-CSRF-Token` header — the double-submit contract of `tempest-fastapi-sdk`'s\n * `CSRFMiddleware` — scoped to the same origins as the bearer token and sent on\n * `skipAuth` requests too. See {@link ApiClientConfig.csrf}.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write. A single call overrides it\n * with {@link RequestOptions.retry}, and opts out of auth entirely with\n * {@link RequestOptions.skipAuth}.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`blob`/\n * `arrayBuffer`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n /**\n * The `Authorization` header for a request, or nothing.\n *\n * Takes the resolved URL rather than reading `config.baseURL`, because an\n * absolute path overrides the base entirely (see `buildApiUrl`) and the\n * credential is scoped to an origin, not to a client.\n *\n * @param url - The absolute URL the request is going to.\n * @param skipAuth - Whether the caller opted this request out of auth.\n * @returns The header, or an empty object.\n */\n function authHeaders(url: string, skipAuth: boolean): Record<string, string> {\n if (skipAuth) return {};\n const token = config.getToken?.();\n if (!token) return {};\n if (!isTrustedCredentialTarget(url, config.baseURL, config.trustedOrigins)) {\n reportSuppressedCredential(url, config.baseURL);\n return {};\n }\n return { Authorization: `Bearer ${token}` };\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId: string | undefined,\n skipAuth: boolean,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n\n const callerHeaders = headers as Record<string, string> | undefined;\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(url, skipAuth),\n ...csrfHeaders({\n method: rest.method ?? \"GET\",\n url,\n reference: config.baseURL,\n csrf: config.csrf,\n trustedOrigins: config.trustedOrigins,\n headers: { ...config.headers, ...callerHeaders },\n }),\n ...callerHeaders,\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n skipAuth: boolean,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId, skipAuth);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId, skipAuth);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n /**\n * Call `onUnauthorized`, keeping the request's own error unless the hook\n * says the attempt belongs to an ended session.\n *\n * @param response - The `401` that ended the attempt.\n * @param requestId - Correlation id for the log.\n * @param context - The credential and session the attempt left with.\n * @throws {SessionSupersededError} When `onUnauthorized` threw it.\n */\n async function notifyUnauthorized(\n response: Response,\n requestId: string,\n context: RequestAuthContext,\n ): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response, context);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n /**\n * The credential and session an attempt leaves with, read just before it is\n * sent.\n *\n * @param skipAuth - Whether the attempt goes out without credentials.\n * @returns The context handed to `refresh` and `onUnauthorized`.\n */\n function authContext(skipAuth: boolean): RequestAuthContext {\n return {\n token: skipAuth ? null : (config.getToken?.() ?? null),\n epoch: config.getSessionEpoch?.() ?? null,\n };\n }\n\n async function attempt<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { skipAuth = false, skipAuthRetry = false, ...init } = options;\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (init.method ?? \"GET\").toUpperCase();\n const sent = authContext(skipAuth);\n let response = await send(path, init, requestId, method, skipAuth);\n\n if (response.status === 401 && !skipAuth && !skipAuthRetry) {\n if (config.refresh) {\n let replayed: RequestAuthContext;\n try {\n await config.refresh(sent);\n replayed = authContext(skipAuth);\n response = await send(path, init, requestId, method, skipAuth);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n await notifyUnauthorized(response, requestId, sent);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId, replayed);\n }\n } else {\n await notifyUnauthorized(response, requestId, sent);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n return decode(response);\n }\n\n async function run<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { retry: perRequest, ...rest } = options;\n const retryOptions = resolveRetry(perRequest !== undefined ? perRequest : config.retry);\n if (!retryOptions) return attempt<T>(path, rest, decode);\n\n const method = (rest.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, rest, decode), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return run<T>(path, options, decodeByContentType);\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n blob: (path: string, options?: RequestOptions) =>\n run<Blob>(path, { ...options }, (response) => response.blob()),\n arrayBuffer: (path: string, options?: RequestOptions) =>\n run<ArrayBuffer>(path, { ...options }, (response) => response.arrayBuffer()),\n upload,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","names":[],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\nimport { csrfHeaders } from \"./csrf\";\nimport { decodeByContentType } from \"./decode-response\";\nimport type { ResponseDecoder } from \"./decode-response\";\nimport {\n buildApiError,\n SessionSupersededError,\n TempestApiError,\n isRetriableStatus,\n} from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestAuthContext, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Binary bodies** have their own methods — `blob()` and `arrayBuffer()` — which\n * run the same pipeline and skip the parse. `request()` no longer decodes an\n * unknown `Content-Type` as text either: it returns a `Blob` and says so once in\n * a development build, because reading `image/jpeg` as UTF-8 destroyed the bytes\n * on the way in.\n *\n * **The bearer token is scoped to `baseURL`'s origin** since 0.66.0. A path may\n * be an absolute URL, which overrides the base entirely, so without a scope the\n * destination of a credentialed request could come from a value read off the\n * network. A request to another origin still goes out; it goes without the\n * header, and a development build says so once. Declare the exceptions in\n * {@link ApiClientConfig.trustedOrigins}.\n *\n * **CSRF** is off unless you set `csrf`. With it, every unsafe request (anything\n * but `GET`/`HEAD`/`OPTIONS`/`TRACE`) echoes the `csrf_token` cookie in an\n * `X-CSRF-Token` header — the double-submit contract of `tempest-fastapi-sdk`'s\n * `CSRFMiddleware` — scoped to the same origins as the bearer token and sent on\n * `skipAuth` requests too. See {@link ApiClientConfig.csrf}.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write. A single call overrides it\n * with {@link RequestOptions.retry}, and opts out of auth entirely with\n * {@link RequestOptions.skipAuth}.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`blob`/\n * `arrayBuffer`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n /**\n * The `Authorization` header for a request, or nothing.\n *\n * Takes the resolved URL rather than reading `config.baseURL`, because an\n * absolute path overrides the base entirely (see `buildApiUrl`) and the\n * credential is scoped to an origin, not to a client.\n *\n * @param url - The absolute URL the request is going to.\n * @param skipAuth - Whether the caller opted this request out of auth.\n * @returns The header, or an empty object.\n */\n function authHeaders(url: string, skipAuth: boolean): Record<string, string> {\n if (skipAuth) return {};\n const token = config.getToken?.();\n if (!token) return {};\n if (!isTrustedCredentialTarget(url, config.baseURL, config.trustedOrigins)) {\n reportSuppressedCredential(url, config.baseURL);\n return {};\n }\n return { Authorization: `Bearer ${token}` };\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId: string | undefined,\n skipAuth: boolean,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n\n const callerHeaders = headers as Record<string, string> | undefined;\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(url, skipAuth),\n ...csrfHeaders({\n method: rest.method ?? \"GET\",\n url,\n reference: config.baseURL,\n csrf: config.csrf,\n trustedOrigins: config.trustedOrigins,\n headers: { ...config.headers, ...callerHeaders },\n }),\n ...callerHeaders,\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n skipAuth: boolean,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId, skipAuth);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId, skipAuth);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n /**\n * Call `onUnauthorized`, keeping the request's own error unless the hook\n * says the attempt belongs to an ended session.\n *\n * @param response - The `401` that ended the attempt.\n * @param requestId - Correlation id for the log.\n * @param context - The credential and session the attempt left with.\n * @throws {SessionSupersededError} When `onUnauthorized` threw it.\n */\n async function notifyUnauthorized(\n response: Response,\n requestId: string,\n context: RequestAuthContext,\n ): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response, context);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n /**\n * The credential and session an attempt leaves with, read just before it is\n * sent.\n *\n * @param skipAuth - Whether the attempt goes out without credentials.\n * @returns The context handed to `refresh` and `onUnauthorized`.\n */\n function authContext(skipAuth: boolean): RequestAuthContext {\n return {\n token: skipAuth ? null : (config.getToken?.() ?? null),\n epoch: config.getSessionEpoch?.() ?? null,\n };\n }\n\n async function attempt<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { skipAuth = false, skipAuthRetry = false, ...init } = options;\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (init.method ?? \"GET\").toUpperCase();\n const sent = authContext(skipAuth);\n let response = await send(path, init, requestId, method, skipAuth);\n\n if (response.status === 401 && !skipAuth && !skipAuthRetry) {\n if (config.refresh) {\n let replayed: RequestAuthContext;\n try {\n await config.refresh(sent);\n replayed = authContext(skipAuth);\n response = await send(path, init, requestId, method, skipAuth);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n await notifyUnauthorized(response, requestId, sent);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId, replayed);\n }\n } else {\n await notifyUnauthorized(response, requestId, sent);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n return decode(response);\n }\n\n async function run<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { retry: perRequest, ...rest } = options;\n const retryOptions = resolveRetry(perRequest !== undefined ? perRequest : config.retry);\n if (!retryOptions) return attempt<T>(path, rest, decode);\n\n const method = (rest.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, rest, decode), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return run<T>(path, options, decodeByContentType);\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n blob: (path: string, options?: RequestOptions) =>\n run<Blob>(path, { ...options }, (response) => response.blob()),\n arrayBuffer: (path: string, options?: RequestOptions) =>\n run<ArrayBuffer>(path, { ...options }, (response) => response.arrayBuffer()),\n upload,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-client.js","names":["retryWithBackoff","IDEMPOTENT_METHODS","isRetriableFailure","method","error","TempestApiError","isRetriableStatus","resolveRetry","config","DEFAULT_TIMEOUT","DEFAULT_UPLOAD_TIMEOUT","isFormData","body","elapsedMs","startedAt","parseError","response","buildApiError","sentRequestId","createApiClient","fetcher","authHeaders","skipAuth","token","isTrustedCredentialTarget","url","reportSuppressedCredential","rawRequest","rest","options","isForm","configured","limit","timeout","buildApiUrl","path","callerHeaders","headers","finalHeaders","requestId","csrfHeaders","timed","withTimeout","signal","init","cause","send","log","entry","line","notifyUnauthorized","context","SessionSupersededError","authContext","attempt","randomId","sent","skipAuthRetry","replayed","decode","run","perRequest","retryOptions","retry","request","decodeByContentType","upload","formData"],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\nimport { csrfHeaders } from \"./csrf\";\nimport { decodeByContentType } from \"./decode-response\";\nimport type { ResponseDecoder } from \"./decode-response\";\nimport {\n buildApiError,\n SessionSupersededError,\n TempestApiError,\n isRetriableStatus,\n} from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestAuthContext, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Binary bodies** have their own methods — `blob()` and `arrayBuffer()` — which\n * run the same pipeline and skip the parse. `request()` no longer decodes an\n * unknown `Content-Type` as text either: it returns a `Blob` and says so once in\n * a development build, because reading `image/jpeg` as UTF-8 destroyed the bytes\n * on the way in.\n *\n * **The bearer token is scoped to `baseURL`'s origin** since 0.66.0. A path may\n * be an absolute URL, which overrides the base entirely, so without a scope the\n * destination of a credentialed request could come from a value read off the\n * network. A request to another origin still goes out; it goes without the\n * header, and a development build says so once. Declare the exceptions in\n * {@link ApiClientConfig.trustedOrigins}.\n *\n * **CSRF** is off unless you set `csrf`. With it, every unsafe request (anything\n * but `GET`/`HEAD`/`OPTIONS`/`TRACE`) echoes the `csrf_token` cookie in an\n * `X-CSRF-Token` header — the double-submit contract of `tempest-fastapi-sdk`'s\n * `CSRFMiddleware` — scoped to the same origins as the bearer token and sent on\n * `skipAuth` requests too. See {@link ApiClientConfig.csrf}.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write. A single call overrides it\n * with {@link RequestOptions.retry}, and opts out of auth entirely with\n * {@link RequestOptions.skipAuth}.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`blob`/\n * `arrayBuffer`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n /**\n * The `Authorization` header for a request, or nothing.\n *\n * Takes the resolved URL rather than reading `config.baseURL`, because an\n * absolute path overrides the base entirely (see `buildApiUrl`) and the\n * credential is scoped to an origin, not to a client.\n *\n * @param url - The absolute URL the request is going to.\n * @param skipAuth - Whether the caller opted this request out of auth.\n * @returns The header, or an empty object.\n */\n function authHeaders(url: string, skipAuth: boolean): Record<string, string> {\n if (skipAuth) return {};\n const token = config.getToken?.();\n if (!token) return {};\n if (!isTrustedCredentialTarget(url, config.baseURL, config.trustedOrigins)) {\n reportSuppressedCredential(url, config.baseURL);\n return {};\n }\n return { Authorization: `Bearer ${token}` };\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId: string | undefined,\n skipAuth: boolean,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n\n const callerHeaders = headers as Record<string, string> | undefined;\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(url, skipAuth),\n ...csrfHeaders({\n method: rest.method ?? \"GET\",\n url,\n reference: config.baseURL,\n csrf: config.csrf,\n trustedOrigins: config.trustedOrigins,\n headers: { ...config.headers, ...callerHeaders },\n }),\n ...callerHeaders,\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n skipAuth: boolean,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId, skipAuth);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId, skipAuth);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n /**\n * Call `onUnauthorized`, keeping the request's own error unless the hook\n * says the attempt belongs to an ended session.\n *\n * @param response - The `401` that ended the attempt.\n * @param requestId - Correlation id for the log.\n * @param context - The credential and session the attempt left with.\n * @throws {SessionSupersededError} When `onUnauthorized` threw it.\n */\n async function notifyUnauthorized(\n response: Response,\n requestId: string,\n context: RequestAuthContext,\n ): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response, context);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n /**\n * The credential and session an attempt leaves with, read just before it is\n * sent.\n *\n * @param skipAuth - Whether the attempt goes out without credentials.\n * @returns The context handed to `refresh` and `onUnauthorized`.\n */\n function authContext(skipAuth: boolean): RequestAuthContext {\n return {\n token: skipAuth ? null : (config.getToken?.() ?? null),\n epoch: config.getSessionEpoch?.() ?? null,\n };\n }\n\n async function attempt<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { skipAuth = false, skipAuthRetry = false, ...init } = options;\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (init.method ?? \"GET\").toUpperCase();\n const sent = authContext(skipAuth);\n let response = await send(path, init, requestId, method, skipAuth);\n\n if (response.status === 401 && !skipAuth && !skipAuthRetry) {\n if (config.refresh) {\n let replayed: RequestAuthContext;\n try {\n await config.refresh(sent);\n replayed = authContext(skipAuth);\n response = await send(path, init, requestId, method, skipAuth);\n } catch (error) {\n if (error instanceof SessionSupersededError) throw error;\n await notifyUnauthorized(response, requestId, sent);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId, replayed);\n }\n } else {\n await notifyUnauthorized(response, requestId, sent);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n return decode(response);\n }\n\n async function run<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const { retry: perRequest, ...rest } = options;\n const retryOptions = resolveRetry(perRequest !== undefined ? perRequest : config.retry);\n if (!retryOptions) return attempt<T>(path, rest, decode);\n\n const method = (rest.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, rest, decode), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return run<T>(path, options, decodeByContentType);\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n blob: (path: string, options?: RequestOptions) =>\n run<Blob>(path, { ...options }, (response) => response.blob()),\n arrayBuffer: (path: string, options?: RequestOptions) =>\n run<ArrayBuffer>(path, { ...options }, (response) => response.arrayBuffer()),\n upload,\n };\n}\n"],"mappings":";;;;;;;;;AA8BA,IAAMC,oBAA0C,IAAI,IAAI;CAAC;CAAO;CAAQ;AAAS,CAAC;AAoBlF,SAASC,EAAmB,GAAgB,GAAyB;CAGjE,OAFI,CAACD,EAAmB,IAAIE,CAAM,KAC9B,EAAEC,aAAiBC,KAAyB,KACzCC,EAAkBF,EAAM,MAAM;AACzC;AAQA,SAASG,EAAa,GAAiE;CAEnF,OADKC,IACEA,MAAW,KAAO,CAAC,IAAIA,IADV;AAExB;AAGA,IAAMC,IAAkB,MAGlBC,IAAyB;AAE/B,SAASC,EAAW,GAAiC;CACjD,OAAO,OAAO,WAAa,OAAeC,aAAgB;AAC9D;AAaA,SAASC,EAAU,GAA2B;CAC1C,OAAO,KAAK,MAAM,YAAY,IAAI,IAAIC,CAAS;AACnD;AAEA,eAAeC,EAAW,GAAoB,GAAkD;CAC5F,IAAIH;CACJ,IAAI;EACA,IAAO,MAAMI,EAAS,MAAM,CAAC,CAAC,KAAK;CACvC,QAAQ;EACJ,IAAI;GACA,IAAO,MAAMA,EAAS,KAAK;EAC/B,QAAQ;GACJ,IAAO;EACX;CACJ;CACA,OAAO,IAAIX,EACPY,EAAcD,EAAS,QAAQJ,GAAMI,EAAS,SAASE,CAAa,CACxE;AACJ;AA0DA,SAAgBC,EAAgB,GAAoC;CAChE,IAAMC,IAAUZ,EAAO,WAAW,WAAW,MAAM,KAAK,UAAU;CAalE,SAASa,EAAY,GAAa,GAA2C;EACzE,IAAIC,GAAU,OAAO,CAAC;EACtB,IAAMC,IAAQf,EAAO,WAAW;EAMhC,OALKe,IACAC,EAA0BC,GAAKjB,EAAO,SAASA,EAAO,cAAc,IAIlE,EAAE,eAAe,UAAUe,IAAQ,KAHtCG,EAA2BD,GAAKjB,EAAO,OAAO,GACvC,CAAC,KAHO,CAAC;CAMxB;CAEA,eAAemB,EACX,GACA,GACA,GACA,GACiB;EACjB,IAAM,EAAE,SAAM,WAAQ,YAAS,WAAQ,YAAS,GAAGC,MAASC,GACtDC,IAASnB,EAAWC,CAAI,GACxBmB,IAAaD,IAAStB,EAAO,gBAAgBA,EAAO,SAEpDwB,IACFC,MAAY,KAAA,IAAsBF,MAAe,KAAA,IAFpCD,IAASpB,IAAyBD,IAEcsB,IAArCE,GAEtBR,IAAMS,EAAY1B,EAAO,SAAS2B,GAAM;GAAE,QAAQ3B,EAAO;GAAQ;EAAO,CAAC,GAEzE4B,IAAgBC,GAChBC,IAAuC;GACzC,GAAIR,IAAS,CAAC,IAAI,EAAE,gBAAgB,mBAAmB;GACvD,GAAIS,IAAY,EAAE,gBAAgBA,EAAU,IAAI,CAAC;GACjD,GAAG/B,EAAO;GACV,GAAGa,EAAYI,GAAKH,CAAQ;GAC5B,GAAGkB,EAAY;IACX,QAAQZ,EAAK,UAAU;IACvB;IACA,WAAWpB,EAAO;IAClB,MAAMA,EAAO;IACb,gBAAgBA,EAAO;IACvB,SAAS;KAAE,GAAGA,EAAO;KAAS,GAAG4B;IAAc;GACnD,CAAC;GACD,GAAGA;EACP,GAEMK,IAAQC,EAAYC,GAAQX,CAAK,GACjCY,IAAoB;GACtB,GAAGhB;GACH,QAAQa,EAAM;GACd,SAASH;GACT,aAAa9B,EAAO,kBAAkB,YAAYoB,EAAK;GACvD,MACIhB,KAA+B,OACzB,KAAA,IACAkB,IACGlB,IACD,KAAK,UAAUA,CAAI;EACnC;EAEA,IAAI;GACA,OAAO,MAAMQ,EAAQK,GAAKmB,CAAI;EAClC,SAASC,GAAO;GAOZ,MANIJ,EAAM,SAAS,IACT,IAAIpC,EAAgB;IACtB,QAAQ;IACR,QAAQ,wBAAwB2B,EAAM;GAC1C,CAAC,IAECa;EACV,UAAU;GACN,EAAM,QAAQ;EAClB;CACJ;CAEA,eAAeC,EACX,GACA,GACA,GACA,GACA,GACiB;EACjB,IAAMC,IAAMvC,EAAO;EACnB,IAAI,CAACuC,GAAK,OAAOpB,EAAWQ,GAAMN,GAASU,GAAWjB,CAAQ;EAE9D,IAAMR,IAAY,YAAY,IAAI;EAClC,IAAI;GACA,IAAME,IAAW,MAAMW,EAAWQ,GAAMN,GAASU,GAAWjB,CAAQ,GAC9D0B,IAAQ;IAAE;IAAW,QAAQhC,EAAS;IAAQ,IAAIH,EAAUC,CAAS;GAAE,GACvEmC,IAAO,GAAG9C,EAAO,GAAGgC,EAAK,KAAKnB,EAAS;GAG7C,OAFIA,EAAS,UAAU,MAAK+B,EAAI,KAAKE,GAAMD,CAAK,IAC3CD,EAAI,MAAME,GAAMD,CAAK,GACnBhC;EACX,SAASZ,GAAO;GAMZ,MALA2C,EAAI,KAAK,GAAG5C,EAAO,GAAGgC,EAAK,iBAAiB;IACxC;IACA,IAAItB,EAAUC,CAAS;IACvB;GACJ,CAAC,GACKV;EACV;CACJ;CAWA,eAAe8C,EACX,GACA,GACA,GACa;EACb,IAAK1C,EAAO,gBACZ;KAAO,QAAQ,KAAK,yCAAyC;IACzD;IACA,QAAQQ,EAAS;GACrB,CAAC;GACD,IAAI;IACA,MAAMR,EAAO,eAAeQ,GAAUmC,CAAO;GACjD,SAAS/C,GAAO;IACZ,IAAIA,aAAiBgD,GAAwB,MAAMhD;IACnD,EAAO,QAAQ,KAAK,8DAA8D;KAC9E;KACA,QAAQY,EAAS;KACjB;IACJ,CAAC;GACL;EAVC;CAWL;CASA,SAASqC,EAAY,GAAuC;EACxD,OAAO;GACH,OAAO/B,IAAW,OAAQd,EAAO,WAAW,KAAK;GACjD,OAAOA,EAAO,kBAAkB,KAAK;EACzC;CACJ;CAEA,eAAe8C,EACX,GACA,GACA,GACU;EACV,IAAM,EAAE,cAAW,IAAO,mBAAgB,IAAO,GAAGV,MAASf,GACvDU,IAAY/B,EAAO,YAAYA,EAAO,UAAU,IAAI+C,EAAS,GAC7DpD,KAAUyC,EAAK,UAAU,MAAA,CAAO,YAAY,GAC5CY,IAAOH,EAAY/B,CAAQ,GAC7BN,IAAW,MAAM8B,EAAKX,GAAMS,GAAML,GAAWpC,GAAQmB,CAAQ;EAEjE,IAAIN,EAAS,WAAW,OAAO,CAACM,KAAY,CAACmC,GAAe;GACxD,IAAIjD,EAAO,SAAS;IAChB,IAAIkD;IACJ,IAAI;KAGA,AAFA,MAAMlD,EAAO,QAAQgD,CAAI,GACzB,IAAWH,EAAY/B,CAAQ,GAC/B,IAAW,MAAMwB,EAAKX,GAAMS,GAAML,GAAWpC,GAAQmB,CAAQ;IACjE,SAASlB,GAAO;KAGZ,MAFIA,aAAiBgD,IAA8BhD,KACnD,MAAM8C,EAAmBlC,GAAUuB,GAAWiB,CAAI,GAC5C,MAAMzC,EAAWC,GAAUuB,CAAS;IAC9C;IACA,AAAIvB,EAAS,WAAW,OACpB,MAAMkC,EAAmBlC,GAAUuB,GAAWmB,CAAQ;GAE9D,OACI,MAAMR,EAAmBlC,GAAUuB,GAAWiB,CAAI;EAE1D;EAEA,IAAI,CAACxC,EAAS,IACV,MAAM,MAAMD,EAAWC,GAAUuB,CAAS;EAG9C,OAAOoB,EAAO3C,CAAQ;CAC1B;CAEA,eAAe4C,EACX,GACA,GACA,GACU;EACV,IAAM,EAAE,OAAOC,GAAY,GAAGjC,MAASC,GACjCiC,IAAevD,EAAasD,MAAe,KAAA,IAAyBrD,EAAO,QAApBqD,CAAyB;EACtF,IAAI,CAACC,GAAc,OAAOR,EAAWnB,GAAMP,GAAM+B,CAAM;EAEvD,IAAMxD,KAAUyB,EAAK,UAAU,MAAA,CAAO,YAAY;EAClD,OAAO5B,QAAuBsD,EAAWnB,GAAMP,GAAM+B,CAAM,GAAG;GAC1D,GAAGG;GACH,aACIA,EAAa,iBAAiB,MAAmB5D,EAAmBE,GAAOD,CAAM;EACzF,CAAC;CACL;CAEA,eAAe6D,EAAW,GAAc,IAA0B,CAAC,GAAe;EAC9E,OAAOJ,EAAOzB,GAAMN,GAASoC,CAAmB;CACpD;CAEA,eAAeC,EACX,GACA,GACA,IAAmC,QACnC,GACU;EACV,OAAOF,EAAW7B,GAAM;GAAE,GAAGN;GAAS;GAAQ,MAAMsC;EAAS,CAAC;CAClE;CAEA,OAAO;EACH;EACA,MAAS,GAAc,MACnBH,EAAW7B,GAAM;GAAE,GAAGN;GAAS,QAAQ;EAAM,CAAC;EAClD,OAAU,GAAc,MACpBmC,EAAW7B,GAAM;GAAE,GAAGN;GAAS,QAAQ;EAAO,CAAC;EACnD,MAAS,GAAc,MACnBmC,EAAW7B,GAAM;GAAE,GAAGN;GAAS,QAAQ;EAAM,CAAC;EAClD,QAAW,GAAc,MACrBmC,EAAW7B,GAAM;GAAE,GAAGN;GAAS,QAAQ;EAAQ,CAAC;EACpD,SAAY,GAAc,MACtBmC,EAAW7B,GAAM;GAAE,GAAGN;GAAS,QAAQ;EAAS,CAAC;EACrD,OAAO,GAAc,MACjB+B,EAAUzB,GAAM,EAAE,GAAGN,EAAQ,IAAI,MAAab,EAAS,KAAK,CAAC;EACjE,cAAc,GAAc,MACxB4C,EAAiBzB,GAAM,EAAE,GAAGN,EAAQ,IAAI,MAAab,EAAS,YAAY,CAAC;EAC/E;CACJ;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"build-url.cjs","names":[],"sources":["../../src/http/build-url.ts"],"sourcesContent":["/**\n * Matches a path that already carries its own scheme (`https:`, `blob:`), which\n * makes it an absolute URL rather than something to resolve against the base.\n */\nconst ABSOLUTE_URL = /^[a-z][a-z\\d+\\-.]*:/i;\n\n/** Split a path into its non-empty segments, dropping surrounding slashes. */\nfunction segments(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n}\n\n/**\n * Whether `path` already starts with every segment of `prefix`.\n *\n * Compared segment by segment, so a `/api` prefix is not considered present in\n * `/api-keys` — a plain `startsWith` would swallow the resource.\n *\n * @param path - Segments of the request path.\n * @param prefix - Segments of the base path.\n * @returns Whether the prefix is already applied.\n */\nfunction startsWithSegments(path: string[], prefix: string[]): boolean {\n if (prefix.length === 0 || prefix.length > path.length) return false;\n return prefix.every((segment, index) => path[index] === segment);\n}\n\n/**\n * Resolve the origin a relative `baseURL` hangs off.\n *\n * A base such as `\"/api\"` is the shape you get behind a dev-server proxy or a\n * reverse proxy that serves app and API from one host. It only means something\n * in a browsing context, so this throws with the config to fix rather than\n * letting `new URL` report `Invalid base URL` from three frames deeper.\n *\n * @param baseURL - The base as the caller wrote it.\n * @returns The origin to resolve against.\n * @throws When there is no `location` to borrow an origin from.\n */\nfunction currentOrigin(baseURL: string): string {\n const origin = globalThis.location?.origin;\n if (!origin) {\n throw new TypeError(\n `createApiClient: baseURL \"${baseURL}\" is relative and there is no location to resolve it against. Pass an absolute URL (https://api.example.com) outside the browser.`,\n );\n }\n return origin;\n}\n\n/** Options accepted by {@link buildApiUrl}. */\nexport interface BuildApiUrlOptions {\n /**\n * Path segment every request is nested under, such as `\"/api\"`. Joined\n * after the path the `baseURL` already carries.\n */\n prefix?: string;\n /** Query params to append. `undefined` and `null` values are skipped. */\n params?: Record<string, string | number | boolean | undefined | null>;\n}\n\n/**\n * Join a base URL, an optional prefix and a request path into an absolute URL.\n *\n * `new URL(path, base)` on its own is wrong for an API client. It follows the\n * URL spec, where a path starting with `/` is absolute against the *origin* and\n * therefore discards whatever path the base carried: a client on\n * `https://api.example.com/api` asked for `/auth/login` reaches\n * `https://api.example.com/auth/login`, and every request 404s with nothing in\n * the config that looks wrong. This function resolves the path against the base\n * *path* instead, so the leading slash is a matter of taste rather than a\n * silent 404, and `baseURL` + `prefix` are interchangeable ways to say the same\n * thing.\n *\n * The prefix is applied at most once: a path that already opens with it — say\n * `\"/api/auth/login\"` under a `\"/api\"` prefix — is left alone, so a codebase\n * migrating to `prefix` can move its call sites one at a time. The check is per\n * segment, so `/api-keys` is not mistaken for an already-prefixed path.\n *\n * A path that is itself an absolute URL wins over all of this, which is how a\n * client reaches a second host (a signed upload endpoint, a CDN) without a\n * second client.\n *\n * @example\n * buildApiUrl(\"https://api.example.com\", \"/auth/login\", { prefix: \"/api\" });\n * // \"https://api.example.com/api/auth/login\"\n *\n * buildApiUrl(\"https://api.example.com/api\", \"auth/login\");\n * // \"https://api.example.com/api/auth/login\"\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path, or an absolute URL to use as-is.\n * @param options - Optional prefix and query params.\n * @returns The absolute URL to fetch.\n * @throws When `baseURL` is relative and there is no `location` to resolve it.\n */\nexport function buildApiUrl(\n baseURL: string,\n path: string,\n options: BuildApiUrlOptions = {},\n): string {\n const { prefix, params } = options;\n const url = ABSOLUTE_URL.test(path) ? new URL(path) : new URL(resolve(baseURL, path, prefix));\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n}\n\n/**\n * Build the absolute URL string for a path that is not already absolute.\n *\n * Kept separate from {@link buildApiUrl} so the query-param loop is not nested\n * inside the joining rules.\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path.\n * @param prefix - Optional segment every request is nested under.\n * @returns The joined absolute URL.\n */\nfunction resolve(baseURL: string, path: string, prefix?: string): string {\n const base = ABSOLUTE_URL.test(baseURL)\n ? new URL(baseURL)\n : new URL(baseURL, currentOrigin(baseURL));\n\n const queryStart = path.indexOf(\"?\");\n const rawPath = queryStart === -1 ? path : path.slice(0, queryStart);\n const query = queryStart === -1 ? \"\" : path.slice(queryStart);\n\n const basePath = [...segments(base.pathname), ...segments(prefix ?? \"\")];\n const requested = segments(rawPath);\n const joined = startsWithSegments(requested, basePath)\n ? requested\n : [...basePath, ...requested];\n\n const trailing = rawPath.endsWith(\"/\") ? \"/\" : \"\";\n const pathname = joined.length > 0 ? `/${joined.join(\"/\")}${trailing}` : \"/\";\n return `${base.origin}${pathname}${query}`;\n}\n"],"mappings":"AAIA,IAAM,EAAe,uBAGrB,SAAS,EAAS,EAAwB,CACtC,OAAO,EAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CACzC,CAYA,SAAS,EAAmB,EAAgB,EAA2B,CAEnE,OADI,EAAO,SAAW,GAAK,EAAO,OAAS,EAAK,OAAe,GACxD,EAAO,OAAO,EAAS,IAAU,EAAK,KAAW,CAAO,CACnE,CAcA,SAAS,EAAc,EAAyB,CAC5C,IAAM,EAAS,WAAW,UAAU,OACpC,GAAI,CAAC,EACD,MAAU,UACN,6BAA6B,EAAQ,kIACzC,EAEJ,OAAO,CACX,CAgDA,SAAgB,EACZ,EACA,EACA,EAA8B,CAAC,EACzB,CACN,GAAM,CAAE,SAAQ,UAAW,EACrB,EAAM,EAAa,KAAK,CAAI,EAAI,IAAI,IAAI,CAAI,EAAI,IAAI,IAAI,EAAQ,EAAS,EAAM,CAAM,CAAC,EAE5F,GAAI,EACK,IAAA,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAM,EACxC,GAAiC,MACjC,EAAI,aAAa,IAAI,EAAK,OAAO,CAAK,CAAC,EAInD,OAAO,EAAI,SAAS,CACxB,CAaA,SAAS,EAAQ,EAAiB,EAAc,EAAyB,CACrE,IAAM,EAAO,EAAa,KAAK,CAAO,EAChC,IAAI,IAAI,CAAO,EACf,IAAI,IAAI,EAAS,EAAc,CAAO,CAAC,EAEvC,EAAa,EAAK,QAAQ,GAAG,EAC7B,EAAU,IAAe,GAAK,EAAO,EAAK,MAAM,EAAG,CAAU,EAC7D,EAAQ,IAAe,GAAK,GAAK,EAAK,MAAM,CAAU,EAEtD,EAAW,CAAC,GAAG,EAAS,EAAK,QAAQ,EAAG,GAAG,EAAS,GAAU,EAAE,CAAC,EACjE,EAAY,EAAS,CAAO,EAC5B,EAAS,EAAmB,EAAW,CAAQ,EAC/C,EACA,CAAC,GAAG,EAAU,GAAG,CAAS,EAE1B,EAAW,EAAQ,SAAS,GAAG,EAAI,IAAM,GACzC,EAAW,EAAO,OAAS,EAAI,IAAI,EAAO,KAAK,GAAG,IAAI,IAAa,IACzE,MAAO,GAAG,EAAK,SAAS,IAAW,GACvC"}
1
+ {"version":3,"file":"build-url.cjs","names":["ABSOLUTE_URL","segments","path","startsWithSegments","prefix","index","segment","currentOrigin","origin","baseURL","buildApiUrl","options","url","resolve","params","key","value","base","queryStart","rawPath","query","basePath","requested","joined","trailing","pathname"],"sources":["../../src/http/build-url.ts"],"sourcesContent":["/**\n * Matches a path that already carries its own scheme (`https:`, `blob:`), which\n * makes it an absolute URL rather than something to resolve against the base.\n */\nconst ABSOLUTE_URL = /^[a-z][a-z\\d+\\-.]*:/i;\n\n/** Split a path into its non-empty segments, dropping surrounding slashes. */\nfunction segments(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n}\n\n/**\n * Whether `path` already starts with every segment of `prefix`.\n *\n * Compared segment by segment, so a `/api` prefix is not considered present in\n * `/api-keys` — a plain `startsWith` would swallow the resource.\n *\n * @param path - Segments of the request path.\n * @param prefix - Segments of the base path.\n * @returns Whether the prefix is already applied.\n */\nfunction startsWithSegments(path: string[], prefix: string[]): boolean {\n if (prefix.length === 0 || prefix.length > path.length) return false;\n return prefix.every((segment, index) => path[index] === segment);\n}\n\n/**\n * Resolve the origin a relative `baseURL` hangs off.\n *\n * A base such as `\"/api\"` is the shape you get behind a dev-server proxy or a\n * reverse proxy that serves app and API from one host. It only means something\n * in a browsing context, so this throws with the config to fix rather than\n * letting `new URL` report `Invalid base URL` from three frames deeper.\n *\n * @param baseURL - The base as the caller wrote it.\n * @returns The origin to resolve against.\n * @throws When there is no `location` to borrow an origin from.\n */\nfunction currentOrigin(baseURL: string): string {\n const origin = globalThis.location?.origin;\n if (!origin) {\n throw new TypeError(\n `createApiClient: baseURL \"${baseURL}\" is relative and there is no location to resolve it against. Pass an absolute URL (https://api.example.com) outside the browser.`,\n );\n }\n return origin;\n}\n\n/** Options accepted by {@link buildApiUrl}. */\nexport interface BuildApiUrlOptions {\n /**\n * Path segment every request is nested under, such as `\"/api\"`. Joined\n * after the path the `baseURL` already carries.\n */\n prefix?: string;\n /** Query params to append. `undefined` and `null` values are skipped. */\n params?: Record<string, string | number | boolean | undefined | null>;\n}\n\n/**\n * Join a base URL, an optional prefix and a request path into an absolute URL.\n *\n * `new URL(path, base)` on its own is wrong for an API client. It follows the\n * URL spec, where a path starting with `/` is absolute against the *origin* and\n * therefore discards whatever path the base carried: a client on\n * `https://api.example.com/api` asked for `/auth/login` reaches\n * `https://api.example.com/auth/login`, and every request 404s with nothing in\n * the config that looks wrong. This function resolves the path against the base\n * *path* instead, so the leading slash is a matter of taste rather than a\n * silent 404, and `baseURL` + `prefix` are interchangeable ways to say the same\n * thing.\n *\n * The prefix is applied at most once: a path that already opens with it — say\n * `\"/api/auth/login\"` under a `\"/api\"` prefix — is left alone, so a codebase\n * migrating to `prefix` can move its call sites one at a time. The check is per\n * segment, so `/api-keys` is not mistaken for an already-prefixed path.\n *\n * A path that is itself an absolute URL wins over all of this, which is how a\n * client reaches a second host (a signed upload endpoint, a CDN) without a\n * second client.\n *\n * @example\n * buildApiUrl(\"https://api.example.com\", \"/auth/login\", { prefix: \"/api\" });\n * // \"https://api.example.com/api/auth/login\"\n *\n * buildApiUrl(\"https://api.example.com/api\", \"auth/login\");\n * // \"https://api.example.com/api/auth/login\"\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path, or an absolute URL to use as-is.\n * @param options - Optional prefix and query params.\n * @returns The absolute URL to fetch.\n * @throws When `baseURL` is relative and there is no `location` to resolve it.\n */\nexport function buildApiUrl(\n baseURL: string,\n path: string,\n options: BuildApiUrlOptions = {},\n): string {\n const { prefix, params } = options;\n const url = ABSOLUTE_URL.test(path) ? new URL(path) : new URL(resolve(baseURL, path, prefix));\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n}\n\n/**\n * Build the absolute URL string for a path that is not already absolute.\n *\n * Kept separate from {@link buildApiUrl} so the query-param loop is not nested\n * inside the joining rules.\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path.\n * @param prefix - Optional segment every request is nested under.\n * @returns The joined absolute URL.\n */\nfunction resolve(baseURL: string, path: string, prefix?: string): string {\n const base = ABSOLUTE_URL.test(baseURL)\n ? new URL(baseURL)\n : new URL(baseURL, currentOrigin(baseURL));\n\n const queryStart = path.indexOf(\"?\");\n const rawPath = queryStart === -1 ? path : path.slice(0, queryStart);\n const query = queryStart === -1 ? \"\" : path.slice(queryStart);\n\n const basePath = [...segments(base.pathname), ...segments(prefix ?? \"\")];\n const requested = segments(rawPath);\n const joined = startsWithSegments(requested, basePath)\n ? requested\n : [...basePath, ...requested];\n\n const trailing = rawPath.endsWith(\"/\") ? \"/\" : \"\";\n const pathname = joined.length > 0 ? `/${joined.join(\"/\")}${trailing}` : \"/\";\n return `${base.origin}${pathname}${query}`;\n}\n"],"mappings":"AAIA,IAAMA,EAAe,uBAGrB,SAASC,EAAS,EAAwB,CACtC,OAAOC,EAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CACzC,CAYA,SAASC,EAAmB,EAAgB,EAA2B,CAEnE,OADIC,EAAO,SAAW,GAAKA,EAAO,OAASF,EAAK,OAAe,GACxDE,EAAO,OAAO,EAAS,IAAUF,EAAKG,KAAWC,CAAO,CACnE,CAcA,SAASC,EAAc,EAAyB,CAC5C,IAAMC,EAAS,WAAW,UAAU,OACpC,GAAI,CAACA,EACD,MAAU,UACN,6BAA6BC,EAAQ,kIACzC,EAEJ,OAAOD,CACX,CAgDA,SAAgBE,EACZ,EACA,EACA,EAA8B,CAAC,EACzB,CACN,GAAM,CAAE,SAAQ,UAAWC,EACrBC,EAAMZ,EAAa,KAAKE,CAAI,EAAI,IAAI,IAAIA,CAAI,EAAI,IAAI,IAAIW,EAAQJ,EAASP,EAAME,CAAM,CAAC,EAE5F,GAAIU,EACK,IAAA,GAAM,CAACC,EAAKC,KAAU,OAAO,QAAQF,CAAM,EACxCE,GAAiC,MACjCJ,EAAI,aAAa,IAAIG,EAAK,OAAOC,CAAK,CAAC,EAInD,OAAOJ,EAAI,SAAS,CACxB,CAaA,SAASC,EAAQ,EAAiB,EAAc,EAAyB,CACrE,IAAMI,EAAOjB,EAAa,KAAKS,CAAO,EAChC,IAAI,IAAIA,CAAO,EACf,IAAI,IAAIA,EAASF,EAAcE,CAAO,CAAC,EAEvCS,EAAahB,EAAK,QAAQ,GAAG,EAC7BiB,EAAUD,IAAe,GAAKhB,EAAOA,EAAK,MAAM,EAAGgB,CAAU,EAC7DE,EAAQF,IAAe,GAAK,GAAKhB,EAAK,MAAMgB,CAAU,EAEtDG,EAAW,CAAC,GAAGpB,EAASgB,EAAK,QAAQ,EAAG,GAAGhB,EAASG,GAAU,EAAE,CAAC,EACjEkB,EAAYrB,EAASkB,CAAO,EAC5BI,EAASpB,EAAmBmB,EAAWD,CAAQ,EAC/CC,EACA,CAAC,GAAGD,EAAU,GAAGC,CAAS,EAE1BE,EAAWL,EAAQ,SAAS,GAAG,EAAI,IAAM,GACzCM,EAAWF,EAAO,OAAS,EAAI,IAAIA,EAAO,KAAK,GAAG,IAAIC,IAAa,IACzE,MAAO,GAAGP,EAAK,SAASQ,IAAWL,GACvC,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"build-url.js","names":[],"sources":["../../src/http/build-url.ts"],"sourcesContent":["/**\n * Matches a path that already carries its own scheme (`https:`, `blob:`), which\n * makes it an absolute URL rather than something to resolve against the base.\n */\nconst ABSOLUTE_URL = /^[a-z][a-z\\d+\\-.]*:/i;\n\n/** Split a path into its non-empty segments, dropping surrounding slashes. */\nfunction segments(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n}\n\n/**\n * Whether `path` already starts with every segment of `prefix`.\n *\n * Compared segment by segment, so a `/api` prefix is not considered present in\n * `/api-keys` — a plain `startsWith` would swallow the resource.\n *\n * @param path - Segments of the request path.\n * @param prefix - Segments of the base path.\n * @returns Whether the prefix is already applied.\n */\nfunction startsWithSegments(path: string[], prefix: string[]): boolean {\n if (prefix.length === 0 || prefix.length > path.length) return false;\n return prefix.every((segment, index) => path[index] === segment);\n}\n\n/**\n * Resolve the origin a relative `baseURL` hangs off.\n *\n * A base such as `\"/api\"` is the shape you get behind a dev-server proxy or a\n * reverse proxy that serves app and API from one host. It only means something\n * in a browsing context, so this throws with the config to fix rather than\n * letting `new URL` report `Invalid base URL` from three frames deeper.\n *\n * @param baseURL - The base as the caller wrote it.\n * @returns The origin to resolve against.\n * @throws When there is no `location` to borrow an origin from.\n */\nfunction currentOrigin(baseURL: string): string {\n const origin = globalThis.location?.origin;\n if (!origin) {\n throw new TypeError(\n `createApiClient: baseURL \"${baseURL}\" is relative and there is no location to resolve it against. Pass an absolute URL (https://api.example.com) outside the browser.`,\n );\n }\n return origin;\n}\n\n/** Options accepted by {@link buildApiUrl}. */\nexport interface BuildApiUrlOptions {\n /**\n * Path segment every request is nested under, such as `\"/api\"`. Joined\n * after the path the `baseURL` already carries.\n */\n prefix?: string;\n /** Query params to append. `undefined` and `null` values are skipped. */\n params?: Record<string, string | number | boolean | undefined | null>;\n}\n\n/**\n * Join a base URL, an optional prefix and a request path into an absolute URL.\n *\n * `new URL(path, base)` on its own is wrong for an API client. It follows the\n * URL spec, where a path starting with `/` is absolute against the *origin* and\n * therefore discards whatever path the base carried: a client on\n * `https://api.example.com/api` asked for `/auth/login` reaches\n * `https://api.example.com/auth/login`, and every request 404s with nothing in\n * the config that looks wrong. This function resolves the path against the base\n * *path* instead, so the leading slash is a matter of taste rather than a\n * silent 404, and `baseURL` + `prefix` are interchangeable ways to say the same\n * thing.\n *\n * The prefix is applied at most once: a path that already opens with it — say\n * `\"/api/auth/login\"` under a `\"/api\"` prefix — is left alone, so a codebase\n * migrating to `prefix` can move its call sites one at a time. The check is per\n * segment, so `/api-keys` is not mistaken for an already-prefixed path.\n *\n * A path that is itself an absolute URL wins over all of this, which is how a\n * client reaches a second host (a signed upload endpoint, a CDN) without a\n * second client.\n *\n * @example\n * buildApiUrl(\"https://api.example.com\", \"/auth/login\", { prefix: \"/api\" });\n * // \"https://api.example.com/api/auth/login\"\n *\n * buildApiUrl(\"https://api.example.com/api\", \"auth/login\");\n * // \"https://api.example.com/api/auth/login\"\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path, or an absolute URL to use as-is.\n * @param options - Optional prefix and query params.\n * @returns The absolute URL to fetch.\n * @throws When `baseURL` is relative and there is no `location` to resolve it.\n */\nexport function buildApiUrl(\n baseURL: string,\n path: string,\n options: BuildApiUrlOptions = {},\n): string {\n const { prefix, params } = options;\n const url = ABSOLUTE_URL.test(path) ? new URL(path) : new URL(resolve(baseURL, path, prefix));\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n}\n\n/**\n * Build the absolute URL string for a path that is not already absolute.\n *\n * Kept separate from {@link buildApiUrl} so the query-param loop is not nested\n * inside the joining rules.\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path.\n * @param prefix - Optional segment every request is nested under.\n * @returns The joined absolute URL.\n */\nfunction resolve(baseURL: string, path: string, prefix?: string): string {\n const base = ABSOLUTE_URL.test(baseURL)\n ? new URL(baseURL)\n : new URL(baseURL, currentOrigin(baseURL));\n\n const queryStart = path.indexOf(\"?\");\n const rawPath = queryStart === -1 ? path : path.slice(0, queryStart);\n const query = queryStart === -1 ? \"\" : path.slice(queryStart);\n\n const basePath = [...segments(base.pathname), ...segments(prefix ?? \"\")];\n const requested = segments(rawPath);\n const joined = startsWithSegments(requested, basePath)\n ? requested\n : [...basePath, ...requested];\n\n const trailing = rawPath.endsWith(\"/\") ? \"/\" : \"\";\n const pathname = joined.length > 0 ? `/${joined.join(\"/\")}${trailing}` : \"/\";\n return `${base.origin}${pathname}${query}`;\n}\n"],"mappings":";AAIA,IAAM,IAAe;AAGrB,SAAS,EAAS,GAAwB;CACtC,OAAO,EAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;AACzC;AAYA,SAAS,EAAmB,GAAgB,GAA2B;CAEnE,OADI,EAAO,WAAW,KAAK,EAAO,SAAS,EAAK,SAAe,KACxD,EAAO,OAAO,GAAS,MAAU,EAAK,OAAW,CAAO;AACnE;AAcA,SAAS,EAAc,GAAyB;CAC5C,IAAM,IAAS,WAAW,UAAU;CACpC,IAAI,CAAC,GACD,MAAU,UACN,6BAA6B,EAAQ,kIACzC;CAEJ,OAAO;AACX;AAgDA,SAAgB,EACZ,GACA,GACA,IAA8B,CAAC,GACzB;CACN,IAAM,EAAE,WAAQ,cAAW,GACrB,IAAM,EAAa,KAAK,CAAI,IAAI,IAAI,IAAI,CAAI,IAAI,IAAI,IAAI,EAAQ,GAAS,GAAM,CAAM,CAAC;CAE5F,IAAI,GACK,KAAA,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAM,GAC5C,AAAI,KAAiC,QACjC,EAAI,aAAa,IAAI,GAAK,OAAO,CAAK,CAAC;CAInD,OAAO,EAAI,SAAS;AACxB;AAaA,SAAS,EAAQ,GAAiB,GAAc,GAAyB;CACrE,IAAM,IAAO,EAAa,KAAK,CAAO,IAChC,IAAI,IAAI,CAAO,IACf,IAAI,IAAI,GAAS,EAAc,CAAO,CAAC,GAEvC,IAAa,EAAK,QAAQ,GAAG,GAC7B,IAAU,MAAe,KAAK,IAAO,EAAK,MAAM,GAAG,CAAU,GAC7D,IAAQ,MAAe,KAAK,KAAK,EAAK,MAAM,CAAU,GAEtD,IAAW,CAAC,GAAG,EAAS,EAAK,QAAQ,GAAG,GAAG,EAAS,KAAU,EAAE,CAAC,GACjE,IAAY,EAAS,CAAO,GAC5B,IAAS,EAAmB,GAAW,CAAQ,IAC/C,IACA,CAAC,GAAG,GAAU,GAAG,CAAS,GAE1B,IAAW,EAAQ,SAAS,GAAG,IAAI,MAAM,IACzC,IAAW,EAAO,SAAS,IAAI,IAAI,EAAO,KAAK,GAAG,IAAI,MAAa;CACzE,OAAO,GAAG,EAAK,SAAS,IAAW;AACvC"}
1
+ {"version":3,"file":"build-url.js","names":["ABSOLUTE_URL","segments","path","startsWithSegments","prefix","index","segment","currentOrigin","origin","baseURL","buildApiUrl","options","url","resolve","params","key","value","base","queryStart","rawPath","query","basePath","requested","joined","trailing","pathname"],"sources":["../../src/http/build-url.ts"],"sourcesContent":["/**\n * Matches a path that already carries its own scheme (`https:`, `blob:`), which\n * makes it an absolute URL rather than something to resolve against the base.\n */\nconst ABSOLUTE_URL = /^[a-z][a-z\\d+\\-.]*:/i;\n\n/** Split a path into its non-empty segments, dropping surrounding slashes. */\nfunction segments(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n}\n\n/**\n * Whether `path` already starts with every segment of `prefix`.\n *\n * Compared segment by segment, so a `/api` prefix is not considered present in\n * `/api-keys` — a plain `startsWith` would swallow the resource.\n *\n * @param path - Segments of the request path.\n * @param prefix - Segments of the base path.\n * @returns Whether the prefix is already applied.\n */\nfunction startsWithSegments(path: string[], prefix: string[]): boolean {\n if (prefix.length === 0 || prefix.length > path.length) return false;\n return prefix.every((segment, index) => path[index] === segment);\n}\n\n/**\n * Resolve the origin a relative `baseURL` hangs off.\n *\n * A base such as `\"/api\"` is the shape you get behind a dev-server proxy or a\n * reverse proxy that serves app and API from one host. It only means something\n * in a browsing context, so this throws with the config to fix rather than\n * letting `new URL` report `Invalid base URL` from three frames deeper.\n *\n * @param baseURL - The base as the caller wrote it.\n * @returns The origin to resolve against.\n * @throws When there is no `location` to borrow an origin from.\n */\nfunction currentOrigin(baseURL: string): string {\n const origin = globalThis.location?.origin;\n if (!origin) {\n throw new TypeError(\n `createApiClient: baseURL \"${baseURL}\" is relative and there is no location to resolve it against. Pass an absolute URL (https://api.example.com) outside the browser.`,\n );\n }\n return origin;\n}\n\n/** Options accepted by {@link buildApiUrl}. */\nexport interface BuildApiUrlOptions {\n /**\n * Path segment every request is nested under, such as `\"/api\"`. Joined\n * after the path the `baseURL` already carries.\n */\n prefix?: string;\n /** Query params to append. `undefined` and `null` values are skipped. */\n params?: Record<string, string | number | boolean | undefined | null>;\n}\n\n/**\n * Join a base URL, an optional prefix and a request path into an absolute URL.\n *\n * `new URL(path, base)` on its own is wrong for an API client. It follows the\n * URL spec, where a path starting with `/` is absolute against the *origin* and\n * therefore discards whatever path the base carried: a client on\n * `https://api.example.com/api` asked for `/auth/login` reaches\n * `https://api.example.com/auth/login`, and every request 404s with nothing in\n * the config that looks wrong. This function resolves the path against the base\n * *path* instead, so the leading slash is a matter of taste rather than a\n * silent 404, and `baseURL` + `prefix` are interchangeable ways to say the same\n * thing.\n *\n * The prefix is applied at most once: a path that already opens with it — say\n * `\"/api/auth/login\"` under a `\"/api\"` prefix — is left alone, so a codebase\n * migrating to `prefix` can move its call sites one at a time. The check is per\n * segment, so `/api-keys` is not mistaken for an already-prefixed path.\n *\n * A path that is itself an absolute URL wins over all of this, which is how a\n * client reaches a second host (a signed upload endpoint, a CDN) without a\n * second client.\n *\n * @example\n * buildApiUrl(\"https://api.example.com\", \"/auth/login\", { prefix: \"/api\" });\n * // \"https://api.example.com/api/auth/login\"\n *\n * buildApiUrl(\"https://api.example.com/api\", \"auth/login\");\n * // \"https://api.example.com/api/auth/login\"\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path, or an absolute URL to use as-is.\n * @param options - Optional prefix and query params.\n * @returns The absolute URL to fetch.\n * @throws When `baseURL` is relative and there is no `location` to resolve it.\n */\nexport function buildApiUrl(\n baseURL: string,\n path: string,\n options: BuildApiUrlOptions = {},\n): string {\n const { prefix, params } = options;\n const url = ABSOLUTE_URL.test(path) ? new URL(path) : new URL(resolve(baseURL, path, prefix));\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n}\n\n/**\n * Build the absolute URL string for a path that is not already absolute.\n *\n * Kept separate from {@link buildApiUrl} so the query-param loop is not nested\n * inside the joining rules.\n *\n * @param baseURL - Absolute base URL, or a path relative to the current origin.\n * @param path - The request path.\n * @param prefix - Optional segment every request is nested under.\n * @returns The joined absolute URL.\n */\nfunction resolve(baseURL: string, path: string, prefix?: string): string {\n const base = ABSOLUTE_URL.test(baseURL)\n ? new URL(baseURL)\n : new URL(baseURL, currentOrigin(baseURL));\n\n const queryStart = path.indexOf(\"?\");\n const rawPath = queryStart === -1 ? path : path.slice(0, queryStart);\n const query = queryStart === -1 ? \"\" : path.slice(queryStart);\n\n const basePath = [...segments(base.pathname), ...segments(prefix ?? \"\")];\n const requested = segments(rawPath);\n const joined = startsWithSegments(requested, basePath)\n ? requested\n : [...basePath, ...requested];\n\n const trailing = rawPath.endsWith(\"/\") ? \"/\" : \"\";\n const pathname = joined.length > 0 ? `/${joined.join(\"/\")}${trailing}` : \"/\";\n return `${base.origin}${pathname}${query}`;\n}\n"],"mappings":";AAIA,IAAMA,IAAe;AAGrB,SAASC,EAAS,GAAwB;CACtC,OAAOC,EAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;AACzC;AAYA,SAASC,EAAmB,GAAgB,GAA2B;CAEnE,OADIC,EAAO,WAAW,KAAKA,EAAO,SAASF,EAAK,SAAe,KACxDE,EAAO,OAAO,GAAS,MAAUF,EAAKG,OAAWC,CAAO;AACnE;AAcA,SAASC,EAAc,GAAyB;CAC5C,IAAMC,IAAS,WAAW,UAAU;CACpC,IAAI,CAACA,GACD,MAAU,UACN,6BAA6BC,EAAQ,kIACzC;CAEJ,OAAOD;AACX;AAgDA,SAAgBE,EACZ,GACA,GACA,IAA8B,CAAC,GACzB;CACN,IAAM,EAAE,WAAQ,cAAWC,GACrBC,IAAMZ,EAAa,KAAKE,CAAI,IAAI,IAAI,IAAIA,CAAI,IAAI,IAAI,IAAIW,EAAQJ,GAASP,GAAME,CAAM,CAAC;CAE5F,IAAIU,GACK,KAAA,IAAM,CAACC,GAAKC,MAAU,OAAO,QAAQF,CAAM,GAC5C,AAAIE,KAAiC,QACjCJ,EAAI,aAAa,IAAIG,GAAK,OAAOC,CAAK,CAAC;CAInD,OAAOJ,EAAI,SAAS;AACxB;AAaA,SAASC,EAAQ,GAAiB,GAAc,GAAyB;CACrE,IAAMI,IAAOjB,EAAa,KAAKS,CAAO,IAChC,IAAI,IAAIA,CAAO,IACf,IAAI,IAAIA,GAASF,EAAcE,CAAO,CAAC,GAEvCS,IAAahB,EAAK,QAAQ,GAAG,GAC7BiB,IAAUD,MAAe,KAAKhB,IAAOA,EAAK,MAAM,GAAGgB,CAAU,GAC7DE,IAAQF,MAAe,KAAK,KAAKhB,EAAK,MAAMgB,CAAU,GAEtDG,IAAW,CAAC,GAAGpB,EAASgB,EAAK,QAAQ,GAAG,GAAGhB,EAASG,KAAU,EAAE,CAAC,GACjEkB,IAAYrB,EAASkB,CAAO,GAC5BI,IAASpB,EAAmBmB,GAAWD,CAAQ,IAC/CC,IACA,CAAC,GAAGD,GAAU,GAAGC,CAAS,GAE1BE,IAAWL,EAAQ,SAAS,GAAG,IAAI,MAAM,IACzCM,IAAWF,EAAO,SAAS,IAAI,IAAIA,EAAO,KAAK,GAAG,IAAIC,MAAa;CACzE,OAAO,GAAGP,EAAK,SAASQ,IAAWL;AACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"credential-scope.cjs","names":[],"sources":["../../src/http/credential-scope.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Origins already reported by {@link reportSuppressedCredential}, so a chunked\n * upload warns once instead of once per chunk.\n */\nconst reported = new Set<string>();\n\n/**\n * The origin a URL resolves to, or `null` when it has none to compare.\n *\n * Relative values resolve against the document, because that is what they mean\n * everywhere else in the SDK: an `endpoint` of `\"/api/uploads\"` and a `baseURL`\n * of `\"/api\"` are the shape you get behind a dev-server or a reverse proxy, and\n * both name the page's own origin. Comparing a resolved absolute target against\n * an unresolved relative reference is how the first draft of this function\n * withheld the credential from every client configured that way.\n *\n * `null` is reserved for the case with genuinely nothing to compare: a relative\n * URL outside a browsing context, where there is no document to resolve against.\n *\n * @param url - Absolute or relative URL.\n * @returns The origin, or `null` when it cannot be resolved.\n */\nfunction originOf(url: string): string | null {\n try {\n return new URL(url, globalThis.location?.href).origin;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a request to `target` may carry the caller's credential.\n *\n * The SDK writes `Authorization: Bearer` in three places, and until 0.66.0 none\n * of them looked at where the request was going. That is only safe while every\n * target URL is written by the app: a resumable upload takes its URL from the\n * server's `Location` header, and `createApiClient` lets an absolute path\n * override `baseURL` entirely, so a URL arriving over the network could decide\n * which origin received the token — and the file bytes with it.\n *\n * Handing an upload off to object storage on another host is ordinary `tus`\n * deployment, not an attack, which is exactly why the credential must be scoped\n * rather than the request blocked: the upload still goes through, it just goes\n * without the API's bearer token.\n *\n * Both sides are resolved against the document first, so a relative `baseURL`\n * or `endpoint` — the shape behind a dev-server or reverse proxy — compares\n * equal to the absolute URL the request actually goes to. Outside a browsing\n * context a relative target resolves to nothing and is allowed: there is no\n * origin for it to cross.\n *\n * @param target - The URL the request is about to go to.\n * @param reference - The origin the credential belongs to, normally the\n * client's `baseURL` or the upload `endpoint`.\n * @param trustedOrigins - Extra origins the app declared, for the legitimate\n * second host: a CDN, a signed upload endpoint.\n * @returns Whether the credential may be attached.\n *\n * @example\n * isTrustedCredentialTarget(\"https://api.acme.com/me\", \"https://api.acme.com\");\n * // true\n * isTrustedCredentialTarget(\"https://cdn.other/u/1\", \"https://api.acme.com\");\n * // false\n */\nexport function isTrustedCredentialTarget(\n target: string,\n reference: string,\n trustedOrigins: readonly string[] = [],\n): boolean {\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return true;\n if (targetOrigin === originOf(reference)) return true;\n return trustedOrigins.some((origin) => originOf(origin) === targetOrigin);\n}\n\n/**\n * Say once, in a development build, that a credential was withheld.\n *\n * Without it the symptom is a `401` (or, for the CSRF header, a `403`) from a\n * host the developer never typed, and nothing in the app's code mentions the\n * origin that produced it. Keyed by credential and target origin, so a\n * hundred-chunk upload reports one line per header it withheld.\n *\n * Silent in production for the same reason {@link parseResponse} is: the origin\n * an app talks to is not something to print into a user's console or ship to an\n * error tracker.\n *\n * @param target - The URL whose request went out unauthenticated.\n * @param reference - The origin the credential was scoped to.\n * @param header - The header that was withheld. Default `\"Authorization\"`.\n */\nexport function reportSuppressedCredential(\n target: string,\n reference: string,\n header = \"Authorization\",\n): void {\n if (!isDevBuild()) return;\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return;\n const key = `${header} ${targetOrigin}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.warn(\n `[tempest-react-sdk] ${header} was not sent to ${targetOrigin}: the credential is scoped to ${originOf(reference) ?? reference}. Add the origin to trustedOrigins if it should receive the token.`,\n );\n}\n\n/**\n * Forget which origins were already reported.\n *\n * Exported for tests, which assert the once-per-origin behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetSuppressedCredentialReports(): void {\n reported.clear();\n}\n"],"mappings":"yCAMA,IAAM,EAAW,IAAI,IAkBrB,SAAS,EAAS,EAA4B,CAC1C,GAAI,CACA,OAAO,IAAI,IAAI,EAAK,WAAW,UAAU,IAAI,CAAC,CAAC,MACnD,MAAQ,CACJ,OAAO,IACX,CACJ,CAoCA,SAAgB,EACZ,EACA,EACA,EAAoC,CAAC,EAC9B,CACP,IAAM,EAAe,EAAS,CAAM,EAGpC,OAFI,IAAiB,MACjB,IAAiB,EAAS,CAAS,GAChC,EAAe,KAAM,GAAW,EAAS,CAAM,IAAM,CAAY,CAC5E,CAkBA,SAAgB,EACZ,EACA,EACA,EAAS,gBACL,CACJ,GAAI,CAAC,EAAA,WAAW,EAAG,OACnB,IAAM,EAAe,EAAS,CAAM,EACpC,GAAI,IAAiB,KAAM,OAC3B,IAAM,EAAM,GAAG,EAAO,GAAG,IACrB,EAAS,IAAI,CAAG,IACpB,EAAS,IAAI,CAAG,EAChB,QAAQ,KACJ,uBAAuB,EAAO,mBAAmB,EAAa,gCAAgC,EAAS,CAAS,GAAK,EAAU,mEACnI,EACJ"}
1
+ {"version":3,"file":"credential-scope.cjs","names":["isDevBuild","require_dev_mode","reported","originOf","url","isTrustedCredentialTarget","targetOrigin","target","reference","trustedOrigins","origin","reportSuppressedCredential","key","header"],"sources":["../../src/http/credential-scope.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Origins already reported by {@link reportSuppressedCredential}, so a chunked\n * upload warns once instead of once per chunk.\n */\nconst reported = new Set<string>();\n\n/**\n * The origin a URL resolves to, or `null` when it has none to compare.\n *\n * Relative values resolve against the document, because that is what they mean\n * everywhere else in the SDK: an `endpoint` of `\"/api/uploads\"` and a `baseURL`\n * of `\"/api\"` are the shape you get behind a dev-server or a reverse proxy, and\n * both name the page's own origin. Comparing a resolved absolute target against\n * an unresolved relative reference is how the first draft of this function\n * withheld the credential from every client configured that way.\n *\n * `null` is reserved for the case with genuinely nothing to compare: a relative\n * URL outside a browsing context, where there is no document to resolve against.\n *\n * @param url - Absolute or relative URL.\n * @returns The origin, or `null` when it cannot be resolved.\n */\nfunction originOf(url: string): string | null {\n try {\n return new URL(url, globalThis.location?.href).origin;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a request to `target` may carry the caller's credential.\n *\n * The SDK writes `Authorization: Bearer` in three places, and until 0.66.0 none\n * of them looked at where the request was going. That is only safe while every\n * target URL is written by the app: a resumable upload takes its URL from the\n * server's `Location` header, and `createApiClient` lets an absolute path\n * override `baseURL` entirely, so a URL arriving over the network could decide\n * which origin received the token — and the file bytes with it.\n *\n * Handing an upload off to object storage on another host is ordinary `tus`\n * deployment, not an attack, which is exactly why the credential must be scoped\n * rather than the request blocked: the upload still goes through, it just goes\n * without the API's bearer token.\n *\n * Both sides are resolved against the document first, so a relative `baseURL`\n * or `endpoint` — the shape behind a dev-server or reverse proxy — compares\n * equal to the absolute URL the request actually goes to. Outside a browsing\n * context a relative target resolves to nothing and is allowed: there is no\n * origin for it to cross.\n *\n * @param target - The URL the request is about to go to.\n * @param reference - The origin the credential belongs to, normally the\n * client's `baseURL` or the upload `endpoint`.\n * @param trustedOrigins - Extra origins the app declared, for the legitimate\n * second host: a CDN, a signed upload endpoint.\n * @returns Whether the credential may be attached.\n *\n * @example\n * isTrustedCredentialTarget(\"https://api.acme.com/me\", \"https://api.acme.com\");\n * // true\n * isTrustedCredentialTarget(\"https://cdn.other/u/1\", \"https://api.acme.com\");\n * // false\n */\nexport function isTrustedCredentialTarget(\n target: string,\n reference: string,\n trustedOrigins: readonly string[] = [],\n): boolean {\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return true;\n if (targetOrigin === originOf(reference)) return true;\n return trustedOrigins.some((origin) => originOf(origin) === targetOrigin);\n}\n\n/**\n * Say once, in a development build, that a credential was withheld.\n *\n * Without it the symptom is a `401` (or, for the CSRF header, a `403`) from a\n * host the developer never typed, and nothing in the app's code mentions the\n * origin that produced it. Keyed by credential and target origin, so a\n * hundred-chunk upload reports one line per header it withheld.\n *\n * Silent in production for the same reason {@link parseResponse} is: the origin\n * an app talks to is not something to print into a user's console or ship to an\n * error tracker.\n *\n * @param target - The URL whose request went out unauthenticated.\n * @param reference - The origin the credential was scoped to.\n * @param header - The header that was withheld. Default `\"Authorization\"`.\n */\nexport function reportSuppressedCredential(\n target: string,\n reference: string,\n header = \"Authorization\",\n): void {\n if (!isDevBuild()) return;\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return;\n const key = `${header} ${targetOrigin}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.warn(\n `[tempest-react-sdk] ${header} was not sent to ${targetOrigin}: the credential is scoped to ${originOf(reference) ?? reference}. Add the origin to trustedOrigins if it should receive the token.`,\n );\n}\n\n/**\n * Forget which origins were already reported.\n *\n * Exported for tests, which assert the once-per-origin behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetSuppressedCredentialReports(): void {\n reported.clear();\n}\n"],"mappings":"A,yCAMA,IAAME,EAAW,IAAI,IAkBrB,SAASC,EAAS,EAA4B,CAC1C,GAAI,CACA,OAAO,IAAI,IAAIC,EAAK,WAAW,UAAU,IAAI,CAAC,CAAC,MACnD,MAAQ,CACJ,OAAO,IACX,CACJ,CAoCA,SAAgBC,EACZ,EACA,EACA,EAAoC,CAAC,EAC9B,CACP,IAAMC,EAAeH,EAASI,CAAM,EAGpC,OAFID,IAAiB,MACjBA,IAAiBH,EAASK,CAAS,GAChCC,EAAe,KAAM,GAAWN,EAASO,CAAM,IAAMJ,CAAY,CAC5E,CAkBA,SAAgBK,EACZ,EACA,EACA,EAAS,gBACL,CACJ,GAAI,CAACX,EAAAA,WAAW,EAAG,OACnB,IAAMM,EAAeH,EAASI,CAAM,EACpC,GAAID,IAAiB,KAAM,OAC3B,IAAMM,EAAM,GAAGC,EAAO,GAAGP,IACrBJ,EAAS,IAAIU,CAAG,IACpBV,EAAS,IAAIU,CAAG,EAChB,QAAQ,KACJ,uBAAuBC,EAAO,mBAAmBP,EAAa,gCAAgCH,EAASK,CAAS,GAAKA,EAAU,mEACnI,EACJ,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"credential-scope.js","names":[],"sources":["../../src/http/credential-scope.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Origins already reported by {@link reportSuppressedCredential}, so a chunked\n * upload warns once instead of once per chunk.\n */\nconst reported = new Set<string>();\n\n/**\n * The origin a URL resolves to, or `null` when it has none to compare.\n *\n * Relative values resolve against the document, because that is what they mean\n * everywhere else in the SDK: an `endpoint` of `\"/api/uploads\"` and a `baseURL`\n * of `\"/api\"` are the shape you get behind a dev-server or a reverse proxy, and\n * both name the page's own origin. Comparing a resolved absolute target against\n * an unresolved relative reference is how the first draft of this function\n * withheld the credential from every client configured that way.\n *\n * `null` is reserved for the case with genuinely nothing to compare: a relative\n * URL outside a browsing context, where there is no document to resolve against.\n *\n * @param url - Absolute or relative URL.\n * @returns The origin, or `null` when it cannot be resolved.\n */\nfunction originOf(url: string): string | null {\n try {\n return new URL(url, globalThis.location?.href).origin;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a request to `target` may carry the caller's credential.\n *\n * The SDK writes `Authorization: Bearer` in three places, and until 0.66.0 none\n * of them looked at where the request was going. That is only safe while every\n * target URL is written by the app: a resumable upload takes its URL from the\n * server's `Location` header, and `createApiClient` lets an absolute path\n * override `baseURL` entirely, so a URL arriving over the network could decide\n * which origin received the token — and the file bytes with it.\n *\n * Handing an upload off to object storage on another host is ordinary `tus`\n * deployment, not an attack, which is exactly why the credential must be scoped\n * rather than the request blocked: the upload still goes through, it just goes\n * without the API's bearer token.\n *\n * Both sides are resolved against the document first, so a relative `baseURL`\n * or `endpoint` — the shape behind a dev-server or reverse proxy — compares\n * equal to the absolute URL the request actually goes to. Outside a browsing\n * context a relative target resolves to nothing and is allowed: there is no\n * origin for it to cross.\n *\n * @param target - The URL the request is about to go to.\n * @param reference - The origin the credential belongs to, normally the\n * client's `baseURL` or the upload `endpoint`.\n * @param trustedOrigins - Extra origins the app declared, for the legitimate\n * second host: a CDN, a signed upload endpoint.\n * @returns Whether the credential may be attached.\n *\n * @example\n * isTrustedCredentialTarget(\"https://api.acme.com/me\", \"https://api.acme.com\");\n * // true\n * isTrustedCredentialTarget(\"https://cdn.other/u/1\", \"https://api.acme.com\");\n * // false\n */\nexport function isTrustedCredentialTarget(\n target: string,\n reference: string,\n trustedOrigins: readonly string[] = [],\n): boolean {\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return true;\n if (targetOrigin === originOf(reference)) return true;\n return trustedOrigins.some((origin) => originOf(origin) === targetOrigin);\n}\n\n/**\n * Say once, in a development build, that a credential was withheld.\n *\n * Without it the symptom is a `401` (or, for the CSRF header, a `403`) from a\n * host the developer never typed, and nothing in the app's code mentions the\n * origin that produced it. Keyed by credential and target origin, so a\n * hundred-chunk upload reports one line per header it withheld.\n *\n * Silent in production for the same reason {@link parseResponse} is: the origin\n * an app talks to is not something to print into a user's console or ship to an\n * error tracker.\n *\n * @param target - The URL whose request went out unauthenticated.\n * @param reference - The origin the credential was scoped to.\n * @param header - The header that was withheld. Default `\"Authorization\"`.\n */\nexport function reportSuppressedCredential(\n target: string,\n reference: string,\n header = \"Authorization\",\n): void {\n if (!isDevBuild()) return;\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return;\n const key = `${header} ${targetOrigin}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.warn(\n `[tempest-react-sdk] ${header} was not sent to ${targetOrigin}: the credential is scoped to ${originOf(reference) ?? reference}. Add the origin to trustedOrigins if it should receive the token.`,\n );\n}\n\n/**\n * Forget which origins were already reported.\n *\n * Exported for tests, which assert the once-per-origin behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetSuppressedCredentialReports(): void {\n reported.clear();\n}\n"],"mappings":";;AAMA,IAAM,oBAAW,IAAI,IAAY;AAkBjC,SAAS,EAAS,GAA4B;CAC1C,IAAI;EACA,OAAO,IAAI,IAAI,GAAK,WAAW,UAAU,IAAI,CAAC,CAAC;CACnD,QAAQ;EACJ,OAAO;CACX;AACJ;AAoCA,SAAgB,EACZ,GACA,GACA,IAAoC,CAAC,GAC9B;CACP,IAAM,IAAe,EAAS,CAAM;CAGpC,OAFI,MAAiB,QACjB,MAAiB,EAAS,CAAS,KAChC,EAAe,MAAM,MAAW,EAAS,CAAM,MAAM,CAAY;AAC5E;AAkBA,SAAgB,EACZ,GACA,GACA,IAAS,iBACL;CACJ,IAAI,CAAC,EAAW,GAAG;CACnB,IAAM,IAAe,EAAS,CAAM;CACpC,IAAI,MAAiB,MAAM;CAC3B,IAAM,IAAM,GAAG,EAAO,GAAG;CACrB,EAAS,IAAI,CAAG,MACpB,EAAS,IAAI,CAAG,GAChB,QAAQ,KACJ,uBAAuB,EAAO,mBAAmB,EAAa,gCAAgC,EAAS,CAAS,KAAK,EAAU,mEACnI;AACJ"}
1
+ {"version":3,"file":"credential-scope.js","names":["reported","originOf","url","isTrustedCredentialTarget","targetOrigin","target","reference","trustedOrigins","origin","reportSuppressedCredential","isDevBuild","key","header"],"sources":["../../src/http/credential-scope.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Origins already reported by {@link reportSuppressedCredential}, so a chunked\n * upload warns once instead of once per chunk.\n */\nconst reported = new Set<string>();\n\n/**\n * The origin a URL resolves to, or `null` when it has none to compare.\n *\n * Relative values resolve against the document, because that is what they mean\n * everywhere else in the SDK: an `endpoint` of `\"/api/uploads\"` and a `baseURL`\n * of `\"/api\"` are the shape you get behind a dev-server or a reverse proxy, and\n * both name the page's own origin. Comparing a resolved absolute target against\n * an unresolved relative reference is how the first draft of this function\n * withheld the credential from every client configured that way.\n *\n * `null` is reserved for the case with genuinely nothing to compare: a relative\n * URL outside a browsing context, where there is no document to resolve against.\n *\n * @param url - Absolute or relative URL.\n * @returns The origin, or `null` when it cannot be resolved.\n */\nfunction originOf(url: string): string | null {\n try {\n return new URL(url, globalThis.location?.href).origin;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a request to `target` may carry the caller's credential.\n *\n * The SDK writes `Authorization: Bearer` in three places, and until 0.66.0 none\n * of them looked at where the request was going. That is only safe while every\n * target URL is written by the app: a resumable upload takes its URL from the\n * server's `Location` header, and `createApiClient` lets an absolute path\n * override `baseURL` entirely, so a URL arriving over the network could decide\n * which origin received the token — and the file bytes with it.\n *\n * Handing an upload off to object storage on another host is ordinary `tus`\n * deployment, not an attack, which is exactly why the credential must be scoped\n * rather than the request blocked: the upload still goes through, it just goes\n * without the API's bearer token.\n *\n * Both sides are resolved against the document first, so a relative `baseURL`\n * or `endpoint` — the shape behind a dev-server or reverse proxy — compares\n * equal to the absolute URL the request actually goes to. Outside a browsing\n * context a relative target resolves to nothing and is allowed: there is no\n * origin for it to cross.\n *\n * @param target - The URL the request is about to go to.\n * @param reference - The origin the credential belongs to, normally the\n * client's `baseURL` or the upload `endpoint`.\n * @param trustedOrigins - Extra origins the app declared, for the legitimate\n * second host: a CDN, a signed upload endpoint.\n * @returns Whether the credential may be attached.\n *\n * @example\n * isTrustedCredentialTarget(\"https://api.acme.com/me\", \"https://api.acme.com\");\n * // true\n * isTrustedCredentialTarget(\"https://cdn.other/u/1\", \"https://api.acme.com\");\n * // false\n */\nexport function isTrustedCredentialTarget(\n target: string,\n reference: string,\n trustedOrigins: readonly string[] = [],\n): boolean {\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return true;\n if (targetOrigin === originOf(reference)) return true;\n return trustedOrigins.some((origin) => originOf(origin) === targetOrigin);\n}\n\n/**\n * Say once, in a development build, that a credential was withheld.\n *\n * Without it the symptom is a `401` (or, for the CSRF header, a `403`) from a\n * host the developer never typed, and nothing in the app's code mentions the\n * origin that produced it. Keyed by credential and target origin, so a\n * hundred-chunk upload reports one line per header it withheld.\n *\n * Silent in production for the same reason {@link parseResponse} is: the origin\n * an app talks to is not something to print into a user's console or ship to an\n * error tracker.\n *\n * @param target - The URL whose request went out unauthenticated.\n * @param reference - The origin the credential was scoped to.\n * @param header - The header that was withheld. Default `\"Authorization\"`.\n */\nexport function reportSuppressedCredential(\n target: string,\n reference: string,\n header = \"Authorization\",\n): void {\n if (!isDevBuild()) return;\n const targetOrigin = originOf(target);\n if (targetOrigin === null) return;\n const key = `${header} ${targetOrigin}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.warn(\n `[tempest-react-sdk] ${header} was not sent to ${targetOrigin}: the credential is scoped to ${originOf(reference) ?? reference}. Add the origin to trustedOrigins if it should receive the token.`,\n );\n}\n\n/**\n * Forget which origins were already reported.\n *\n * Exported for tests, which assert the once-per-origin behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetSuppressedCredentialReports(): void {\n reported.clear();\n}\n"],"mappings":";;AAMA,IAAMA,oBAAW,IAAI,IAAY;AAkBjC,SAASC,EAAS,GAA4B;CAC1C,IAAI;EACA,OAAO,IAAI,IAAIC,GAAK,WAAW,UAAU,IAAI,CAAC,CAAC;CACnD,QAAQ;EACJ,OAAO;CACX;AACJ;AAoCA,SAAgBC,EACZ,GACA,GACA,IAAoC,CAAC,GAC9B;CACP,IAAMC,IAAeH,EAASI,CAAM;CAGpC,OAFID,MAAiB,QACjBA,MAAiBH,EAASK,CAAS,KAChCC,EAAe,MAAM,MAAWN,EAASO,CAAM,MAAMJ,CAAY;AAC5E;AAkBA,SAAgBK,EACZ,GACA,GACA,IAAS,iBACL;CACJ,IAAI,CAACC,EAAW,GAAG;CACnB,IAAMN,IAAeH,EAASI,CAAM;CACpC,IAAID,MAAiB,MAAM;CAC3B,IAAMO,IAAM,GAAGC,EAAO,GAAGR;CACzB,AAAIJ,EAAS,IAAIW,CAAG,MACpBX,EAAS,IAAIW,CAAG,GAChB,QAAQ,KACJ,uBAAuBC,EAAO,mBAAmBR,EAAa,gCAAgCH,EAASK,CAAS,KAAKA,EAAU,mEACnI;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"csrf.cjs","names":[],"sources":["../../src/http/csrf.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\n\n/**\n * Default cookie the CSRF token is read from.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_COOKIE_NAME`\n * (`tempest_fastapi_sdk/api/middlewares/csrf.py`), which is the cookie its\n * `make_csrf_token_dependency()` sets and its `CSRFMiddleware` compares against.\n * Matching it is what lets `csrf: true` work against that backend with no\n * configuration on either side.\n */\nexport const DEFAULT_CSRF_COOKIE_NAME = \"csrf_token\";\n\n/**\n * Default header the CSRF token is echoed in.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_HEADER_NAME`, the header its\n * `CSRFMiddleware` reads on every unsafe request.\n */\nexport const DEFAULT_CSRF_HEADER_NAME = \"X-CSRF-Token\";\n\n/**\n * Where the CSRF token comes from and which header carries it.\n *\n * The default is the **double-submit cookie**: the server sets a cookie that is\n * deliberately not `HttpOnly`, the client reads it and echoes the value in a\n * header, and the server rejects a write whose header does not match the\n * cookie. A page on another site can make the browser *send* the cookie, but\n * cannot *read* it, so it cannot write the header.\n *\n * The token is read again on every request, so a server that rotates the\n * cookie is followed without any capture step: the browser's cookie jar is the\n * store. That is also why there is no \"read the token from a response header\"\n * mode — it would depend on `Access-Control-Expose-Headers`, and a missing\n * expose header fails silently, as a `403` on the second write.\n */\nexport interface CsrfOptions {\n /** Cookie to read the token from. Default {@link DEFAULT_CSRF_COOKIE_NAME}. */\n cookieName?: string;\n /** Header to send the token in. Default {@link DEFAULT_CSRF_HEADER_NAME}. */\n headerName?: string;\n /**\n * Supply the token yourself instead of reading `cookieName`.\n *\n * For the cases the cookie cannot serve: an API on another **site**, whose\n * cookie `document.cookie` cannot see, or a backend that hands the token\n * out in a response body. Called per request, like `getToken`.\n */\n getToken?: () => string | null | undefined;\n}\n\n/**\n * Methods that must not change state, and so never carry the token.\n *\n * A deny list rather than an allow list of the four write verbs: RFC 9110\n * names the safe methods, and a custom method (`PROPFIND`, a tus extension)\n * is a write until proven otherwise. Sending the token to its own origin on\n * an unexpected verb costs nothing; omitting it costs a `403`.\n */\nconst SAFE_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"]);\n\n/** Token sources already reported empty, so a burst of writes warns once. */\nconst reportedMissing = new Set<string>();\n\n/**\n * Read one cookie from `document.cookie`, or `null` when it is absent.\n *\n * Returns `null` outside a document (a worker, a test without jsdom), where\n * there is no cookie jar to read. The value is URI-decoded when it can be,\n * and returned raw when it is not valid percent-encoding.\n *\n * @param name - The cookie name.\n * @returns The value, or `null`.\n */\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(\";\")) {\n const entry = part.trim();\n if (!entry.startsWith(prefix)) continue;\n const raw = entry.slice(prefix.length);\n try {\n return decodeURIComponent(raw);\n } catch {\n return raw;\n }\n }\n return null;\n}\n\n/**\n * Say once, in a development build, that CSRF is on but there is no token.\n *\n * The request still goes out, because the SDK cannot know whether this path\n * is guarded — `CSRFMiddleware` is commonly mounted with `exclude_paths`. When\n * it is guarded, the symptom is a `403 CSRF_VALIDATION_FAILED` with nothing\n * in the app's code pointing at the cause, and the three usual causes are all\n * on the server: the cookie was never issued, was issued `HttpOnly`, or was\n * issued for a domain this page cannot read.\n *\n * @param source - What was read: the cookie name, or `\"getToken\"`.\n */\nfunction reportMissingToken(source: string): void {\n if (!isDevBuild() || reportedMissing.has(source)) return;\n reportedMissing.add(source);\n const where =\n source === \"getToken\"\n ? \"csrf.getToken() returned nothing\"\n : `no readable \"${source}\" cookie on this page`;\n console.warn(\n `[tempest-react-sdk] CSRF is enabled but ${where}, so the write went without the token. The cookie must be issued before the first write and must not be HttpOnly.`,\n );\n}\n\n/**\n * Whether a header is already present, compared case-insensitively.\n *\n * Header names are case-insensitive, but object keys are not: a caller's\n * `\"x-csrf-token\"` next to the SDK's `\"X-CSRF-Token\"` would reach `fetch` as\n * two entries and be joined into `\"a, b\"`, which matches neither.\n *\n * @param headers - The headers the caller already set.\n * @param name - The header to look for.\n * @returns Whether it is set.\n */\nfunction hasHeader(headers: HeadersInit | undefined, name: string): boolean {\n if (!headers) return false;\n return new Headers(headers).has(name);\n}\n\n/** What {@link csrfHeaders} needs to decide. */\nexport interface CsrfHeadersInput {\n /** The HTTP method of the request. Case-insensitive. */\n method: string;\n /** The URL the request is going to. */\n url: string;\n /**\n * The origin the token belongs to, normally the API's `baseURL`. The token\n * is only sent to this origin or to one listed in `trustedOrigins`.\n */\n reference: string;\n /** The CSRF config. `undefined` or `false` turns the header off. */\n csrf: boolean | CsrfOptions | undefined;\n /** Extra origins allowed to receive the token. */\n trustedOrigins?: readonly string[];\n /** Headers the caller already set. A CSRF header among them is never replaced. */\n headers?: HeadersInit;\n}\n\n/**\n * The CSRF header a request should carry, or an empty object.\n *\n * Every request path in the SDK — `createApiClient`, `uploadWithProgress`,\n * `createResumableUpload` — asks this function, so the rules are one rule:\n *\n * - **Off unless configured.** Without `csrf`, nothing changes.\n * - **Unsafe methods only.** `GET`, `HEAD`, `OPTIONS` and `TRACE` never carry\n * it; they must not change state, and a token in a `GET` ends up in logs\n * and caches for nothing.\n * - **Never across an origin.** The token follows the same scope as the bearer\n * credential ({@link isTrustedCredentialTarget}), because a URL can come off\n * the network — a tus `Location`, a pagination link — and a CSRF token sent\n * to a third party is a token that third party can replay. Withheld tokens\n * are reported once per origin in a development build.\n * - **Your header wins.** A CSRF header you set by hand, in any casing, is\n * left alone.\n * - **Independent of auth.** It is sent on `skipAuth` requests too: login and\n * refresh are exactly the writes a cookie session exposes to forgery.\n *\n * Exported for the request you build by hand, so it follows the same rules.\n *\n * @example\n * const headers = csrfHeaders({\n * method: \"POST\",\n * url: \"https://api.acme.com/orders\",\n * reference: \"https://api.acme.com\",\n * csrf: true,\n * });\n * // { \"X-CSRF-Token\": \"<value of the csrf_token cookie>\" }\n *\n * @param input - The request and the CSRF config.\n * @returns A header record to spread into the request's headers.\n */\nexport function csrfHeaders(input: CsrfHeadersInput): Record<string, string> {\n const { method, url, reference, csrf, trustedOrigins, headers } = input;\n if (!csrf) return {};\n if (SAFE_METHODS.has(method.toUpperCase())) return {};\n const options: CsrfOptions = csrf === true ? {} : csrf;\n const headerName = options.headerName ?? DEFAULT_CSRF_HEADER_NAME;\n if (hasHeader(headers, headerName)) return {};\n if (!isTrustedCredentialTarget(url, reference, trustedOrigins)) {\n reportSuppressedCredential(url, reference, headerName);\n return {};\n }\n const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;\n const token = options.getToken ? options.getToken() : readCookie(cookieName);\n if (!token) {\n reportMissingToken(options.getToken ? \"getToken\" : cookieName);\n return {};\n }\n return { [headerName]: token };\n}\n\n/**\n * Forget which token sources were already reported empty.\n *\n * Exported for tests, which assert the once-per-source behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetCsrfReports(): void {\n reportedMissing.clear();\n}\n"],"mappings":"6EAYA,IAAa,EAA2B,aAQ3B,EAA2B,eAwClC,EAAoC,IAAI,IAAI,CAAC,MAAO,OAAQ,UAAW,OAAO,CAAC,EAG/E,EAAkB,IAAI,IAY5B,SAAS,EAAW,EAA6B,CAC7C,GAAI,OAAO,SAAa,IAAa,OAAO,KAC5C,IAAM,EAAS,GAAG,EAAK,GACvB,IAAK,IAAM,KAAQ,SAAS,OAAO,MAAM,GAAG,EAAG,CAC3C,IAAM,EAAQ,EAAK,KAAK,EACxB,GAAI,CAAC,EAAM,WAAW,CAAM,EAAG,SAC/B,IAAM,EAAM,EAAM,MAAM,EAAO,MAAM,EACrC,GAAI,CACA,OAAO,mBAAmB,CAAG,CACjC,MAAQ,CACJ,OAAO,CACX,CACJ,CACA,OAAO,IACX,CAcA,SAAS,EAAmB,EAAsB,CAC9C,GAAI,CAAC,EAAA,WAAW,GAAK,EAAgB,IAAI,CAAM,EAAG,OAClD,EAAgB,IAAI,CAAM,EAC1B,IAAM,EACF,IAAW,WACL,mCACA,gBAAgB,EAAO,uBACjC,QAAQ,KACJ,2CAA2C,EAAM,kHACrD,CACJ,CAaA,SAAS,EAAU,EAAkC,EAAuB,CAExE,OADK,EACE,IAAI,QAAQ,CAAO,CAAC,CAAC,IAAI,CAAI,EADf,EAEzB,CAuDA,SAAgB,EAAY,EAAiD,CACzE,GAAM,CAAE,SAAQ,MAAK,YAAW,OAAM,iBAAgB,WAAY,EAElE,GADI,CAAC,GACD,EAAa,IAAI,EAAO,YAAY,CAAC,EAAG,MAAO,CAAC,EACpD,IAAM,EAAuB,IAAS,GAAO,CAAC,EAAI,EAC5C,EAAa,EAAQ,YAAA,eAC3B,GAAI,EAAU,EAAS,CAAU,EAAG,MAAO,CAAC,EAC5C,GAAI,CAAC,EAAA,0BAA0B,EAAK,EAAW,CAAc,EAEzD,OADA,EAAA,2BAA2B,EAAK,EAAW,CAAU,EAC9C,CAAC,EAEZ,IAAM,EAAa,EAAQ,YAAA,aACrB,EAAQ,EAAQ,SAAW,EAAQ,SAAS,EAAI,EAAW,CAAU,EAK3E,OAJK,EAIE,EAAG,GAAa,CAAM,GAHzB,EAAmB,EAAQ,SAAW,WAAa,CAAU,EACtD,CAAC,EAGhB"}
1
+ {"version":3,"file":"csrf.cjs","names":["isDevBuild","isTrustedCredentialTarget","require_dev_mode","require_credential_scope","DEFAULT_CSRF_COOKIE_NAME","DEFAULT_CSRF_HEADER_NAME","SAFE_METHODS","reportedMissing","readCookie","prefix","name","part","entry","raw","reportMissingToken","source","where","hasHeader","headers","csrfHeaders","input","csrf","method","options","headerName","url","reference","trustedOrigins","cookieName","token"],"sources":["../../src/http/csrf.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\n\n/**\n * Default cookie the CSRF token is read from.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_COOKIE_NAME`\n * (`tempest_fastapi_sdk/api/middlewares/csrf.py`), which is the cookie its\n * `make_csrf_token_dependency()` sets and its `CSRFMiddleware` compares against.\n * Matching it is what lets `csrf: true` work against that backend with no\n * configuration on either side.\n */\nexport const DEFAULT_CSRF_COOKIE_NAME = \"csrf_token\";\n\n/**\n * Default header the CSRF token is echoed in.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_HEADER_NAME`, the header its\n * `CSRFMiddleware` reads on every unsafe request.\n */\nexport const DEFAULT_CSRF_HEADER_NAME = \"X-CSRF-Token\";\n\n/**\n * Where the CSRF token comes from and which header carries it.\n *\n * The default is the **double-submit cookie**: the server sets a cookie that is\n * deliberately not `HttpOnly`, the client reads it and echoes the value in a\n * header, and the server rejects a write whose header does not match the\n * cookie. A page on another site can make the browser *send* the cookie, but\n * cannot *read* it, so it cannot write the header.\n *\n * The token is read again on every request, so a server that rotates the\n * cookie is followed without any capture step: the browser's cookie jar is the\n * store. That is also why there is no \"read the token from a response header\"\n * mode — it would depend on `Access-Control-Expose-Headers`, and a missing\n * expose header fails silently, as a `403` on the second write.\n */\nexport interface CsrfOptions {\n /** Cookie to read the token from. Default {@link DEFAULT_CSRF_COOKIE_NAME}. */\n cookieName?: string;\n /** Header to send the token in. Default {@link DEFAULT_CSRF_HEADER_NAME}. */\n headerName?: string;\n /**\n * Supply the token yourself instead of reading `cookieName`.\n *\n * For the cases the cookie cannot serve: an API on another **site**, whose\n * cookie `document.cookie` cannot see, or a backend that hands the token\n * out in a response body. Called per request, like `getToken`.\n */\n getToken?: () => string | null | undefined;\n}\n\n/**\n * Methods that must not change state, and so never carry the token.\n *\n * A deny list rather than an allow list of the four write verbs: RFC 9110\n * names the safe methods, and a custom method (`PROPFIND`, a tus extension)\n * is a write until proven otherwise. Sending the token to its own origin on\n * an unexpected verb costs nothing; omitting it costs a `403`.\n */\nconst SAFE_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"]);\n\n/** Token sources already reported empty, so a burst of writes warns once. */\nconst reportedMissing = new Set<string>();\n\n/**\n * Read one cookie from `document.cookie`, or `null` when it is absent.\n *\n * Returns `null` outside a document (a worker, a test without jsdom), where\n * there is no cookie jar to read. The value is URI-decoded when it can be,\n * and returned raw when it is not valid percent-encoding.\n *\n * @param name - The cookie name.\n * @returns The value, or `null`.\n */\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(\";\")) {\n const entry = part.trim();\n if (!entry.startsWith(prefix)) continue;\n const raw = entry.slice(prefix.length);\n try {\n return decodeURIComponent(raw);\n } catch {\n return raw;\n }\n }\n return null;\n}\n\n/**\n * Say once, in a development build, that CSRF is on but there is no token.\n *\n * The request still goes out, because the SDK cannot know whether this path\n * is guarded — `CSRFMiddleware` is commonly mounted with `exclude_paths`. When\n * it is guarded, the symptom is a `403 CSRF_VALIDATION_FAILED` with nothing\n * in the app's code pointing at the cause, and the three usual causes are all\n * on the server: the cookie was never issued, was issued `HttpOnly`, or was\n * issued for a domain this page cannot read.\n *\n * @param source - What was read: the cookie name, or `\"getToken\"`.\n */\nfunction reportMissingToken(source: string): void {\n if (!isDevBuild() || reportedMissing.has(source)) return;\n reportedMissing.add(source);\n const where =\n source === \"getToken\"\n ? \"csrf.getToken() returned nothing\"\n : `no readable \"${source}\" cookie on this page`;\n console.warn(\n `[tempest-react-sdk] CSRF is enabled but ${where}, so the write went without the token. The cookie must be issued before the first write and must not be HttpOnly.`,\n );\n}\n\n/**\n * Whether a header is already present, compared case-insensitively.\n *\n * Header names are case-insensitive, but object keys are not: a caller's\n * `\"x-csrf-token\"` next to the SDK's `\"X-CSRF-Token\"` would reach `fetch` as\n * two entries and be joined into `\"a, b\"`, which matches neither.\n *\n * @param headers - The headers the caller already set.\n * @param name - The header to look for.\n * @returns Whether it is set.\n */\nfunction hasHeader(headers: HeadersInit | undefined, name: string): boolean {\n if (!headers) return false;\n return new Headers(headers).has(name);\n}\n\n/** What {@link csrfHeaders} needs to decide. */\nexport interface CsrfHeadersInput {\n /** The HTTP method of the request. Case-insensitive. */\n method: string;\n /** The URL the request is going to. */\n url: string;\n /**\n * The origin the token belongs to, normally the API's `baseURL`. The token\n * is only sent to this origin or to one listed in `trustedOrigins`.\n */\n reference: string;\n /** The CSRF config. `undefined` or `false` turns the header off. */\n csrf: boolean | CsrfOptions | undefined;\n /** Extra origins allowed to receive the token. */\n trustedOrigins?: readonly string[];\n /** Headers the caller already set. A CSRF header among them is never replaced. */\n headers?: HeadersInit;\n}\n\n/**\n * The CSRF header a request should carry, or an empty object.\n *\n * Every request path in the SDK — `createApiClient`, `uploadWithProgress`,\n * `createResumableUpload` — asks this function, so the rules are one rule:\n *\n * - **Off unless configured.** Without `csrf`, nothing changes.\n * - **Unsafe methods only.** `GET`, `HEAD`, `OPTIONS` and `TRACE` never carry\n * it; they must not change state, and a token in a `GET` ends up in logs\n * and caches for nothing.\n * - **Never across an origin.** The token follows the same scope as the bearer\n * credential ({@link isTrustedCredentialTarget}), because a URL can come off\n * the network — a tus `Location`, a pagination link — and a CSRF token sent\n * to a third party is a token that third party can replay. Withheld tokens\n * are reported once per origin in a development build.\n * - **Your header wins.** A CSRF header you set by hand, in any casing, is\n * left alone.\n * - **Independent of auth.** It is sent on `skipAuth` requests too: login and\n * refresh are exactly the writes a cookie session exposes to forgery.\n *\n * Exported for the request you build by hand, so it follows the same rules.\n *\n * @example\n * const headers = csrfHeaders({\n * method: \"POST\",\n * url: \"https://api.acme.com/orders\",\n * reference: \"https://api.acme.com\",\n * csrf: true,\n * });\n * // { \"X-CSRF-Token\": \"<value of the csrf_token cookie>\" }\n *\n * @param input - The request and the CSRF config.\n * @returns A header record to spread into the request's headers.\n */\nexport function csrfHeaders(input: CsrfHeadersInput): Record<string, string> {\n const { method, url, reference, csrf, trustedOrigins, headers } = input;\n if (!csrf) return {};\n if (SAFE_METHODS.has(method.toUpperCase())) return {};\n const options: CsrfOptions = csrf === true ? {} : csrf;\n const headerName = options.headerName ?? DEFAULT_CSRF_HEADER_NAME;\n if (hasHeader(headers, headerName)) return {};\n if (!isTrustedCredentialTarget(url, reference, trustedOrigins)) {\n reportSuppressedCredential(url, reference, headerName);\n return {};\n }\n const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;\n const token = options.getToken ? options.getToken() : readCookie(cookieName);\n if (!token) {\n reportMissingToken(options.getToken ? \"getToken\" : cookieName);\n return {};\n }\n return { [headerName]: token };\n}\n\n/**\n * Forget which token sources were already reported empty.\n *\n * Exported for tests, which assert the once-per-source behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetCsrfReports(): void {\n reportedMissing.clear();\n}\n"],"mappings":"A,6EAYA,IAAaI,EAA2B,aAQ3BC,EAA2B,eAwClCC,EAAoC,IAAI,IAAI,CAAC,MAAO,OAAQ,UAAW,OAAO,CAAC,EAG/EC,EAAkB,IAAI,IAY5B,SAASC,EAAW,EAA6B,CAC7C,GAAI,OAAO,SAAa,IAAa,OAAO,KAC5C,IAAMC,EAAS,GAAGC,EAAK,GACvB,IAAK,IAAMC,KAAQ,SAAS,OAAO,MAAM,GAAG,EAAG,CAC3C,IAAMC,EAAQD,EAAK,KAAK,EACxB,GAAI,CAACC,EAAM,WAAWH,CAAM,EAAG,SAC/B,IAAMI,EAAMD,EAAM,MAAMH,EAAO,MAAM,EACrC,GAAI,CACA,OAAO,mBAAmBI,CAAG,CACjC,MAAQ,CACJ,OAAOA,CACX,CACJ,CACA,OAAO,IACX,CAcA,SAASC,EAAmB,EAAsB,CAC9C,GAAI,CAACd,EAAAA,WAAW,GAAKO,EAAgB,IAAIQ,CAAM,EAAG,OAClDR,EAAgB,IAAIQ,CAAM,EAC1B,IAAMC,EACFD,IAAW,WACL,mCACA,gBAAgBA,EAAO,uBACjC,QAAQ,KACJ,2CAA2CC,EAAM,kHACrD,CACJ,CAaA,SAASC,EAAU,EAAkC,EAAuB,CAExE,OADKC,EACE,IAAI,QAAQA,CAAO,CAAC,CAAC,IAAIR,CAAI,EADf,EAEzB,CAuDA,SAAgBS,EAAY,EAAiD,CACzE,GAAM,CAAE,SAAQ,MAAK,YAAW,OAAM,iBAAgB,WAAYC,EAElE,GADI,CAACC,GACDf,EAAa,IAAIgB,EAAO,YAAY,CAAC,EAAG,MAAO,CAAC,EACpD,IAAMC,EAAuBF,IAAS,GAAO,CAAC,EAAIA,EAC5CG,EAAaD,EAAQ,YAAA,eAC3B,GAAIN,EAAUC,EAASM,CAAU,EAAG,MAAO,CAAC,EAC5C,GAAI,CAACvB,EAAAA,0BAA0BwB,EAAKC,EAAWC,CAAc,EAEzD,OADAxB,EAAA,2BAA2BsB,EAAKC,EAAWF,CAAU,EAC9C,CAAC,EAEZ,IAAMI,EAAaL,EAAQ,YAAA,aACrBM,EAAQN,EAAQ,SAAWA,EAAQ,SAAS,EAAIf,EAAWoB,CAAU,EAK3E,OAJKC,EAIE,EAAGL,GAAaK,CAAM,GAHzBf,EAAmBS,EAAQ,SAAW,WAAaK,CAAU,EACtD,CAAC,EAGhB,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"csrf.js","names":[],"sources":["../../src/http/csrf.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\n\n/**\n * Default cookie the CSRF token is read from.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_COOKIE_NAME`\n * (`tempest_fastapi_sdk/api/middlewares/csrf.py`), which is the cookie its\n * `make_csrf_token_dependency()` sets and its `CSRFMiddleware` compares against.\n * Matching it is what lets `csrf: true` work against that backend with no\n * configuration on either side.\n */\nexport const DEFAULT_CSRF_COOKIE_NAME = \"csrf_token\";\n\n/**\n * Default header the CSRF token is echoed in.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_HEADER_NAME`, the header its\n * `CSRFMiddleware` reads on every unsafe request.\n */\nexport const DEFAULT_CSRF_HEADER_NAME = \"X-CSRF-Token\";\n\n/**\n * Where the CSRF token comes from and which header carries it.\n *\n * The default is the **double-submit cookie**: the server sets a cookie that is\n * deliberately not `HttpOnly`, the client reads it and echoes the value in a\n * header, and the server rejects a write whose header does not match the\n * cookie. A page on another site can make the browser *send* the cookie, but\n * cannot *read* it, so it cannot write the header.\n *\n * The token is read again on every request, so a server that rotates the\n * cookie is followed without any capture step: the browser's cookie jar is the\n * store. That is also why there is no \"read the token from a response header\"\n * mode — it would depend on `Access-Control-Expose-Headers`, and a missing\n * expose header fails silently, as a `403` on the second write.\n */\nexport interface CsrfOptions {\n /** Cookie to read the token from. Default {@link DEFAULT_CSRF_COOKIE_NAME}. */\n cookieName?: string;\n /** Header to send the token in. Default {@link DEFAULT_CSRF_HEADER_NAME}. */\n headerName?: string;\n /**\n * Supply the token yourself instead of reading `cookieName`.\n *\n * For the cases the cookie cannot serve: an API on another **site**, whose\n * cookie `document.cookie` cannot see, or a backend that hands the token\n * out in a response body. Called per request, like `getToken`.\n */\n getToken?: () => string | null | undefined;\n}\n\n/**\n * Methods that must not change state, and so never carry the token.\n *\n * A deny list rather than an allow list of the four write verbs: RFC 9110\n * names the safe methods, and a custom method (`PROPFIND`, a tus extension)\n * is a write until proven otherwise. Sending the token to its own origin on\n * an unexpected verb costs nothing; omitting it costs a `403`.\n */\nconst SAFE_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"]);\n\n/** Token sources already reported empty, so a burst of writes warns once. */\nconst reportedMissing = new Set<string>();\n\n/**\n * Read one cookie from `document.cookie`, or `null` when it is absent.\n *\n * Returns `null` outside a document (a worker, a test without jsdom), where\n * there is no cookie jar to read. The value is URI-decoded when it can be,\n * and returned raw when it is not valid percent-encoding.\n *\n * @param name - The cookie name.\n * @returns The value, or `null`.\n */\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(\";\")) {\n const entry = part.trim();\n if (!entry.startsWith(prefix)) continue;\n const raw = entry.slice(prefix.length);\n try {\n return decodeURIComponent(raw);\n } catch {\n return raw;\n }\n }\n return null;\n}\n\n/**\n * Say once, in a development build, that CSRF is on but there is no token.\n *\n * The request still goes out, because the SDK cannot know whether this path\n * is guarded — `CSRFMiddleware` is commonly mounted with `exclude_paths`. When\n * it is guarded, the symptom is a `403 CSRF_VALIDATION_FAILED` with nothing\n * in the app's code pointing at the cause, and the three usual causes are all\n * on the server: the cookie was never issued, was issued `HttpOnly`, or was\n * issued for a domain this page cannot read.\n *\n * @param source - What was read: the cookie name, or `\"getToken\"`.\n */\nfunction reportMissingToken(source: string): void {\n if (!isDevBuild() || reportedMissing.has(source)) return;\n reportedMissing.add(source);\n const where =\n source === \"getToken\"\n ? \"csrf.getToken() returned nothing\"\n : `no readable \"${source}\" cookie on this page`;\n console.warn(\n `[tempest-react-sdk] CSRF is enabled but ${where}, so the write went without the token. The cookie must be issued before the first write and must not be HttpOnly.`,\n );\n}\n\n/**\n * Whether a header is already present, compared case-insensitively.\n *\n * Header names are case-insensitive, but object keys are not: a caller's\n * `\"x-csrf-token\"` next to the SDK's `\"X-CSRF-Token\"` would reach `fetch` as\n * two entries and be joined into `\"a, b\"`, which matches neither.\n *\n * @param headers - The headers the caller already set.\n * @param name - The header to look for.\n * @returns Whether it is set.\n */\nfunction hasHeader(headers: HeadersInit | undefined, name: string): boolean {\n if (!headers) return false;\n return new Headers(headers).has(name);\n}\n\n/** What {@link csrfHeaders} needs to decide. */\nexport interface CsrfHeadersInput {\n /** The HTTP method of the request. Case-insensitive. */\n method: string;\n /** The URL the request is going to. */\n url: string;\n /**\n * The origin the token belongs to, normally the API's `baseURL`. The token\n * is only sent to this origin or to one listed in `trustedOrigins`.\n */\n reference: string;\n /** The CSRF config. `undefined` or `false` turns the header off. */\n csrf: boolean | CsrfOptions | undefined;\n /** Extra origins allowed to receive the token. */\n trustedOrigins?: readonly string[];\n /** Headers the caller already set. A CSRF header among them is never replaced. */\n headers?: HeadersInit;\n}\n\n/**\n * The CSRF header a request should carry, or an empty object.\n *\n * Every request path in the SDK — `createApiClient`, `uploadWithProgress`,\n * `createResumableUpload` — asks this function, so the rules are one rule:\n *\n * - **Off unless configured.** Without `csrf`, nothing changes.\n * - **Unsafe methods only.** `GET`, `HEAD`, `OPTIONS` and `TRACE` never carry\n * it; they must not change state, and a token in a `GET` ends up in logs\n * and caches for nothing.\n * - **Never across an origin.** The token follows the same scope as the bearer\n * credential ({@link isTrustedCredentialTarget}), because a URL can come off\n * the network — a tus `Location`, a pagination link — and a CSRF token sent\n * to a third party is a token that third party can replay. Withheld tokens\n * are reported once per origin in a development build.\n * - **Your header wins.** A CSRF header you set by hand, in any casing, is\n * left alone.\n * - **Independent of auth.** It is sent on `skipAuth` requests too: login and\n * refresh are exactly the writes a cookie session exposes to forgery.\n *\n * Exported for the request you build by hand, so it follows the same rules.\n *\n * @example\n * const headers = csrfHeaders({\n * method: \"POST\",\n * url: \"https://api.acme.com/orders\",\n * reference: \"https://api.acme.com\",\n * csrf: true,\n * });\n * // { \"X-CSRF-Token\": \"<value of the csrf_token cookie>\" }\n *\n * @param input - The request and the CSRF config.\n * @returns A header record to spread into the request's headers.\n */\nexport function csrfHeaders(input: CsrfHeadersInput): Record<string, string> {\n const { method, url, reference, csrf, trustedOrigins, headers } = input;\n if (!csrf) return {};\n if (SAFE_METHODS.has(method.toUpperCase())) return {};\n const options: CsrfOptions = csrf === true ? {} : csrf;\n const headerName = options.headerName ?? DEFAULT_CSRF_HEADER_NAME;\n if (hasHeader(headers, headerName)) return {};\n if (!isTrustedCredentialTarget(url, reference, trustedOrigins)) {\n reportSuppressedCredential(url, reference, headerName);\n return {};\n }\n const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;\n const token = options.getToken ? options.getToken() : readCookie(cookieName);\n if (!token) {\n reportMissingToken(options.getToken ? \"getToken\" : cookieName);\n return {};\n }\n return { [headerName]: token };\n}\n\n/**\n * Forget which token sources were already reported empty.\n *\n * Exported for tests, which assert the once-per-source behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetCsrfReports(): void {\n reportedMissing.clear();\n}\n"],"mappings":";;;AAYA,IAAa,IAA2B,cAQ3B,IAA2B,gBAwClC,oBAAoC,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAW;AAAO,CAAC,GAG/E,oBAAkB,IAAI,IAAY;AAYxC,SAAS,EAAW,GAA6B;CAC7C,IAAI,OAAO,WAAa,KAAa,OAAO;CAC5C,IAAM,IAAS,GAAG,EAAK;CACvB,KAAK,IAAM,KAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;EAC3C,IAAM,IAAQ,EAAK,KAAK;EACxB,IAAI,CAAC,EAAM,WAAW,CAAM,GAAG;EAC/B,IAAM,IAAM,EAAM,MAAM,EAAO,MAAM;EACrC,IAAI;GACA,OAAO,mBAAmB,CAAG;EACjC,QAAQ;GACJ,OAAO;EACX;CACJ;CACA,OAAO;AACX;AAcA,SAAS,EAAmB,GAAsB;CAC9C,IAAI,CAAC,EAAW,KAAK,EAAgB,IAAI,CAAM,GAAG;CAClD,EAAgB,IAAI,CAAM;CAC1B,IAAM,IACF,MAAW,aACL,qCACA,gBAAgB,EAAO;CACjC,QAAQ,KACJ,2CAA2C,EAAM,kHACrD;AACJ;AAaA,SAAS,EAAU,GAAkC,GAAuB;CAExE,OADK,IACE,IAAI,QAAQ,CAAO,CAAC,CAAC,IAAI,CAAI,IADf;AAEzB;AAuDA,SAAgB,EAAY,GAAiD;CACzE,IAAM,EAAE,WAAQ,QAAK,cAAW,SAAM,mBAAgB,eAAY;CAElE,IADI,CAAC,KACD,EAAa,IAAI,EAAO,YAAY,CAAC,GAAG,OAAO,CAAC;CACpD,IAAM,IAAuB,MAAS,KAAO,CAAC,IAAI,GAC5C,IAAa,EAAQ,cAAA;CAC3B,IAAI,EAAU,GAAS,CAAU,GAAG,OAAO,CAAC;CAC5C,IAAI,CAAC,EAA0B,GAAK,GAAW,CAAc,GAEzD,OADA,EAA2B,GAAK,GAAW,CAAU,GAC9C,CAAC;CAEZ,IAAM,IAAa,EAAQ,cAAA,cACrB,IAAQ,EAAQ,WAAW,EAAQ,SAAS,IAAI,EAAW,CAAU;CAK3E,OAJK,IAIE,GAAG,IAAa,EAAM,KAHzB,EAAmB,EAAQ,WAAW,aAAa,CAAU,GACtD,CAAC;AAGhB"}
1
+ {"version":3,"file":"csrf.js","names":["DEFAULT_CSRF_COOKIE_NAME","DEFAULT_CSRF_HEADER_NAME","SAFE_METHODS","reportedMissing","readCookie","prefix","name","part","entry","raw","reportMissingToken","isDevBuild","source","where","hasHeader","headers","csrfHeaders","input","csrf","method","options","headerName","isTrustedCredentialTarget","url","reference","trustedOrigins","reportSuppressedCredential","cookieName","token"],"sources":["../../src/http/csrf.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\nimport { isTrustedCredentialTarget, reportSuppressedCredential } from \"./credential-scope\";\n\n/**\n * Default cookie the CSRF token is read from.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_COOKIE_NAME`\n * (`tempest_fastapi_sdk/api/middlewares/csrf.py`), which is the cookie its\n * `make_csrf_token_dependency()` sets and its `CSRFMiddleware` compares against.\n * Matching it is what lets `csrf: true` work against that backend with no\n * configuration on either side.\n */\nexport const DEFAULT_CSRF_COOKIE_NAME = \"csrf_token\";\n\n/**\n * Default header the CSRF token is echoed in.\n *\n * Ported from `tempest-fastapi-sdk`'s `CSRF_HEADER_NAME`, the header its\n * `CSRFMiddleware` reads on every unsafe request.\n */\nexport const DEFAULT_CSRF_HEADER_NAME = \"X-CSRF-Token\";\n\n/**\n * Where the CSRF token comes from and which header carries it.\n *\n * The default is the **double-submit cookie**: the server sets a cookie that is\n * deliberately not `HttpOnly`, the client reads it and echoes the value in a\n * header, and the server rejects a write whose header does not match the\n * cookie. A page on another site can make the browser *send* the cookie, but\n * cannot *read* it, so it cannot write the header.\n *\n * The token is read again on every request, so a server that rotates the\n * cookie is followed without any capture step: the browser's cookie jar is the\n * store. That is also why there is no \"read the token from a response header\"\n * mode — it would depend on `Access-Control-Expose-Headers`, and a missing\n * expose header fails silently, as a `403` on the second write.\n */\nexport interface CsrfOptions {\n /** Cookie to read the token from. Default {@link DEFAULT_CSRF_COOKIE_NAME}. */\n cookieName?: string;\n /** Header to send the token in. Default {@link DEFAULT_CSRF_HEADER_NAME}. */\n headerName?: string;\n /**\n * Supply the token yourself instead of reading `cookieName`.\n *\n * For the cases the cookie cannot serve: an API on another **site**, whose\n * cookie `document.cookie` cannot see, or a backend that hands the token\n * out in a response body. Called per request, like `getToken`.\n */\n getToken?: () => string | null | undefined;\n}\n\n/**\n * Methods that must not change state, and so never carry the token.\n *\n * A deny list rather than an allow list of the four write verbs: RFC 9110\n * names the safe methods, and a custom method (`PROPFIND`, a tus extension)\n * is a write until proven otherwise. Sending the token to its own origin on\n * an unexpected verb costs nothing; omitting it costs a `403`.\n */\nconst SAFE_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"]);\n\n/** Token sources already reported empty, so a burst of writes warns once. */\nconst reportedMissing = new Set<string>();\n\n/**\n * Read one cookie from `document.cookie`, or `null` when it is absent.\n *\n * Returns `null` outside a document (a worker, a test without jsdom), where\n * there is no cookie jar to read. The value is URI-decoded when it can be,\n * and returned raw when it is not valid percent-encoding.\n *\n * @param name - The cookie name.\n * @returns The value, or `null`.\n */\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(\";\")) {\n const entry = part.trim();\n if (!entry.startsWith(prefix)) continue;\n const raw = entry.slice(prefix.length);\n try {\n return decodeURIComponent(raw);\n } catch {\n return raw;\n }\n }\n return null;\n}\n\n/**\n * Say once, in a development build, that CSRF is on but there is no token.\n *\n * The request still goes out, because the SDK cannot know whether this path\n * is guarded — `CSRFMiddleware` is commonly mounted with `exclude_paths`. When\n * it is guarded, the symptom is a `403 CSRF_VALIDATION_FAILED` with nothing\n * in the app's code pointing at the cause, and the three usual causes are all\n * on the server: the cookie was never issued, was issued `HttpOnly`, or was\n * issued for a domain this page cannot read.\n *\n * @param source - What was read: the cookie name, or `\"getToken\"`.\n */\nfunction reportMissingToken(source: string): void {\n if (!isDevBuild() || reportedMissing.has(source)) return;\n reportedMissing.add(source);\n const where =\n source === \"getToken\"\n ? \"csrf.getToken() returned nothing\"\n : `no readable \"${source}\" cookie on this page`;\n console.warn(\n `[tempest-react-sdk] CSRF is enabled but ${where}, so the write went without the token. The cookie must be issued before the first write and must not be HttpOnly.`,\n );\n}\n\n/**\n * Whether a header is already present, compared case-insensitively.\n *\n * Header names are case-insensitive, but object keys are not: a caller's\n * `\"x-csrf-token\"` next to the SDK's `\"X-CSRF-Token\"` would reach `fetch` as\n * two entries and be joined into `\"a, b\"`, which matches neither.\n *\n * @param headers - The headers the caller already set.\n * @param name - The header to look for.\n * @returns Whether it is set.\n */\nfunction hasHeader(headers: HeadersInit | undefined, name: string): boolean {\n if (!headers) return false;\n return new Headers(headers).has(name);\n}\n\n/** What {@link csrfHeaders} needs to decide. */\nexport interface CsrfHeadersInput {\n /** The HTTP method of the request. Case-insensitive. */\n method: string;\n /** The URL the request is going to. */\n url: string;\n /**\n * The origin the token belongs to, normally the API's `baseURL`. The token\n * is only sent to this origin or to one listed in `trustedOrigins`.\n */\n reference: string;\n /** The CSRF config. `undefined` or `false` turns the header off. */\n csrf: boolean | CsrfOptions | undefined;\n /** Extra origins allowed to receive the token. */\n trustedOrigins?: readonly string[];\n /** Headers the caller already set. A CSRF header among them is never replaced. */\n headers?: HeadersInit;\n}\n\n/**\n * The CSRF header a request should carry, or an empty object.\n *\n * Every request path in the SDK — `createApiClient`, `uploadWithProgress`,\n * `createResumableUpload` — asks this function, so the rules are one rule:\n *\n * - **Off unless configured.** Without `csrf`, nothing changes.\n * - **Unsafe methods only.** `GET`, `HEAD`, `OPTIONS` and `TRACE` never carry\n * it; they must not change state, and a token in a `GET` ends up in logs\n * and caches for nothing.\n * - **Never across an origin.** The token follows the same scope as the bearer\n * credential ({@link isTrustedCredentialTarget}), because a URL can come off\n * the network — a tus `Location`, a pagination link — and a CSRF token sent\n * to a third party is a token that third party can replay. Withheld tokens\n * are reported once per origin in a development build.\n * - **Your header wins.** A CSRF header you set by hand, in any casing, is\n * left alone.\n * - **Independent of auth.** It is sent on `skipAuth` requests too: login and\n * refresh are exactly the writes a cookie session exposes to forgery.\n *\n * Exported for the request you build by hand, so it follows the same rules.\n *\n * @example\n * const headers = csrfHeaders({\n * method: \"POST\",\n * url: \"https://api.acme.com/orders\",\n * reference: \"https://api.acme.com\",\n * csrf: true,\n * });\n * // { \"X-CSRF-Token\": \"<value of the csrf_token cookie>\" }\n *\n * @param input - The request and the CSRF config.\n * @returns A header record to spread into the request's headers.\n */\nexport function csrfHeaders(input: CsrfHeadersInput): Record<string, string> {\n const { method, url, reference, csrf, trustedOrigins, headers } = input;\n if (!csrf) return {};\n if (SAFE_METHODS.has(method.toUpperCase())) return {};\n const options: CsrfOptions = csrf === true ? {} : csrf;\n const headerName = options.headerName ?? DEFAULT_CSRF_HEADER_NAME;\n if (hasHeader(headers, headerName)) return {};\n if (!isTrustedCredentialTarget(url, reference, trustedOrigins)) {\n reportSuppressedCredential(url, reference, headerName);\n return {};\n }\n const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;\n const token = options.getToken ? options.getToken() : readCookie(cookieName);\n if (!token) {\n reportMissingToken(options.getToken ? \"getToken\" : cookieName);\n return {};\n }\n return { [headerName]: token };\n}\n\n/**\n * Forget which token sources were already reported empty.\n *\n * Exported for tests, which assert the once-per-source behaviour and would\n * otherwise leak state between cases.\n */\nexport function resetCsrfReports(): void {\n reportedMissing.clear();\n}\n"],"mappings":";;;AAYA,IAAaA,IAA2B,cAQ3BC,IAA2B,gBAwClCC,oBAAoC,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAW;AAAO,CAAC,GAG/EC,oBAAkB,IAAI,IAAY;AAYxC,SAASC,EAAW,GAA6B;CAC7C,IAAI,OAAO,WAAa,KAAa,OAAO;CAC5C,IAAMC,IAAS,GAAGC,EAAK;CACvB,KAAK,IAAMC,KAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;EAC3C,IAAMC,IAAQD,EAAK,KAAK;EACxB,IAAI,CAACC,EAAM,WAAWH,CAAM,GAAG;EAC/B,IAAMI,IAAMD,EAAM,MAAMH,EAAO,MAAM;EACrC,IAAI;GACA,OAAO,mBAAmBI,CAAG;EACjC,QAAQ;GACJ,OAAOA;EACX;CACJ;CACA,OAAO;AACX;AAcA,SAASC,EAAmB,GAAsB;CAC9C,IAAI,CAACC,EAAW,KAAKR,EAAgB,IAAIS,CAAM,GAAG;CAClD,EAAgB,IAAIA,CAAM;CAC1B,IAAMC,IACFD,MAAW,aACL,qCACA,gBAAgBA,EAAO;CACjC,QAAQ,KACJ,2CAA2CC,EAAM,kHACrD;AACJ;AAaA,SAASC,EAAU,GAAkC,GAAuB;CAExE,OADKC,IACE,IAAI,QAAQA,CAAO,CAAC,CAAC,IAAIT,CAAI,IADf;AAEzB;AAuDA,SAAgBU,EAAY,GAAiD;CACzE,IAAM,EAAE,WAAQ,QAAK,cAAW,SAAM,mBAAgB,eAAYC;CAElE,IADI,CAACC,KACDhB,EAAa,IAAIiB,EAAO,YAAY,CAAC,GAAG,OAAO,CAAC;CACpD,IAAMC,IAAuBF,MAAS,KAAO,CAAC,IAAIA,GAC5CG,IAAaD,EAAQ,cAAA;CAC3B,IAAIN,EAAUC,GAASM,CAAU,GAAG,OAAO,CAAC;CAC5C,IAAI,CAACC,EAA0BC,GAAKC,GAAWC,CAAc,GAEzD,OADAC,EAA2BH,GAAKC,GAAWH,CAAU,GAC9C,CAAC;CAEZ,IAAMM,IAAaP,EAAQ,cAAA,cACrBQ,IAAQR,EAAQ,WAAWA,EAAQ,SAAS,IAAIhB,EAAWuB,CAAU;CAK3E,OAJKC,IAIE,GAAGP,IAAaO,EAAM,KAHzBlB,EAAmBU,EAAQ,WAAW,aAAaO,CAAU,GACtD,CAAC;AAGhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"decode-response.cjs","names":[],"sources":["../../src/http/decode-response.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Media-type fragments that name something safe to read as text, for the types\n * that do not open with `text/` — `application/xml`, `application/javascript`,\n * `application/x-www-form-urlencoded`.\n */\nconst TEXTUAL_TOKENS: readonly string[] = [\"xml\", \"javascript\", \"ecmascript\", \"urlencoded\", \"csv\"];\n\n/** How a {@link createApiClient} response body becomes the value a caller awaited. */\nexport type ResponseDecoder<T> = (response: Response) => Promise<T>;\n\n/**\n * Whether a `Content-Type` names a JSON dialect.\n *\n * Matches the suffix forms as well as the plain one, so `application/json`,\n * `application/problem+json` (RFC 9457, what a FastAPI error handler sends) and\n * `application/vnd.tempest.v2+json` all decode as JSON instead of falling\n * through to text.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.json()`.\n */\nexport function isJsonContentType(contentType: string): boolean {\n return contentType.toLowerCase().includes(\"json\");\n}\n\n/**\n * Whether a `Content-Type` names something that survives being read as text.\n *\n * An absent header counts as textual: a backend that answers without one is\n * almost always sending text, and treating it as binary would change what\n * existing callers get back for no measured gain.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.text()`.\n */\nexport function isTextualContentType(contentType: string): boolean {\n const type = contentType.trim().toLowerCase();\n if (type === \"\") return true;\n if (type.startsWith(\"text/\")) return true;\n return TEXTUAL_TOKENS.some((token) => type.includes(token));\n}\n\n/**\n * Warn, in a development build, that a binary body reached the JSON/text path.\n *\n * @param contentType - The `Content-Type` that was decoded as a `Blob`.\n */\nfunction warnBinaryBody(contentType: string): void {\n if (!isDevBuild()) return;\n console.warn(\n `[tempest] <ApiClient> received a binary response (content-type: ${contentType}) and returned a Blob. ` +\n \"Call `client.blob()` or `client.arrayBuffer()` so the type matches what arrives.\",\n );\n}\n\n/**\n * Decode a response the way its `Content-Type` asks to be decoded.\n *\n * JSON is parsed, text is read as text, and **everything else comes back as a\n * `Blob`**. That last branch is the fix for a silent data defect: the client\n * used to fall back to `response.text()` for any non-JSON body, so an\n * `image/jpeg` was decoded as UTF-8 and the bytes were destroyed on the way in.\n * Measured on a bare JPEG header — `ff d8 ff e0 00 10 4a 46 49 46` — the\n * round-trip through text returns 18 bytes for the 10 that arrived, 4 of them\n * replaced by `U+FFFD`. No caller can undo that, which is why the download had\n * to leave the client entirely.\n *\n * A `204` has no body at all and resolves to `undefined`, whatever the headers\n * claim.\n *\n * @typeParam T - What the caller expects back.\n * @param response - A response already known to be successful.\n * @returns The decoded body.\n */\nexport async function decodeByContentType<T>(response: Response): Promise<T> {\n if (response.status === 204) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (isJsonContentType(contentType)) {\n return (await response.json()) as T;\n }\n if (isTextualContentType(contentType)) {\n return (await response.text()) as unknown as T;\n }\n\n warnBinaryBody(contentType);\n return (await response.blob()) as unknown as T;\n}\n"],"mappings":"yCAOA,IAAM,EAAoC,CAAC,MAAO,aAAc,aAAc,aAAc,KAAK,EAgBjG,SAAgB,EAAkB,EAA8B,CAC5D,OAAO,EAAY,YAAY,CAAC,CAAC,SAAS,MAAM,CACpD,CAYA,SAAgB,EAAqB,EAA8B,CAC/D,IAAM,EAAO,EAAY,KAAK,CAAC,CAAC,YAAY,EAG5C,OAFI,IAAS,IACT,EAAK,WAAW,OAAO,EAAU,GAC9B,EAAe,KAAM,GAAU,EAAK,SAAS,CAAK,CAAC,CAC9D,CAOA,SAAS,EAAe,EAA2B,CAC1C,EAAA,WAAW,GAChB,QAAQ,KACJ,mEAAmE,EAAY,4GAEnF,CACJ,CAqBA,eAAsB,EAAuB,EAAgC,CACzE,GAAI,EAAS,SAAW,IACpB,OAGJ,IAAM,EAAc,EAAS,QAAQ,IAAI,cAAc,GAAK,GAS5D,OARI,EAAkB,CAAW,EACrB,MAAM,EAAS,KAAK,EAE5B,EAAqB,CAAW,EACxB,MAAM,EAAS,KAAK,GAGhC,EAAe,CAAW,EAClB,MAAM,EAAS,KAAK,EAChC"}
1
+ {"version":3,"file":"decode-response.cjs","names":["isDevBuild","require_dev_mode","TEXTUAL_TOKENS","isJsonContentType","contentType","isTextualContentType","type","token","warnBinaryBody","decodeByContentType","response"],"sources":["../../src/http/decode-response.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Media-type fragments that name something safe to read as text, for the types\n * that do not open with `text/` — `application/xml`, `application/javascript`,\n * `application/x-www-form-urlencoded`.\n */\nconst TEXTUAL_TOKENS: readonly string[] = [\"xml\", \"javascript\", \"ecmascript\", \"urlencoded\", \"csv\"];\n\n/** How a {@link createApiClient} response body becomes the value a caller awaited. */\nexport type ResponseDecoder<T> = (response: Response) => Promise<T>;\n\n/**\n * Whether a `Content-Type` names a JSON dialect.\n *\n * Matches the suffix forms as well as the plain one, so `application/json`,\n * `application/problem+json` (RFC 9457, what a FastAPI error handler sends) and\n * `application/vnd.tempest.v2+json` all decode as JSON instead of falling\n * through to text.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.json()`.\n */\nexport function isJsonContentType(contentType: string): boolean {\n return contentType.toLowerCase().includes(\"json\");\n}\n\n/**\n * Whether a `Content-Type` names something that survives being read as text.\n *\n * An absent header counts as textual: a backend that answers without one is\n * almost always sending text, and treating it as binary would change what\n * existing callers get back for no measured gain.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.text()`.\n */\nexport function isTextualContentType(contentType: string): boolean {\n const type = contentType.trim().toLowerCase();\n if (type === \"\") return true;\n if (type.startsWith(\"text/\")) return true;\n return TEXTUAL_TOKENS.some((token) => type.includes(token));\n}\n\n/**\n * Warn, in a development build, that a binary body reached the JSON/text path.\n *\n * @param contentType - The `Content-Type` that was decoded as a `Blob`.\n */\nfunction warnBinaryBody(contentType: string): void {\n if (!isDevBuild()) return;\n console.warn(\n `[tempest] <ApiClient> received a binary response (content-type: ${contentType}) and returned a Blob. ` +\n \"Call `client.blob()` or `client.arrayBuffer()` so the type matches what arrives.\",\n );\n}\n\n/**\n * Decode a response the way its `Content-Type` asks to be decoded.\n *\n * JSON is parsed, text is read as text, and **everything else comes back as a\n * `Blob`**. That last branch is the fix for a silent data defect: the client\n * used to fall back to `response.text()` for any non-JSON body, so an\n * `image/jpeg` was decoded as UTF-8 and the bytes were destroyed on the way in.\n * Measured on a bare JPEG header — `ff d8 ff e0 00 10 4a 46 49 46` — the\n * round-trip through text returns 18 bytes for the 10 that arrived, 4 of them\n * replaced by `U+FFFD`. No caller can undo that, which is why the download had\n * to leave the client entirely.\n *\n * A `204` has no body at all and resolves to `undefined`, whatever the headers\n * claim.\n *\n * @typeParam T - What the caller expects back.\n * @param response - A response already known to be successful.\n * @returns The decoded body.\n */\nexport async function decodeByContentType<T>(response: Response): Promise<T> {\n if (response.status === 204) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (isJsonContentType(contentType)) {\n return (await response.json()) as T;\n }\n if (isTextualContentType(contentType)) {\n return (await response.text()) as unknown as T;\n }\n\n warnBinaryBody(contentType);\n return (await response.blob()) as unknown as T;\n}\n"],"mappings":"A,yCAOA,IAAME,EAAoC,CAAC,MAAO,aAAc,aAAc,aAAc,KAAK,EAgBjG,SAAgBC,EAAkB,EAA8B,CAC5D,OAAOC,EAAY,YAAY,CAAC,CAAC,SAAS,MAAM,CACpD,CAYA,SAAgBC,EAAqB,EAA8B,CAC/D,IAAMC,EAAOF,EAAY,KAAK,CAAC,CAAC,YAAY,EAG5C,OAFIE,IAAS,IACTA,EAAK,WAAW,OAAO,EAAU,GAC9BJ,EAAe,KAAM,GAAUI,EAAK,SAASC,CAAK,CAAC,CAC9D,CAOA,SAASC,EAAe,EAA2B,CAC1CR,EAAAA,WAAW,GAChB,QAAQ,KACJ,mEAAmEI,EAAY,4GAEnF,CACJ,CAqBA,eAAsBK,EAAuB,EAAgC,CACzE,GAAIC,EAAS,SAAW,IACpB,OAGJ,IAAMN,EAAcM,EAAS,QAAQ,IAAI,cAAc,GAAK,GAS5D,OARIP,EAAkBC,CAAW,EACrB,MAAMM,EAAS,KAAK,EAE5BL,EAAqBD,CAAW,EACxB,MAAMM,EAAS,KAAK,GAGhCF,EAAeJ,CAAW,EAClB,MAAMM,EAAS,KAAK,EAChC,C"}