@salla.sa/twilight-theme-engine 1.0.143 → 1.0.145
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.
- package/dist/{AddToCartForm-HIIF72O4.js → AddToCartForm-NZNFVGDV.js} +3 -3
- package/dist/{AddToCartForm-HIIF72O4.js.map → AddToCartForm-NZNFVGDV.js.map} +1 -1
- package/dist/{BlogAuthorPage-LVUTPDWU.js → BlogAuthorPage-BXRIYXVN.js} +28 -27
- package/dist/BlogAuthorPage-BXRIYXVN.js.map +1 -0
- package/dist/{BlogCategoryPage-4Q2MU5IF.js → BlogCategoryPage-GHWC2WVM.js} +28 -27
- package/dist/BlogCategoryPage-GHWC2WVM.js.map +1 -0
- package/dist/{BlogPage-YG3INJ6S.js → BlogPage-ZCGNKBLI.js} +26 -25
- package/dist/BlogPage-ZCGNKBLI.js.map +1 -0
- package/dist/{BlogSinglePage-P4OPKCYA.js → BlogSinglePage-TH7Z3MKB.js} +26 -25
- package/dist/BlogSinglePage-TH7Z3MKB.js.map +1 -0
- package/dist/{BlogTagPage-RC4CSYJM.js → BlogTagPage-GM422SOW.js} +28 -27
- package/dist/BlogTagPage-GM422SOW.js.map +1 -0
- package/dist/{BrandsPage-SRQANTCQ.js → BrandsPage-LNNPU4NX.js} +27 -26
- package/dist/BrandsPage-LNNPU4NX.js.map +1 -0
- package/dist/{Breadcrumb-I6RHU7TL.js → Breadcrumb-TSG2CW3S.js} +26 -25
- package/dist/Breadcrumb-TSG2CW3S.js.map +1 -0
- package/dist/{CartItem-WXV4HG7L.js → CartItem-UVSLCSEP.js} +26 -25
- package/dist/CartItem-UVSLCSEP.js.map +1 -0
- package/dist/{CartSummary-66PEAPVR.js → CartSummary-ZCXTED4G.js} +26 -25
- package/dist/CartSummary-ZCXTED4G.js.map +1 -0
- package/dist/{Copyright-ADNRUD2V.js → Copyright-B25RLEVV.js} +3 -3
- package/dist/{Copyright-ADNRUD2V.js.map → Copyright-B25RLEVV.js.map} +1 -1
- package/dist/{CustomerLayout-S4PJGKMT.js → CustomerLayout-WGEUJEDP.js} +26 -25
- package/dist/CustomerLayout-WGEUJEDP.js.map +1 -0
- package/dist/{Footer-RYWLSTKI.js → Footer-QMNESEEI.js} +4 -4
- package/dist/{Footer-RYWLSTKI.js.map → Footer-QMNESEEI.js.map} +1 -1
- package/dist/{Header-IM7KKNSG.js → Header-ZPDXQ7U6.js} +11 -11
- package/dist/{Header-IM7KKNSG.js.map → Header-ZPDXQ7U6.js.map} +1 -1
- package/dist/{LatestProducts-VMDICC67.js → LatestProducts-UEUM47MI.js} +28 -27
- package/dist/LatestProducts-UEUM47MI.js.map +1 -0
- package/dist/{LoyaltyPage-N7LLJ3ZW.js → LoyaltyPage-ZM3FDTV3.js} +26 -25
- package/dist/LoyaltyPage-ZM3FDTV3.js.map +1 -0
- package/dist/{LoyaltyPointsPage-HVK6PJRL.js → LoyaltyPointsPage-QQIKIBTH.js} +8 -8
- package/dist/{LoyaltyPointsPage-HVK6PJRL.js.map → LoyaltyPointsPage-QQIKIBTH.js.map} +1 -1
- package/dist/{MainMenu-ICQUOKYN.js → MainMenu-3Z7HRQGU.js} +7 -7
- package/dist/{MainMenu-ICQUOKYN.js.map → MainMenu-3Z7HRQGU.js.map} +1 -1
- package/dist/{MasterLayout-WO743UZA.js → MasterLayout-ZRTWOZGC.js} +26 -25
- package/dist/{MasterLayout-WO743UZA.js.map → MasterLayout-ZRTWOZGC.js.map} +1 -1
- package/dist/{MobileMenu-TK5S3UAR.js → MobileMenu-SC7HJ6BT.js} +27 -26
- package/dist/MobileMenu-SC7HJ6BT.js.map +1 -0
- package/dist/{NotificationsPage-FNC7EOFV.js → NotificationsPage-JMAZ2N2A.js} +26 -25
- package/dist/NotificationsPage-JMAZ2N2A.js.map +1 -0
- package/dist/{OrderSinglePage-YS6FBSCD.js → OrderSinglePage-6MAFH4Q6.js} +27 -26
- package/dist/OrderSinglePage-6MAFH4Q6.js.map +1 -0
- package/dist/{OrdersPage-V3YMXMSN.js → OrdersPage-NMINSG67.js} +26 -25
- package/dist/OrdersPage-NMINSG67.js.map +1 -0
- package/dist/{PageSingle-QAAJ6NL7.js → PageSingle-WLIXOODC.js} +6 -6
- package/dist/{PageSingle-QAAJ6NL7.js.map → PageSingle-WLIXOODC.js.map} +1 -1
- package/dist/{ProductDetails-DUQPPDWZ.js → ProductDetails-NFZLUKLN.js} +7 -7
- package/dist/{ProductDetails-DUQPPDWZ.js.map → ProductDetails-NFZLUKLN.js.map} +1 -1
- package/dist/{ProfilePage-L7DOZZBH.js → ProfilePage-5PBU637J.js} +26 -25
- package/dist/ProfilePage-5PBU637J.js.map +1 -0
- package/dist/{ReviewsPage-6EIMUR5L.js → ReviewsPage-RWNFVHWR.js} +3 -3
- package/dist/{ReviewsPage-6EIMUR5L.js.map → ReviewsPage-RWNFVHWR.js.map} +1 -1
- package/dist/{SeoCartWidget-IW2EIOP3.js → SeoCartWidget-HPBQ6673.js} +26 -25
- package/dist/SeoCartWidget-HPBQ6673.js.map +1 -0
- package/dist/{SettingsPage-3BZD6EXX.js → SettingsPage-Y5X5BNHD.js} +26 -25
- package/dist/SettingsPage-Y5X5BNHD.js.map +1 -0
- package/dist/{StoreClosedNotification-Z7QF4CPA.js → StoreClosedNotification-5DOQFF2O.js} +27 -26
- package/dist/{StoreClosedNotification-Z7QF4CPA.js.map → StoreClosedNotification-5DOQFF2O.js.map} +1 -1
- package/dist/{TestimonialsPage-IA7YUNJI.js → TestimonialsPage-ZDALOH2L.js} +6 -6
- package/dist/{TestimonialsPage-IA7YUNJI.js.map → TestimonialsPage-ZDALOH2L.js.map} +1 -1
- package/dist/{ThankYouPage-GPPMDT4G.js → ThankYouPage-SYMPRWCS.js} +26 -25
- package/dist/ThankYouPage-SYMPRWCS.js.map +1 -0
- package/dist/{WalletPage-JYNPVXER.js → WalletPage-DPWZBROY.js} +27 -26
- package/dist/WalletPage-DPWZBROY.js.map +1 -0
- package/dist/WebMcpTools-3TBLKZL5.js +404 -0
- package/dist/WebMcpTools-3TBLKZL5.js.map +1 -0
- package/dist/{WishlistPage-APID33BZ.js → WishlistPage-BM3XSMQF.js} +28 -27
- package/dist/WishlistPage-BM3XSMQF.js.map +1 -0
- package/dist/api/advertisement.js +4 -4
- package/dist/api/apps.js +4 -4
- package/dist/api/blog.js +6 -6
- package/dist/api/brands.js +6 -6
- package/dist/api/cart.js +6 -6
- package/dist/api/category.js +6 -6
- package/dist/api/client.js +3 -3
- package/dist/api/home.js +4 -4
- package/dist/api/loyalty.js +6 -6
- package/dist/api/menu.js +4 -4
- package/dist/api/notification.js +4 -4
- package/dist/api/order.js +6 -6
- package/dist/api/page.js +6 -6
- package/dist/api/product.js +6 -6
- package/dist/api/profile.js +3 -3
- package/dist/api/store.js +5 -5
- package/dist/api/translations.js +4 -4
- package/dist/api/user.js +4 -4
- package/dist/api/wallet.js +4 -4
- package/dist/api/wishlist.js +7 -7
- package/dist/{chunk-FH4EVOMN.js → chunk-2N6XZZ4W.js} +4 -4
- package/dist/{chunk-FH4EVOMN.js.map → chunk-2N6XZZ4W.js.map} +1 -1
- package/dist/{chunk-2LB2TBNP.js → chunk-2ZESCQRM.js} +3 -3
- package/dist/{chunk-2LB2TBNP.js.map → chunk-2ZESCQRM.js.map} +1 -1
- package/dist/{chunk-BXBXCVSQ.js → chunk-52QZKUDU.js} +6 -6
- package/dist/{chunk-BXBXCVSQ.js.map → chunk-52QZKUDU.js.map} +1 -1
- package/dist/{chunk-7HZ6JQAJ.js → chunk-5JZSBFA5.js} +3 -3
- package/dist/{chunk-7HZ6JQAJ.js.map → chunk-5JZSBFA5.js.map} +1 -1
- package/dist/{chunk-N6ZE6HUX.js → chunk-5V4W3GBI.js} +5 -5
- package/dist/{chunk-N6ZE6HUX.js.map → chunk-5V4W3GBI.js.map} +1 -1
- package/dist/{chunk-3E3ABCPC.js → chunk-6TFM3UTF.js} +3 -3
- package/dist/{chunk-3E3ABCPC.js.map → chunk-6TFM3UTF.js.map} +1 -1
- package/dist/{chunk-4LTS5AZ3.js → chunk-7NTPNCIK.js} +3 -3
- package/dist/{chunk-4LTS5AZ3.js.map → chunk-7NTPNCIK.js.map} +1 -1
- package/dist/{chunk-SBZZEW6D.js → chunk-AJM7KUA3.js} +5 -5
- package/dist/{chunk-SBZZEW6D.js.map → chunk-AJM7KUA3.js.map} +1 -1
- package/dist/{chunk-2OHGW43N.js → chunk-BMCECPSU.js} +3 -3
- package/dist/{chunk-2OHGW43N.js.map → chunk-BMCECPSU.js.map} +1 -1
- package/dist/{chunk-LBYLBSVN.js → chunk-DHWMC6VU.js} +4 -4
- package/dist/{chunk-LBYLBSVN.js.map → chunk-DHWMC6VU.js.map} +1 -1
- package/dist/{chunk-GDLT2GGX.js → chunk-DMR3ICV5.js} +6 -6
- package/dist/{chunk-GDLT2GGX.js.map → chunk-DMR3ICV5.js.map} +1 -1
- package/dist/{chunk-WQPG22DY.js → chunk-EGI7F57E.js} +3 -3
- package/dist/{chunk-WQPG22DY.js.map → chunk-EGI7F57E.js.map} +1 -1
- package/dist/{chunk-4RKNISJB.js → chunk-ETC7OJT5.js} +3 -3
- package/dist/{chunk-4RKNISJB.js.map → chunk-ETC7OJT5.js.map} +1 -1
- package/dist/{chunk-RI6FUYJT.js → chunk-FPGR63AQ.js} +3 -3
- package/dist/{chunk-RI6FUYJT.js.map → chunk-FPGR63AQ.js.map} +1 -1
- package/dist/{chunk-4XB425HW.js → chunk-GBMMP344.js} +38 -23
- package/dist/chunk-GBMMP344.js.map +1 -0
- package/dist/{chunk-2FISCDW2.js → chunk-GFRJHCRX.js} +4 -4
- package/dist/{chunk-2FISCDW2.js.map → chunk-GFRJHCRX.js.map} +1 -1
- package/dist/{chunk-TF6HFXTW.js → chunk-H7LRGY7U.js} +3 -3
- package/dist/{chunk-TF6HFXTW.js.map → chunk-H7LRGY7U.js.map} +1 -1
- package/dist/{chunk-VS2GO7GL.js → chunk-HJGN3XVG.js} +8 -8
- package/dist/{chunk-VS2GO7GL.js.map → chunk-HJGN3XVG.js.map} +1 -1
- package/dist/{chunk-OPON37ZR.js → chunk-HRW4YFHR.js} +5 -5
- package/dist/{chunk-OPON37ZR.js.map → chunk-HRW4YFHR.js.map} +1 -1
- package/dist/{chunk-HOJ5E2PG.js → chunk-IHOUADLX.js} +3 -3
- package/dist/{chunk-HOJ5E2PG.js.map → chunk-IHOUADLX.js.map} +1 -1
- package/dist/{chunk-4XUBBJUJ.js → chunk-ITNUDQVP.js} +27 -20
- package/dist/chunk-ITNUDQVP.js.map +1 -0
- package/dist/{chunk-TVNO5MCL.js → chunk-KGSB2Y7O.js} +4 -4
- package/dist/{chunk-TVNO5MCL.js.map → chunk-KGSB2Y7O.js.map} +1 -1
- package/dist/{chunk-MNI3ZVUN.js → chunk-KKTVDCVO.js} +6 -6
- package/dist/{chunk-MNI3ZVUN.js.map → chunk-KKTVDCVO.js.map} +1 -1
- package/dist/{chunk-42GSY6HV.js → chunk-LSMKTPIE.js} +4 -4
- package/dist/{chunk-42GSY6HV.js.map → chunk-LSMKTPIE.js.map} +1 -1
- package/dist/{chunk-LFHYQ6AN.js → chunk-M5WTY3EH.js} +3 -3
- package/dist/{chunk-LFHYQ6AN.js.map → chunk-M5WTY3EH.js.map} +1 -1
- package/dist/{chunk-RYGEIQWO.js → chunk-MGG4XAJ5.js} +3 -3
- package/dist/{chunk-RYGEIQWO.js.map → chunk-MGG4XAJ5.js.map} +1 -1
- package/dist/{chunk-3MDXVF4Y.js → chunk-MIAVMNPM.js} +6 -6
- package/dist/{chunk-3MDXVF4Y.js.map → chunk-MIAVMNPM.js.map} +1 -1
- package/dist/{chunk-ROW2E5ZY.js → chunk-N44U2AA7.js} +4 -4
- package/dist/{chunk-ROW2E5ZY.js.map → chunk-N44U2AA7.js.map} +1 -1
- package/dist/{chunk-XYLGWKPG.js → chunk-NGWHUW34.js} +3 -3
- package/dist/{chunk-XYLGWKPG.js.map → chunk-NGWHUW34.js.map} +1 -1
- package/dist/{chunk-DYSSY56M.js → chunk-NLKLS3GZ.js} +5 -5
- package/dist/{chunk-DYSSY56M.js.map → chunk-NLKLS3GZ.js.map} +1 -1
- package/dist/{chunk-QN5XSUBT.js → chunk-NR5YIBTS.js} +4 -4
- package/dist/{chunk-QN5XSUBT.js.map → chunk-NR5YIBTS.js.map} +1 -1
- package/dist/{chunk-NSZOUCAR.js → chunk-OLL5OGQ5.js} +4 -4
- package/dist/{chunk-NSZOUCAR.js.map → chunk-OLL5OGQ5.js.map} +1 -1
- package/dist/{chunk-JKSDTWEC.js → chunk-PCB5DCS4.js} +4 -4
- package/dist/{chunk-JKSDTWEC.js.map → chunk-PCB5DCS4.js.map} +1 -1
- package/dist/chunk-Q77J3D2W.js +16 -0
- package/dist/chunk-Q77J3D2W.js.map +1 -0
- package/dist/{chunk-QXHO52TF.js → chunk-QIHSKEWU.js} +4 -4
- package/dist/{chunk-QXHO52TF.js.map → chunk-QIHSKEWU.js.map} +1 -1
- package/dist/{chunk-MWYKP7CI.js → chunk-QMWP2ZP6.js} +3 -3
- package/dist/{chunk-MWYKP7CI.js.map → chunk-QMWP2ZP6.js.map} +1 -1
- package/dist/{chunk-JRJYZHQE.js → chunk-R64ITZ7U.js} +4 -4
- package/dist/{chunk-JRJYZHQE.js.map → chunk-R64ITZ7U.js.map} +1 -1
- package/dist/{chunk-5UWRPWK2.js → chunk-R7VWIXFX.js} +3 -3
- package/dist/{chunk-5UWRPWK2.js.map → chunk-R7VWIXFX.js.map} +1 -1
- package/dist/{chunk-ATDOPTQ2.js → chunk-RJKMW36K.js} +8 -8
- package/dist/{chunk-ATDOPTQ2.js.map → chunk-RJKMW36K.js.map} +1 -1
- package/dist/{chunk-Q7E4TNN7.js → chunk-SLBO4SEE.js} +3 -3
- package/dist/{chunk-Q7E4TNN7.js.map → chunk-SLBO4SEE.js.map} +1 -1
- package/dist/{chunk-FXVII733.js → chunk-T2752RH7.js} +27 -3
- package/dist/chunk-T2752RH7.js.map +1 -0
- package/dist/{chunk-X7WJ2TAE.js → chunk-TF46NIZF.js} +4 -4
- package/dist/{chunk-X7WJ2TAE.js.map → chunk-TF46NIZF.js.map} +1 -1
- package/dist/{chunk-NGT46BX2.js → chunk-TWYTA2SX.js} +7 -7
- package/dist/{chunk-NGT46BX2.js.map → chunk-TWYTA2SX.js.map} +1 -1
- package/dist/{chunk-WDL6T5RX.js → chunk-U2UNWN4G.js} +5 -5
- package/dist/{chunk-WDL6T5RX.js.map → chunk-U2UNWN4G.js.map} +1 -1
- package/dist/{chunk-UME7NAC5.js → chunk-U5TWRPMK.js} +7 -7
- package/dist/{chunk-UME7NAC5.js.map → chunk-U5TWRPMK.js.map} +1 -1
- package/dist/{chunk-XK4UZHW7.js → chunk-VCMGBB5Y.js} +3 -3
- package/dist/{chunk-XK4UZHW7.js.map → chunk-VCMGBB5Y.js.map} +1 -1
- package/dist/{chunk-BKHGXHCJ.js → chunk-VZRZQV4Q.js} +3 -3
- package/dist/{chunk-BKHGXHCJ.js.map → chunk-VZRZQV4Q.js.map} +1 -1
- package/dist/{chunk-P3ZYGK5E.js → chunk-WIDH6AK6.js} +4 -4
- package/dist/{chunk-P3ZYGK5E.js.map → chunk-WIDH6AK6.js.map} +1 -1
- package/dist/{chunk-ZJLNYJCD.js → chunk-X4ITNSMT.js} +5 -5
- package/dist/{chunk-ZJLNYJCD.js.map → chunk-X4ITNSMT.js.map} +1 -1
- package/dist/{chunk-NHA4SBKG.js → chunk-XMRNYUQY.js} +3 -3
- package/dist/{chunk-NHA4SBKG.js.map → chunk-XMRNYUQY.js.map} +1 -1
- package/dist/{chunk-C76E3NHH.js → chunk-XV3HPKLI.js} +3 -3
- package/dist/{chunk-C76E3NHH.js.map → chunk-XV3HPKLI.js.map} +1 -1
- package/dist/{chunk-7BNWZKXI.js → chunk-YQOCPSOI.js} +4 -4
- package/dist/{chunk-7BNWZKXI.js.map → chunk-YQOCPSOI.js.map} +1 -1
- package/dist/{chunk-KAWAAVGL.js → chunk-YYVZFOUI.js} +3 -3
- package/dist/{chunk-KAWAAVGL.js.map → chunk-YYVZFOUI.js.map} +1 -1
- package/dist/components/cart/index.js +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/drawer/index.js +24 -23
- package/dist/components/home/index.js +29 -28
- package/dist/components/layout/index.js +6 -6
- package/dist/components/product/index.js +26 -25
- package/dist/components/store/index.js +25 -24
- package/dist/components/toast/index.js +4 -4
- package/dist/dev/editor/index.js +2 -2
- package/dist/dev/index.js +2 -2
- package/dist/document-class-VHDNGZQK.js +32 -0
- package/dist/{document-class-NJGMU7RC.js.map → document-class-VHDNGZQK.js.map} +1 -1
- package/dist/hooks/index.js +24 -23
- package/dist/hooks/useComments.js +3 -3
- package/dist/hooks/useGtm.js +24 -23
- package/dist/hooks/useMoney.js +24 -23
- package/dist/hooks/useProduct.js +3 -3
- package/dist/hooks/useStore.js +24 -23
- package/dist/hooks/useUser.js +5 -5
- package/dist/hooks/useWishlist.js +3 -3
- package/dist/index.js +24 -23
- package/dist/index.js.map +1 -1
- package/dist/native-app/index.js +3 -3
- package/dist/{navigation-ATNB3OMU.js → navigation-C5K5SOU2.js} +8 -8
- package/dist/{navigation-ATNB3OMU.js.map → navigation-C5K5SOU2.js.map} +1 -1
- package/dist/{navigation-XB2AA2QD.js → navigation-VW5P7XQM.js} +7 -7
- package/dist/{navigation-XB2AA2QD.js.map → navigation-VW5P7XQM.js.map} +1 -1
- package/dist/{not-found-6PQMIL5E.js → not-found-U2LJEYDT.js} +27 -26
- package/dist/not-found-U2LJEYDT.js.map +1 -0
- package/dist/providers/TwilightProvider.d.ts +1 -1
- package/dist/providers/TwilightProvider.d.ts.map +1 -1
- package/dist/providers/index.js +24 -23
- package/dist/routes/account/orders.js +8 -8
- package/dist/routes/account.js +17 -17
- package/dist/routes/blog.js +12 -12
- package/dist/routes/brands.js +8 -8
- package/dist/routes/cart.js +33 -32
- package/dist/routes/cart.js.map +1 -1
- package/dist/routes/home.js +30 -29
- package/dist/routes/index.js +6 -6
- package/dist/routes/loyalty.js +9 -9
- package/dist/routes/page.js +8 -8
- package/dist/routes/product-listing.js +31 -30
- package/dist/routes/product-listing.js.map +1 -1
- package/dist/routes/product.js +29 -28
- package/dist/routes/product.js.map +1 -1
- package/dist/routes/root/beforeLoad.d.ts.map +1 -1
- package/dist/routes/seo-redirects.js +6 -6
- package/dist/routes/testimonials.js +4 -4
- package/dist/routes/thank-you.js +8 -8
- package/dist/skeleton.js +30 -29
- package/dist/{store-lookup-MDUKB5VN.js → store-lookup-YL4EUIS2.js} +11 -11
- package/dist/{store-lookup-MDUKB5VN.js.map → store-lookup-YL4EUIS2.js.map} +1 -1
- package/dist/tanstack.js +19 -19
- package/dist/types/index.d.ts +5 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/salla-sdk.d.ts +9 -1
- package/dist/types/salla-sdk.d.ts.map +1 -1
- package/dist/types/twilight.d.ts +8 -0
- package/dist/types/twilight.d.ts.map +1 -1
- package/dist/utils/baseHead.js +2 -2
- package/dist/utils/index.js +6 -6
- package/dist/utils/store-base.d.ts +30 -0
- package/dist/utils/store-base.d.ts.map +1 -1
- package/dist/utils/store-identity.d.ts +8 -0
- package/dist/utils/store-identity.d.ts.map +1 -1
- package/dist/vite/index.js +3 -3
- package/dist/webmcp/WebMcpTools.d.ts +8 -0
- package/dist/webmcp/WebMcpTools.d.ts.map +1 -0
- package/dist/webmcp/cart-tools.d.ts +3 -0
- package/dist/webmcp/cart-tools.d.ts.map +1 -0
- package/dist/webmcp/catalog-tools.d.ts +3 -0
- package/dist/webmcp/catalog-tools.d.ts.map +1 -0
- package/dist/webmcp/input.d.ts +20 -0
- package/dist/webmcp/input.d.ts.map +1 -0
- package/dist/webmcp/model-context.d.ts +10 -0
- package/dist/webmcp/model-context.d.ts.map +1 -0
- package/dist/webmcp/page-navigation.d.ts +17 -0
- package/dist/webmcp/page-navigation.d.ts.map +1 -0
- package/dist/webmcp/page-tools.d.ts +3 -0
- package/dist/webmcp/page-tools.d.ts.map +1 -0
- package/dist/webmcp/registerWebMcpTools.d.ts +9 -0
- package/dist/webmcp/registerWebMcpTools.d.ts.map +1 -0
- package/dist/webmcp/results.d.ts +9 -0
- package/dist/webmcp/results.d.ts.map +1 -0
- package/dist/webmcp/salla-deps.d.ts +9 -0
- package/dist/webmcp/salla-deps.d.ts.map +1 -0
- package/dist/webmcp/schema.d.ts +14 -0
- package/dist/webmcp/schema.d.ts.map +1 -0
- package/dist/webmcp/tools.d.ts +8 -0
- package/dist/webmcp/tools.d.ts.map +1 -0
- package/dist/webmcp/types.d.ts +83 -0
- package/dist/webmcp/types.d.ts.map +1 -0
- package/dist/webmcp/useWebMcpSupported.d.ts +9 -0
- package/dist/webmcp/useWebMcpSupported.d.ts.map +1 -0
- package/dist/webmcp/useWebMcpTools.d.ts +10 -0
- package/dist/webmcp/useWebMcpTools.d.ts.map +1 -0
- package/package.json +1 -1
- package/tailwind/routes/root/beforeLoad.ts.txt +27 -9
- package/dist/BlogAuthorPage-LVUTPDWU.js.map +0 -1
- package/dist/BlogCategoryPage-4Q2MU5IF.js.map +0 -1
- package/dist/BlogPage-YG3INJ6S.js.map +0 -1
- package/dist/BlogSinglePage-P4OPKCYA.js.map +0 -1
- package/dist/BlogTagPage-RC4CSYJM.js.map +0 -1
- package/dist/BrandsPage-SRQANTCQ.js.map +0 -1
- package/dist/Breadcrumb-I6RHU7TL.js.map +0 -1
- package/dist/CartItem-WXV4HG7L.js.map +0 -1
- package/dist/CartSummary-66PEAPVR.js.map +0 -1
- package/dist/CustomerLayout-S4PJGKMT.js.map +0 -1
- package/dist/LatestProducts-VMDICC67.js.map +0 -1
- package/dist/LoyaltyPage-N7LLJ3ZW.js.map +0 -1
- package/dist/MobileMenu-TK5S3UAR.js.map +0 -1
- package/dist/NotificationsPage-FNC7EOFV.js.map +0 -1
- package/dist/OrderSinglePage-YS6FBSCD.js.map +0 -1
- package/dist/OrdersPage-V3YMXMSN.js.map +0 -1
- package/dist/ProfilePage-L7DOZZBH.js.map +0 -1
- package/dist/SeoCartWidget-IW2EIOP3.js.map +0 -1
- package/dist/SettingsPage-3BZD6EXX.js.map +0 -1
- package/dist/ThankYouPage-GPPMDT4G.js.map +0 -1
- package/dist/WalletPage-JYNPVXER.js.map +0 -1
- package/dist/WishlistPage-APID33BZ.js.map +0 -1
- package/dist/chunk-4XB425HW.js.map +0 -1
- package/dist/chunk-4XUBBJUJ.js.map +0 -1
- package/dist/chunk-FXVII733.js.map +0 -1
- package/dist/document-class-NJGMU7RC.js +0 -32
- package/dist/not-found-6PQMIL5E.js.map +0 -1
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { product } from './chunk-WIDH6AK6.js';
|
|
2
|
+
import { getModelContext } from './chunk-Q77J3D2W.js';
|
|
3
|
+
import { storePageUrl } from './chunk-MGG4XAJ5.js';
|
|
4
|
+
import { useNavigate, resolveRelativePath, defaultNavigate } from './chunk-HRW4YFHR.js';
|
|
5
|
+
import './chunk-OUW6WESU.js';
|
|
6
|
+
import './chunk-U2UNWN4G.js';
|
|
7
|
+
import './chunk-Z5M4YYWT.js';
|
|
8
|
+
import './chunk-6TFM3UTF.js';
|
|
9
|
+
import { whenSallaReady } from './chunk-XMRNYUQY.js';
|
|
10
|
+
import './chunk-T2752RH7.js';
|
|
11
|
+
import { hasTwilightSettings, getTwilightContext } from './chunk-6K34BCUP.js';
|
|
12
|
+
import './chunk-T72DAX7R.js';
|
|
13
|
+
import './chunk-DF6FBKDN.js';
|
|
14
|
+
import './chunk-DGUM43GV.js';
|
|
15
|
+
import { useRef, useEffect } from 'react';
|
|
16
|
+
|
|
17
|
+
// src/webmcp/page-navigation.ts
|
|
18
|
+
var isAbsolute = (to) => /^[a-z][a-z\d+.-]*:/i.test(to);
|
|
19
|
+
function currentSettings() {
|
|
20
|
+
return hasTwilightSettings() ? getTwilightContext().settings : void 0;
|
|
21
|
+
}
|
|
22
|
+
function withStoreAddress(navigate) {
|
|
23
|
+
const usesWindowLocation = navigate === defaultNavigate;
|
|
24
|
+
return (to) => {
|
|
25
|
+
const settings = currentSettings();
|
|
26
|
+
if (usesWindowLocation) {
|
|
27
|
+
return navigate(isAbsolute(to) ? to : storePageUrl(settings, to) ?? to);
|
|
28
|
+
}
|
|
29
|
+
if (!isAbsolute(to)) return navigate(to);
|
|
30
|
+
const store = settings?.store;
|
|
31
|
+
const path = store?.url ? resolveRelativePath(to, store.url, store.username) : null;
|
|
32
|
+
return path ? navigate(path) : defaultNavigate(to);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/webmcp/input.ts
|
|
37
|
+
var ok = (value) => ({ ok: true, value });
|
|
38
|
+
var fail = (error) => ({ ok: false, error });
|
|
39
|
+
function parsePositiveInt(raw, field) {
|
|
40
|
+
const value = typeof raw === "string" && raw.trim() !== "" ? Number(raw) : raw;
|
|
41
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
|
|
42
|
+
return fail(`"${field}" must be a positive whole number.`);
|
|
43
|
+
}
|
|
44
|
+
return ok(value);
|
|
45
|
+
}
|
|
46
|
+
function parseQuantity(raw) {
|
|
47
|
+
return raw === void 0 ? ok(1) : parsePositiveInt(raw, "quantity");
|
|
48
|
+
}
|
|
49
|
+
function parseId(raw, field) {
|
|
50
|
+
const value = typeof raw === "number" ? String(raw) : raw;
|
|
51
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
52
|
+
return fail(`"${field}" is required. Get it from get-cart.`);
|
|
53
|
+
}
|
|
54
|
+
return ok(value.trim());
|
|
55
|
+
}
|
|
56
|
+
function parseKeyword(raw) {
|
|
57
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
58
|
+
return fail('"keyword" is required: the words to search the catalog for.');
|
|
59
|
+
}
|
|
60
|
+
return ok(raw.trim());
|
|
61
|
+
}
|
|
62
|
+
var SEARCH_LIMIT_DEFAULT = 5;
|
|
63
|
+
var SEARCH_LIMIT_MAX = 10;
|
|
64
|
+
function parseLimit(raw) {
|
|
65
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) return SEARCH_LIMIT_DEFAULT;
|
|
66
|
+
return Math.min(SEARCH_LIMIT_MAX, Math.max(1, Math.trunc(raw)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/webmcp/results.ts
|
|
70
|
+
function jsonResult(payload) {
|
|
71
|
+
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
72
|
+
}
|
|
73
|
+
function errorResult(message) {
|
|
74
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
75
|
+
}
|
|
76
|
+
function errorMessage(error) {
|
|
77
|
+
return error instanceof Error && error.message ? error.message : "Unknown error";
|
|
78
|
+
}
|
|
79
|
+
async function guarded(label, action) {
|
|
80
|
+
try {
|
|
81
|
+
return await action();
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return errorResult(`${label} failed: ${errorMessage(error)}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/webmcp/schema.ts
|
|
88
|
+
var PRODUCT_ID_SCHEMA = {
|
|
89
|
+
type: "number",
|
|
90
|
+
description: "Product id, from search-products."
|
|
91
|
+
};
|
|
92
|
+
var ITEM_ID_SCHEMA = {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: 'Cart line id (the "id" of an item in get-cart), not the product id.'
|
|
95
|
+
};
|
|
96
|
+
var QUANTITY_SCHEMA = {
|
|
97
|
+
type: "number",
|
|
98
|
+
description: "Whole number of units. Defaults to 1."
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/webmcp/cart-tools.ts
|
|
102
|
+
function getCartTool(deps) {
|
|
103
|
+
return {
|
|
104
|
+
name: "get-cart",
|
|
105
|
+
description: "Read the shopper's current cart: items (with the line ids needed to change them), count and total. The cart is null when it is empty.",
|
|
106
|
+
inputSchema: { type: "object", properties: {} },
|
|
107
|
+
execute: () => guarded("Reading the cart", async () => jsonResult({ cart: await deps.getCart() }))
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function addToCartTool(deps) {
|
|
111
|
+
return {
|
|
112
|
+
name: "add-to-cart",
|
|
113
|
+
description: "Add a product to the shopper's cart and return the updated cart. Only works for products with no required options; for those, use open-page to send the shopper to the product page. Does not check out.",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: { productId: PRODUCT_ID_SCHEMA, quantity: QUANTITY_SCHEMA },
|
|
117
|
+
required: ["productId"]
|
|
118
|
+
},
|
|
119
|
+
execute: (input) => guarded("Adding to the cart", async () => {
|
|
120
|
+
const id = parsePositiveInt(input.productId, "productId");
|
|
121
|
+
if (!id.ok) return errorResult(id.error);
|
|
122
|
+
const quantity = parseQuantity(input.quantity);
|
|
123
|
+
if (!quantity.ok) return errorResult(quantity.error);
|
|
124
|
+
const product2 = await deps.getProduct(id.value);
|
|
125
|
+
if (!product2.inStock) {
|
|
126
|
+
return errorResult(`"${product2.name}" is out of stock or unavailable.`);
|
|
127
|
+
}
|
|
128
|
+
if (product2.needsProductPage === true) {
|
|
129
|
+
return errorResult(
|
|
130
|
+
`"${product2.name}" needs choices made first (options, a variant, an amount\u2026). Use open-page with page "product" and productId ${product2.id} (${product2.url}) so the shopper can pick them.`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return jsonResult({ cart: await deps.addToCart(id.value, quantity.value) });
|
|
134
|
+
})
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function updateCartItemTool(deps) {
|
|
138
|
+
return {
|
|
139
|
+
name: "update-cart-item",
|
|
140
|
+
description: "Change the quantity of a line already in the cart (use get-cart for the line id). Returns the updated cart.",
|
|
141
|
+
inputSchema: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
itemId: ITEM_ID_SCHEMA,
|
|
145
|
+
quantity: { ...QUANTITY_SCHEMA, description: "New quantity." }
|
|
146
|
+
},
|
|
147
|
+
required: ["itemId", "quantity"]
|
|
148
|
+
},
|
|
149
|
+
execute: (input) => guarded("Updating the cart", async () => {
|
|
150
|
+
const itemId = parseId(input.itemId, "itemId");
|
|
151
|
+
if (!itemId.ok) return errorResult(itemId.error);
|
|
152
|
+
const quantity = parsePositiveInt(input.quantity, "quantity");
|
|
153
|
+
if (!quantity.ok) return errorResult(quantity.error);
|
|
154
|
+
return jsonResult({ cart: await deps.updateCartItem(itemId.value, quantity.value) });
|
|
155
|
+
})
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function removeCartItemTool(deps) {
|
|
159
|
+
return {
|
|
160
|
+
name: "remove-cart-item",
|
|
161
|
+
description: "Remove a line from the cart (use get-cart for the line id). Returns the updated cart.",
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: "object",
|
|
164
|
+
properties: { itemId: ITEM_ID_SCHEMA },
|
|
165
|
+
required: ["itemId"]
|
|
166
|
+
},
|
|
167
|
+
execute: (input) => guarded("Removing from the cart", async () => {
|
|
168
|
+
const itemId = parseId(input.itemId, "itemId");
|
|
169
|
+
if (!itemId.ok) return errorResult(itemId.error);
|
|
170
|
+
return jsonResult({ cart: await deps.removeCartItem(itemId.value) });
|
|
171
|
+
})
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function createCartTools(deps) {
|
|
175
|
+
return [
|
|
176
|
+
getCartTool(deps),
|
|
177
|
+
addToCartTool(deps),
|
|
178
|
+
updateCartItemTool(deps),
|
|
179
|
+
removeCartItemTool(deps)
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/webmcp/catalog-tools.ts
|
|
184
|
+
function searchProductsTool(deps) {
|
|
185
|
+
return {
|
|
186
|
+
name: "search-products",
|
|
187
|
+
description: "Search this store's catalog by keyword. Returns up to a few matching products with id, name, price, stock and page URL. Use it to find a product before reading details or adding it to the cart.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
type: "object",
|
|
190
|
+
properties: {
|
|
191
|
+
keyword: { type: "string", description: 'Words to search for, e.g. "oud perfume".' },
|
|
192
|
+
limit: {
|
|
193
|
+
type: "number",
|
|
194
|
+
description: `How many products to return (1-${SEARCH_LIMIT_MAX}). Defaults to 5.`
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
required: ["keyword"]
|
|
198
|
+
},
|
|
199
|
+
execute: (input) => guarded("Product search", async () => {
|
|
200
|
+
const keyword = parseKeyword(input.keyword);
|
|
201
|
+
if (!keyword.ok) return errorResult(keyword.error);
|
|
202
|
+
const products = await deps.searchProducts(keyword.value, parseLimit(input.limit));
|
|
203
|
+
return jsonResult({ products });
|
|
204
|
+
})
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function getProductTool(deps) {
|
|
208
|
+
return {
|
|
209
|
+
name: "get-product",
|
|
210
|
+
description: "Get one product by id: price, sale state, stock, and whether the shopper must pick options (size, color\u2026) on the product page first.",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: { productId: PRODUCT_ID_SCHEMA },
|
|
214
|
+
required: ["productId"]
|
|
215
|
+
},
|
|
216
|
+
execute: (input) => guarded("Loading the product", async () => {
|
|
217
|
+
const id = parsePositiveInt(input.productId, "productId");
|
|
218
|
+
if (!id.ok) return errorResult(id.error);
|
|
219
|
+
return jsonResult({ product: await deps.getProduct(id.value) });
|
|
220
|
+
})
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function createCatalogTools(deps) {
|
|
224
|
+
return [searchProductsTool(deps), getProductTool(deps)];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/webmcp/page-tools.ts
|
|
228
|
+
function openPageTool(deps) {
|
|
229
|
+
return {
|
|
230
|
+
name: "open-page",
|
|
231
|
+
description: `Navigate the shopper's visible page to the cart, the home page, or a product page. Use "cart" to let the shopper review and check out themselves; checkout is never done by a tool.`,
|
|
232
|
+
inputSchema: {
|
|
233
|
+
type: "object",
|
|
234
|
+
properties: {
|
|
235
|
+
page: { type: "string", enum: ["cart", "home", "product"] },
|
|
236
|
+
productId: { ...PRODUCT_ID_SCHEMA, description: 'Required when page is "product".' }
|
|
237
|
+
},
|
|
238
|
+
required: ["page"]
|
|
239
|
+
},
|
|
240
|
+
execute: (input) => guarded("Opening the page", async () => {
|
|
241
|
+
if (input.page === "cart") {
|
|
242
|
+
deps.openPage("/cart");
|
|
243
|
+
return jsonResult({ opened: "cart" });
|
|
244
|
+
}
|
|
245
|
+
if (input.page === "home") {
|
|
246
|
+
deps.openPage("/");
|
|
247
|
+
return jsonResult({ opened: "home" });
|
|
248
|
+
}
|
|
249
|
+
if (input.page === "product") {
|
|
250
|
+
const id = parsePositiveInt(input.productId, "productId");
|
|
251
|
+
if (!id.ok) return errorResult(id.error);
|
|
252
|
+
const product2 = await deps.getProduct(id.value);
|
|
253
|
+
deps.openPage(product2.url);
|
|
254
|
+
return jsonResult({ opened: product2.url });
|
|
255
|
+
}
|
|
256
|
+
return errorResult('"page" must be one of: cart, home, product.');
|
|
257
|
+
})
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function createPageTools(deps) {
|
|
261
|
+
return [openPageTool(deps)];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/webmcp/tools.ts
|
|
265
|
+
function createWebMcpTools(deps) {
|
|
266
|
+
return [...createCatalogTools(deps), ...createCartTools(deps), ...createPageTools(deps)];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/webmcp/registerWebMcpTools.ts
|
|
270
|
+
var NOT_ALLOWED = "NotAllowedError";
|
|
271
|
+
function reportRegistrationFailure(toolName, error) {
|
|
272
|
+
if (error instanceof DOMException && error.name === NOT_ALLOWED) return;
|
|
273
|
+
console.warn("[twilight] WebMCP could not register tool:", toolName, error);
|
|
274
|
+
}
|
|
275
|
+
function registerWebMcpTools(deps) {
|
|
276
|
+
const modelContext = getModelContext();
|
|
277
|
+
if (!modelContext) return () => {
|
|
278
|
+
};
|
|
279
|
+
const controller = new AbortController();
|
|
280
|
+
for (const tool of createWebMcpTools(deps)) {
|
|
281
|
+
try {
|
|
282
|
+
Promise.resolve(modelContext.registerTool(tool, { signal: controller.signal })).catch(
|
|
283
|
+
(error) => reportRegistrationFailure(tool.name, error)
|
|
284
|
+
);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
reportRegistrationFailure(tool.name, error);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return () => controller.abort();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/webmcp/salla-deps.ts
|
|
293
|
+
var SDK_WAIT_MS = 8e3;
|
|
294
|
+
var SIMPLE_TYPES = /* @__PURE__ */ new Set(["product", "digital"]);
|
|
295
|
+
function sdkReady() {
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
const timer = setTimeout(() => {
|
|
298
|
+
cancel();
|
|
299
|
+
reject(new Error("The store is not ready yet. Try again in a moment."));
|
|
300
|
+
}, SDK_WAIT_MS);
|
|
301
|
+
const cancel = whenSallaReady((sdk) => {
|
|
302
|
+
clearTimeout(timer);
|
|
303
|
+
resolve(sdk);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function toAmount(value) {
|
|
308
|
+
if (typeof value === "number") return value;
|
|
309
|
+
if (value && typeof value === "object" && "amount" in value) {
|
|
310
|
+
return toAmount(value.amount);
|
|
311
|
+
}
|
|
312
|
+
if (typeof value === "string") {
|
|
313
|
+
const parsed = Number.parseFloat(value.replace(/,/g, "").replace(/[^\d.-]/g, ""));
|
|
314
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
315
|
+
}
|
|
316
|
+
return 0;
|
|
317
|
+
}
|
|
318
|
+
function needsProductPage(p, detailed) {
|
|
319
|
+
if (!SIMPLE_TYPES.has(p.type)) return true;
|
|
320
|
+
if ((p.options ?? []).some((option) => option.required)) return true;
|
|
321
|
+
if ((p.skus ?? []).length > 0) return true;
|
|
322
|
+
if (detailed) return false;
|
|
323
|
+
return p.has_options === true ? true : void 0;
|
|
324
|
+
}
|
|
325
|
+
function toProductSummary(p, detailed) {
|
|
326
|
+
const onSale = p.is_on_sale === true;
|
|
327
|
+
const needs = needsProductPage(p, detailed);
|
|
328
|
+
return {
|
|
329
|
+
id: Number(p.id),
|
|
330
|
+
name: p.name,
|
|
331
|
+
url: p.url,
|
|
332
|
+
price: toAmount(onSale && p.sale_price ? p.sale_price : p.price),
|
|
333
|
+
...onSale ? { regularPrice: toAmount(p.regular_price) } : {},
|
|
334
|
+
currency: p.currency,
|
|
335
|
+
onSale,
|
|
336
|
+
inStock: p.status !== "out" && p.status !== "out-and-notify" && p.is_available !== false,
|
|
337
|
+
...needs === void 0 ? {} : { needsProductPage: needs }
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function toCartSummary(cart, currency) {
|
|
341
|
+
return {
|
|
342
|
+
id: cart.id,
|
|
343
|
+
count: cart.count,
|
|
344
|
+
total: toAmount(cart.total),
|
|
345
|
+
currency,
|
|
346
|
+
coupon: cart.coupon ?? null,
|
|
347
|
+
items: (cart.items ?? []).map((item) => ({
|
|
348
|
+
id: String(item.id),
|
|
349
|
+
productId: item.product_id,
|
|
350
|
+
name: item.product_name,
|
|
351
|
+
quantity: item.quantity,
|
|
352
|
+
total: toAmount(item.total)
|
|
353
|
+
}))
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
async function readCart(sdk) {
|
|
357
|
+
const cartId = await sdk.cart.api.getCurrentCartId();
|
|
358
|
+
if (!cartId) return null;
|
|
359
|
+
const response = await sdk.api.cart.details(cartId, ["items"]);
|
|
360
|
+
const cart = response?.data?.cart;
|
|
361
|
+
return cart ? toCartSummary(cart, sdk.config.currency()?.code ?? "") : null;
|
|
362
|
+
}
|
|
363
|
+
function createSallaWebMcpDeps(navigate) {
|
|
364
|
+
const mutateThenRead = async (change) => {
|
|
365
|
+
const sdk = await sdkReady();
|
|
366
|
+
await change(sdk);
|
|
367
|
+
return readCart(sdk);
|
|
368
|
+
};
|
|
369
|
+
return {
|
|
370
|
+
searchProducts: async (keyword, limit) => {
|
|
371
|
+
const { items } = await product.list({ source: "search", keyword, perPage: limit });
|
|
372
|
+
return items.map((item) => toProductSummary(item, false));
|
|
373
|
+
},
|
|
374
|
+
getProduct: async (productId) => toProductSummary(await product.find(String(productId)), true),
|
|
375
|
+
getCart: async () => readCart(await sdkReady()),
|
|
376
|
+
addToCart: (productId, quantity) => mutateThenRead((sdk) => sdk.cart.addItem({ id: productId, quantity })),
|
|
377
|
+
updateCartItem: (itemId, quantity) => mutateThenRead((sdk) => sdk.cart.updateItem({ id: itemId, quantity })),
|
|
378
|
+
removeCartItem: (itemId) => mutateThenRead((sdk) => sdk.cart.deleteItem(itemId)),
|
|
379
|
+
openPage: navigate
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/webmcp/useWebMcpTools.ts
|
|
384
|
+
function useWebMcpTools() {
|
|
385
|
+
const navigate = useNavigate();
|
|
386
|
+
const navigateRef = useRef(navigate);
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
navigateRef.current = navigate;
|
|
389
|
+
}, [navigate]);
|
|
390
|
+
useEffect(
|
|
391
|
+
() => registerWebMcpTools(createSallaWebMcpDeps((to) => withStoreAddress(navigateRef.current)(to))),
|
|
392
|
+
[]
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// src/webmcp/WebMcpTools.tsx
|
|
397
|
+
function WebMcpTools() {
|
|
398
|
+
useWebMcpTools();
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export { WebMcpTools as default };
|
|
403
|
+
//# sourceMappingURL=WebMcpTools-3TBLKZL5.js.map
|
|
404
|
+
//# sourceMappingURL=WebMcpTools-3TBLKZL5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/webmcp/page-navigation.ts","../src/webmcp/input.ts","../src/webmcp/results.ts","../src/webmcp/schema.ts","../src/webmcp/cart-tools.ts","../src/webmcp/catalog-tools.ts","../src/webmcp/page-tools.ts","../src/webmcp/tools.ts","../src/webmcp/registerWebMcpTools.ts","../src/webmcp/salla-deps.ts","../src/webmcp/useWebMcpTools.ts","../src/webmcp/WebMcpTools.tsx"],"names":["product"],"mappings":";;;;;;;;;;;;;;;;;AAMA,IAAM,UAAA,GAAa,CAAC,EAAA,KAAwB,qBAAA,CAAsB,KAAK,EAAE,CAAA;AAEzE,SAAS,eAAA,GAAkB;AACzB,EAAA,OAAO,mBAAA,EAAoB,GAAI,kBAAA,EAAmB,CAAE,QAAA,GAAW,MAAA;AACjE;AAeO,SAAS,iBAAiB,QAAA,EAA8B;AAC7D,EAAA,MAAM,qBAAqB,QAAA,KAAa,eAAA;AAExC,EAAA,OAAO,CAAC,EAAA,KAAO;AACb,IAAA,MAAM,WAAW,eAAA,EAAgB;AAEjC,IAAA,IAAI,kBAAA,EAAoB;AACtB,MAAA,OAAO,QAAA,CAAS,WAAW,EAAE,CAAA,GAAI,KAAM,YAAA,CAAa,QAAA,EAAU,EAAE,CAAA,IAAK,EAAG,CAAA;AAAA,IAC1E;AACA,IAAA,IAAI,CAAC,UAAA,CAAW,EAAE,CAAA,EAAG,OAAO,SAAS,EAAE,CAAA;AAEvC,IAAA,MAAM,QAAQ,QAAA,EAAU,KAAA;AACxB,IAAA,MAAM,IAAA,GAAO,OAAO,GAAA,GAAM,mBAAA,CAAoB,IAAI,KAAA,CAAM,GAAA,EAAK,KAAA,CAAM,QAAQ,CAAA,GAAI,IAAA;AAC/E,IAAA,OAAO,IAAA,GAAO,QAAA,CAAS,IAAI,CAAA,GAAI,gBAAgB,EAAE,CAAA;AAAA,EACnD,CAAA;AACF;;;ACjCA,IAAM,KAAK,CAAI,KAAA,MAAyB,EAAE,EAAA,EAAI,MAAM,KAAA,EAAM,CAAA;AAC1D,IAAM,OAAO,CAAC,KAAA,MAAkC,EAAE,EAAA,EAAI,OAAO,KAAA,EAAM,CAAA;AAG5D,SAAS,gBAAA,CAAiB,KAAc,KAAA,EAA+B;AAC5E,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,MAAK,KAAM,EAAA,GAAK,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA;AAC3E,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,CAAC,OAAO,SAAA,CAAU,KAAK,CAAA,IAAK,KAAA,GAAQ,CAAA,EAAG;AACtE,IAAA,OAAO,IAAA,CAAK,CAAA,CAAA,EAAI,KAAK,CAAA,kCAAA,CAAoC,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,GAAG,KAAK,CAAA;AACjB;AAEO,SAAS,cAAc,GAAA,EAA8B;AAC1D,EAAA,OAAO,QAAQ,MAAA,GAAY,EAAA,CAAG,CAAC,CAAA,GAAI,gBAAA,CAAiB,KAAK,UAAU,CAAA;AACrE;AAEO,SAAS,OAAA,CAAQ,KAAc,KAAA,EAA+B;AACnE,EAAA,MAAM,QAAQ,OAAO,GAAA,KAAQ,QAAA,GAAW,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA;AACtD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,IAAA,OAAW,EAAA,EAAI;AACpD,IAAA,OAAO,IAAA,CAAK,CAAA,CAAA,EAAI,KAAK,CAAA,oCAAA,CAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,EAAA,CAAG,KAAA,CAAM,IAAA,EAAM,CAAA;AACxB;AAEO,SAAS,aAAa,GAAA,EAA8B;AACzD,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,IAAA,OAAW,EAAA,EAAI;AAChD,IAAA,OAAO,KAAK,6DAA6D,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,EAAA,CAAG,GAAA,CAAI,IAAA,EAAM,CAAA;AACtB;AAEO,IAAM,oBAAA,GAAuB,CAAA;AAC7B,IAAM,gBAAA,GAAmB,EAAA;AAEzB,SAAS,WAAW,GAAA,EAAsB;AAC/C,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,CAAC,OAAO,QAAA,CAAS,GAAG,GAAG,OAAO,oBAAA;AAC7D,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,KAAA,CAAM,GAAG,CAAC,CAAC,CAAA;AAChE;;;ACzCO,SAAS,WAAW,OAAA,EAAoC;AAC7D,EAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG,CAAA,EAAE;AACtE;AAGO,SAAS,YAAY,OAAA,EAAmC;AAC7D,EAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,IAAA,EAAK;AACrE;AAEO,SAAS,aAAa,KAAA,EAAwB;AACnD,EAAA,OAAO,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,GAAU,MAAM,OAAA,GAAU,eAAA;AACnE;AAGA,eAAsB,OAAA,CACpB,OACA,MAAA,EAC2B;AAC3B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,MAAA,EAAO;AAAA,EACtB,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,YAAY,CAAA,EAAG,KAAK,YAAY,YAAA,CAAa,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EAC9D;AACF;;;ACxBO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,IAAA,EAAM,QAAA;AAAA,EACN,WAAA,EAAa;AACf,CAAA;AAEO,IAAM,cAAA,GAAiB;AAAA,EAC5B,IAAA,EAAM,QAAA;AAAA,EACN,WAAA,EAAa;AACf,CAAA;AAEO,IAAM,eAAA,GAAkB;AAAA,EAC7B,IAAA,EAAM,QAAA;AAAA,EACN,WAAA,EAAa;AACf,CAAA;;;ACVA,SAAS,YAAY,IAAA,EAA8B;AACjD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EACE,uIAAA;AAAA,IACF,aAAa,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,EAAC,EAAE;AAAA,IAC9C,OAAA,EAAS,MACP,OAAA,CAAQ,kBAAA,EAAoB,YAAY,UAAA,CAAW,EAAE,IAAA,EAAM,MAAM,IAAA,CAAK,OAAA,EAAQ,EAAG,CAAC;AAAA,GACtF;AACF;AAEA,SAAS,cAAc,IAAA,EAA8B;AACnD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,0MAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY,EAAE,SAAA,EAAW,iBAAA,EAAmB,UAAU,eAAA,EAAgB;AAAA,MACtE,QAAA,EAAU,CAAC,WAAW;AAAA,KACxB;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,sBAAsB,YAAY;AACxC,MAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,KAAA,CAAM,SAAA,EAAW,WAAW,CAAA;AACxD,MAAA,IAAI,CAAC,EAAA,CAAG,EAAA,EAAI,OAAO,WAAA,CAAY,GAAG,KAAK,CAAA;AACvC,MAAA,MAAM,QAAA,GAAW,aAAA,CAAc,KAAA,CAAM,QAAQ,CAAA;AAC7C,MAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,WAAA,CAAY,SAAS,KAAK,CAAA;AAEnD,MAAA,MAAMA,QAAAA,GAAU,MAAM,IAAA,CAAK,UAAA,CAAW,GAAG,KAAK,CAAA;AAC9C,MAAA,IAAI,CAACA,SAAQ,OAAA,EAAS;AACpB,QAAA,OAAO,WAAA,CAAY,CAAA,CAAA,EAAIA,QAAAA,CAAQ,IAAI,CAAA,iCAAA,CAAmC,CAAA;AAAA,MACxE;AACA,MAAA,IAAIA,QAAAA,CAAQ,qBAAqB,IAAA,EAAM;AACrC,QAAA,OAAO,WAAA;AAAA,UACL,CAAA,CAAA,EAAIA,SAAQ,IAAI,CAAA,kHAAA,EAAgHA,SAAQ,EAAE,CAAA,EAAA,EAAKA,SAAQ,GAAG,CAAA,+BAAA;AAAA,SAC5J;AAAA,MACF;AACA,MAAA,OAAO,UAAA,CAAW,EAAE,IAAA,EAAM,MAAM,IAAA,CAAK,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,QAAA,CAAS,KAAK,CAAA,EAAG,CAAA;AAAA,IAC5E,CAAC;AAAA,GACL;AACF;AAEA,SAAS,mBAAmB,IAAA,EAA8B;AACxD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EACE,6GAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,MAAA,EAAQ,cAAA;AAAA,QACR,QAAA,EAAU,EAAE,GAAG,eAAA,EAAiB,aAAa,eAAA;AAAgB,OAC/D;AAAA,MACA,QAAA,EAAU,CAAC,QAAA,EAAU,UAAU;AAAA,KACjC;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,qBAAqB,YAAY;AACvC,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,QAAQ,CAAA;AAC7C,MAAA,IAAI,CAAC,MAAA,CAAO,EAAA,EAAI,OAAO,WAAA,CAAY,OAAO,KAAK,CAAA;AAC/C,MAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,KAAA,CAAM,QAAA,EAAU,UAAU,CAAA;AAC5D,MAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,WAAA,CAAY,SAAS,KAAK,CAAA;AACnD,MAAA,OAAO,UAAA,CAAW,EAAE,IAAA,EAAM,MAAM,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,KAAA,EAAO,QAAA,CAAS,KAAK,CAAA,EAAG,CAAA;AAAA,IACrF,CAAC;AAAA,GACL;AACF;AAEA,SAAS,mBAAmB,IAAA,EAA8B;AACxD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EACE,uFAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY,EAAE,MAAA,EAAQ,cAAA,EAAe;AAAA,MACrC,QAAA,EAAU,CAAC,QAAQ;AAAA,KACrB;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,0BAA0B,YAAY;AAC5C,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,QAAQ,CAAA;AAC7C,MAAA,IAAI,CAAC,MAAA,CAAO,EAAA,EAAI,OAAO,WAAA,CAAY,OAAO,KAAK,CAAA;AAC/C,MAAA,OAAO,UAAA,CAAW,EAAE,IAAA,EAAM,MAAM,KAAK,cAAA,CAAe,MAAA,CAAO,KAAK,CAAA,EAAG,CAAA;AAAA,IACrE,CAAC;AAAA,GACL;AACF;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO;AAAA,IACL,YAAY,IAAI,CAAA;AAAA,IAChB,cAAc,IAAI,CAAA;AAAA,IAClB,mBAAmB,IAAI,CAAA;AAAA,IACvB,mBAAmB,IAAI;AAAA,GACzB;AACF;;;AC5FA,SAAS,mBAAmB,IAAA,EAA8B;AACxD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,iBAAA;AAAA,IACN,WAAA,EACE,mMAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0CAAA,EAA2C;AAAA,QACnF,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa,kCAAkC,gBAAgB,CAAA,iBAAA;AAAA;AACjE,OACF;AAAA,MACA,QAAA,EAAU,CAAC,SAAS;AAAA,KACtB;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,kBAAkB,YAAY;AACpC,MAAA,MAAM,OAAA,GAAU,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AAC1C,MAAA,IAAI,CAAC,OAAA,CAAQ,EAAA,EAAI,OAAO,WAAA,CAAY,QAAQ,KAAK,CAAA;AACjD,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,cAAA,CAAe,QAAQ,KAAA,EAAO,UAAA,CAAW,KAAA,CAAM,KAAK,CAAC,CAAA;AACjF,MAAA,OAAO,UAAA,CAAW,EAAE,QAAA,EAAU,CAAA;AAAA,IAChC,CAAC;AAAA,GACL;AACF;AAEA,SAAS,eAAe,IAAA,EAA8B;AACpD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,2IAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY,EAAE,SAAA,EAAW,iBAAA,EAAkB;AAAA,MAC3C,QAAA,EAAU,CAAC,WAAW;AAAA,KACxB;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,uBAAuB,YAAY;AACzC,MAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,KAAA,CAAM,SAAA,EAAW,WAAW,CAAA;AACxD,MAAA,IAAI,CAAC,EAAA,CAAG,EAAA,EAAI,OAAO,WAAA,CAAY,GAAG,KAAK,CAAA;AACvC,MAAA,OAAO,UAAA,CAAW,EAAE,OAAA,EAAS,MAAM,KAAK,UAAA,CAAW,EAAA,CAAG,KAAK,CAAA,EAAG,CAAA;AAAA,IAChE,CAAC;AAAA,GACL;AACF;AAEO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,OAAO,CAAC,kBAAA,CAAmB,IAAI,CAAA,EAAG,cAAA,CAAe,IAAI,CAAC,CAAA;AACxD;;;AC/CA,SAAS,aAAa,IAAA,EAA8B;AAClD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACE,CAAA,mLAAA,CAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,SAAS,CAAA,EAAE;AAAA,QAC1D,SAAA,EAAW,EAAE,GAAG,iBAAA,EAAmB,aAAa,kCAAA;AAAmC,OACrF;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA,KACnB;AAAA,IACA,OAAA,EAAS,CAAC,KAAA,KACR,OAAA,CAAQ,oBAAoB,YAAY;AACtC,MAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,QAAA,IAAA,CAAK,SAAS,OAAO,CAAA;AACrB,QAAA,OAAO,UAAA,CAAW,EAAE,MAAA,EAAQ,MAAA,EAAQ,CAAA;AAAA,MACtC;AACA,MAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,QAAA,IAAA,CAAK,SAAS,GAAG,CAAA;AACjB,QAAA,OAAO,UAAA,CAAW,EAAE,MAAA,EAAQ,MAAA,EAAQ,CAAA;AAAA,MACtC;AACA,MAAA,IAAI,KAAA,CAAM,SAAS,SAAA,EAAW;AAC5B,QAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,KAAA,CAAM,SAAA,EAAW,WAAW,CAAA;AACxD,QAAA,IAAI,CAAC,EAAA,CAAG,EAAA,EAAI,OAAO,WAAA,CAAY,GAAG,KAAK,CAAA;AACvC,QAAA,MAAMA,QAAAA,GAAU,MAAM,IAAA,CAAK,UAAA,CAAW,GAAG,KAAK,CAAA;AAC9C,QAAA,IAAA,CAAK,QAAA,CAASA,SAAQ,GAAG,CAAA;AACzB,QAAA,OAAO,UAAA,CAAW,EAAE,MAAA,EAAQA,QAAAA,CAAQ,KAAK,CAAA;AAAA,MAC3C;AACA,MAAA,OAAO,YAAY,6CAA6C,CAAA;AAAA,IAClE,CAAC;AAAA,GACL;AACF;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO,CAAC,YAAA,CAAa,IAAI,CAAC,CAAA;AAC5B;;;AChCO,SAAS,kBAAkB,IAAA,EAAgC;AAChE,EAAA,OAAO,CAAC,GAAG,kBAAA,CAAmB,IAAI,CAAA,EAAG,GAAG,eAAA,CAAgB,IAAI,CAAA,EAAG,GAAG,eAAA,CAAgB,IAAI,CAAC,CAAA;AACzF;;;ACRA,IAAM,WAAA,GAAc,iBAAA;AAEpB,SAAS,yBAAA,CAA0B,UAAkB,KAAA,EAAsB;AAGzE,EAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,WAAA,EAAa;AACjE,EAAA,OAAA,CAAQ,IAAA,CAAK,4CAAA,EAA8C,QAAA,EAAU,KAAK,CAAA;AAC5E;AAQO,SAAS,oBAAoB,IAAA,EAA8B;AAChE,EAAA,MAAM,eAAe,eAAA,EAAgB;AACrC,EAAA,IAAI,CAAC,YAAA,EAAc,OAAO,MAAM;AAAA,EAAC,CAAA;AAEjC,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,KAAA,MAAW,IAAA,IAAQ,iBAAA,CAAkB,IAAI,CAAA,EAAG;AAC1C,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,OAAA,CAAQ,YAAA,CAAa,YAAA,CAAa,IAAA,EAAM,EAAE,QAAQ,UAAA,CAAW,MAAA,EAAQ,CAAC,CAAA,CAAE,KAAA;AAAA,QAC9E,CAAC,KAAA,KAAmB,yBAAA,CAA0B,IAAA,CAAK,MAAM,KAAK;AAAA,OAChE;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,yBAAA,CAA0B,IAAA,CAAK,MAAM,KAAK,CAAA;AAAA,IAC5C;AAAA,EACF;AACA,EAAA,OAAO,MAAM,WAAW,KAAA,EAAM;AAChC;;;AC3BA,IAAM,WAAA,GAAc,GAAA;AAGpB,IAAM,+BAAoC,IAAI,GAAA,CAAI,CAAC,SAAA,EAAW,SAAS,CAAC,CAAA;AAExE,SAAS,QAAA,GAA8B;AACrC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,MAAA,EAAO;AACP,MAAA,MAAA,CAAO,IAAI,KAAA,CAAM,oDAAoD,CAAC,CAAA;AAAA,IACxE,GAAG,WAAW,CAAA;AACd,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAC,GAAA,KAAQ;AACrC,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,OAAA,CAAQ,GAAG,CAAA;AAAA,IACb,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAGA,SAAS,SAAS,KAAA,EAAwB;AACxC,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,YAAY,KAAA,EAAO;AAC3D,IAAA,OAAO,QAAA,CAAU,MAAgB,MAAM,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,CAAE,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAC,CAAA;AAChF,IAAA,OAAO,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,GAAI,MAAA,GAAS,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,CAAA;AACT;AAOA,SAAS,gBAAA,CAAiB,GAAY,QAAA,EAAwC;AAC5E,EAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,OAAO,IAAA;AACtC,EAAA,IAAA,CAAK,CAAA,CAAE,OAAA,IAAW,EAAC,EAAG,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,QAAQ,CAAA,EAAG,OAAO,IAAA;AAChE,EAAA,IAAA,CAAK,EAAE,IAAA,IAAQ,EAAC,EAAG,MAAA,GAAS,GAAG,OAAO,IAAA;AACtC,EAAA,IAAI,UAAU,OAAO,KAAA;AACrB,EAAA,OAAO,CAAA,CAAE,WAAA,KAAgB,IAAA,GAAO,IAAA,GAAO,MAAA;AACzC;AAEA,SAAS,gBAAA,CAAiB,GAAY,QAAA,EAAyC;AAC7E,EAAA,MAAM,MAAA,GAAS,EAAE,UAAA,KAAe,IAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,CAAA,EAAG,QAAQ,CAAA;AAE1C,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,EAAE,CAAA;AAAA,IACf,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,KAAK,CAAA,CAAE,GAAA;AAAA,IACP,KAAA,EAAO,SAAS,MAAA,IAAU,CAAA,CAAE,aAAa,CAAA,CAAE,UAAA,GAAa,EAAE,KAAK,CAAA;AAAA,IAC/D,GAAI,SAAS,EAAE,YAAA,EAAc,SAAS,CAAA,CAAE,aAAa,CAAA,EAAE,GAAI,EAAC;AAAA,IAC5D,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,MAAA;AAAA,IACA,OAAA,EAAS,EAAE,MAAA,KAAW,KAAA,IAAS,EAAE,MAAA,KAAW,gBAAA,IAAoB,EAAE,YAAA,KAAiB,KAAA;AAAA,IACnF,GAAI,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,EAAE,kBAAkB,KAAA;AAAM,GAC3D;AACF;AAEA,SAAS,aAAA,CAAc,MAA4B,QAAA,EAAqC;AACtF,EAAA,OAAO;AAAA,IACL,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,KAAA,EAAO,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA;AAAA,IAC1B,QAAA;AAAA,IACA,MAAA,EAAQ,KAAK,MAAA,IAAU,IAAA;AAAA,IACvB,QAAQ,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,MACvC,EAAA,EAAI,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AAAA,MAClB,WAAW,IAAA,CAAK,UAAA;AAAA,MAChB,MAAM,IAAA,CAAK,YAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,KAAA,EAAO,QAAA,CAAS,IAAA,CAAK,KAAK;AAAA,KAC5B,CAAE;AAAA,GACJ;AACF;AAEA,eAAe,SAAS,GAAA,EAAkD;AACxE,EAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,CAAK,IAAI,gBAAA,EAAiB;AACnD,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,GAAA,CAAI,KAAK,OAAA,CAAQ,MAAA,EAAQ,CAAC,OAAO,CAAC,CAAA;AAE7D,EAAA,MAAM,IAAA,GAAO,UAAU,IAAA,EAAM,IAAA;AAC7B,EAAA,OAAO,IAAA,GAAO,cAAc,IAAA,EAAM,GAAA,CAAI,OAAO,QAAA,EAAS,EAAG,IAAA,IAAQ,EAAE,CAAA,GAAI,IAAA;AACzE;AAQO,SAAS,sBAAsB,QAAA,EAA4C;AAChF,EAAA,MAAM,cAAA,GAAiB,OACrB,MAAA,KACsC;AACtC,IAAA,MAAM,GAAA,GAAM,MAAM,QAAA,EAAS;AAC3B,IAAA,MAAM,OAAO,GAAG,CAAA;AAChB,IAAA,OAAO,SAAS,GAAG,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,cAAA,EAAgB,OAAO,OAAA,EAAS,KAAA,KAAU;AACxC,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,OAAA,CAAW,IAAA,CAAK,EAAE,MAAA,EAAQ,QAAA,EAAU,OAAA,EAAS,OAAA,EAAS,KAAA,EAAO,CAAA;AACrF,MAAA,OAAO,MAAM,GAAA,CAAI,CAAC,SAAS,gBAAA,CAAiB,IAAA,EAAM,KAAK,CAAC,CAAA;AAAA,IAC1D,CAAA;AAAA,IACA,UAAA,EAAY,OAAO,SAAA,KACjB,gBAAA,CAAiB,MAAM,OAAA,CAAW,IAAA,CAAK,MAAA,CAAO,SAAS,CAAC,CAAA,EAAG,IAAI,CAAA;AAAA,IACjE,OAAA,EAAS,YAAY,QAAA,CAAS,MAAM,UAAU,CAAA;AAAA,IAC9C,SAAA,EAAW,CAAC,SAAA,EAAW,QAAA,KACrB,eAAe,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAA,CAAK,QAAQ,EAAE,EAAA,EAAI,SAAA,EAAW,QAAA,EAAU,CAAC,CAAA;AAAA,IACvE,cAAA,EAAgB,CAAC,MAAA,EAAQ,QAAA,KACvB,eAAe,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAA,CAAK,WAAW,EAAE,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,CAAC,CAAA;AAAA,IACvE,cAAA,EAAgB,CAAC,MAAA,KAAW,cAAA,CAAe,CAAC,QAAQ,GAAA,CAAI,IAAA,CAAK,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,IAC/E,QAAA,EAAU;AAAA,GACZ;AACF;;;AC9GO,SAAS,cAAA,GAAuB;AACrC,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AACnC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EACxB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,SAAA;AAAA,IACE,MACE,mBAAA,CAAoB,qBAAA,CAAsB,CAAC,EAAA,KAAO,gBAAA,CAAiB,WAAA,CAAY,OAAO,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA;AAAA,IAC9F;AAAC,GACH;AACF;;;AClBe,SAAR,WAAA,GAAqC;AAC1C,EAAA,cAAA,EAAe;AACf,EAAA,OAAO,IAAA;AACT","file":"WebMcpTools-3TBLKZL5.js","sourcesContent":["import { defaultNavigate, resolveRelativePath } from '../providers/NavigationProvider';\nimport { getTwilightContext, hasTwilightSettings } from '../twilight/context';\nimport { storePageUrl } from '../utils/baseHead';\n\ntype Navigate = (to: string) => void;\n\nconst isAbsolute = (to: string): boolean => /^[a-z][a-z\\d+.-]*:/i.test(to);\n\nfunction currentSettings() {\n return hasTwilightSettings() ? getTwilightContext().settings : undefined;\n}\n\n/**\n * Make `navigate` safe to call with either a store-relative path (`/cart`) or the\n * absolute URL the API gives a product (`https://shop.example/ar/oud/p7`).\n *\n * - The TanStack router's navigate takes the router's own paths and would append an\n * absolute URL to the current page (`/ar/cart/https:/shop…`). A same-store URL is\n * turned into its store-relative path, as the engine's link interception does; one\n * that cannot be (another origin) loads as a normal page.\n * - The default navigate (`client={false}`, the Next.js adapter) assigns\n * `window.location`, where `/cart` is the host's cart: on a shared host that is\n * another store's page, because stores live under their username. A path becomes\n * the store's own address; an absolute URL is already one.\n */\nexport function withStoreAddress(navigate: Navigate): Navigate {\n const usesWindowLocation = navigate === defaultNavigate;\n\n return (to) => {\n const settings = currentSettings();\n\n if (usesWindowLocation) {\n return navigate(isAbsolute(to) ? to : (storePageUrl(settings, to) ?? to));\n }\n if (!isAbsolute(to)) return navigate(to);\n\n const store = settings?.store;\n const path = store?.url ? resolveRelativePath(to, store.url, store.username) : null;\n return path ? navigate(path) : defaultNavigate(to);\n };\n}\n","/**\n * Input parsing for the tools. The JSON schema is only a hint to the model, so\n * every handler re-checks here and returns a message the agent can correct from.\n */\n\nexport type Parsed<T> = { ok: true; value: T } | { ok: false; error: string };\n\nconst ok = <T>(value: T): Parsed<T> => ({ ok: true, value });\nconst fail = (error: string): Parsed<never> => ({ ok: false, error });\n\n/** A positive whole number from a number or numeric string. */\nexport function parsePositiveInt(raw: unknown, field: string): Parsed<number> {\n const value = typeof raw === 'string' && raw.trim() !== '' ? Number(raw) : raw;\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 1) {\n return fail(`\"${field}\" must be a positive whole number.`);\n }\n return ok(value);\n}\n\nexport function parseQuantity(raw: unknown): Parsed<number> {\n return raw === undefined ? ok(1) : parsePositiveInt(raw, 'quantity');\n}\n\nexport function parseId(raw: unknown, field: string): Parsed<string> {\n const value = typeof raw === 'number' ? String(raw) : raw;\n if (typeof value !== 'string' || value.trim() === '') {\n return fail(`\"${field}\" is required. Get it from get-cart.`);\n }\n return ok(value.trim());\n}\n\nexport function parseKeyword(raw: unknown): Parsed<string> {\n if (typeof raw !== 'string' || raw.trim() === '') {\n return fail('\"keyword\" is required: the words to search the catalog for.');\n }\n return ok(raw.trim());\n}\n\nexport const SEARCH_LIMIT_DEFAULT = 5;\nexport const SEARCH_LIMIT_MAX = 10;\n\nexport function parseLimit(raw: unknown): number {\n if (typeof raw !== 'number' || !Number.isFinite(raw)) return SEARCH_LIMIT_DEFAULT;\n return Math.min(SEARCH_LIMIT_MAX, Math.max(1, Math.trunc(raw)));\n}\n","import type { WebMcpToolResult } from './types';\n\n/** A successful result: the payload as JSON text, which is what agents read best. */\nexport function jsonResult(payload: unknown): WebMcpToolResult {\n return { content: [{ type: 'text', text: JSON.stringify(payload) }] };\n}\n\n/** A failed result with a message the agent can act on. Handlers never throw. */\nexport function errorResult(message: string): WebMcpToolResult {\n return { content: [{ type: 'text', text: message }], isError: true };\n}\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error && error.message ? error.message : 'Unknown error';\n}\n\n/** Run `action`, turning anything it throws into an error result. */\nexport async function guarded(\n label: string,\n action: () => Promise<WebMcpToolResult>\n): Promise<WebMcpToolResult> {\n try {\n return await action();\n } catch (error) {\n return errorResult(`${label} failed: ${errorMessage(error)}`);\n }\n}\n","/** JSON Schema pieces shared by several tools. */\n\nexport const PRODUCT_ID_SCHEMA = {\n type: 'number',\n description: 'Product id, from search-products.',\n} as const;\n\nexport const ITEM_ID_SCHEMA = {\n type: 'string',\n description: 'Cart line id (the \"id\" of an item in get-cart), not the product id.',\n} as const;\n\nexport const QUANTITY_SCHEMA = {\n type: 'number',\n description: 'Whole number of units. Defaults to 1.',\n} as const;\n","import { parseId, parsePositiveInt, parseQuantity } from './input';\nimport { errorResult, guarded, jsonResult } from './results';\nimport { ITEM_ID_SCHEMA, PRODUCT_ID_SCHEMA, QUANTITY_SCHEMA } from './schema';\nimport type { WebMcpDeps, WebMcpTool } from './types';\n\nfunction getCartTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'get-cart',\n description:\n \"Read the shopper's current cart: items (with the line ids needed to change them), count and total. The cart is null when it is empty.\",\n inputSchema: { type: 'object', properties: {} },\n execute: () =>\n guarded('Reading the cart', async () => jsonResult({ cart: await deps.getCart() })),\n };\n}\n\nfunction addToCartTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'add-to-cart',\n description:\n \"Add a product to the shopper's cart and return the updated cart. Only works for products with no required options; for those, use open-page to send the shopper to the product page. Does not check out.\",\n inputSchema: {\n type: 'object',\n properties: { productId: PRODUCT_ID_SCHEMA, quantity: QUANTITY_SCHEMA },\n required: ['productId'],\n },\n execute: (input) =>\n guarded('Adding to the cart', async () => {\n const id = parsePositiveInt(input.productId, 'productId');\n if (!id.ok) return errorResult(id.error);\n const quantity = parseQuantity(input.quantity);\n if (!quantity.ok) return errorResult(quantity.error);\n\n const product = await deps.getProduct(id.value);\n if (!product.inStock) {\n return errorResult(`\"${product.name}\" is out of stock or unavailable.`);\n }\n if (product.needsProductPage === true) {\n return errorResult(\n `\"${product.name}\" needs choices made first (options, a variant, an amount…). Use open-page with page \"product\" and productId ${product.id} (${product.url}) so the shopper can pick them.`\n );\n }\n return jsonResult({ cart: await deps.addToCart(id.value, quantity.value) });\n }),\n };\n}\n\nfunction updateCartItemTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'update-cart-item',\n description:\n 'Change the quantity of a line already in the cart (use get-cart for the line id). Returns the updated cart.',\n inputSchema: {\n type: 'object',\n properties: {\n itemId: ITEM_ID_SCHEMA,\n quantity: { ...QUANTITY_SCHEMA, description: 'New quantity.' },\n },\n required: ['itemId', 'quantity'],\n },\n execute: (input) =>\n guarded('Updating the cart', async () => {\n const itemId = parseId(input.itemId, 'itemId');\n if (!itemId.ok) return errorResult(itemId.error);\n const quantity = parsePositiveInt(input.quantity, 'quantity');\n if (!quantity.ok) return errorResult(quantity.error);\n return jsonResult({ cart: await deps.updateCartItem(itemId.value, quantity.value) });\n }),\n };\n}\n\nfunction removeCartItemTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'remove-cart-item',\n description:\n 'Remove a line from the cart (use get-cart for the line id). Returns the updated cart.',\n inputSchema: {\n type: 'object',\n properties: { itemId: ITEM_ID_SCHEMA },\n required: ['itemId'],\n },\n execute: (input) =>\n guarded('Removing from the cart', async () => {\n const itemId = parseId(input.itemId, 'itemId');\n if (!itemId.ok) return errorResult(itemId.error);\n return jsonResult({ cart: await deps.removeCartItem(itemId.value) });\n }),\n };\n}\n\nexport function createCartTools(deps: WebMcpDeps): WebMcpTool[] {\n return [\n getCartTool(deps),\n addToCartTool(deps),\n updateCartItemTool(deps),\n removeCartItemTool(deps),\n ];\n}\n","import { parseKeyword, parseLimit, parsePositiveInt, SEARCH_LIMIT_MAX } from './input';\nimport { errorResult, guarded, jsonResult } from './results';\nimport { PRODUCT_ID_SCHEMA } from './schema';\nimport type { WebMcpDeps, WebMcpTool } from './types';\n\nfunction searchProductsTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'search-products',\n description:\n \"Search this store's catalog by keyword. Returns up to a few matching products with id, name, price, stock and page URL. Use it to find a product before reading details or adding it to the cart.\",\n inputSchema: {\n type: 'object',\n properties: {\n keyword: { type: 'string', description: 'Words to search for, e.g. \"oud perfume\".' },\n limit: {\n type: 'number',\n description: `How many products to return (1-${SEARCH_LIMIT_MAX}). Defaults to 5.`,\n },\n },\n required: ['keyword'],\n },\n execute: (input) =>\n guarded('Product search', async () => {\n const keyword = parseKeyword(input.keyword);\n if (!keyword.ok) return errorResult(keyword.error);\n const products = await deps.searchProducts(keyword.value, parseLimit(input.limit));\n return jsonResult({ products });\n }),\n };\n}\n\nfunction getProductTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'get-product',\n description:\n 'Get one product by id: price, sale state, stock, and whether the shopper must pick options (size, color…) on the product page first.',\n inputSchema: {\n type: 'object',\n properties: { productId: PRODUCT_ID_SCHEMA },\n required: ['productId'],\n },\n execute: (input) =>\n guarded('Loading the product', async () => {\n const id = parsePositiveInt(input.productId, 'productId');\n if (!id.ok) return errorResult(id.error);\n return jsonResult({ product: await deps.getProduct(id.value) });\n }),\n };\n}\n\nexport function createCatalogTools(deps: WebMcpDeps): WebMcpTool[] {\n return [searchProductsTool(deps), getProductTool(deps)];\n}\n","import { parsePositiveInt } from './input';\nimport { errorResult, guarded, jsonResult } from './results';\nimport { PRODUCT_ID_SCHEMA } from './schema';\nimport type { WebMcpDeps, WebMcpTool } from './types';\n\nfunction openPageTool(deps: WebMcpDeps): WebMcpTool {\n return {\n name: 'open-page',\n description:\n 'Navigate the shopper\\'s visible page to the cart, the home page, or a product page. Use \"cart\" to let the shopper review and check out themselves; checkout is never done by a tool.',\n inputSchema: {\n type: 'object',\n properties: {\n page: { type: 'string', enum: ['cart', 'home', 'product'] },\n productId: { ...PRODUCT_ID_SCHEMA, description: 'Required when page is \"product\".' },\n },\n required: ['page'],\n },\n execute: (input) =>\n guarded('Opening the page', async () => {\n if (input.page === 'cart') {\n deps.openPage('/cart');\n return jsonResult({ opened: 'cart' });\n }\n if (input.page === 'home') {\n deps.openPage('/');\n return jsonResult({ opened: 'home' });\n }\n if (input.page === 'product') {\n const id = parsePositiveInt(input.productId, 'productId');\n if (!id.ok) return errorResult(id.error);\n const product = await deps.getProduct(id.value);\n deps.openPage(product.url);\n return jsonResult({ opened: product.url });\n }\n return errorResult('\"page\" must be one of: cart, home, product.');\n }),\n };\n}\n\nexport function createPageTools(deps: WebMcpDeps): WebMcpTool[] {\n return [openPageTool(deps)];\n}\n","import { createCartTools } from './cart-tools';\nimport { createCatalogTools } from './catalog-tools';\nimport { createPageTools } from './page-tools';\nimport type { WebMcpDeps, WebMcpTool } from './types';\n\n/**\n * The storefront tools. Deliberately small — every tool costs the agent context\n * (see the spec's \"tool budget\") — and none of them places an order or pays: the\n * shopper finishes checkout on the page.\n */\nexport function createWebMcpTools(deps: WebMcpDeps): WebMcpTool[] {\n return [...createCatalogTools(deps), ...createCartTools(deps), ...createPageTools(deps)];\n}\n","import { getModelContext } from './model-context';\nimport { createWebMcpTools } from './tools';\nimport type { WebMcpDeps } from './types';\n\nconst NOT_ALLOWED = 'NotAllowedError';\n\nfunction reportRegistrationFailure(toolName: string, error: unknown): void {\n // The page's Permissions-Policy (or an iframe without `allow`) can switch tools\n // off. That is a choice, not a fault, so it stays quiet.\n if (error instanceof DOMException && error.name === NOT_ALLOWED) return;\n console.warn('[twilight] WebMCP could not register tool:', toolName, error);\n}\n\n/**\n * Register the storefront tools with the browser's WebMCP, if it has one.\n *\n * A no-op everywhere else. Returns a dispose that unregisters every tool (they\n * share one `AbortSignal`, which is how the spec unregisters a tool).\n */\nexport function registerWebMcpTools(deps: WebMcpDeps): () => void {\n const modelContext = getModelContext();\n if (!modelContext) return () => {};\n\n const controller = new AbortController();\n for (const tool of createWebMcpTools(deps)) {\n try {\n Promise.resolve(modelContext.registerTool(tool, { signal: controller.signal })).catch(\n (error: unknown) => reportRegistrationFailure(tool.name, error)\n );\n } catch (error) {\n reportRegistrationFailure(tool.name, error);\n }\n }\n return () => controller.abort();\n}\n","import { product as productApi } from '../api/product';\nimport type { Money, Product } from '../types';\nimport type { SallaCartDetailsData, SallaSDK } from '../types/salla-sdk';\nimport { whenSallaReady } from '../utils/sdk-helpers';\nimport type { WebMcpCartSummary, WebMcpDeps, WebMcpProductSummary } from './types';\n\n/** How long a tool waits for the Salla SDK before telling the agent to retry. */\nconst SDK_WAIT_MS = 8_000;\n\n/** Product types a plain \"add one\" call can buy; the rest need input from the shopper. */\nconst SIMPLE_TYPES: ReadonlySet<string> = new Set(['product', 'digital']);\n\nfunction sdkReady(): Promise<SallaSDK> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cancel();\n reject(new Error('The store is not ready yet. Try again in a moment.'));\n }, SDK_WAIT_MS);\n const cancel = whenSallaReady((sdk) => {\n clearTimeout(timer);\n resolve(sdk);\n });\n });\n}\n\n/** Prices arrive as numbers, `{ amount }` objects or formatted text (\"1,200.50 SAR\"). */\nfunction toAmount(value: unknown): number {\n if (typeof value === 'number') return value;\n if (value && typeof value === 'object' && 'amount' in value) {\n return toAmount((value as Money).amount);\n }\n if (typeof value === 'string') {\n const parsed = Number.parseFloat(value.replace(/,/g, '').replace(/[^\\d.-]/g, ''));\n return Number.isFinite(parsed) ? parsed : 0;\n }\n return 0;\n}\n\n/**\n * Whether the product needs choices made on its page. A details response lists the\n * options and variants, so it can say no; a list response does not, so it can only\n * say yes (a non-plain type, or `has_options`) and otherwise leaves the answer open.\n */\nfunction needsProductPage(p: Product, detailed: boolean): boolean | undefined {\n if (!SIMPLE_TYPES.has(p.type)) return true;\n if ((p.options ?? []).some((option) => option.required)) return true;\n if ((p.skus ?? []).length > 0) return true;\n if (detailed) return false;\n return p.has_options === true ? true : undefined;\n}\n\nfunction toProductSummary(p: Product, detailed: boolean): WebMcpProductSummary {\n const onSale = p.is_on_sale === true;\n const needs = needsProductPage(p, detailed);\n\n return {\n id: Number(p.id),\n name: p.name,\n url: p.url,\n price: toAmount(onSale && p.sale_price ? p.sale_price : p.price),\n ...(onSale ? { regularPrice: toAmount(p.regular_price) } : {}),\n currency: p.currency,\n onSale,\n inStock: p.status !== 'out' && p.status !== 'out-and-notify' && p.is_available !== false,\n ...(needs === undefined ? {} : { needsProductPage: needs }),\n };\n}\n\nfunction toCartSummary(cart: SallaCartDetailsData, currency: string): WebMcpCartSummary {\n return {\n id: cart.id,\n count: cart.count,\n total: toAmount(cart.total),\n currency,\n coupon: cart.coupon ?? null,\n items: (cart.items ?? []).map((item) => ({\n id: String(item.id),\n productId: item.product_id,\n name: item.product_name,\n quantity: item.quantity,\n total: toAmount(item.total),\n })),\n };\n}\n\nasync function readCart(sdk: SallaSDK): Promise<WebMcpCartSummary | null> {\n const cartId = await sdk.cart.api.getCurrentCartId();\n if (!cartId) return null;\n const response = await sdk.api.cart.details(cartId, ['items']);\n // A cart already turned into an order answers with a redirect and no `cart`.\n const cart = response?.data?.cart;\n return cart ? toCartSummary(cart, sdk.config.currency()?.code ?? '') : null;\n}\n\n/**\n * The real tool dependencies: the engine's product API for the catalog, and the\n * Salla SDK for the cart. Cart changes go through `salla.cart.*`, the same calls\n * the UI buttons use, so the cart badge, drawer and toasts update as they would\n * for a click — the shopper and the agent share one visible cart.\n */\nexport function createSallaWebMcpDeps(navigate: (to: string) => void): WebMcpDeps {\n const mutateThenRead = async (\n change: (sdk: SallaSDK) => Promise<unknown>\n ): Promise<WebMcpCartSummary | null> => {\n const sdk = await sdkReady();\n await change(sdk);\n return readCart(sdk);\n };\n\n return {\n searchProducts: async (keyword, limit) => {\n const { items } = await productApi.list({ source: 'search', keyword, perPage: limit });\n return items.map((item) => toProductSummary(item, false));\n },\n getProduct: async (productId) =>\n toProductSummary(await productApi.find(String(productId)), true),\n getCart: async () => readCart(await sdkReady()),\n addToCart: (productId, quantity) =>\n mutateThenRead((sdk) => sdk.cart.addItem({ id: productId, quantity })),\n updateCartItem: (itemId, quantity) =>\n mutateThenRead((sdk) => sdk.cart.updateItem({ id: itemId, quantity })),\n removeCartItem: (itemId) => mutateThenRead((sdk) => sdk.cart.deleteItem(itemId)),\n openPage: navigate,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useNavigate } from '../providers/NavigationProvider';\nimport { withStoreAddress } from './page-navigation';\nimport { registerWebMcpTools } from './registerWebMcpTools';\nimport { createSallaWebMcpDeps } from './salla-deps';\n\n/**\n * Expose the storefront to in-browser AI agents through WebMCP for as long as the\n * calling component is mounted. Does nothing where the browser has no WebMCP.\n *\n * `navigate` is read through a ref so a router that hands out a new function on\n * each render does not unregister and re-register every tool (the spec warns\n * that each change churns the agent's tool list).\n */\nexport function useWebMcpTools(): void {\n const navigate = useNavigate();\n const navigateRef = useRef(navigate);\n useEffect(() => {\n navigateRef.current = navigate;\n }, [navigate]);\n\n useEffect(\n () =>\n registerWebMcpTools(createSallaWebMcpDeps((to) => withStoreAddress(navigateRef.current)(to))),\n []\n );\n}\n","import { useWebMcpTools } from './useWebMcpTools';\n\n/**\n * Mounts the WebMCP storefront tools. Renders nothing; a component rather than a\n * call in `TwilightProvider` because it needs the router's `navigate`, which only\n * exists below the provider's navigation setup. Loaded lazily — no shopper needs\n * it to see the page.\n */\nexport default function WebMcpTools(): null {\n useWebMcpTools();\n return null;\n}\n"]}
|
|
@@ -1,45 +1,46 @@
|
|
|
1
|
-
import { wishlist } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import { useMoney } from './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-
|
|
1
|
+
import { wishlist } from './chunk-TF46NIZF.js';
|
|
2
|
+
import './chunk-WIDH6AK6.js';
|
|
3
|
+
import { useMoney } from './chunk-GBMMP344.js';
|
|
4
|
+
import './chunk-Q77J3D2W.js';
|
|
5
|
+
import './chunk-U5TWRPMK.js';
|
|
6
|
+
import './chunk-YYVZFOUI.js';
|
|
7
|
+
import './chunk-5V4W3GBI.js';
|
|
7
8
|
import './chunk-X55R4VVK.js';
|
|
8
9
|
import './chunk-YL6X3ZMG.js';
|
|
9
|
-
import './chunk-
|
|
10
|
+
import './chunk-PCB5DCS4.js';
|
|
10
11
|
import './chunk-OXMUPNMH.js';
|
|
11
|
-
import './chunk-
|
|
12
|
+
import './chunk-NGWHUW34.js';
|
|
12
13
|
import './chunk-VVZNW5CB.js';
|
|
13
|
-
import './chunk-
|
|
14
|
+
import './chunk-EGI7F57E.js';
|
|
14
15
|
import './chunk-GD26FI4J.js';
|
|
15
|
-
import './chunk-
|
|
16
|
-
import './chunk-
|
|
17
|
-
import { useLocation } from './chunk-
|
|
16
|
+
import './chunk-SLBO4SEE.js';
|
|
17
|
+
import './chunk-MGG4XAJ5.js';
|
|
18
|
+
import { useLocation } from './chunk-HRW4YFHR.js';
|
|
18
19
|
import './chunk-OUW6WESU.js';
|
|
19
|
-
import './chunk-
|
|
20
|
+
import './chunk-IHOUADLX.js';
|
|
20
21
|
import './chunk-HI5V5X3S.js';
|
|
21
|
-
import './chunk-
|
|
22
|
-
import './chunk-
|
|
22
|
+
import './chunk-XV3HPKLI.js';
|
|
23
|
+
import './chunk-5JZSBFA5.js';
|
|
23
24
|
import './chunk-MVT5AF2A.js';
|
|
24
25
|
import './chunk-Z653O7MX.js';
|
|
25
26
|
import './chunk-ZCH7W7DZ.js';
|
|
26
|
-
import './chunk-
|
|
27
|
+
import './chunk-H7LRGY7U.js';
|
|
27
28
|
import './chunk-JWXJPJBO.js';
|
|
28
29
|
import './chunk-CW625T2E.js';
|
|
29
30
|
import './chunk-7V36I5GT.js';
|
|
30
31
|
import './chunk-6WI7R2BD.js';
|
|
31
|
-
import { useWishlist } from './chunk-
|
|
32
|
+
import { useWishlist } from './chunk-M5WTY3EH.js';
|
|
32
33
|
import './chunk-OAMIDZKW.js';
|
|
33
|
-
import './chunk-
|
|
34
|
+
import './chunk-KGSB2Y7O.js';
|
|
34
35
|
import './chunk-OQIIJRAS.js';
|
|
35
36
|
import './chunk-V2ZDTY6H.js';
|
|
36
|
-
import './chunk-
|
|
37
|
+
import './chunk-ETC7OJT5.js';
|
|
37
38
|
import { HookSlot } from './chunk-5XDPAKF5.js';
|
|
38
39
|
import './chunk-GCPEMNSU.js';
|
|
39
|
-
import './chunk-
|
|
40
|
+
import './chunk-U2UNWN4G.js';
|
|
40
41
|
import './chunk-Z5M4YYWT.js';
|
|
41
42
|
import { useTranslation } from './chunk-TYNZ5B2B.js';
|
|
42
|
-
import { LazyNoContent, Image } from './chunk-
|
|
43
|
+
import { LazyNoContent, Image } from './chunk-VZRZQV4Q.js';
|
|
43
44
|
import './chunk-AXW67SY7.js';
|
|
44
45
|
import './chunk-BYMOPN2S.js';
|
|
45
46
|
import './chunk-SKLEJJ6M.js';
|
|
@@ -47,10 +48,10 @@ import './chunk-6BZ5TKEV.js';
|
|
|
47
48
|
import './chunk-FZKRSGLP.js';
|
|
48
49
|
import './chunk-KYMWEUN2.js';
|
|
49
50
|
import './chunk-YA6ABQB7.js';
|
|
50
|
-
import './chunk-
|
|
51
|
-
import './chunk-
|
|
52
|
-
import { onSallaEvent } from './chunk-
|
|
53
|
-
import './chunk-
|
|
51
|
+
import './chunk-QMWP2ZP6.js';
|
|
52
|
+
import './chunk-6TFM3UTF.js';
|
|
53
|
+
import { onSallaEvent } from './chunk-XMRNYUQY.js';
|
|
54
|
+
import './chunk-T2752RH7.js';
|
|
54
55
|
import './chunk-6K34BCUP.js';
|
|
55
56
|
import './chunk-T72DAX7R.js';
|
|
56
57
|
import './chunk-DF6FBKDN.js';
|
|
@@ -501,5 +502,5 @@ function WishlistPage(props) {
|
|
|
501
502
|
}
|
|
502
503
|
|
|
503
504
|
export { WishlistPage };
|
|
504
|
-
//# sourceMappingURL=WishlistPage-
|
|
505
|
-
//# sourceMappingURL=WishlistPage-
|
|
505
|
+
//# sourceMappingURL=WishlistPage-BM3XSMQF.js.map
|
|
506
|
+
//# sourceMappingURL=WishlistPage-BM3XSMQF.js.map
|