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.
- package/README.md +107 -60
- package/admin/README.md +99 -0
- package/admin/src/components/AdminLayout.tsx +22 -0
- package/admin/src/components/BreakingChangesWarningDialog.tsx +81 -0
- package/admin/src/components/BulkActionBar.tsx +190 -0
- package/admin/src/components/BulkOperationModal.tsx +177 -0
- package/admin/src/components/ContentEntryEditor.tsx +1104 -0
- package/admin/src/components/ContentTypeFormModal.tsx +1012 -0
- package/admin/src/components/ErrorBoundary.tsx +83 -0
- package/admin/src/components/ErrorState.tsx +147 -0
- package/admin/src/components/Header.tsx +294 -0
- package/admin/src/components/RouteGuard.tsx +264 -0
- package/admin/src/components/Sidebar.tsx +90 -0
- package/admin/src/components/TaxonomyEditor.tsx +348 -0
- package/admin/src/components/TermTree.tsx +533 -0
- package/admin/src/components/UploadDropzone.tsx +383 -0
- package/admin/src/components/VersionCompare.tsx +250 -0
- package/admin/src/components/VersionHistory.tsx +279 -0
- package/admin/src/components/VersionRollbackModal.tsx +79 -0
- package/admin/src/components/cmsds/CmsButton.tsx +101 -0
- package/admin/src/components/cmsds/CmsDialog.tsx +139 -0
- package/admin/src/components/cmsds/CmsDropdown.tsx +62 -0
- package/admin/src/components/cmsds/CmsEmptyState.tsx +54 -0
- package/admin/src/components/cmsds/CmsField.tsx +47 -0
- package/admin/src/components/cmsds/CmsPageHeader.tsx +35 -0
- package/admin/src/components/cmsds/CmsStatusBadge.tsx +153 -0
- package/admin/src/components/cmsds/CmsSurface.tsx +52 -0
- package/admin/src/components/cmsds/CmsTable.tsx +164 -0
- package/admin/src/components/cmsds/CmsToolbar.tsx +58 -0
- package/admin/src/components/cmsds/index.ts +10 -0
- package/admin/src/components/fields/BooleanField.tsx +74 -0
- package/admin/src/components/fields/CategoryField.tsx +394 -0
- package/admin/src/components/fields/DateField.tsx +173 -0
- package/admin/src/components/fields/DefaultFieldRenderer.tsx +74 -0
- package/admin/src/components/fields/FieldRenderer.tsx +180 -0
- package/admin/src/components/fields/FieldWrapper.tsx +57 -0
- package/admin/src/components/fields/JsonField.tsx +172 -0
- package/admin/src/components/fields/MediaField.tsx +367 -0
- package/admin/src/components/fields/MultiSelectField.tsx +118 -0
- package/admin/src/components/fields/NumberField.tsx +77 -0
- package/admin/src/components/fields/ReferenceField.tsx +386 -0
- package/admin/src/components/fields/RichTextField.tsx +171 -0
- package/admin/src/components/fields/SelectField.tsx +62 -0
- package/admin/src/components/fields/TagField.tsx +325 -0
- package/admin/src/components/fields/TextAreaField.tsx +68 -0
- package/admin/src/components/fields/TextField.tsx +56 -0
- package/admin/src/components/fields/index.ts +54 -0
- package/admin/src/components/fields/registry.ts +64 -0
- package/admin/src/components/fields/types.ts +217 -0
- package/admin/src/components/filters/TaxonomyFilter.tsx +254 -0
- package/admin/src/components/filters/index.ts +1 -0
- package/admin/src/components/index.ts +8 -0
- package/admin/src/components/media/MediaAssetActions.tsx +115 -0
- package/admin/src/components/media/MediaAssetEditDialog.tsx +217 -0
- package/admin/src/components/media/MediaBulkActionBar.tsx +51 -0
- package/admin/src/components/media/MediaFolderActions.tsx +69 -0
- package/admin/src/components/media/MediaFolderEditDialog.tsx +126 -0
- package/admin/src/components/media/MediaMoveModal.tsx +179 -0
- package/admin/src/components/media/MediaPreviewModal.tsx +370 -0
- package/admin/src/components/media/MediaTaxonomyPicker.tsx +304 -0
- package/admin/src/components/media/MediaTrashBulkActionBar.tsx +59 -0
- package/admin/src/components/ui/accordion.tsx +64 -0
- package/admin/src/components/ui/alert-dialog.tsx +155 -0
- package/admin/src/components/ui/alert.tsx +66 -0
- package/admin/src/components/ui/avatar.tsx +53 -0
- package/admin/src/components/ui/badge.tsx +46 -0
- package/admin/src/components/ui/breadcrumb.tsx +109 -0
- package/admin/src/components/ui/button.tsx +62 -0
- package/admin/src/components/ui/calendar.tsx +220 -0
- package/admin/src/components/ui/card.tsx +92 -0
- package/admin/src/components/ui/checkbox.tsx +30 -0
- package/admin/src/components/ui/command.tsx +182 -0
- package/admin/src/components/ui/dialog.tsx +143 -0
- package/admin/src/components/ui/dropdown-menu.tsx +257 -0
- package/admin/src/components/ui/form.tsx +167 -0
- package/admin/src/components/ui/input.tsx +21 -0
- package/admin/src/components/ui/label.tsx +24 -0
- package/admin/src/components/ui/popover.tsx +46 -0
- package/admin/src/components/ui/scroll-area.tsx +56 -0
- package/admin/src/components/ui/select.tsx +190 -0
- package/admin/src/components/ui/separator.tsx +26 -0
- package/admin/src/components/ui/sheet.tsx +137 -0
- package/admin/src/components/ui/sidebar.tsx +724 -0
- package/admin/src/components/ui/skeleton.tsx +13 -0
- package/admin/src/components/ui/sonner.tsx +38 -0
- package/admin/src/components/ui/switch.tsx +31 -0
- package/admin/src/components/ui/table.tsx +114 -0
- package/admin/src/components/ui/tabs.tsx +66 -0
- package/admin/src/components/ui/textarea.tsx +18 -0
- package/admin/src/components/ui/tooltip.tsx +61 -0
- package/admin/src/contexts/AdminConfigContext.tsx +30 -0
- package/admin/src/contexts/AuthContext.tsx +330 -0
- package/admin/src/contexts/BreadcrumbContext.tsx +49 -0
- package/admin/src/contexts/SettingsConfigContext.tsx +57 -0
- package/admin/src/contexts/ThemeContext.tsx +91 -0
- package/admin/src/contexts/index.ts +20 -0
- package/admin/src/embed/components/EmbedHeader.tsx +103 -0
- package/admin/src/embed/components/EmbedLayout.tsx +29 -0
- package/admin/src/embed/components/EmbedSidebar.tsx +119 -0
- package/admin/src/embed/components/index.ts +3 -0
- package/admin/src/embed/contexts/ApiContext.tsx +32 -0
- package/admin/src/embed/index.tsx +184 -0
- package/admin/src/embed/navigation.tsx +202 -0
- package/admin/src/embed/pages/Content.tsx +19 -0
- package/admin/src/embed/pages/ContentTypes.tsx +19 -0
- package/admin/src/embed/pages/Dashboard.tsx +19 -0
- package/admin/src/embed/pages/Media.tsx +19 -0
- package/admin/src/embed/pages/Settings.tsx +22 -0
- package/admin/src/embed/pages/Taxonomies.tsx +22 -0
- package/admin/src/embed/pages/Trash.tsx +22 -0
- package/admin/src/embed/pages/index.ts +7 -0
- package/admin/src/embed/types.ts +24 -0
- package/admin/src/hooks/index.ts +2 -0
- package/admin/src/hooks/use-mobile.ts +19 -0
- package/admin/src/hooks/useBreadcrumbLabel.ts +15 -0
- package/admin/src/hooks/usePermissions.ts +211 -0
- package/admin/src/lib/admin-config.ts +111 -0
- package/admin/src/lib/cn.ts +6 -0
- package/admin/src/lib/config.server.ts +56 -0
- package/admin/src/lib/convex.ts +26 -0
- package/admin/src/lib/embed-adapter.ts +80 -0
- package/admin/src/lib/icons.tsx +96 -0
- package/admin/src/lib/loadAdminConfig.ts +92 -0
- package/admin/src/lib/motion.ts +29 -0
- package/admin/src/lib/navigation.ts +43 -0
- package/admin/src/lib/tanstack-adapter.ts +82 -0
- package/admin/src/pages/ContentPage.tsx +337 -0
- package/admin/src/pages/ContentTypesPage.tsx +457 -0
- package/admin/src/pages/DashboardPage.tsx +163 -0
- package/admin/src/pages/MediaPage.tsx +34 -0
- package/admin/src/pages/SettingsPage.tsx +486 -0
- package/admin/src/pages/TaxonomiesPage.tsx +289 -0
- package/admin/src/pages/TrashPage.tsx +421 -0
- package/admin/src/pages/index.ts +14 -0
- package/admin/src/routeTree.gen.ts +262 -0
- package/admin/src/router.tsx +22 -0
- package/admin/src/routes/__root.tsx +250 -0
- package/admin/src/routes/content-types.tsx +20 -0
- package/admin/src/routes/content.tsx +20 -0
- package/admin/src/routes/entries/$entryId.tsx +107 -0
- package/admin/src/routes/entries/new.$contentTypeId.tsx +69 -0
- package/admin/src/routes/entries/type/$contentTypeId.tsx +503 -0
- package/admin/src/routes/index.tsx +20 -0
- package/admin/src/routes/media.tsx +1095 -0
- package/admin/src/routes/settings.tsx +20 -0
- package/admin/src/routes/taxonomies.tsx +20 -0
- package/admin/src/routes/trash.tsx +20 -0
- package/admin/src/styles/globals.css +69 -0
- package/admin/src/styles/tailwind-config.css +74 -0
- package/admin/src/styles/theme.css +73 -0
- package/admin/src/types/index.ts +221 -0
- package/admin/src/utils/errorParsing.ts +163 -0
- package/admin/src/utils/index.ts +5 -0
- package/admin/src/vite-env.d.ts +14 -0
- package/admin/tailwind.preset.cjs +102 -0
- package/admin-dist/nitro.json +1 -1
- package/admin-dist/public/assets/{CmsEmptyState-CRswfTzk.js → CmsEmptyState-CkqBIab3.js} +2 -2
- package/admin-dist/public/assets/{CmsPageHeader-CirpXndm.js → CmsPageHeader-CUtl5MMG.js} +1 -1
- package/admin-dist/public/assets/{CmsStatusBadge-CbEUpQu-.js → CmsStatusBadge-CUYFgEe-.js} +1 -1
- package/admin-dist/public/assets/CmsSurface-CsJfAVa3.js +1 -0
- package/admin-dist/public/assets/{CmsToolbar-BI2nZOXp.js → CmsToolbar-CnfbcxeP.js} +1 -1
- package/admin-dist/public/assets/{ContentEntryEditor-CBeCyK_m.js → ContentEntryEditor-BU220CCy.js} +1 -1
- package/admin-dist/public/assets/TaxonomyFilter-CWCxC5HZ.js +1 -0
- package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +1 -0
- package/admin-dist/public/assets/{_entryId-CKU_glsK.js → _entryId-CuVMExbb.js} +1 -1
- package/admin-dist/public/assets/alert-CF1BSzGR.js +1 -0
- package/admin-dist/public/assets/{badge-hvUOzpVZ.js → badge-CmuOIVKp.js} +1 -1
- package/admin-dist/public/assets/{circle-check-big-CF_pR17r.js → circle-check-big-BKDVG6DU.js} +1 -1
- package/admin-dist/public/assets/{command-DU82cJlt.js → command-XJxnF2Sd.js} +1 -1
- package/admin-dist/public/assets/content-QBUxdxbS.js +1 -0
- package/admin-dist/public/assets/content-types-CrNEm8Hf.js +2 -0
- package/admin-dist/public/assets/globals-B7Wsfh_v.css +1 -0
- package/admin-dist/public/assets/index-C7xOwudI.js +1 -0
- package/admin-dist/public/assets/{label-KNtpL71g.js → label-CHCnXeBk.js} +1 -1
- package/admin-dist/public/assets/{link-2-Bw2aI4V4.js → link-2-Bb34judH.js} +1 -1
- package/admin-dist/public/assets/{list-sYepHjt_.js → list-9Pzt48ld.js} +1 -1
- package/admin-dist/public/assets/{main-CKj5yfEi.js → main-CjQ2VI9L.js} +3 -3
- package/admin-dist/public/assets/media-Dc5PWt2Q.js +1 -0
- package/admin-dist/public/assets/{new._contentTypeId-C3LstjNs.js → new._contentTypeId-C_I4YxIa.js} +1 -1
- package/admin-dist/public/assets/{plus-DUn8v_Xf.js → plus-Ceef7DHk.js} +1 -1
- package/admin-dist/public/assets/{rotate-ccw-DJEoHcRI.js → rotate-ccw-7k7-4VUq.js} +1 -1
- package/admin-dist/public/assets/scroll-area-CC6wujnp.js +1 -0
- package/admin-dist/public/assets/{search-MuAUDJKR.js → search-DwoUV2pv.js} +1 -1
- package/admin-dist/public/assets/select-hOZTp8aC.js +1 -0
- package/admin-dist/public/assets/settings-t2PbCZh4.js +1 -0
- package/admin-dist/public/assets/switch-jX2pDaNU.js +1 -0
- package/admin-dist/public/assets/tabs-q4EbZk7c.js +1 -0
- package/admin-dist/public/assets/tanstack-adapter-B-Glm4kH.js +1 -0
- package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +1 -0
- package/admin-dist/public/assets/{textarea-BTy7nwzR.js → textarea-B6SfBmr0.js} +1 -1
- package/admin-dist/public/assets/trash-BOCnIznD.js +1 -0
- package/admin-dist/public/assets/{triangle-alert-E52Vfeuh.js → triangle-alert-CXFIO_Gu.js} +1 -1
- package/admin-dist/public/assets/useBreadcrumbLabel-_6qBagc3.js +1 -0
- package/admin-dist/public/assets/{usePermissions-Basjs9BT.js → usePermissions-M1ijZ7a6.js} +1 -1
- package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +7 -0
- package/admin-dist/server/_ssr/{badge-6BsP37vG.mjs → CmsButton-DOiTVKQq.mjs} +33 -33
- package/admin-dist/server/_ssr/{CmsEmptyState-DU7-7-mV.mjs → CmsEmptyState-fbnGt3LD.mjs} +2 -2
- package/admin-dist/server/_ssr/{CmsPageHeader-CseW0AHm.mjs → CmsPageHeader-DHRrdOZa.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsStatusBadge-B_pi4KCp.mjs → CmsStatusBadge-s7obWbKZ.mjs} +2 -2
- package/admin-dist/server/_ssr/CmsSurface-rFoYjb62.mjs +44 -0
- package/admin-dist/server/_ssr/{CmsToolbar-X75ex6ek.mjs → CmsToolbar-zTE45z2q.mjs} +2 -2
- package/admin-dist/server/_ssr/{ContentEntryEditor-CepusRsA.mjs → ContentEntryEditor-BLoEjT_m.mjs} +12 -12
- package/admin-dist/server/_ssr/{TaxonomyFilter-Bwrq0-cz.mjs → TaxonomyFilter-XAtaJC2z.mjs} +5 -5
- package/admin-dist/server/_ssr/{_contentTypeId-BqYKEcLr.mjs → _contentTypeId-Csl4822C.mjs} +13 -13
- package/admin-dist/server/_ssr/{_entryId-CRfnqeDf.mjs → _entryId-D8alLFBx.mjs} +15 -15
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +4 -0
- package/admin-dist/server/_ssr/{command-fy8epIKf.mjs → command-C0Di14--.mjs} +1 -1
- package/admin-dist/server/_ssr/{content-B5RhL7uW.mjs → content-CT-FPsmV.mjs} +170 -98
- package/admin-dist/server/_ssr/{content-types-BIOqCQYN.mjs → content-types-C8cBFdzE.mjs} +260 -115
- package/admin-dist/server/_ssr/{index-DHSHDPt1.mjs → index-BJtcrEc-.mjs} +88 -17
- package/admin-dist/server/_ssr/index.mjs +2 -2
- package/admin-dist/server/_ssr/{label-C8Dko1j7.mjs → label-qn2Afwl4.mjs} +1 -1
- package/admin-dist/server/_ssr/{media-CSx3XttC.mjs → media-qv5IAsMZ.mjs} +43 -43
- package/admin-dist/server/_ssr/{new._contentTypeId-DzanEZQM.mjs → new._contentTypeId-DdGyrhqs.mjs} +13 -13
- package/admin-dist/server/_ssr/{router-DDWcF-kt.mjs → router-nSVkxb6Y.mjs} +11 -11
- package/admin-dist/server/_ssr/{scroll-area-bjPYwhXN.mjs → scroll-area-BCinP455.mjs} +1 -1
- package/admin-dist/server/_ssr/{select-BUhDDf4T.mjs → select-BKQlQScw.mjs} +1 -1
- package/admin-dist/server/_ssr/{settings-DAsxnw2q.mjs → settings-BCr2KQlk.mjs} +236 -139
- package/admin-dist/server/_ssr/{switch-BgyRtQ1Z.mjs → switch-BaOi42fE.mjs} +1 -1
- package/admin-dist/server/_ssr/{tabs-DzMdRB1A.mjs → tabs-DYXEi9kq.mjs} +5 -3
- package/admin-dist/server/_ssr/tanstack-adapter-Bsz8kha-.mjs +119 -0
- package/admin-dist/server/_ssr/{taxonomies-C8j8g5Q5.mjs → taxonomies-CueMHTbE.mjs} +184 -73
- package/admin-dist/server/_ssr/{textarea-9jNeYJSc.mjs → textarea-CI0Jqx2x.mjs} +1 -1
- package/admin-dist/server/_ssr/{trash-DYMxwhZB.mjs → trash-DE6W8GoX.mjs} +211 -88
- package/admin-dist/server/_ssr/{useBreadcrumbLabel-FNSAr2Ha.mjs → useBreadcrumbLabel-B5Yi72lM.mjs} +1 -1
- package/admin-dist/server/_ssr/{usePermissions-BJGGahrJ.mjs → usePermissions-C3nZ-Izm.mjs} +1 -1
- package/admin-dist/server/index.mjs +189 -182
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +156 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/client/admin/bulk.d.ts +79 -0
- package/dist/client/admin/bulk.d.ts.map +1 -0
- package/dist/client/admin/bulk.js +72 -0
- package/dist/client/admin/bulk.js.map +1 -0
- package/dist/client/admin/contentLock.d.ts +118 -0
- package/dist/client/admin/contentLock.d.ts.map +1 -0
- package/dist/client/admin/contentLock.js +81 -0
- package/dist/client/admin/contentLock.js.map +1 -0
- package/dist/client/admin/contentTypes.d.ts +1204 -0
- package/dist/client/admin/contentTypes.d.ts.map +1 -0
- package/dist/client/admin/contentTypes.js +122 -0
- package/dist/client/admin/contentTypes.js.map +1 -0
- package/dist/client/admin/dashboard.d.ts +16 -0
- package/dist/client/admin/dashboard.d.ts.map +1 -0
- package/dist/client/admin/dashboard.js +33 -0
- package/dist/client/admin/dashboard.js.map +1 -0
- package/dist/client/admin/entries.d.ts +358 -0
- package/dist/client/admin/entries.d.ts.map +1 -0
- package/dist/client/admin/entries.js +220 -0
- package/dist/client/admin/entries.js.map +1 -0
- package/dist/client/admin/index.d.ts +6568 -0
- package/dist/client/admin/index.d.ts.map +1 -0
- package/dist/client/admin/index.js +305 -0
- package/dist/client/admin/index.js.map +1 -0
- package/dist/client/admin/media.d.ts +1038 -0
- package/dist/client/admin/media.d.ts.map +1 -0
- package/dist/client/admin/media.js +489 -0
- package/dist/client/admin/media.js.map +1 -0
- package/dist/client/admin/taxonomies.d.ts +339 -0
- package/dist/client/admin/taxonomies.d.ts.map +1 -0
- package/dist/client/admin/taxonomies.js +364 -0
- package/dist/client/admin/taxonomies.js.map +1 -0
- package/dist/client/admin/trash.d.ts +91 -0
- package/dist/client/admin/trash.d.ts.map +1 -0
- package/dist/client/admin/trash.js +71 -0
- package/dist/client/admin/trash.js.map +1 -0
- package/dist/client/admin/types.d.ts +320 -0
- package/dist/client/admin/types.d.ts.map +1 -0
- package/dist/client/admin/types.js +7 -0
- package/dist/client/admin/types.js.map +1 -0
- package/dist/client/admin/validators.d.ts +3886 -0
- package/dist/client/admin/validators.d.ts.map +1 -0
- package/dist/client/admin/validators.js +322 -0
- package/dist/client/admin/validators.js.map +1 -0
- package/dist/client/admin/versions.d.ts +106 -0
- package/dist/client/admin/versions.d.ts.map +1 -0
- package/dist/client/admin/versions.js +57 -0
- package/dist/client/admin/versions.js.map +1 -0
- package/dist/client/adminApiTypes.d.ts +27 -0
- package/dist/client/adminApiTypes.d.ts.map +1 -0
- package/dist/client/adminApiTypes.js +12 -0
- package/dist/client/adminApiTypes.js.map +1 -0
- package/dist/client/{admin-config.d.ts → adminConfig.d.ts} +4 -4
- package/dist/client/adminConfig.d.ts.map +1 -0
- package/dist/client/{admin-config.js → adminConfig.js} +3 -3
- package/dist/client/adminConfig.js.map +1 -0
- package/dist/client/agentTools.d.ts +11 -21
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/client/agentTools.js +4 -4
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +19 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/schema/codegen.d.ts +2 -2
- package/dist/client/schema/codegen.d.ts.map +1 -1
- package/dist/client/schema/codegen.js +3 -3
- package/dist/client/schema/codegen.js.map +1 -1
- package/dist/client/schema/defineContentType.d.ts +3 -3
- package/dist/client/schema/defineContentType.js +3 -3
- package/dist/client/schema/index.d.ts +7 -7
- package/dist/client/schema/index.d.ts.map +1 -1
- package/dist/client/schema/index.js +5 -5
- package/dist/client/schema/index.js.map +1 -1
- package/dist/client/schema/schemaDrift.d.ts +1 -1
- package/dist/client/schema/schemaDrift.js +1 -1
- package/dist/client/schema/typedClient.d.ts +2 -2
- package/dist/client/schema/typedClient.js +2 -2
- package/dist/client/schema/types.d.ts +1 -1
- package/dist/client/schema/types.js +1 -1
- package/dist/client/wrapper.d.ts +108 -65
- package/dist/client/wrapper.d.ts.map +1 -1
- package/dist/client/wrapper.js +22 -22
- package/dist/client/wrapper.js.map +1 -1
- package/dist/component/contentEntries.d.ts +4 -4
- package/dist/component/contentEntryMutations.d.ts +46 -0
- package/dist/component/contentEntryMutations.d.ts.map +1 -1
- package/dist/component/contentEntryMutations.js +1 -1
- package/dist/component/contentEntryMutations.js.map +1 -1
- package/dist/component/contentTypeMigration.d.ts +1 -1
- package/dist/component/contentTypeMutations.d.ts +22 -0
- package/dist/component/contentTypeMutations.d.ts.map +1 -1
- package/dist/component/contentTypeMutations.js +1 -1
- package/dist/component/contentTypeMutations.js.map +1 -1
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/convex.config.js +2 -2
- package/dist/component/index.d.ts +1 -1
- package/dist/component/index.js +1 -1
- package/dist/component/lib/ragContentChunker.d.ts +1 -1
- package/dist/component/lib/ragContentChunker.js +1 -1
- package/dist/component/mediaAssetMutations.d.ts +47 -0
- package/dist/component/mediaAssetMutations.d.ts.map +1 -1
- package/dist/component/mediaAssetMutations.js +1 -1
- package/dist/component/mediaAssetMutations.js.map +1 -1
- package/dist/component/roles.d.ts +1 -1
- package/dist/component/roles.js +1 -1
- package/dist/component/schema.d.ts +9 -0
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +1 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +13 -7
- package/dist/react/index.js.map +1 -1
- package/dist/test.d.ts +2 -2
- package/dist/test.js +2 -2
- package/package.json +115 -13
- package/admin-dist/public/assets/ErrorState-BIVaWmom.js +0 -1
- package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +0 -1
- package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +0 -1
- package/admin-dist/public/assets/alert-BXjTqrwQ.js +0 -1
- package/admin-dist/public/assets/content-_LXl3pp7.js +0 -1
- package/admin-dist/public/assets/content-types-KjxaXGxY.js +0 -2
- package/admin-dist/public/assets/globals-CS6BZ0zp.css +0 -1
- package/admin-dist/public/assets/index-DNGIZHL-.js +0 -1
- package/admin-dist/public/assets/media-Bkrkffm7.js +0 -1
- package/admin-dist/public/assets/scroll-area-DfIlT0in.js +0 -1
- package/admin-dist/public/assets/select-BD29IXCI.js +0 -1
- package/admin-dist/public/assets/settings-DmMyn_6A.js +0 -1
- package/admin-dist/public/assets/switch-h3Rrnl5i.js +0 -1
- package/admin-dist/public/assets/tabs-imc8h-Dp.js +0 -1
- package/admin-dist/public/assets/taxonomies-dAsrT65H.js +0 -1
- package/admin-dist/public/assets/trash-SAWKZZHv.js +0 -1
- package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +0 -1
- package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +0 -89
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +0 -4
- package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +0 -92
- package/dist/client/admin-config.d.ts.map +0 -1
- package/dist/client/admin-config.js.map +0 -1
- package/dist/client/adminApi.d.ts +0 -2273
- package/dist/client/adminApi.d.ts.map +0 -1
- package/dist/client/adminApi.js +0 -716
- 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
|
+
}
|