@salla.sa/twilight-theme-engine 1.0.133 → 1.0.135

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 (274) hide show
  1. package/dist/{AddToCartForm-2BD3R4BH.js → AddToCartForm-ODVZPTKN.js} +3 -3
  2. package/dist/{AddToCartForm-2BD3R4BH.js.map → AddToCartForm-ODVZPTKN.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-BF5XVPHV.js → BlogAuthorPage-BU23SINI.js} +29 -29
  4. package/dist/{BlogAuthorPage-BF5XVPHV.js.map → BlogAuthorPage-BU23SINI.js.map} +1 -1
  5. package/dist/{BlogCategoryPage-BZTNFEM7.js → BlogCategoryPage-ZVITUHP4.js} +29 -29
  6. package/dist/{BlogCategoryPage-BZTNFEM7.js.map → BlogCategoryPage-ZVITUHP4.js.map} +1 -1
  7. package/dist/{BlogPage-7HOCNIL5.js → BlogPage-IN3V7FYK.js} +27 -27
  8. package/dist/{BlogPage-7HOCNIL5.js.map → BlogPage-IN3V7FYK.js.map} +1 -1
  9. package/dist/{BlogSinglePage-SF575W74.js → BlogSinglePage-UJG7YPYZ.js} +27 -27
  10. package/dist/{BlogSinglePage-SF575W74.js.map → BlogSinglePage-UJG7YPYZ.js.map} +1 -1
  11. package/dist/{BlogTagPage-TALXABAF.js → BlogTagPage-XDETNKGR.js} +29 -29
  12. package/dist/{BlogTagPage-TALXABAF.js.map → BlogTagPage-XDETNKGR.js.map} +1 -1
  13. package/dist/{BrandsPage-UNHLTVUG.js → BrandsPage-CBU7JFSX.js} +28 -28
  14. package/dist/{BrandsPage-UNHLTVUG.js.map → BrandsPage-CBU7JFSX.js.map} +1 -1
  15. package/dist/{Breadcrumb-VFMPAWSR.js → Breadcrumb-EA2XETAM.js} +27 -27
  16. package/dist/{Breadcrumb-VFMPAWSR.js.map → Breadcrumb-EA2XETAM.js.map} +1 -1
  17. package/dist/{CartItem-CI2XOVRH.js → CartItem-2TW36QTW.js} +27 -27
  18. package/dist/{CartItem-CI2XOVRH.js.map → CartItem-2TW36QTW.js.map} +1 -1
  19. package/dist/{CartSummary-EQOBVLXK.js → CartSummary-TW2CAX57.js} +27 -27
  20. package/dist/{CartSummary-EQOBVLXK.js.map → CartSummary-TW2CAX57.js.map} +1 -1
  21. package/dist/{Copyright-3JGEXCQZ.js → Copyright-57XPE75X.js} +3 -3
  22. package/dist/{Copyright-3JGEXCQZ.js.map → Copyright-57XPE75X.js.map} +1 -1
  23. package/dist/{CustomerLayout-V5T4OPRY.js → CustomerLayout-A2M7IY34.js} +27 -27
  24. package/dist/{CustomerLayout-V5T4OPRY.js.map → CustomerLayout-A2M7IY34.js.map} +1 -1
  25. package/dist/{Footer-QX4EO5Y4.js → Footer-L5BIYCZ2.js} +4 -4
  26. package/dist/{Footer-QX4EO5Y4.js.map → Footer-L5BIYCZ2.js.map} +1 -1
  27. package/dist/Header-NLBDW4MR.js +23 -0
  28. package/dist/{Header-ORMIZKUL.js.map → Header-NLBDW4MR.js.map} +1 -1
  29. package/dist/{LoyaltyPage-HCLFYNTM.js → LoyaltyPage-BVTDPSP3.js} +27 -27
  30. package/dist/{LoyaltyPage-HCLFYNTM.js.map → LoyaltyPage-BVTDPSP3.js.map} +1 -1
  31. package/dist/{LoyaltyPointsPage-V5OWHGR5.js → LoyaltyPointsPage-HZYPCO7C.js} +9 -9
  32. package/dist/{LoyaltyPointsPage-V5OWHGR5.js.map → LoyaltyPointsPage-HZYPCO7C.js.map} +1 -1
  33. package/dist/{MainMenu-RX7PU77H.js → MainMenu-3HP3YJDH.js} +8 -8
  34. package/dist/{MainMenu-RX7PU77H.js.map → MainMenu-3HP3YJDH.js.map} +1 -1
  35. package/dist/MaintenancePage-U5P43D52.js +7 -0
  36. package/dist/{MaintenancePage-A7CNHM7B.js.map → MaintenancePage-U5P43D52.js.map} +1 -1
  37. package/dist/{MasterLayout-CTVC6FPX.js → MasterLayout-KD3GLYYX.js} +27 -27
  38. package/dist/{MasterLayout-CTVC6FPX.js.map → MasterLayout-KD3GLYYX.js.map} +1 -1
  39. package/dist/{MobileMenu-EQFL7JGB.js → MobileMenu-3UEQTURY.js} +28 -28
  40. package/dist/{MobileMenu-EQFL7JGB.js.map → MobileMenu-3UEQTURY.js.map} +1 -1
  41. package/dist/{NotificationsPage-ZBZNPTZS.js → NotificationsPage-C6LNYZTB.js} +27 -27
  42. package/dist/{NotificationsPage-ZBZNPTZS.js.map → NotificationsPage-C6LNYZTB.js.map} +1 -1
  43. package/dist/{OrderSinglePage-LMWLOLW2.js → OrderSinglePage-LXKINOXP.js} +28 -28
  44. package/dist/{OrderSinglePage-LMWLOLW2.js.map → OrderSinglePage-LXKINOXP.js.map} +1 -1
  45. package/dist/{OrdersPage-6G7BES7J.js → OrdersPage-VBF3P3JH.js} +27 -27
  46. package/dist/{OrdersPage-6G7BES7J.js.map → OrdersPage-VBF3P3JH.js.map} +1 -1
  47. package/dist/{PageSingle-5TPYMYII.js → PageSingle-E7DTNIY7.js} +7 -7
  48. package/dist/{PageSingle-5TPYMYII.js.map → PageSingle-E7DTNIY7.js.map} +1 -1
  49. package/dist/{ProductDetails-JHZ2ZJAA.js → ProductDetails-ZQLQWU7S.js} +8 -8
  50. package/dist/{ProductDetails-JHZ2ZJAA.js.map → ProductDetails-ZQLQWU7S.js.map} +1 -1
  51. package/dist/{ProfilePage-6JITWBAJ.js → ProfilePage-7LAIDEHS.js} +27 -27
  52. package/dist/{ProfilePage-6JITWBAJ.js.map → ProfilePage-7LAIDEHS.js.map} +1 -1
  53. package/dist/{ReviewsPage-PFMEZ27R.js → ReviewsPage-FA3V745S.js} +3 -3
  54. package/dist/{ReviewsPage-PFMEZ27R.js.map → ReviewsPage-FA3V745S.js.map} +1 -1
  55. package/dist/{SeoCartWidget-ZU3ZZRQB.js → SeoCartWidget-4456ASOT.js} +27 -27
  56. package/dist/{SeoCartWidget-ZU3ZZRQB.js.map → SeoCartWidget-4456ASOT.js.map} +1 -1
  57. package/dist/{SettingsPage-J5AF6ECW.js → SettingsPage-IVOHCXVY.js} +27 -27
  58. package/dist/{SettingsPage-J5AF6ECW.js.map → SettingsPage-IVOHCXVY.js.map} +1 -1
  59. package/dist/StoreClosedNotification-DIF6SKBX.js +58 -0
  60. package/dist/{StoreClosedNotification-3FYHHAIP.js.map → StoreClosedNotification-DIF6SKBX.js.map} +1 -1
  61. package/dist/{TestimonialsPage-4Y55RF5P.js → TestimonialsPage-JY7MF5NW.js} +7 -7
  62. package/dist/{TestimonialsPage-4Y55RF5P.js.map → TestimonialsPage-JY7MF5NW.js.map} +1 -1
  63. package/dist/{ThankYouPage-WETHDHC2.js → ThankYouPage-KNHHBFPZ.js} +27 -27
  64. package/dist/{ThankYouPage-WETHDHC2.js.map → ThankYouPage-KNHHBFPZ.js.map} +1 -1
  65. package/dist/{WalletPage-PSTUYDCC.js → WalletPage-HH72DHOC.js} +28 -28
  66. package/dist/{WalletPage-PSTUYDCC.js.map → WalletPage-HH72DHOC.js.map} +1 -1
  67. package/dist/{WishlistPage-AROQHMZ2.js → WishlistPage-5BR63SMU.js} +29 -29
  68. package/dist/{WishlistPage-AROQHMZ2.js.map → WishlistPage-5BR63SMU.js.map} +1 -1
  69. package/dist/ambient/salla-components.d.ts +5 -0
  70. package/dist/api/advertisement.js +5 -5
  71. package/dist/api/apps.js +5 -5
  72. package/dist/api/blog.js +7 -7
  73. package/dist/api/brands.js +7 -7
  74. package/dist/api/cart.js +7 -7
  75. package/dist/api/category.js +7 -7
  76. package/dist/api/client.js +4 -4
  77. package/dist/api/home.js +5 -5
  78. package/dist/api/loyalty.js +7 -7
  79. package/dist/api/menu.js +5 -5
  80. package/dist/api/notification.js +5 -5
  81. package/dist/api/order.js +7 -7
  82. package/dist/api/page.js +7 -7
  83. package/dist/api/product.js +7 -7
  84. package/dist/api/profile.js +4 -4
  85. package/dist/api/store.js +6 -6
  86. package/dist/api/translations.js +5 -5
  87. package/dist/api/user.js +5 -5
  88. package/dist/api/wallet.js +5 -5
  89. package/dist/api/wishlist.js +8 -8
  90. package/dist/{chunk-WBPOWM74.js → chunk-25UDBM27.js} +4 -4
  91. package/dist/{chunk-WBPOWM74.js.map → chunk-25UDBM27.js.map} +1 -1
  92. package/dist/{chunk-XQLAAPWR.js → chunk-2GSYVPQS.js} +7 -7
  93. package/dist/{chunk-XQLAAPWR.js.map → chunk-2GSYVPQS.js.map} +1 -1
  94. package/dist/{chunk-2TLIULJZ.js → chunk-3E3ABCPC.js} +3 -3
  95. package/dist/{chunk-2TLIULJZ.js.map → chunk-3E3ABCPC.js.map} +1 -1
  96. package/dist/{chunk-HTV4KO7G.js → chunk-4CM6JIQF.js} +3 -3
  97. package/dist/{chunk-HTV4KO7G.js.map → chunk-4CM6JIQF.js.map} +1 -1
  98. package/dist/{chunk-U2I3W3KW.js → chunk-4NZKBANW.js} +4 -4
  99. package/dist/{chunk-U2I3W3KW.js.map → chunk-4NZKBANW.js.map} +1 -1
  100. package/dist/{chunk-OOLS535M.js → chunk-4SCGS2CM.js} +7 -7
  101. package/dist/{chunk-OOLS535M.js.map → chunk-4SCGS2CM.js.map} +1 -1
  102. package/dist/{chunk-XN77EK3X.js → chunk-5A37NING.js} +4 -4
  103. package/dist/{chunk-XN77EK3X.js.map → chunk-5A37NING.js.map} +1 -1
  104. package/dist/{chunk-ETQFCKGR.js → chunk-5AOW2SQW.js} +3 -3
  105. package/dist/{chunk-ETQFCKGR.js.map → chunk-5AOW2SQW.js.map} +1 -1
  106. package/dist/{chunk-EHTLXK5F.js → chunk-5UWRPWK2.js} +5 -5
  107. package/dist/{chunk-EHTLXK5F.js.map → chunk-5UWRPWK2.js.map} +1 -1
  108. package/dist/{chunk-7VNVCHID.js → chunk-6K34BCUP.js} +2 -2
  109. package/dist/{chunk-7VNVCHID.js.map → chunk-6K34BCUP.js.map} +1 -1
  110. package/dist/{chunk-QIJJTWW6.js → chunk-6VYW7CVL.js} +4 -4
  111. package/dist/{chunk-QIJJTWW6.js.map → chunk-6VYW7CVL.js.map} +1 -1
  112. package/dist/{chunk-JUFJV4AK.js → chunk-7U5OLKOS.js} +3 -3
  113. package/dist/{chunk-JUFJV4AK.js.map → chunk-7U5OLKOS.js.map} +1 -1
  114. package/dist/{chunk-B3DGM7TM.js → chunk-A5AU64GV.js} +4 -4
  115. package/dist/{chunk-B3DGM7TM.js.map → chunk-A5AU64GV.js.map} +1 -1
  116. package/dist/{chunk-GG5DAIGJ.js → chunk-AXWX5SJC.js} +5 -5
  117. package/dist/{chunk-GG5DAIGJ.js.map → chunk-AXWX5SJC.js.map} +1 -1
  118. package/dist/{chunk-CKH6WBMA.js → chunk-CZ6VJPCG.js} +3 -3
  119. package/dist/{chunk-CKH6WBMA.js.map → chunk-CZ6VJPCG.js.map} +1 -1
  120. package/dist/{chunk-F5BU7T6H.js → chunk-D53M5ASN.js} +7 -7
  121. package/dist/{chunk-F5BU7T6H.js.map → chunk-D53M5ASN.js.map} +1 -1
  122. package/dist/{chunk-RQG44QD7.js → chunk-E5DP3MHE.js} +6 -6
  123. package/dist/{chunk-RQG44QD7.js.map → chunk-E5DP3MHE.js.map} +1 -1
  124. package/dist/{chunk-FHU2MXZA.js → chunk-FXVII733.js} +18 -8
  125. package/dist/chunk-FXVII733.js.map +1 -0
  126. package/dist/{chunk-VSEMOZZY.js → chunk-HDSY5DWF.js} +3 -3
  127. package/dist/{chunk-VSEMOZZY.js.map → chunk-HDSY5DWF.js.map} +1 -1
  128. package/dist/{chunk-Z6E7MMXW.js → chunk-HIOYW3CS.js} +4 -4
  129. package/dist/{chunk-Z6E7MMXW.js.map → chunk-HIOYW3CS.js.map} +1 -1
  130. package/dist/{chunk-BK5TBUGG.js → chunk-HOJ5E2PG.js} +3 -3
  131. package/dist/{chunk-BK5TBUGG.js.map → chunk-HOJ5E2PG.js.map} +1 -1
  132. package/dist/{chunk-G3UTLR3D.js → chunk-IOLNWPRO.js} +4 -4
  133. package/dist/{chunk-G3UTLR3D.js.map → chunk-IOLNWPRO.js.map} +1 -1
  134. package/dist/{chunk-33UM6VQJ.js → chunk-KWJUCI7M.js} +4 -4
  135. package/dist/{chunk-33UM6VQJ.js.map → chunk-KWJUCI7M.js.map} +1 -1
  136. package/dist/{chunk-JGVEGQHJ.js → chunk-LFHYQ6AN.js} +3 -3
  137. package/dist/{chunk-JGVEGQHJ.js.map → chunk-LFHYQ6AN.js.map} +1 -1
  138. package/dist/{chunk-BYLNAYIZ.js → chunk-LUPDYN4T.js} +5 -5
  139. package/dist/{chunk-BYLNAYIZ.js.map → chunk-LUPDYN4T.js.map} +1 -1
  140. package/dist/{chunk-NVL6M25Q.js → chunk-MWG734P7.js} +3 -3
  141. package/dist/{chunk-NVL6M25Q.js.map → chunk-MWG734P7.js.map} +1 -1
  142. package/dist/{chunk-V2M5YNZQ.js → chunk-MWYKP7CI.js} +3 -3
  143. package/dist/{chunk-V2M5YNZQ.js.map → chunk-MWYKP7CI.js.map} +1 -1
  144. package/dist/{chunk-GYXUYHKO.js → chunk-NHA4SBKG.js} +4 -4
  145. package/dist/{chunk-GYXUYHKO.js.map → chunk-NHA4SBKG.js.map} +1 -1
  146. package/dist/{chunk-37O7OVPL.js → chunk-OJKTKMWS.js} +4 -4
  147. package/dist/{chunk-37O7OVPL.js.map → chunk-OJKTKMWS.js.map} +1 -1
  148. package/dist/chunk-OKKS2RA4.js +14 -0
  149. package/dist/{chunk-JYEUOEEI.js.map → chunk-OKKS2RA4.js.map} +1 -1
  150. package/dist/{chunk-QGKARX6O.js → chunk-P3D67RVR.js} +8 -8
  151. package/dist/{chunk-QGKARX6O.js.map → chunk-P3D67RVR.js.map} +1 -1
  152. package/dist/{chunk-MBSWV56J.js → chunk-P6TJCCM3.js} +4 -4
  153. package/dist/{chunk-MBSWV56J.js.map → chunk-P6TJCCM3.js.map} +1 -1
  154. package/dist/{chunk-FID76MUV.js → chunk-Q7E4TNN7.js} +10 -6
  155. package/dist/chunk-Q7E4TNN7.js.map +1 -0
  156. package/dist/{chunk-LDQGZ4R2.js → chunk-RBXGVURD.js} +4 -4
  157. package/dist/{chunk-LDQGZ4R2.js.map → chunk-RBXGVURD.js.map} +1 -1
  158. package/dist/{chunk-4UEXSD7E.js → chunk-RLJLG4EN.js} +6 -6
  159. package/dist/{chunk-4UEXSD7E.js.map → chunk-RLJLG4EN.js.map} +1 -1
  160. package/dist/{chunk-OM2GRPDH.js → chunk-RYGEIQWO.js} +3 -3
  161. package/dist/{chunk-OM2GRPDH.js.map → chunk-RYGEIQWO.js.map} +1 -1
  162. package/dist/{chunk-7ED3XSYN.js → chunk-SGB7HCXF.js} +4 -4
  163. package/dist/{chunk-7ED3XSYN.js.map → chunk-SGB7HCXF.js.map} +1 -1
  164. package/dist/{chunk-PCEKL6S3.js → chunk-SXI2XBCC.js} +7 -7
  165. package/dist/{chunk-PCEKL6S3.js.map → chunk-SXI2XBCC.js.map} +1 -1
  166. package/dist/{chunk-L4TQBWR7.js → chunk-TF6HFXTW.js} +3 -3
  167. package/dist/{chunk-L4TQBWR7.js.map → chunk-TF6HFXTW.js.map} +1 -1
  168. package/dist/{chunk-VSP3INDK.js → chunk-TTLRRVM2.js} +7 -7
  169. package/dist/{chunk-VSP3INDK.js.map → chunk-TTLRRVM2.js.map} +1 -1
  170. package/dist/{chunk-P2WO5CNH.js → chunk-UHGDQIIF.js} +5 -5
  171. package/dist/{chunk-P2WO5CNH.js.map → chunk-UHGDQIIF.js.map} +1 -1
  172. package/dist/{chunk-L55G7FJZ.js → chunk-VNDUKDZG.js} +38 -10
  173. package/dist/chunk-VNDUKDZG.js.map +1 -0
  174. package/dist/{chunk-HIGI3M7E.js → chunk-VZPEPWDF.js} +9 -9
  175. package/dist/{chunk-HIGI3M7E.js.map → chunk-VZPEPWDF.js.map} +1 -1
  176. package/dist/{chunk-KLJTNLZ5.js → chunk-WEKO2DAN.js} +5 -5
  177. package/dist/{chunk-KLJTNLZ5.js.map → chunk-WEKO2DAN.js.map} +1 -1
  178. package/dist/{chunk-RSRGLHVQ.js → chunk-WHFKJ3AS.js} +4 -4
  179. package/dist/{chunk-RSRGLHVQ.js.map → chunk-WHFKJ3AS.js.map} +1 -1
  180. package/dist/{chunk-5FJFN3IW.js → chunk-WQPG22DY.js} +3 -3
  181. package/dist/{chunk-5FJFN3IW.js.map → chunk-WQPG22DY.js.map} +1 -1
  182. package/dist/{chunk-Z2K2O3DI.js → chunk-WVSGVFMM.js} +4 -4
  183. package/dist/{chunk-Z2K2O3DI.js.map → chunk-WVSGVFMM.js.map} +1 -1
  184. package/dist/{chunk-JYV25VNZ.js → chunk-X55R4VVK.js} +3 -3
  185. package/dist/{chunk-JYV25VNZ.js.map → chunk-X55R4VVK.js.map} +1 -1
  186. package/dist/{chunk-IPICQKIF.js → chunk-X5QZBD5V.js} +7 -7
  187. package/dist/{chunk-IPICQKIF.js.map → chunk-X5QZBD5V.js.map} +1 -1
  188. package/dist/{chunk-TLOA4BJF.js → chunk-XHWBJYJL.js} +3 -3
  189. package/dist/{chunk-TLOA4BJF.js.map → chunk-XHWBJYJL.js.map} +1 -1
  190. package/dist/{chunk-PAMMBDFM.js → chunk-YBIL64R7.js} +3 -3
  191. package/dist/{chunk-PAMMBDFM.js.map → chunk-YBIL64R7.js.map} +1 -1
  192. package/dist/{chunk-4SM6UKLE.js → chunk-YJWJPS25.js} +17 -17
  193. package/dist/chunk-YJWJPS25.js.map +1 -0
  194. package/dist/{chunk-N4YBKFJM.js → chunk-YKNDXZAD.js} +24 -24
  195. package/dist/chunk-YKNDXZAD.js.map +1 -0
  196. package/dist/{chunk-SQBLVCES.js → chunk-ZRJXN766.js} +4 -4
  197. package/dist/{chunk-SQBLVCES.js.map → chunk-ZRJXN766.js.map} +1 -1
  198. package/dist/components/cart/index.js +1 -1
  199. package/dist/components/common/index.js +1 -1
  200. package/dist/components/drawer/index.js +25 -25
  201. package/dist/components/home/BundleComponent.d.ts +3 -0
  202. package/dist/components/home/BundleComponent.d.ts.map +1 -1
  203. package/dist/components/home/index.js +29 -29
  204. package/dist/components/layout/index.js +7 -7
  205. package/dist/components/product/index.js +26 -26
  206. package/dist/components/store/index.js +27 -27
  207. package/dist/components/toast/index.js +5 -5
  208. package/dist/dev/editor/index.js +3 -3
  209. package/dist/dev/index.js +3 -3
  210. package/dist/document-class-3GOSUA4H.js +31 -0
  211. package/dist/{document-class-4DT4LTK5.js.map → document-class-3GOSUA4H.js.map} +1 -1
  212. package/dist/hooks/index.js +25 -25
  213. package/dist/hooks/useComments.js +4 -4
  214. package/dist/hooks/useGtm.js +25 -25
  215. package/dist/hooks/useMoney.js +25 -25
  216. package/dist/hooks/useProduct.js +4 -4
  217. package/dist/hooks/useStore.js +25 -25
  218. package/dist/hooks/useUser.js +6 -6
  219. package/dist/hooks/useWishlist.js +4 -4
  220. package/dist/index.js +25 -25
  221. package/dist/native-app/index.js +4 -4
  222. package/dist/{navigation-FTU3OC4V.js → navigation-SN2ZTS4V.js} +8 -8
  223. package/dist/{navigation-FTU3OC4V.js.map → navigation-SN2ZTS4V.js.map} +1 -1
  224. package/dist/navigation-ZV4TGIAA.js +15 -0
  225. package/dist/{navigation-DT6HXCUG.js.map → navigation-ZV4TGIAA.js.map} +1 -1
  226. package/dist/{not-found-BVJSPRMZ.js → not-found-J3UJVHNJ.js} +28 -28
  227. package/dist/{not-found-BVJSPRMZ.js.map → not-found-J3UJVHNJ.js.map} +1 -1
  228. package/dist/providers/index.js +25 -25
  229. package/dist/providers/twilight-init.d.ts.map +1 -1
  230. package/dist/routes/account/orders.js +9 -9
  231. package/dist/routes/account.js +18 -18
  232. package/dist/routes/blog.js +13 -13
  233. package/dist/routes/brands.js +9 -9
  234. package/dist/routes/cart.js +33 -33
  235. package/dist/routes/home.js +30 -30
  236. package/dist/routes/index.js +7 -7
  237. package/dist/routes/loyalty.js +10 -10
  238. package/dist/routes/page.js +9 -9
  239. package/dist/routes/product-listing.js +31 -31
  240. package/dist/routes/product.js +29 -29
  241. package/dist/routes/root/beforeLoad.d.ts +6 -0
  242. package/dist/routes/root/beforeLoad.d.ts.map +1 -1
  243. package/dist/routes/seo-redirects.js +7 -7
  244. package/dist/routes/testimonials.js +5 -5
  245. package/dist/routes/thank-you.js +9 -9
  246. package/dist/skeleton.js +30 -30
  247. package/dist/{store-lookup-OWYYSCDT.js → store-lookup-U6TJNLZM.js} +12 -12
  248. package/dist/{store-lookup-OWYYSCDT.js.map → store-lookup-U6TJNLZM.js.map} +1 -1
  249. package/dist/tanstack.js +22 -22
  250. package/dist/twilight/context.d.ts +3 -2
  251. package/dist/twilight/context.d.ts.map +1 -1
  252. package/dist/utils/baseHead.js +3 -3
  253. package/dist/utils/cookies.d.ts +15 -1
  254. package/dist/utils/cookies.d.ts.map +1 -1
  255. package/dist/utils/index.js +7 -7
  256. package/dist/utils/maintenance.d.ts +37 -5
  257. package/dist/utils/maintenance.d.ts.map +1 -1
  258. package/dist/utils/store-identity.d.ts +10 -0
  259. package/dist/utils/store-identity.d.ts.map +1 -1
  260. package/dist/vite/index.js +5 -5
  261. package/package.json +1 -1
  262. package/tailwind/components/home/BundleComponent.tsx.txt +46 -3
  263. package/tailwind/routes/root/beforeLoad.ts.txt +8 -1
  264. package/dist/Header-ORMIZKUL.js +0 -23
  265. package/dist/MaintenancePage-A7CNHM7B.js +0 -7
  266. package/dist/StoreClosedNotification-3FYHHAIP.js +0 -58
  267. package/dist/chunk-4SM6UKLE.js.map +0 -1
  268. package/dist/chunk-FHU2MXZA.js.map +0 -1
  269. package/dist/chunk-FID76MUV.js.map +0 -1
  270. package/dist/chunk-JYEUOEEI.js +0 -14
  271. package/dist/chunk-L55G7FJZ.js.map +0 -1
  272. package/dist/chunk-N4YBKFJM.js.map +0 -1
  273. package/dist/document-class-4DT4LTK5.js +0 -31
  274. package/dist/navigation-DT6HXCUG.js +0 -15
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tanstack/link.tsx","../src/tanstack/native-app-events.tsx","../src/utils/request-host.ts","../src/tanstack/navigation.tsx"],"names":["TanStackLink","tanstackNotFound","tanstackRedirect","useParams","jsx"],"mappings":"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","file":"chunk-OOLS535M.js","sourcesContent":["import { forwardRef, createElement } from 'react';\nimport { Link as TanStackLink, useParams } from '@tanstack/react-router';\nimport { isLocale } from '../providers/locale-constants';\nimport type { BaseLinkProps } from '../components/common/Link.types';\n\n/**\n * Routes live under an optional `/{-$locale}` param, so a bare `to=\"/brands\"`\n * resolves with the locale omitted and the $locale loader bounces the user to\n * the fallback locale. Prefix the current locale onto internal paths that\n * don't already carry one.\n */\nexport function localizeDestination(destination: string, locale?: string) {\n if (!locale || !destination.startsWith('/') || destination.startsWith('//')) return destination;\n const firstSegment = destination.split('/')[1]?.split(/[?#]/)[0];\n if (isLocale(firstSegment)) return destination;\n return destination === '/' ? `/${locale}` : `/${locale}${destination}`;\n}\n\n/**\n * TanStack Router Link adapter.\n * Translates framework-agnostic props to TanStack Router Link props.\n */\nexport const TanStackLinkAdapter = forwardRef<HTMLAnchorElement, BaseLinkProps>(\n (\n {\n to,\n href,\n children,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload,\n replace,\n 'aria-label': ariaLabel,\n ...rest\n },\n ref\n ) => {\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const destination = localizeDestination(to ?? href ?? '/', locale);\n\n return createElement(\n TanStackLink,\n {\n ref,\n to: destination,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload: preload === 'intent' || preload === false ? preload : undefined,\n replace,\n 'aria-label': ariaLabel,\n ...(rest as Record<string, unknown>),\n },\n children\n );\n }\n);\n\nTanStackLinkAdapter.displayName = 'TanStackLinkAdapter';\n\n/**\n * Create a TanStack Router Link adapter component.\n */\nexport function createTanStackLinkAdapter() {\n return TanStackLinkAdapter;\n}\n","import { useEffect } from 'react';\nimport { useRouter } from '@tanstack/react-router';\nimport { resolveRelativePath } from '../providers/NavigationProvider';\nimport { useTwilight } from '../providers/twilight-context';\nimport { isLocale } from '../providers/locale-constants';\nimport { getTwilightContext } from '../twilight/context';\nimport { useIsNativeApp } from '../native-app';\nimport { onSallaEvent } from '../utils/sdk-helpers';\nimport { hasStoreUrlBase } from '../utils/store-base';\nimport { localizeDestination } from './link';\n\nconst UI_UPDATE_EVENT = 'mobile::ui.update';\nconst OPEN_ORDER_EVENT = 'mobile::open.order';\nconst NAVIGATE_TO_EVENT = 'mobile::navigate.to';\n\n/**\n * Events the native app sends into its webview. `NavigationSetup` mounts this once, so a\n * theme adds no listener of its own:\n *\n * - `mobile::ui.update` re-runs the route loaders and refetches what is on screen.\n * - `mobile::open.order` `{ id }` opens that order, with a fresh cart.\n * - `mobile::navigate.to` `{ url }` opens a notification deep link in-app. Only a link to\n * this store is followed (`deepLinkPath`), so `javascript:`, off-site and other stores'\n * URLs are dropped.\n *\n * Nothing is mounted outside the app (`useIsNativeApp()`), so a browser runs none of it.\n */\nexport function NativeAppEvents({ locale }: { locale?: string }) {\n return useIsNativeApp() ? <Listeners locale={locale} /> : null;\n}\n\nfunction Listeners({ locale }: { locale?: string }) {\n useNativeAppEvents(locale);\n return null;\n}\n\n/** The listeners themselves. `NativeAppEvents` mounts them inside the app only. */\nexport function useNativeAppEvents(locale?: string): void {\n const router = useRouter();\n const { store } = useTwilight();\n const storeUrl = store?.url;\n const username = store?.username;\n\n useEffect(() => {\n // `href`, not `to`: the router parses the query and the hash out of it.\n const open = (path: string) =>\n void router.navigate({ href: localizeDestination(path, locale) });\n\n const refresh = () => {\n void Promise.allSettled([\n router.invalidate(),\n getTwilightContext().queryClient?.refetchQueries({ type: 'active' }),\n ]);\n };\n const openOrder = (data?: unknown) => {\n const rawId = (data as { id?: unknown } | undefined)?.id;\n if (typeof rawId !== 'string' && typeof rawId !== 'number') return;\n\n const id = String(rawId).trim();\n if (!id) return;\n\n void getTwilightContext().queryClient?.invalidateQueries({ queryKey: ['cart'] });\n open(`/account/orders/${encodeURIComponent(id)}`);\n };\n const navigateTo = (data?: unknown) => {\n const url = (data as { url?: unknown } | undefined)?.url;\n if (typeof url !== 'string' || !url.trim() || !storeUrl) return;\n\n const path = deepLinkPath(url.trim(), storeUrl, username);\n if (path) void router.navigate({ href: inLocale(path, locale) });\n };\n\n const offs = [\n onSallaEvent(UI_UPDATE_EVENT, refresh),\n onSallaEvent(OPEN_ORDER_EVENT, openOrder),\n onSallaEvent(NAVIGATE_TO_EVENT, navigateTo),\n ];\n return () => offs.forEach((off) => off());\n }, [router, locale, storeUrl, username]);\n}\n\n/** A URL that names its host: `https://…` or `//…`. Anything else is a path of this app. */\nfunction isAbsoluteUrl(url: string): boolean {\n if (url.startsWith('//')) return true;\n try {\n // Without a base, only a URL with its own scheme parses.\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The application path of a deep link to this store, or null for any other link.\n *\n * It passes the test a tapped link does (`resolveRelativePath`: the store's origin, the\n * username taken off), and one more. On a shared host that origin is every store's, so\n * an absolute link has to carry this store's username: without it, another store's\n * `/ar/offers` would open this store's offers.\n */\nfunction deepLinkPath(url: string, storeUrl: string, username?: string): string | null {\n const path = resolveRelativePath(url, storeUrl, username);\n if (!path || !isAbsoluteUrl(url)) return path;\n\n // Both parse: `resolveRelativePath` returns null when either does not.\n const { pathname } = new URL(url, window.location.href);\n return hasStoreUrlBase(pathname, new URL(storeUrl).pathname, username) ? path : null;\n}\n\n/**\n * A deep link in the locale the visitor is browsing in. A notification is written in one\n * language and opened in whichever is on screen, so the link's own locale gives way.\n *\n * The prefix is written here, not by `localizeDestination`: that one leaves a path alone\n * when it already starts with a locale, and would take the slug of `/ar/en/p456` for one.\n */\nfunction inLocale(path: string, locale?: string): string {\n const first = path.split('/')[1]?.split(/[?#]/)[0];\n const own = isLocale(first) ? path.slice(first.length + 1) : path;\n const rest = own.startsWith('/') ? own : `/${own}`;\n\n if (!locale) return rest;\n return rest === '/' ? `/${locale}` : `/${locale}${rest}`;\n}\n","/**\n * What the request itself is enough to describe: its host.\n *\n * Small, and deliberately its own module rather than a helper inside the\n * middleware. This value decides two things — which store a live storefront is,\n * and whether the request is allowed to name a store at all — so it is worth\n * testing directly instead of only through the wiring that calls it.\n */\nimport { isLoopback } from './cookies';\n\n/** The part of a `Request` this needs, so a test does not have to build a whole one. */\nexport interface HostSource {\n url: string;\n headers: { get(name: string): string | null };\n}\n\n/**\n * The host this request arrived on, with its port when it has one.\n *\n * Taken from the request URL, which in a Worker is the address the platform\n * actually routed on, and from the `Host` header only when that fails.\n *\n * **`X-Forwarded-Host` is deliberately not consulted.** A client can set it, and\n * this value gates `allowsRequestStoreId` — so honouring it would be a way to\n * talk a merchant's own domain into behaving like the preview host, and from\n * there into serving a stranger's shop. The dispatcher strips that header today;\n * a theme must not be one edit to another repository's allowlist away from a\n * spoofable identity.\n */\nexport function requestHostOf(request: HostSource): string | null {\n try {\n const fromUrl = new URL(request.url).host;\n if (fromUrl) return fromUrl;\n } catch {\n /* an unparseable URL falls through to the header */\n }\n\n return request.headers.get('Host')?.trim() || null;\n}\n\n/** The origin a browser reached this host on: `http` for a dev server, `https` otherwise. */\nexport function requestOriginOf(host: string): string {\n return `${isLoopback(host.replace(/:\\d+$/, '')) ? 'http' : 'https'}://${host}`;\n}\n","import {\n useNavigate,\n useParams,\n redirect as tanstackRedirect,\n notFound as tanstackNotFound,\n} from '@tanstack/react-router';\nimport {\n NavigationProvider,\n configureNavigation,\n type NavigateOptions,\n} from '../providers/NavigationProvider';\nimport { LinkProvider } from '../providers/LinkProvider';\nimport { TanStackLinkAdapter, localizeDestination } from './link';\nimport { NativeAppEvents } from './native-app-events';\nimport { useCallback, type ReactNode } from 'react';\nimport { UnauthorizedError, type RedirectOptions } from '../providers/NavigationProvider';\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport { resolveStoreBase, resolveStoreBaseFollowsLocale } from '../utils/store-identity';\nimport { loginRedirectHref } from '../utils/store-base';\nimport { requestOriginOf } from '../utils/request-host';\n\nfunction currentOrigin(): string | null {\n if (typeof window !== 'undefined') return window.location.origin;\n const host = getRequestStore().requestHost;\n return host ? requestOriginOf(host) : null;\n}\n\nconfigureNavigation({\n notFound: (message?: string) => {\n throw tanstackNotFound({ data: message });\n },\n redirect: (path: string, opts?: RedirectOptions) => {\n throw tanstackRedirect({ to: path, replace: opts?.replace, statusCode: opts?.statusCode });\n },\n unauthorized: (message?: string) => {\n const origin = currentOrigin();\n const { pathname, searchStr } = getTwilightContext().location;\n const href =\n origin &&\n loginRedirectHref({\n pathname,\n searchStr,\n origin,\n base: resolveStoreBase(),\n baseFollowsLocale: resolveStoreBaseFollowsLocale(),\n });\n // A full load, because the SDK only reads `intended_to` when a page starts.\n if (href) throw tanstackRedirect({ href, reloadDocument: true, replace: true });\n throw new UnauthorizedError(message);\n },\n});\n\n/**\n * TanStack navigation setup - wraps children with NavigationProvider and LinkProvider.\n * Called by TwilightProvider when client.framework === 'tanstack'.\n */\nexport function NavigationSetup({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const navigateFn = useCallback(\n (to: string, opts?: NavigateOptions) =>\n navigate({ to: localizeDestination(to, locale), replace: opts?.replace }),\n [navigate, locale]\n );\n\n return (\n <NavigationProvider navigate={navigateFn}>\n <NativeAppEvents locale={locale} />\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n\n/** @deprecated Use NavigationSetup instead */\nexport function TanStackNavigationProvider({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n return (\n <NavigationProvider\n navigate={(to: string, opts?: NavigateOptions) => navigate({ to, replace: opts?.replace })}\n >\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/tanstack/link.tsx","../src/tanstack/native-app-events.tsx","../src/utils/request-host.ts","../src/tanstack/navigation.tsx"],"names":["TanStackLink","tanstackNotFound","tanstackRedirect","useParams","jsx"],"mappings":"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","file":"chunk-4SCGS2CM.js","sourcesContent":["import { forwardRef, createElement } from 'react';\nimport { Link as TanStackLink, useParams } from '@tanstack/react-router';\nimport { isLocale } from '../providers/locale-constants';\nimport type { BaseLinkProps } from '../components/common/Link.types';\n\n/**\n * Routes live under an optional `/{-$locale}` param, so a bare `to=\"/brands\"`\n * resolves with the locale omitted and the $locale loader bounces the user to\n * the fallback locale. Prefix the current locale onto internal paths that\n * don't already carry one.\n */\nexport function localizeDestination(destination: string, locale?: string) {\n if (!locale || !destination.startsWith('/') || destination.startsWith('//')) return destination;\n const firstSegment = destination.split('/')[1]?.split(/[?#]/)[0];\n if (isLocale(firstSegment)) return destination;\n return destination === '/' ? `/${locale}` : `/${locale}${destination}`;\n}\n\n/**\n * TanStack Router Link adapter.\n * Translates framework-agnostic props to TanStack Router Link props.\n */\nexport const TanStackLinkAdapter = forwardRef<HTMLAnchorElement, BaseLinkProps>(\n (\n {\n to,\n href,\n children,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload,\n replace,\n 'aria-label': ariaLabel,\n ...rest\n },\n ref\n ) => {\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const destination = localizeDestination(to ?? href ?? '/', locale);\n\n return createElement(\n TanStackLink,\n {\n ref,\n to: destination,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload: preload === 'intent' || preload === false ? preload : undefined,\n replace,\n 'aria-label': ariaLabel,\n ...(rest as Record<string, unknown>),\n },\n children\n );\n }\n);\n\nTanStackLinkAdapter.displayName = 'TanStackLinkAdapter';\n\n/**\n * Create a TanStack Router Link adapter component.\n */\nexport function createTanStackLinkAdapter() {\n return TanStackLinkAdapter;\n}\n","import { useEffect } from 'react';\nimport { useRouter } from '@tanstack/react-router';\nimport { resolveRelativePath } from '../providers/NavigationProvider';\nimport { useTwilight } from '../providers/twilight-context';\nimport { isLocale } from '../providers/locale-constants';\nimport { getTwilightContext } from '../twilight/context';\nimport { useIsNativeApp } from '../native-app';\nimport { onSallaEvent } from '../utils/sdk-helpers';\nimport { hasStoreUrlBase } from '../utils/store-base';\nimport { localizeDestination } from './link';\n\nconst UI_UPDATE_EVENT = 'mobile::ui.update';\nconst OPEN_ORDER_EVENT = 'mobile::open.order';\nconst NAVIGATE_TO_EVENT = 'mobile::navigate.to';\n\n/**\n * Events the native app sends into its webview. `NavigationSetup` mounts this once, so a\n * theme adds no listener of its own:\n *\n * - `mobile::ui.update` re-runs the route loaders and refetches what is on screen.\n * - `mobile::open.order` `{ id }` opens that order, with a fresh cart.\n * - `mobile::navigate.to` `{ url }` opens a notification deep link in-app. Only a link to\n * this store is followed (`deepLinkPath`), so `javascript:`, off-site and other stores'\n * URLs are dropped.\n *\n * Nothing is mounted outside the app (`useIsNativeApp()`), so a browser runs none of it.\n */\nexport function NativeAppEvents({ locale }: { locale?: string }) {\n return useIsNativeApp() ? <Listeners locale={locale} /> : null;\n}\n\nfunction Listeners({ locale }: { locale?: string }) {\n useNativeAppEvents(locale);\n return null;\n}\n\n/** The listeners themselves. `NativeAppEvents` mounts them inside the app only. */\nexport function useNativeAppEvents(locale?: string): void {\n const router = useRouter();\n const { store } = useTwilight();\n const storeUrl = store?.url;\n const username = store?.username;\n\n useEffect(() => {\n // `href`, not `to`: the router parses the query and the hash out of it.\n const open = (path: string) =>\n void router.navigate({ href: localizeDestination(path, locale) });\n\n const refresh = () => {\n void Promise.allSettled([\n router.invalidate(),\n getTwilightContext().queryClient?.refetchQueries({ type: 'active' }),\n ]);\n };\n const openOrder = (data?: unknown) => {\n const rawId = (data as { id?: unknown } | undefined)?.id;\n if (typeof rawId !== 'string' && typeof rawId !== 'number') return;\n\n const id = String(rawId).trim();\n if (!id) return;\n\n void getTwilightContext().queryClient?.invalidateQueries({ queryKey: ['cart'] });\n open(`/account/orders/${encodeURIComponent(id)}`);\n };\n const navigateTo = (data?: unknown) => {\n const url = (data as { url?: unknown } | undefined)?.url;\n if (typeof url !== 'string' || !url.trim() || !storeUrl) return;\n\n const path = deepLinkPath(url.trim(), storeUrl, username);\n if (path) void router.navigate({ href: inLocale(path, locale) });\n };\n\n const offs = [\n onSallaEvent(UI_UPDATE_EVENT, refresh),\n onSallaEvent(OPEN_ORDER_EVENT, openOrder),\n onSallaEvent(NAVIGATE_TO_EVENT, navigateTo),\n ];\n return () => offs.forEach((off) => off());\n }, [router, locale, storeUrl, username]);\n}\n\n/** A URL that names its host: `https://…` or `//…`. Anything else is a path of this app. */\nfunction isAbsoluteUrl(url: string): boolean {\n if (url.startsWith('//')) return true;\n try {\n // Without a base, only a URL with its own scheme parses.\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The application path of a deep link to this store, or null for any other link.\n *\n * It passes the test a tapped link does (`resolveRelativePath`: the store's origin, the\n * username taken off), and one more. On a shared host that origin is every store's, so\n * an absolute link has to carry this store's username: without it, another store's\n * `/ar/offers` would open this store's offers.\n */\nfunction deepLinkPath(url: string, storeUrl: string, username?: string): string | null {\n const path = resolveRelativePath(url, storeUrl, username);\n if (!path || !isAbsoluteUrl(url)) return path;\n\n // Both parse: `resolveRelativePath` returns null when either does not.\n const { pathname } = new URL(url, window.location.href);\n return hasStoreUrlBase(pathname, new URL(storeUrl).pathname, username) ? path : null;\n}\n\n/**\n * A deep link in the locale the visitor is browsing in. A notification is written in one\n * language and opened in whichever is on screen, so the link's own locale gives way.\n *\n * The prefix is written here, not by `localizeDestination`: that one leaves a path alone\n * when it already starts with a locale, and would take the slug of `/ar/en/p456` for one.\n */\nfunction inLocale(path: string, locale?: string): string {\n const first = path.split('/')[1]?.split(/[?#]/)[0];\n const own = isLocale(first) ? path.slice(first.length + 1) : path;\n const rest = own.startsWith('/') ? own : `/${own}`;\n\n if (!locale) return rest;\n return rest === '/' ? `/${locale}` : `/${locale}${rest}`;\n}\n","/**\n * What the request itself is enough to describe: its host.\n *\n * Small, and deliberately its own module rather than a helper inside the\n * middleware. This value decides two things — which store a live storefront is,\n * and whether the request is allowed to name a store at all — so it is worth\n * testing directly instead of only through the wiring that calls it.\n */\nimport { isLoopback } from './cookies';\n\n/** The part of a `Request` this needs, so a test does not have to build a whole one. */\nexport interface HostSource {\n url: string;\n headers: { get(name: string): string | null };\n}\n\n/**\n * The host this request arrived on, with its port when it has one.\n *\n * Taken from the request URL, which in a Worker is the address the platform\n * actually routed on, and from the `Host` header only when that fails.\n *\n * **`X-Forwarded-Host` is deliberately not consulted.** A client can set it, and\n * this value gates `allowsRequestStoreId` — so honouring it would be a way to\n * talk a merchant's own domain into behaving like the preview host, and from\n * there into serving a stranger's shop. The dispatcher strips that header today;\n * a theme must not be one edit to another repository's allowlist away from a\n * spoofable identity.\n */\nexport function requestHostOf(request: HostSource): string | null {\n try {\n const fromUrl = new URL(request.url).host;\n if (fromUrl) return fromUrl;\n } catch {\n /* an unparseable URL falls through to the header */\n }\n\n return request.headers.get('Host')?.trim() || null;\n}\n\n/** The origin a browser reached this host on: `http` for a dev server, `https` otherwise. */\nexport function requestOriginOf(host: string): string {\n return `${isLoopback(host.replace(/:\\d+$/, '')) ? 'http' : 'https'}://${host}`;\n}\n","import {\n useNavigate,\n useParams,\n redirect as tanstackRedirect,\n notFound as tanstackNotFound,\n} from '@tanstack/react-router';\nimport {\n NavigationProvider,\n configureNavigation,\n type NavigateOptions,\n} from '../providers/NavigationProvider';\nimport { LinkProvider } from '../providers/LinkProvider';\nimport { TanStackLinkAdapter, localizeDestination } from './link';\nimport { NativeAppEvents } from './native-app-events';\nimport { useCallback, type ReactNode } from 'react';\nimport { UnauthorizedError, type RedirectOptions } from '../providers/NavigationProvider';\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport { resolveStoreBase, resolveStoreBaseFollowsLocale } from '../utils/store-identity';\nimport { loginRedirectHref } from '../utils/store-base';\nimport { requestOriginOf } from '../utils/request-host';\n\nfunction currentOrigin(): string | null {\n if (typeof window !== 'undefined') return window.location.origin;\n const host = getRequestStore().requestHost;\n return host ? requestOriginOf(host) : null;\n}\n\nconfigureNavigation({\n notFound: (message?: string) => {\n throw tanstackNotFound({ data: message });\n },\n redirect: (path: string, opts?: RedirectOptions) => {\n throw tanstackRedirect({ to: path, replace: opts?.replace, statusCode: opts?.statusCode });\n },\n unauthorized: (message?: string) => {\n const origin = currentOrigin();\n const { pathname, searchStr } = getTwilightContext().location;\n const href =\n origin &&\n loginRedirectHref({\n pathname,\n searchStr,\n origin,\n base: resolveStoreBase(),\n baseFollowsLocale: resolveStoreBaseFollowsLocale(),\n });\n // A full load, because the SDK only reads `intended_to` when a page starts.\n if (href) throw tanstackRedirect({ href, reloadDocument: true, replace: true });\n throw new UnauthorizedError(message);\n },\n});\n\n/**\n * TanStack navigation setup - wraps children with NavigationProvider and LinkProvider.\n * Called by TwilightProvider when client.framework === 'tanstack'.\n */\nexport function NavigationSetup({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const navigateFn = useCallback(\n (to: string, opts?: NavigateOptions) =>\n navigate({ to: localizeDestination(to, locale), replace: opts?.replace }),\n [navigate, locale]\n );\n\n return (\n <NavigationProvider navigate={navigateFn}>\n <NativeAppEvents locale={locale} />\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n\n/** @deprecated Use NavigationSetup instead */\nexport function TanStackNavigationProvider({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n return (\n <NavigationProvider\n navigate={(to: string, opts?: NavigateOptions) => navigate({ to, replace: opts?.replace })}\n >\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { getActiveScope, api } from './chunk-RQG44QD7.js';
2
- import { getTwilightContext } from './chunk-7VNVCHID.js';
1
+ import { getActiveScope, api } from './chunk-E5DP3MHE.js';
2
+ import { getTwilightContext } from './chunk-6K34BCUP.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
5
5
  function advertisementsFor(ads, pageSlug) {
@@ -25,5 +25,5 @@ var advertisement = {
25
25
  };
26
26
 
27
27
  export { advertisement, advertisementsFor };
28
- //# sourceMappingURL=chunk-XN77EK3X.js.map
29
- //# sourceMappingURL=chunk-XN77EK3X.js.map
28
+ //# sourceMappingURL=chunk-5A37NING.js.map
29
+ //# sourceMappingURL=chunk-5A37NING.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/advertisement.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAA,CACd,KACA,QAAA,EACiB;AACjB,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACT,CAAC,EAAA,KACC,KAAA,CAAM,QAAQ,EAAA,CAAG,KAAK,MACrB,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,KAAK,KAAM,CAAC,CAAC,YAAY,EAAA,CAAG,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,GAC1E;AACF;AAEO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,MAAM,YAAsC;AAE1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,gBAAA,EAAkB,EAAE,OAAA,EAAS,GAAA,EAAM,CAAA,CACvC,IAAA,EAAiC;AACpC,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,OAAO,EAAC;AAAA,EACvC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,gBAAA,EAAkB,kBAAA,EAAmB,CAAE,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MACrF,OAAA,EAAS,MAAM,aAAA,CAAc,IAAA,EAAK;AAAA,MAClC,SAAA,EAAW,QAAA;AAAA;AAAA,MAEX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-XN77EK3X.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport { getTwilightContext } from '../twilight/context';\n\n/** A merchant's announcement bar, as `GET advertisements` returns it. */\nexport interface Advertisement {\n id: number;\n title?: string;\n description?: string;\n icon?: string | null;\n url?: string | null;\n target?: string | null;\n colors?: { bg?: string; text?: string };\n /** Page slugs the ad shows on (`salla.config` `page.slug`), or `all`. */\n pages?: string[];\n}\n\n/** The ads a page shows: the rule the API applies to `?page=`, run on the full list. */\nexport function advertisementsFor(\n ads: readonly Advertisement[],\n pageSlug: string | null | undefined\n): Advertisement[] {\n return ads.filter(\n (ad) =>\n Array.isArray(ad.pages) &&\n (ad.pages.includes('all') || (!!pageSlug && ad.pages.includes(pageSlug)))\n );\n}\n\nexport const advertisement = {\n /** Every active ad, unfiltered: one request serves all pages, filtered with `advertisementsFor`. */\n list: async (): Promise<Advertisement[]> => {\n // Short timeout: it is fetched with the store settings on every server render.\n const { data } = await api\n .get('advertisements', { timeout: 3000 })\n .json<{ data?: Advertisement[] }>();\n return Array.isArray(data) ? data : [];\n },\n\n queries: {\n list: () =>\n queryOptions({\n queryKey: ['advertisements', getTwilightContext().locale, { scope: getActiveScope() }],\n queryFn: () => advertisement.list(),\n staleTime: Infinity,\n // Awaited in rootBeforeLoad: a retry would double the 3s budget. `PageAdvertisements` retries.\n retry: 0,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/advertisement.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAA,CACd,KACA,QAAA,EACiB;AACjB,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACT,CAAC,EAAA,KACC,KAAA,CAAM,QAAQ,EAAA,CAAG,KAAK,MACrB,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,KAAK,KAAM,CAAC,CAAC,YAAY,EAAA,CAAG,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,GAC1E;AACF;AAEO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,MAAM,YAAsC;AAE1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,gBAAA,EAAkB,EAAE,OAAA,EAAS,GAAA,EAAM,CAAA,CACvC,IAAA,EAAiC;AACpC,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,OAAO,EAAC;AAAA,EACvC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,gBAAA,EAAkB,kBAAA,EAAmB,CAAE,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MACrF,OAAA,EAAS,MAAM,aAAA,CAAc,IAAA,EAAK;AAAA,MAClC,SAAA,EAAW,QAAA;AAAA;AAAA,MAEX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-5A37NING.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport { getTwilightContext } from '../twilight/context';\n\n/** A merchant's announcement bar, as `GET advertisements` returns it. */\nexport interface Advertisement {\n id: number;\n title?: string;\n description?: string;\n icon?: string | null;\n url?: string | null;\n target?: string | null;\n colors?: { bg?: string; text?: string };\n /** Page slugs the ad shows on (`salla.config` `page.slug`), or `all`. */\n pages?: string[];\n}\n\n/** The ads a page shows: the rule the API applies to `?page=`, run on the full list. */\nexport function advertisementsFor(\n ads: readonly Advertisement[],\n pageSlug: string | null | undefined\n): Advertisement[] {\n return ads.filter(\n (ad) =>\n Array.isArray(ad.pages) &&\n (ad.pages.includes('all') || (!!pageSlug && ad.pages.includes(pageSlug)))\n );\n}\n\nexport const advertisement = {\n /** Every active ad, unfiltered: one request serves all pages, filtered with `advertisementsFor`. */\n list: async (): Promise<Advertisement[]> => {\n // Short timeout: it is fetched with the store settings on every server render.\n const { data } = await api\n .get('advertisements', { timeout: 3000 })\n .json<{ data?: Advertisement[] }>();\n return Array.isArray(data) ? data : [];\n },\n\n queries: {\n list: () =>\n queryOptions({\n queryKey: ['advertisements', getTwilightContext().locale, { scope: getActiveScope() }],\n queryFn: () => advertisement.list(),\n staleTime: Infinity,\n // Awaited in rootBeforeLoad: a retry would double the 3s budget. `PageAdvertisements` retries.\n retry: 0,\n }),\n },\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { api } from './chunk-RQG44QD7.js';
1
+ import { api } from './chunk-E5DP3MHE.js';
2
2
 
3
3
  // src/api/wallet.ts
4
4
  var wallet = {
@@ -20,5 +20,5 @@ var wallet = {
20
20
  };
21
21
 
22
22
  export { wallet };
23
- //# sourceMappingURL=chunk-ETQFCKGR.js.map
24
- //# sourceMappingURL=chunk-ETQFCKGR.js.map
23
+ //# sourceMappingURL=chunk-5AOW2SQW.js.map
24
+ //# sourceMappingURL=chunk-5AOW2SQW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-ETQFCKGR.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-5AOW2SQW.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
@@ -1,6 +1,6 @@
1
- import { ensureTwilightContextFromMatches } from './chunk-JYV25VNZ.js';
2
- import { storePageUrl } from './chunk-OM2GRPDH.js';
3
- import { getTwilightContext, SettingsError } from './chunk-7VNVCHID.js';
1
+ import { ensureTwilightContextFromMatches } from './chunk-X55R4VVK.js';
2
+ import { storePageUrl } from './chunk-RYGEIQWO.js';
3
+ import { getTwilightContext, SettingsError } from './chunk-6K34BCUP.js';
4
4
 
5
5
  // src/tanstack/head.ts
6
6
  function normalizeOgImages(images) {
@@ -125,5 +125,5 @@ function withHead(route, extend) {
125
125
  }
126
126
 
127
127
  export { tanstackHeadAdapter, withHead };
128
- //# sourceMappingURL=chunk-EHTLXK5F.js.map
129
- //# sourceMappingURL=chunk-EHTLXK5F.js.map
128
+ //# sourceMappingURL=chunk-5UWRPWK2.js.map
129
+ //# sourceMappingURL=chunk-5UWRPWK2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tanstack/head.ts"],"names":[],"mappings":"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","file":"chunk-EHTLXK5F.js","sourcesContent":["import type { HeadDescriptor, OpenGraphImage } from '../utils/head';\nimport type { TwilightContext } from '../twilight/context';\nimport { getTwilightContext } from '../twilight/context';\nimport type { TwilightContextMatch } from '../twilight/ensure-context';\nimport { ensureTwilightContextFromMatches } from '../twilight/ensure-context';\nimport { SettingsError } from '../utils/errors';\nimport { storePageUrl } from '../utils/baseHead';\n\ntype OgImagesInput = string | OpenGraphImage | Array<string | OpenGraphImage> | undefined;\n\nfunction normalizeOgImages(images: OgImagesInput): OpenGraphImage[] {\n if (!images) return [];\n const arr = Array.isArray(images) ? images : [images];\n return arr.map((img) => (typeof img === 'string' ? { url: img } : img));\n}\n\n/** Merchant descriptions are rich-text HTML; description meta tags take plain text. */\nfunction plainText(html: string): string {\n return html\n .replace(/<br\\s*\\/?>|<\\/(?:p|div|li|h[1-6])>/gi, ' ')\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nexport function tanstackHeadAdapter(descriptor: HeadDescriptor) {\n const meta: Array<Record<string, unknown>> = [];\n const links: Array<Record<string, unknown>> = [];\n const scripts: Array<Record<string, unknown>> = [];\n const styles: Record<string, unknown>[] = [];\n\n if (descriptor.title) meta.push({ title: descriptor.title });\n if (descriptor.description)\n meta.push({ name: 'description', content: plainText(descriptor.description) });\n\n if (descriptor.keywords) {\n const kw = Array.isArray(descriptor.keywords)\n ? descriptor.keywords.join(', ')\n : descriptor.keywords;\n meta.push({ name: 'keywords', content: kw });\n }\n\n if (descriptor.robots) meta.push({ name: 'robots', content: descriptor.robots });\n\n // Open Graph\n const og = descriptor.openGraph;\n if (og) {\n if (og.siteName) meta.push({ property: 'og:site_name', content: og.siteName });\n if (og.type) meta.push({ property: 'og:type', content: og.type });\n if (og.title) meta.push({ property: 'og:title', content: og.title });\n if (og.description)\n meta.push({ property: 'og:description', content: plainText(og.description) });\n if (og.url) meta.push({ property: 'og:url', content: og.url });\n if (og.locale) meta.push({ property: 'og:locale', content: og.locale });\n for (const alt of og.alternateLocale ?? []) {\n meta.push({ property: 'og:locale:alternate', content: alt });\n }\n for (const img of normalizeOgImages(og.images)) {\n meta.push({ property: 'og:image', content: img.url });\n if (img.width != null) meta.push({ property: 'og:image:width', content: String(img.width) });\n if (img.height != null)\n meta.push({ property: 'og:image:height', content: String(img.height) });\n if (img.alt) meta.push({ property: 'og:image:alt', content: img.alt });\n }\n if (og.publishedTime)\n meta.push({ property: 'article:published_time', content: og.publishedTime });\n if (og.modifiedTime) meta.push({ property: 'article:modified_time', content: og.modifiedTime });\n }\n\n // Twitter Card\n const tw = descriptor.twitter;\n if (tw) {\n if (tw.card) meta.push({ name: 'twitter:card', content: tw.card });\n if (tw.title) meta.push({ name: 'twitter:title', content: tw.title });\n if (tw.description)\n meta.push({ name: 'twitter:description', content: plainText(tw.description) });\n if (tw.site) meta.push({ name: 'twitter:site', content: tw.site });\n if (tw.creator) meta.push({ name: 'twitter:creator', content: tw.creator });\n if (tw.url) meta.push({ name: 'twitter:url', content: tw.url });\n const twImages = tw.images ? (Array.isArray(tw.images) ? tw.images : [tw.images]) : [];\n for (const img of twImages) {\n meta.push({ name: 'twitter:image', content: img });\n }\n }\n\n // Canonical\n if (descriptor.canonical) links.push({ rel: 'canonical', href: descriptor.canonical });\n\n // hreflang alternates (React requires camelCase: hrefLang)\n for (const alt of descriptor.alternateLanguages ?? []) {\n links.push({ rel: 'alternate', hrefLang: alt.hreflang, href: alt.href });\n }\n\n // JSON-LD\n if (descriptor.jsonLd) {\n scripts.push({ type: 'application/ld+json', children: JSON.stringify(descriptor.jsonLd) });\n }\n\n // Escape hatches\n for (const m of descriptor.meta ?? []) {\n const { httpEquiv, ...rest } = m as typeof m & { httpEquiv?: string };\n meta.push(httpEquiv ? { httpEquiv, ...rest } : rest);\n }\n for (const l of descriptor.links ?? []) links.push(l);\n for (const s of descriptor.styles ?? []) styles.push(s as unknown as Record<string, unknown>);\n\n // Import maps must be emitted before module scripts that rely on bare specifiers.\n for (const im of descriptor.importMap ?? []) {\n scripts.push({ type: 'importmap', children: JSON.stringify(im) });\n }\n for (const s of descriptor.scripts ?? []) scripts.push(s);\n\n return { meta, links, styles, scripts };\n}\n\n// ============================================================================\n// withHead - Simplified head callback wrapper for TanStack Router\n// ============================================================================\n\n/** Twig's page title format: \"<page title> - <store meta title or store name>\". */\nfunction appendStoreTitle(\n descriptor: HeadDescriptor,\n settings: TwilightContext['settings']\n): HeadDescriptor {\n const store = settings?.store;\n const storeTitle = store?.meta?.title || store?.name;\n const pageTitle = descriptor.title;\n if (!pageTitle || !storeTitle || descriptor.appendStoreTitle === false) return descriptor;\n if (pageTitle === storeTitle) return descriptor;\n\n const title = `${pageTitle} - ${storeTitle}`;\n // Share titles follow the page title too, unless the route set its own.\n const shareTitle = (current?: string) => (!current || current === pageTitle ? title : current);\n return {\n ...descriptor,\n title,\n openGraph: { ...descriptor.openGraph, title: shareTitle(descriptor.openGraph?.title) },\n twitter: { ...descriptor.twitter, title: shareTitle(descriptor.twitter?.title) },\n };\n}\n\n/**\n * Twig's page URL for a page that names none: its own path on the store's domain, without the\n * query, as the canonical and the og:url and twitter:url share cards read.\n */\nfunction withPageUrl(descriptor: HeadDescriptor, ctx: TwilightContext): HeadDescriptor {\n const pathname = ctx.location?.pathname;\n const canonical =\n descriptor.canonical ?? (pathname ? storePageUrl(ctx.settings, pathname) : undefined);\n if (!canonical) return descriptor;\n return {\n ...descriptor,\n canonical,\n openGraph: { ...descriptor.openGraph, url: descriptor.openGraph?.url ?? canonical },\n twitter: { ...descriptor.twitter, url: descriptor.twitter?.url ?? canonical },\n };\n}\n\n/**\n * Minimal shape we need from TanStack Router's AssetFnContextOptions.\n * `loaderData` feeds the route's own head function; `matches` is the recovery\n * source for store settings when the twilight module store is not populated yet\n * (see `ensureTwilightContextFromMatches`).\n */\ntype HeadContext = {\n loaderData?: unknown;\n matches?: readonly TwilightContextMatch[];\n};\n\n/**\n * Wraps a route module's head function for TanStack Router.\n *\n * @example\n * ```typescript\n * head: withHead(Offers)\n * head: withHead(Product, (result) => ({ ...result, robots: 'noindex, follow' }))\n * ```\n */\nexport function withHead<T>(\n route: { head: (ctx: TwilightContext, data: T) => HeadDescriptor },\n extend?: (result: HeadDescriptor, _ctx: TwilightContext, data: T) => HeadDescriptor\n): (_ctx: Record<string, unknown>) => Record<string, unknown> {\n return (ctx: HeadContext) => {\n const loaderData = ctx.loaderData;\n\n if (!loaderData) return {};\n\n // TanStack re-runs every matched route's head() during client hydration,\n // where the twilight module store can still be empty. Recover it from the\n // match context TanStack has already resolved before giving up.\n ensureTwilightContextFromMatches(ctx.matches);\n\n try {\n const context = getTwilightContext();\n const result = route.head(context, loaderData as T);\n const extended = extend ? extend(result, context, loaderData as T) : result;\n const finalResult = withPageUrl(appendStoreTitle(extended, context.settings), context);\n\n return tanstackHeadAdapter(finalResult);\n } catch (error) {\n // A head function must never throw: TanStack surfaces the throw as a\n // hydration error, React then discards the server-rendered tree and the\n // storefront renders blank. Dropping this route's head tags degrades\n // gracefully — the server-rendered ones stay in the document.\n if (error instanceof SettingsError) return {};\n throw error;\n }\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/tanstack/head.ts"],"names":[],"mappings":"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","file":"chunk-5UWRPWK2.js","sourcesContent":["import type { HeadDescriptor, OpenGraphImage } from '../utils/head';\nimport type { TwilightContext } from '../twilight/context';\nimport { getTwilightContext } from '../twilight/context';\nimport type { TwilightContextMatch } from '../twilight/ensure-context';\nimport { ensureTwilightContextFromMatches } from '../twilight/ensure-context';\nimport { SettingsError } from '../utils/errors';\nimport { storePageUrl } from '../utils/baseHead';\n\ntype OgImagesInput = string | OpenGraphImage | Array<string | OpenGraphImage> | undefined;\n\nfunction normalizeOgImages(images: OgImagesInput): OpenGraphImage[] {\n if (!images) return [];\n const arr = Array.isArray(images) ? images : [images];\n return arr.map((img) => (typeof img === 'string' ? { url: img } : img));\n}\n\n/** Merchant descriptions are rich-text HTML; description meta tags take plain text. */\nfunction plainText(html: string): string {\n return html\n .replace(/<br\\s*\\/?>|<\\/(?:p|div|li|h[1-6])>/gi, ' ')\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nexport function tanstackHeadAdapter(descriptor: HeadDescriptor) {\n const meta: Array<Record<string, unknown>> = [];\n const links: Array<Record<string, unknown>> = [];\n const scripts: Array<Record<string, unknown>> = [];\n const styles: Record<string, unknown>[] = [];\n\n if (descriptor.title) meta.push({ title: descriptor.title });\n if (descriptor.description)\n meta.push({ name: 'description', content: plainText(descriptor.description) });\n\n if (descriptor.keywords) {\n const kw = Array.isArray(descriptor.keywords)\n ? descriptor.keywords.join(', ')\n : descriptor.keywords;\n meta.push({ name: 'keywords', content: kw });\n }\n\n if (descriptor.robots) meta.push({ name: 'robots', content: descriptor.robots });\n\n // Open Graph\n const og = descriptor.openGraph;\n if (og) {\n if (og.siteName) meta.push({ property: 'og:site_name', content: og.siteName });\n if (og.type) meta.push({ property: 'og:type', content: og.type });\n if (og.title) meta.push({ property: 'og:title', content: og.title });\n if (og.description)\n meta.push({ property: 'og:description', content: plainText(og.description) });\n if (og.url) meta.push({ property: 'og:url', content: og.url });\n if (og.locale) meta.push({ property: 'og:locale', content: og.locale });\n for (const alt of og.alternateLocale ?? []) {\n meta.push({ property: 'og:locale:alternate', content: alt });\n }\n for (const img of normalizeOgImages(og.images)) {\n meta.push({ property: 'og:image', content: img.url });\n if (img.width != null) meta.push({ property: 'og:image:width', content: String(img.width) });\n if (img.height != null)\n meta.push({ property: 'og:image:height', content: String(img.height) });\n if (img.alt) meta.push({ property: 'og:image:alt', content: img.alt });\n }\n if (og.publishedTime)\n meta.push({ property: 'article:published_time', content: og.publishedTime });\n if (og.modifiedTime) meta.push({ property: 'article:modified_time', content: og.modifiedTime });\n }\n\n // Twitter Card\n const tw = descriptor.twitter;\n if (tw) {\n if (tw.card) meta.push({ name: 'twitter:card', content: tw.card });\n if (tw.title) meta.push({ name: 'twitter:title', content: tw.title });\n if (tw.description)\n meta.push({ name: 'twitter:description', content: plainText(tw.description) });\n if (tw.site) meta.push({ name: 'twitter:site', content: tw.site });\n if (tw.creator) meta.push({ name: 'twitter:creator', content: tw.creator });\n if (tw.url) meta.push({ name: 'twitter:url', content: tw.url });\n const twImages = tw.images ? (Array.isArray(tw.images) ? tw.images : [tw.images]) : [];\n for (const img of twImages) {\n meta.push({ name: 'twitter:image', content: img });\n }\n }\n\n // Canonical\n if (descriptor.canonical) links.push({ rel: 'canonical', href: descriptor.canonical });\n\n // hreflang alternates (React requires camelCase: hrefLang)\n for (const alt of descriptor.alternateLanguages ?? []) {\n links.push({ rel: 'alternate', hrefLang: alt.hreflang, href: alt.href });\n }\n\n // JSON-LD\n if (descriptor.jsonLd) {\n scripts.push({ type: 'application/ld+json', children: JSON.stringify(descriptor.jsonLd) });\n }\n\n // Escape hatches\n for (const m of descriptor.meta ?? []) {\n const { httpEquiv, ...rest } = m as typeof m & { httpEquiv?: string };\n meta.push(httpEquiv ? { httpEquiv, ...rest } : rest);\n }\n for (const l of descriptor.links ?? []) links.push(l);\n for (const s of descriptor.styles ?? []) styles.push(s as unknown as Record<string, unknown>);\n\n // Import maps must be emitted before module scripts that rely on bare specifiers.\n for (const im of descriptor.importMap ?? []) {\n scripts.push({ type: 'importmap', children: JSON.stringify(im) });\n }\n for (const s of descriptor.scripts ?? []) scripts.push(s);\n\n return { meta, links, styles, scripts };\n}\n\n// ============================================================================\n// withHead - Simplified head callback wrapper for TanStack Router\n// ============================================================================\n\n/** Twig's page title format: \"<page title> - <store meta title or store name>\". */\nfunction appendStoreTitle(\n descriptor: HeadDescriptor,\n settings: TwilightContext['settings']\n): HeadDescriptor {\n const store = settings?.store;\n const storeTitle = store?.meta?.title || store?.name;\n const pageTitle = descriptor.title;\n if (!pageTitle || !storeTitle || descriptor.appendStoreTitle === false) return descriptor;\n if (pageTitle === storeTitle) return descriptor;\n\n const title = `${pageTitle} - ${storeTitle}`;\n // Share titles follow the page title too, unless the route set its own.\n const shareTitle = (current?: string) => (!current || current === pageTitle ? title : current);\n return {\n ...descriptor,\n title,\n openGraph: { ...descriptor.openGraph, title: shareTitle(descriptor.openGraph?.title) },\n twitter: { ...descriptor.twitter, title: shareTitle(descriptor.twitter?.title) },\n };\n}\n\n/**\n * Twig's page URL for a page that names none: its own path on the store's domain, without the\n * query, as the canonical and the og:url and twitter:url share cards read.\n */\nfunction withPageUrl(descriptor: HeadDescriptor, ctx: TwilightContext): HeadDescriptor {\n const pathname = ctx.location?.pathname;\n const canonical =\n descriptor.canonical ?? (pathname ? storePageUrl(ctx.settings, pathname) : undefined);\n if (!canonical) return descriptor;\n return {\n ...descriptor,\n canonical,\n openGraph: { ...descriptor.openGraph, url: descriptor.openGraph?.url ?? canonical },\n twitter: { ...descriptor.twitter, url: descriptor.twitter?.url ?? canonical },\n };\n}\n\n/**\n * Minimal shape we need from TanStack Router's AssetFnContextOptions.\n * `loaderData` feeds the route's own head function; `matches` is the recovery\n * source for store settings when the twilight module store is not populated yet\n * (see `ensureTwilightContextFromMatches`).\n */\ntype HeadContext = {\n loaderData?: unknown;\n matches?: readonly TwilightContextMatch[];\n};\n\n/**\n * Wraps a route module's head function for TanStack Router.\n *\n * @example\n * ```typescript\n * head: withHead(Offers)\n * head: withHead(Product, (result) => ({ ...result, robots: 'noindex, follow' }))\n * ```\n */\nexport function withHead<T>(\n route: { head: (ctx: TwilightContext, data: T) => HeadDescriptor },\n extend?: (result: HeadDescriptor, _ctx: TwilightContext, data: T) => HeadDescriptor\n): (_ctx: Record<string, unknown>) => Record<string, unknown> {\n return (ctx: HeadContext) => {\n const loaderData = ctx.loaderData;\n\n if (!loaderData) return {};\n\n // TanStack re-runs every matched route's head() during client hydration,\n // where the twilight module store can still be empty. Recover it from the\n // match context TanStack has already resolved before giving up.\n ensureTwilightContextFromMatches(ctx.matches);\n\n try {\n const context = getTwilightContext();\n const result = route.head(context, loaderData as T);\n const extended = extend ? extend(result, context, loaderData as T) : result;\n const finalResult = withPageUrl(appendStoreTitle(extended, context.settings), context);\n\n return tanstackHeadAdapter(finalResult);\n } catch (error) {\n // A head function must never throw: TanStack surfaces the throw as a\n // hydration error, React then discards the server-rendered tree and the\n // storefront renders blank. Dropping this route's head tags degrades\n // gracefully — the server-rendered ones stay in the document.\n if (error instanceof SettingsError) return {};\n throw error;\n }\n };\n}\n"]}
@@ -313,5 +313,5 @@ function getTwilightContext() {
313
313
  }
314
314
 
315
315
  export { SettingsError, composeMessages, createI18nInstance, getRequestStore, getTwilightContext, hasTwilightSettings, isPlainObject, messagesForLocale, runWithTwilightContext, storeTranslationsQueryKey, subscribeTwilight, translationsQueryKey, updateTwilightContext };
316
- //# sourceMappingURL=chunk-7VNVCHID.js.map
317
- //# sourceMappingURL=chunk-7VNVCHID.js.map
316
+ //# sourceMappingURL=chunk-6K34BCUP.js.map
317
+ //# sourceMappingURL=chunk-6K34BCUP.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/translations-key.ts","../src/api/messages.ts","../src/utils/errors.ts","../src/providers/i18n-factory.ts","../src/twilight/context.ts"],"names":[],"mappings":"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","file":"chunk-7VNVCHID.js","sourcesContent":["/**\n * @fileoverview The translations query key, on its own, importing nothing.\n *\n * Three places read the cached translations — `rootBeforeLoad`, the hydration\n * path in `tanstack/router.tsx`, and the lazy `i18n` accessor in\n * `twilight/context.ts` — and all three have to agree on the key or the\n * hydrated page misses the entry it was just handed and refetches. One\n * definition is the only way to keep that true.\n *\n * It lives here rather than in `api/translations.ts`, where it would naturally\n * sit, because **`twilight/context.ts` cannot afford that module's imports**.\n * `api/translations` pulls in `api/client`, which pulls in `ky`; `context.ts`\n * is imported directly by tests that mock `ky`, and adding that edge made six\n * of them stop being mocked and start issuing real requests to `api.salla.dev`\n * (`tests/routes/rootBeforeLoad.test.ts`, bisected to exactly this import). A\n * leaf module with no imports of its own cannot do that to anyone.\n */\n\n/**\n * @param locale is part of the key because each file on the CDN holds one\n * language. The global file this replaced carried every language and was\n * sliced after the cache, so a key without the locale was correct then and is\n * a wrong-language bug now: `/ar` → `/en` would reuse the Arabic entry.\n */\nexport function translationsQueryKey(locale: string): [string, string] {\n return ['translations', locale];\n}\n\n/**\n * The merchant's own wording for one store and one language.\n *\n * Separate from {@link translationsQueryKey} rather than folded into it,\n * because the two files have different lifetimes and different audiences: the\n * platform's copy is the same object for every store on the CDN, and this one\n * is a single merchant's overrides. Keeping them apart means a store with no\n * overrides never invalidates, refetches or dehydrates anything on its account.\n *\n * @param storeId is `settings.store.id` — the Optimus-encoded numeric id, which\n * is what names the object. It is safe in a key even though the locale-only key\n * deliberately avoids naming a store: that warning is about a store *resolved\n * from the request*, which differs between server and client. This one is read\n * out of the settings payload, so both sides compute it from the same\n * dehydrated data and agree.\n */\nexport function storeTranslationsQueryKey(\n storeId: string | number,\n locale: string\n): [string, string, string] {\n return ['translations', String(storeId), locale];\n}\n","/**\n * @fileoverview Composing one language's messages out of the query cache.\n *\n * **There are three places that build an i18n instance**, and they have to\n * agree on more than the key: `rootBeforeLoad`, the hydration path in\n * `tanstack/router.tsx`, and the lazy `i18n` accessor in `twilight/context.ts`.\n * When the platform's copy was the only source, agreeing on\n * `translationsQueryKey` was enough. It is not any more — a merchant's own\n * wording is a second cache entry, and a reader that knows about one and not\n * the other renders different text from the page beside it.\n *\n * That is exactly what shipped in #366: the server rendered the merchant's\n * words and hydration replaced them with the platform's, because only\n * `rootBeforeLoad` had been taught to merge. Greptile caught it. This module is\n * the single answer to \"what are the messages for this locale\", so the next\n * source cannot be added to one reader and forgotten in two.\n *\n * It lives beside `translations-key.ts` and imports nothing at runtime for the\n * same reason that file does: `twilight/context.ts` cannot afford\n * `api/translations`, which pulls in `api/client` and therefore `ky`, and tests\n * that mock `ky` stop being mocked the moment that edge exists.\n */\nimport type { QueryClient } from '@tanstack/react-query';\nimport { translationsQueryKey } from './translations-key';\nimport type { TranslationMessages } from '../providers/I18nProvider';\n\nexport type Messages = Record<string, unknown>;\n\nexport function isPlainObject(value: unknown): value is Messages {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * `overrides` laid over `base`, one leaf at a time.\n *\n * Recursive rather than a spread, because both files are nested by group\n * (`common.errors.500`) and a top-level spread would make a merchant who\n * overrode one string inside `common` lose every other string in it. The\n * merchant's value wins at the leaf, and a group they never touched is left\n * exactly as the platform sent it.\n *\n * A type conflict — one side an object where the other is a string — resolves\n * to the merchant's value. It is the more specific of the two and there is no\n * sensible way to merge a string into a group; the alternative, keeping the\n * platform's, would mean a merchant's edit silently doing nothing.\n */\nexport function mergeMessages(base: Messages, overrides: Messages): Messages {\n const merged: Messages = { ...base };\n\n for (const [key, value] of Object.entries(overrides)) {\n const existing = merged[key];\n merged[key] =\n isPlainObject(existing) && isPlainObject(value) ? mergeMessages(existing, value) : value;\n }\n\n return merged;\n}\n\n/**\n * This store's overrides for `locale`, if any were fetched into the cache.\n *\n * Found by **shape** rather than by asking the settings for a store id, and\n * that is deliberate: the two readers that were missing the merge have a\n * `queryClient` and a locale between them and nothing else, and reaching for\n * `api/store` from `twilight/context.ts` would drag `ky` in through the back\n * door. One document serves one store — a request naming a different one is\n * redirected with `reloadDocument` — so at most one such entry per locale\n * exists, and matching `['translations', <anything>, <locale>]` cannot pick up\n * somebody else's.\n */\nfunction cachedOverrides(queryClient: QueryClient, locale: string): Messages | undefined {\n const entries = queryClient.getQueriesData<Messages>({ queryKey: ['translations'] });\n\n for (const [key, data] of entries) {\n if (key.length === 3 && key[2] === locale && isPlainObject(data)) {\n return data;\n }\n }\n\n return undefined;\n}\n\n/**\n * The messages for `locale`: the platform's copy with this merchant's over it.\n *\n * Reads only — whoever wants the merchant's file in the cache has to have put\n * it there, which `rootBeforeLoad` does and only when the settings say there is\n * one. A reader that runs without it simply gets the platform's copy, which is\n * the same thing it got before any of this existed.\n */\nexport function messagesForLocale(\n queryClient: QueryClient | undefined,\n locale: string\n): TranslationMessages | undefined {\n const common = queryClient?.getQueryData<TranslationMessages>(translationsQueryKey(locale));\n const overrides = queryClient ? cachedOverrides(queryClient, locale) : undefined;\n\n return composeMessages(common, overrides, locale);\n}\n\n/**\n * The same composition from values rather than from the cache.\n *\n * `rootBeforeLoad` has both in hand already — it just awaited them — so it\n * composes directly instead of reading back what it put in.\n */\nexport function composeMessages(\n common: TranslationMessages | null | undefined,\n overrides: Messages | null | undefined,\n locale: string\n): TranslationMessages | undefined {\n if (!overrides || Object.keys(overrides).length === 0) return common ?? undefined;\n\n const base = common?.[`${locale}.trans`];\n\n return {\n [`${locale}.trans`]: mergeMessages(isPlainObject(base) ? base : {}, overrides) as Record<\n string,\n string\n >,\n };\n}\n","/**\n * Why a store's settings did not load:\n * - `no-store`: nothing named a store for this request;\n * - `timeout`: the Salla API did not answer in time;\n * - `not-found`: it answered that no store has that identifier;\n * - `http`: it answered with another error status;\n * - `network`: no answer arrived at all;\n * - `empty`: it answered without settings.\n */\nexport type SettingsErrorReason =\n 'no-store' | 'timeout' | 'not-found' | 'http' | 'network' | 'empty';\n\nexport interface SettingsErrorDetails {\n reason?: SettingsErrorReason;\n /** The API's status, when `reason` is `'http'` or `'not-found'`. */\n status?: number;\n}\n\nexport class SettingsError extends Error {\n /** Absent when nothing said why, e.g. `getTwilightContext().settings` read before they loaded. */\n readonly reason?: SettingsErrorReason;\n readonly status?: number;\n\n constructor(message?: string, details?: SettingsErrorDetails) {\n super(message ?? 'Store settings could not be loaded.');\n this.name = 'SettingsError';\n this.reason = details?.reason;\n this.status = details?.status;\n }\n}\n","import { createInstance, type i18n as I18nInstance } from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nexport type TranslationMessages = Record<string, Record<string, string>>;\n\n/**\n * Creates a new i18next instance for the given locale.\n *\n * @param locale - Active locale code, e.g. `'ar'`\n * @param translations - App translations from the Salla API (store-specific)\n * @param themeTranslations - Bundled theme translations (static defaults)\n */\nexport function createI18nInstance(\n locale: string,\n translations?: TranslationMessages,\n themeTranslations?: TranslationMessages\n): I18nInstance {\n const instance = createInstance();\n const transKey = `${locale}.trans`;\n\n instance.use(initReactI18next).init({\n lng: locale,\n fallbackLng: locale,\n ns: ['app', 'theme'],\n defaultNS: 'app',\n fallbackNS: 'theme',\n resources: {\n [locale]: {\n app: translations?.[transKey] ?? {},\n theme: themeTranslations?.[transKey] ?? {},\n },\n },\n interpolation: { escapeValue: false },\n react: { useSuspense: false },\n keySeparator: '.',\n nsSeparator: false,\n });\n\n return instance;\n}\n\n/**\n * Creates i18n instance for testing\n * @param locale - Locale code (default: 'ar')\n * @param translations - Optional translations\n */\nexport function createTestI18n(locale = 'ar', translations?: TranslationMessages): I18nInstance {\n return createI18nInstance(locale, translations);\n}\n","import type { QueryClient } from '@tanstack/react-query';\nimport type { i18n } from 'i18next';\nimport type { StoreContext } from '../api/store';\nimport type { AppSnippet, AppSettings } from '../api/apps';\nimport { FALLBACK_LOCALE, getLanguageInfo } from '../providers/locale-constants';\nimport { createI18nInstance } from '../providers/i18n-factory';\nimport { messagesForLocale } from '../api/messages';\nimport { SettingsError } from '../utils/errors';\nimport type { ActiveScope } from '../utils/cookies';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TwilightLocation<TSearch = Record<string, unknown>> {\n href: string;\n pathname: string;\n search: TSearch;\n searchStr: string;\n state: Record<string, unknown>;\n hash: string;\n}\n\nexport interface PageContext {\n slug: string;\n id?: string | number;\n title: string;\n url?: string;\n parent?: { id: string | number; name: string; url: string } | null;\n breadcrumbs?: { name: string; url: string }[];\n}\n\nexport interface TwilightContext {\n queryClient: QueryClient;\n settings: StoreContext;\n locale: string;\n routeId: string;\n location: TwilightLocation;\n authToken: string | null;\n /**\n * The selected market and, once bullet delivery confirmed one, its branch\n * allocation — the full object the SDK sends as `s-scope-*` headers. Seeded from\n * the `scope` cookie on the server; see {@link ActiveScope}.\n */\n scope: ActiveScope | null;\n /** `scope.id`, kept for callers that only need the market. */\n scopeId: string | null;\n /**\n * Which store this request is for, when something other than the hostname says\n * so — the `?storeId=` a preview was opened with, or the cookie remembering it.\n *\n * Null on a live storefront, where the hostname is the answer and there is\n * nothing to carry. See {@link resolveRequestStoreId}.\n */\n storeId: string | null;\n /**\n * Which store the first segment of this request's path named, on a host where\n * the store is the root of every URL: `mtgr-alaatr-2` for\n * `https://preview.salla.design/mtgr-alaatr-2/cart`.\n *\n * Null whenever something else named the store, and on every merchant domain.\n * See {@link resolveRequestStoreBase}.\n */\n storeBase: string | null;\n /**\n * Where {@link storeBase} sits in this request's paths: behind the locale on a\n * Salla shared host (`/ar/dev-x/cart`, named by the dispatcher), in front of it\n * everywhere else. See {@link resolveAddressedStore}.\n */\n storeBaseFollowsLocale: boolean;\n /**\n * Which version of the theme's settings this request asked for — the\n * `?versionId=` an editor preview or a local dev session was opened with, or\n * the cookie remembering it.\n *\n * Null on an ordinary storefront visit, which is the common case: nothing\n * named a version, so the store's live one is what the API answers with. See\n * {@link resolveRequestVersionId}.\n */\n versionId: string | null;\n /**\n * The host this request arrived on, captured server-side.\n *\n * A theme worker is deployed with no vars and no bindings, so the request is\n * the only thing that knows which storefront it is serving. On the client this\n * is `window.location.host`; on the server nothing else has it.\n */\n requestHost: string | null;\n /** The native app's `s-app-*` headers when the request came from its webview; see {@link readNativeAppHeaders}. */\n nativeAppHeaders: Record<string, string> | null;\n i18n: i18n;\n dir: 'ltr' | 'rtl';\n page?: PageContext;\n /** Installed apps' snippets, fetched in rootBeforeLoad so AppsSnippets can render CDN\n * <script> tags during SSR (React Query isn't dehydrated here, so useQuery has no SSR data). */\n appsSnippets?: AppSnippet[];\n /** Per-app public `app.*` buckets, fetched in rootBeforeLoad so rootHead can install the\n * `Salla.appScope` factory inline at parse time — ahead of the snippets' onReady callbacks. */\n appsSettings?: AppSettings;\n /**\n * This visitor sees the maintenance page, not the store. Decided in rootBeforeLoad\n * from `settings.maintenance` and the merchant's owner view; see `utils/maintenance`.\n */\n maintenance: boolean;\n /**\n * The Salla API answered that no store has the identifier this request named. Set by\n * rootBeforeLoad; `twilightMiddleware` answers with Twig's 410 page instead of the render.\n */\n storeNotFound: boolean;\n extras?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Internal Store\n// ============================================================================\n\nconst DEFAULT_LOCATION: TwilightLocation = {\n href: '',\n pathname: '',\n search: {},\n searchStr: '',\n state: {},\n hash: '',\n};\n\ninterface ContextData {\n queryClient: QueryClient;\n settings: StoreContext | null;\n locale: string;\n routeId: string;\n location: TwilightLocation;\n authToken: string | null;\n scope: ActiveScope | null;\n storeId: string | null;\n storeBase: string | null;\n storeBaseFollowsLocale: boolean;\n versionId: string | null;\n requestHost: string | null;\n nativeAppHeaders: Record<string, string> | null;\n i18n?: i18n;\n page?: PageContext;\n appsSnippets?: AppSnippet[];\n appsSettings?: AppSettings;\n maintenance: boolean;\n storeNotFound: boolean;\n extras?: Record<string, unknown>;\n}\n\nconst DEFAULT_DATA: ContextData = {\n queryClient: null as unknown as QueryClient,\n settings: null,\n locale: FALLBACK_LOCALE,\n routeId: '',\n location: { ...DEFAULT_LOCATION },\n authToken: null,\n scope: null,\n storeId: null,\n storeBase: null,\n storeBaseFollowsLocale: false,\n versionId: null,\n requestHost: null,\n nativeAppHeaders: null,\n i18n: undefined,\n page: undefined,\n maintenance: false,\n storeNotFound: false,\n};\n\n// ============================================================================\n// Storage: AsyncLocalStorage (server) or module-level store (client)\n// ============================================================================\n\ntype AsyncLocalStore<T> = { getStore(): T | undefined; run(val: T, fn: () => unknown): unknown };\n\n// Initialize ALS at module load time for SSR — no race condition\ntype AsyncHooks = { AsyncLocalStorage: new <T>() => AsyncLocalStore<T> };\n\n// workerd has no global `require`, so a bundled `require()` throws there; it does have\n// `process.getBuiltinModule` (so does Node >= 20.16), which keeps this out of the browser bundle.\nfunction loadAsyncHooks(): AsyncHooks | null {\n const proc = (globalThis as { process?: { getBuiltinModule?: (id: string) => unknown } }).process;\n try {\n const builtin = proc?.getBuiltinModule?.('node:async_hooks') as AsyncHooks | undefined;\n if (builtin?.AsyncLocalStorage) return builtin;\n } catch {\n /* fall through to require */\n }\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require('node:async_hooks') as AsyncHooks;\n } catch {\n return null;\n }\n}\n\nconst isServer = typeof window === 'undefined';\n// One instance per isolate, so a re-evaluated or duplicated copy of this module (dev\n// reloads, src next to dist) reads the scope the request middleware opened.\nconst ALS_KEY = Symbol.for('salla.twilight.context.als');\nlet _als: AsyncLocalStore<ContextData> | null = null;\nif (isServer) {\n const registry = globalThis as { [ALS_KEY]?: AsyncLocalStore<ContextData> };\n const hooks = registry[ALS_KEY] ? null : loadAsyncHooks();\n if (hooks) registry[ALS_KEY] = new hooks.AsyncLocalStorage<ContextData>();\n _als = registry[ALS_KEY] ?? null;\n}\n\n// Without request isolation every request would share `clientStore`: one visitor's\n// auth token and store settings rendered into another's page.\nfunction assertRequestIsolation(): void {\n if (isServer && !_als) {\n throw new Error(\n '[Twilight] AsyncLocalStorage is unavailable; refusing to share request state.'\n );\n }\n}\n\n// The browser's store, shared by every copy of this module on the page like the ALS above,\n// so a loader in one copy reads the location and token the router wrote through another.\nconst CLIENT_KEY = Symbol.for('salla.twilight.context.client');\nconst clientRegistry = globalThis as {\n [CLIENT_KEY]?: { store: ContextData; listeners: Set<() => void> };\n};\nconst clientShared = (clientRegistry[CLIENT_KEY] ??= {\n store: { ...DEFAULT_DATA },\n listeners: new Set<() => void>(),\n});\nconst clientStore: ContextData = clientShared.store;\n\nfunction getTwilightStore(): ContextData {\n assertRequestIsolation();\n if (_als) {\n const store = _als.getStore();\n if (!store)\n throw new Error('[Twilight] No request context. Wrap with runWithTwilightContext().');\n return store;\n }\n return clientStore;\n}\n\nfunction writableStore(): ContextData {\n if (_als) {\n const store = _als.getStore();\n if (store) return store;\n }\n return clientStore;\n}\n\nfunction mergeIntoStore(store: ContextData, partial: Partial<TwilightContext>): void {\n if ('queryClient' in partial && partial.queryClient) store.queryClient = partial.queryClient;\n if ('settings' in partial && partial.settings != null) store.settings = partial.settings;\n if ('locale' in partial && partial.locale != null) store.locale = partial.locale;\n if ('routeId' in partial && partial.routeId != null) store.routeId = partial.routeId;\n if ('location' in partial && partial.location != null)\n store.location = { ...store.location, ...partial.location };\n if ('authToken' in partial && partial.authToken !== undefined)\n store.authToken = partial.authToken ?? null;\n if ('scope' in partial && partial.scope !== undefined) store.scope = partial.scope ?? null;\n else if ('scopeId' in partial && partial.scopeId !== undefined)\n store.scope = partial.scopeId == null ? null : { id: partial.scopeId };\n if ('storeId' in partial && partial.storeId !== undefined)\n store.storeId = partial.storeId ?? null;\n if ('storeBase' in partial && partial.storeBase !== undefined)\n store.storeBase = partial.storeBase ?? null;\n if ('storeBaseFollowsLocale' in partial && partial.storeBaseFollowsLocale !== undefined)\n store.storeBaseFollowsLocale = partial.storeBaseFollowsLocale === true;\n if ('versionId' in partial && partial.versionId !== undefined)\n store.versionId = partial.versionId ?? null;\n if ('requestHost' in partial && partial.requestHost !== undefined)\n store.requestHost = partial.requestHost ?? null;\n if ('nativeAppHeaders' in partial && partial.nativeAppHeaders !== undefined)\n store.nativeAppHeaders = partial.nativeAppHeaders ?? null;\n if ('i18n' in partial && partial.i18n != null) store.i18n = partial.i18n;\n if ('page' in partial) store.page = partial.page;\n if ('appsSnippets' in partial) store.appsSnippets = partial.appsSnippets;\n if ('appsSettings' in partial) store.appsSettings = partial.appsSettings;\n if ('maintenance' in partial) store.maintenance = partial.maintenance === true;\n if ('storeNotFound' in partial) store.storeNotFound = partial.storeNotFound === true;\n if ('extras' in partial) store.extras = partial.extras;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\nexport function runWithTwilightContext<T>(partial: Partial<TwilightContext>, fn: () => T): T {\n assertRequestIsolation();\n if (_als) {\n const data: ContextData = { ...DEFAULT_DATA };\n mergeIntoStore(data, partial);\n return _als.run(data, fn) as T;\n }\n mergeIntoStore(clientStore, partial);\n return fn();\n}\n\n// Client-only subscription so React consumers (useRouteId/useIsHome/…) re-render\n// when navigation mutates the module store. Mirrors hooks/useWishlist.ts.\nconst listeners = clientShared.listeners;\n\nexport function subscribeTwilight(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function updateTwilightContext(partial: Partial<TwilightContext>): void {\n mergeIntoStore(getTwilightStore(), partial);\n // Server uses AsyncLocalStorage and has no React subscribers; notify on client only.\n if (typeof window !== 'undefined') {\n for (const listener of listeners) listener();\n }\n}\n\n/**\n * Whether store settings are available, without throwing.\n *\n * `getTwilightContext().settings` throws a `SettingsError` when the store is\n * empty, which is fatal inside a head function during hydration. Callers that\n * need to *test* availability must use this instead of a try/catch around the\n * getter. Returns false when there is no request context at all (server-side\n * calls outside `runWithTwilightContext`).\n */\nexport function hasTwilightSettings(): boolean {\n try {\n return getTwilightStore().settings != null;\n } catch {\n return false;\n }\n}\n\n/** What a request addressed, as opposed to what it is. */\nexport interface RequestAddressing {\n storeId: string | null;\n storeBase: string | null;\n storeBaseFollowsLocale: boolean;\n versionId: string | null;\n requestHost: string | null;\n}\n\n/**\n * What this request named and the host it arrived on, without throwing.\n *\n * Separate from {@link getTwilightContext} because store identity is read while\n * deciding *what to fetch* — before there is a context worth having — and on the\n * server outside a request the getter throws. A caller asking \"which store?\" has\n * a sane answer for \"none named\"; it has none for an exception.\n *\n * The version rides along rather than getting an accessor of its own: it is read\n * at the same moment, for the same reason, and by the same callers, and a second\n * copy of this try/catch would be a second thing to remember to widen.\n */\nexport function getRequestStore(): RequestAddressing {\n try {\n const data = getTwilightStore();\n return {\n storeId: data.storeId,\n storeBase: data.storeBase,\n storeBaseFollowsLocale: data.storeBaseFollowsLocale,\n versionId: data.versionId,\n requestHost: data.requestHost,\n };\n } catch {\n return {\n storeId: null,\n storeBase: null,\n storeBaseFollowsLocale: false,\n versionId: null,\n requestHost: null,\n };\n }\n}\n\nexport function getTwilightContext(): TwilightContext {\n const data = getTwilightStore();\n return {\n get queryClient() {\n return data.queryClient;\n },\n get settings() {\n if (!data.settings) throw new SettingsError();\n return data.settings;\n },\n get locale() {\n return data.locale;\n },\n get routeId() {\n return data.routeId;\n },\n get location() {\n return data.location;\n },\n get authToken() {\n return data.authToken;\n },\n get scope() {\n return data.scope;\n },\n get scopeId() {\n return data.scope?.id ?? null;\n },\n get storeId() {\n return data.storeId;\n },\n get storeBase() {\n return data.storeBase;\n },\n get storeBaseFollowsLocale() {\n return data.storeBaseFollowsLocale;\n },\n get versionId() {\n return data.versionId;\n },\n get requestHost() {\n return data.requestHost;\n },\n get nativeAppHeaders() {\n return data.nativeAppHeaders;\n },\n get i18n() {\n if (!data.i18n) {\n // Composed the same way as `rootBeforeLoad` and the hydration path —\n // the platform's copy with this merchant's over it. See\n // `api/messages.ts`: this accessor reading one entry while the others\n // read two is precisely the drift that module exists to stop.\n data.i18n = createI18nInstance(\n data.locale,\n messagesForLocale(data.queryClient, data.locale)\n );\n }\n return data.i18n;\n },\n get dir() {\n return getLanguageInfo(data.locale).dir;\n },\n get page() {\n return data.page;\n },\n get appsSnippets() {\n return data.appsSnippets;\n },\n get appsSettings() {\n return data.appsSettings;\n },\n get maintenance() {\n return data.maintenance;\n },\n get storeNotFound() {\n return data.storeNotFound;\n },\n get extras() {\n return data.extras;\n },\n };\n}\n\n/** @internal Reset store for testing */\nexport function resetForTesting(): void {\n Object.assign(writableStore(), { ...DEFAULT_DATA });\n}\n"]}
1
+ {"version":3,"sources":["../src/api/translations-key.ts","../src/api/messages.ts","../src/utils/errors.ts","../src/providers/i18n-factory.ts","../src/twilight/context.ts"],"names":[],"mappings":";;;;;;AAwBO,SAAS,qBAAqB,MAAA,EAAkC;AACrE,EAAA,OAAO,CAAC,gBAAgB,MAAM,CAAA;AAChC;AAkBO,SAAS,yBAAA,CACd,SACA,MAAA,EAC0B;AAC1B,EAAA,OAAO,CAAC,cAAA,EAAgB,MAAA,CAAO,OAAO,GAAG,MAAM,CAAA;AACjD;;;ACrBO,SAAS,cAAc,KAAA,EAAmC;AAC/D,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAgBO,SAAS,aAAA,CAAc,MAAgB,SAAA,EAA+B;AAC3E,EAAA,MAAM,MAAA,GAAmB,EAAE,GAAG,IAAA,EAAK;AAEnC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpD,IAAA,MAAM,QAAA,GAAW,OAAO,GAAG,CAAA;AAC3B,IAAA,MAAA,CAAO,GAAG,CAAA,GACR,aAAA,CAAc,QAAQ,CAAA,IAAK,aAAA,CAAc,KAAK,CAAA,GAAI,aAAA,CAAc,QAAA,EAAU,KAAK,CAAA,GAAI,KAAA;AAAA,EACvF;AAEA,EAAA,OAAO,MAAA;AACT;AAcA,SAAS,eAAA,CAAgB,aAA0B,MAAA,EAAsC;AACvF,EAAA,MAAM,OAAA,GAAU,YAAY,cAAA,CAAyB,EAAE,UAAU,CAAC,cAAc,GAAG,CAAA;AAEnF,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,OAAA,EAAS;AACjC,IAAA,IAAI,GAAA,CAAI,WAAW,CAAA,IAAK,GAAA,CAAI,CAAC,CAAA,KAAM,MAAA,IAAU,aAAA,CAAc,IAAI,CAAA,EAAG;AAChE,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,iBAAA,CACd,aACA,MAAA,EACiC;AACjC,EAAA,MAAM,MAAA,GAAS,WAAA,EAAa,YAAA,CAAkC,oBAAA,CAAqB,MAAM,CAAC,CAAA;AAC1F,EAAA,MAAM,SAAA,GAAY,WAAA,GAAc,eAAA,CAAgB,WAAA,EAAa,MAAM,CAAA,GAAI,MAAA;AAEvE,EAAA,OAAO,eAAA,CAAgB,MAAA,EAAQ,SAAA,EAAW,MAAM,CAAA;AAClD;AAQO,SAAS,eAAA,CACd,MAAA,EACA,SAAA,EACA,MAAA,EACiC;AACjC,EAAA,IAAI,CAAC,aAAa,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA,IAAU,MAAA;AAExE,EAAA,MAAM,IAAA,GAAO,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,MAAA,CAAQ,CAAA;AAEvC,EAAA,OAAO;AAAA,IACL,CAAC,CAAA,EAAG,MAAM,CAAA,MAAA,CAAQ,GAAG,aAAA,CAAc,aAAA,CAAc,IAAI,CAAA,GAAI,IAAA,GAAO,EAAC,EAAG,SAAS;AAAA,GAI/E;AACF;;;ACvGO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAKvC,WAAA,CAAY,SAAkB,OAAA,EAAgC;AAC5D,IAAA,KAAA,CAAM,WAAW,qCAAqC,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,SAAS,OAAA,EAAS,MAAA;AACvB,IAAA,IAAA,CAAK,SAAS,OAAA,EAAS,MAAA;AAAA,EACzB;AACF;ACjBO,SAAS,kBAAA,CACd,MAAA,EACA,YAAA,EACA,iBAAA,EACc;AACd,EAAA,MAAM,WAAW,cAAA,EAAe;AAChC,EAAA,MAAM,QAAA,GAAW,GAAG,MAAM,CAAA,MAAA,CAAA;AAE1B,EAAA,QAAA,CAAS,GAAA,CAAI,gBAAgB,CAAA,CAAE,IAAA,CAAK;AAAA,IAClC,GAAA,EAAK,MAAA;AAAA,IACL,WAAA,EAAa,MAAA;AAAA,IACb,EAAA,EAAI,CAAC,KAAA,EAAO,OAAO,CAAA;AAAA,IACnB,SAAA,EAAW,KAAA;AAAA,IACX,UAAA,EAAY,OAAA;AAAA,IACZ,SAAA,EAAW;AAAA,MACT,CAAC,MAAM,GAAG;AAAA,QACR,GAAA,EAAK,YAAA,GAAe,QAAQ,CAAA,IAAK,EAAC;AAAA,QAClC,KAAA,EAAO,iBAAA,GAAoB,QAAQ,CAAA,IAAK;AAAC;AAC3C,KACF;AAAA,IACA,aAAA,EAAe,EAAE,WAAA,EAAa,KAAA,EAAM;AAAA,IACpC,KAAA,EAAO,EAAE,WAAA,EAAa,KAAA,EAAM;AAAA,IAC5B,YAAA,EAAc,GAAA;AAAA,IACd,WAAA,EAAa;AAAA,GACd,CAAA;AAED,EAAA,OAAO,QAAA;AACT;;;AC8EA,IAAM,gBAAA,GAAqC;AAAA,EACzC,IAAA,EAAM,EAAA;AAAA,EACN,QAAA,EAAU,EAAA;AAAA,EACV,QAAQ,EAAC;AAAA,EACT,SAAA,EAAW,EAAA;AAAA,EACX,OAAO,EAAC;AAAA,EACR,IAAA,EAAM;AACR,CAAA;AAyBA,IAAM,YAAA,GAA4B;AAAA,EAChC,WAAA,EAAa,IAAA;AAAA,EACb,QAAA,EAAU,IAAA;AAAA,EACV,MAAA,EAAQ,eAAA;AAAA,EACR,OAAA,EAAS,EAAA;AAAA,EACT,QAAA,EAAU,EAAE,GAAG,gBAAA,EAAiB;AAAA,EAChC,SAAA,EAAW,IAAA;AAAA,EACX,KAAA,EAAO,IAAA;AAAA,EACP,OAAA,EAAS,IAAA;AAAA,EACT,SAAA,EAAW,IAAA;AAAA,EACX,sBAAA,EAAwB,KAAA;AAAA,EACxB,SAAA,EAAW,IAAA;AAAA,EACX,WAAA,EAAa,IAAA;AAAA,EACb,gBAAA,EAAkB,IAAA;AAAA,EAClB,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EAAa,KAAA;AAAA,EACb,aAAA,EAAe;AACjB,CAAA;AAaA,SAAS,cAAA,GAAoC;AAC3C,EAAA,MAAM,OAAQ,UAAA,CAA4E,OAAA;AAC1F,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,IAAA,EAAM,gBAAA,GAAmB,kBAAkB,CAAA;AAC3D,IAAA,IAAI,OAAA,EAAS,mBAAmB,OAAO,OAAA;AAAA,EACzC,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,IAAI;AAEF,IAAA,OAAO,UAAQ,aAAkB,CAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,IAAM,QAAA,GAAW,OAAO,MAAA,KAAW,WAAA;AAGnC,IAAM,OAAA,mBAAU,MAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA;AACvD,IAAI,IAAA,GAA4C,IAAA;AAChD,IAAI,QAAA,EAAU;AACZ,EAAA,MAAM,QAAA,GAAW,UAAA;AACjB,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAO,CAAA,GAAI,OAAO,cAAA,EAAe;AACxD,EAAA,IAAI,OAAO,QAAA,CAAS,OAAO,CAAA,GAAI,IAAI,MAAM,iBAAA,EAA+B;AACxE,EAAA,IAAA,GAAO,QAAA,CAAS,OAAO,CAAA,IAAK,IAAA;AAC9B;AAIA,SAAS,sBAAA,GAA+B;AACtC,EAAA,IAAI,QAAA,IAAY,CAAC,IAAA,EAAM;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACF;AAIA,IAAM,UAAA,mBAAa,MAAA,CAAO,GAAA,CAAI,+BAA+B,CAAA;AAC7D,IAAM,cAAA,GAAiB,UAAA;AAGvB,IAAM,YAAA,GAAgB,cAAA,CAAe,UAAU,CAAA,KAAM;AAAA,EACnD,KAAA,EAAO,EAAE,GAAG,YAAA,EAAa;AAAA,EACzB,SAAA,sBAAe,GAAA;AACjB,CAAA;AACA,IAAM,cAA2B,YAAA,CAAa,KAAA;AAE9C,SAAS,gBAAA,GAAgC;AACvC,EAAA,sBAAA,EAAuB;AACvB,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,KAAA;AACH,MAAA,MAAM,IAAI,MAAM,oEAAoE,CAAA;AACtF,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,WAAA;AACT;AAUA,SAAS,cAAA,CAAe,OAAoB,OAAA,EAAyC;AACnF,EAAA,IAAI,iBAAiB,OAAA,IAAW,OAAA,CAAQ,WAAA,EAAa,KAAA,CAAM,cAAc,OAAA,CAAQ,WAAA;AACjF,EAAA,IAAI,cAAc,OAAA,IAAW,OAAA,CAAQ,YAAY,IAAA,EAAM,KAAA,CAAM,WAAW,OAAA,CAAQ,QAAA;AAChF,EAAA,IAAI,YAAY,OAAA,IAAW,OAAA,CAAQ,UAAU,IAAA,EAAM,KAAA,CAAM,SAAS,OAAA,CAAQ,MAAA;AAC1E,EAAA,IAAI,aAAa,OAAA,IAAW,OAAA,CAAQ,WAAW,IAAA,EAAM,KAAA,CAAM,UAAU,OAAA,CAAQ,OAAA;AAC7E,EAAA,IAAI,UAAA,IAAc,OAAA,IAAW,OAAA,CAAQ,QAAA,IAAY,IAAA;AAC/C,IAAA,KAAA,CAAM,WAAW,EAAE,GAAG,MAAM,QAAA,EAAU,GAAG,QAAQ,QAAA,EAAS;AAC5D,EAAA,IAAI,WAAA,IAAe,OAAA,IAAW,OAAA,CAAQ,SAAA,KAAc,MAAA;AAClD,IAAA,KAAA,CAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,IAAA;AACzC,EAAA,IAAI,OAAA,IAAW,WAAW,OAAA,CAAQ,KAAA,KAAU,QAAW,KAAA,CAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,IAAA;AAAA,OAAA,IAC7E,SAAA,IAAa,OAAA,IAAW,OAAA,CAAQ,OAAA,KAAY,MAAA;AACnD,IAAA,KAAA,CAAM,KAAA,GAAQ,QAAQ,OAAA,IAAW,IAAA,GAAO,OAAO,EAAE,EAAA,EAAI,QAAQ,OAAA,EAAQ;AACvE,EAAA,IAAI,SAAA,IAAa,OAAA,IAAW,OAAA,CAAQ,OAAA,KAAY,MAAA;AAC9C,IAAA,KAAA,CAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,IAAA;AACrC,EAAA,IAAI,WAAA,IAAe,OAAA,IAAW,OAAA,CAAQ,SAAA,KAAc,MAAA;AAClD,IAAA,KAAA,CAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,IAAA;AACzC,EAAA,IAAI,wBAAA,IAA4B,OAAA,IAAW,OAAA,CAAQ,sBAAA,KAA2B,MAAA;AAC5E,IAAA,KAAA,CAAM,sBAAA,GAAyB,QAAQ,sBAAA,KAA2B,IAAA;AACpE,EAAA,IAAI,WAAA,IAAe,OAAA,IAAW,OAAA,CAAQ,SAAA,KAAc,MAAA;AAClD,IAAA,KAAA,CAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,IAAA;AACzC,EAAA,IAAI,aAAA,IAAiB,OAAA,IAAW,OAAA,CAAQ,WAAA,KAAgB,MAAA;AACtD,IAAA,KAAA,CAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,IAAA;AAC7C,EAAA,IAAI,kBAAA,IAAsB,OAAA,IAAW,OAAA,CAAQ,gBAAA,KAAqB,MAAA;AAChE,IAAA,KAAA,CAAM,gBAAA,GAAmB,QAAQ,gBAAA,IAAoB,IAAA;AACvD,EAAA,IAAI,UAAU,OAAA,IAAW,OAAA,CAAQ,QAAQ,IAAA,EAAM,KAAA,CAAM,OAAO,OAAA,CAAQ,IAAA;AACpE,EAAA,IAAI,MAAA,IAAU,OAAA,EAAS,KAAA,CAAM,IAAA,GAAO,OAAA,CAAQ,IAAA;AAC5C,EAAA,IAAI,cAAA,IAAkB,OAAA,EAAS,KAAA,CAAM,YAAA,GAAe,OAAA,CAAQ,YAAA;AAC5D,EAAA,IAAI,cAAA,IAAkB,OAAA,EAAS,KAAA,CAAM,YAAA,GAAe,OAAA,CAAQ,YAAA;AAC5D,EAAA,IAAI,aAAA,IAAiB,OAAA,EAAS,KAAA,CAAM,WAAA,GAAc,QAAQ,WAAA,KAAgB,IAAA;AAC1E,EAAA,IAAI,eAAA,IAAmB,OAAA,EAAS,KAAA,CAAM,aAAA,GAAgB,QAAQ,aAAA,KAAkB,IAAA;AAChF,EAAA,IAAI,QAAA,IAAY,OAAA,EAAS,KAAA,CAAM,MAAA,GAAS,OAAA,CAAQ,MAAA;AAClD;AAMO,SAAS,sBAAA,CAA0B,SAAmC,EAAA,EAAgB;AAC3F,EAAA,sBAAA,EAAuB;AACvB,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,MAAM,IAAA,GAAoB,EAAE,GAAG,YAAA,EAAa;AAC5C,IAAA,cAAA,CAAe,MAAM,OAAO,CAAA;AAC5B,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAE,CAAA;AAAA,EAC1B;AACA,EAAA,cAAA,CAAe,aAAa,OAAO,CAAA;AACnC,EAAA,OAAO,EAAA,EAAG;AACZ;AAIA,IAAM,YAAY,YAAA,CAAa,SAAA;AAExB,SAAS,kBAAkB,QAAA,EAAkC;AAClE,EAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,EAAA,OAAO,MAAM;AACX,IAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,EAC3B,CAAA;AACF;AAEO,SAAS,sBAAsB,OAAA,EAAyC;AAC7E,EAAA,cAAA,CAAe,gBAAA,IAAoB,OAAO,CAAA;AAE1C,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,KAAA,MAAW,QAAA,IAAY,WAAW,QAAA,EAAS;AAAA,EAC7C;AACF;AAWO,SAAS,mBAAA,GAA+B;AAC7C,EAAA,IAAI;AACF,IAAA,OAAO,gBAAA,GAAmB,QAAA,IAAY,IAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAuBO,SAAS,eAAA,GAAqC;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,gBAAA,EAAiB;AAC9B,IAAA,OAAO;AAAA,MACL,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,wBAAwB,IAAA,CAAK,sBAAA;AAAA,MAC7B,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,aAAa,IAAA,CAAK;AAAA,KACpB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,IAAA;AAAA,MACX,sBAAA,EAAwB,KAAA;AAAA,MACxB,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa;AAAA,KACf;AAAA,EACF;AACF;AAEO,SAAS,kBAAA,GAAsC;AACpD,EAAA,MAAM,OAAO,gBAAA,EAAiB;AAC9B,EAAA,OAAO;AAAA,IACL,IAAI,WAAA,GAAc;AAChB,MAAA,OAAO,IAAA,CAAK,WAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,QAAA,GAAW;AACb,MAAA,IAAI,CAAC,IAAA,CAAK,QAAA,EAAU,MAAM,IAAI,aAAA,EAAc;AAC5C,MAAA,OAAO,IAAA,CAAK,QAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,MAAA,GAAS;AACX,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,OAAA,GAAU;AACZ,MAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,QAAA,GAAW;AACb,MAAA,OAAO,IAAA,CAAK,QAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACd,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,KAAA,GAAQ;AACV,MAAA,OAAO,IAAA,CAAK,KAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,OAAA,GAAU;AACZ,MAAA,OAAO,IAAA,CAAK,OAAO,EAAA,IAAM,IAAA;AAAA,IAC3B,CAAA;AAAA,IACA,IAAI,OAAA,GAAU;AACZ,MAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACd,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,sBAAA,GAAyB;AAC3B,MAAA,OAAO,IAAA,CAAK,sBAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACd,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,WAAA,GAAc;AAChB,MAAA,OAAO,IAAA,CAAK,WAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,gBAAA,GAAmB;AACrB,MAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,IAAA,GAAO;AACT,MAAA,IAAI,CAAC,KAAK,IAAA,EAAM;AAKd,QAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,UACV,IAAA,CAAK,MAAA;AAAA,UACL,iBAAA,CAAkB,IAAA,CAAK,WAAA,EAAa,IAAA,CAAK,MAAM;AAAA,SACjD;AAAA,MACF;AACA,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,GAAA,GAAM;AACR,MAAA,OAAO,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA,CAAE,GAAA;AAAA,IACtC,CAAA;AAAA,IACA,IAAI,IAAA,GAAO;AACT,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,YAAA,GAAe;AACjB,MAAA,OAAO,IAAA,CAAK,YAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,YAAA,GAAe;AACjB,MAAA,OAAO,IAAA,CAAK,YAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,WAAA,GAAc;AAChB,MAAA,OAAO,IAAA,CAAK,WAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,aAAA,GAAgB;AAClB,MAAA,OAAO,IAAA,CAAK,aAAA;AAAA,IACd,CAAA;AAAA,IACA,IAAI,MAAA,GAAS;AACX,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd;AAAA,GACF;AACF","file":"chunk-6K34BCUP.js","sourcesContent":["/**\n * @fileoverview The translations query key, on its own, importing nothing.\n *\n * Three places read the cached translations — `rootBeforeLoad`, the hydration\n * path in `tanstack/router.tsx`, and the lazy `i18n` accessor in\n * `twilight/context.ts` — and all three have to agree on the key or the\n * hydrated page misses the entry it was just handed and refetches. One\n * definition is the only way to keep that true.\n *\n * It lives here rather than in `api/translations.ts`, where it would naturally\n * sit, because **`twilight/context.ts` cannot afford that module's imports**.\n * `api/translations` pulls in `api/client`, which pulls in `ky`; `context.ts`\n * is imported directly by tests that mock `ky`, and adding that edge made six\n * of them stop being mocked and start issuing real requests to `api.salla.dev`\n * (`tests/routes/rootBeforeLoad.test.ts`, bisected to exactly this import). A\n * leaf module with no imports of its own cannot do that to anyone.\n */\n\n/**\n * @param locale is part of the key because each file on the CDN holds one\n * language. The global file this replaced carried every language and was\n * sliced after the cache, so a key without the locale was correct then and is\n * a wrong-language bug now: `/ar` → `/en` would reuse the Arabic entry.\n */\nexport function translationsQueryKey(locale: string): [string, string] {\n return ['translations', locale];\n}\n\n/**\n * The merchant's own wording for one store and one language.\n *\n * Separate from {@link translationsQueryKey} rather than folded into it,\n * because the two files have different lifetimes and different audiences: the\n * platform's copy is the same object for every store on the CDN, and this one\n * is a single merchant's overrides. Keeping them apart means a store with no\n * overrides never invalidates, refetches or dehydrates anything on its account.\n *\n * @param storeId is `settings.store.id` — the Optimus-encoded numeric id, which\n * is what names the object. It is safe in a key even though the locale-only key\n * deliberately avoids naming a store: that warning is about a store *resolved\n * from the request*, which differs between server and client. This one is read\n * out of the settings payload, so both sides compute it from the same\n * dehydrated data and agree.\n */\nexport function storeTranslationsQueryKey(\n storeId: string | number,\n locale: string\n): [string, string, string] {\n return ['translations', String(storeId), locale];\n}\n","/**\n * @fileoverview Composing one language's messages out of the query cache.\n *\n * **There are three places that build an i18n instance**, and they have to\n * agree on more than the key: `rootBeforeLoad`, the hydration path in\n * `tanstack/router.tsx`, and the lazy `i18n` accessor in `twilight/context.ts`.\n * When the platform's copy was the only source, agreeing on\n * `translationsQueryKey` was enough. It is not any more — a merchant's own\n * wording is a second cache entry, and a reader that knows about one and not\n * the other renders different text from the page beside it.\n *\n * That is exactly what shipped in #366: the server rendered the merchant's\n * words and hydration replaced them with the platform's, because only\n * `rootBeforeLoad` had been taught to merge. Greptile caught it. This module is\n * the single answer to \"what are the messages for this locale\", so the next\n * source cannot be added to one reader and forgotten in two.\n *\n * It lives beside `translations-key.ts` and imports nothing at runtime for the\n * same reason that file does: `twilight/context.ts` cannot afford\n * `api/translations`, which pulls in `api/client` and therefore `ky`, and tests\n * that mock `ky` stop being mocked the moment that edge exists.\n */\nimport type { QueryClient } from '@tanstack/react-query';\nimport { translationsQueryKey } from './translations-key';\nimport type { TranslationMessages } from '../providers/I18nProvider';\n\nexport type Messages = Record<string, unknown>;\n\nexport function isPlainObject(value: unknown): value is Messages {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * `overrides` laid over `base`, one leaf at a time.\n *\n * Recursive rather than a spread, because both files are nested by group\n * (`common.errors.500`) and a top-level spread would make a merchant who\n * overrode one string inside `common` lose every other string in it. The\n * merchant's value wins at the leaf, and a group they never touched is left\n * exactly as the platform sent it.\n *\n * A type conflict — one side an object where the other is a string — resolves\n * to the merchant's value. It is the more specific of the two and there is no\n * sensible way to merge a string into a group; the alternative, keeping the\n * platform's, would mean a merchant's edit silently doing nothing.\n */\nexport function mergeMessages(base: Messages, overrides: Messages): Messages {\n const merged: Messages = { ...base };\n\n for (const [key, value] of Object.entries(overrides)) {\n const existing = merged[key];\n merged[key] =\n isPlainObject(existing) && isPlainObject(value) ? mergeMessages(existing, value) : value;\n }\n\n return merged;\n}\n\n/**\n * This store's overrides for `locale`, if any were fetched into the cache.\n *\n * Found by **shape** rather than by asking the settings for a store id, and\n * that is deliberate: the two readers that were missing the merge have a\n * `queryClient` and a locale between them and nothing else, and reaching for\n * `api/store` from `twilight/context.ts` would drag `ky` in through the back\n * door. One document serves one store — a request naming a different one is\n * redirected with `reloadDocument` — so at most one such entry per locale\n * exists, and matching `['translations', <anything>, <locale>]` cannot pick up\n * somebody else's.\n */\nfunction cachedOverrides(queryClient: QueryClient, locale: string): Messages | undefined {\n const entries = queryClient.getQueriesData<Messages>({ queryKey: ['translations'] });\n\n for (const [key, data] of entries) {\n if (key.length === 3 && key[2] === locale && isPlainObject(data)) {\n return data;\n }\n }\n\n return undefined;\n}\n\n/**\n * The messages for `locale`: the platform's copy with this merchant's over it.\n *\n * Reads only — whoever wants the merchant's file in the cache has to have put\n * it there, which `rootBeforeLoad` does and only when the settings say there is\n * one. A reader that runs without it simply gets the platform's copy, which is\n * the same thing it got before any of this existed.\n */\nexport function messagesForLocale(\n queryClient: QueryClient | undefined,\n locale: string\n): TranslationMessages | undefined {\n const common = queryClient?.getQueryData<TranslationMessages>(translationsQueryKey(locale));\n const overrides = queryClient ? cachedOverrides(queryClient, locale) : undefined;\n\n return composeMessages(common, overrides, locale);\n}\n\n/**\n * The same composition from values rather than from the cache.\n *\n * `rootBeforeLoad` has both in hand already — it just awaited them — so it\n * composes directly instead of reading back what it put in.\n */\nexport function composeMessages(\n common: TranslationMessages | null | undefined,\n overrides: Messages | null | undefined,\n locale: string\n): TranslationMessages | undefined {\n if (!overrides || Object.keys(overrides).length === 0) return common ?? undefined;\n\n const base = common?.[`${locale}.trans`];\n\n return {\n [`${locale}.trans`]: mergeMessages(isPlainObject(base) ? base : {}, overrides) as Record<\n string,\n string\n >,\n };\n}\n","/**\n * Why a store's settings did not load:\n * - `no-store`: nothing named a store for this request;\n * - `timeout`: the Salla API did not answer in time;\n * - `not-found`: it answered that no store has that identifier;\n * - `http`: it answered with another error status;\n * - `network`: no answer arrived at all;\n * - `empty`: it answered without settings.\n */\nexport type SettingsErrorReason =\n 'no-store' | 'timeout' | 'not-found' | 'http' | 'network' | 'empty';\n\nexport interface SettingsErrorDetails {\n reason?: SettingsErrorReason;\n /** The API's status, when `reason` is `'http'` or `'not-found'`. */\n status?: number;\n}\n\nexport class SettingsError extends Error {\n /** Absent when nothing said why, e.g. `getTwilightContext().settings` read before they loaded. */\n readonly reason?: SettingsErrorReason;\n readonly status?: number;\n\n constructor(message?: string, details?: SettingsErrorDetails) {\n super(message ?? 'Store settings could not be loaded.');\n this.name = 'SettingsError';\n this.reason = details?.reason;\n this.status = details?.status;\n }\n}\n","import { createInstance, type i18n as I18nInstance } from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nexport type TranslationMessages = Record<string, Record<string, string>>;\n\n/**\n * Creates a new i18next instance for the given locale.\n *\n * @param locale - Active locale code, e.g. `'ar'`\n * @param translations - App translations from the Salla API (store-specific)\n * @param themeTranslations - Bundled theme translations (static defaults)\n */\nexport function createI18nInstance(\n locale: string,\n translations?: TranslationMessages,\n themeTranslations?: TranslationMessages\n): I18nInstance {\n const instance = createInstance();\n const transKey = `${locale}.trans`;\n\n instance.use(initReactI18next).init({\n lng: locale,\n fallbackLng: locale,\n ns: ['app', 'theme'],\n defaultNS: 'app',\n fallbackNS: 'theme',\n resources: {\n [locale]: {\n app: translations?.[transKey] ?? {},\n theme: themeTranslations?.[transKey] ?? {},\n },\n },\n interpolation: { escapeValue: false },\n react: { useSuspense: false },\n keySeparator: '.',\n nsSeparator: false,\n });\n\n return instance;\n}\n\n/**\n * Creates i18n instance for testing\n * @param locale - Locale code (default: 'ar')\n * @param translations - Optional translations\n */\nexport function createTestI18n(locale = 'ar', translations?: TranslationMessages): I18nInstance {\n return createI18nInstance(locale, translations);\n}\n","import type { QueryClient } from '@tanstack/react-query';\nimport type { i18n } from 'i18next';\nimport type { StoreContext } from '../api/store';\nimport type { AppSnippet, AppSettings } from '../api/apps';\nimport { FALLBACK_LOCALE, getLanguageInfo } from '../providers/locale-constants';\nimport { createI18nInstance } from '../providers/i18n-factory';\nimport { messagesForLocale } from '../api/messages';\nimport { SettingsError } from '../utils/errors';\nimport type { ActiveScope } from '../utils/cookies';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TwilightLocation<TSearch = Record<string, unknown>> {\n href: string;\n pathname: string;\n search: TSearch;\n searchStr: string;\n state: Record<string, unknown>;\n hash: string;\n}\n\nexport interface PageContext {\n slug: string;\n id?: string | number;\n title: string;\n url?: string;\n parent?: { id: string | number; name: string; url: string } | null;\n breadcrumbs?: { name: string; url: string }[];\n}\n\nexport interface TwilightContext {\n queryClient: QueryClient;\n settings: StoreContext;\n locale: string;\n routeId: string;\n location: TwilightLocation;\n authToken: string | null;\n /**\n * The selected market and, once bullet delivery confirmed one, its branch\n * allocation — the full object the SDK sends as `s-scope-*` headers. Seeded from\n * the `scope` cookie on the server; see {@link ActiveScope}.\n */\n scope: ActiveScope | null;\n /** `scope.id`, kept for callers that only need the market. */\n scopeId: string | null;\n /**\n * Which store this request is for, when something other than the hostname says\n * so — the `?storeId=` a preview was opened with, or the cookie remembering it.\n *\n * Null on a live storefront, where the hostname is the answer and there is\n * nothing to carry. See {@link resolveRequestStoreId}.\n */\n storeId: string | null;\n /**\n * Which store the first segment of this request's path named, on a host where\n * the store is the root of every URL: `mtgr-alaatr-2` for\n * `https://preview.salla.design/mtgr-alaatr-2/cart`.\n *\n * Null whenever something else named the store, and on every merchant domain.\n * See {@link resolveRequestStoreBase}.\n */\n storeBase: string | null;\n /**\n * Where {@link storeBase} sits in this request's paths: behind the locale on a\n * Salla shared host (`/ar/dev-x/cart`, named by the dispatcher), in front of it\n * everywhere else. See {@link resolveAddressedStore}.\n */\n storeBaseFollowsLocale: boolean;\n /**\n * Which version of the theme's settings this request asked for — the\n * `?versionId=` an editor preview or a local dev session was opened with, or\n * the cookie remembering it.\n *\n * Null on an ordinary storefront visit, which is the common case: nothing\n * named a version, so the store's live one is what the API answers with. See\n * {@link resolveRequestVersionId}.\n */\n versionId: string | null;\n /**\n * The host this request arrived on, captured server-side.\n *\n * A theme worker is deployed with no vars and no bindings, so the request is\n * the only thing that knows which storefront it is serving. Null in the browser,\n * where nothing sets it: read {@link currentHost}, which falls back to\n * `window.location.host`, rather than this.\n */\n requestHost: string | null;\n /** The native app's `s-app-*` headers when the request came from its webview; see {@link readNativeAppHeaders}. */\n nativeAppHeaders: Record<string, string> | null;\n i18n: i18n;\n dir: 'ltr' | 'rtl';\n page?: PageContext;\n /** Installed apps' snippets, fetched in rootBeforeLoad so AppsSnippets can render CDN\n * <script> tags during SSR (React Query isn't dehydrated here, so useQuery has no SSR data). */\n appsSnippets?: AppSnippet[];\n /** Per-app public `app.*` buckets, fetched in rootBeforeLoad so rootHead can install the\n * `Salla.appScope` factory inline at parse time — ahead of the snippets' onReady callbacks. */\n appsSettings?: AppSettings;\n /**\n * This visitor sees the maintenance page, not the store. Decided in rootBeforeLoad\n * from `settings.maintenance` and the merchant's owner view; see `utils/maintenance`.\n */\n maintenance: boolean;\n /**\n * The Salla API answered that no store has the identifier this request named. Set by\n * rootBeforeLoad; `twilightMiddleware` answers with Twig's 410 page instead of the render.\n */\n storeNotFound: boolean;\n extras?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Internal Store\n// ============================================================================\n\nconst DEFAULT_LOCATION: TwilightLocation = {\n href: '',\n pathname: '',\n search: {},\n searchStr: '',\n state: {},\n hash: '',\n};\n\ninterface ContextData {\n queryClient: QueryClient;\n settings: StoreContext | null;\n locale: string;\n routeId: string;\n location: TwilightLocation;\n authToken: string | null;\n scope: ActiveScope | null;\n storeId: string | null;\n storeBase: string | null;\n storeBaseFollowsLocale: boolean;\n versionId: string | null;\n requestHost: string | null;\n nativeAppHeaders: Record<string, string> | null;\n i18n?: i18n;\n page?: PageContext;\n appsSnippets?: AppSnippet[];\n appsSettings?: AppSettings;\n maintenance: boolean;\n storeNotFound: boolean;\n extras?: Record<string, unknown>;\n}\n\nconst DEFAULT_DATA: ContextData = {\n queryClient: null as unknown as QueryClient,\n settings: null,\n locale: FALLBACK_LOCALE,\n routeId: '',\n location: { ...DEFAULT_LOCATION },\n authToken: null,\n scope: null,\n storeId: null,\n storeBase: null,\n storeBaseFollowsLocale: false,\n versionId: null,\n requestHost: null,\n nativeAppHeaders: null,\n i18n: undefined,\n page: undefined,\n maintenance: false,\n storeNotFound: false,\n};\n\n// ============================================================================\n// Storage: AsyncLocalStorage (server) or module-level store (client)\n// ============================================================================\n\ntype AsyncLocalStore<T> = { getStore(): T | undefined; run(val: T, fn: () => unknown): unknown };\n\n// Initialize ALS at module load time for SSR — no race condition\ntype AsyncHooks = { AsyncLocalStorage: new <T>() => AsyncLocalStore<T> };\n\n// workerd has no global `require`, so a bundled `require()` throws there; it does have\n// `process.getBuiltinModule` (so does Node >= 20.16), which keeps this out of the browser bundle.\nfunction loadAsyncHooks(): AsyncHooks | null {\n const proc = (globalThis as { process?: { getBuiltinModule?: (id: string) => unknown } }).process;\n try {\n const builtin = proc?.getBuiltinModule?.('node:async_hooks') as AsyncHooks | undefined;\n if (builtin?.AsyncLocalStorage) return builtin;\n } catch {\n /* fall through to require */\n }\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require('node:async_hooks') as AsyncHooks;\n } catch {\n return null;\n }\n}\n\nconst isServer = typeof window === 'undefined';\n// One instance per isolate, so a re-evaluated or duplicated copy of this module (dev\n// reloads, src next to dist) reads the scope the request middleware opened.\nconst ALS_KEY = Symbol.for('salla.twilight.context.als');\nlet _als: AsyncLocalStore<ContextData> | null = null;\nif (isServer) {\n const registry = globalThis as { [ALS_KEY]?: AsyncLocalStore<ContextData> };\n const hooks = registry[ALS_KEY] ? null : loadAsyncHooks();\n if (hooks) registry[ALS_KEY] = new hooks.AsyncLocalStorage<ContextData>();\n _als = registry[ALS_KEY] ?? null;\n}\n\n// Without request isolation every request would share `clientStore`: one visitor's\n// auth token and store settings rendered into another's page.\nfunction assertRequestIsolation(): void {\n if (isServer && !_als) {\n throw new Error(\n '[Twilight] AsyncLocalStorage is unavailable; refusing to share request state.'\n );\n }\n}\n\n// The browser's store, shared by every copy of this module on the page like the ALS above,\n// so a loader in one copy reads the location and token the router wrote through another.\nconst CLIENT_KEY = Symbol.for('salla.twilight.context.client');\nconst clientRegistry = globalThis as {\n [CLIENT_KEY]?: { store: ContextData; listeners: Set<() => void> };\n};\nconst clientShared = (clientRegistry[CLIENT_KEY] ??= {\n store: { ...DEFAULT_DATA },\n listeners: new Set<() => void>(),\n});\nconst clientStore: ContextData = clientShared.store;\n\nfunction getTwilightStore(): ContextData {\n assertRequestIsolation();\n if (_als) {\n const store = _als.getStore();\n if (!store)\n throw new Error('[Twilight] No request context. Wrap with runWithTwilightContext().');\n return store;\n }\n return clientStore;\n}\n\nfunction writableStore(): ContextData {\n if (_als) {\n const store = _als.getStore();\n if (store) return store;\n }\n return clientStore;\n}\n\nfunction mergeIntoStore(store: ContextData, partial: Partial<TwilightContext>): void {\n if ('queryClient' in partial && partial.queryClient) store.queryClient = partial.queryClient;\n if ('settings' in partial && partial.settings != null) store.settings = partial.settings;\n if ('locale' in partial && partial.locale != null) store.locale = partial.locale;\n if ('routeId' in partial && partial.routeId != null) store.routeId = partial.routeId;\n if ('location' in partial && partial.location != null)\n store.location = { ...store.location, ...partial.location };\n if ('authToken' in partial && partial.authToken !== undefined)\n store.authToken = partial.authToken ?? null;\n if ('scope' in partial && partial.scope !== undefined) store.scope = partial.scope ?? null;\n else if ('scopeId' in partial && partial.scopeId !== undefined)\n store.scope = partial.scopeId == null ? null : { id: partial.scopeId };\n if ('storeId' in partial && partial.storeId !== undefined)\n store.storeId = partial.storeId ?? null;\n if ('storeBase' in partial && partial.storeBase !== undefined)\n store.storeBase = partial.storeBase ?? null;\n if ('storeBaseFollowsLocale' in partial && partial.storeBaseFollowsLocale !== undefined)\n store.storeBaseFollowsLocale = partial.storeBaseFollowsLocale === true;\n if ('versionId' in partial && partial.versionId !== undefined)\n store.versionId = partial.versionId ?? null;\n if ('requestHost' in partial && partial.requestHost !== undefined)\n store.requestHost = partial.requestHost ?? null;\n if ('nativeAppHeaders' in partial && partial.nativeAppHeaders !== undefined)\n store.nativeAppHeaders = partial.nativeAppHeaders ?? null;\n if ('i18n' in partial && partial.i18n != null) store.i18n = partial.i18n;\n if ('page' in partial) store.page = partial.page;\n if ('appsSnippets' in partial) store.appsSnippets = partial.appsSnippets;\n if ('appsSettings' in partial) store.appsSettings = partial.appsSettings;\n if ('maintenance' in partial) store.maintenance = partial.maintenance === true;\n if ('storeNotFound' in partial) store.storeNotFound = partial.storeNotFound === true;\n if ('extras' in partial) store.extras = partial.extras;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\nexport function runWithTwilightContext<T>(partial: Partial<TwilightContext>, fn: () => T): T {\n assertRequestIsolation();\n if (_als) {\n const data: ContextData = { ...DEFAULT_DATA };\n mergeIntoStore(data, partial);\n return _als.run(data, fn) as T;\n }\n mergeIntoStore(clientStore, partial);\n return fn();\n}\n\n// Client-only subscription so React consumers (useRouteId/useIsHome/…) re-render\n// when navigation mutates the module store. Mirrors hooks/useWishlist.ts.\nconst listeners = clientShared.listeners;\n\nexport function subscribeTwilight(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function updateTwilightContext(partial: Partial<TwilightContext>): void {\n mergeIntoStore(getTwilightStore(), partial);\n // Server uses AsyncLocalStorage and has no React subscribers; notify on client only.\n if (typeof window !== 'undefined') {\n for (const listener of listeners) listener();\n }\n}\n\n/**\n * Whether store settings are available, without throwing.\n *\n * `getTwilightContext().settings` throws a `SettingsError` when the store is\n * empty, which is fatal inside a head function during hydration. Callers that\n * need to *test* availability must use this instead of a try/catch around the\n * getter. Returns false when there is no request context at all (server-side\n * calls outside `runWithTwilightContext`).\n */\nexport function hasTwilightSettings(): boolean {\n try {\n return getTwilightStore().settings != null;\n } catch {\n return false;\n }\n}\n\n/** What a request addressed, as opposed to what it is. */\nexport interface RequestAddressing {\n storeId: string | null;\n storeBase: string | null;\n storeBaseFollowsLocale: boolean;\n versionId: string | null;\n requestHost: string | null;\n}\n\n/**\n * What this request named and the host it arrived on, without throwing.\n *\n * Separate from {@link getTwilightContext} because store identity is read while\n * deciding *what to fetch* — before there is a context worth having — and on the\n * server outside a request the getter throws. A caller asking \"which store?\" has\n * a sane answer for \"none named\"; it has none for an exception.\n *\n * The version rides along rather than getting an accessor of its own: it is read\n * at the same moment, for the same reason, and by the same callers, and a second\n * copy of this try/catch would be a second thing to remember to widen.\n */\nexport function getRequestStore(): RequestAddressing {\n try {\n const data = getTwilightStore();\n return {\n storeId: data.storeId,\n storeBase: data.storeBase,\n storeBaseFollowsLocale: data.storeBaseFollowsLocale,\n versionId: data.versionId,\n requestHost: data.requestHost,\n };\n } catch {\n return {\n storeId: null,\n storeBase: null,\n storeBaseFollowsLocale: false,\n versionId: null,\n requestHost: null,\n };\n }\n}\n\nexport function getTwilightContext(): TwilightContext {\n const data = getTwilightStore();\n return {\n get queryClient() {\n return data.queryClient;\n },\n get settings() {\n if (!data.settings) throw new SettingsError();\n return data.settings;\n },\n get locale() {\n return data.locale;\n },\n get routeId() {\n return data.routeId;\n },\n get location() {\n return data.location;\n },\n get authToken() {\n return data.authToken;\n },\n get scope() {\n return data.scope;\n },\n get scopeId() {\n return data.scope?.id ?? null;\n },\n get storeId() {\n return data.storeId;\n },\n get storeBase() {\n return data.storeBase;\n },\n get storeBaseFollowsLocale() {\n return data.storeBaseFollowsLocale;\n },\n get versionId() {\n return data.versionId;\n },\n get requestHost() {\n return data.requestHost;\n },\n get nativeAppHeaders() {\n return data.nativeAppHeaders;\n },\n get i18n() {\n if (!data.i18n) {\n // Composed the same way as `rootBeforeLoad` and the hydration path —\n // the platform's copy with this merchant's over it. See\n // `api/messages.ts`: this accessor reading one entry while the others\n // read two is precisely the drift that module exists to stop.\n data.i18n = createI18nInstance(\n data.locale,\n messagesForLocale(data.queryClient, data.locale)\n );\n }\n return data.i18n;\n },\n get dir() {\n return getLanguageInfo(data.locale).dir;\n },\n get page() {\n return data.page;\n },\n get appsSnippets() {\n return data.appsSnippets;\n },\n get appsSettings() {\n return data.appsSettings;\n },\n get maintenance() {\n return data.maintenance;\n },\n get storeNotFound() {\n return data.storeNotFound;\n },\n get extras() {\n return data.extras;\n },\n };\n}\n\n/** @internal Reset store for testing */\nexport function resetForTesting(): void {\n Object.assign(writableStore(), { ...DEFAULT_DATA });\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { rememberProductPreview } from './chunk-BYLNAYIZ.js';
2
- import { getActiveScope, api } from './chunk-RQG44QD7.js';
1
+ import { rememberProductPreview } from './chunk-LUPDYN4T.js';
2
+ import { getActiveScope, api } from './chunk-E5DP3MHE.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
5
5
  var wishlist = {
@@ -31,5 +31,5 @@ var wishlist = {
31
31
  };
32
32
 
33
33
  export { wishlist };
34
- //# sourceMappingURL=chunk-QIJJTWW6.js.map
35
- //# sourceMappingURL=chunk-QIJJTWW6.js.map
34
+ //# sourceMappingURL=chunk-6VYW7CVL.js.map
35
+ //# sourceMappingURL=chunk-6VYW7CVL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/wishlist.ts"],"names":[],"mappings":";;;;AAmBO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,MAAA,GAA6B,EAAC,KAAmC;AAC5E,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,UAAU,EAAA,EAAI,UAAA,EAAY,QAAO,GAAI,MAAA;AAEvD,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAU,UAAU,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAA,GAAa,GAAA,GAAM,GAAG,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,SAAA,EAAY,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CACzD,IAAA,EAA2B;AAE9B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,IAAQ,EAAC;AAChC,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,sBAAA,CAAuB,IAAI,CAAA;AAErD,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,IAAA,EAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,IAAQ;AAAA,KACjC;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,MAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,UAAA,EAAY,MAAA,EAAQ,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MAClE,OAAA,EAAS,CAAC,EAAE,MAAA,EAAO,KAAM,QAAA,CAAS,IAAA,CAAK,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ;AAAA,KAC7D;AAAA;AAEP","file":"chunk-QIJJTWW6.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport {\n rememberProductPreview,\n type ProductsListResult,\n type ProductsListResponse,\n} from './product';\n\nexport interface WishlistListParams {\n page?: number;\n perPage?: number;\n filterable?: boolean;\n signal?: AbortSignal;\n}\n\n/**\n * Wishlist API — page-based pagination only.\n * Kept separate from product.list to avoid mixing cursor and page pagination strategies.\n */\nexport const wishlist = {\n list: async (params: WishlistListParams = {}): Promise<ProductsListResult> => {\n const { page = 1, perPage = 15, filterable, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('source', 'wishlist');\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n if (filterable !== undefined) {\n searchParams.set('filterable', filterable ? '1' : '0');\n }\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`products?${searchParams.toString()}`, options as any)\n .json<ProductsListResponse>();\n\n const items = response.data ?? [];\n for (const item of items) rememberProductPreview(item);\n\n return {\n items,\n next: response.cursor?.next ?? null,\n };\n },\n\n queries: {\n list: (params: Omit<WishlistListParams, 'signal'>) =>\n queryOptions({\n queryKey: ['wishlist', 'list', params, { scope: getActiveScope() }],\n queryFn: ({ signal }) => wishlist.list({ ...params, signal }),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/wishlist.ts"],"names":[],"mappings":";;;;AAmBO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,MAAA,GAA6B,EAAC,KAAmC;AAC5E,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,UAAU,EAAA,EAAI,UAAA,EAAY,QAAO,GAAI,MAAA;AAEvD,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAU,UAAU,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAA,GAAa,GAAA,GAAM,GAAG,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,SAAA,EAAY,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CACzD,IAAA,EAA2B;AAE9B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,IAAQ,EAAC;AAChC,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,sBAAA,CAAuB,IAAI,CAAA;AAErD,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,IAAA,EAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,IAAQ;AAAA,KACjC;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,MAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,UAAA,EAAY,MAAA,EAAQ,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MAClE,OAAA,EAAS,CAAC,EAAE,MAAA,EAAO,KAAM,QAAA,CAAS,IAAA,CAAK,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ;AAAA,KAC7D;AAAA;AAEP","file":"chunk-6VYW7CVL.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport {\n rememberProductPreview,\n type ProductsListResult,\n type ProductsListResponse,\n} from './product';\n\nexport interface WishlistListParams {\n page?: number;\n perPage?: number;\n filterable?: boolean;\n signal?: AbortSignal;\n}\n\n/**\n * Wishlist API — page-based pagination only.\n * Kept separate from product.list to avoid mixing cursor and page pagination strategies.\n */\nexport const wishlist = {\n list: async (params: WishlistListParams = {}): Promise<ProductsListResult> => {\n const { page = 1, perPage = 15, filterable, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('source', 'wishlist');\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n if (filterable !== undefined) {\n searchParams.set('filterable', filterable ? '1' : '0');\n }\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`products?${searchParams.toString()}`, options as any)\n .json<ProductsListResponse>();\n\n const items = response.data ?? [];\n for (const item of items) rememberProductPreview(item);\n\n return {\n items,\n next: response.cursor?.next ?? null,\n };\n },\n\n queries: {\n list: (params: Omit<WishlistListParams, 'signal'>) =>\n queryOptions({\n queryKey: ['wishlist', 'list', params, { scope: getActiveScope() }],\n queryFn: ({ signal }) => wishlist.list({ ...params, signal }),\n }),\n },\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { api } from './chunk-RQG44QD7.js';
1
+ import { api } from './chunk-E5DP3MHE.js';
2
2
  import { queryOptions } from '@tanstack/react-query';
3
3
 
4
4
  var apps = {
@@ -40,5 +40,5 @@ var apps = {
40
40
  };
41
41
 
42
42
  export { apps };
43
- //# sourceMappingURL=chunk-JUFJV4AK.js.map
44
- //# sourceMappingURL=chunk-JUFJV4AK.js.map
43
+ //# sourceMappingURL=chunk-7U5OLKOS.js.map
44
+ //# sourceMappingURL=chunk-7U5OLKOS.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/apps.ts"],"names":[],"mappings":";;;AAmCO,IAAM,IAAA,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKlB,UAAU,YAAmC;AAC3C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,eAAA,EAAiB,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CACtC,IAAA,EAA8B;AACjC,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,YAAkC;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,wBAAA,EAA0B,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CAC/C,IAAA,EAAsC;AACzC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,IAAQ,EAAC,EAAE;AAAA,EAClC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA;AAAA;AAAA;AAAA,MAIX,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,IAEH,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA,MACX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-JUFJV4AK.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\n\nexport interface AppSnippetRow {\n place: string;\n content: string;\n url?: string | null;\n /**\n * Raw snippet id, emitted as `data-snippet-id`. Present only on CDN rows — the\n * inline branch of the backend's snippet parser omits the key entirely.\n */\n id?: number;\n /** `{{customer.x}}` placeholders in `content` to substitute from SDK config `user.*` keys. */\n customer_parameters?: string[];\n}\n\nexport interface AppSnippet {\n service: string;\n app_id: string;\n /** Encoded app id (`getRouteKey()`): the scope id its snippets bind to via `data-scope-id`,\n * and its settings-bucket key. Absent on payloads predating the settings API. */\n id?: string;\n app_slug: string;\n status: string;\n snippets: AppSnippetRow[];\n}\n\n/**\n * Per-app public `app.*` buckets for CDN snippets, keyed by encoded app id (== `AppSnippet.id`,\n * the `Salla.appScope` scope id). One isolated bucket per app; reads within a scope are bare `app.*`.\n */\nexport interface AppSettings {\n apps: Record<string, Record<string, unknown>>;\n}\n\nexport const apps = {\n /**\n * Installed apps' snippets (scripts/HTML to inject). Timeout-bounded because it's awaited in\n * rootBeforeLoad (SSR/TTFB): a slow response degrades to no CDN tags, never stalls the page.\n */\n snippets: async (): Promise<AppSnippet[]> => {\n const { data } = await api\n .get('apps/snippets', { timeout: 2500 })\n .json<{ data?: AppSnippet[] }>();\n return data ?? [];\n },\n\n /**\n * Per-app public `app.*` buckets, keyed by encoded app id. Timeout-bounded (SSR-awaited):\n * a slow response degrades to empty buckets (fail-open), never strands injection.\n */\n settings: async (): Promise<AppSettings> => {\n const { data } = await api\n .get('apps/snippets/settings', { timeout: 2500 })\n .json<{ data?: Partial<AppSettings> }>();\n return { apps: data?.apps ?? {} };\n },\n\n queries: {\n snippets: () =>\n queryOptions({\n queryKey: ['apps', 'snippets'],\n queryFn: () => apps.snippets(),\n // Snippets are static per session; one fetch per page load is enough.\n staleTime: Infinity,\n // No retry: this is awaited in rootBeforeLoad, so the router's default `retry: 1` would\n // make the SSR wait 2 x the 2500ms timeout (plus backoff) before failing open. The\n // 2500ms timeout must be the whole budget; the client fallback query does the retrying.\n retry: 0,\n }),\n\n settings: () =>\n queryOptions({\n queryKey: ['apps', 'settings'],\n queryFn: () => apps.settings(),\n // Encoded app ids and their buckets are stable per page; one fetch is enough.\n staleTime: Infinity,\n retry: 0,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/apps.ts"],"names":[],"mappings":";;;AAmCO,IAAM,IAAA,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKlB,UAAU,YAAmC;AAC3C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,eAAA,EAAiB,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CACtC,IAAA,EAA8B;AACjC,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,YAAkC;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,wBAAA,EAA0B,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CAC/C,IAAA,EAAsC;AACzC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,IAAQ,EAAC,EAAE;AAAA,EAClC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA;AAAA;AAAA;AAAA,MAIX,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,IAEH,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA,MACX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-7U5OLKOS.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\n\nexport interface AppSnippetRow {\n place: string;\n content: string;\n url?: string | null;\n /**\n * Raw snippet id, emitted as `data-snippet-id`. Present only on CDN rows — the\n * inline branch of the backend's snippet parser omits the key entirely.\n */\n id?: number;\n /** `{{customer.x}}` placeholders in `content` to substitute from SDK config `user.*` keys. */\n customer_parameters?: string[];\n}\n\nexport interface AppSnippet {\n service: string;\n app_id: string;\n /** Encoded app id (`getRouteKey()`): the scope id its snippets bind to via `data-scope-id`,\n * and its settings-bucket key. Absent on payloads predating the settings API. */\n id?: string;\n app_slug: string;\n status: string;\n snippets: AppSnippetRow[];\n}\n\n/**\n * Per-app public `app.*` buckets for CDN snippets, keyed by encoded app id (== `AppSnippet.id`,\n * the `Salla.appScope` scope id). One isolated bucket per app; reads within a scope are bare `app.*`.\n */\nexport interface AppSettings {\n apps: Record<string, Record<string, unknown>>;\n}\n\nexport const apps = {\n /**\n * Installed apps' snippets (scripts/HTML to inject). Timeout-bounded because it's awaited in\n * rootBeforeLoad (SSR/TTFB): a slow response degrades to no CDN tags, never stalls the page.\n */\n snippets: async (): Promise<AppSnippet[]> => {\n const { data } = await api\n .get('apps/snippets', { timeout: 2500 })\n .json<{ data?: AppSnippet[] }>();\n return data ?? [];\n },\n\n /**\n * Per-app public `app.*` buckets, keyed by encoded app id. Timeout-bounded (SSR-awaited):\n * a slow response degrades to empty buckets (fail-open), never strands injection.\n */\n settings: async (): Promise<AppSettings> => {\n const { data } = await api\n .get('apps/snippets/settings', { timeout: 2500 })\n .json<{ data?: Partial<AppSettings> }>();\n return { apps: data?.apps ?? {} };\n },\n\n queries: {\n snippets: () =>\n queryOptions({\n queryKey: ['apps', 'snippets'],\n queryFn: () => apps.snippets(),\n // Snippets are static per session; one fetch per page load is enough.\n staleTime: Infinity,\n // No retry: this is awaited in rootBeforeLoad, so the router's default `retry: 1` would\n // make the SSR wait 2 x the 2500ms timeout (plus backoff) before failing open. The\n // 2500ms timeout must be the whole budget; the client fallback query does the retrying.\n retry: 0,\n }),\n\n settings: () =>\n queryOptions({\n queryKey: ['apps', 'settings'],\n queryFn: () => apps.settings(),\n // Encoded app ids and their buckets are stable per page; one fetch is enough.\n staleTime: Infinity,\n retry: 0,\n }),\n },\n};\n"]}
@@ -1,5 +1,5 @@
1
- import { orThrow } from './chunk-4UEXSD7E.js';
2
- import { api } from './chunk-RQG44QD7.js';
1
+ import { orThrow } from './chunk-RLJLG4EN.js';
2
+ import { api } from './chunk-E5DP3MHE.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
5
5
  var blog = {
@@ -63,5 +63,5 @@ var blog = {
63
63
  };
64
64
 
65
65
  export { blog };
66
- //# sourceMappingURL=chunk-B3DGM7TM.js.map
67
- //# sourceMappingURL=chunk-B3DGM7TM.js.map
66
+ //# sourceMappingURL=chunk-A5AU64GV.js.map
67
+ //# sourceMappingURL=chunk-A5AU64GV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/blog.ts"],"names":[],"mappings":"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","file":"chunk-B3DGM7TM.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport type { Options as KyOptions } from 'ky';\nimport { api } from './client';\nimport type { Pagination } from './types';\nimport type {\n ArticleSummary,\n ArticleDetail,\n BlogAuthor,\n BlogCategory,\n BlogTag,\n BlogOverview,\n} from '../routes/blog/types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport interface BlogArticlesListParams {\n category?: string;\n author?: string;\n tag?: string;\n page?: number;\n cursor?: string | null;\n signal?: AbortSignal;\n}\n\nexport interface BlogArticlesListResponse {\n data: ArticleSummary[];\n categories?: BlogCategory[];\n category: BlogCategory;\n author: BlogAuthor;\n tag: BlogTag;\n cursor: Pagination;\n}\n\nexport interface BlogGetResponse {\n data: {\n categories: BlogCategory[] | null;\n slides: ArticleSummary[] | null;\n articles: ArticleSummary[] | null;\n popular: ArticleSummary[] | null;\n };\n}\n\nexport const blog = {\n get: async (signal?: AbortSignal): Promise<BlogOverview> => {\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api.get('blog', options as KyOptions).json<BlogGetResponse>();\n\n return {\n categories: response.data.categories ?? [],\n slides: response.data.slides ?? [],\n articles: response.data.articles ?? [],\n popular: response.data.popular ?? [],\n };\n },\n\n articles: {\n list: async (params?: BlogArticlesListParams): Promise<BlogArticlesListResponse> => {\n const { category, author, tag, page, cursor, signal } = params ?? {};\n\n const searchParams = new URLSearchParams();\n if (page !== undefined) searchParams.set('page', String(page));\n if (cursor) searchParams.set('cursor', cursor);\n if (category) searchParams.set('category', category);\n if (author) searchParams.set('author', author);\n if (tag) searchParams.set('tag', tag);\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`blog/articles?${searchParams.toString()}`, options as KyOptions)\n .json<{\n data: ArticleSummary[] | null;\n categories?: BlogCategory[] | null;\n category: BlogCategory;\n author: BlogAuthor;\n tag: BlogTag;\n cursor: Pagination;\n }>();\n\n return {\n data: response.data ?? [],\n categories: response.categories ?? undefined,\n category: response.category,\n author: response.author,\n tag: response.tag,\n cursor: response.cursor,\n };\n },\n\n find: async (id: string, signal?: AbortSignal): Promise<ArticleDetail> => {\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`blog/articles/${id}`, options as KyOptions)\n .json<{ data: ArticleDetail | null }>();\n\n if (!response.data) {\n throw new Error(`Article ${id} not found`);\n }\n\n return response.data;\n },\n\n findOrThrow: (id: string, signal?: AbortSignal): Promise<ArticleDetail> =>\n orThrow(blog.articles.find(id, signal)),\n },\n\n queries: {\n overview: () =>\n queryOptions({\n queryKey: ['blog', 'overview'],\n queryFn: ({ signal }) => blog.get(signal),\n }),\n articles: (params?: Omit<BlogArticlesListParams, 'signal'>) =>\n queryOptions({\n queryKey: ['blog', 'articles', params],\n queryFn: ({ signal }) => blog.articles.list({ ...params, signal }),\n }),\n article: (id: string) =>\n queryOptions({\n queryKey: ['blog', 'article', id],\n queryFn: ({ signal }) => blog.articles.find(id, signal),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/blog.ts"],"names":[],"mappings":"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","file":"chunk-A5AU64GV.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport type { Options as KyOptions } from 'ky';\nimport { api } from './client';\nimport type { Pagination } from './types';\nimport type {\n ArticleSummary,\n ArticleDetail,\n BlogAuthor,\n BlogCategory,\n BlogTag,\n BlogOverview,\n} from '../routes/blog/types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport interface BlogArticlesListParams {\n category?: string;\n author?: string;\n tag?: string;\n page?: number;\n cursor?: string | null;\n signal?: AbortSignal;\n}\n\nexport interface BlogArticlesListResponse {\n data: ArticleSummary[];\n categories?: BlogCategory[];\n category: BlogCategory;\n author: BlogAuthor;\n tag: BlogTag;\n cursor: Pagination;\n}\n\nexport interface BlogGetResponse {\n data: {\n categories: BlogCategory[] | null;\n slides: ArticleSummary[] | null;\n articles: ArticleSummary[] | null;\n popular: ArticleSummary[] | null;\n };\n}\n\nexport const blog = {\n get: async (signal?: AbortSignal): Promise<BlogOverview> => {\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api.get('blog', options as KyOptions).json<BlogGetResponse>();\n\n return {\n categories: response.data.categories ?? [],\n slides: response.data.slides ?? [],\n articles: response.data.articles ?? [],\n popular: response.data.popular ?? [],\n };\n },\n\n articles: {\n list: async (params?: BlogArticlesListParams): Promise<BlogArticlesListResponse> => {\n const { category, author, tag, page, cursor, signal } = params ?? {};\n\n const searchParams = new URLSearchParams();\n if (page !== undefined) searchParams.set('page', String(page));\n if (cursor) searchParams.set('cursor', cursor);\n if (category) searchParams.set('category', category);\n if (author) searchParams.set('author', author);\n if (tag) searchParams.set('tag', tag);\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`blog/articles?${searchParams.toString()}`, options as KyOptions)\n .json<{\n data: ArticleSummary[] | null;\n categories?: BlogCategory[] | null;\n category: BlogCategory;\n author: BlogAuthor;\n tag: BlogTag;\n cursor: Pagination;\n }>();\n\n return {\n data: response.data ?? [],\n categories: response.categories ?? undefined,\n category: response.category,\n author: response.author,\n tag: response.tag,\n cursor: response.cursor,\n };\n },\n\n find: async (id: string, signal?: AbortSignal): Promise<ArticleDetail> => {\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`blog/articles/${id}`, options as KyOptions)\n .json<{ data: ArticleDetail | null }>();\n\n if (!response.data) {\n throw new Error(`Article ${id} not found`);\n }\n\n return response.data;\n },\n\n findOrThrow: (id: string, signal?: AbortSignal): Promise<ArticleDetail> =>\n orThrow(blog.articles.find(id, signal)),\n },\n\n queries: {\n overview: () =>\n queryOptions({\n queryKey: ['blog', 'overview'],\n queryFn: ({ signal }) => blog.get(signal),\n }),\n articles: (params?: Omit<BlogArticlesListParams, 'signal'>) =>\n queryOptions({\n queryKey: ['blog', 'articles', params],\n queryFn: ({ signal }) => blog.articles.list({ ...params, signal }),\n }),\n article: (id: string) =>\n queryOptions({\n queryKey: ['blog', 'article', id],\n queryFn: ({ signal }) => blog.articles.find(id, signal),\n }),\n },\n};\n"]}
@@ -1,6 +1,6 @@
1
- import { getActiveCurrency } from './chunk-RQG44QD7.js';
2
- import { whenSallaLoaded } from './chunk-GYXUYHKO.js';
3
- import { getTwilightContext } from './chunk-7VNVCHID.js';
1
+ import { getActiveCurrency } from './chunk-E5DP3MHE.js';
2
+ import { whenSallaLoaded } from './chunk-NHA4SBKG.js';
3
+ import { getTwilightContext } from './chunk-6K34BCUP.js';
4
4
 
5
5
  // src/utils/sdk-events.ts
6
6
  function dispatchRouteChanged() {
@@ -36,5 +36,5 @@ function dispatchProductViewed(product) {
36
36
  }
37
37
 
38
38
  export { dispatchProductViewed, dispatchRouteChanged };
39
- //# sourceMappingURL=chunk-GG5DAIGJ.js.map
40
- //# sourceMappingURL=chunk-GG5DAIGJ.js.map
39
+ //# sourceMappingURL=chunk-AXWX5SJC.js.map
40
+ //# sourceMappingURL=chunk-AXWX5SJC.js.map