tanstack_start_ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/.wrangler/deploy/config.json +1 -0
  2. package/bunfig.toml +6 -0
  3. package/components.json +22 -0
  4. package/config.json +0 -0
  5. package/dist/client/.assetsignore +2 -0
  6. package/dist/client/assets/ProductCard-DbIkJAE-.js +1 -0
  7. package/dist/client/assets/about-AskxOruL.js +1 -0
  8. package/dist/client/assets/admin-BZVcAQM3.js +1 -0
  9. package/dist/client/assets/admin.functions--RdVcuBx.js +1 -0
  10. package/dist/client/assets/admin.login-QgrF_9Fp.js +1 -0
  11. package/dist/client/assets/affiliate-disclosure-BIAsA-HO.js +1 -0
  12. package/dist/client/assets/categories-D0N418mK.js +1 -0
  13. package/dist/client/assets/category._slug-aCaQm14E.js +1 -0
  14. package/dist/client/assets/contact-PhvO-V15.js +1 -0
  15. package/dist/client/assets/faq-BsiHWPM8.js +1 -0
  16. package/dist/client/assets/hero-bg-BP2eVUIX.jpg +0 -0
  17. package/dist/client/assets/index-BU9rnkF3.js +1 -0
  18. package/dist/client/assets/index-BpJWZkva.js +1 -0
  19. package/dist/client/assets/index-vRX-zAyq.js +1 -0
  20. package/dist/client/assets/login-DteE0ZGp.js +1 -0
  21. package/dist/client/assets/logo-pSNfLJQk.png +0 -0
  22. package/dist/client/assets/privacy-B_Pu7040.js +1 -0
  23. package/dist/client/assets/product-links-BkZ41Gv3.js +1 -0
  24. package/dist/client/assets/product._id-BVUysCW-.js +1 -0
  25. package/dist/client/assets/products.functions-cGzRziKO.js +1 -0
  26. package/dist/client/assets/profile-CveRcKq2.js +1 -0
  27. package/dist/client/assets/reset-password-ySEjItX_.js +1 -0
  28. package/dist/client/assets/saved-CHtdQDJF.js +1 -0
  29. package/dist/client/assets/search-CXWfET1y.js +1 -0
  30. package/dist/client/assets/signup-CEx90iuV.js +1 -0
  31. package/dist/client/assets/styles-DrNJG0BO.css +1 -0
  32. package/dist/client/assets/terms-VqJ9kX9b.js +1 -0
  33. package/dist/client/assets/update-password-C-d0ix5e.js +1 -0
  34. package/dist/client/assets/vendor-aria-hidden-DvXkyWUv.js +1 -0
  35. package/dist/client/assets/vendor-class-variance-authority-5VPnzWs2.js +1 -0
  36. package/dist/client/assets/vendor-clsx-B-dksMZM.js +1 -0
  37. package/dist/client/assets/vendor-cookie-es-CS0aJGDi.js +1 -0
  38. package/dist/client/assets/vendor-detect-node-es-l0sNRNKZ.js +1 -0
  39. package/dist/client/assets/vendor-floating-ui-core-BlUy28sp.js +1 -0
  40. package/dist/client/assets/vendor-floating-ui-dom-BxK0hn2R.js +1 -0
  41. package/dist/client/assets/vendor-floating-ui-react-dom-Bas3975S.js +1 -0
  42. package/dist/client/assets/vendor-floating-ui-utils-BfYUAVcw.js +1 -0
  43. package/dist/client/assets/vendor-framer-motion-BMdL-cuX.js +9 -0
  44. package/dist/client/assets/vendor-get-nonce-C-Z93AgS.js +1 -0
  45. package/dist/client/assets/vendor-iceberg-js-tWD4K6Lg.js +1 -0
  46. package/dist/client/assets/vendor-lovable.dev-cloud-auth-js-VuzqtJVg.js +1 -0
  47. package/dist/client/assets/vendor-lucide-react-b5K2fehp.js +1 -0
  48. package/dist/client/assets/vendor-motion-dom-BETJamZt.js +1 -0
  49. package/dist/client/assets/vendor-motion-utils-BuWewJbj.js +1 -0
  50. package/dist/client/assets/vendor-radix-ui-primitive-Dc_FVRD7.js +1 -0
  51. package/dist/client/assets/vendor-radix-ui-react-accordion-C22Rgxe9.js +1 -0
  52. package/dist/client/assets/vendor-radix-ui-react-arrow-DMHj2mKI.js +1 -0
  53. package/dist/client/assets/vendor-radix-ui-react-avatar-CVPBkFXg.js +1 -0
  54. package/dist/client/assets/vendor-radix-ui-react-collapsible-BvM-4sKX.js +1 -0
  55. package/dist/client/assets/vendor-radix-ui-react-collection-D9KtqmHm.js +1 -0
  56. package/dist/client/assets/vendor-radix-ui-react-compose-refs-Cvq0AS8Z.js +1 -0
  57. package/dist/client/assets/vendor-radix-ui-react-context-CAqqn5Nx.js +1 -0
  58. package/dist/client/assets/vendor-radix-ui-react-dialog-DZ01vOLq.js +5 -0
  59. package/dist/client/assets/vendor-radix-ui-react-direction-DxZwNuei.js +1 -0
  60. package/dist/client/assets/vendor-radix-ui-react-dismissable-layer-Dqgrs55Y.js +1 -0
  61. package/dist/client/assets/vendor-radix-ui-react-dropdown-menu-0uzvrqkn.js +1 -0
  62. package/dist/client/assets/vendor-radix-ui-react-focus-guards-DgWoZ-fP.js +1 -0
  63. package/dist/client/assets/vendor-radix-ui-react-focus-scope-BLIu5QaL.js +1 -0
  64. package/dist/client/assets/vendor-radix-ui-react-id-bpga_rLa.js +1 -0
  65. package/dist/client/assets/vendor-radix-ui-react-menu-D0qf2r6_.js +1 -0
  66. package/dist/client/assets/vendor-radix-ui-react-popper-BafIylxU.js +1 -0
  67. package/dist/client/assets/vendor-radix-ui-react-portal-BnAsfNCS.js +1 -0
  68. package/dist/client/assets/vendor-radix-ui-react-presence-C-f3UKQ2.js +1 -0
  69. package/dist/client/assets/vendor-radix-ui-react-primitive-zTHwXNoz.js +1 -0
  70. package/dist/client/assets/vendor-radix-ui-react-roving-focus-jyJB8K2E.js +1 -0
  71. package/dist/client/assets/vendor-radix-ui-react-slot-6LXHJrHl.js +1 -0
  72. package/dist/client/assets/vendor-radix-ui-react-use-callback-ref-E91aPc6s.js +1 -0
  73. package/dist/client/assets/vendor-radix-ui-react-use-controllable-state-Ca3eMtxa.js +1 -0
  74. package/dist/client/assets/vendor-radix-ui-react-use-effect-event-CPeX4A3c.js +1 -0
  75. package/dist/client/assets/vendor-radix-ui-react-use-escape-keydown-7n3YsXFo.js +1 -0
  76. package/dist/client/assets/vendor-radix-ui-react-use-is-hydrated-C1PY1qNv.js +1 -0
  77. package/dist/client/assets/vendor-radix-ui-react-use-layout-effect-B3AcGWPy.js +1 -0
  78. package/dist/client/assets/vendor-radix-ui-react-use-size-CXS04sct.js +1 -0
  79. package/dist/client/assets/vendor-react-dom-BnNs-kzm.js +9 -0
  80. package/dist/client/assets/vendor-react-gJPiVnX5.js +1 -0
  81. package/dist/client/assets/vendor-react-remove-scroll-DHKl-IMP.js +4 -0
  82. package/dist/client/assets/vendor-react-remove-scroll-bar-CSjdInc2.js +38 -0
  83. package/dist/client/assets/vendor-react-style-singleton-BqHpkgXn.js +1 -0
  84. package/dist/client/assets/vendor-scheduler-7OC5HNn7.js +1 -0
  85. package/dist/client/assets/vendor-seroval-B_Fur-nl.js +3 -0
  86. package/dist/client/assets/vendor-seroval-plugins-CBHnPkZJ.js +1 -0
  87. package/dist/client/assets/vendor-sonner-71-LdGG1.js +1 -0
  88. package/dist/client/assets/vendor-supabase-auth-js-DWrN-bIx.js +18 -0
  89. package/dist/client/assets/vendor-supabase-functions-js-uY_V-TxC.js +1 -0
  90. package/dist/client/assets/vendor-supabase-phoenix-BzEf37Ve.js +2 -0
  91. package/dist/client/assets/vendor-supabase-postgrest-js-C4rBWbCx.js +4 -0
  92. package/dist/client/assets/vendor-supabase-realtime-js-D6BlOYKE.js +23 -0
  93. package/dist/client/assets/vendor-supabase-storage-js-BG98L3Zz.js +1 -0
  94. package/dist/client/assets/vendor-supabase-supabase-js-DCCzdwBJ.js +1 -0
  95. package/dist/client/assets/vendor-tailwind-merge-Ct12j0u0.js +1 -0
  96. package/dist/client/assets/vendor-tanstack-history-C617CaxG.js +1 -0
  97. package/dist/client/assets/vendor-tanstack-query-core-7wuJJ5ZL.js +1 -0
  98. package/dist/client/assets/vendor-tanstack-react-query-HImzo8sX.js +1 -0
  99. package/dist/client/assets/vendor-tanstack-react-router-sIZLK-LU.js +1 -0
  100. package/dist/client/assets/vendor-tanstack-react-start-client-GiYCfWmf.js +1 -0
  101. package/dist/client/assets/vendor-tanstack-react-store-EvTi3ahh.js +1 -0
  102. package/dist/client/assets/vendor-tanstack-router-core-Cr7bYUZv.js +1 -0
  103. package/dist/client/assets/vendor-tanstack-start-client-core-C-00BBOu.js +2 -0
  104. package/dist/client/assets/vendor-tanstack-start-fn-stubs-l0sNRNKZ.js +1 -0
  105. package/dist/client/assets/vendor-tanstack-store-BC7mA7pq.js +1 -0
  106. package/dist/client/assets/vendor-tslib-Du-meQkk.js +1 -0
  107. package/dist/client/assets/vendor-use-callback-ref-C_fIAtot.js +1 -0
  108. package/dist/client/assets/vendor-use-sidecar-Bh0DDN6h.js +1 -0
  109. package/dist/client/assets/vendor-use-sync-external-store-ZvKHXaIn.js +1 -0
  110. package/dist/client/assets/vendor-vercel-analytics-DwPM5BWs.js +1 -0
  111. package/dist/client/assets/vendor-zod-By9teAtI.js +1 -0
  112. package/dist/client/robots.txt +2 -0
  113. package/dist/server/.dev.vars +5 -0
  114. package/dist/server/.vite/manifest.json +2528 -0
  115. package/dist/server/assets/ProductCard-CUPXy5Eo.js +149 -0
  116. package/dist/server/assets/_tanstack-start-manifest_v-do7vTWFD.js +4 -0
  117. package/dist/server/assets/about-TfKQw0Ga.js +28 -0
  118. package/dist/server/assets/admin-DspfJOJk.js +578 -0
  119. package/dist/server/assets/admin.functions-B78ppWLR.js +645 -0
  120. package/dist/server/assets/admin.functions-BWlKBoTL.js +93 -0
  121. package/dist/server/assets/admin.login-CV7QfeA6.js +139 -0
  122. package/dist/server/assets/affiliate-disclosure-B1wI1cDb.js +86 -0
  123. package/dist/server/assets/auth-middleware-Cn49MidW.js +62 -0
  124. package/dist/server/assets/categories-Z7jnAYZP.js +108 -0
  125. package/dist/server/assets/category._slug-D0XY3FGK.js +112 -0
  126. package/dist/server/assets/contact-IzyONsXs.js +104 -0
  127. package/dist/server/assets/faq-aRhB_CR3.js +133 -0
  128. package/dist/server/assets/hero-bg-BP2eVUIX.jpg +0 -0
  129. package/dist/server/assets/index-BTPHbXw9.js +221 -0
  130. package/dist/server/assets/index-ByJkHkrU.js +30 -0
  131. package/dist/server/assets/login-Dvy5Dm0f.js +175 -0
  132. package/dist/server/assets/logo-pSNfLJQk.png +0 -0
  133. package/dist/server/assets/privacy-B6Wiez1P.js +93 -0
  134. package/dist/server/assets/product-links-CGYEPP56.js +16 -0
  135. package/dist/server/assets/product._id-BpRa-1z0.js +231 -0
  136. package/dist/server/assets/products.functions-DSlmibYN.js +209 -0
  137. package/dist/server/assets/products.functions-DlHkRiqi.js +24 -0
  138. package/dist/server/assets/profile-B0NWzVAZ.js +314 -0
  139. package/dist/server/assets/reset-password-CY-rmqMr.js +115 -0
  140. package/dist/server/assets/saved-7FA6Dbom.js +126 -0
  141. package/dist/server/assets/search-Yw5c_fZa.js +329 -0
  142. package/dist/server/assets/signup-UPzgZo4i.js +143 -0
  143. package/dist/server/assets/styles-DrNJG0BO.css +1 -0
  144. package/dist/server/assets/terms-CMnX95bP.js +89 -0
  145. package/dist/server/assets/update-password-Cr94ea8n.js +131 -0
  146. package/dist/server/assets/vendor-aria-hidden-DPa16MWu.js +122 -0
  147. package/dist/server/assets/vendor-class-variance-authority-0YxJPB9Y.js +44 -0
  148. package/dist/server/assets/vendor-cloudflare-unenv-preset-ya0VEFBz.js +250 -0
  149. package/dist/server/assets/vendor-clsx-DgYk2OaC.js +16 -0
  150. package/dist/server/assets/vendor-cookie-es-DAoofYiI.js +44 -0
  151. package/dist/server/assets/vendor-detect-node-es-l0sNRNKZ.js +1 -0
  152. package/dist/server/assets/vendor-floating-ui-core-3tkK0THV.js +726 -0
  153. package/dist/server/assets/vendor-floating-ui-dom-C-cPtgJv.js +626 -0
  154. package/dist/server/assets/vendor-floating-ui-react-dom-CRG6gBpH.js +319 -0
  155. package/dist/server/assets/vendor-floating-ui-utils-DmXANH-E.js +320 -0
  156. package/dist/server/assets/vendor-framer-motion-X4zAkX3J.js +1979 -0
  157. package/dist/server/assets/vendor-get-nonce-DiSj3EHl.js +9 -0
  158. package/dist/server/assets/vendor-h3-v2-CCobnLY5.js +287 -0
  159. package/dist/server/assets/vendor-iceberg-js-bHCkXyJn.js +534 -0
  160. package/dist/server/assets/vendor-isbot-CZ7WjwVs.js +21 -0
  161. package/dist/server/assets/vendor-lovable.dev-cloud-auth-js-BE03njZw.js +180 -0
  162. package/dist/server/assets/vendor-lucide-react-Ddew6HYb.js +458 -0
  163. package/dist/server/assets/vendor-motion-dom-D2MTwGIG.js +5983 -0
  164. package/dist/server/assets/vendor-motion-utils-LJlIFN6m.js +161 -0
  165. package/dist/server/assets/vendor-radix-ui-primitive-B-mNdDrH.js +11 -0
  166. package/dist/server/assets/vendor-radix-ui-react-accordion-1Izf6x00.js +308 -0
  167. package/dist/server/assets/vendor-radix-ui-react-arrow-B882lnFK.js +23 -0
  168. package/dist/server/assets/vendor-radix-ui-react-avatar-BVgZt2Ab.js +209 -0
  169. package/dist/server/assets/vendor-radix-ui-react-collapsible-DCBbMZiS.js +147 -0
  170. package/dist/server/assets/vendor-radix-ui-react-collection-BZ2srfgU.js +150 -0
  171. package/dist/server/assets/vendor-radix-ui-react-compose-refs-D3qsKVk1.js +39 -0
  172. package/dist/server/assets/vendor-radix-ui-react-context-BVoNDLue.js +78 -0
  173. package/dist/server/assets/vendor-radix-ui-react-dialog-DlxMaNYK.js +406 -0
  174. package/dist/server/assets/vendor-radix-ui-react-direction-Dt_WDL1t.js +9 -0
  175. package/dist/server/assets/vendor-radix-ui-react-dismissable-layer-CjsuPohV.js +210 -0
  176. package/dist/server/assets/vendor-radix-ui-react-dropdown-menu-DVxKumY8.js +263 -0
  177. package/dist/server/assets/vendor-radix-ui-react-focus-guards-D_6NoePE.js +29 -0
  178. package/dist/server/assets/vendor-radix-ui-react-focus-scope-DEIhTJJH.js +206 -0
  179. package/dist/server/assets/vendor-radix-ui-react-id-DFFpgh6m.js +14 -0
  180. package/dist/server/assets/vendor-radix-ui-react-menu-CiTMLwjT.js +893 -0
  181. package/dist/server/assets/vendor-radix-ui-react-popper-23Ye2Vyc.js +286 -0
  182. package/dist/server/assets/vendor-radix-ui-react-portal-CZCH5uPk.js +16 -0
  183. package/dist/server/assets/vendor-radix-ui-react-presence-CaAULlDU.js +128 -0
  184. package/dist/server/assets/vendor-radix-ui-react-primitive-BeOk3UYa.js +124 -0
  185. package/dist/server/assets/vendor-radix-ui-react-roving-focus-DES9GR8l.js +224 -0
  186. package/dist/server/assets/vendor-radix-ui-react-slot-DUhZbzoH.js +103 -0
  187. package/dist/server/assets/vendor-radix-ui-react-use-callback-ref-BynBgohw.js +11 -0
  188. package/dist/server/assets/vendor-radix-ui-react-use-controllable-state-C9KpT6DG.js +69 -0
  189. package/dist/server/assets/vendor-radix-ui-react-use-effect-event-gpNY2xjS.js +1 -0
  190. package/dist/server/assets/vendor-radix-ui-react-use-escape-keydown-CcYRQ2pp.js +17 -0
  191. package/dist/server/assets/vendor-radix-ui-react-use-is-hydrated-D_LcBPXY.js +15 -0
  192. package/dist/server/assets/vendor-radix-ui-react-use-layout-effect-1LNLXAjr.js +6 -0
  193. package/dist/server/assets/vendor-radix-ui-react-use-size-D6fiKJQo.js +39 -0
  194. package/dist/server/assets/vendor-react-DvBrY0qp.js +511 -0
  195. package/dist/server/assets/vendor-react-dom-yvMLPM0j.js +10484 -0
  196. package/dist/server/assets/vendor-react-remove-scroll-BNtiEvVN.js +328 -0
  197. package/dist/server/assets/vendor-react-remove-scroll-bar-hLqRASRk.js +82 -0
  198. package/dist/server/assets/vendor-react-style-singleton-BXjcXskB.js +69 -0
  199. package/dist/server/assets/vendor-rou3-3NaGPdI8.js +8 -0
  200. package/dist/server/assets/vendor-seroval-dJyC-Zhz.js +1775 -0
  201. package/dist/server/assets/vendor-seroval-plugins-Pq_U2meB.js +58 -0
  202. package/dist/server/assets/vendor-sonner-CqbjhsRh.js +1086 -0
  203. package/dist/server/assets/vendor-srvx-BA-baEX9.js +6 -0
  204. package/dist/server/assets/vendor-supabase-auth-js-D4xjVprw.js +7602 -0
  205. package/dist/server/assets/vendor-supabase-functions-js-sWy4UYn1.js +322 -0
  206. package/dist/server/assets/vendor-supabase-phoenix-Bw3Uh2Nn.js +1777 -0
  207. package/dist/server/assets/vendor-supabase-postgrest-js-AO-BXa7I.js +4938 -0
  208. package/dist/server/assets/vendor-supabase-realtime-js-BtdNgJbm.js +2111 -0
  209. package/dist/server/assets/vendor-supabase-storage-js-Dk_MrPYO.js +2679 -0
  210. package/dist/server/assets/vendor-supabase-supabase-js-D1EEtG3j.js +697 -0
  211. package/dist/server/assets/vendor-tailwind-merge-BHb_obmC.js +3255 -0
  212. package/dist/server/assets/vendor-tanstack-history-C4pKJmkt.js +204 -0
  213. package/dist/server/assets/vendor-tanstack-query-core-PwwTR5ld.js +2552 -0
  214. package/dist/server/assets/vendor-tanstack-react-query-hhHzXAK1.js +190 -0
  215. package/dist/server/assets/vendor-tanstack-react-router-XzqpA65A.js +1120 -0
  216. package/dist/server/assets/vendor-tanstack-react-start-RvWUpvat.js +37 -0
  217. package/dist/server/assets/vendor-tanstack-react-start-client-gpNY2xjS.js +1 -0
  218. package/dist/server/assets/vendor-tanstack-react-start-server-uj_Y9pEN.js +15 -0
  219. package/dist/server/assets/vendor-tanstack-react-store-gpNY2xjS.js +1 -0
  220. package/dist/server/assets/vendor-tanstack-router-core-6wywV3KN.js +4252 -0
  221. package/dist/server/assets/vendor-tanstack-start-client-core-DoOKV2pA.js +1741 -0
  222. package/dist/server/assets/vendor-tanstack-start-fn-stubs-l0sNRNKZ.js +1 -0
  223. package/dist/server/assets/vendor-tanstack-start-server-core-CsAstXv7.js +1421 -0
  224. package/dist/server/assets/vendor-tanstack-start-storage-context-DgH9hIJT.js +17 -0
  225. package/dist/server/assets/vendor-tanstack-store-l0sNRNKZ.js +1 -0
  226. package/dist/server/assets/vendor-tslib-_8ICaZ64.js +67 -0
  227. package/dist/server/assets/vendor-unenv-DUvF4YIF.js +544 -0
  228. package/dist/server/assets/vendor-use-callback-ref-DMFDRvmi.js +66 -0
  229. package/dist/server/assets/vendor-use-sidecar-DG1tHua4.js +106 -0
  230. package/dist/server/assets/vendor-use-sync-external-store-rZ8vi0It.js +64 -0
  231. package/dist/server/assets/vendor-vercel-analytics-oP8BDp0L.js +168 -0
  232. package/dist/server/assets/vendor-zod-BRyQdbC-.js +3580 -0
  233. package/dist/server/index.js +158 -0
  234. package/dist/server/wrangler.json +1 -0
  235. package/enable-powershell.ps1 +7 -0
  236. package/eslint.config.js +41 -0
  237. package/lint.bat +4 -0
  238. package/package.json +95 -0
  239. package/public/robots.txt +2 -0
  240. package/run-npm-build.cjs +20 -0
  241. package/run-npm-build.js +20 -0
  242. package/src/assets/hero-bg.jpg +0 -0
  243. package/src/assets/logo.png +0 -0
  244. package/src/components/scrollsy/Footer.tsx +68 -0
  245. package/src/components/scrollsy/LiveTicker.tsx +31 -0
  246. package/src/components/scrollsy/Logo.tsx +28 -0
  247. package/src/components/scrollsy/Nav.tsx +255 -0
  248. package/src/components/scrollsy/ProductCard.tsx +190 -0
  249. package/src/components/scrollsy/ProductFilters.tsx +226 -0
  250. package/src/components/scrollsy/SupportWidget.tsx +197 -0
  251. package/src/components/ui/accordion.tsx +51 -0
  252. package/src/components/ui/alert-dialog.tsx +115 -0
  253. package/src/components/ui/alert.tsx +49 -0
  254. package/src/components/ui/aspect-ratio.tsx +5 -0
  255. package/src/components/ui/avatar.tsx +47 -0
  256. package/src/components/ui/badge.tsx +32 -0
  257. package/src/components/ui/breadcrumb.tsx +101 -0
  258. package/src/components/ui/button.tsx +49 -0
  259. package/src/components/ui/calendar.tsx +177 -0
  260. package/src/components/ui/card.tsx +55 -0
  261. package/src/components/ui/carousel.tsx +240 -0
  262. package/src/components/ui/chart.tsx +331 -0
  263. package/src/components/ui/checkbox.tsx +26 -0
  264. package/src/components/ui/collapsible.tsx +11 -0
  265. package/src/components/ui/command.tsx +143 -0
  266. package/src/components/ui/context-menu.tsx +187 -0
  267. package/src/components/ui/dialog.tsx +104 -0
  268. package/src/components/ui/drawer.tsx +98 -0
  269. package/src/components/ui/dropdown-menu.tsx +188 -0
  270. package/src/components/ui/form.tsx +171 -0
  271. package/src/components/ui/hover-card.tsx +27 -0
  272. package/src/components/ui/input-otp.tsx +69 -0
  273. package/src/components/ui/input.tsx +22 -0
  274. package/src/components/ui/label.tsx +21 -0
  275. package/src/components/ui/menubar.tsx +229 -0
  276. package/src/components/ui/navigation-menu.tsx +120 -0
  277. package/src/components/ui/pagination.tsx +98 -0
  278. package/src/components/ui/popover.tsx +31 -0
  279. package/src/components/ui/progress.tsx +25 -0
  280. package/src/components/ui/radio-group.tsx +36 -0
  281. package/src/components/ui/resizable.tsx +37 -0
  282. package/src/components/ui/scroll-area.tsx +44 -0
  283. package/src/components/ui/select.tsx +152 -0
  284. package/src/components/ui/separator.tsx +24 -0
  285. package/src/components/ui/sheet.tsx +122 -0
  286. package/src/components/ui/sidebar.tsx +744 -0
  287. package/src/components/ui/skeleton.tsx +7 -0
  288. package/src/components/ui/slider.tsx +23 -0
  289. package/src/components/ui/sonner.tsx +23 -0
  290. package/src/components/ui/switch.tsx +27 -0
  291. package/src/components/ui/table.tsx +94 -0
  292. package/src/components/ui/tabs.tsx +53 -0
  293. package/src/components/ui/textarea.tsx +21 -0
  294. package/src/components/ui/toggle-group.tsx +57 -0
  295. package/src/components/ui/toggle.tsx +42 -0
  296. package/src/components/ui/tooltip.tsx +32 -0
  297. package/src/hooks/use-auth.ts +26 -0
  298. package/src/hooks/use-mobile.tsx +19 -0
  299. package/src/integrations/lovable/index.ts +41 -0
  300. package/src/lib/admin.functions.ts +564 -0
  301. package/src/lib/error-capture.ts +27 -0
  302. package/src/lib/error-page.ts +30 -0
  303. package/src/lib/product-links.ts +39 -0
  304. package/src/lib/products.functions.ts +101 -0
  305. package/src/lib/utils.ts +6 -0
  306. package/src/routeTree.gen.ts +480 -0
  307. package/src/router.tsx +16 -0
  308. package/src/routes/__root.tsx +177 -0
  309. package/src/routes/about.tsx +66 -0
  310. package/src/routes/admin.login.tsx +95 -0
  311. package/src/routes/admin.tsx +811 -0
  312. package/src/routes/affiliate-disclosure.tsx +35 -0
  313. package/src/routes/categories.tsx +57 -0
  314. package/src/routes/category.$slug.tsx +51 -0
  315. package/src/routes/contact.tsx +69 -0
  316. package/src/routes/faq.tsx +63 -0
  317. package/src/routes/index.tsx +269 -0
  318. package/src/routes/login.tsx +160 -0
  319. package/src/routes/privacy.tsx +39 -0
  320. package/src/routes/product.$id.tsx +212 -0
  321. package/src/routes/profile.tsx +393 -0
  322. package/src/routes/reset-password.tsx +71 -0
  323. package/src/routes/saved.tsx +83 -0
  324. package/src/routes/search.tsx +136 -0
  325. package/src/routes/signup.tsx +108 -0
  326. package/src/routes/sitemap[.]xml.ts +34 -0
  327. package/src/routes/terms.tsx +40 -0
  328. package/src/routes/update-password.tsx +91 -0
  329. package/src/server.ts +80 -0
  330. package/src/start.ts +24 -0
  331. package/src/styles.css +333 -0
  332. package/terminal-test-output.txt +1 -0
  333. package/tsconfig.json +27 -0
  334. package/vercel.json +26 -0
  335. package/vite.config.ts +38 -0
  336. package/wrangler.jsonc +7 -0
@@ -0,0 +1,645 @@
1
+ import { c as createServerRpc } from "./vendor-tanstack-start-server-core-CsAstXv7.js";
2
+ import { n as createServerFn } from "./vendor-tanstack-start-client-core-DoOKV2pA.js";
3
+ import { r as requireSupabaseAuth } from "./auth-middleware-Cn49MidW.js";
4
+ import { c as createClient } from "./vendor-supabase-supabase-js-D1EEtG3j.js";
5
+ import { o as objectType, s as stringType, b as booleanType, a as arrayType, n as numberType, Z as ZodIssueCode } from "./vendor-zod-BRyQdbC-.js";
6
+ import "node:async_hooks";
7
+ import "./vendor-h3-v2-CCobnLY5.js";
8
+ import "./vendor-rou3-3NaGPdI8.js";
9
+ import "./vendor-srvx-BA-baEX9.js";
10
+ import "./vendor-tanstack-router-core-6wywV3KN.js";
11
+ import "./vendor-tanstack-history-C4pKJmkt.js";
12
+ import "./vendor-seroval-dJyC-Zhz.js";
13
+ import "./vendor-seroval-plugins-Pq_U2meB.js";
14
+ import "./vendor-cookie-es-DAoofYiI.js";
15
+ import "node:stream/web";
16
+ import "node:stream";
17
+ import "./vendor-tanstack-start-storage-context-DgH9hIJT.js";
18
+ import "./vendor-tanstack-react-router-XzqpA65A.js";
19
+ import "./vendor-react-DvBrY0qp.js";
20
+ import "./vendor-react-dom-yvMLPM0j.js";
21
+ import "./vendor-isbot-CZ7WjwVs.js";
22
+ import "./vendor-tanstack-react-query-hhHzXAK1.js";
23
+ import "./vendor-tanstack-query-core-PwwTR5ld.js";
24
+ import "./vendor-vercel-analytics-oP8BDp0L.js";
25
+ import "./vendor-radix-ui-react-dropdown-menu-DVxKumY8.js";
26
+ import "./vendor-radix-ui-primitive-B-mNdDrH.js";
27
+ import "./vendor-radix-ui-react-compose-refs-D3qsKVk1.js";
28
+ import "./vendor-radix-ui-react-context-BVoNDLue.js";
29
+ import "./vendor-radix-ui-react-use-controllable-state-C9KpT6DG.js";
30
+ import "./vendor-radix-ui-react-use-layout-effect-1LNLXAjr.js";
31
+ import "./vendor-radix-ui-react-primitive-BeOk3UYa.js";
32
+ import "./vendor-radix-ui-react-menu-CiTMLwjT.js";
33
+ import "./vendor-radix-ui-react-collection-BZ2srfgU.js";
34
+ import "./vendor-radix-ui-react-direction-Dt_WDL1t.js";
35
+ import "./vendor-radix-ui-react-dismissable-layer-CjsuPohV.js";
36
+ import "./vendor-radix-ui-react-use-callback-ref-BynBgohw.js";
37
+ import "./vendor-radix-ui-react-use-escape-keydown-CcYRQ2pp.js";
38
+ import "./vendor-radix-ui-react-focus-guards-D_6NoePE.js";
39
+ import "./vendor-radix-ui-react-focus-scope-DEIhTJJH.js";
40
+ import "./vendor-radix-ui-react-popper-23Ye2Vyc.js";
41
+ import "./vendor-floating-ui-react-dom-CRG6gBpH.js";
42
+ import "./vendor-floating-ui-dom-C-cPtgJv.js";
43
+ import "./vendor-floating-ui-core-3tkK0THV.js";
44
+ import "./vendor-floating-ui-utils-DmXANH-E.js";
45
+ import "./vendor-radix-ui-react-arrow-B882lnFK.js";
46
+ import "./vendor-radix-ui-react-use-size-D6fiKJQo.js";
47
+ import "./vendor-radix-ui-react-portal-CZCH5uPk.js";
48
+ import "./vendor-radix-ui-react-presence-CaAULlDU.js";
49
+ import "./vendor-radix-ui-react-roving-focus-DES9GR8l.js";
50
+ import "./vendor-radix-ui-react-id-DFFpgh6m.js";
51
+ import "./vendor-aria-hidden-DPa16MWu.js";
52
+ import "./vendor-react-remove-scroll-BNtiEvVN.js";
53
+ import "./vendor-tslib-_8ICaZ64.js";
54
+ import "./vendor-react-remove-scroll-bar-hLqRASRk.js";
55
+ import "./vendor-react-style-singleton-BXjcXskB.js";
56
+ import "./vendor-get-nonce-DiSj3EHl.js";
57
+ import "./vendor-use-sidecar-DG1tHua4.js";
58
+ import "./vendor-use-callback-ref-DMFDRvmi.js";
59
+ import "./vendor-clsx-DgYk2OaC.js";
60
+ import "./vendor-tailwind-merge-BHb_obmC.js";
61
+ import "./vendor-lucide-react-Ddew6HYb.js";
62
+ import "./vendor-radix-ui-react-avatar-BVgZt2Ab.js";
63
+ import "./vendor-radix-ui-react-slot-DUhZbzoH.js";
64
+ import "./vendor-radix-ui-react-use-is-hydrated-D_LcBPXY.js";
65
+ import "./vendor-use-sync-external-store-rZ8vi0It.js";
66
+ import "./vendor-class-variance-authority-0YxJPB9Y.js";
67
+ import "./vendor-radix-ui-react-dialog-DlxMaNYK.js";
68
+ import "./vendor-framer-motion-X4zAkX3J.js";
69
+ import "./vendor-motion-dom-D2MTwGIG.js";
70
+ import "./vendor-motion-utils-LJlIFN6m.js";
71
+ import "./vendor-sonner-CqbjhsRh.js";
72
+ import "./vendor-supabase-postgrest-js-AO-BXa7I.js";
73
+ import "./vendor-supabase-realtime-js-BtdNgJbm.js";
74
+ import "./vendor-supabase-phoenix-Bw3Uh2Nn.js";
75
+ import "./vendor-supabase-storage-js-Dk_MrPYO.js";
76
+ import "./vendor-iceberg-js-bHCkXyJn.js";
77
+ import "./vendor-supabase-auth-js-D4xjVprw.js";
78
+ import "./vendor-supabase-functions-js-sWy4UYn1.js";
79
+ function createSupabaseAdminClient() {
80
+ const SUPABASE_URL = process.env.SUPABASE_URL;
81
+ const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
82
+ if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
83
+ const missing = [
84
+ ...!SUPABASE_URL ? ["SUPABASE_URL"] : [],
85
+ ...!SUPABASE_SERVICE_ROLE_KEY ? ["SUPABASE_SERVICE_ROLE_KEY"] : []
86
+ ];
87
+ const message = `Missing Supabase environment variable(s): ${missing.join(", ")}. Connect Supabase in Lovable Cloud.`;
88
+ console.error(`[Supabase] ${message}`);
89
+ throw new Error(message);
90
+ }
91
+ return createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
92
+ auth: {
93
+ storage: void 0,
94
+ persistSession: false,
95
+ autoRefreshToken: false
96
+ }
97
+ });
98
+ }
99
+ let _supabaseAdmin;
100
+ const supabaseAdmin = new Proxy({}, {
101
+ get(_, prop, receiver) {
102
+ if (!_supabaseAdmin) _supabaseAdmin = createSupabaseAdminClient();
103
+ return Reflect.get(_supabaseAdmin, prop, receiver);
104
+ }
105
+ });
106
+ const MASTER_ADMIN_ID = "doraexplora";
107
+ const FETCH_TIMEOUT_MS = 12e3;
108
+ async function getAdminRole(supabase, userId) {
109
+ const {
110
+ data
111
+ } = await supabase.from("user_roles").select("admin_id").eq("user_id", userId).eq("role", "admin").maybeSingle();
112
+ return data;
113
+ }
114
+ async function requireAdmin(supabase, userId) {
115
+ const role = await getAdminRole(supabase, userId);
116
+ if (!role) throw new Error("Forbidden");
117
+ return role.admin_id;
118
+ }
119
+ async function findAuthUserByEmail(email) {
120
+ const normalizedEmail = email.trim().toLowerCase();
121
+ const {
122
+ data,
123
+ error
124
+ } = await supabaseAdmin.auth.admin.listUsers({
125
+ perPage: 1e3
126
+ });
127
+ if (error) throw new Error(error.message);
128
+ const user = data.users.find((candidate) => candidate.email?.toLowerCase() === normalizedEmail);
129
+ return user ?? null;
130
+ }
131
+ function normalizeUrl(value) {
132
+ const trimmed = value.trim();
133
+ if (!trimmed) return trimmed;
134
+ if (trimmed.startsWith("//")) return `https:${trimmed}`;
135
+ return trimmed;
136
+ }
137
+ function getHostnameLabel(input) {
138
+ try {
139
+ return new URL(input).hostname.replace(/^www\./, "");
140
+ } catch {
141
+ return null;
142
+ }
143
+ }
144
+ function safeText(value) {
145
+ const text = value?.replace(/\s+/g, " ").trim();
146
+ return text ? text : null;
147
+ }
148
+ function firstMatch(html, patterns) {
149
+ for (const pattern of patterns) {
150
+ const match = html.match(pattern);
151
+ if (match?.[1]) return safeText(match[1]);
152
+ }
153
+ return null;
154
+ }
155
+ function extractMetaContent(html, key) {
156
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
157
+ return firstMatch(html, [new RegExp(`<meta[^>]+property=["']${escaped}["'][^>]+content=["']([^"']+)["'][^>]*>`, "i"), new RegExp(`<meta[^>]+name=["']${escaped}["'][^>]+content=["']([^"']+)["'][^>]*>`, "i"), new RegExp(`<meta[^>]+content=["']([^"']+)["'][^>]+property=["']${escaped}["'][^>]*>`, "i"), new RegExp(`<meta[^>]+content=["']([^"']+)["'][^>]+name=["']${escaped}["'][^>]*>`, "i")]);
158
+ }
159
+ function extractJsonLdObjects(html) {
160
+ const matches = [...html.matchAll(/<script[^>]+type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi)];
161
+ const parsed = [];
162
+ for (const match of matches) {
163
+ const raw = safeText(match[1]);
164
+ if (!raw) continue;
165
+ try {
166
+ const json = JSON.parse(raw);
167
+ if (Array.isArray(json)) parsed.push(...json);
168
+ else parsed.push(json);
169
+ } catch {
170
+ continue;
171
+ }
172
+ }
173
+ return parsed;
174
+ }
175
+ function pickJsonLdProduct(html) {
176
+ const objects = extractJsonLdObjects(html);
177
+ for (const object of objects) {
178
+ if (!object || typeof object !== "object") continue;
179
+ const candidate = object;
180
+ const type = candidate["@type"];
181
+ if (type === "Product") return candidate;
182
+ if (Array.isArray(type) && type.includes("Product")) return candidate;
183
+ }
184
+ return null;
185
+ }
186
+ function toNumber(value) {
187
+ if (typeof value === "number" && Number.isFinite(value)) return value;
188
+ if (typeof value === "string") {
189
+ const parsed = Number(value.replace(/[^\d.-]/g, ""));
190
+ return Number.isFinite(parsed) ? parsed : null;
191
+ }
192
+ return null;
193
+ }
194
+ function extractProductPreview(url, html) {
195
+ const hostname = getHostnameLabel(url);
196
+ const jsonLd = pickJsonLdProduct(html);
197
+ const title = safeText(jsonLd?.name ?? void 0) || extractMetaContent(html, "og:title") || extractMetaContent(html, "twitter:title") || firstMatch(html, [/<title[^>]*>([\s\S]*?)<\/title>/i]) || hostname || "Imported product";
198
+ const description = safeText(jsonLd?.description ?? void 0) || extractMetaContent(html, "og:description") || extractMetaContent(html, "twitter:description") || extractMetaContent(html, "description");
199
+ const imageFromJsonLd = jsonLd?.image;
200
+ const image_url = (Array.isArray(imageFromJsonLd) ? safeText(imageFromJsonLd[0]) : safeText(imageFromJsonLd)) || extractMetaContent(html, "og:image") || extractMetaContent(html, "twitter:image") || extractMetaContent(html, "twitter:image:src") || "https://images.unsplash.com/photo-1558862107-d49ef2a04d72?auto=format&fit=crop&w=1200&q=80";
201
+ const offers = jsonLd?.offers;
202
+ const offer = Array.isArray(offers) ? offers[0] : offers;
203
+ const price = toNumber(offer?.price) ?? toNumber(extractMetaContent(html, "product:price:amount")) ?? toNumber(extractMetaContent(html, "price")) ?? 0;
204
+ const originalPrice = toNumber(extractMetaContent(html, "product:original_price")) ?? toNumber(extractMetaContent(html, "og:price:amount")) ?? null;
205
+ const currency = safeText(offer?.priceCurrency) || extractMetaContent(html, "product:price:currency") || "USD";
206
+ const merchant = safeText(jsonLd?.brand?.name) || safeText(jsonLd?.seller?.name) || hostname;
207
+ const aggregateRating = jsonLd?.aggregateRating;
208
+ const ratingValue = toNumber(aggregateRating?.ratingValue);
209
+ const ratingCount = toNumber(aggregateRating?.ratingCount) ?? toNumber(aggregateRating?.reviewCount);
210
+ const badges = [ratingValue ? `${ratingValue.toFixed(1)}★` : null, ratingCount ? `${Math.round(ratingCount)} reviews` : null].filter(Boolean);
211
+ const imported_from = hostname;
212
+ const notes = `Imported from ${hostname ?? "shared link"}`;
213
+ return {
214
+ title,
215
+ description,
216
+ image_url,
217
+ price,
218
+ original_price: originalPrice,
219
+ currency,
220
+ merchant,
221
+ product_url: url,
222
+ source_url: url,
223
+ tracking_url: url,
224
+ imported_from,
225
+ tags: hostname ? [hostname.split(".")[0]] : [],
226
+ badges,
227
+ shipping_info: null,
228
+ delivery_estimate: null,
229
+ import_notes: notes
230
+ };
231
+ }
232
+ async function fetchImportHtml(url) {
233
+ const controller = new AbortController();
234
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
235
+ try {
236
+ const response = await fetch(url, {
237
+ headers: {
238
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Safari/537.36",
239
+ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
240
+ },
241
+ signal: controller.signal
242
+ });
243
+ if (!response.ok) {
244
+ throw new Error(`Import failed with status ${response.status}`);
245
+ }
246
+ const contentType = response.headers.get("content-type") ?? "";
247
+ if (!contentType.includes("text/html") && !contentType.includes("application/xhtml+xml")) {
248
+ throw new Error("The provided link does not look like a product page");
249
+ }
250
+ return await response.text();
251
+ } finally {
252
+ clearTimeout(timeout);
253
+ }
254
+ }
255
+ const isAdmin_createServerFn_handler = createServerRpc({
256
+ id: "f56374ba3aaffab4ed8ab7e2a3691b799933caea50cc55628ceb0dfe711b588b",
257
+ name: "isAdmin",
258
+ filename: "src/lib/admin.functions.ts"
259
+ }, (opts) => isAdmin.__executeServer(opts));
260
+ const isAdmin = createServerFn({
261
+ method: "GET"
262
+ }).middleware([requireSupabaseAuth]).handler(isAdmin_createServerFn_handler, async ({
263
+ context
264
+ }) => {
265
+ const {
266
+ supabase,
267
+ userId
268
+ } = context;
269
+ const role = await getAdminRole(supabase, userId);
270
+ return {
271
+ admin: !!role,
272
+ admin_id: role?.admin_id ?? null,
273
+ is_master: role?.admin_id === MASTER_ADMIN_ID
274
+ };
275
+ });
276
+ const getAdminBootstrapStatus_createServerFn_handler = createServerRpc({
277
+ id: "3ce88ecd9b40619039a92eb9befb2a1baa534430c56c7c035dc6cc7fb6ea3320",
278
+ name: "getAdminBootstrapStatus",
279
+ filename: "src/lib/admin.functions.ts"
280
+ }, (opts) => getAdminBootstrapStatus.__executeServer(opts));
281
+ const getAdminBootstrapStatus = createServerFn({
282
+ method: "GET"
283
+ }).handler(getAdminBootstrapStatus_createServerFn_handler, async () => {
284
+ const {
285
+ count,
286
+ error
287
+ } = await supabaseAdmin.from("user_roles").select("*", {
288
+ count: "exact",
289
+ head: true
290
+ }).eq("role", "admin");
291
+ if (error) throw new Error(error.message);
292
+ return {
293
+ needs_bootstrap: (count ?? 0) === 0
294
+ };
295
+ });
296
+ const bootstrapMasterAdmin_createServerFn_handler = createServerRpc({
297
+ id: "f228903e5a9f497053d1e0541c339d13437987d304e8fca9781a3a4b7021da29",
298
+ name: "bootstrapMasterAdmin",
299
+ filename: "src/lib/admin.functions.ts"
300
+ }, (opts) => bootstrapMasterAdmin.__executeServer(opts));
301
+ const bootstrapMasterAdmin = createServerFn({
302
+ method: "POST"
303
+ }).inputValidator((d) => objectType({
304
+ email: stringType().email().max(255),
305
+ password: stringType().min(8).max(128)
306
+ }).parse(d)).handler(bootstrapMasterAdmin_createServerFn_handler, async ({
307
+ data
308
+ }) => {
309
+ const {
310
+ count,
311
+ error: countError
312
+ } = await supabaseAdmin.from("user_roles").select("*", {
313
+ count: "exact",
314
+ head: true
315
+ }).eq("role", "admin");
316
+ if (countError) throw new Error(countError.message);
317
+ if ((count ?? 0) > 0) {
318
+ throw new Error("Master Admin is already set up.");
319
+ }
320
+ const existingUser = await findAuthUserByEmail(data.email);
321
+ let userId = existingUser?.id;
322
+ let createdUser = false;
323
+ if (!userId) {
324
+ const {
325
+ data: created,
326
+ error: createError
327
+ } = await supabaseAdmin.auth.admin.createUser({
328
+ email: data.email,
329
+ password: data.password,
330
+ email_confirm: true
331
+ });
332
+ if (createError || !created.user) {
333
+ throw new Error(createError?.message ?? "Failed to create master admin account");
334
+ }
335
+ userId = created.user.id;
336
+ createdUser = true;
337
+ }
338
+ const {
339
+ error: roleError
340
+ } = await supabaseAdmin.from("user_roles").insert({
341
+ user_id: userId,
342
+ role: "admin",
343
+ admin_id: MASTER_ADMIN_ID
344
+ });
345
+ if (roleError) {
346
+ if (createdUser) {
347
+ await supabaseAdmin.auth.admin.deleteUser(userId);
348
+ }
349
+ throw new Error(roleError.message);
350
+ }
351
+ return {
352
+ ok: true,
353
+ user_id: userId,
354
+ admin_id: MASTER_ADMIN_ID,
355
+ created_user: createdUser
356
+ };
357
+ });
358
+ const importProductFromLink_createServerFn_handler = createServerRpc({
359
+ id: "89e33d850036f54ba22d80a5c340288b7904337506fd94deacc6372a910c3cac",
360
+ name: "importProductFromLink",
361
+ filename: "src/lib/admin.functions.ts"
362
+ }, (opts) => importProductFromLink.__executeServer(opts));
363
+ const importProductFromLink = createServerFn({
364
+ method: "POST"
365
+ }).middleware([requireSupabaseAuth]).inputValidator((d) => objectType({
366
+ url: stringType().url().max(2e3)
367
+ }).parse(d)).handler(importProductFromLink_createServerFn_handler, async ({
368
+ data,
369
+ context
370
+ }) => {
371
+ await requireAdmin(context.supabase, context.userId);
372
+ const url = normalizeUrl(data.url);
373
+ const html = await fetchImportHtml(url);
374
+ return extractProductPreview(url, html);
375
+ });
376
+ const upsertProduct_createServerFn_handler = createServerRpc({
377
+ id: "87057b699c92d5e9cc4f021e767a44009606525481c8a27886c5fc0375dc6625",
378
+ name: "upsertProduct",
379
+ filename: "src/lib/admin.functions.ts"
380
+ }, (opts) => upsertProduct.__executeServer(opts));
381
+ const upsertProduct = createServerFn({
382
+ method: "POST"
383
+ }).middleware([requireSupabaseAuth]).inputValidator((d) => productSchema.parse(d)).handler(upsertProduct_createServerFn_handler, async ({
384
+ data,
385
+ context
386
+ }) => {
387
+ await requireAdmin(context.supabase, context.userId);
388
+ const product_url = normalizeUrl(data.product_url ?? data.source_url ?? data.tracking_url ?? data.affiliate_url ?? "");
389
+ const source_url = normalizeUrl(data.source_url ?? data.product_url ?? data.affiliate_url ?? product_url);
390
+ const tracking_url = normalizeUrl(data.tracking_url ?? data.affiliate_url ?? product_url);
391
+ const affiliate_url = normalizeUrl(data.affiliate_url ?? tracking_url ?? product_url);
392
+ const payload = {
393
+ ...data,
394
+ product_url,
395
+ source_url,
396
+ tracking_url,
397
+ affiliate_url,
398
+ imported_from: data.imported_from ?? getHostnameLabel(source_url ?? product_url),
399
+ import_notes: data.import_notes ?? null
400
+ };
401
+ if (payload.id) {
402
+ const {
403
+ error: error2
404
+ } = await context.supabase.from("products").update(payload).eq("id", payload.id);
405
+ if (error2) throw new Error(error2.message);
406
+ return {
407
+ id: payload.id
408
+ };
409
+ }
410
+ const {
411
+ data: ins,
412
+ error
413
+ } = await context.supabase.from("products").insert(payload).select("id").single();
414
+ if (error) throw new Error(error.message);
415
+ return {
416
+ id: ins.id
417
+ };
418
+ });
419
+ const deleteProduct_createServerFn_handler = createServerRpc({
420
+ id: "d58e9647e4364d7098cb0d840b98a827719a64c5b316ad80080e28b97fb3f1cb",
421
+ name: "deleteProduct",
422
+ filename: "src/lib/admin.functions.ts"
423
+ }, (opts) => deleteProduct.__executeServer(opts));
424
+ const deleteProduct = createServerFn({
425
+ method: "POST"
426
+ }).middleware([requireSupabaseAuth]).inputValidator((d) => objectType({
427
+ id: stringType().uuid()
428
+ }).parse(d)).handler(deleteProduct_createServerFn_handler, async ({
429
+ data,
430
+ context
431
+ }) => {
432
+ await requireAdmin(context.supabase, context.userId);
433
+ const {
434
+ error
435
+ } = await context.supabase.from("products").delete().eq("id", data.id);
436
+ if (error) throw new Error(error.message);
437
+ return {
438
+ ok: true
439
+ };
440
+ });
441
+ const listAllProducts_createServerFn_handler = createServerRpc({
442
+ id: "8db3a7d2924568f7f51e14d9d73d2a96f312b0d2adb7276fdd08fe90dcf12de3",
443
+ name: "listAllProducts",
444
+ filename: "src/lib/admin.functions.ts"
445
+ }, (opts) => listAllProducts.__executeServer(opts));
446
+ const listAllProducts = createServerFn({
447
+ method: "GET"
448
+ }).middleware([requireSupabaseAuth]).handler(listAllProducts_createServerFn_handler, async ({
449
+ context
450
+ }) => {
451
+ await requireAdmin(context.supabase, context.userId);
452
+ const {
453
+ data
454
+ } = await context.supabase.from("products").select("*").order("created_at", {
455
+ ascending: false
456
+ });
457
+ return data ?? [];
458
+ });
459
+ const productSchema = objectType({
460
+ id: stringType().uuid().optional(),
461
+ title: stringType().min(1).max(200),
462
+ description: stringType().max(2e3).optional().nullable(),
463
+ image_url: stringType().url().max(2e3),
464
+ price: numberType().min(0).max(1e5),
465
+ original_price: numberType().min(0).max(1e5).optional().nullable(),
466
+ currency: stringType().min(1).max(12).default("USD"),
467
+ affiliate_url: stringType().url().max(2e3).optional().nullable(),
468
+ product_url: stringType().url().max(2e3).optional().nullable(),
469
+ tracking_url: stringType().url().max(2e3).optional().nullable(),
470
+ source_url: stringType().url().max(2e3).optional().nullable(),
471
+ imported_from: stringType().max(120).optional().nullable(),
472
+ import_notes: stringType().max(500).optional().nullable(),
473
+ merchant: stringType().max(100).optional().nullable(),
474
+ category_id: stringType().uuid().optional().nullable(),
475
+ tags: arrayType(stringType().max(40)).max(20).default([]),
476
+ badges: arrayType(stringType().max(40)).max(10).default([]),
477
+ is_trending: booleanType().default(false),
478
+ is_hot: booleanType().default(false),
479
+ is_featured: booleanType().default(false),
480
+ shipping_info: stringType().max(120).optional().nullable(),
481
+ delivery_estimate: stringType().max(60).optional().nullable()
482
+ }).superRefine((value, ctx) => {
483
+ if (!value.product_url && !value.source_url && !value.tracking_url && !value.affiliate_url) {
484
+ ctx.addIssue({
485
+ code: ZodIssueCode.custom,
486
+ path: ["product_url"],
487
+ message: "Provide a product URL, source URL, tracking URL, or affiliate URL"
488
+ });
489
+ }
490
+ });
491
+ const grantSelfAdmin_createServerFn_handler = createServerRpc({
492
+ id: "c579e6cf81462f6a2bea1160758f9416a190d3246ad7147937aa785904bea01e",
493
+ name: "grantSelfAdmin",
494
+ filename: "src/lib/admin.functions.ts"
495
+ }, (opts) => grantSelfAdmin.__executeServer(opts));
496
+ const grantSelfAdmin = createServerFn({
497
+ method: "POST"
498
+ }).middleware([requireSupabaseAuth]).handler(grantSelfAdmin_createServerFn_handler, async ({
499
+ context
500
+ }) => {
501
+ const {
502
+ supabase,
503
+ userId
504
+ } = context;
505
+ const {
506
+ count,
507
+ error
508
+ } = await supabase.from("user_roles").select("*", {
509
+ count: "exact",
510
+ head: true
511
+ }).eq("role", "admin");
512
+ if (error) throw new Error(error.message);
513
+ if ((count ?? 0) > 0) throw new Error("Admin already exists. Ask the Master Admin to grant you access.");
514
+ const {
515
+ error: insertError
516
+ } = await supabaseAdmin.from("user_roles").insert({
517
+ user_id: userId,
518
+ role: "admin",
519
+ admin_id: MASTER_ADMIN_ID
520
+ });
521
+ if (insertError) throw new Error(insertError.message);
522
+ return {
523
+ ok: true,
524
+ admin_id: MASTER_ADMIN_ID
525
+ };
526
+ });
527
+ const createAdmin_createServerFn_handler = createServerRpc({
528
+ id: "36d868d9acaba43916ce260adef4026deeafe7052311a1a61a689052f8d2a6a5",
529
+ name: "createAdmin",
530
+ filename: "src/lib/admin.functions.ts"
531
+ }, (opts) => createAdmin.__executeServer(opts));
532
+ const createAdmin = createServerFn({
533
+ method: "POST"
534
+ }).middleware([requireSupabaseAuth]).inputValidator((d) => objectType({
535
+ email: stringType().email().max(255),
536
+ password: stringType().min(8).max(128),
537
+ admin_id: stringType().min(3).max(40).regex(/^[a-zA-Z0-9_-]+$/, "Admin ID may only contain letters, numbers, _ and -")
538
+ }).parse(d)).handler(createAdmin_createServerFn_handler, async ({
539
+ data,
540
+ context
541
+ }) => {
542
+ const callerAdminId = await requireAdmin(context.supabase, context.userId);
543
+ if (callerAdminId !== MASTER_ADMIN_ID) throw new Error("Only the Master Admin can create new admins");
544
+ if (data.admin_id === MASTER_ADMIN_ID) throw new Error("That admin ID is reserved");
545
+ const {
546
+ data: existing
547
+ } = await supabaseAdmin.from("user_roles").select("id").eq("admin_id", data.admin_id).maybeSingle();
548
+ if (existing) throw new Error("Admin ID is already taken");
549
+ const {
550
+ data: created,
551
+ error: createErr
552
+ } = await supabaseAdmin.auth.admin.createUser({
553
+ email: data.email,
554
+ password: data.password,
555
+ email_confirm: true
556
+ });
557
+ if (createErr || !created.user) throw new Error(createErr?.message ?? "Failed to create user");
558
+ const newUserId = created.user.id;
559
+ const {
560
+ error: roleErr
561
+ } = await supabaseAdmin.from("user_roles").insert({
562
+ user_id: newUserId,
563
+ role: "admin",
564
+ admin_id: data.admin_id
565
+ });
566
+ if (roleErr) {
567
+ await supabaseAdmin.auth.admin.deleteUser(newUserId);
568
+ throw new Error(roleErr.message);
569
+ }
570
+ return {
571
+ ok: true,
572
+ user_id: newUserId,
573
+ admin_id: data.admin_id
574
+ };
575
+ });
576
+ const listAdmins_createServerFn_handler = createServerRpc({
577
+ id: "1f15f91371ebbf2f3cadc34ffa88e17615477c189c7d20a14989f46b3a531730",
578
+ name: "listAdmins",
579
+ filename: "src/lib/admin.functions.ts"
580
+ }, (opts) => listAdmins.__executeServer(opts));
581
+ const listAdmins = createServerFn({
582
+ method: "GET"
583
+ }).middleware([requireSupabaseAuth]).handler(listAdmins_createServerFn_handler, async ({
584
+ context
585
+ }) => {
586
+ await requireAdmin(context.supabase, context.userId);
587
+ const {
588
+ data: roles
589
+ } = await supabaseAdmin.from("user_roles").select("user_id, admin_id, created_at").eq("role", "admin").order("created_at", {
590
+ ascending: true
591
+ });
592
+ if (!roles?.length) return [];
593
+ const {
594
+ data: users
595
+ } = await supabaseAdmin.auth.admin.listUsers({
596
+ perPage: 1e3
597
+ });
598
+ const emailById = new Map(users.users.map((u) => [u.id, u.email]));
599
+ return roles.map((r) => ({
600
+ user_id: r.user_id,
601
+ admin_id: r.admin_id,
602
+ email: emailById.get(r.user_id) ?? null,
603
+ is_master: r.admin_id === MASTER_ADMIN_ID,
604
+ created_at: r.created_at
605
+ }));
606
+ });
607
+ const verifyAdminId_createServerFn_handler = createServerRpc({
608
+ id: "911c12f56db314b9eea0d9463dda510d0464e04b72b14405d69546cc93ebeb33",
609
+ name: "verifyAdminId",
610
+ filename: "src/lib/admin.functions.ts"
611
+ }, (opts) => verifyAdminId.__executeServer(opts));
612
+ const verifyAdminId = createServerFn({
613
+ method: "POST"
614
+ }).middleware([requireSupabaseAuth]).inputValidator((d) => objectType({
615
+ admin_id: stringType().min(1).max(40)
616
+ }).parse(d)).handler(verifyAdminId_createServerFn_handler, async ({
617
+ data,
618
+ context
619
+ }) => {
620
+ const {
621
+ supabase,
622
+ userId
623
+ } = context;
624
+ const row = await getAdminRole(supabase, userId);
625
+ if (!row || row.admin_id !== data.admin_id) {
626
+ throw new Error("Invalid admin credentials");
627
+ }
628
+ return {
629
+ ok: true,
630
+ is_master: row.admin_id === MASTER_ADMIN_ID
631
+ };
632
+ });
633
+ export {
634
+ bootstrapMasterAdmin_createServerFn_handler,
635
+ createAdmin_createServerFn_handler,
636
+ deleteProduct_createServerFn_handler,
637
+ getAdminBootstrapStatus_createServerFn_handler,
638
+ grantSelfAdmin_createServerFn_handler,
639
+ importProductFromLink_createServerFn_handler,
640
+ isAdmin_createServerFn_handler,
641
+ listAdmins_createServerFn_handler,
642
+ listAllProducts_createServerFn_handler,
643
+ upsertProduct_createServerFn_handler,
644
+ verifyAdminId_createServerFn_handler
645
+ };