@rovela-ai/sdk 0.19.4 → 0.19.6

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 (236) hide show
  1. package/dist/admin/components/AdminPageHeader.d.ts.map +1 -1
  2. package/dist/admin/components/AdminPageHeader.js +9 -2
  3. package/dist/admin/components/AdminPageHeader.js.map +1 -1
  4. package/dist/admin/components/AdminUserMenu.d.ts.map +1 -1
  5. package/dist/admin/components/AdminUserMenu.js +2 -1
  6. package/dist/admin/components/AdminUserMenu.js.map +1 -1
  7. package/dist/admin/components/CustomerDetails.d.ts.map +1 -1
  8. package/dist/admin/components/CustomerDetails.js +2 -1
  9. package/dist/admin/components/CustomerDetails.js.map +1 -1
  10. package/dist/admin/components/EmailsManager.d.ts.map +1 -1
  11. package/dist/admin/components/EmailsManager.js +2 -1
  12. package/dist/admin/components/EmailsManager.js.map +1 -1
  13. package/dist/admin/components/LowStockAlert.d.ts.map +1 -1
  14. package/dist/admin/components/LowStockAlert.js +3 -2
  15. package/dist/admin/components/LowStockAlert.js.map +1 -1
  16. package/dist/admin/components/OrderDetails.d.ts.map +1 -1
  17. package/dist/admin/components/OrderDetails.js +2 -1
  18. package/dist/admin/components/OrderDetails.js.map +1 -1
  19. package/dist/admin/components/ProductTable.d.ts.map +1 -1
  20. package/dist/admin/components/ProductTable.js +4 -3
  21. package/dist/admin/components/ProductTable.js.map +1 -1
  22. package/dist/admin/components/RecentOrders.d.ts.map +1 -1
  23. package/dist/admin/components/RecentOrders.js +2 -1
  24. package/dist/admin/components/RecentOrders.js.map +1 -1
  25. package/dist/admin/components/SEOPreview.d.ts +2 -8
  26. package/dist/admin/components/SEOPreview.d.ts.map +1 -1
  27. package/dist/admin/components/SEOPreview.js +32 -5
  28. package/dist/admin/components/SEOPreview.js.map +1 -1
  29. package/dist/admin/components/SecondaryMetricsRow.d.ts.map +1 -1
  30. package/dist/admin/components/SecondaryMetricsRow.js +3 -2
  31. package/dist/admin/components/SecondaryMetricsRow.js.map +1 -1
  32. package/dist/admin/components/StatsCards.d.ts.map +1 -1
  33. package/dist/admin/components/StatsCards.js +2 -1
  34. package/dist/admin/components/StatsCards.js.map +1 -1
  35. package/docs/changelog/README.md +53 -0
  36. package/docs/changelog/epoch-01-chrome-consent.md +63 -0
  37. package/docs/changelog/epoch-02-platform-commerce.md +108 -0
  38. package/docs/changelog/epoch-03-i18n-files.md +72 -0
  39. package/docs/changelog/epoch-04-emails.md +65 -0
  40. package/docs/changelog/epoch-05-admin-experience.md +98 -0
  41. package/docs/changelog/epoch-06-mobile-integrity.md +92 -0
  42. package/docs/design/admin-ledger-visual-universe.html +1961 -0
  43. package/docs/design/admin-sidebar-and-band.html +542 -0
  44. package/package.json +3 -1
  45. package/templates/store-template/.claude/skills/add-section/SKILL.md +438 -0
  46. package/templates/store-template/.claude/skills/build-feature/SKILL.md +201 -0
  47. package/templates/store-template/.claude/skills/customize-theme/SKILL.md +167 -0
  48. package/templates/store-template/.claude/skills/debug-errors/SKILL.md +68 -0
  49. package/templates/store-template/.claude/skills/frontend-design/SKILL.md +176 -0
  50. package/templates/store-template/.claude/skills/generate-images/SKILL.md +115 -0
  51. package/templates/store-template/.claude/skills/manage-products/SKILL.md +187 -0
  52. package/templates/store-template/.claude/skills/override-sdk-component/SKILL.md +154 -0
  53. package/templates/store-template/.env.example +50 -0
  54. package/templates/store-template/.mcp.json +8 -0
  55. package/templates/store-template/.rovela/blueprint.example.json +190 -0
  56. package/templates/store-template/CLAUDE.md +14 -0
  57. package/templates/store-template/app/LayoutContent.tsx +106 -0
  58. package/templates/store-template/app/[...path]/page.tsx +79 -0
  59. package/templates/store-template/app/account/addresses/page.tsx +45 -0
  60. package/templates/store-template/app/account/layout.tsx +17 -0
  61. package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +277 -0
  62. package/templates/store-template/app/account/orders/[id]/page.tsx +725 -0
  63. package/templates/store-template/app/account/orders/page.tsx +153 -0
  64. package/templates/store-template/app/account/page.tsx +184 -0
  65. package/templates/store-template/app/account/profile/page.tsx +434 -0
  66. package/templates/store-template/app/admin/(dashboard)/account/page.tsx +16 -0
  67. package/templates/store-template/app/admin/(dashboard)/analytics/events/page.tsx +14 -0
  68. package/templates/store-template/app/admin/(dashboard)/analytics/layout.tsx +48 -0
  69. package/templates/store-template/app/admin/(dashboard)/analytics/page.tsx +15 -0
  70. package/templates/store-template/app/admin/(dashboard)/analytics/visitors/page.tsx +14 -0
  71. package/templates/store-template/app/admin/(dashboard)/categories/[id]/page.tsx +38 -0
  72. package/templates/store-template/app/admin/(dashboard)/categories/new/page.tsx +35 -0
  73. package/templates/store-template/app/admin/(dashboard)/categories/page.tsx +223 -0
  74. package/templates/store-template/app/admin/(dashboard)/customers/[id]/page.tsx +26 -0
  75. package/templates/store-template/app/admin/(dashboard)/customers/page.tsx +33 -0
  76. package/templates/store-template/app/admin/(dashboard)/discounts/page.tsx +16 -0
  77. package/templates/store-template/app/admin/(dashboard)/emails/page.tsx +16 -0
  78. package/templates/store-template/app/admin/(dashboard)/files/page.tsx +16 -0
  79. package/templates/store-template/app/admin/(dashboard)/layout.tsx +44 -0
  80. package/templates/store-template/app/admin/(dashboard)/loading.tsx +88 -0
  81. package/templates/store-template/app/admin/(dashboard)/locations/page.tsx +16 -0
  82. package/templates/store-template/app/admin/(dashboard)/orders/[id]/page.tsx +66 -0
  83. package/templates/store-template/app/admin/(dashboard)/orders/page.tsx +26 -0
  84. package/templates/store-template/app/admin/(dashboard)/page.tsx +146 -0
  85. package/templates/store-template/app/admin/(dashboard)/payments/page.tsx +15 -0
  86. package/templates/store-template/app/admin/(dashboard)/products/[id]/page.tsx +38 -0
  87. package/templates/store-template/app/admin/(dashboard)/products/new/page.tsx +35 -0
  88. package/templates/store-template/app/admin/(dashboard)/products/page.tsx +31 -0
  89. package/templates/store-template/app/admin/(dashboard)/settings/page.tsx +46 -0
  90. package/templates/store-template/app/admin/(dashboard)/shipping/page.tsx +15 -0
  91. package/templates/store-template/app/admin/(dashboard)/tax/page.tsx +15 -0
  92. package/templates/store-template/app/admin/(dashboard)/users/[id]/page.tsx +114 -0
  93. package/templates/store-template/app/admin/(dashboard)/users/page.tsx +16 -0
  94. package/templates/store-template/app/admin/accept-invite/page.tsx +36 -0
  95. package/templates/store-template/app/admin/forgot-password/page.tsx +13 -0
  96. package/templates/store-template/app/admin/layout.tsx +47 -0
  97. package/templates/store-template/app/admin/login/page.tsx +528 -0
  98. package/templates/store-template/app/admin/reset-password/page.tsx +36 -0
  99. package/templates/store-template/app/api/account/addresses/[id]/route.ts +10 -0
  100. package/templates/store-template/app/api/account/addresses/route.ts +10 -0
  101. package/templates/store-template/app/api/account/change-password/route.ts +107 -0
  102. package/templates/store-template/app/api/account/orders/[id]/refund/route.ts +11 -0
  103. package/templates/store-template/app/api/account/orders/[id]/return/route.ts +14 -0
  104. package/templates/store-template/app/api/account/orders/[id]/route.ts +42 -0
  105. package/templates/store-template/app/api/account/orders/route.ts +29 -0
  106. package/templates/store-template/app/api/account/profile/route.ts +165 -0
  107. package/templates/store-template/app/api/admin/accept-invite/route.ts +11 -0
  108. package/templates/store-template/app/api/admin/analytics/events/route.ts +9 -0
  109. package/templates/store-template/app/api/admin/analytics/route.ts +10 -0
  110. package/templates/store-template/app/api/admin/analytics/visitors/route.ts +9 -0
  111. package/templates/store-template/app/api/admin/branding/favicon/route.ts +9 -0
  112. package/templates/store-template/app/api/admin/branding/logo/route.ts +9 -0
  113. package/templates/store-template/app/api/admin/categories/[id]/route.ts +9 -0
  114. package/templates/store-template/app/api/admin/categories/route.ts +9 -0
  115. package/templates/store-template/app/api/admin/check/route.ts +10 -0
  116. package/templates/store-template/app/api/admin/customer-groups/[id]/route.ts +10 -0
  117. package/templates/store-template/app/api/admin/customer-groups/route.ts +10 -0
  118. package/templates/store-template/app/api/admin/customers/[id]/addresses/[addressId]/route.ts +15 -0
  119. package/templates/store-template/app/api/admin/customers/[id]/addresses/route.ts +15 -0
  120. package/templates/store-template/app/api/admin/customers/[id]/route.ts +11 -0
  121. package/templates/store-template/app/api/admin/customers/bulk/route.ts +8 -0
  122. package/templates/store-template/app/api/admin/customers/route.ts +9 -0
  123. package/templates/store-template/app/api/admin/discounts/[id]/route.ts +11 -0
  124. package/templates/store-template/app/api/admin/discounts/route.ts +10 -0
  125. package/templates/store-template/app/api/admin/emails/preview/route.ts +4 -0
  126. package/templates/store-template/app/api/admin/emails/route.ts +5 -0
  127. package/templates/store-template/app/api/admin/emails/test/route.ts +4 -0
  128. package/templates/store-template/app/api/admin/files/route.ts +8 -0
  129. package/templates/store-template/app/api/admin/forgot-password/route.ts +7 -0
  130. package/templates/store-template/app/api/admin/linked-customer/route.ts +11 -0
  131. package/templates/store-template/app/api/admin/locations/[id]/route.ts +10 -0
  132. package/templates/store-template/app/api/admin/locations/route.ts +10 -0
  133. package/templates/store-template/app/api/admin/me/password/route.ts +13 -0
  134. package/templates/store-template/app/api/admin/me/route.ts +11 -0
  135. package/templates/store-template/app/api/admin/orders/[id]/refund/route.ts +7 -0
  136. package/templates/store-template/app/api/admin/orders/[id]/return/approve/route.ts +7 -0
  137. package/templates/store-template/app/api/admin/orders/[id]/return/reject/route.ts +7 -0
  138. package/templates/store-template/app/api/admin/orders/[id]/route.ts +9 -0
  139. package/templates/store-template/app/api/admin/orders/[id]/ship-with-shippo/route.ts +6 -0
  140. package/templates/store-template/app/api/admin/orders/[id]/shippo-rates/route.ts +6 -0
  141. package/templates/store-template/app/api/admin/orders/bulk/route.ts +8 -0
  142. package/templates/store-template/app/api/admin/orders/route.ts +9 -0
  143. package/templates/store-template/app/api/admin/payment-methods/[id]/route.ts +10 -0
  144. package/templates/store-template/app/api/admin/payment-methods/route.ts +10 -0
  145. package/templates/store-template/app/api/admin/products/[id]/route.ts +9 -0
  146. package/templates/store-template/app/api/admin/products/bulk/route.ts +9 -0
  147. package/templates/store-template/app/api/admin/products/route.ts +9 -0
  148. package/templates/store-template/app/api/admin/products/stats/route.ts +10 -0
  149. package/templates/store-template/app/api/admin/reset-password/route.ts +10 -0
  150. package/templates/store-template/app/api/admin/settings/route.ts +11 -0
  151. package/templates/store-template/app/api/admin/setup/route.ts +10 -0
  152. package/templates/store-template/app/api/admin/setup-guide/manual-mark/route.ts +13 -0
  153. package/templates/store-template/app/api/admin/setup-guide/route.ts +10 -0
  154. package/templates/store-template/app/api/admin/shipping/carriers/[id]/route.ts +9 -0
  155. package/templates/store-template/app/api/admin/shipping/carriers/route.ts +9 -0
  156. package/templates/store-template/app/api/admin/shipping/rates/[id]/route.ts +9 -0
  157. package/templates/store-template/app/api/admin/shipping/rates/route.ts +9 -0
  158. package/templates/store-template/app/api/admin/shipping/shippo/api-key/route.ts +1 -0
  159. package/templates/store-template/app/api/admin/shipping/shippo/validate/route.ts +1 -0
  160. package/templates/store-template/app/api/admin/shipping/zones/[id]/route.ts +9 -0
  161. package/templates/store-template/app/api/admin/shipping/zones/route.ts +9 -0
  162. package/templates/store-template/app/api/admin/stats/route.ts +9 -0
  163. package/templates/store-template/app/api/admin/stripe-status/route.ts +1 -0
  164. package/templates/store-template/app/api/admin/tax-zones/[id]/route.ts +7 -0
  165. package/templates/store-template/app/api/admin/tax-zones/route.ts +7 -0
  166. package/templates/store-template/app/api/admin/users/[id]/route.ts +14 -0
  167. package/templates/store-template/app/api/admin/users/route.ts +12 -0
  168. package/templates/store-template/app/api/admin-auth/[...nextauth]/route.ts +17 -0
  169. package/templates/store-template/app/api/analytics/track/route.ts +12 -0
  170. package/templates/store-template/app/api/auth/[...nextauth]/route.ts +19 -0
  171. package/templates/store-template/app/api/auth/forgot-password/route.ts +9 -0
  172. package/templates/store-template/app/api/auth/register/route.ts +9 -0
  173. package/templates/store-template/app/api/auth/resend-verification/route.ts +9 -0
  174. package/templates/store-template/app/api/auth/reset-password/route.ts +10 -0
  175. package/templates/store-template/app/api/auth/verify-email/route.ts +10 -0
  176. package/templates/store-template/app/api/categories/route.ts +10 -0
  177. package/templates/store-template/app/api/checkout/countries/route.ts +7 -0
  178. package/templates/store-template/app/api/checkout/discount/route.ts +9 -0
  179. package/templates/store-template/app/api/checkout/manual/route.ts +10 -0
  180. package/templates/store-template/app/api/checkout/payment-methods/route.ts +8 -0
  181. package/templates/store-template/app/api/checkout/pickup-locations/route.ts +8 -0
  182. package/templates/store-template/app/api/checkout/route.ts +10 -0
  183. package/templates/store-template/app/api/checkout/shipping/route.ts +21 -0
  184. package/templates/store-template/app/api/checkout/status/route.ts +10 -0
  185. package/templates/store-template/app/api/contact/route.ts +164 -0
  186. package/templates/store-template/app/api/media/presign/route.ts +7 -0
  187. package/templates/store-template/app/api/media/route.ts +7 -0
  188. package/templates/store-template/app/api/products/[slug]/route.ts +10 -0
  189. package/templates/store-template/app/api/products/route.ts +10 -0
  190. package/templates/store-template/app/api/store/settings/route.ts +12 -0
  191. package/templates/store-template/app/api/webhooks/stripe/route.ts +63 -0
  192. package/templates/store-template/app/auth/forgot-password/page.tsx +38 -0
  193. package/templates/store-template/app/auth/layout.tsx +17 -0
  194. package/templates/store-template/app/auth/reset-password/page.tsx +81 -0
  195. package/templates/store-template/app/auth/signin/page.tsx +62 -0
  196. package/templates/store-template/app/auth/signup/page.tsx +38 -0
  197. package/templates/store-template/app/auth/verify-email/page.tsx +185 -0
  198. package/templates/store-template/app/cart/page.tsx +137 -0
  199. package/templates/store-template/app/checkout/page.tsx +88 -0
  200. package/templates/store-template/app/checkout/success/page.tsx +50 -0
  201. package/templates/store-template/app/contact/layout.tsx +24 -0
  202. package/templates/store-template/app/contact/page.tsx +321 -0
  203. package/templates/store-template/app/faq/page.tsx +153 -0
  204. package/templates/store-template/app/globals.css +99 -0
  205. package/templates/store-template/app/layout.tsx +269 -0
  206. package/templates/store-template/app/not-found.tsx +35 -0
  207. package/templates/store-template/app/page.tsx +23 -0
  208. package/templates/store-template/app/privacy/page.tsx +281 -0
  209. package/templates/store-template/app/products/[slug]/ProductDetailClient.tsx +179 -0
  210. package/templates/store-template/app/products/[slug]/page.tsx +149 -0
  211. package/templates/store-template/app/products/layout.tsx +26 -0
  212. package/templates/store-template/app/products/page.tsx +102 -0
  213. package/templates/store-template/app/robots.ts +25 -0
  214. package/templates/store-template/app/sitemap.ts +76 -0
  215. package/templates/store-template/app/terms/page.tsx +313 -0
  216. package/templates/store-template/components/PathSyncBridge.tsx +61 -0
  217. package/templates/store-template/components/Providers.tsx +37 -0
  218. package/templates/store-template/components/layout/Footer.tsx +150 -0
  219. package/templates/store-template/components/layout/Header.tsx +162 -0
  220. package/templates/store-template/components/sections/.gitkeep +7 -0
  221. package/templates/store-template/components/sections/CTA.tsx +51 -0
  222. package/templates/store-template/components/sections/Features.tsx +91 -0
  223. package/templates/store-template/components/sections/Hero.tsx +85 -0
  224. package/templates/store-template/eslint.config.mjs +18 -0
  225. package/templates/store-template/lib/store-config.ts +77 -0
  226. package/templates/store-template/lib/store-policy.ts +68 -0
  227. package/templates/store-template/lib/utils.ts +21 -0
  228. package/templates/store-template/next-env.d.ts +6 -0
  229. package/templates/store-template/next.config.js +105 -0
  230. package/templates/store-template/package.json +32 -0
  231. package/templates/store-template/postcss.config.js +6 -0
  232. package/templates/store-template/proxy.ts +150 -0
  233. package/templates/store-template/public/rovela-logo.png +0 -0
  234. package/templates/store-template/tailwind.config.ts +74 -0
  235. package/templates/store-template/tsconfig.json +41 -0
  236. package/templates/store-template/types/next-auth.d.ts +32 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Single Payment Method API Route
3
+ *
4
+ * PUT /api/admin/payment-methods/[id] - Update a method
5
+ * DELETE /api/admin/payment-methods/[id] - Delete a method (order history keeps its label)
6
+ */
7
+
8
+ import { updatePaymentMethodHandler, deletePaymentMethodHandler } from '@rovela-ai/sdk/admin/api'
9
+
10
+ export { updatePaymentMethodHandler as PUT, deletePaymentMethodHandler as DELETE }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Payment Methods API Route
3
+ *
4
+ * GET /api/admin/payment-methods - List all methods
5
+ * POST /api/admin/payment-methods - Create a manual method
6
+ */
7
+
8
+ import { getPaymentMethods, createPaymentMethodHandler } from '@rovela-ai/sdk/admin/api'
9
+
10
+ export { getPaymentMethods as GET, createPaymentMethodHandler as POST }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Single Product API Route
3
+ *
4
+ * GET/PUT/DELETE /api/admin/products/[id]
5
+ */
6
+
7
+ import { getProduct, updateProduct, deleteProduct } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getProduct as GET, updateProduct as PUT, deleteProduct as DELETE }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Products Bulk Action API Route
3
+ *
4
+ * POST /api/admin/products/bulk
5
+ *
6
+ * Body: { ids: string[], action: 'activate' | 'archive' | 'delete' }
7
+ */
8
+
9
+ export { POST } from '@rovela-ai/sdk/admin/api/products-bulk'
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Products API Route
3
+ *
4
+ * GET/POST /api/admin/products - List/Create products
5
+ */
6
+
7
+ import { getProducts, createProduct } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getProducts as GET, createProduct as POST }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Products Metrics API Route
3
+ *
4
+ * GET /api/admin/products/stats
5
+ *
6
+ * Returns: { data: { activeCount, outOfStockCount, bestSeller } }
7
+ * - bestSeller is over the last 30 days, by units sold; null when no sales.
8
+ */
9
+
10
+ export { GET } from '@rovela-ai/sdk/admin/api/products-stats'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Reset Password API Route
3
+ *
4
+ * Thin re-export of the SDK handler.
5
+ *
6
+ * - GET ?token=X → non-destructive token validation (used by the UI on mount)
7
+ * - POST { token, password } → consume the token and update the admin's password
8
+ */
9
+
10
+ export { GET, POST } from '@rovela-ai/sdk/admin/api/reset-password'
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Admin Settings API Route
3
+ *
4
+ * GET /api/admin/settings - Get store settings (with lazy init from blueprint)
5
+ * PUT /api/admin/settings - Update store settings
6
+ */
7
+
8
+ import { getSettings, updateSettings } from '@rovela-ai/sdk/admin/api'
9
+
10
+ export const GET = getSettings
11
+ export const PUT = updateSettings
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Setup API Route
3
+ *
4
+ * First-time admin account creation.
5
+ * Only works when no admins exist for the store.
6
+ */
7
+
8
+ import { POST as handler } from '@rovela-ai/sdk/admin/api/setup'
9
+
10
+ export const POST = handler
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Admin Setup Guide Manual-Mark API Route
3
+ *
4
+ * POST /api/admin/setup-guide/manual-mark
5
+ *
6
+ * Body: { key: 'taxNoneNeeded' | 'legalPagesReviewed' | 'firstProductTouched'
7
+ * | 'logoUploaded' | 'dismiss' | 'reopen', value: boolean }
8
+ *
9
+ * Allowlisted-key writeback to `store_settings.onboarding` JSONB. Auth gate
10
+ * `settings.write`. See SDK §32.
11
+ */
12
+
13
+ export { markSetupTask as POST } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Admin Setup Guide API Route
3
+ *
4
+ * GET /api/admin/setup-guide
5
+ *
6
+ * Returns the 9 setup-guide tasks + per-tier progress for the dashboard
7
+ * card. Auth gate `settings.read`. See SDK §32 for the full spec.
8
+ */
9
+
10
+ export { getSetupGuide as GET } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Single Shipping Carrier API Route
3
+ *
4
+ * GET/PUT/DELETE /api/admin/shipping/carriers/[id]
5
+ */
6
+
7
+ import { getShippingCarrier, updateShippingCarrier, deleteShippingCarrier } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getShippingCarrier as GET, updateShippingCarrier as PUT, deleteShippingCarrier as DELETE }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Shipping Carriers API Route
3
+ *
4
+ * GET/POST /api/admin/shipping/carriers - List/Create shipping carriers
5
+ */
6
+
7
+ import { getShippingCarriers, createShippingCarrier } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getShippingCarriers as GET, createShippingCarrier as POST }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Single Shipping Rate API Route
3
+ *
4
+ * PUT/DELETE /api/admin/shipping/rates/[id]
5
+ */
6
+
7
+ import { updateShippingRate, deleteShippingRate } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { updateShippingRate as PUT, deleteShippingRate as DELETE }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Shipping Rates API Route
3
+ *
4
+ * POST /api/admin/shipping/rates - Create shipping rate
5
+ */
6
+
7
+ import { createShippingRate } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { createShippingRate as POST }
@@ -0,0 +1 @@
1
+ export { saveShippoApiKey as POST, deleteShippoApiKey as DELETE } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1 @@
1
+ export { validateShippoApiKey as POST } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Single Shipping Zone API Route
3
+ *
4
+ * GET/PUT/DELETE /api/admin/shipping/zones/[id]
5
+ */
6
+
7
+ import { getShippingZone, updateShippingZone, deleteShippingZone } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getShippingZone as GET, updateShippingZone as PUT, deleteShippingZone as DELETE }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Shipping Zones API Route
3
+ *
4
+ * GET/POST /api/admin/shipping/zones - List/Create shipping zones
5
+ */
6
+
7
+ import { getShippingZones, createShippingZone } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getShippingZones as GET, createShippingZone as POST }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Admin Stats API Route
3
+ *
4
+ * GET /api/admin/stats - Dashboard metrics
5
+ */
6
+
7
+ import { getStats } from '@rovela-ai/sdk/admin/api'
8
+
9
+ export { getStats as GET }
@@ -0,0 +1 @@
1
+ export { getStripeStatus as GET } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Admin Single Tax Zone API Route
3
+ *
4
+ * GET/PUT/DELETE /api/admin/tax-zones/[id]
5
+ */
6
+
7
+ export { getTaxZone as GET, updateTaxZone as PUT, deleteTaxZone as DELETE } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Admin Tax Zones API Route
3
+ *
4
+ * GET/POST /api/admin/tax-zones - List/Create tax zones
5
+ */
6
+
7
+ export { getTaxZones as GET, createTaxZone as POST } from '@rovela-ai/sdk/admin/api'
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Admin Users API Route — detail + actions
3
+ *
4
+ * Thin re-export of the SDK handlers:
5
+ * GET — detail (users.read)
6
+ * PATCH — { action: 'deactivate' | 'reactivate' } (users.write)
7
+ * DELETE — hard delete (users.delete, owner only)
8
+ */
9
+
10
+ export {
11
+ getUser as GET,
12
+ PATCH,
13
+ DELETE,
14
+ } from '@rovela-ai/sdk/admin/api/users'
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Admin Users API Route — list + invite
3
+ *
4
+ * Thin re-export of the SDK handlers:
5
+ * GET — list all admins (users.read)
6
+ * POST — invite a new admin (users.write; Phase 3)
7
+ *
8
+ * The SDK enforces all permissions and invariants; this file just mounts
9
+ * the handlers at the expected path.
10
+ */
11
+
12
+ export { GET, POST } from '@rovela-ai/sdk/admin/api/users'
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Store Admin Authentication Route
3
+ *
4
+ * Dedicated NextAuth endpoint for admin sign-in/sign-out/session. Writes
5
+ * its own cookie (`__Secure-rovela.admin.session-token`), completely
6
+ * separate from the storefront customer session cookie. Both can coexist
7
+ * in the same browser.
8
+ *
9
+ * Customer authentication lives at /api/auth/[...nextauth].
10
+ */
11
+
12
+ import NextAuth from 'next-auth'
13
+ import { createAdminAuthOptions } from '@rovela-ai/sdk/admin'
14
+
15
+ const handler = NextAuth(createAdminAuthOptions())
16
+
17
+ export { handler as GET, handler as POST }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * POST /api/analytics/track
3
+ *
4
+ * Storefront analytics event ingest. Public endpoint — events are pseudonymous
5
+ * (visitor_id is a random UUID, no PII). The SDK handler validates the event,
6
+ * filters bots + admin sessions, derives device/country, and inserts to the
7
+ * store's own Neon branch.
8
+ *
9
+ * See CLAUDE.md §46.
10
+ */
11
+
12
+ export { POST } from '@rovela-ai/sdk/analytics/api/track'
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Storefront Customer Authentication Route
3
+ *
4
+ * Handles customer sign-in/sign-up/session for the storefront.
5
+ * Uses the 'credentials' provider and writes the customer session cookie
6
+ * (`__Secure-rovela.customer.session-token`).
7
+ *
8
+ * Admin authentication lives at a SEPARATE endpoint:
9
+ * /api/admin-auth/[...nextauth]
10
+ * with its own cookie (`__Secure-rovela.admin.session-token`), so an admin
11
+ * and a customer session can coexist in the same browser.
12
+ */
13
+
14
+ import NextAuth from 'next-auth'
15
+ import { createCustomerAuthOptions } from '@rovela-ai/sdk/auth'
16
+
17
+ const handler = NextAuth(createCustomerAuthOptions())
18
+
19
+ export { handler as GET, handler as POST }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Forgot Password Route
3
+ *
4
+ * POST /api/auth/forgot-password - Request password reset
5
+ */
6
+
7
+ import { POST as handler } from '@rovela-ai/sdk/auth/api/forgot-password'
8
+
9
+ export const POST = handler
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Customer Registration Route
3
+ *
4
+ * POST /api/auth/register - Register new customer
5
+ */
6
+
7
+ import { POST as handler } from '@rovela-ai/sdk/auth/api/register'
8
+
9
+ export const POST = handler
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resend Verification Route
3
+ *
4
+ * POST /api/auth/resend-verification - Resend verification email
5
+ */
6
+
7
+ import { POST as handler } from '@rovela-ai/sdk/auth/api/resend-verification'
8
+
9
+ export const POST = handler
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Reset Password Route
3
+ *
4
+ * GET/POST /api/auth/reset-password - Validate token / Reset password
5
+ */
6
+
7
+ import { GET as getHandler, POST as postHandler } from '@rovela-ai/sdk/auth/api/reset-password'
8
+
9
+ export const GET = getHandler
10
+ export const POST = postHandler
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Email Verification Route
3
+ *
4
+ * GET/POST /api/auth/verify-email - Verify customer email
5
+ */
6
+
7
+ import { GET as getHandler, POST as postHandler } from '@rovela-ai/sdk/auth/api/verify-email'
8
+
9
+ export const GET = getHandler
10
+ export const POST = postHandler
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Categories API Route
3
+ *
4
+ * GET /api/categories - List all categories
5
+ * Wires directly to SDK handler.
6
+ */
7
+
8
+ import { getCategories } from '@rovela-ai/sdk/products'
9
+
10
+ export const GET = getCategories
@@ -0,0 +1,7 @@
1
+ /**
2
+ * GET /api/checkout/countries
3
+ *
4
+ * Returns allowed shipping countries from store settings.
5
+ * Used by CheckoutFlow to filter country dropdown in ShippingForm.
6
+ */
7
+ export { CountriesGET as GET } from '@rovela-ai/sdk/checkout'
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Checkout Discount Preview API Route
3
+ *
4
+ * POST /api/checkout/discount - Validate a discount code against the current
5
+ * cart (and surface automatic promotions) before placing the order. Runs the
6
+ * same server-side pricing pipeline as order creation.
7
+ */
8
+
9
+ export { POST } from '@rovela-ai/sdk/checkout/api/discount'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Manual Checkout API Route
3
+ *
4
+ * POST /api/checkout/manual - Place an order with a manual payment method
5
+ * (cash on delivery, wire transfer…). Order is created as 'pending'; the
6
+ * merchant marks it paid from the admin. All amounts are recomputed
7
+ * server-side from the database.
8
+ */
9
+
10
+ export { POST } from '@rovela-ai/sdk/checkout/api/manual'
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checkout Payment Methods API Route (public)
3
+ *
4
+ * GET /api/checkout/payment-methods - Enabled payment methods offered at
5
+ * checkout alongside card payments.
6
+ */
7
+
8
+ export { GET } from '@rovela-ai/sdk/checkout/api/payment-methods'
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checkout Pickup Locations API Route (public)
3
+ *
4
+ * GET /api/checkout/pickup-locations - Pickup-enabled store locations for the
5
+ * checkout's "Pick up in store" selector. Empty list = toggle hidden.
6
+ */
7
+
8
+ export { GET } from '@rovela-ai/sdk/checkout/api/pickup-locations'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checkout API Route
3
+ *
4
+ * POST /api/checkout - Create Stripe Checkout session
5
+ * Wires directly to SDK handler.
6
+ */
7
+
8
+ import { POST as handler } from '@rovela-ai/sdk/checkout/api'
9
+
10
+ export const POST = handler
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shipping calculation API route
3
+ *
4
+ * POST /api/checkout/shipping
5
+ * Calculates available shipping options based on address and cart items.
6
+ * Supports both manual (zone-based) and Shippo (carrier API) modes.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const response = await fetch('/api/checkout/shipping', {
11
+ * method: 'POST',
12
+ * headers: { 'Content-Type': 'application/json' },
13
+ * body: JSON.stringify({
14
+ * address: { firstName, lastName, line1, city, state, postalCode, country },
15
+ * items: [{ price: 2999, quantity: 2 }]
16
+ * })
17
+ * })
18
+ * const { options, flatOptions, mode } = await response.json()
19
+ * ```
20
+ */
21
+ export { ShippingPOST as POST } from '@rovela-ai/sdk/checkout/api'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checkout Status Route
3
+ *
4
+ * GET /api/checkout/status - Check if payments are configured
5
+ *
6
+ * Used by CheckoutButton component to verify the store can accept payments
7
+ * before showing the checkout button.
8
+ */
9
+
10
+ export { GET } from '@rovela-ai/sdk/checkout/api/payment-status'
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Contact Form API Route
3
+ *
4
+ * POST /api/contact - Send contact form message to store owner
5
+ *
6
+ * Uses SDK email system to send formatted emails.
7
+ */
8
+
9
+ import { NextRequest, NextResponse } from 'next/server'
10
+ import {
11
+ sendEmail,
12
+ baseLayout,
13
+ getEmailConfig,
14
+ getSupportEmail,
15
+ escapeHtml,
16
+ } from '@rovela-ai/sdk/emails'
17
+
18
+ // =============================================================================
19
+ // Types
20
+ // =============================================================================
21
+
22
+ interface ContactFormData {
23
+ name: string
24
+ email: string
25
+ subject: string
26
+ message: string
27
+ }
28
+
29
+ // =============================================================================
30
+ // Validation
31
+ // =============================================================================
32
+
33
+ function validateContactForm(data: unknown): {
34
+ valid: boolean
35
+ error?: string
36
+ data?: ContactFormData
37
+ } {
38
+ if (!data || typeof data !== 'object') {
39
+ return { valid: false, error: 'Invalid request body' }
40
+ }
41
+
42
+ const { name, email, subject, message } = data as Record<string, unknown>
43
+
44
+ if (typeof name !== 'string' || name.trim().length < 2) {
45
+ return { valid: false, error: 'Name must be at least 2 characters' }
46
+ }
47
+
48
+ if (typeof email !== 'string' || !email.includes('@') || email.length < 5) {
49
+ return { valid: false, error: 'Please provide a valid email address' }
50
+ }
51
+
52
+ if (typeof subject !== 'string' || subject.trim().length < 5) {
53
+ return { valid: false, error: 'Subject must be at least 5 characters' }
54
+ }
55
+
56
+ if (typeof message !== 'string' || message.trim().length < 10) {
57
+ return { valid: false, error: 'Message must be at least 10 characters' }
58
+ }
59
+
60
+ return {
61
+ valid: true,
62
+ data: {
63
+ name: name.trim(),
64
+ email: email.trim().toLowerCase(),
65
+ subject: subject.trim(),
66
+ message: message.trim(),
67
+ },
68
+ }
69
+ }
70
+
71
+ // =============================================================================
72
+ // POST Handler
73
+ // =============================================================================
74
+
75
+ export async function POST(request: NextRequest) {
76
+ try {
77
+ // Parse request body
78
+ const body = await request.json()
79
+
80
+ // Validate form data
81
+ const validation = validateContactForm(body)
82
+ if (!validation.valid || !validation.data) {
83
+ return NextResponse.json(
84
+ { success: false, error: validation.error },
85
+ { status: 400 }
86
+ )
87
+ }
88
+
89
+ const { name, email, subject, message } = validation.data
90
+
91
+ // Get email configuration
92
+ const config = await getEmailConfig()
93
+
94
+ // Determine recipient - store owner or support email
95
+ const recipientEmail =
96
+ process.env.STORE_OWNER_EMAIL || (await getSupportEmail())
97
+
98
+ // Build email content
99
+ const emailContent = `
100
+ <h1 style="margin: 0 0 24px 0; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; font-size: 30px; font-weight: 700; color: #0A0A0A; text-align: center; line-height: 1.1;">New Contact Form Message</h1>
101
+ <p style="margin: 0 0 16px 0; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; font-size: 16px; font-weight: 400; line-height: 1.625; color: #78716C;">You've received a new message from your store's contact form.</p>
102
+
103
+ <table style="width: 100%; border-collapse: collapse; margin: 24px 0;">
104
+ <tr>
105
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3; font-weight: 600; width: 100px;">From:</td>
106
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3;">${escapeHtml(name)}</td>
107
+ </tr>
108
+ <tr>
109
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3; font-weight: 600;">Email:</td>
110
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3;">
111
+ <a href="mailto:${escapeHtml(email)}" style="color: #0CAF7D; text-decoration: none;">${escapeHtml(email)}</a>
112
+ </td>
113
+ </tr>
114
+ <tr>
115
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3; font-weight: 600;">Subject:</td>
116
+ <td style="padding: 12px 0; border-bottom: 1px solid #E8DFD3;">${escapeHtml(subject)}</td>
117
+ </tr>
118
+ </table>
119
+
120
+ <h2 style="margin: 24px 0 16px 0; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; font-size: 20px; font-weight: 600; color: #0A0A0A;">Message</h2>
121
+ <div style="background-color: #F7F7F7; border-radius: 8px; padding: 20px; margin-top: 16px;">
122
+ <p style="margin: 0; white-space: pre-wrap; line-height: 1.6;">${escapeHtml(message)}</p>
123
+ </div>
124
+
125
+ <p style="margin: 24px 0 0 0; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; font-size: 14px; font-weight: 400; line-height: 1.625; color: #78716C;"><em>You can reply directly to this email to respond to ${escapeHtml(name)}.</em></p>
126
+ `
127
+
128
+ // Render with base layout
129
+ const html = baseLayout({
130
+ config,
131
+ title: `Contact: ${subject}`,
132
+ content: emailContent,
133
+ })
134
+
135
+ // Send email with reply-to set to customer's email
136
+ const result = await sendEmail({
137
+ to: recipientEmail,
138
+ subject: `[${config.storeName}] Contact: ${subject}`,
139
+ html,
140
+ replyTo: email,
141
+ })
142
+
143
+ if (!result.success) {
144
+ console.error('[Contact API] Email send failed:', result.error)
145
+ return NextResponse.json(
146
+ { success: false, error: 'Failed to send message. Please try again.' },
147
+ { status: 500 }
148
+ )
149
+ }
150
+
151
+ console.log('[Contact API] Message sent successfully to:', recipientEmail)
152
+
153
+ return NextResponse.json({
154
+ success: true,
155
+ message: 'Message sent successfully',
156
+ })
157
+ } catch (error) {
158
+ console.error('[Contact API] Error:', error)
159
+ return NextResponse.json(
160
+ { success: false, error: 'An unexpected error occurred' },
161
+ { status: 500 }
162
+ )
163
+ }
164
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Media Presign API Route
3
+ *
4
+ * POST /api/media/presign - Generate presigned URL for file upload
5
+ */
6
+
7
+ export { POST } from '@rovela-ai/sdk/media/api'