@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/utils/sdk-events.ts"],"names":[],"mappings":";;;;;AA6BO,SAAS,oBAAA,GAA6B;AAC3C,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,EAAA,IAAI,CAAC,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU;AAE7B,EAAA,MAAM,MAAM,kBAAA,EAAmB;AAC/B,EAAA,KAAA,CAAM,MAAM,QAAA,CAAS,gBAAA,EAAkB,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAA;AACvD;AAMO,SAAS,sBAAsB,OAAA,EAAwB;AAC5D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,GAAA,IAAO,EAAA;AACpC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAA,EAAY,OAAA,CAAQ,QAAA,GAAW,CAAC,EAAE,EAAA,EAAI,OAAA,CAAQ,QAAA,CAAS,EAAA,EAAI,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,IAAI,EAAC;AAAA,IAC7F,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU,IAAA,IAAQ,EAAA;AAAA,IACpC,KAAA;AAAA,IACA,QAAA,EAAU,CAAA;AAAA,IACV,OAAA,EAAS,EAAA;AAAA,IACT,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,IAAA,IAAQ,EAAA;AAAA,IAC9B,KAAA;AAAA,IACA,QAAA,EAAU,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC5C,GAAA,EAAK,QAAQ,GAAA,IAAO,EAAA;AAAA,IACpB,KAAA,EAAO,KAAA;AAAA,IACP,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACb;AAEA,EAAA,eAAA;AAAA,IACE,CAAC,GAAA,KAAQ,KAAK,GAAA,CAAI,SAAQ,CAAE,IAAA,CAAK,MAAM,GAAA,CAAI,MAAM,QAAA,CAAS,gBAAA,EAAkB,CAAC,OAAO,CAAC,CAAC;AAAA,GACxF;AACF","file":"chunk-GG5DAIGJ.js","sourcesContent":["import { getTwilightContext } from '../twilight/context';\nimport type { PageContext } from '../twilight/context';\nimport type { Product } from '../types';\nimport { getActiveCurrency } from '../api/client';\nimport { whenSallaLoaded } from './sdk-helpers';\n\n/**\n * Payload dispatched via `salla.event.dispatch('route::changed', payload)`\n * after each client-side navigation completes.\n *\n * The page config fields are spread at root level. When the matched route\n * has no page data (e.g., 404, error boundary), an empty object is dispatched.\n *\n * @example\n * ```ts\n * salla.event.on('route::changed', (page: RouteChangedEvent) => {\n * console.log(page.slug, page.title, page.id);\n * });\n * ```\n */\nexport type RouteChangedEvent = PageContext;\n\n/**\n * Dispatch the `route::changed` Salla SDK event with the current page config.\n *\n * Framework-agnostic — reads from the twilight context store which is\n * populated by whichever framework adapter is active (TanStack, Next.js, etc.).\n * Each adapter should call this after navigation resolves.\n */\nexport function dispatchRouteChanged(): void {\n if (typeof window === 'undefined') return;\n\n const salla = window.salla;\n if (!salla?.event?.dispatch) return;\n\n const ctx = getTwilightContext();\n salla.event.dispatch('route::changed', ctx.page ?? {});\n}\n\n/**\n * Dispatch `Product Viewed`, which Twig's product page hands the SDK through `salla.init`'s\n * `events`: store analytics, pixels and apps that remember viewed products listen for it.\n */\nexport function dispatchProductViewed(product: Product): void {\n if (typeof window === 'undefined') return;\n const price = Number(product.price) || 0;\n const image = product.image?.url ?? '';\n const payload = {\n id: product.id,\n name: product.name,\n categories: product.category ? [{ id: product.category.id, name: product.category.name }] : [],\n category: product.category?.name ?? '',\n price,\n quantity: 1,\n variant: '',\n brand: product.brand?.name ?? '',\n image,\n currency: getActiveCurrency(product.currency),\n sku: product.sku ?? '',\n value: price,\n url: product.url,\n image_url: image,\n };\n // After init: analytics drops events until `salla.init` has merged the store's `jitsu` list.\n whenSallaLoaded(\n (sdk) => void sdk.onReady().then(() => sdk.event.dispatch('Product Viewed', [payload]))\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/sdk-events.ts"],"names":[],"mappings":";;;;;AA6BO,SAAS,oBAAA,GAA6B;AAC3C,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,EAAA,IAAI,CAAC,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU;AAE7B,EAAA,MAAM,MAAM,kBAAA,EAAmB;AAC/B,EAAA,KAAA,CAAM,MAAM,QAAA,CAAS,gBAAA,EAAkB,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAA;AACvD;AAMO,SAAS,sBAAsB,OAAA,EAAwB;AAC5D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,GAAA,IAAO,EAAA;AACpC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAA,EAAY,OAAA,CAAQ,QAAA,GAAW,CAAC,EAAE,EAAA,EAAI,OAAA,CAAQ,QAAA,CAAS,EAAA,EAAI,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,IAAI,EAAC;AAAA,IAC7F,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU,IAAA,IAAQ,EAAA;AAAA,IACpC,KAAA;AAAA,IACA,QAAA,EAAU,CAAA;AAAA,IACV,OAAA,EAAS,EAAA;AAAA,IACT,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,IAAA,IAAQ,EAAA;AAAA,IAC9B,KAAA;AAAA,IACA,QAAA,EAAU,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC5C,GAAA,EAAK,QAAQ,GAAA,IAAO,EAAA;AAAA,IACpB,KAAA,EAAO,KAAA;AAAA,IACP,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACb;AAEA,EAAA,eAAA;AAAA,IACE,CAAC,GAAA,KAAQ,KAAK,GAAA,CAAI,SAAQ,CAAE,IAAA,CAAK,MAAM,GAAA,CAAI,MAAM,QAAA,CAAS,gBAAA,EAAkB,CAAC,OAAO,CAAC,CAAC;AAAA,GACxF;AACF","file":"chunk-AXWX5SJC.js","sourcesContent":["import { getTwilightContext } from '../twilight/context';\nimport type { PageContext } from '../twilight/context';\nimport type { Product } from '../types';\nimport { getActiveCurrency } from '../api/client';\nimport { whenSallaLoaded } from './sdk-helpers';\n\n/**\n * Payload dispatched via `salla.event.dispatch('route::changed', payload)`\n * after each client-side navigation completes.\n *\n * The page config fields are spread at root level. When the matched route\n * has no page data (e.g., 404, error boundary), an empty object is dispatched.\n *\n * @example\n * ```ts\n * salla.event.on('route::changed', (page: RouteChangedEvent) => {\n * console.log(page.slug, page.title, page.id);\n * });\n * ```\n */\nexport type RouteChangedEvent = PageContext;\n\n/**\n * Dispatch the `route::changed` Salla SDK event with the current page config.\n *\n * Framework-agnostic — reads from the twilight context store which is\n * populated by whichever framework adapter is active (TanStack, Next.js, etc.).\n * Each adapter should call this after navigation resolves.\n */\nexport function dispatchRouteChanged(): void {\n if (typeof window === 'undefined') return;\n\n const salla = window.salla;\n if (!salla?.event?.dispatch) return;\n\n const ctx = getTwilightContext();\n salla.event.dispatch('route::changed', ctx.page ?? {});\n}\n\n/**\n * Dispatch `Product Viewed`, which Twig's product page hands the SDK through `salla.init`'s\n * `events`: store analytics, pixels and apps that remember viewed products listen for it.\n */\nexport function dispatchProductViewed(product: Product): void {\n if (typeof window === 'undefined') return;\n const price = Number(product.price) || 0;\n const image = product.image?.url ?? '';\n const payload = {\n id: product.id,\n name: product.name,\n categories: product.category ? [{ id: product.category.id, name: product.category.name }] : [],\n category: product.category?.name ?? '',\n price,\n quantity: 1,\n variant: '',\n brand: product.brand?.name ?? '',\n image,\n currency: getActiveCurrency(product.currency),\n sku: product.sku ?? '',\n value: price,\n url: product.url,\n image_url: image,\n };\n // After init: analytics drops events until `salla.init` has merged the store's `jitsu` list.\n whenSallaLoaded(\n (sdk) => void sdk.onReady().then(() => sdk.event.dispatch('Product Viewed', [payload]))\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { useTranslation } from './chunk-TYNZ5B2B.js';
2
- import { getTwilightContext } from './chunk-7VNVCHID.js';
2
+ import { getTwilightContext } from './chunk-6K34BCUP.js';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  var THUMB_URL = "https://cdn.assets.salla.network/prod/stores/images/construction-01.png";
@@ -168,5 +168,5 @@ function MaintenancePage() {
168
168
  }
169
169
 
170
170
  export { MaintenancePage };
171
- //# sourceMappingURL=chunk-CKH6WBMA.js.map
172
- //# sourceMappingURL=chunk-CKH6WBMA.js.map
171
+ //# sourceMappingURL=chunk-CZ6VJPCG.js.map
172
+ //# sourceMappingURL=chunk-CZ6VJPCG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/store/MaintenancePage.tsx"],"names":[],"mappings":"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","file":"chunk-CKH6WBMA.js","sourcesContent":["import { getTwilightContext } from '../../twilight/context';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport type { Store, StoreSocial } from '../../types';\n\nconst THUMB_URL = 'https://cdn.assets.salla.network/prod/stores/images/construction-01.png';\nconst LAUNCHING_THUMB_URL =\n 'https://cdn.assets.salla.network/prod/stores/images/under-construction.png';\n\n/** Social networks the page links to, in the old page's order, with their Salla icon class. */\nconst SOCIAL_ICONS: [keyof StoreSocial, string][] = [\n ['twitter', 'sicon-x'],\n ['snapchat', 'sicon-snapchat'],\n ['youtube', 'sicon-youtube'],\n ['tiktok', 'sicon-tiktok'],\n ['facebook', 'sicon-facebook'],\n ['instagram', 'sicon-instagram'],\n];\n\n/** The store's social links the page shows, each with its icon class. */\nfunction socialLinks(store: Store | undefined) {\n return SOCIAL_ICONS.flatMap(([key, icon]) => {\n const href = store?.social?.[key];\n return href ? [{ key, icon, href }] : [];\n });\n}\n\n// The platform's maintenance page (Store `pages/maintenance.blade.php` + `_maintenance.scss`),\n// trimmed to what it renders: greyscale, logo + title beside the message, contacts under a\n// rule, the illustration alongside; stacked and centred under 1024px.\n//\n// The page is its own scroll container, the viewport tall, because app-shell themes lock\n// `html, body { overflow: hidden }` and scroll only their main element, which this page\n// replaces. Centring is by auto margins, not `justify-content`, so content taller than the\n// viewport starts at the top instead of being clipped at both ends.\nconst STYLE = `\n.s-maintenance{display:flex;flex-direction:column;align-items:center;width:100%;height:100vh;height:100dvh;overflow-y:auto;color:#a3a3a3;background:#fff;filter:grayscale(100%);box-sizing:border-box}\n.s-maintenance *{box-sizing:border-box}\n.s-maintenance .mt-container{width:100%;max-width:1200px;margin:auto 0;padding:0 15px}\n.s-maintenance .mt-panel{display:flex;flex-direction:row;align-items:center;justify-content:space-between;width:100%}\n.s-maintenance .mt-message{width:100%;padding-inline-start:80px;animation:revealMtBlock 1.5s forwards}\n.s-maintenance .mt-title{display:flex;align-items:center;margin:0 0 20px}\n.s-maintenance .mt-logo{display:block;flex-shrink:0;width:80px;height:80px;margin-inline-end:20px;border-radius:50%;overflow:hidden;box-shadow:0 0 5px rgb(0 0 0 / 10%)}\n.s-maintenance .mt-logo img{display:block;width:100%;height:100%;object-fit:cover}\n.s-maintenance .mt-title h1{font-size:2.25rem;line-height:1;margin:0;color:#666}\n.s-maintenance .mt-content p{margin:0;white-space:pre-line}\n.s-maintenance .mt-contact-list{display:inline-block;list-style:none;width:100%;max-width:500px;margin:20px 0 0;padding:20px 0 0;border-top:1px solid #eee}\n.s-maintenance .mt-contact-list li{display:inline-block;margin-inline-end:10px}\n.s-maintenance .mt-contact-list a{display:inline-flex;align-items:center;padding:5px;color:rgb(102 102 102 / 80%);text-decoration:none;font-size:1.25rem}\n.s-maintenance .mt-contact-list a:hover{color:#666}\n.s-maintenance .mt-contact--btn{padding:3px 20px 5px;border-radius:20px;color:#fff!important;background:rgb(102 102 102 / 80%);font-size:1rem!important}\n.s-maintenance .mt-contact--btn:hover{background:#666}\n.s-maintenance .mt-contact--btn i{margin-inline-end:10px}\n.s-maintenance .thumb{width:100%;animation:revealMtBlock 1.5s .1s forwards;opacity:0}\n.s-maintenance .thumb img{display:block;width:100%;max-width:450px;margin:0 auto}\n@media (max-width:1024px){\n.s-maintenance{padding:40px 0 10px}\n.s-maintenance .mt-panel{flex-direction:column}\n.s-maintenance .mt-message{order:2;text-align:center;padding:0;margin:50px 0 0}\n.s-maintenance .mt-title{flex-direction:column;margin-bottom:30px}\n.s-maintenance .mt-logo{margin:0 0 10px}\n.s-maintenance .mt-title h1{font-size:1.5rem}\n}\n@media (max-width:640px){.s-maintenance .thumb img{width:80%}}\n@keyframes revealMtBlock{from{opacity:0;transform:translateY(50%)}to{opacity:1;transform:translateY(0)}}\n`;\n\n/** The phone button and social links under the message; nothing when the store lists none. */\nfunction Contacts({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const mobile = store?.contacts?.mobile;\n const socials = socialLinks(store);\n if (!mobile && socials.length === 0) return null;\n\n return (\n <ul className=\"mt-contact-list\">\n {mobile && (\n <li>\n <a href={`tel:${mobile}`} className=\"mt-contact--btn\">\n <i className=\"sicon-phone\" aria-hidden=\"true\" />\n {t('common.elements.contact_us', {\n defaultValue: arabic ? 'تواصل معنا' : 'Contact us',\n })}\n </a>\n </li>\n )}\n {socials.map(({ key, icon, href }) => (\n <li key={key}>\n <a href={href} target=\"_blank\" rel=\"noreferrer\" aria-label={key}>\n <i className={icon} aria-hidden=\"true\" />\n </a>\n </li>\n ))}\n </ul>\n );\n}\n\n// The platform's page for a store that has not launched yet (Store\n// `pages/construction.blade.php` + the `construction` rules of `_maintenance.scss`): in\n// colour, logo over the illustration over the title, centred, contacts in a bar along the\n// bottom. Its own scroll container, as the maintenance page above is.\nconst LAUNCHING_STYLE = `\n.s-launching{display:flex;flex-direction:column;align-items:center;width:100%;height:100vh;height:100dvh;overflow-y:auto;color:#a3a3a3;background:#fff;text-align:center;box-sizing:border-box}\n.s-launching *{box-sizing:border-box}\n.s-launching .ls-panel{display:flex;flex-direction:column;align-items:center;width:100%;max-width:1200px;margin:auto 0;padding:40px 15px 100px;animation:revealMtBlock 1.5s forwards}\n.s-launching .ls-logo{display:block;max-width:70px;margin:0 0 60px}\n.s-launching .ls-thumb{display:block;width:100%;max-width:250px}\n.s-launching h1{font-size:3.125rem;line-height:1;margin:20px 0;color:#000}\n.s-launching .ls-content p{margin:0;white-space:pre-line}\n.s-launching .ls-footer{position:fixed;inset-inline:0;bottom:0;display:flex;align-items:center;justify-content:space-between;padding:0 25px;color:#000;background:#fbfbfb}\n.s-launching .ls-contacts{display:flex;align-items:center}\n.s-launching .ls-contacts h2{margin:1em 0;font-size:1rem;color:#7d7d7d}\n.s-launching .ls-contacts h2::after{content:\"|\";margin:0 10px;font-weight:700;color:#dbdbdb}\n.s-launching .ls-contacts ul{display:flex;list-style:none;margin:0;padding:0}\n.s-launching .ls-contacts li{padding:0 10px}\n.s-launching .ls-contacts a{display:inline-flex;align-items:center;gap:5px;color:#000;text-decoration:none}\n.s-launching .ls-footer-logo{display:block;max-width:30px}\n@media (max-width:1024px){.s-launching h1{font-size:1.5625rem}}\n@media (max-width:767px){.s-launching .ls-contacts a span{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}\n@keyframes revealMtBlock{from{opacity:0;transform:translateY(50%)}to{opacity:1;transform:translateY(0)}}\n`;\n\n/** The bar along the bottom with the phone and social links; nothing when the store lists none. */\nfunction LaunchingContacts({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const mobile = store?.contacts?.mobile;\n const socials = socialLinks(store);\n if (!mobile && socials.length === 0) return null;\n\n return (\n <footer className=\"ls-footer\">\n <div className=\"ls-contacts\">\n <h2>\n {t('common.elements.contact_us', {\n defaultValue: arabic ? 'تواصل معنا' : 'Contact us',\n })}\n </h2>\n <ul>\n {mobile && (\n <li>\n <a href={`tel:${mobile}`}>\n <i className=\"sicon-phone\" aria-hidden=\"true\" />\n <span dir=\"ltr\">{mobile}</span>\n </a>\n </li>\n )}\n {socials.map(({ key, icon, href }) => (\n <li key={key}>\n <a href={href} target=\"_blank\" rel=\"noreferrer\" aria-label={key}>\n <i className={icon} aria-hidden=\"true\" />\n </a>\n </li>\n ))}\n </ul>\n </div>\n {store?.logo && <img className=\"ls-footer-logo\" src={store.logo} alt=\"\" />}\n </footer>\n );\n}\n\n/**\n * The page a customer sees while the store has not launched yet. Its wording is the\n * platform's own, not `maintenance_details`: for an unlaunched store that holds the\n * merchant's \"finish launching\" notice, addressed to the merchant.\n */\nfunction LaunchingSoon({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const logoAlt =\n store?.name ||\n t('common.elements.store_logo', { defaultValue: arabic ? 'شعار المتجر' : 'Store logo' });\n\n return (\n <div className=\"s-launching\" data-testid=\"store-launching-soon-page\">\n <style>{LAUNCHING_STYLE}</style>\n <section className=\"ls-panel\">\n {store?.logo && <img className=\"ls-logo\" src={store.logo} alt={logoAlt} />}\n <img className=\"ls-thumb\" src={LAUNCHING_THUMB_URL} alt=\"\" />\n <h1>\n {t('pages.launching_soon.title', {\n defaultValue: arabic ? 'ترقَّب إطلاق المتجر' : 'The store is launching soon',\n })}\n </h1>\n <div className=\"ls-content\">\n <p>\n {t('pages.launching_soon.message', {\n defaultValue: arabic\n ? 'نعمل على وضع اللمسات الأخيرة لنقدم لك تجربة تسوق متكاملة، قريبًا!'\n : \"We're putting the finishing touches on a complete shopping experience for you. Coming soon!\",\n })}\n </p>\n </div>\n </section>\n <LaunchingContacts store={store} arabic={arabic} />\n </div>\n );\n}\n\n/**\n * The page a customer sees while the store is closed: the platform's maintenance page,\n * fed by the settings' `maintenance_details` (the merchant's title and message) and the\n * store's contacts; or, while the store has not launched yet (`settings.launched` is\n * `false`), the platform's launching-soon page. Rendered by `TwilightProvider` in place\n * of the layout; see `rootBeforeLoad` for who sees it.\n */\nexport function MaintenancePage() {\n const { settings, locale } = getTwilightContext();\n const { t } = useTranslation();\n const store = settings.store;\n const details = settings.maintenance_details;\n const arabic = locale.startsWith('ar');\n\n if (settings.launched === false) return <LaunchingSoon store={store} arabic={arabic} />;\n\n const title =\n details?.title ||\n t('pages.maintenance.title', {\n defaultValue: arabic ? 'المتجر قيد الصيانة' : 'Store under maintenance',\n });\n\n return (\n <div className=\"s-maintenance\" data-testid=\"store-maintenance-page\">\n <style>{STYLE}</style>\n <div className=\"mt-container\">\n <section className=\"mt-panel\">\n <div className=\"mt-message\">\n <div className=\"mt-title\">\n {store?.logo && (\n <span className=\"mt-logo\">\n <img\n src={store.logo}\n alt={\n store.name ||\n t('common.elements.store_logo', {\n defaultValue: arabic ? 'شعار المتجر' : 'Store logo',\n })\n }\n />\n </span>\n )}\n <h1>{title}</h1>\n </div>\n <div className=\"mt-content\">\n {details?.message ? (\n // The merchant's own wording: a plain string the dashboard caps at 200 characters.\n <p>{details.message}</p>\n ) : (\n <>\n <p>\n {t('pages.maintenance.message', {\n defaultValue: arabic\n ? 'عذرا عزيزي العميل، المتجر حاليا قيد الصيانة و سنعاود العمل خلال فترة وجيزة'\n : 'Sorry, the store is under maintenance and will be back shortly.',\n })}\n </p>\n <p>\n {t('pages.maintenance.thanks', {\n defaultValue: arabic ? 'شكرا لتفهمكم' : 'Thank you for your understanding.',\n })}\n </p>\n </>\n )}\n </div>\n <Contacts store={store} arabic={arabic} />\n </div>\n <div className=\"thumb\">\n <img src={THUMB_URL} alt=\"\" />\n </div>\n </section>\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/store/MaintenancePage.tsx"],"names":[],"mappings":"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","file":"chunk-CZ6VJPCG.js","sourcesContent":["import { getTwilightContext } from '../../twilight/context';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport type { Store, StoreSocial } from '../../types';\n\nconst THUMB_URL = 'https://cdn.assets.salla.network/prod/stores/images/construction-01.png';\nconst LAUNCHING_THUMB_URL =\n 'https://cdn.assets.salla.network/prod/stores/images/under-construction.png';\n\n/** Social networks the page links to, in the old page's order, with their Salla icon class. */\nconst SOCIAL_ICONS: [keyof StoreSocial, string][] = [\n ['twitter', 'sicon-x'],\n ['snapchat', 'sicon-snapchat'],\n ['youtube', 'sicon-youtube'],\n ['tiktok', 'sicon-tiktok'],\n ['facebook', 'sicon-facebook'],\n ['instagram', 'sicon-instagram'],\n];\n\n/** The store's social links the page shows, each with its icon class. */\nfunction socialLinks(store: Store | undefined) {\n return SOCIAL_ICONS.flatMap(([key, icon]) => {\n const href = store?.social?.[key];\n return href ? [{ key, icon, href }] : [];\n });\n}\n\n// The platform's maintenance page (Store `pages/maintenance.blade.php` + `_maintenance.scss`),\n// trimmed to what it renders: greyscale, logo + title beside the message, contacts under a\n// rule, the illustration alongside; stacked and centred under 1024px.\n//\n// The page is its own scroll container, the viewport tall, because app-shell themes lock\n// `html, body { overflow: hidden }` and scroll only their main element, which this page\n// replaces. Centring is by auto margins, not `justify-content`, so content taller than the\n// viewport starts at the top instead of being clipped at both ends.\nconst STYLE = `\n.s-maintenance{display:flex;flex-direction:column;align-items:center;width:100%;height:100vh;height:100dvh;overflow-y:auto;color:#a3a3a3;background:#fff;filter:grayscale(100%);box-sizing:border-box}\n.s-maintenance *{box-sizing:border-box}\n.s-maintenance .mt-container{width:100%;max-width:1200px;margin:auto 0;padding:0 15px}\n.s-maintenance .mt-panel{display:flex;flex-direction:row;align-items:center;justify-content:space-between;width:100%}\n.s-maintenance .mt-message{width:100%;padding-inline-start:80px;animation:revealMtBlock 1.5s forwards}\n.s-maintenance .mt-title{display:flex;align-items:center;margin:0 0 20px}\n.s-maintenance .mt-logo{display:block;flex-shrink:0;width:80px;height:80px;margin-inline-end:20px;border-radius:50%;overflow:hidden;box-shadow:0 0 5px rgb(0 0 0 / 10%)}\n.s-maintenance .mt-logo img{display:block;width:100%;height:100%;object-fit:cover}\n.s-maintenance .mt-title h1{font-size:2.25rem;line-height:1;margin:0;color:#666}\n.s-maintenance .mt-content p{margin:0;white-space:pre-line}\n.s-maintenance .mt-contact-list{display:inline-block;list-style:none;width:100%;max-width:500px;margin:20px 0 0;padding:20px 0 0;border-top:1px solid #eee}\n.s-maintenance .mt-contact-list li{display:inline-block;margin-inline-end:10px}\n.s-maintenance .mt-contact-list a{display:inline-flex;align-items:center;padding:5px;color:rgb(102 102 102 / 80%);text-decoration:none;font-size:1.25rem}\n.s-maintenance .mt-contact-list a:hover{color:#666}\n.s-maintenance .mt-contact--btn{padding:3px 20px 5px;border-radius:20px;color:#fff!important;background:rgb(102 102 102 / 80%);font-size:1rem!important}\n.s-maintenance .mt-contact--btn:hover{background:#666}\n.s-maintenance .mt-contact--btn i{margin-inline-end:10px}\n.s-maintenance .thumb{width:100%;animation:revealMtBlock 1.5s .1s forwards;opacity:0}\n.s-maintenance .thumb img{display:block;width:100%;max-width:450px;margin:0 auto}\n@media (max-width:1024px){\n.s-maintenance{padding:40px 0 10px}\n.s-maintenance .mt-panel{flex-direction:column}\n.s-maintenance .mt-message{order:2;text-align:center;padding:0;margin:50px 0 0}\n.s-maintenance .mt-title{flex-direction:column;margin-bottom:30px}\n.s-maintenance .mt-logo{margin:0 0 10px}\n.s-maintenance .mt-title h1{font-size:1.5rem}\n}\n@media (max-width:640px){.s-maintenance .thumb img{width:80%}}\n@keyframes revealMtBlock{from{opacity:0;transform:translateY(50%)}to{opacity:1;transform:translateY(0)}}\n`;\n\n/** The phone button and social links under the message; nothing when the store lists none. */\nfunction Contacts({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const mobile = store?.contacts?.mobile;\n const socials = socialLinks(store);\n if (!mobile && socials.length === 0) return null;\n\n return (\n <ul className=\"mt-contact-list\">\n {mobile && (\n <li>\n <a href={`tel:${mobile}`} className=\"mt-contact--btn\">\n <i className=\"sicon-phone\" aria-hidden=\"true\" />\n {t('common.elements.contact_us', {\n defaultValue: arabic ? 'تواصل معنا' : 'Contact us',\n })}\n </a>\n </li>\n )}\n {socials.map(({ key, icon, href }) => (\n <li key={key}>\n <a href={href} target=\"_blank\" rel=\"noreferrer\" aria-label={key}>\n <i className={icon} aria-hidden=\"true\" />\n </a>\n </li>\n ))}\n </ul>\n );\n}\n\n// The platform's page for a store that has not launched yet (Store\n// `pages/construction.blade.php` + the `construction` rules of `_maintenance.scss`): in\n// colour, logo over the illustration over the title, centred, contacts in a bar along the\n// bottom. Its own scroll container, as the maintenance page above is.\nconst LAUNCHING_STYLE = `\n.s-launching{display:flex;flex-direction:column;align-items:center;width:100%;height:100vh;height:100dvh;overflow-y:auto;color:#a3a3a3;background:#fff;text-align:center;box-sizing:border-box}\n.s-launching *{box-sizing:border-box}\n.s-launching .ls-panel{display:flex;flex-direction:column;align-items:center;width:100%;max-width:1200px;margin:auto 0;padding:40px 15px 100px;animation:revealMtBlock 1.5s forwards}\n.s-launching .ls-logo{display:block;max-width:70px;margin:0 0 60px}\n.s-launching .ls-thumb{display:block;width:100%;max-width:250px}\n.s-launching h1{font-size:3.125rem;line-height:1;margin:20px 0;color:#000}\n.s-launching .ls-content p{margin:0;white-space:pre-line}\n.s-launching .ls-footer{position:fixed;inset-inline:0;bottom:0;display:flex;align-items:center;justify-content:space-between;padding:0 25px;color:#000;background:#fbfbfb}\n.s-launching .ls-contacts{display:flex;align-items:center}\n.s-launching .ls-contacts h2{margin:1em 0;font-size:1rem;color:#7d7d7d}\n.s-launching .ls-contacts h2::after{content:\"|\";margin:0 10px;font-weight:700;color:#dbdbdb}\n.s-launching .ls-contacts ul{display:flex;list-style:none;margin:0;padding:0}\n.s-launching .ls-contacts li{padding:0 10px}\n.s-launching .ls-contacts a{display:inline-flex;align-items:center;gap:5px;color:#000;text-decoration:none}\n.s-launching .ls-footer-logo{display:block;max-width:30px}\n@media (max-width:1024px){.s-launching h1{font-size:1.5625rem}}\n@media (max-width:767px){.s-launching .ls-contacts a span{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}\n@keyframes revealMtBlock{from{opacity:0;transform:translateY(50%)}to{opacity:1;transform:translateY(0)}}\n`;\n\n/** The bar along the bottom with the phone and social links; nothing when the store lists none. */\nfunction LaunchingContacts({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const mobile = store?.contacts?.mobile;\n const socials = socialLinks(store);\n if (!mobile && socials.length === 0) return null;\n\n return (\n <footer className=\"ls-footer\">\n <div className=\"ls-contacts\">\n <h2>\n {t('common.elements.contact_us', {\n defaultValue: arabic ? 'تواصل معنا' : 'Contact us',\n })}\n </h2>\n <ul>\n {mobile && (\n <li>\n <a href={`tel:${mobile}`}>\n <i className=\"sicon-phone\" aria-hidden=\"true\" />\n <span dir=\"ltr\">{mobile}</span>\n </a>\n </li>\n )}\n {socials.map(({ key, icon, href }) => (\n <li key={key}>\n <a href={href} target=\"_blank\" rel=\"noreferrer\" aria-label={key}>\n <i className={icon} aria-hidden=\"true\" />\n </a>\n </li>\n ))}\n </ul>\n </div>\n {store?.logo && <img className=\"ls-footer-logo\" src={store.logo} alt=\"\" />}\n </footer>\n );\n}\n\n/**\n * The page a customer sees while the store has not launched yet. Its wording is the\n * platform's own, not `maintenance_details`: for an unlaunched store that holds the\n * merchant's \"finish launching\" notice, addressed to the merchant.\n */\nfunction LaunchingSoon({ store, arabic }: { store: Store | undefined; arabic: boolean }) {\n const { t } = useTranslation();\n const logoAlt =\n store?.name ||\n t('common.elements.store_logo', { defaultValue: arabic ? 'شعار المتجر' : 'Store logo' });\n\n return (\n <div className=\"s-launching\" data-testid=\"store-launching-soon-page\">\n <style>{LAUNCHING_STYLE}</style>\n <section className=\"ls-panel\">\n {store?.logo && <img className=\"ls-logo\" src={store.logo} alt={logoAlt} />}\n <img className=\"ls-thumb\" src={LAUNCHING_THUMB_URL} alt=\"\" />\n <h1>\n {t('pages.launching_soon.title', {\n defaultValue: arabic ? 'ترقَّب إطلاق المتجر' : 'The store is launching soon',\n })}\n </h1>\n <div className=\"ls-content\">\n <p>\n {t('pages.launching_soon.message', {\n defaultValue: arabic\n ? 'نعمل على وضع اللمسات الأخيرة لنقدم لك تجربة تسوق متكاملة، قريبًا!'\n : \"We're putting the finishing touches on a complete shopping experience for you. Coming soon!\",\n })}\n </p>\n </div>\n </section>\n <LaunchingContacts store={store} arabic={arabic} />\n </div>\n );\n}\n\n/**\n * The page a customer sees while the store is closed: the platform's maintenance page,\n * fed by the settings' `maintenance_details` (the merchant's title and message) and the\n * store's contacts; or, while the store has not launched yet (`settings.launched` is\n * `false`), the platform's launching-soon page. Rendered by `TwilightProvider` in place\n * of the layout; see `rootBeforeLoad` for who sees it.\n */\nexport function MaintenancePage() {\n const { settings, locale } = getTwilightContext();\n const { t } = useTranslation();\n const store = settings.store;\n const details = settings.maintenance_details;\n const arabic = locale.startsWith('ar');\n\n if (settings.launched === false) return <LaunchingSoon store={store} arabic={arabic} />;\n\n const title =\n details?.title ||\n t('pages.maintenance.title', {\n defaultValue: arabic ? 'المتجر قيد الصيانة' : 'Store under maintenance',\n });\n\n return (\n <div className=\"s-maintenance\" data-testid=\"store-maintenance-page\">\n <style>{STYLE}</style>\n <div className=\"mt-container\">\n <section className=\"mt-panel\">\n <div className=\"mt-message\">\n <div className=\"mt-title\">\n {store?.logo && (\n <span className=\"mt-logo\">\n <img\n src={store.logo}\n alt={\n store.name ||\n t('common.elements.store_logo', {\n defaultValue: arabic ? 'شعار المتجر' : 'Store logo',\n })\n }\n />\n </span>\n )}\n <h1>{title}</h1>\n </div>\n <div className=\"mt-content\">\n {details?.message ? (\n // The merchant's own wording: a plain string the dashboard caps at 200 characters.\n <p>{details.message}</p>\n ) : (\n <>\n <p>\n {t('pages.maintenance.message', {\n defaultValue: arabic\n ? 'عذرا عزيزي العميل، المتجر حاليا قيد الصيانة و سنعاود العمل خلال فترة وجيزة'\n : 'Sorry, the store is under maintenance and will be back shortly.',\n })}\n </p>\n <p>\n {t('pages.maintenance.thanks', {\n defaultValue: arabic ? 'شكرا لتفهمكم' : 'Thank you for your understanding.',\n })}\n </p>\n </>\n )}\n </div>\n <Contacts store={store} arabic={arabic} />\n </div>\n <div className=\"thumb\">\n <img src={THUMB_URL} alt=\"\" />\n </div>\n </section>\n </div>\n </div>\n );\n}\n"]}
@@ -1,8 +1,8 @@
1
- import { isNotLaunchedNotice } from './chunk-FID76MUV.js';
2
- import { getActiveScope, api, STORE_IDENTIFIER_HEADER, devSettingsFetchedAt } from './chunk-RQG44QD7.js';
3
- import { requestedThemeVersionId } from './chunk-GYXUYHKO.js';
4
- import { resolveStoreIdentifier, parseStoreId } from './chunk-FHU2MXZA.js';
5
- import { getTwilightContext, SettingsError } from './chunk-7VNVCHID.js';
1
+ import { isNotLaunchedNotice } from './chunk-Q7E4TNN7.js';
2
+ import { getActiveScope, api, STORE_IDENTIFIER_HEADER, devSettingsFetchedAt } from './chunk-E5DP3MHE.js';
3
+ import { requestedThemeVersionId } from './chunk-NHA4SBKG.js';
4
+ import { resolveStoreIdentifier, parseStoreId } from './chunk-FXVII733.js';
5
+ import { getTwilightContext, SettingsError } from './chunk-6K34BCUP.js';
6
6
  import { queryOptions } from '@tanstack/react-query';
7
7
  import { isTimeoutError, isHTTPError, isNetworkError } from 'ky';
8
8
 
@@ -207,5 +207,5 @@ var store = {
207
207
  };
208
208
 
209
209
  export { readNativeAppHeaders, store };
210
- //# sourceMappingURL=chunk-F5BU7T6H.js.map
211
- //# sourceMappingURL=chunk-F5BU7T6H.js.map
210
+ //# sourceMappingURL=chunk-D53M5ASN.js.map
211
+ //# sourceMappingURL=chunk-D53M5ASN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/native-app-headers.ts","../src/api/store.ts"],"names":[],"mappings":"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","file":"chunk-F5BU7T6H.js","sourcesContent":["/** The headers the Salla native app sends with every page it loads in its webview. */\nexport const NATIVE_APP_HEADERS = [\n 's-app-os',\n 's-app-version',\n 's-app-full-version',\n 's-app-os-version',\n];\n\n/**\n * The native app's own headers on this request, or null when it is not the app.\n *\n * On a Twig theme Laravel copies them into the settings' `jitsu.context.extra.headers`,\n * where the SDK reads the app's platform and version from (`salla.config.isMobileApp()`).\n * A React theme asks for its settings from the server, through the API, so the app's\n * headers never reach that call: the request is the only place they are.\n */\nexport function readNativeAppHeaders(headers: Headers): Record<string, string> | null {\n const os = headers.get('s-app-os')?.toLowerCase();\n if (os !== 'ios' && os !== 'android') return null;\n const found: Record<string, string> = {};\n for (const name of NATIVE_APP_HEADERS) {\n const value = headers.get(name);\n if (value) found[name] = value;\n }\n return found;\n}\n","import { queryOptions } from '@tanstack/react-query';\nimport { isHTTPError, isNetworkError, isTimeoutError } from 'ky';\nimport { api, getActiveScope, STORE_IDENTIFIER_HEADER } from './client';\nimport { devSettingsFetchedAt } from './dev-settings-cache';\nimport { SettingsError } from '../utils/errors';\nimport type { Store, Theme, Language, JitsuConfig, MaintenanceDetails } from '../types';\nimport { getTwilightContext } from '../twilight/context';\nimport { resolveStoreIdentifier } from '../utils/store-identity';\nimport { parseStoreId } from '../utils/cookies';\nimport { requestedThemeVersionId } from '../utils/theme-version';\nimport { NATIVE_APP_HEADERS } from '../utils/native-app-headers';\nimport { isNotLaunchedNotice } from '../utils/maintenance';\n\nexport { resolveStoreIdentifier };\n\nconst DEFAULT_INCLUDE_ITEMS = [\n 'store',\n 'settings',\n 'theme',\n 'theme_settings',\n 'external_services',\n 'currencies',\n 'languages',\n 'payments',\n 'product_widgets',\n 'rating',\n 'ratings',\n 'user',\n];\n\n/** Twig's `salla.init({ user })` object; the endpoint ignores the token, so always the guest. */\nexport interface SettingsUser {\n type: 'guest' | 'user';\n id?: number | string | null;\n language_code?: string;\n currency_code?: string;\n country_code?: string;\n [key: string]: unknown;\n}\n\n/**\n * Raw API response for settings endpoint.\n * Languages come as object: { \"AR\": { code, name, ... }, \"EN\": {...} }\n */\ninterface SettingsApiResponse {\n store?: Store;\n theme?: Theme;\n languages?: Record<string, Language>;\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean;\n policy_url?: string;\n user?: SettingsUser;\n swoole?: string[];\n jitsu?: JitsuConfig;\n maintenance?: boolean;\n maintenance_details?: MaintenanceDetails;\n}\n\n/**\n * Central settings context - single source of truth for all API data.\n * Contains everything from the settings endpoint response after processing.\n */\nexport interface StoreContext {\n store?: Store;\n theme?: Theme;\n /** Languages as array after conversion from API object format */\n languages?: Language[];\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean; // todo:: remove it\n policy_url?: string;\n user?: SettingsUser;\n /** API paths the SDK sends with `s-store-api-version: swoole` */\n swoole?: string[];\n /** Where the SDK's analytics send events, and which ones; without it the SDK tracks nothing. */\n jitsu?: JitsuConfig;\n /**\n * The store is closed: by the merchant from the dashboard, by the platform, or\n * for the selected market only. The engine then renders the maintenance page\n * to everyone but the merchant; see `rootBeforeLoad`.\n */\n maintenance?: boolean;\n /** What the maintenance page says; sent beside `maintenance`. */\n maintenance_details?: MaintenanceDetails;\n /**\n * `false` while the store has not launched yet: `maintenance` is then `true` and the\n * engine's maintenance page says the store is launching soon. Absent otherwise. Not\n * from the API: read off `maintenance_details` by `store.settings`, since the\n * backend sends the merchant's \"finish launching\" notice there for every visitor,\n * which is not for a customer's eyes.\n */\n launched?: false;\n /**\n * The scope these settings were requested with; absent when none was. Not from\n * the API: stamped by `store.settings`, so `resolveThemeVersionId` can tell\n * whether the version they name still answers the scope that is active now.\n */\n requestedScopeId?: string;\n /** Which answer of the API these settings are; see {@link SettingsAnswer}. */\n answer?: SettingsAnswer;\n /**\n * When the dev server fetched these settings from the API (epoch ms). It reuses\n * them for a while (see `dev-settings-cache.ts`) and the theme editor says how old\n * they are. Only on a dev server render; absent everywhere else.\n */\n devFetchedAt?: number;\n}\n\n/**\n * Which answer of the settings API a set of settings came from, read off the\n * response rather than the body: the API's request id, the Store's trace, and\n * whether Cloudflare served it from its cache and how old it was. A decision the\n * settings drive for every visitor alike (the maintenance page) can then be\n * traced to the exact request the backend logged, or to a cached copy of it.\n */\nexport interface SettingsAnswer {\n requestId?: string;\n traceId?: string;\n cacheStatus?: string;\n age?: string;\n}\n\nconst ANSWER_HEADERS: Record<keyof SettingsAnswer, string> = {\n requestId: 's-request-id',\n traceId: 'x-trace-id',\n cacheStatus: 'cf-cache-status',\n age: 'age',\n};\n\nfunction settingsAnswerOf(headers: Headers | undefined): SettingsAnswer | undefined {\n if (!headers) return undefined;\n const answer: SettingsAnswer = {};\n for (const [field, name] of Object.entries(ANSWER_HEADERS) as [keyof SettingsAnswer, string][]) {\n const value = headers.get(name);\n if (value) answer[field] = value;\n }\n return Object.keys(answer).length ? answer : undefined;\n}\n\n/**\n * Converts languages object from API to array format.\n * API returns: { \"AR\": { code, name, ... }, \"EN\": { ... } }\n * We need: [{ code, name, ... }, { code, name, ... }]\n * todo:: return the languages as object from the APIs to avoid this\n */\nfunction languagesToArray(languages?: Record<string, Language>): Language[] | undefined {\n if (!languages) return undefined;\n // The SDK's localization modal reads `lang.iso_code` (not `code`) when a language is\n // selected — without it the switch navigates to `/undefined/...`.\n return Object.values(languages).map((lang) => ({ iso_code: lang.code, ...lang }));\n}\n\n/**\n * The settings' analytics context with the native app's headers in it, as Laravel\n * writes it for a Twig theme: the SDK reads the app's platform and version from there.\n * The API answers a server-side call with the engine's own headers, never the app's.\n */\nfunction withNativeAppHeaders(jitsu?: JitsuConfig): JitsuConfig | undefined {\n if (!jitsu || typeof window !== 'undefined') return jitsu;\n let appHeaders: Record<string, string> | null = null;\n try {\n appHeaders = getTwilightContext().nativeAppHeaders;\n } catch {\n return jitsu;\n }\n if (!appHeaders) return jitsu;\n const extra = jitsu.context?.extra;\n // The engine's own app headers go, so an app that sends no version doesn't get the engine's.\n const headers = { ...extra?.headers };\n for (const name of NATIVE_APP_HEADERS) delete headers[name];\n return {\n ...jitsu,\n context: {\n ...jitsu.context,\n extra: { ...extra, headers: { ...headers, ...appHeaders } },\n },\n };\n}\n\nconst SETTINGS_TIMEOUT_MS = 5000;\n\nasync function requestSettings(identifier: string): Promise<StoreContext> {\n const includeParams = DEFAULT_INCLUDE_ITEMS.map((i) => `include[]=${i}`).join('&');\n const scope = getActiveScope();\n const params = scope != null ? `${includeParams}&scope=${scope.id}` : includeParams;\n\n const request = api\n // Sent explicitly rather than left to the client's own resolution, so\n // the identifier this function checked is the identifier that travels.\n // They agree today; a caller passing one and being answered about\n // another is the failure this makes impossible rather than unlikely.\n .get(`store/settings?${params}`, {\n timeout: SETTINGS_TIMEOUT_MS,\n headers: { [STORE_IDENTIFIER_HEADER]: identifier },\n });\n const json = await request.json<{ data?: SettingsApiResponse }>();\n // The same response, already settled; only its headers are read.\n const headers = (await request)?.headers;\n const answer = settingsAnswerOf(headers);\n const devFetchedAt = devSettingsFetchedAt(headers);\n\n const data = json?.data;\n if (!data) {\n throw new SettingsError(\n `The Salla API answered the settings request for store \"${identifier}\" without settings.`,\n { reason: 'empty' }\n );\n }\n\n // Convert languages from object to array\n const languages = languagesToArray(data.languages);\n\n return {\n store: data.store,\n theme: data.theme,\n languages,\n currencies: data.currencies,\n external_services: data.external_services,\n headers: data.headers,\n login: data.login,\n affiliate: data.affiliate,\n policy_url: data.policy_url,\n user: data.user,\n swoole: data.swoole,\n jitsu: withNativeAppHeaders(data.jitsu),\n maintenance: data.maintenance,\n maintenance_details: data.maintenance_details,\n ...(data.maintenance === true &&\n isNotLaunchedNotice(data.maintenance_details) && { launched: false as const }),\n ...(scope && { requestedScopeId: scope.id }),\n ...(answer && { answer }),\n ...(devFetchedAt && { devFetchedAt }),\n };\n}\n\n/** The message the API put in an error body, `{ error: { message } }`, when it sent one. */\nfunction apiErrorMessage(data: unknown): string | undefined {\n const message = (data as { error?: { message?: unknown } } | undefined)?.error?.message;\n return typeof message === 'string' && message.length > 0 && message.length <= 200\n ? message\n : undefined;\n}\n\n/**\n * What core's `CurrentStoreMiddleware` answers, with a 422, when no store has the\n * username or domain it was given (or the store's status is `deleted`). The lookup is\n * `loadUseUsernameOrDomain`, the same one Twig's `checkUsername` turns into its 410.\n * The literal is not translated: it reads the same whatever language was asked for.\n */\nconst STORE_NOT_FOUND_MESSAGE = 'المتجر غير موجود';\n\n/**\n * Whether the API answered that no store has this identifier. A numeric identifier\n * is looked up with `findOrFail`, which Store's exception handler answers with a 410;\n * a username or domain gets {@link STORE_NOT_FOUND_MESSAGE}. A 410 for a username is\n * not read as one: nothing on that path answers it, and a store that does exist must\n * never be told it does not.\n */\nfunction isStoreNotFound(identifier: string, status: number, said: string | undefined): boolean {\n if (status === 410) return parseStoreId(identifier) !== null;\n return status === 422 && said === STORE_NOT_FOUND_MESSAGE;\n}\n\n/**\n * Names what went wrong, because the page, the server log and Sentry all carry\n * this message. Every failure used to read \"Make sure VITE_STORE_DOMAIN is set\",\n * a local-development variable no deployed theme has, so a slow API looked like\n * a misconfigured theme.\n */\nfunction describeSettingsFailure(identifier: string, error: unknown): SettingsError {\n if (error instanceof SettingsError) return error;\n const request = `the settings request for store \"${identifier}\"`;\n if (isTimeoutError(error)) {\n return new SettingsError(\n `The Salla API did not answer ${request} within ${SETTINGS_TIMEOUT_MS} ms.`,\n { reason: 'timeout' }\n );\n }\n if (isHTTPError(error)) {\n const { status } = error.response;\n const said = apiErrorMessage(error.data);\n return new SettingsError(\n `The Salla API answered ${request} with HTTP ${status}${said ? `: ${said}` : ''}.`,\n { reason: isStoreNotFound(identifier, status, said) ? 'not-found' : 'http', status }\n );\n }\n if (isNetworkError(error)) {\n return new SettingsError(`The Salla API could not be reached for ${request}.`, {\n reason: 'network',\n });\n }\n const detail = error instanceof Error ? `: ${error.message}` : '';\n return new SettingsError(`The settings request for store \"${identifier}\" failed${detail}.`);\n}\n\n/**\n * The settings, or a {@link SettingsError} that says why there are none. The\n * query throws it so the root route can say why the store did not load;\n * `store.settings` keeps answering `null` for its own callers.\n */\nasync function fetchSettings(storeIdentifier?: string): Promise<StoreContext> {\n const identifier = storeIdentifier ?? resolveStoreIdentifier();\n\n if (!identifier) {\n const error = new SettingsError(\n 'No store is named for this request: add `?storeId=` on the preview host, or set VITE_STORE_DOMAIN in local development.',\n { reason: 'no-store' }\n );\n console.warn('[store.settings]', error.message);\n throw error;\n }\n\n try {\n return await requestSettings(identifier);\n } catch (cause) {\n const error = describeSettingsFailure(identifier, cause);\n console.error('[store.settings]', error.message, ...(cause === error ? [] : [cause]));\n throw error;\n }\n}\n\nexport const store = {\n settings: async (storeIdentifier?: string): Promise<StoreContext | null> => {\n try {\n return await fetchSettings(storeIdentifier);\n } catch {\n // Already logged, with the reason.\n return null;\n }\n },\n\n queries: {\n settings: (storeIdentifier?: string) =>\n queryOptions<StoreContext | null>({\n queryKey: [\n 'store',\n 'settings',\n storeIdentifier,\n getTwilightContext().locale,\n getActiveScope(),\n // Two versions of one store's settings are two different answers, and\n // this is the query whose answer decides what every other call is\n // pinned to. `requestedThemeVersionId` rather than the resolved one:\n // the resolved value falls back to what these settings report, so it\n // is not knowable until after this query has run — the key would be\n // one thing on the server and another on the client, and the hydrated\n // page would refetch the settings it was just handed.\n requestedThemeVersionId(),\n ],\n // Throws rather than resolving `null`, so the failure keeps its reason.\n queryFn: () => fetchSettings(storeIdentifier),\n // A null never retried, and the root route waits on this: the router's\n // default `retry: 1` would sit through the timeout twice.\n retry: 0,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/utils/native-app-headers.ts","../src/api/store.ts"],"names":[],"mappings":"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","file":"chunk-D53M5ASN.js","sourcesContent":["/** The headers the Salla native app sends with every page it loads in its webview. */\nexport const NATIVE_APP_HEADERS = [\n 's-app-os',\n 's-app-version',\n 's-app-full-version',\n 's-app-os-version',\n];\n\n/**\n * The native app's own headers on this request, or null when it is not the app.\n *\n * On a Twig theme Laravel copies them into the settings' `jitsu.context.extra.headers`,\n * where the SDK reads the app's platform and version from (`salla.config.isMobileApp()`).\n * A React theme asks for its settings from the server, through the API, so the app's\n * headers never reach that call: the request is the only place they are.\n */\nexport function readNativeAppHeaders(headers: Headers): Record<string, string> | null {\n const os = headers.get('s-app-os')?.toLowerCase();\n if (os !== 'ios' && os !== 'android') return null;\n const found: Record<string, string> = {};\n for (const name of NATIVE_APP_HEADERS) {\n const value = headers.get(name);\n if (value) found[name] = value;\n }\n return found;\n}\n","import { queryOptions } from '@tanstack/react-query';\nimport { isHTTPError, isNetworkError, isTimeoutError } from 'ky';\nimport { api, getActiveScope, STORE_IDENTIFIER_HEADER } from './client';\nimport { devSettingsFetchedAt } from './dev-settings-cache';\nimport { SettingsError } from '../utils/errors';\nimport type { Store, Theme, Language, JitsuConfig, MaintenanceDetails } from '../types';\nimport { getTwilightContext } from '../twilight/context';\nimport { resolveStoreIdentifier } from '../utils/store-identity';\nimport { parseStoreId } from '../utils/cookies';\nimport { requestedThemeVersionId } from '../utils/theme-version';\nimport { NATIVE_APP_HEADERS } from '../utils/native-app-headers';\nimport { isNotLaunchedNotice } from '../utils/maintenance';\n\nexport { resolveStoreIdentifier };\n\nconst DEFAULT_INCLUDE_ITEMS = [\n 'store',\n 'settings',\n 'theme',\n 'theme_settings',\n 'external_services',\n 'currencies',\n 'languages',\n 'payments',\n 'product_widgets',\n 'rating',\n 'ratings',\n 'user',\n];\n\n/** Twig's `salla.init({ user })` object; the endpoint ignores the token, so always the guest. */\nexport interface SettingsUser {\n type: 'guest' | 'user';\n id?: number | string | null;\n language_code?: string;\n currency_code?: string;\n country_code?: string;\n [key: string]: unknown;\n}\n\n/**\n * Raw API response for settings endpoint.\n * Languages come as object: { \"AR\": { code, name, ... }, \"EN\": {...} }\n */\ninterface SettingsApiResponse {\n store?: Store;\n theme?: Theme;\n languages?: Record<string, Language>;\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean;\n policy_url?: string;\n user?: SettingsUser;\n swoole?: string[];\n jitsu?: JitsuConfig;\n maintenance?: boolean;\n maintenance_details?: MaintenanceDetails;\n}\n\n/**\n * Central settings context - single source of truth for all API data.\n * Contains everything from the settings endpoint response after processing.\n */\nexport interface StoreContext {\n store?: Store;\n theme?: Theme;\n /** Languages as array after conversion from API object format */\n languages?: Language[];\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean; // todo:: remove it\n policy_url?: string;\n user?: SettingsUser;\n /** API paths the SDK sends with `s-store-api-version: swoole` */\n swoole?: string[];\n /** Where the SDK's analytics send events, and which ones; without it the SDK tracks nothing. */\n jitsu?: JitsuConfig;\n /**\n * The store is closed: by the merchant from the dashboard, by the platform, or\n * for the selected market only. The engine then renders the maintenance page\n * to everyone but the merchant; see `rootBeforeLoad`.\n */\n maintenance?: boolean;\n /** What the maintenance page says; sent beside `maintenance`. */\n maintenance_details?: MaintenanceDetails;\n /**\n * `false` while the store has not launched yet: `maintenance` is then `true` and the\n * engine's maintenance page says the store is launching soon. Absent otherwise. Not\n * from the API: read off `maintenance_details` by `store.settings`, since the\n * backend sends the merchant's \"finish launching\" notice there for every visitor,\n * which is not for a customer's eyes.\n */\n launched?: false;\n /**\n * The scope these settings were requested with; absent when none was. Not from\n * the API: stamped by `store.settings`, so `resolveThemeVersionId` can tell\n * whether the version they name still answers the scope that is active now.\n */\n requestedScopeId?: string;\n /** Which answer of the API these settings are; see {@link SettingsAnswer}. */\n answer?: SettingsAnswer;\n /**\n * When the dev server fetched these settings from the API (epoch ms). It reuses\n * them for a while (see `dev-settings-cache.ts`) and the theme editor says how old\n * they are. Only on a dev server render; absent everywhere else.\n */\n devFetchedAt?: number;\n}\n\n/**\n * Which answer of the settings API a set of settings came from, read off the\n * response rather than the body: the API's request id, the Store's trace, and\n * whether Cloudflare served it from its cache and how old it was. A decision the\n * settings drive for every visitor alike (the maintenance page) can then be\n * traced to the exact request the backend logged, or to a cached copy of it.\n */\nexport interface SettingsAnswer {\n requestId?: string;\n traceId?: string;\n cacheStatus?: string;\n age?: string;\n}\n\nconst ANSWER_HEADERS: Record<keyof SettingsAnswer, string> = {\n requestId: 's-request-id',\n traceId: 'x-trace-id',\n cacheStatus: 'cf-cache-status',\n age: 'age',\n};\n\nfunction settingsAnswerOf(headers: Headers | undefined): SettingsAnswer | undefined {\n if (!headers) return undefined;\n const answer: SettingsAnswer = {};\n for (const [field, name] of Object.entries(ANSWER_HEADERS) as [keyof SettingsAnswer, string][]) {\n const value = headers.get(name);\n if (value) answer[field] = value;\n }\n return Object.keys(answer).length ? answer : undefined;\n}\n\n/**\n * Converts languages object from API to array format.\n * API returns: { \"AR\": { code, name, ... }, \"EN\": { ... } }\n * We need: [{ code, name, ... }, { code, name, ... }]\n * todo:: return the languages as object from the APIs to avoid this\n */\nfunction languagesToArray(languages?: Record<string, Language>): Language[] | undefined {\n if (!languages) return undefined;\n // The SDK's localization modal reads `lang.iso_code` (not `code`) when a language is\n // selected — without it the switch navigates to `/undefined/...`.\n return Object.values(languages).map((lang) => ({ iso_code: lang.code, ...lang }));\n}\n\n/**\n * The settings' analytics context with the native app's headers in it, as Laravel\n * writes it for a Twig theme: the SDK reads the app's platform and version from there.\n * The API answers a server-side call with the engine's own headers, never the app's.\n */\nfunction withNativeAppHeaders(jitsu?: JitsuConfig): JitsuConfig | undefined {\n if (!jitsu || typeof window !== 'undefined') return jitsu;\n let appHeaders: Record<string, string> | null = null;\n try {\n appHeaders = getTwilightContext().nativeAppHeaders;\n } catch {\n return jitsu;\n }\n if (!appHeaders) return jitsu;\n const extra = jitsu.context?.extra;\n // The engine's own app headers go, so an app that sends no version doesn't get the engine's.\n const headers = { ...extra?.headers };\n for (const name of NATIVE_APP_HEADERS) delete headers[name];\n return {\n ...jitsu,\n context: {\n ...jitsu.context,\n extra: { ...extra, headers: { ...headers, ...appHeaders } },\n },\n };\n}\n\nconst SETTINGS_TIMEOUT_MS = 5000;\n\nasync function requestSettings(identifier: string): Promise<StoreContext> {\n const includeParams = DEFAULT_INCLUDE_ITEMS.map((i) => `include[]=${i}`).join('&');\n const scope = getActiveScope();\n const params = scope != null ? `${includeParams}&scope=${scope.id}` : includeParams;\n\n const request = api\n // Sent explicitly rather than left to the client's own resolution, so\n // the identifier this function checked is the identifier that travels.\n // They agree today; a caller passing one and being answered about\n // another is the failure this makes impossible rather than unlikely.\n .get(`store/settings?${params}`, {\n timeout: SETTINGS_TIMEOUT_MS,\n headers: { [STORE_IDENTIFIER_HEADER]: identifier },\n });\n const json = await request.json<{ data?: SettingsApiResponse }>();\n // The same response, already settled; only its headers are read.\n const headers = (await request)?.headers;\n const answer = settingsAnswerOf(headers);\n const devFetchedAt = devSettingsFetchedAt(headers);\n\n const data = json?.data;\n if (!data) {\n throw new SettingsError(\n `The Salla API answered the settings request for store \"${identifier}\" without settings.`,\n { reason: 'empty' }\n );\n }\n\n // Convert languages from object to array\n const languages = languagesToArray(data.languages);\n\n return {\n store: data.store,\n theme: data.theme,\n languages,\n currencies: data.currencies,\n external_services: data.external_services,\n headers: data.headers,\n login: data.login,\n affiliate: data.affiliate,\n policy_url: data.policy_url,\n user: data.user,\n swoole: data.swoole,\n jitsu: withNativeAppHeaders(data.jitsu),\n maintenance: data.maintenance,\n maintenance_details: data.maintenance_details,\n ...(data.maintenance === true &&\n isNotLaunchedNotice(data.maintenance_details) && { launched: false as const }),\n ...(scope && { requestedScopeId: scope.id }),\n ...(answer && { answer }),\n ...(devFetchedAt && { devFetchedAt }),\n };\n}\n\n/** The message the API put in an error body, `{ error: { message } }`, when it sent one. */\nfunction apiErrorMessage(data: unknown): string | undefined {\n const message = (data as { error?: { message?: unknown } } | undefined)?.error?.message;\n return typeof message === 'string' && message.length > 0 && message.length <= 200\n ? message\n : undefined;\n}\n\n/**\n * What core's `CurrentStoreMiddleware` answers, with a 422, when no store has the\n * username or domain it was given (or the store's status is `deleted`). The lookup is\n * `loadUseUsernameOrDomain`, the same one Twig's `checkUsername` turns into its 410.\n * The literal is not translated: it reads the same whatever language was asked for.\n */\nconst STORE_NOT_FOUND_MESSAGE = 'المتجر غير موجود';\n\n/**\n * Whether the API answered that no store has this identifier. A numeric identifier\n * is looked up with `findOrFail`, which Store's exception handler answers with a 410;\n * a username or domain gets {@link STORE_NOT_FOUND_MESSAGE}. A 410 for a username is\n * not read as one: nothing on that path answers it, and a store that does exist must\n * never be told it does not.\n */\nfunction isStoreNotFound(identifier: string, status: number, said: string | undefined): boolean {\n if (status === 410) return parseStoreId(identifier) !== null;\n return status === 422 && said === STORE_NOT_FOUND_MESSAGE;\n}\n\n/**\n * Names what went wrong, because the page, the server log and Sentry all carry\n * this message. Every failure used to read \"Make sure VITE_STORE_DOMAIN is set\",\n * a local-development variable no deployed theme has, so a slow API looked like\n * a misconfigured theme.\n */\nfunction describeSettingsFailure(identifier: string, error: unknown): SettingsError {\n if (error instanceof SettingsError) return error;\n const request = `the settings request for store \"${identifier}\"`;\n if (isTimeoutError(error)) {\n return new SettingsError(\n `The Salla API did not answer ${request} within ${SETTINGS_TIMEOUT_MS} ms.`,\n { reason: 'timeout' }\n );\n }\n if (isHTTPError(error)) {\n const { status } = error.response;\n const said = apiErrorMessage(error.data);\n return new SettingsError(\n `The Salla API answered ${request} with HTTP ${status}${said ? `: ${said}` : ''}.`,\n { reason: isStoreNotFound(identifier, status, said) ? 'not-found' : 'http', status }\n );\n }\n if (isNetworkError(error)) {\n return new SettingsError(`The Salla API could not be reached for ${request}.`, {\n reason: 'network',\n });\n }\n const detail = error instanceof Error ? `: ${error.message}` : '';\n return new SettingsError(`The settings request for store \"${identifier}\" failed${detail}.`);\n}\n\n/**\n * The settings, or a {@link SettingsError} that says why there are none. The\n * query throws it so the root route can say why the store did not load;\n * `store.settings` keeps answering `null` for its own callers.\n */\nasync function fetchSettings(storeIdentifier?: string): Promise<StoreContext> {\n const identifier = storeIdentifier ?? resolveStoreIdentifier();\n\n if (!identifier) {\n const error = new SettingsError(\n 'No store is named for this request: add `?storeId=` on the preview host, or set VITE_STORE_DOMAIN in local development.',\n { reason: 'no-store' }\n );\n console.warn('[store.settings]', error.message);\n throw error;\n }\n\n try {\n return await requestSettings(identifier);\n } catch (cause) {\n const error = describeSettingsFailure(identifier, cause);\n console.error('[store.settings]', error.message, ...(cause === error ? [] : [cause]));\n throw error;\n }\n}\n\nexport const store = {\n settings: async (storeIdentifier?: string): Promise<StoreContext | null> => {\n try {\n return await fetchSettings(storeIdentifier);\n } catch {\n // Already logged, with the reason.\n return null;\n }\n },\n\n queries: {\n settings: (storeIdentifier?: string) =>\n queryOptions<StoreContext | null>({\n queryKey: [\n 'store',\n 'settings',\n storeIdentifier,\n getTwilightContext().locale,\n getActiveScope(),\n // Two versions of one store's settings are two different answers, and\n // this is the query whose answer decides what every other call is\n // pinned to. `requestedThemeVersionId` rather than the resolved one:\n // the resolved value falls back to what these settings report, so it\n // is not knowable until after this query has run — the key would be\n // one thing on the server and another on the client, and the hydrated\n // page would refetch the settings it was just handed.\n requestedThemeVersionId(),\n ],\n // Throws rather than resolving `null`, so the failure keeps its reason.\n queryFn: () => fetchSettings(storeIdentifier),\n // A null never retried, and the root route waits on this: the router's\n // default `retry: 1` would sit through the timeout twice.\n retry: 0,\n }),\n },\n};\n"]}
@@ -1,13 +1,13 @@
1
1
  import { DEV_SETTINGS_REFRESH_COOKIE } from './chunk-Z5M4YYWT.js';
2
- import { getStoreIdentifier, resolveThemeVersionId } from './chunk-GYXUYHKO.js';
3
- import { AUTH_TOKEN_COOKIE_NAME, extractTokenFromCookies, toCurrencyCode, CURRENCY_COOKIE_NAME, getInjectedRuntimeEnv, readEnv, readSdkScope, extractScopeFromCookies, extractCurrencyFromCookies } from './chunk-FHU2MXZA.js';
4
- import { getTwilightContext } from './chunk-7VNVCHID.js';
2
+ import { getStoreIdentifier, resolveThemeVersionId } from './chunk-NHA4SBKG.js';
3
+ import { AUTH_TOKEN_COOKIE_NAME, extractTokenFromCookies, toCurrencyCode, CURRENCY_COOKIE_NAME, getInjectedRuntimeEnv, readEnv, readSdkScope, extractScopeFromCookies, extractCurrencyFromCookies } from './chunk-FXVII733.js';
4
+ import { getTwilightContext } from './chunk-6K34BCUP.js';
5
5
  import ky from 'ky';
6
6
  import { createIsomorphicFn } from '@tanstack/react-start';
7
7
  import { getCookie } from '@tanstack/react-start/server';
8
8
 
9
9
  // src/utils/engine-version.ts
10
- var ENGINE_VERSION = "1.0.133" ;
10
+ var ENGINE_VERSION = "1.0.135" ;
11
11
  var DEV_SETTINGS_TTL_MS = 60 * 6e4;
12
12
  var HIT_HEADER = "x-twilight-dev-cache";
13
13
  var FETCHED_AT_HEADER = "x-twilight-dev-fetched-at";
@@ -242,5 +242,5 @@ var filesCdn = ky.extend({
242
242
  });
243
243
 
244
244
  export { ENGINE_VERSION, STORE_IDENTIFIER_HEADER, api, cdn, devSettingsFetchedAt, filesCdn, getActiveCurrency, getActiveScope, getActiveScopeId, getAuthToken };
245
- //# sourceMappingURL=chunk-RQG44QD7.js.map
246
- //# sourceMappingURL=chunk-RQG44QD7.js.map
245
+ //# sourceMappingURL=chunk-E5DP3MHE.js.map
246
+ //# sourceMappingURL=chunk-E5DP3MHE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/engine-version.ts","../src/api/dev-settings-cache.ts","../src/api/client.ts"],"names":["entry","createIsomorphicFn","getCookie"],"mappings":"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","file":"chunk-RQG44QD7.js","sourcesContent":["/**\n * The engine's own build version, injected by tsup `define` when dist is\n * built. Falls back to 'dev' when the source runs unbundled (vitest, direct\n * src imports in the monorepo).\n *\n * Exposed at runtime as `salla.versions.engine` by `useTwilightInit` so a\n * storefront can always be asked which engine build rendered it.\n */\nexport const ENGINE_VERSION: string =\n typeof __TWILIGHT_ENGINE_VERSION__ !== 'undefined' ? __TWILIGHT_ENGINE_VERSION__ : 'dev';\n","import type { AfterResponseHook, BeforeRequestHook } from 'ky';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport { DEV_SETTINGS_REFRESH_COOKIE } from '../utils/dev-settings-refresh';\n\n/**\n * A dev server reuses a store's settings for up to an hour.\n *\n * Every server render asks the API for `store/settings`, and a developer clicking\n * around a theme renders dozens of pages a minute. The API answers a burst of\n * settings requests for one store from one address with a challenge, which a\n * server-side fetch cannot pass, so the dev server rendered \"Store Unavailable\"\n * (6.05k challenged `(development; ssr)` calls in the 7 days to 2026-10-25). In\n * development, on the server, the same request within {@link DEV_SETTINGS_TTL_MS}\n * is answered from memory instead. An hour because the API counts settings\n * requests per hour, so one fetch an hour can never reach its limit; the theme\n * editor's \"Fetch fresh store data\" fetches sooner, and says how old the settings\n * are. A production build never runs it: `import.meta.env.DEV` is statically\n * false there.\n */\nexport const DEV_SETTINGS_TTL_MS = 60 * 60_000;\n\n/** Marks an answer from memory, so the store step does not file it again. */\nconst HIT_HEADER = 'x-twilight-dev-cache';\n\n/** When the answer was really fetched from the API (epoch ms), on fresh answers and reused ones alike. */\nconst FETCHED_AT_HEADER = 'x-twilight-dev-fetched-at';\n\n/**\n * When the dev server fetched these settings from the API, read off the answer the\n * cache handed back; `undefined` when the cache did not handle the call (a\n * production build, the browser, a test), so nothing new reaches the settings there.\n */\nexport function devSettingsFetchedAt(headers: Headers | undefined): number | undefined {\n const at = Number(headers?.get(FETCHED_AT_HEADER));\n return Number.isFinite(at) && at > 0 ? at : undefined;\n}\n\n/**\n * Not carried over to an answer from memory: the body is stored decoded, so its\n * original encoding and length no longer describe it.\n */\nconst DROPPED_HEADERS = new Set(['content-encoding', 'content-length']);\n\ninterface Entry {\n body: string;\n status: number;\n statusText: string;\n headers: [string, string][];\n fetchedAt: number;\n /** The refresh cookie's value when this answer was fetched. */\n refresh: string | null;\n}\n\nexport interface DevSettingsCacheOptions {\n /** Whether this call may use the cache at all. */\n enabled: () => boolean;\n /** The current value of {@link DEV_SETTINGS_REFRESH_COOKIE}, or null. */\n refreshToken: () => string | null;\n now?: () => number;\n ttlMs?: number;\n /** Called the first time an answer comes from memory. */\n onFirstHit?: () => void;\n}\n\nfunction isSettingsRequest(request: Request): boolean {\n if (request.method !== 'GET') return false;\n try {\n return new URL(request.url).pathname.endsWith('/store/settings');\n } catch {\n return false;\n }\n}\n\n/**\n * An answer `requestSettings` accepts: JSON carrying `data`. A 200 without it is\n * refused there as \"Store Unavailable\"; kept here, it would be refused for the next\n * hour too, after the API had recovered.\n */\nfunction hasSettings(body: string): boolean {\n try {\n return Boolean((JSON.parse(body) as { data?: unknown } | null)?.data);\n } catch {\n return false;\n }\n}\n\n/**\n * The request as the API receives it: method, URL and every header the client's\n * hooks set. Keyed on the request itself rather than on the inputs that build it,\n * so a header added to the client later cannot be missing from the key.\n */\nfunction keyOf(request: Request): string {\n const headers = [...request.headers].map(([name, value]) => `${name}: ${value}`).join('\\n');\n return `${request.method} ${request.url}\\n${headers}`;\n}\n\n/**\n * The two ky hooks behind the cache: `lookup` runs last among `beforeRequest`, once\n * every header is set, and `store` among `afterResponse`. Only an answer with\n * settings in it is kept, so a timeout, a 429, a challenge or an empty 200 is asked\n * again on the next render.\n */\nexport function createDevSettingsCache(options: DevSettingsCacheOptions) {\n const {\n enabled,\n refreshToken,\n now = Date.now,\n ttlMs = DEV_SETTINGS_TTL_MS,\n onFirstHit,\n } = options;\n const entries = new Map<string, Entry>();\n let announced = false;\n\n const isFresh = (entry: Entry): boolean =>\n now() - entry.fetchedAt < ttlMs && entry.refresh === refreshToken();\n\n const answerOf = (entry: Entry, hit: boolean): Response => {\n const headers = new Headers(entry.headers);\n headers.set(FETCHED_AT_HEADER, String(entry.fetchedAt));\n if (hit) headers.set(HIT_HEADER, 'hit');\n return new Response(entry.body, {\n status: entry.status,\n statusText: entry.statusText,\n headers,\n });\n };\n\n const lookup: BeforeRequestHook = ({ request }) => {\n if (!enabled() || !isSettingsRequest(request)) return;\n const key = keyOf(request);\n const entry = entries.get(key);\n if (!entry) return;\n if (!isFresh(entry)) {\n entries.delete(key);\n return;\n }\n if (!announced) {\n announced = true;\n onFirstHit?.();\n }\n return answerOf(entry, true);\n };\n\n const store: AfterResponseHook = async ({ request, response }) => {\n if (!enabled() || !isSettingsRequest(request) || !response.ok) return;\n if (response.headers.has(HIT_HEADER)) return;\n // ky hands each hook a clone, so reading it leaves the answer it returns intact.\n const body = await response.text();\n if (!hasSettings(body)) return;\n for (const [key, entry] of entries) {\n if (now() - entry.fetchedAt >= ttlMs) entries.delete(key);\n }\n const entry: Entry = {\n body,\n status: response.status,\n statusText: response.statusText,\n headers: [...response.headers].filter(([name]) => !DROPPED_HEADERS.has(name)),\n fetchedAt: now(),\n refresh: refreshToken(),\n };\n entries.set(keyOf(request), entry);\n // Handed on in place of the API's own answer, so it carries its fetch time too.\n return answerOf(entry, false);\n };\n\n return { lookup, store, clear: () => entries.clear() };\n}\n\nconst readRefreshCookie = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(DEV_SETTINGS_REFRESH_COOKIE) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\nexport const devSettingsCache = createDevSettingsCache({\n // A dev server's render only. A production build has `DEV` statically false,\n // the browser keeps the settings it was handed in its query cache, and vitest\n // runs in `test` mode, where every test wants the request it mocked.\n enabled: () =>\n import.meta.env.DEV && import.meta.env.MODE !== 'test' && typeof document === 'undefined',\n refreshToken: readRefreshCookie,\n onFirstHit: () =>\n console.warn(\n `[twilight] Store settings are reused for up to ${DEV_SETTINGS_TTL_MS / 60_000} minutes while you develop, to stay under the Salla API's rate limit. To see a change you made in the dashboard, press \"Fetch fresh store data\" in the theme editor's side panel: it also says when they were last fetched.`\n ),\n});\n","import ky from 'ky';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport { getStoreIdentifier } from '../utils/sdk-helpers';\nimport { resolveThemeVersionId } from '../utils/theme-version';\nimport { getInjectedRuntimeEnv, readEnv } from '../utils/runtime-env';\nimport { getTwilightContext } from '../twilight/context';\nimport { ENGINE_VERSION } from '../utils/engine-version';\nimport { devSettingsCache } from './dev-settings-cache';\nimport {\n AUTH_TOKEN_COOKIE_NAME,\n CURRENCY_COOKIE_NAME,\n extractCurrencyFromCookies,\n extractScopeFromCookies,\n toCurrencyCode,\n extractTokenFromCookies,\n readSdkScope,\n type ActiveScope,\n} from '../utils/cookies';\n\n// The twilight module store doesn't reliably carry authToken into every scope: on the\n// SERVER workerd has no AsyncLocalStorage, and on BOTH sides this api client can live in a\n// different module instance than the one rootBeforeLoad populates (engine subpath import vs\n// engine-internal relative import). So `getTwilightContext().authToken` is often null even\n// for logged-in users → API calls (orders/customer/…) return `token_not_provided` (400).\n// Read the token directly from the request cookie (server) or document.cookie / salla.storage\n// (client) as a fallback. The server-only import is stripped from the client bundle by\n// createIsomorphicFn.\nconst readFallbackToken = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(AUTH_TOKEN_COOKIE_NAME) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => {\n const fromCookie =\n typeof document !== 'undefined'\n ? extractTokenFromCookies(document.cookie, AUTH_TOKEN_COOKIE_NAME)\n : null;\n if (fromCookie) return fromCookie;\n const storage = typeof window !== 'undefined' ? window.salla?.storage : undefined;\n const fromStorage =\n typeof storage?.get === 'function' ? storage.get(AUTH_TOKEN_COOKIE_NAME) : null;\n if (typeof fromStorage === 'string' && fromStorage) return fromStorage;\n // `?token=` webview injection lands only on the SDK's axios instance\n const fromSdkApi = typeof window !== 'undefined' ? window.salla?.api?.token : undefined;\n return typeof fromSdkApi === 'string' && fromSdkApi ? fromSdkApi : null;\n });\n\n/**\n * The auth token as the api client sees it: twilight context first, cookie/storage fallback.\n * Use this (not `getTwilightContext().authToken`, which is often null for logged-in users —\n * see the note above) to decide whether an authenticated-only query should run.\n */\nexport const getAuthToken = (): string | null =>\n getTwilightContext().authToken ?? readFallbackToken();\n\nconst readRequestCurrency = createIsomorphicFn()\n .server((): string | null => {\n try {\n return toCurrencyCode(getCookie(CURRENCY_COOKIE_NAME));\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\n/**\n * The currency the visitor chose, from the `s-curr` cookie the SDK writes: the API\n * answers in the store's own currency unless the request names one.\n */\nexport function getActiveCurrency(): string | null;\nexport function getActiveCurrency(fallback: string): string;\nexport function getActiveCurrency(fallback: string | null = null): string | null {\n const chosen =\n typeof document !== 'undefined'\n ? extractCurrencyFromCookies(document.cookie)\n : readRequestCurrency();\n return chosen ?? fallback;\n}\n\nconst API_HEADERS = {\n ACCEPT: 'accept',\n ACCEPT_LANGUAGE: 'accept-language',\n APP_OS: 's-app-os',\n APP_VERSION: 's-app-version',\n RAY: 's-ray',\n SOURCE: 's-source',\n THEME_TYPE: 's-theme-type',\n STORE_API_VERSION: 's-store-api-version',\n REQUESTED_WITH: 'x-requested-with',\n CF_PROXY_WHITELIST: 's-cf-proxy-whitelist-id',\n STORE_IDENTIFIER: 'store-identifier',\n CURRENCY: 'currency',\n AUTHORIZATION: 'Authorization',\n VERSION_ID: 's-version-id',\n SCOPE_ID: 's-scope-id',\n SCOPE_TYPE: 's-scope-type',\n SCOPE_ALLOCATION_TYPE: 's-scope-allocation-type',\n SCOPE_ALLOCATION_ID: 's-scope-allocation-id',\n USER_AGENT: 'user-agent',\n} as const;\n\n/**\n * The header every Salla API call is answered by store.\n *\n * Exported because a caller that already knows which store it is asking about\n * must be able to say so on the request itself — see `store.settings`. Without\n * it the only way to name a store is the ambient resolver, and \"the identifier\n * I checked\" and \"the identifier that was sent\" become two different things.\n */\nexport const STORE_IDENTIFIER_HEADER = API_HEADERS.STORE_IDENTIFIER;\n\n/**\n * Active scope: the market plus its branch allocation, as the SDK stores it. On the\n * client it comes from `salla.storage.get('scope')`; before the SDK hydrates storage\n * it falls back to the `scope` cookie the theme mirrors that selection into (see\n * writeScopeCookie), then to the scope twilightMiddleware seeded from the same\n * cookie on the server. Requests vary by the `s-scope-*` headers, so React Query\n * keys must include this to avoid serving another branch's cached categories/products.\n *\n * The cookie step matters for hydration: the SDK is not guaranteed to have\n * populated `salla.storage` by the time the client rebuilds a dehydrated query\n * key, and without it the client would compute null against a scoped SSR key.\n */\nexport const getActiveScope = (): ActiveScope | null => {\n // `!== undefined`, not `!= null`: a null here is the SDK authoritatively saying \"no branch\n // selected\", which must beat a cookie left over from the previous selection. Only a\n // not-yet-ready storage API (undefined) falls through to the cookie.\n const fromStorage = readSdkScope();\n if (fromStorage !== undefined) return fromStorage;\n\n if (typeof document !== 'undefined') {\n const fromCookie = extractScopeFromCookies(document.cookie);\n if (fromCookie != null) return fromCookie;\n }\n\n try {\n return getTwilightContext().scope;\n } catch {\n return null;\n }\n};\n\n/** {@link getActiveScope} reduced to the market id. */\nexport const getActiveScopeId = (): string | null => getActiveScope()?.id ?? null;\n\nconst sharedHeaders = (locale: string) => ({\n [API_HEADERS.ACCEPT]: 'application/json' as const,\n [API_HEADERS.ACCEPT_LANGUAGE]: locale,\n [API_HEADERS.APP_OS]: 'browser',\n [API_HEADERS.APP_VERSION]: '2.14.363',\n [API_HEADERS.RAY]: '50',\n [API_HEADERS.SOURCE]: 'twilight',\n [API_HEADERS.THEME_TYPE]: 'react',\n [API_HEADERS.STORE_API_VERSION]: 'swoole',\n [API_HEADERS.REQUESTED_WITH]: 'XMLHttpRequest',\n [API_HEADERS.CF_PROXY_WHITELIST]: '019a2f78-a64c-7edb-proxy-whitelist-id-9a3a-17afda90f03a',\n});\n\n/**\n * Who a server-rendered call says it is.\n *\n * Every theme worker reaches api.salla.dev from Cloudflare's one Workers address, so\n * salla.dev's per-IP rate limits counted every React store as a single client and\n * refused the calls each page makes (`store/settings` among them: \"Store Unavailable\").\n * The zone skips rate limiting for a User-Agent shaped `Salla-<Name>/<N.N.N> (<env>; <meta>)`\n * from Cloudflare's or AWS's networks, the convention Salla's other services already send.\n *\n * Built from fixed parts: the zone's pattern takes only digits and dots for the version,\n * so a prerelease suffix is dropped, and an unbundled engine (`dev`) reads as `0.0.0`.\n */\nconst SERVER_USER_AGENT = `Salla-TwilightReact/${\n /^\\d+(?:\\.\\d+)*/.exec(ENGINE_VERSION)?.[0] ?? '0.0.0'\n} (${import.meta.env.DEV ? 'development' : 'production'}; ssr)`;\n\n/**\n * Store API base. `VITE_API_URL` override points a preview at a branch backend; unset → prod\n * `api.salla.dev`. Resolution order matters: the value the SSR worker resolved (published into\n * the head, since worker `vars` are server-only `process.env` and never reach the browser\n * bundle) wins, so the hydrated client keeps talking to the backend that rendered the page.\n */\n\nconst STORE_API_BASE =\n getInjectedRuntimeEnv().apiBase || readEnv('VITE_API_URL') || 'https://api.salla.dev/store/v1';\n\nexport const api = ky.extend({\n prefix: STORE_API_BASE,\n timeout: 8000,\n hooks: {\n beforeRequest: [\n ({ request }) => {\n const { locale, authToken } = getTwilightContext();\n const headers = sharedHeaders(locale);\n for (const [key, value] of Object.entries(headers)) {\n request.headers.set(key, value);\n }\n // Only when the caller did not say. `headers.set` here would otherwise\n // overwrite a per-request identifier with the ambient one, which is a\n // silent way to answer a question about one store with another's data.\n if (!request.headers.get(API_HEADERS.STORE_IDENTIFIER)) {\n request.headers.set(API_HEADERS.STORE_IDENTIFIER, getStoreIdentifier());\n }\n\n // Server only. A browser call comes from the shopper's own address and is\n // counted against it, which is what the zone's limits are for.\n if (typeof document === 'undefined') {\n request.headers.set(API_HEADERS.USER_AGENT, SERVER_USER_AGENT);\n }\n\n const scope = getActiveScope();\n\n // The version the request asked for, else the one the settings named for\n // this scope. Absent means \"whatever is live\", which is what an ordinary\n // storefront visit wants — so a null is left off rather than sent empty.\n const versionId = resolveThemeVersionId(scope?.id ?? null);\n if (versionId) {\n request.headers.set(API_HEADERS.VERSION_ID, versionId);\n }\n\n const currency = getActiveCurrency();\n if (currency) request.headers.set(API_HEADERS.CURRENCY, currency);\n\n const token = authToken ?? readFallbackToken();\n if (token) {\n request.headers.set(API_HEADERS.AUTHORIZATION, `Bearer ${token}`);\n }\n\n // The same four the SDK's own client sends. The API resolves stock per\n // allocation: id alone asks about the market, not the branch the shopper chose.\n if (scope) {\n request.headers.set(API_HEADERS.SCOPE_ID, scope.id);\n if (scope.type) request.headers.set(API_HEADERS.SCOPE_TYPE, scope.type);\n if (scope.allocation_type)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_TYPE, scope.allocation_type);\n if (scope.allocation_id)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_ID, scope.allocation_id);\n }\n },\n // Last, so it keys on the request with every header above set.\n devSettingsCache.lookup,\n ],\n afterResponse: [devSettingsCache.store],\n },\n});\n\nexport const cdn = ky.extend({\n prefix: 'https://cdn.salla.network',\n timeout: 5000,\n});\n\n/**\n * The merchant uploader's public bucket, `admin-uploader-prod`.\n *\n * A different host from {@link cdn} and a different thing behind it: this one\n * is an R2 custom domain, so a read never passes through a worker. Storefront\n * translations live here, per language, under `translations/` — see\n * `api/translations.ts`.\n */\nexport const filesCdn = ky.extend({\n prefix: 'https://cdn.files.salla.network',\n timeout: 5000,\n});\n"]}
1
+ {"version":3,"sources":["../src/utils/engine-version.ts","../src/api/dev-settings-cache.ts","../src/api/client.ts"],"names":["entry","createIsomorphicFn","getCookie"],"mappings":"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","file":"chunk-E5DP3MHE.js","sourcesContent":["/**\n * The engine's own build version, injected by tsup `define` when dist is\n * built. Falls back to 'dev' when the source runs unbundled (vitest, direct\n * src imports in the monorepo).\n *\n * Exposed at runtime as `salla.versions.engine` by `useTwilightInit` so a\n * storefront can always be asked which engine build rendered it.\n */\nexport const ENGINE_VERSION: string =\n typeof __TWILIGHT_ENGINE_VERSION__ !== 'undefined' ? __TWILIGHT_ENGINE_VERSION__ : 'dev';\n","import type { AfterResponseHook, BeforeRequestHook } from 'ky';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport { DEV_SETTINGS_REFRESH_COOKIE } from '../utils/dev-settings-refresh';\n\n/**\n * A dev server reuses a store's settings for up to an hour.\n *\n * Every server render asks the API for `store/settings`, and a developer clicking\n * around a theme renders dozens of pages a minute. The API answers a burst of\n * settings requests for one store from one address with a challenge, which a\n * server-side fetch cannot pass, so the dev server rendered \"Store Unavailable\"\n * (6.05k challenged `(development; ssr)` calls in the 7 days to 2026-10-25). In\n * development, on the server, the same request within {@link DEV_SETTINGS_TTL_MS}\n * is answered from memory instead. An hour because the API counts settings\n * requests per hour, so one fetch an hour can never reach its limit; the theme\n * editor's \"Fetch fresh store data\" fetches sooner, and says how old the settings\n * are. A production build never runs it: `import.meta.env.DEV` is statically\n * false there.\n */\nexport const DEV_SETTINGS_TTL_MS = 60 * 60_000;\n\n/** Marks an answer from memory, so the store step does not file it again. */\nconst HIT_HEADER = 'x-twilight-dev-cache';\n\n/** When the answer was really fetched from the API (epoch ms), on fresh answers and reused ones alike. */\nconst FETCHED_AT_HEADER = 'x-twilight-dev-fetched-at';\n\n/**\n * When the dev server fetched these settings from the API, read off the answer the\n * cache handed back; `undefined` when the cache did not handle the call (a\n * production build, the browser, a test), so nothing new reaches the settings there.\n */\nexport function devSettingsFetchedAt(headers: Headers | undefined): number | undefined {\n const at = Number(headers?.get(FETCHED_AT_HEADER));\n return Number.isFinite(at) && at > 0 ? at : undefined;\n}\n\n/**\n * Not carried over to an answer from memory: the body is stored decoded, so its\n * original encoding and length no longer describe it.\n */\nconst DROPPED_HEADERS = new Set(['content-encoding', 'content-length']);\n\ninterface Entry {\n body: string;\n status: number;\n statusText: string;\n headers: [string, string][];\n fetchedAt: number;\n /** The refresh cookie's value when this answer was fetched. */\n refresh: string | null;\n}\n\nexport interface DevSettingsCacheOptions {\n /** Whether this call may use the cache at all. */\n enabled: () => boolean;\n /** The current value of {@link DEV_SETTINGS_REFRESH_COOKIE}, or null. */\n refreshToken: () => string | null;\n now?: () => number;\n ttlMs?: number;\n /** Called the first time an answer comes from memory. */\n onFirstHit?: () => void;\n}\n\nfunction isSettingsRequest(request: Request): boolean {\n if (request.method !== 'GET') return false;\n try {\n return new URL(request.url).pathname.endsWith('/store/settings');\n } catch {\n return false;\n }\n}\n\n/**\n * An answer `requestSettings` accepts: JSON carrying `data`. A 200 without it is\n * refused there as \"Store Unavailable\"; kept here, it would be refused for the next\n * hour too, after the API had recovered.\n */\nfunction hasSettings(body: string): boolean {\n try {\n return Boolean((JSON.parse(body) as { data?: unknown } | null)?.data);\n } catch {\n return false;\n }\n}\n\n/**\n * The request as the API receives it: method, URL and every header the client's\n * hooks set. Keyed on the request itself rather than on the inputs that build it,\n * so a header added to the client later cannot be missing from the key.\n */\nfunction keyOf(request: Request): string {\n const headers = [...request.headers].map(([name, value]) => `${name}: ${value}`).join('\\n');\n return `${request.method} ${request.url}\\n${headers}`;\n}\n\n/**\n * The two ky hooks behind the cache: `lookup` runs last among `beforeRequest`, once\n * every header is set, and `store` among `afterResponse`. Only an answer with\n * settings in it is kept, so a timeout, a 429, a challenge or an empty 200 is asked\n * again on the next render.\n */\nexport function createDevSettingsCache(options: DevSettingsCacheOptions) {\n const {\n enabled,\n refreshToken,\n now = Date.now,\n ttlMs = DEV_SETTINGS_TTL_MS,\n onFirstHit,\n } = options;\n const entries = new Map<string, Entry>();\n let announced = false;\n\n const isFresh = (entry: Entry): boolean =>\n now() - entry.fetchedAt < ttlMs && entry.refresh === refreshToken();\n\n const answerOf = (entry: Entry, hit: boolean): Response => {\n const headers = new Headers(entry.headers);\n headers.set(FETCHED_AT_HEADER, String(entry.fetchedAt));\n if (hit) headers.set(HIT_HEADER, 'hit');\n return new Response(entry.body, {\n status: entry.status,\n statusText: entry.statusText,\n headers,\n });\n };\n\n const lookup: BeforeRequestHook = ({ request }) => {\n if (!enabled() || !isSettingsRequest(request)) return;\n const key = keyOf(request);\n const entry = entries.get(key);\n if (!entry) return;\n if (!isFresh(entry)) {\n entries.delete(key);\n return;\n }\n if (!announced) {\n announced = true;\n onFirstHit?.();\n }\n return answerOf(entry, true);\n };\n\n const store: AfterResponseHook = async ({ request, response }) => {\n if (!enabled() || !isSettingsRequest(request) || !response.ok) return;\n if (response.headers.has(HIT_HEADER)) return;\n // ky hands each hook a clone, so reading it leaves the answer it returns intact.\n const body = await response.text();\n if (!hasSettings(body)) return;\n for (const [key, entry] of entries) {\n if (now() - entry.fetchedAt >= ttlMs) entries.delete(key);\n }\n const entry: Entry = {\n body,\n status: response.status,\n statusText: response.statusText,\n headers: [...response.headers].filter(([name]) => !DROPPED_HEADERS.has(name)),\n fetchedAt: now(),\n refresh: refreshToken(),\n };\n entries.set(keyOf(request), entry);\n // Handed on in place of the API's own answer, so it carries its fetch time too.\n return answerOf(entry, false);\n };\n\n return { lookup, store, clear: () => entries.clear() };\n}\n\nconst readRefreshCookie = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(DEV_SETTINGS_REFRESH_COOKIE) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\nexport const devSettingsCache = createDevSettingsCache({\n // A dev server's render only. A production build has `DEV` statically false,\n // the browser keeps the settings it was handed in its query cache, and vitest\n // runs in `test` mode, where every test wants the request it mocked.\n enabled: () =>\n import.meta.env.DEV && import.meta.env.MODE !== 'test' && typeof document === 'undefined',\n refreshToken: readRefreshCookie,\n onFirstHit: () =>\n console.warn(\n `[twilight] Store settings are reused for up to ${DEV_SETTINGS_TTL_MS / 60_000} minutes while you develop, to stay under the Salla API's rate limit. To see a change you made in the dashboard, press \"Fetch fresh store data\" in the theme editor's side panel: it also says when they were last fetched.`\n ),\n});\n","import ky from 'ky';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport { getStoreIdentifier } from '../utils/sdk-helpers';\nimport { resolveThemeVersionId } from '../utils/theme-version';\nimport { getInjectedRuntimeEnv, readEnv } from '../utils/runtime-env';\nimport { getTwilightContext } from '../twilight/context';\nimport { ENGINE_VERSION } from '../utils/engine-version';\nimport { devSettingsCache } from './dev-settings-cache';\nimport {\n AUTH_TOKEN_COOKIE_NAME,\n CURRENCY_COOKIE_NAME,\n extractCurrencyFromCookies,\n extractScopeFromCookies,\n toCurrencyCode,\n extractTokenFromCookies,\n readSdkScope,\n type ActiveScope,\n} from '../utils/cookies';\n\n// The twilight module store doesn't reliably carry authToken into every scope: on the\n// SERVER workerd has no AsyncLocalStorage, and on BOTH sides this api client can live in a\n// different module instance than the one rootBeforeLoad populates (engine subpath import vs\n// engine-internal relative import). So `getTwilightContext().authToken` is often null even\n// for logged-in users → API calls (orders/customer/…) return `token_not_provided` (400).\n// Read the token directly from the request cookie (server) or document.cookie / salla.storage\n// (client) as a fallback. The server-only import is stripped from the client bundle by\n// createIsomorphicFn.\nconst readFallbackToken = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(AUTH_TOKEN_COOKIE_NAME) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => {\n const fromCookie =\n typeof document !== 'undefined'\n ? extractTokenFromCookies(document.cookie, AUTH_TOKEN_COOKIE_NAME)\n : null;\n if (fromCookie) return fromCookie;\n const storage = typeof window !== 'undefined' ? window.salla?.storage : undefined;\n const fromStorage =\n typeof storage?.get === 'function' ? storage.get(AUTH_TOKEN_COOKIE_NAME) : null;\n if (typeof fromStorage === 'string' && fromStorage) return fromStorage;\n // `?token=` webview injection lands only on the SDK's axios instance\n const fromSdkApi = typeof window !== 'undefined' ? window.salla?.api?.token : undefined;\n return typeof fromSdkApi === 'string' && fromSdkApi ? fromSdkApi : null;\n });\n\n/**\n * The auth token as the api client sees it: twilight context first, cookie/storage fallback.\n * Use this (not `getTwilightContext().authToken`, which is often null for logged-in users —\n * see the note above) to decide whether an authenticated-only query should run.\n */\nexport const getAuthToken = (): string | null =>\n getTwilightContext().authToken ?? readFallbackToken();\n\nconst readRequestCurrency = createIsomorphicFn()\n .server((): string | null => {\n try {\n return toCurrencyCode(getCookie(CURRENCY_COOKIE_NAME));\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\n/**\n * The currency the visitor chose, from the `s-curr` cookie the SDK writes: the API\n * answers in the store's own currency unless the request names one.\n */\nexport function getActiveCurrency(): string | null;\nexport function getActiveCurrency(fallback: string): string;\nexport function getActiveCurrency(fallback: string | null = null): string | null {\n const chosen =\n typeof document !== 'undefined'\n ? extractCurrencyFromCookies(document.cookie)\n : readRequestCurrency();\n return chosen ?? fallback;\n}\n\nconst API_HEADERS = {\n ACCEPT: 'accept',\n ACCEPT_LANGUAGE: 'accept-language',\n APP_OS: 's-app-os',\n APP_VERSION: 's-app-version',\n RAY: 's-ray',\n SOURCE: 's-source',\n THEME_TYPE: 's-theme-type',\n STORE_API_VERSION: 's-store-api-version',\n REQUESTED_WITH: 'x-requested-with',\n CF_PROXY_WHITELIST: 's-cf-proxy-whitelist-id',\n STORE_IDENTIFIER: 'store-identifier',\n CURRENCY: 'currency',\n AUTHORIZATION: 'Authorization',\n VERSION_ID: 's-version-id',\n SCOPE_ID: 's-scope-id',\n SCOPE_TYPE: 's-scope-type',\n SCOPE_ALLOCATION_TYPE: 's-scope-allocation-type',\n SCOPE_ALLOCATION_ID: 's-scope-allocation-id',\n USER_AGENT: 'user-agent',\n} as const;\n\n/**\n * The header every Salla API call is answered by store.\n *\n * Exported because a caller that already knows which store it is asking about\n * must be able to say so on the request itself — see `store.settings`. Without\n * it the only way to name a store is the ambient resolver, and \"the identifier\n * I checked\" and \"the identifier that was sent\" become two different things.\n */\nexport const STORE_IDENTIFIER_HEADER = API_HEADERS.STORE_IDENTIFIER;\n\n/**\n * Active scope: the market plus its branch allocation, as the SDK stores it. On the\n * client it comes from `salla.storage.get('scope')`; before the SDK hydrates storage\n * it falls back to the `scope` cookie the theme mirrors that selection into (see\n * writeScopeCookie), then to the scope twilightMiddleware seeded from the same\n * cookie on the server. Requests vary by the `s-scope-*` headers, so React Query\n * keys must include this to avoid serving another branch's cached categories/products.\n *\n * The cookie step matters for hydration: the SDK is not guaranteed to have\n * populated `salla.storage` by the time the client rebuilds a dehydrated query\n * key, and without it the client would compute null against a scoped SSR key.\n */\nexport const getActiveScope = (): ActiveScope | null => {\n // `!== undefined`, not `!= null`: a null here is the SDK authoritatively saying \"no branch\n // selected\", which must beat a cookie left over from the previous selection. Only a\n // not-yet-ready storage API (undefined) falls through to the cookie.\n const fromStorage = readSdkScope();\n if (fromStorage !== undefined) return fromStorage;\n\n if (typeof document !== 'undefined') {\n const fromCookie = extractScopeFromCookies(document.cookie);\n if (fromCookie != null) return fromCookie;\n }\n\n try {\n return getTwilightContext().scope;\n } catch {\n return null;\n }\n};\n\n/** {@link getActiveScope} reduced to the market id. */\nexport const getActiveScopeId = (): string | null => getActiveScope()?.id ?? null;\n\nconst sharedHeaders = (locale: string) => ({\n [API_HEADERS.ACCEPT]: 'application/json' as const,\n [API_HEADERS.ACCEPT_LANGUAGE]: locale,\n [API_HEADERS.APP_OS]: 'browser',\n [API_HEADERS.APP_VERSION]: '2.14.363',\n [API_HEADERS.RAY]: '50',\n [API_HEADERS.SOURCE]: 'twilight',\n [API_HEADERS.THEME_TYPE]: 'react',\n [API_HEADERS.STORE_API_VERSION]: 'swoole',\n [API_HEADERS.REQUESTED_WITH]: 'XMLHttpRequest',\n [API_HEADERS.CF_PROXY_WHITELIST]: '019a2f78-a64c-7edb-proxy-whitelist-id-9a3a-17afda90f03a',\n});\n\n/**\n * Who a server-rendered call says it is.\n *\n * Every theme worker reaches api.salla.dev from Cloudflare's one Workers address, so\n * salla.dev's per-IP rate limits counted every React store as a single client and\n * refused the calls each page makes (`store/settings` among them: \"Store Unavailable\").\n * The zone skips rate limiting for a User-Agent shaped `Salla-<Name>/<N.N.N> (<env>; <meta>)`\n * from Cloudflare's or AWS's networks, the convention Salla's other services already send.\n *\n * Built from fixed parts: the zone's pattern takes only digits and dots for the version,\n * so a prerelease suffix is dropped, and an unbundled engine (`dev`) reads as `0.0.0`.\n */\nconst SERVER_USER_AGENT = `Salla-TwilightReact/${\n /^\\d+(?:\\.\\d+)*/.exec(ENGINE_VERSION)?.[0] ?? '0.0.0'\n} (${import.meta.env.DEV ? 'development' : 'production'}; ssr)`;\n\n/**\n * Store API base. `VITE_API_URL` override points a preview at a branch backend; unset → prod\n * `api.salla.dev`. Resolution order matters: the value the SSR worker resolved (published into\n * the head, since worker `vars` are server-only `process.env` and never reach the browser\n * bundle) wins, so the hydrated client keeps talking to the backend that rendered the page.\n */\n\nconst STORE_API_BASE =\n getInjectedRuntimeEnv().apiBase || readEnv('VITE_API_URL') || 'https://api.salla.dev/store/v1';\n\nexport const api = ky.extend({\n prefix: STORE_API_BASE,\n timeout: 8000,\n hooks: {\n beforeRequest: [\n ({ request }) => {\n const { locale, authToken } = getTwilightContext();\n const headers = sharedHeaders(locale);\n for (const [key, value] of Object.entries(headers)) {\n request.headers.set(key, value);\n }\n // Only when the caller did not say. `headers.set` here would otherwise\n // overwrite a per-request identifier with the ambient one, which is a\n // silent way to answer a question about one store with another's data.\n if (!request.headers.get(API_HEADERS.STORE_IDENTIFIER)) {\n request.headers.set(API_HEADERS.STORE_IDENTIFIER, getStoreIdentifier());\n }\n\n // Server only. A browser call comes from the shopper's own address and is\n // counted against it, which is what the zone's limits are for.\n if (typeof document === 'undefined') {\n request.headers.set(API_HEADERS.USER_AGENT, SERVER_USER_AGENT);\n }\n\n const scope = getActiveScope();\n\n // The version the request asked for, else the one the settings named for\n // this scope. Absent means \"whatever is live\", which is what an ordinary\n // storefront visit wants — so a null is left off rather than sent empty.\n const versionId = resolveThemeVersionId(scope?.id ?? null);\n if (versionId) {\n request.headers.set(API_HEADERS.VERSION_ID, versionId);\n }\n\n const currency = getActiveCurrency();\n if (currency) request.headers.set(API_HEADERS.CURRENCY, currency);\n\n const token = authToken ?? readFallbackToken();\n if (token) {\n request.headers.set(API_HEADERS.AUTHORIZATION, `Bearer ${token}`);\n }\n\n // The same four the SDK's own client sends. The API resolves stock per\n // allocation: id alone asks about the market, not the branch the shopper chose.\n if (scope) {\n request.headers.set(API_HEADERS.SCOPE_ID, scope.id);\n if (scope.type) request.headers.set(API_HEADERS.SCOPE_TYPE, scope.type);\n if (scope.allocation_type)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_TYPE, scope.allocation_type);\n if (scope.allocation_id)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_ID, scope.allocation_id);\n }\n },\n // Last, so it keys on the request with every header above set.\n devSettingsCache.lookup,\n ],\n afterResponse: [devSettingsCache.store],\n },\n});\n\nexport const cdn = ky.extend({\n prefix: 'https://cdn.salla.network',\n timeout: 5000,\n});\n\n/**\n * The merchant uploader's public bucket, `admin-uploader-prod`.\n *\n * A different host from {@link cdn} and a different thing behind it: this one\n * is an R2 custom domain, so a read never passes through a worker. Storefront\n * translations live here, per language, under `translations/` — see\n * `api/translations.ts`.\n */\nexport const filesCdn = ky.extend({\n prefix: 'https://cdn.files.salla.network',\n timeout: 5000,\n});\n"]}
@@ -1,4 +1,4 @@
1
- import { getRequestStore } from './chunk-7VNVCHID.js';
1
+ import { getRequestStore } from './chunk-6K34BCUP.js';
2
2
  import { FALLBACK_LOCALE, isLocale } from './chunk-T72DAX7R.js';
3
3
 
4
4
  // src/utils/cookies.ts
@@ -29,10 +29,13 @@ function hostnameOf(host) {
29
29
  function isLoopback(hostname) {
30
30
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname.endsWith(".localhost");
31
31
  }
32
+ function isPreviewHost(host) {
33
+ if (!host) return false;
34
+ return STORE_ID_HOSTS.includes(hostnameOf(host));
35
+ }
32
36
  function allowsRequestStoreId(host) {
33
37
  if (!host) return false;
34
- const hostname = hostnameOf(host);
35
- return STORE_ID_HOSTS.includes(hostname) || isLoopback(hostname);
38
+ return isPreviewHost(host) || isLoopback(hostnameOf(host));
36
39
  }
37
40
  function hostIdentifiesStore(host) {
38
41
  return Boolean(host) && !allowsRequestStoreId(host);
@@ -438,11 +441,18 @@ function resolveStoreBaseFollowsLocale() {
438
441
  const published = getInjectedRuntimeEnv();
439
442
  return Boolean(published.storeBase && published.storeBaseFollowsLocale);
440
443
  }
444
+ function currentHost() {
445
+ return getRequestStore().requestHost ?? (typeof window !== "undefined" ? window.location.host : null);
446
+ }
441
447
  function resolveStoreBaseRedirect(username, href) {
442
- const host = getRequestStore().requestHost ?? (typeof window !== "undefined" ? window.location.host : null);
443
- return storeBaseRedirectHref({ host, base: resolveStoreBase(), username, href });
448
+ return storeBaseRedirectHref({
449
+ host: currentHost(),
450
+ base: resolveStoreBase(),
451
+ username,
452
+ href
453
+ });
444
454
  }
445
455
 
446
- export { AUTH_TOKEN_COOKIE_NAME, CURRENCY_COOKIE_NAME, LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_COOKIE_NAME, SCOPE_COOKIE_MAX_AGE, SCOPE_COOKIE_NAME, STORE_BASE_HEADER, clearAuthTokenCookie, decideSharedHostLanguage, escapeForInlineScript, extractCurrencyFromCookies, extractScopeFromCookies, extractScopeFromUrl, extractTokenFromCookies, getInjectedRuntimeEnv, hasLanguageParam, hasStoreUrlBase, isLoopback, legacyLocaleRedirectHref, loginRedirectHref, parseStoreId, prefixStoreBase, readEnv, readSdkScope, rememberDevStoreId, renderRuntimeEnvScript, resolveAddressedStore, resolveRequestScope, resolveRequestVersionId, resolveStoreBase, resolveStoreBaseFollowsLocale, resolveStoreBaseRedirect, resolveStoreIdentifier, sameScope, splitLeadingSegment, stripStoreBase, syncScopeCookie, toCurrencyCode, virtualLocale, withLanguageParam, withoutStoreUrlBase };
447
- //# sourceMappingURL=chunk-FHU2MXZA.js.map
448
- //# sourceMappingURL=chunk-FHU2MXZA.js.map
456
+ export { AUTH_TOKEN_COOKIE_NAME, CURRENCY_COOKIE_NAME, LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_COOKIE_NAME, SCOPE_COOKIE_MAX_AGE, SCOPE_COOKIE_NAME, STORE_BASE_HEADER, clearAuthTokenCookie, currentHost, decideSharedHostLanguage, escapeForInlineScript, extractCurrencyFromCookies, extractScopeFromCookies, extractScopeFromUrl, extractTokenFromCookies, getInjectedRuntimeEnv, hasLanguageParam, hasStoreUrlBase, isLoopback, isPreviewHost, legacyLocaleRedirectHref, loginRedirectHref, parseStoreId, prefixStoreBase, readEnv, readSdkScope, rememberDevStoreId, renderRuntimeEnvScript, resolveAddressedStore, resolveRequestScope, resolveRequestVersionId, resolveStoreBase, resolveStoreBaseFollowsLocale, resolveStoreBaseRedirect, resolveStoreIdentifier, sameScope, splitLeadingSegment, stripStoreBase, syncScopeCookie, toCurrencyCode, virtualLocale, withLanguageParam, withoutStoreUrlBase };
457
+ //# sourceMappingURL=chunk-FXVII733.js.map
458
+ //# sourceMappingURL=chunk-FXVII733.js.map