convex-cms 0.0.3 → 0.0.5-alpha.2

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 (375) hide show
  1. package/README.md +107 -60
  2. package/admin/README.md +99 -0
  3. package/admin/src/components/AdminLayout.tsx +22 -0
  4. package/admin/src/components/BreakingChangesWarningDialog.tsx +81 -0
  5. package/admin/src/components/BulkActionBar.tsx +190 -0
  6. package/admin/src/components/BulkOperationModal.tsx +177 -0
  7. package/admin/src/components/ContentEntryEditor.tsx +1104 -0
  8. package/admin/src/components/ContentTypeFormModal.tsx +1012 -0
  9. package/admin/src/components/ErrorBoundary.tsx +83 -0
  10. package/admin/src/components/ErrorState.tsx +147 -0
  11. package/admin/src/components/Header.tsx +294 -0
  12. package/admin/src/components/RouteGuard.tsx +264 -0
  13. package/admin/src/components/Sidebar.tsx +90 -0
  14. package/admin/src/components/TaxonomyEditor.tsx +348 -0
  15. package/admin/src/components/TermTree.tsx +533 -0
  16. package/admin/src/components/UploadDropzone.tsx +383 -0
  17. package/admin/src/components/VersionCompare.tsx +250 -0
  18. package/admin/src/components/VersionHistory.tsx +279 -0
  19. package/admin/src/components/VersionRollbackModal.tsx +79 -0
  20. package/admin/src/components/cmsds/CmsButton.tsx +101 -0
  21. package/admin/src/components/cmsds/CmsDialog.tsx +139 -0
  22. package/admin/src/components/cmsds/CmsDropdown.tsx +62 -0
  23. package/admin/src/components/cmsds/CmsEmptyState.tsx +54 -0
  24. package/admin/src/components/cmsds/CmsField.tsx +47 -0
  25. package/admin/src/components/cmsds/CmsPageHeader.tsx +35 -0
  26. package/admin/src/components/cmsds/CmsStatusBadge.tsx +153 -0
  27. package/admin/src/components/cmsds/CmsSurface.tsx +52 -0
  28. package/admin/src/components/cmsds/CmsTable.tsx +164 -0
  29. package/admin/src/components/cmsds/CmsToolbar.tsx +58 -0
  30. package/admin/src/components/cmsds/index.ts +10 -0
  31. package/admin/src/components/fields/BooleanField.tsx +74 -0
  32. package/admin/src/components/fields/CategoryField.tsx +394 -0
  33. package/admin/src/components/fields/DateField.tsx +173 -0
  34. package/admin/src/components/fields/DefaultFieldRenderer.tsx +74 -0
  35. package/admin/src/components/fields/FieldRenderer.tsx +180 -0
  36. package/admin/src/components/fields/FieldWrapper.tsx +57 -0
  37. package/admin/src/components/fields/JsonField.tsx +172 -0
  38. package/admin/src/components/fields/MediaField.tsx +367 -0
  39. package/admin/src/components/fields/MultiSelectField.tsx +118 -0
  40. package/admin/src/components/fields/NumberField.tsx +77 -0
  41. package/admin/src/components/fields/ReferenceField.tsx +386 -0
  42. package/admin/src/components/fields/RichTextField.tsx +171 -0
  43. package/admin/src/components/fields/SelectField.tsx +62 -0
  44. package/admin/src/components/fields/TagField.tsx +325 -0
  45. package/admin/src/components/fields/TextAreaField.tsx +68 -0
  46. package/admin/src/components/fields/TextField.tsx +56 -0
  47. package/admin/src/components/fields/index.ts +54 -0
  48. package/admin/src/components/fields/registry.ts +64 -0
  49. package/admin/src/components/fields/types.ts +217 -0
  50. package/admin/src/components/filters/TaxonomyFilter.tsx +254 -0
  51. package/admin/src/components/filters/index.ts +1 -0
  52. package/admin/src/components/index.ts +8 -0
  53. package/admin/src/components/media/MediaAssetActions.tsx +115 -0
  54. package/admin/src/components/media/MediaAssetEditDialog.tsx +217 -0
  55. package/admin/src/components/media/MediaBulkActionBar.tsx +51 -0
  56. package/admin/src/components/media/MediaFolderActions.tsx +69 -0
  57. package/admin/src/components/media/MediaFolderEditDialog.tsx +126 -0
  58. package/admin/src/components/media/MediaMoveModal.tsx +179 -0
  59. package/admin/src/components/media/MediaPreviewModal.tsx +370 -0
  60. package/admin/src/components/media/MediaTaxonomyPicker.tsx +304 -0
  61. package/admin/src/components/media/MediaTrashBulkActionBar.tsx +59 -0
  62. package/admin/src/components/ui/accordion.tsx +64 -0
  63. package/admin/src/components/ui/alert-dialog.tsx +155 -0
  64. package/admin/src/components/ui/alert.tsx +66 -0
  65. package/admin/src/components/ui/avatar.tsx +53 -0
  66. package/admin/src/components/ui/badge.tsx +46 -0
  67. package/admin/src/components/ui/breadcrumb.tsx +109 -0
  68. package/admin/src/components/ui/button.tsx +62 -0
  69. package/admin/src/components/ui/calendar.tsx +220 -0
  70. package/admin/src/components/ui/card.tsx +92 -0
  71. package/admin/src/components/ui/checkbox.tsx +30 -0
  72. package/admin/src/components/ui/command.tsx +182 -0
  73. package/admin/src/components/ui/dialog.tsx +143 -0
  74. package/admin/src/components/ui/dropdown-menu.tsx +257 -0
  75. package/admin/src/components/ui/form.tsx +167 -0
  76. package/admin/src/components/ui/input.tsx +21 -0
  77. package/admin/src/components/ui/label.tsx +24 -0
  78. package/admin/src/components/ui/popover.tsx +46 -0
  79. package/admin/src/components/ui/scroll-area.tsx +56 -0
  80. package/admin/src/components/ui/select.tsx +190 -0
  81. package/admin/src/components/ui/separator.tsx +26 -0
  82. package/admin/src/components/ui/sheet.tsx +137 -0
  83. package/admin/src/components/ui/sidebar.tsx +724 -0
  84. package/admin/src/components/ui/skeleton.tsx +13 -0
  85. package/admin/src/components/ui/sonner.tsx +38 -0
  86. package/admin/src/components/ui/switch.tsx +31 -0
  87. package/admin/src/components/ui/table.tsx +114 -0
  88. package/admin/src/components/ui/tabs.tsx +66 -0
  89. package/admin/src/components/ui/textarea.tsx +18 -0
  90. package/admin/src/components/ui/tooltip.tsx +61 -0
  91. package/admin/src/contexts/AdminConfigContext.tsx +30 -0
  92. package/admin/src/contexts/AuthContext.tsx +330 -0
  93. package/admin/src/contexts/BreadcrumbContext.tsx +49 -0
  94. package/admin/src/contexts/SettingsConfigContext.tsx +57 -0
  95. package/admin/src/contexts/ThemeContext.tsx +91 -0
  96. package/admin/src/contexts/index.ts +20 -0
  97. package/admin/src/embed/components/EmbedHeader.tsx +103 -0
  98. package/admin/src/embed/components/EmbedLayout.tsx +29 -0
  99. package/admin/src/embed/components/EmbedSidebar.tsx +119 -0
  100. package/admin/src/embed/components/index.ts +3 -0
  101. package/admin/src/embed/contexts/ApiContext.tsx +32 -0
  102. package/admin/src/embed/index.tsx +184 -0
  103. package/admin/src/embed/navigation.tsx +202 -0
  104. package/admin/src/embed/pages/Content.tsx +19 -0
  105. package/admin/src/embed/pages/ContentTypes.tsx +19 -0
  106. package/admin/src/embed/pages/Dashboard.tsx +19 -0
  107. package/admin/src/embed/pages/Media.tsx +19 -0
  108. package/admin/src/embed/pages/Settings.tsx +22 -0
  109. package/admin/src/embed/pages/Taxonomies.tsx +22 -0
  110. package/admin/src/embed/pages/Trash.tsx +22 -0
  111. package/admin/src/embed/pages/index.ts +7 -0
  112. package/admin/src/embed/types.ts +24 -0
  113. package/admin/src/hooks/index.ts +2 -0
  114. package/admin/src/hooks/use-mobile.ts +19 -0
  115. package/admin/src/hooks/useBreadcrumbLabel.ts +15 -0
  116. package/admin/src/hooks/usePermissions.ts +211 -0
  117. package/admin/src/lib/admin-config.ts +111 -0
  118. package/admin/src/lib/cn.ts +6 -0
  119. package/admin/src/lib/config.server.ts +56 -0
  120. package/admin/src/lib/convex.ts +26 -0
  121. package/admin/src/lib/embed-adapter.ts +80 -0
  122. package/admin/src/lib/icons.tsx +96 -0
  123. package/admin/src/lib/loadAdminConfig.ts +92 -0
  124. package/admin/src/lib/motion.ts +29 -0
  125. package/admin/src/lib/navigation.ts +43 -0
  126. package/admin/src/lib/tanstack-adapter.ts +82 -0
  127. package/admin/src/pages/ContentPage.tsx +337 -0
  128. package/admin/src/pages/ContentTypesPage.tsx +457 -0
  129. package/admin/src/pages/DashboardPage.tsx +163 -0
  130. package/admin/src/pages/MediaPage.tsx +34 -0
  131. package/admin/src/pages/SettingsPage.tsx +486 -0
  132. package/admin/src/pages/TaxonomiesPage.tsx +289 -0
  133. package/admin/src/pages/TrashPage.tsx +421 -0
  134. package/admin/src/pages/index.ts +14 -0
  135. package/admin/src/routeTree.gen.ts +262 -0
  136. package/admin/src/router.tsx +22 -0
  137. package/admin/src/routes/__root.tsx +250 -0
  138. package/admin/src/routes/content-types.tsx +20 -0
  139. package/admin/src/routes/content.tsx +20 -0
  140. package/admin/src/routes/entries/$entryId.tsx +107 -0
  141. package/admin/src/routes/entries/new.$contentTypeId.tsx +69 -0
  142. package/admin/src/routes/entries/type/$contentTypeId.tsx +503 -0
  143. package/admin/src/routes/index.tsx +20 -0
  144. package/admin/src/routes/media.tsx +1095 -0
  145. package/admin/src/routes/settings.tsx +20 -0
  146. package/admin/src/routes/taxonomies.tsx +20 -0
  147. package/admin/src/routes/trash.tsx +20 -0
  148. package/admin/src/styles/globals.css +69 -0
  149. package/admin/src/styles/tailwind-config.css +74 -0
  150. package/admin/src/styles/theme.css +73 -0
  151. package/admin/src/types/index.ts +221 -0
  152. package/admin/src/utils/errorParsing.ts +163 -0
  153. package/admin/src/utils/index.ts +5 -0
  154. package/admin/src/vite-env.d.ts +14 -0
  155. package/admin/tailwind.preset.cjs +102 -0
  156. package/admin-dist/nitro.json +1 -1
  157. package/admin-dist/public/assets/{CmsEmptyState-CRswfTzk.js → CmsEmptyState-CkqBIab3.js} +2 -2
  158. package/admin-dist/public/assets/{CmsPageHeader-CirpXndm.js → CmsPageHeader-CUtl5MMG.js} +1 -1
  159. package/admin-dist/public/assets/{CmsStatusBadge-CbEUpQu-.js → CmsStatusBadge-CUYFgEe-.js} +1 -1
  160. package/admin-dist/public/assets/CmsSurface-CsJfAVa3.js +1 -0
  161. package/admin-dist/public/assets/{CmsToolbar-BI2nZOXp.js → CmsToolbar-CnfbcxeP.js} +1 -1
  162. package/admin-dist/public/assets/{ContentEntryEditor-CBeCyK_m.js → ContentEntryEditor-BU220CCy.js} +1 -1
  163. package/admin-dist/public/assets/TaxonomyFilter-CWCxC5HZ.js +1 -0
  164. package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +1 -0
  165. package/admin-dist/public/assets/{_entryId-CKU_glsK.js → _entryId-CuVMExbb.js} +1 -1
  166. package/admin-dist/public/assets/alert-CF1BSzGR.js +1 -0
  167. package/admin-dist/public/assets/{badge-hvUOzpVZ.js → badge-CmuOIVKp.js} +1 -1
  168. package/admin-dist/public/assets/{circle-check-big-CF_pR17r.js → circle-check-big-BKDVG6DU.js} +1 -1
  169. package/admin-dist/public/assets/{command-DU82cJlt.js → command-XJxnF2Sd.js} +1 -1
  170. package/admin-dist/public/assets/content-QBUxdxbS.js +1 -0
  171. package/admin-dist/public/assets/content-types-CrNEm8Hf.js +2 -0
  172. package/admin-dist/public/assets/globals-B7Wsfh_v.css +1 -0
  173. package/admin-dist/public/assets/index-C7xOwudI.js +1 -0
  174. package/admin-dist/public/assets/{label-KNtpL71g.js → label-CHCnXeBk.js} +1 -1
  175. package/admin-dist/public/assets/{link-2-Bw2aI4V4.js → link-2-Bb34judH.js} +1 -1
  176. package/admin-dist/public/assets/{list-sYepHjt_.js → list-9Pzt48ld.js} +1 -1
  177. package/admin-dist/public/assets/{main-CKj5yfEi.js → main-CjQ2VI9L.js} +3 -3
  178. package/admin-dist/public/assets/media-Dc5PWt2Q.js +1 -0
  179. package/admin-dist/public/assets/{new._contentTypeId-C3LstjNs.js → new._contentTypeId-C_I4YxIa.js} +1 -1
  180. package/admin-dist/public/assets/{plus-DUn8v_Xf.js → plus-Ceef7DHk.js} +1 -1
  181. package/admin-dist/public/assets/{rotate-ccw-DJEoHcRI.js → rotate-ccw-7k7-4VUq.js} +1 -1
  182. package/admin-dist/public/assets/scroll-area-CC6wujnp.js +1 -0
  183. package/admin-dist/public/assets/{search-MuAUDJKR.js → search-DwoUV2pv.js} +1 -1
  184. package/admin-dist/public/assets/select-hOZTp8aC.js +1 -0
  185. package/admin-dist/public/assets/settings-t2PbCZh4.js +1 -0
  186. package/admin-dist/public/assets/switch-jX2pDaNU.js +1 -0
  187. package/admin-dist/public/assets/tabs-q4EbZk7c.js +1 -0
  188. package/admin-dist/public/assets/tanstack-adapter-B-Glm4kH.js +1 -0
  189. package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +1 -0
  190. package/admin-dist/public/assets/{textarea-BTy7nwzR.js → textarea-B6SfBmr0.js} +1 -1
  191. package/admin-dist/public/assets/trash-BOCnIznD.js +1 -0
  192. package/admin-dist/public/assets/{triangle-alert-E52Vfeuh.js → triangle-alert-CXFIO_Gu.js} +1 -1
  193. package/admin-dist/public/assets/useBreadcrumbLabel-_6qBagc3.js +1 -0
  194. package/admin-dist/public/assets/{usePermissions-Basjs9BT.js → usePermissions-M1ijZ7a6.js} +1 -1
  195. package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +7 -0
  196. package/admin-dist/server/_ssr/{badge-6BsP37vG.mjs → CmsButton-DOiTVKQq.mjs} +33 -33
  197. package/admin-dist/server/_ssr/{CmsEmptyState-DU7-7-mV.mjs → CmsEmptyState-fbnGt3LD.mjs} +2 -2
  198. package/admin-dist/server/_ssr/{CmsPageHeader-CseW0AHm.mjs → CmsPageHeader-DHRrdOZa.mjs} +1 -1
  199. package/admin-dist/server/_ssr/{CmsStatusBadge-B_pi4KCp.mjs → CmsStatusBadge-s7obWbKZ.mjs} +2 -2
  200. package/admin-dist/server/_ssr/CmsSurface-rFoYjb62.mjs +44 -0
  201. package/admin-dist/server/_ssr/{CmsToolbar-X75ex6ek.mjs → CmsToolbar-zTE45z2q.mjs} +2 -2
  202. package/admin-dist/server/_ssr/{ContentEntryEditor-CepusRsA.mjs → ContentEntryEditor-BLoEjT_m.mjs} +12 -12
  203. package/admin-dist/server/_ssr/{TaxonomyFilter-Bwrq0-cz.mjs → TaxonomyFilter-XAtaJC2z.mjs} +5 -5
  204. package/admin-dist/server/_ssr/{_contentTypeId-BqYKEcLr.mjs → _contentTypeId-Csl4822C.mjs} +13 -13
  205. package/admin-dist/server/_ssr/{_entryId-CRfnqeDf.mjs → _entryId-D8alLFBx.mjs} +15 -15
  206. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +4 -0
  207. package/admin-dist/server/_ssr/{command-fy8epIKf.mjs → command-C0Di14--.mjs} +1 -1
  208. package/admin-dist/server/_ssr/{content-B5RhL7uW.mjs → content-CT-FPsmV.mjs} +170 -98
  209. package/admin-dist/server/_ssr/{content-types-BIOqCQYN.mjs → content-types-C8cBFdzE.mjs} +260 -115
  210. package/admin-dist/server/_ssr/{index-DHSHDPt1.mjs → index-BJtcrEc-.mjs} +88 -17
  211. package/admin-dist/server/_ssr/index.mjs +2 -2
  212. package/admin-dist/server/_ssr/{label-C8Dko1j7.mjs → label-qn2Afwl4.mjs} +1 -1
  213. package/admin-dist/server/_ssr/{media-CSx3XttC.mjs → media-qv5IAsMZ.mjs} +43 -43
  214. package/admin-dist/server/_ssr/{new._contentTypeId-DzanEZQM.mjs → new._contentTypeId-DdGyrhqs.mjs} +13 -13
  215. package/admin-dist/server/_ssr/{router-DDWcF-kt.mjs → router-nSVkxb6Y.mjs} +11 -11
  216. package/admin-dist/server/_ssr/{scroll-area-bjPYwhXN.mjs → scroll-area-BCinP455.mjs} +1 -1
  217. package/admin-dist/server/_ssr/{select-BUhDDf4T.mjs → select-BKQlQScw.mjs} +1 -1
  218. package/admin-dist/server/_ssr/{settings-DAsxnw2q.mjs → settings-BCr2KQlk.mjs} +236 -139
  219. package/admin-dist/server/_ssr/{switch-BgyRtQ1Z.mjs → switch-BaOi42fE.mjs} +1 -1
  220. package/admin-dist/server/_ssr/{tabs-DzMdRB1A.mjs → tabs-DYXEi9kq.mjs} +5 -3
  221. package/admin-dist/server/_ssr/tanstack-adapter-Bsz8kha-.mjs +119 -0
  222. package/admin-dist/server/_ssr/{taxonomies-C8j8g5Q5.mjs → taxonomies-CueMHTbE.mjs} +184 -73
  223. package/admin-dist/server/_ssr/{textarea-9jNeYJSc.mjs → textarea-CI0Jqx2x.mjs} +1 -1
  224. package/admin-dist/server/_ssr/{trash-DYMxwhZB.mjs → trash-DE6W8GoX.mjs} +211 -88
  225. package/admin-dist/server/_ssr/{useBreadcrumbLabel-FNSAr2Ha.mjs → useBreadcrumbLabel-B5Yi72lM.mjs} +1 -1
  226. package/admin-dist/server/_ssr/{usePermissions-BJGGahrJ.mjs → usePermissions-C3nZ-Izm.mjs} +1 -1
  227. package/admin-dist/server/index.mjs +189 -182
  228. package/dist/cli/commands/init.d.ts +6 -0
  229. package/dist/cli/commands/init.d.ts.map +1 -0
  230. package/dist/cli/commands/init.js +156 -0
  231. package/dist/cli/commands/init.js.map +1 -0
  232. package/dist/cli/index.js +6 -0
  233. package/dist/cli/index.js.map +1 -1
  234. package/dist/client/admin/bulk.d.ts +79 -0
  235. package/dist/client/admin/bulk.d.ts.map +1 -0
  236. package/dist/client/admin/bulk.js +72 -0
  237. package/dist/client/admin/bulk.js.map +1 -0
  238. package/dist/client/admin/contentLock.d.ts +118 -0
  239. package/dist/client/admin/contentLock.d.ts.map +1 -0
  240. package/dist/client/admin/contentLock.js +81 -0
  241. package/dist/client/admin/contentLock.js.map +1 -0
  242. package/dist/client/admin/contentTypes.d.ts +1204 -0
  243. package/dist/client/admin/contentTypes.d.ts.map +1 -0
  244. package/dist/client/admin/contentTypes.js +122 -0
  245. package/dist/client/admin/contentTypes.js.map +1 -0
  246. package/dist/client/admin/dashboard.d.ts +16 -0
  247. package/dist/client/admin/dashboard.d.ts.map +1 -0
  248. package/dist/client/admin/dashboard.js +33 -0
  249. package/dist/client/admin/dashboard.js.map +1 -0
  250. package/dist/client/admin/entries.d.ts +358 -0
  251. package/dist/client/admin/entries.d.ts.map +1 -0
  252. package/dist/client/admin/entries.js +220 -0
  253. package/dist/client/admin/entries.js.map +1 -0
  254. package/dist/client/admin/index.d.ts +6568 -0
  255. package/dist/client/admin/index.d.ts.map +1 -0
  256. package/dist/client/admin/index.js +305 -0
  257. package/dist/client/admin/index.js.map +1 -0
  258. package/dist/client/admin/media.d.ts +1038 -0
  259. package/dist/client/admin/media.d.ts.map +1 -0
  260. package/dist/client/admin/media.js +489 -0
  261. package/dist/client/admin/media.js.map +1 -0
  262. package/dist/client/admin/taxonomies.d.ts +339 -0
  263. package/dist/client/admin/taxonomies.d.ts.map +1 -0
  264. package/dist/client/admin/taxonomies.js +364 -0
  265. package/dist/client/admin/taxonomies.js.map +1 -0
  266. package/dist/client/admin/trash.d.ts +91 -0
  267. package/dist/client/admin/trash.d.ts.map +1 -0
  268. package/dist/client/admin/trash.js +71 -0
  269. package/dist/client/admin/trash.js.map +1 -0
  270. package/dist/client/admin/types.d.ts +320 -0
  271. package/dist/client/admin/types.d.ts.map +1 -0
  272. package/dist/client/admin/types.js +7 -0
  273. package/dist/client/admin/types.js.map +1 -0
  274. package/dist/client/admin/validators.d.ts +3886 -0
  275. package/dist/client/admin/validators.d.ts.map +1 -0
  276. package/dist/client/admin/validators.js +322 -0
  277. package/dist/client/admin/validators.js.map +1 -0
  278. package/dist/client/admin/versions.d.ts +106 -0
  279. package/dist/client/admin/versions.d.ts.map +1 -0
  280. package/dist/client/admin/versions.js +57 -0
  281. package/dist/client/admin/versions.js.map +1 -0
  282. package/dist/client/adminApiTypes.d.ts +27 -0
  283. package/dist/client/adminApiTypes.d.ts.map +1 -0
  284. package/dist/client/adminApiTypes.js +12 -0
  285. package/dist/client/adminApiTypes.js.map +1 -0
  286. package/dist/client/{admin-config.d.ts → adminConfig.d.ts} +4 -4
  287. package/dist/client/adminConfig.d.ts.map +1 -0
  288. package/dist/client/{admin-config.js → adminConfig.js} +3 -3
  289. package/dist/client/adminConfig.js.map +1 -0
  290. package/dist/client/agentTools.d.ts +11 -21
  291. package/dist/client/agentTools.d.ts.map +1 -1
  292. package/dist/client/agentTools.js +4 -4
  293. package/dist/client/index.d.ts +6 -6
  294. package/dist/client/index.d.ts.map +1 -1
  295. package/dist/client/index.js +19 -6
  296. package/dist/client/index.js.map +1 -1
  297. package/dist/client/schema/codegen.d.ts +2 -2
  298. package/dist/client/schema/codegen.d.ts.map +1 -1
  299. package/dist/client/schema/codegen.js +3 -3
  300. package/dist/client/schema/codegen.js.map +1 -1
  301. package/dist/client/schema/defineContentType.d.ts +3 -3
  302. package/dist/client/schema/defineContentType.js +3 -3
  303. package/dist/client/schema/index.d.ts +7 -7
  304. package/dist/client/schema/index.d.ts.map +1 -1
  305. package/dist/client/schema/index.js +5 -5
  306. package/dist/client/schema/index.js.map +1 -1
  307. package/dist/client/schema/schemaDrift.d.ts +1 -1
  308. package/dist/client/schema/schemaDrift.js +1 -1
  309. package/dist/client/schema/typedClient.d.ts +2 -2
  310. package/dist/client/schema/typedClient.js +2 -2
  311. package/dist/client/schema/types.d.ts +1 -1
  312. package/dist/client/schema/types.js +1 -1
  313. package/dist/client/wrapper.d.ts +108 -65
  314. package/dist/client/wrapper.d.ts.map +1 -1
  315. package/dist/client/wrapper.js +22 -22
  316. package/dist/client/wrapper.js.map +1 -1
  317. package/dist/component/contentEntries.d.ts +4 -4
  318. package/dist/component/contentEntryMutations.d.ts +46 -0
  319. package/dist/component/contentEntryMutations.d.ts.map +1 -1
  320. package/dist/component/contentEntryMutations.js +1 -1
  321. package/dist/component/contentEntryMutations.js.map +1 -1
  322. package/dist/component/contentTypeMigration.d.ts +1 -1
  323. package/dist/component/contentTypeMutations.d.ts +22 -0
  324. package/dist/component/contentTypeMutations.d.ts.map +1 -1
  325. package/dist/component/contentTypeMutations.js +1 -1
  326. package/dist/component/contentTypeMutations.js.map +1 -1
  327. package/dist/component/convex.config.d.ts +2 -2
  328. package/dist/component/convex.config.js +2 -2
  329. package/dist/component/index.d.ts +1 -1
  330. package/dist/component/index.js +1 -1
  331. package/dist/component/lib/ragContentChunker.d.ts +1 -1
  332. package/dist/component/lib/ragContentChunker.js +1 -1
  333. package/dist/component/mediaAssetMutations.d.ts +47 -0
  334. package/dist/component/mediaAssetMutations.d.ts.map +1 -1
  335. package/dist/component/mediaAssetMutations.js +1 -1
  336. package/dist/component/mediaAssetMutations.js.map +1 -1
  337. package/dist/component/roles.d.ts +1 -1
  338. package/dist/component/roles.js +1 -1
  339. package/dist/component/schema.d.ts +9 -0
  340. package/dist/component/schema.d.ts.map +1 -1
  341. package/dist/component/schema.js +1 -1
  342. package/dist/component/schema.js.map +1 -1
  343. package/dist/react/index.d.ts +2 -2
  344. package/dist/react/index.d.ts.map +1 -1
  345. package/dist/react/index.js +13 -7
  346. package/dist/react/index.js.map +1 -1
  347. package/dist/test.d.ts +2 -2
  348. package/dist/test.js +2 -2
  349. package/package.json +115 -13
  350. package/admin-dist/public/assets/ErrorState-BIVaWmom.js +0 -1
  351. package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +0 -1
  352. package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +0 -1
  353. package/admin-dist/public/assets/alert-BXjTqrwQ.js +0 -1
  354. package/admin-dist/public/assets/content-_LXl3pp7.js +0 -1
  355. package/admin-dist/public/assets/content-types-KjxaXGxY.js +0 -2
  356. package/admin-dist/public/assets/globals-CS6BZ0zp.css +0 -1
  357. package/admin-dist/public/assets/index-DNGIZHL-.js +0 -1
  358. package/admin-dist/public/assets/media-Bkrkffm7.js +0 -1
  359. package/admin-dist/public/assets/scroll-area-DfIlT0in.js +0 -1
  360. package/admin-dist/public/assets/select-BD29IXCI.js +0 -1
  361. package/admin-dist/public/assets/settings-DmMyn_6A.js +0 -1
  362. package/admin-dist/public/assets/switch-h3Rrnl5i.js +0 -1
  363. package/admin-dist/public/assets/tabs-imc8h-Dp.js +0 -1
  364. package/admin-dist/public/assets/taxonomies-dAsrT65H.js +0 -1
  365. package/admin-dist/public/assets/trash-SAWKZZHv.js +0 -1
  366. package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +0 -1
  367. package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +0 -89
  368. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +0 -4
  369. package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +0 -92
  370. package/dist/client/admin-config.d.ts.map +0 -1
  371. package/dist/client/admin-config.js.map +0 -1
  372. package/dist/client/adminApi.d.ts +0 -2273
  373. package/dist/client/adminApi.d.ts.map +0 -1
  374. package/dist/client/adminApi.js +0 -716
  375. package/dist/client/adminApi.js.map +0 -1
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Settings Route (CLI)
3
+ *
4
+ * Thin wrapper around the shared SettingsPage component.
5
+ * Provides TanStack Router integration and API access.
6
+ */
7
+
8
+ import { createFileRoute } from "@tanstack/react-router";
9
+ import { api } from "../../convex/_generated/api";
10
+ import { SettingsPage } from "~/pages";
11
+ import { useTanStackNavigation } from "~/lib/tanstack-adapter";
12
+
13
+ export const Route = createFileRoute("/settings")({
14
+ component: SettingsRoute,
15
+ });
16
+
17
+ function SettingsRoute() {
18
+ const navigation = useTanStackNavigation();
19
+ return <SettingsPage api={api.admin} navigation={navigation} />;
20
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Taxonomies Route (CLI)
3
+ *
4
+ * Thin wrapper around the shared TaxonomiesPage component.
5
+ * Provides TanStack Router integration and API access.
6
+ */
7
+
8
+ import { createFileRoute } from "@tanstack/react-router";
9
+ import { api } from "../../convex/_generated/api";
10
+ import { TaxonomiesPage } from "~/pages";
11
+ import { useTanStackNavigation } from "~/lib/tanstack-adapter";
12
+
13
+ export const Route = createFileRoute("/taxonomies")({
14
+ component: TaxonomiesRoute,
15
+ });
16
+
17
+ function TaxonomiesRoute() {
18
+ const navigation = useTanStackNavigation();
19
+ return <TaxonomiesPage api={api.admin} navigation={navigation} />;
20
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Trash Route (CLI)
3
+ *
4
+ * Thin wrapper around the shared TrashPage component.
5
+ * Provides TanStack Router integration and API access.
6
+ */
7
+
8
+ import { createFileRoute } from "@tanstack/react-router";
9
+ import { api } from "../../convex/_generated/api";
10
+ import { TrashPage } from "~/pages";
11
+ import { useTanStackNavigation } from "~/lib/tanstack-adapter";
12
+
13
+ export const Route = createFileRoute("/trash")({
14
+ component: TrashRoute,
15
+ });
16
+
17
+ function TrashRoute() {
18
+ const navigation = useTanStackNavigation();
19
+ return <TrashPage api={api.admin} navigation={navigation} />;
20
+ }
@@ -0,0 +1,69 @@
1
+ @import 'tailwindcss';
2
+ @import "tw-animate-css";
3
+ @import "./theme.css";
4
+ @import "./tailwind-config.css";
5
+
6
+ /* ============================================
7
+ CMS Admin - Base & Utility Layers
8
+ ============================================ */
9
+
10
+ @layer base {
11
+ * {
12
+ @apply border-border;
13
+ }
14
+
15
+ body {
16
+ @apply bg-background text-foreground;
17
+ font-feature-settings: 'rlig' 1, 'calt' 1;
18
+ -webkit-font-smoothing: antialiased;
19
+ -moz-osx-font-smoothing: grayscale;
20
+ }
21
+ }
22
+
23
+ @layer utilities {
24
+ /* Status badge colors */
25
+ .status-draft {
26
+ @apply bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300;
27
+ }
28
+
29
+ .status-published {
30
+ @apply bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400;
31
+ }
32
+
33
+ .status-scheduled {
34
+ @apply bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400;
35
+ }
36
+
37
+ .status-archived {
38
+ @apply bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400;
39
+ }
40
+
41
+ /* Surface elevations */
42
+ .surface-base {
43
+ @apply bg-card border border-border;
44
+ }
45
+
46
+ .surface-elevated {
47
+ @apply bg-card border border-border shadow-sm;
48
+ }
49
+
50
+ .surface-floating {
51
+ @apply bg-popover border border-border shadow-lg;
52
+ }
53
+
54
+ /* Focus styles */
55
+ .focus-ring {
56
+ @apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
57
+ }
58
+
59
+ /* Hidden scrollbar - scroll functionality without visible scrollbar */
60
+ .scrollbar-none {
61
+ overflow-y: auto;
62
+ scrollbar-width: none; /* Firefox */
63
+ -ms-overflow-style: none; /* IE/Edge */
64
+ }
65
+
66
+ .scrollbar-none::-webkit-scrollbar {
67
+ display: none; /* Chrome/Safari/Opera */
68
+ }
69
+ }
@@ -0,0 +1,74 @@
1
+ /* ============================================
2
+ CMS Admin - Tailwind v4 Configuration
3
+
4
+ This file contains Tailwind v4 specific config:
5
+ - @custom-variant for dark mode
6
+ - @theme for base tokens (fonts, radii, animations)
7
+ - @theme inline for color mappings to CSS vars
8
+ ============================================ */
9
+
10
+ @custom-variant dark (&:is(.dark *));
11
+
12
+ @theme {
13
+ /* Typography */
14
+ --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
15
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
16
+
17
+ /* Border Radius */
18
+ --radius-sm: 0.25rem;
19
+ --radius-md: 0.375rem;
20
+ --radius-lg: 0.5rem;
21
+ --radius-xl: 0.75rem;
22
+
23
+ /* Sidebar dimensions */
24
+ --sidebar-width: 16rem;
25
+ --sidebar-width-icon: 3rem;
26
+
27
+ /* Animations */
28
+ --animate-accordion-down: accordion-down 0.2s ease-out;
29
+ --animate-accordion-up: accordion-up 0.2s ease-out;
30
+
31
+ @keyframes accordion-down {
32
+ from { height: 0; }
33
+ to { height: var(--radix-accordion-content-height); }
34
+ }
35
+
36
+ @keyframes accordion-up {
37
+ from { height: var(--radix-accordion-content-height); }
38
+ to { height: 0; }
39
+ }
40
+ }
41
+
42
+ /* Map CSS custom properties to Tailwind theme colors */
43
+ @theme inline {
44
+ /* Main colors */
45
+ --color-background: var(--background);
46
+ --color-foreground: var(--foreground);
47
+ --color-card: var(--card);
48
+ --color-card-foreground: var(--card-foreground);
49
+ --color-popover: var(--popover);
50
+ --color-popover-foreground: var(--popover-foreground);
51
+ --color-primary: var(--primary);
52
+ --color-primary-foreground: var(--primary-foreground);
53
+ --color-secondary: var(--secondary);
54
+ --color-secondary-foreground: var(--secondary-foreground);
55
+ --color-muted: var(--muted);
56
+ --color-muted-foreground: var(--muted-foreground);
57
+ --color-accent: var(--accent);
58
+ --color-accent-foreground: var(--accent-foreground);
59
+ --color-destructive: var(--destructive);
60
+ --color-destructive-foreground: var(--destructive-foreground);
61
+ --color-border: var(--border);
62
+ --color-input: var(--input);
63
+ --color-ring: var(--ring);
64
+
65
+ /* Sidebar */
66
+ --color-sidebar: var(--sidebar);
67
+ --color-sidebar-foreground: var(--sidebar-foreground);
68
+ --color-sidebar-primary: var(--sidebar-primary);
69
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
70
+ --color-sidebar-accent: var(--sidebar-accent);
71
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
72
+ --color-sidebar-border: var(--sidebar-border);
73
+ --color-sidebar-ring: var(--sidebar-ring);
74
+ }
@@ -0,0 +1,73 @@
1
+ /* ============================================
2
+ CMS Admin Theme - CSS Custom Properties
3
+ Professional & Clean (Linear/Notion aesthetic)
4
+
5
+ Consumers can import this file and override
6
+ any variable in their own :root {} block.
7
+ ============================================ */
8
+
9
+ :root {
10
+ /* Main colors */
11
+ --background: hsl(0 0% 98%);
12
+ --foreground: hsl(240 10% 3.9%);
13
+ --card: hsl(0 0% 100%);
14
+ --card-foreground: hsl(240 10% 3.9%);
15
+ --popover: hsl(0 0% 100%);
16
+ --popover-foreground: hsl(240 10% 3.9%);
17
+ --primary: hsl(240 5.9% 10%);
18
+ --primary-foreground: hsl(0 0% 98%);
19
+ --secondary: hsl(240 4.8% 95.9%);
20
+ --secondary-foreground: hsl(240 5.9% 10%);
21
+ --muted: hsl(240 4.8% 95.9%);
22
+ --muted-foreground: hsl(240 3.8% 46.1%);
23
+ --accent: hsl(240 4.8% 95.9%);
24
+ --accent-foreground: hsl(240 5.9% 10%);
25
+ --destructive: hsl(0 84.2% 60.2%);
26
+ --destructive-foreground: hsl(0 0% 98%);
27
+ --border: hsl(240 5.9% 90%);
28
+ --input: hsl(240 5.9% 90%);
29
+ --ring: hsl(240 5.9% 10%);
30
+
31
+ /* Sidebar */
32
+ --sidebar: hsl(0 0% 98%);
33
+ --sidebar-foreground: hsl(240 5.3% 26.1%);
34
+ --sidebar-primary: hsl(240 5.9% 10%);
35
+ --sidebar-primary-foreground: hsl(0 0% 98%);
36
+ --sidebar-accent: hsl(240 4.8% 95.9%);
37
+ --sidebar-accent-foreground: hsl(240 5.9% 10%);
38
+ --sidebar-border: hsl(220 13% 91%);
39
+ --sidebar-ring: hsl(217.2 91.2% 59.8%);
40
+ }
41
+
42
+ .dark {
43
+ /* Main colors */
44
+ --background: hsl(240 10% 3.9%);
45
+ --foreground: hsl(0 0% 98%);
46
+ --card: hsl(240 10% 7%);
47
+ --card-foreground: hsl(0 0% 98%);
48
+ --popover: hsl(240 10% 7%);
49
+ --popover-foreground: hsl(0 0% 98%);
50
+ --primary: hsl(0 0% 98%);
51
+ --primary-foreground: hsl(240 5.9% 10%);
52
+ --secondary: hsl(240 3.7% 15.9%);
53
+ --secondary-foreground: hsl(0 0% 98%);
54
+ --muted: hsl(240 3.7% 15.9%);
55
+ --muted-foreground: hsl(240 5% 64.9%);
56
+ --accent: hsl(240 3.7% 15.9%);
57
+ --accent-foreground: hsl(0 0% 98%);
58
+ --destructive: hsl(0 62.8% 50.6%);
59
+ --destructive-foreground: hsl(0 0% 98%);
60
+ --border: hsl(240 3.7% 20%);
61
+ --input: hsl(240 3.7% 20%);
62
+ --ring: hsl(240 4.9% 83.9%);
63
+
64
+ /* Sidebar */
65
+ --sidebar: hsl(240 5.9% 10%);
66
+ --sidebar-foreground: hsl(240 4.8% 95.9%);
67
+ --sidebar-primary: hsl(224.3 76.3% 48%);
68
+ --sidebar-primary-foreground: hsl(0 0% 100%);
69
+ --sidebar-accent: hsl(240 3.7% 15.9%);
70
+ --sidebar-accent-foreground: hsl(240 4.8% 95.9%);
71
+ --sidebar-border: hsl(240 3.7% 15.9%);
72
+ --sidebar-ring: hsl(217.2 91.2% 59.8%);
73
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Admin UI Type Definitions
3
+ *
4
+ * Since the admin UI has its own Convex schema (only settings table),
5
+ * we define CMS entity types locally rather than using Doc<> from generated types.
6
+ * These types mirror the CMS component's document structure.
7
+ */
8
+
9
+ // =============================================================================
10
+ // Field Definition Types
11
+ // =============================================================================
12
+
13
+ export type FieldType =
14
+ | "text"
15
+ | "number"
16
+ | "boolean"
17
+ | "richText"
18
+ | "media"
19
+ | "select"
20
+ | "multiSelect"
21
+ | "tags"
22
+ | "category"
23
+ | "json"
24
+ | "date"
25
+ | "datetime"
26
+ | "reference";
27
+
28
+ export interface FieldDefinition {
29
+ name: string;
30
+ displayName: string;
31
+ type: FieldType;
32
+ required?: boolean;
33
+ description?: string;
34
+ options?: Record<string, unknown>;
35
+ }
36
+
37
+ // =============================================================================
38
+ // Content Type
39
+ // =============================================================================
40
+
41
+ export interface ContentType {
42
+ _id: string;
43
+ _creationTime: number;
44
+ name: string;
45
+ displayName: string;
46
+ description?: string;
47
+ icon?: string;
48
+ fields: FieldDefinition[];
49
+ singleton: boolean;
50
+ slugField?: string;
51
+ titleField?: string;
52
+ sortOrder: number;
53
+ isActive: boolean;
54
+ createdBy: string;
55
+ updatedBy?: string;
56
+ }
57
+
58
+ export type ContentTypeWithCount = ContentType & {
59
+ entryCount?: number;
60
+ };
61
+
62
+ // =============================================================================
63
+ // Content Entry
64
+ // =============================================================================
65
+
66
+ export type ContentStatus = "draft" | "published" | "scheduled" | "archived";
67
+
68
+ export interface ContentEntry {
69
+ _id: string;
70
+ _creationTime: number;
71
+ contentTypeId: string;
72
+ slug?: string;
73
+ data: Record<string, unknown>;
74
+ status: ContentStatus;
75
+ version: number;
76
+ locale?: string;
77
+ primaryEntryId?: string;
78
+ publishedAt?: number;
79
+ scheduledPublishAt?: number;
80
+ archivedAt?: number;
81
+ createdBy?: string;
82
+ updatedBy?: string;
83
+ deletedAt?: number;
84
+ deletedBy?: string;
85
+ }
86
+
87
+ // =============================================================================
88
+ // Content Version
89
+ // =============================================================================
90
+
91
+ export interface ContentVersion {
92
+ _id: string;
93
+ _creationTime: number;
94
+ entryId: string;
95
+ version: number;
96
+ data: Record<string, unknown>;
97
+ status: ContentStatus;
98
+ changeDescription?: string;
99
+ createdBy?: string;
100
+ }
101
+
102
+ // =============================================================================
103
+ // Media Item
104
+ // =============================================================================
105
+
106
+ export type MediaItemKind = "asset" | "folder";
107
+ export type MediaType = "image" | "video" | "audio" | "document" | "other";
108
+
109
+ export interface MediaItem {
110
+ _id: string;
111
+ _creationTime: number;
112
+ kind: MediaItemKind;
113
+ name: string;
114
+ parentId?: string;
115
+ path?: string;
116
+ sortOrder?: number;
117
+ createdBy?: string;
118
+ deletedAt?: number;
119
+ deletedBy?: string;
120
+ // Asset-specific fields
121
+ storageId?: string;
122
+ mimeType?: string;
123
+ size?: number;
124
+ type?: MediaType;
125
+ width?: number;
126
+ height?: number;
127
+ duration?: number;
128
+ title?: string;
129
+ description?: string;
130
+ altText?: string;
131
+ tags?: string[];
132
+ // Folder-specific fields
133
+ folderDescription?: string;
134
+ }
135
+
136
+ // =============================================================================
137
+ // Media Variant
138
+ // =============================================================================
139
+
140
+ export interface MediaVariant {
141
+ _id: string;
142
+ _creationTime: number;
143
+ assetId: string;
144
+ name: string;
145
+ storageId: string;
146
+ width?: number;
147
+ height?: number;
148
+ format?: string;
149
+ }
150
+
151
+ // =============================================================================
152
+ // Taxonomy
153
+ // =============================================================================
154
+
155
+ export interface Taxonomy {
156
+ _id: string;
157
+ _creationTime: number;
158
+ name: string;
159
+ displayName: string;
160
+ description?: string;
161
+ isHierarchical: boolean;
162
+ allowInlineCreation: boolean;
163
+ isActive: boolean;
164
+ icon?: string;
165
+ sortOrder?: number;
166
+ createdBy?: string;
167
+ deletedAt?: number;
168
+ deletedBy?: string;
169
+ }
170
+
171
+ // =============================================================================
172
+ // Taxonomy Term
173
+ // =============================================================================
174
+
175
+ export interface TaxonomyTerm {
176
+ _id: string;
177
+ _creationTime: number;
178
+ taxonomyId: string;
179
+ name: string;
180
+ slug: string;
181
+ description?: string;
182
+ parentId?: string;
183
+ sortOrder?: number;
184
+ color?: string;
185
+ metadata?: Record<string, unknown>;
186
+ createdBy?: string;
187
+ deletedAt?: number;
188
+ deletedBy?: string;
189
+ }
190
+
191
+ export type TaxonomyTermWithChildren = TaxonomyTerm & {
192
+ children?: TaxonomyTermWithChildren[];
193
+ };
194
+
195
+ // =============================================================================
196
+ // ID Types (string aliases for documentation)
197
+ // =============================================================================
198
+
199
+ export type ContentTypeId = string;
200
+ export type ContentEntryId = string;
201
+ export type ContentVersionId = string;
202
+ export type MediaItemId = string;
203
+ export type MediaVariantId = string;
204
+ export type TaxonomyId = string;
205
+ export type TaxonomyTermId = string;
206
+
207
+ // =============================================================================
208
+ // Type Assertion Helpers
209
+ // =============================================================================
210
+
211
+ export function asTaxonomyId(id: string): TaxonomyId {
212
+ return id;
213
+ }
214
+
215
+ export function asTaxonomyTermId(id: string): TaxonomyTermId {
216
+ return id;
217
+ }
218
+
219
+ export function asTaxonomyTermIds(ids: string[]): TaxonomyTermId[] {
220
+ return ids;
221
+ }
@@ -0,0 +1,163 @@
1
+ import type { FieldError } from '../components/fields/types';
2
+
3
+ /**
4
+ * Parses server validation errors into field-level errors.
5
+ *
6
+ * Supported error formats:
7
+ * 1. JSON format: {"errors": [{"field": "name", "message": "error"}]}
8
+ * 2. Structured text: "Content validation failed: field1: error1; field2: error2"
9
+ * 3. Plain message: "Some error message"
10
+ *
11
+ * @param error - The error to parse (Error object or string)
12
+ * @returns Object with fieldErrors map and a general error message
13
+ */
14
+ export function parseServerError(
15
+ error: Error | string | unknown
16
+ ): { fieldErrors: Record<string, FieldError>; generalError: string | null } {
17
+ const result: { fieldErrors: Record<string, FieldError>; generalError: string | null } = {
18
+ fieldErrors: {},
19
+ generalError: null,
20
+ };
21
+
22
+ if (!error) {
23
+ return result;
24
+ }
25
+
26
+ const message = error instanceof Error ? error.message : String(error);
27
+
28
+ // Try to parse JSON error format first
29
+ try {
30
+ // Check if the error message contains JSON
31
+ const jsonMatch = message.match(/\{[\s\S]*\}/);
32
+ if (jsonMatch) {
33
+ const parsed = JSON.parse(jsonMatch[0]);
34
+
35
+ // Handle {"errors": [{"field": "...", "message": "..."}]} format
36
+ if (Array.isArray(parsed.errors)) {
37
+ for (const err of parsed.errors) {
38
+ if (err.field && err.message) {
39
+ result.fieldErrors[err.field] = {
40
+ message: err.message,
41
+ code: err.code ?? 'SERVER_ERROR',
42
+ };
43
+ }
44
+ }
45
+ if (Object.keys(result.fieldErrors).length > 0) {
46
+ return result;
47
+ }
48
+ }
49
+
50
+ // Handle {"field": "...", "message": "..."} format (single error)
51
+ if (parsed.field && parsed.message) {
52
+ result.fieldErrors[parsed.field] = {
53
+ message: parsed.message,
54
+ code: parsed.code ?? 'SERVER_ERROR',
55
+ };
56
+ return result;
57
+ }
58
+
59
+ // Handle {fieldName: errorMessage} format
60
+ if (typeof parsed === 'object' && !Array.isArray(parsed)) {
61
+ let hasFieldErrors = false;
62
+ for (const [key, value] of Object.entries(parsed)) {
63
+ if (typeof value === 'string' && key !== 'message' && key !== 'code') {
64
+ result.fieldErrors[key] = {
65
+ message: value,
66
+ code: 'SERVER_ERROR',
67
+ };
68
+ hasFieldErrors = true;
69
+ }
70
+ }
71
+ if (hasFieldErrors) {
72
+ return result;
73
+ }
74
+ }
75
+ }
76
+ } catch {
77
+ // JSON parsing failed, continue with text parsing
78
+ }
79
+
80
+ // Try to parse "Content validation failed:" format
81
+ const validationPattern = /(?:Content validation failed|Validation error|Validation failed):\s*(.+)/i;
82
+ const validationMatch = message.match(validationPattern);
83
+
84
+ if (validationMatch) {
85
+ const errorPart = validationMatch[1].trim();
86
+
87
+ // Split by semicolon to get individual field errors
88
+ const fieldErrorParts = errorPart.split(/;\s*/);
89
+
90
+ for (const part of fieldErrorParts) {
91
+ // Try to extract "fieldName: errorMessage" pattern
92
+ const colonIndex = part.indexOf(':');
93
+ if (colonIndex > 0 && colonIndex < part.length - 1) {
94
+ const fieldName = part.substring(0, colonIndex).trim();
95
+ const errorMsg = part.substring(colonIndex + 1).trim();
96
+
97
+ // Validate field name looks reasonable (no spaces, reasonable length)
98
+ if (fieldName && !fieldName.includes(' ') && fieldName.length <= 50 && errorMsg) {
99
+ result.fieldErrors[fieldName] = {
100
+ message: errorMsg,
101
+ code: 'SERVER_ERROR',
102
+ };
103
+ }
104
+ }
105
+ }
106
+
107
+ if (Object.keys(result.fieldErrors).length > 0) {
108
+ return result;
109
+ }
110
+ }
111
+
112
+ // If we couldn't parse field errors, return the general error message
113
+ result.generalError = message;
114
+ return result;
115
+ }
116
+
117
+ /**
118
+ * Format an error for display to users.
119
+ * Removes technical details and provides a user-friendly message.
120
+ */
121
+ export function formatErrorForDisplay(error: Error | string | unknown): string {
122
+ if (!error) {
123
+ return 'An unexpected error occurred';
124
+ }
125
+
126
+ const message = error instanceof Error ? error.message : String(error);
127
+
128
+ // Remove common technical prefixes
129
+ const cleanedMessage = message
130
+ .replace(/^(Error|ConvexError|ValidationError|ServerError):\s*/i, '')
131
+ .replace(/^\[.*?\]\s*/, ''); // Remove bracketed prefixes like [HTTP 500]
132
+
133
+ // Capitalize first letter
134
+ return cleanedMessage.charAt(0).toUpperCase() + cleanedMessage.slice(1);
135
+ }
136
+
137
+ /**
138
+ * Determines if an error is likely transient (network issue, timeout)
139
+ * and worth retrying automatically.
140
+ */
141
+ export function isRetryableError(error: Error | string | unknown): boolean {
142
+ if (!error) return false;
143
+
144
+ const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
145
+
146
+ const retryablePatterns = [
147
+ 'network',
148
+ 'timeout',
149
+ 'timed out',
150
+ 'connection',
151
+ 'fetch failed',
152
+ 'failed to fetch',
153
+ 'offline',
154
+ 'unavailable',
155
+ 'rate limit',
156
+ 'too many requests',
157
+ '503',
158
+ '504',
159
+ '429',
160
+ ];
161
+
162
+ return retryablePatterns.some(pattern => message.includes(pattern));
163
+ }
@@ -0,0 +1,5 @@
1
+ export {
2
+ parseServerError,
3
+ formatErrorForDisplay,
4
+ isRetryableError,
5
+ } from './errorParsing';
@@ -0,0 +1,14 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ readonly VITE_CONVEX_URL: string
5
+ }
6
+
7
+ interface ImportMeta {
8
+ readonly env: ImportMetaEnv
9
+ }
10
+
11
+ declare module '*.css?url' {
12
+ const url: string
13
+ export default url
14
+ }