convex-cms 0.0.2 → 0.0.3

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 (265) hide show
  1. package/admin-dist/nitro.json +15 -0
  2. package/admin-dist/public/assets/CmsEmptyState-CRswfTzk.js +5 -0
  3. package/admin-dist/public/assets/CmsPageHeader-CirpXndm.js +1 -0
  4. package/admin-dist/public/assets/CmsStatusBadge-CbEUpQu-.js +1 -0
  5. package/admin-dist/public/assets/CmsToolbar-BI2nZOXp.js +1 -0
  6. package/admin-dist/public/assets/ContentEntryEditor-CBeCyK_m.js +4 -0
  7. package/admin-dist/public/assets/ErrorState-BIVaWmom.js +1 -0
  8. package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +1 -0
  9. package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +1 -0
  10. package/admin-dist/public/assets/_entryId-CKU_glsK.js +1 -0
  11. package/admin-dist/public/assets/alert-BXjTqrwQ.js +1 -0
  12. package/admin-dist/public/assets/badge-hvUOzpVZ.js +1 -0
  13. package/admin-dist/public/assets/circle-check-big-CF_pR17r.js +1 -0
  14. package/admin-dist/public/assets/command-DU82cJlt.js +1 -0
  15. package/admin-dist/public/assets/content-_LXl3pp7.js +1 -0
  16. package/admin-dist/public/assets/content-types-KjxaXGxY.js +2 -0
  17. package/admin-dist/public/assets/globals-CS6BZ0zp.css +1 -0
  18. package/admin-dist/public/assets/index-DNGIZHL-.js +1 -0
  19. package/admin-dist/public/assets/label-KNtpL71g.js +1 -0
  20. package/admin-dist/public/assets/link-2-Bw2aI4V4.js +1 -0
  21. package/admin-dist/public/assets/list-sYepHjt_.js +1 -0
  22. package/admin-dist/public/assets/main-CKj5yfEi.js +97 -0
  23. package/admin-dist/public/assets/media-Bkrkffm7.js +1 -0
  24. package/admin-dist/public/assets/new._contentTypeId-C3LstjNs.js +1 -0
  25. package/admin-dist/public/assets/plus-DUn8v_Xf.js +1 -0
  26. package/admin-dist/public/assets/rotate-ccw-DJEoHcRI.js +1 -0
  27. package/admin-dist/public/assets/scroll-area-DfIlT0in.js +1 -0
  28. package/admin-dist/public/assets/search-MuAUDJKR.js +1 -0
  29. package/admin-dist/public/assets/select-BD29IXCI.js +1 -0
  30. package/admin-dist/public/assets/settings-DmMyn_6A.js +1 -0
  31. package/admin-dist/public/assets/switch-h3Rrnl5i.js +1 -0
  32. package/admin-dist/public/assets/tabs-imc8h-Dp.js +1 -0
  33. package/admin-dist/public/assets/taxonomies-dAsrT65H.js +1 -0
  34. package/admin-dist/public/assets/textarea-BTy7nwzR.js +1 -0
  35. package/admin-dist/public/assets/trash-SAWKZZHv.js +1 -0
  36. package/admin-dist/public/assets/triangle-alert-E52Vfeuh.js +1 -0
  37. package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +1 -0
  38. package/admin-dist/public/assets/usePermissions-Basjs9BT.js +1 -0
  39. package/admin-dist/public/favicon.ico +0 -0
  40. package/admin-dist/server/_chunks/_libs/@date-fns/tz.mjs +217 -0
  41. package/admin-dist/server/_chunks/_libs/@floating-ui/core.mjs +719 -0
  42. package/admin-dist/server/_chunks/_libs/@floating-ui/dom.mjs +622 -0
  43. package/admin-dist/server/_chunks/_libs/@floating-ui/react-dom.mjs +292 -0
  44. package/admin-dist/server/_chunks/_libs/@floating-ui/utils.mjs +320 -0
  45. package/admin-dist/server/_chunks/_libs/@radix-ui/number.mjs +6 -0
  46. package/admin-dist/server/_chunks/_libs/@radix-ui/primitive.mjs +11 -0
  47. package/admin-dist/server/_chunks/_libs/@radix-ui/react-arrow.mjs +23 -0
  48. package/admin-dist/server/_chunks/_libs/@radix-ui/react-avatar.mjs +119 -0
  49. package/admin-dist/server/_chunks/_libs/@radix-ui/react-checkbox.mjs +270 -0
  50. package/admin-dist/server/_chunks/_libs/@radix-ui/react-collection.mjs +69 -0
  51. package/admin-dist/server/_chunks/_libs/@radix-ui/react-compose-refs.mjs +39 -0
  52. package/admin-dist/server/_chunks/_libs/@radix-ui/react-context.mjs +137 -0
  53. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dialog.mjs +325 -0
  54. package/admin-dist/server/_chunks/_libs/@radix-ui/react-direction.mjs +9 -0
  55. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dismissable-layer.mjs +210 -0
  56. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dropdown-menu.mjs +253 -0
  57. package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-guards.mjs +29 -0
  58. package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-scope.mjs +206 -0
  59. package/admin-dist/server/_chunks/_libs/@radix-ui/react-id.mjs +14 -0
  60. package/admin-dist/server/_chunks/_libs/@radix-ui/react-label.mjs +23 -0
  61. package/admin-dist/server/_chunks/_libs/@radix-ui/react-menu.mjs +812 -0
  62. package/admin-dist/server/_chunks/_libs/@radix-ui/react-popover.mjs +300 -0
  63. package/admin-dist/server/_chunks/_libs/@radix-ui/react-popper.mjs +286 -0
  64. package/admin-dist/server/_chunks/_libs/@radix-ui/react-portal.mjs +16 -0
  65. package/admin-dist/server/_chunks/_libs/@radix-ui/react-presence.mjs +128 -0
  66. package/admin-dist/server/_chunks/_libs/@radix-ui/react-primitive.mjs +141 -0
  67. package/admin-dist/server/_chunks/_libs/@radix-ui/react-roving-focus.mjs +224 -0
  68. package/admin-dist/server/_chunks/_libs/@radix-ui/react-scroll-area.mjs +721 -0
  69. package/admin-dist/server/_chunks/_libs/@radix-ui/react-select.mjs +1163 -0
  70. package/admin-dist/server/_chunks/_libs/@radix-ui/react-separator.mjs +28 -0
  71. package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +601 -0
  72. package/admin-dist/server/_chunks/_libs/@radix-ui/react-switch.mjs +152 -0
  73. package/admin-dist/server/_chunks/_libs/@radix-ui/react-tabs.mjs +189 -0
  74. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-callback-ref.mjs +11 -0
  75. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-controllable-state.mjs +69 -0
  76. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs +1 -0
  77. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-escape-keydown.mjs +17 -0
  78. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-is-hydrated.mjs +15 -0
  79. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-layout-effect.mjs +6 -0
  80. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-previous.mjs +14 -0
  81. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-size.mjs +39 -0
  82. package/admin-dist/server/_chunks/_libs/@radix-ui/react-visually-hidden.mjs +33 -0
  83. package/admin-dist/server/_chunks/_libs/@tanstack/history.mjs +409 -0
  84. package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +1711 -0
  85. package/admin-dist/server/_chunks/_libs/@tanstack/react-store.mjs +56 -0
  86. package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +4829 -0
  87. package/admin-dist/server/_chunks/_libs/@tanstack/store.mjs +134 -0
  88. package/admin-dist/server/_chunks/_libs/react-dom.mjs +10781 -0
  89. package/admin-dist/server/_chunks/_libs/react.mjs +513 -0
  90. package/admin-dist/server/_libs/aria-hidden.mjs +122 -0
  91. package/admin-dist/server/_libs/class-variance-authority.mjs +44 -0
  92. package/admin-dist/server/_libs/clsx.mjs +16 -0
  93. package/admin-dist/server/_libs/cmdk.mjs +315 -0
  94. package/admin-dist/server/_libs/convex.mjs +4841 -0
  95. package/admin-dist/server/_libs/cookie-es.mjs +58 -0
  96. package/admin-dist/server/_libs/croner.mjs +1 -0
  97. package/admin-dist/server/_libs/crossws.mjs +1 -0
  98. package/admin-dist/server/_libs/date-fns.mjs +1716 -0
  99. package/admin-dist/server/_libs/detect-node-es.mjs +1 -0
  100. package/admin-dist/server/_libs/get-nonce.mjs +9 -0
  101. package/admin-dist/server/_libs/h3-v2.mjs +277 -0
  102. package/admin-dist/server/_libs/h3.mjs +401 -0
  103. package/admin-dist/server/_libs/hookable.mjs +1 -0
  104. package/admin-dist/server/_libs/isbot.mjs +20 -0
  105. package/admin-dist/server/_libs/lucide-react.mjs +850 -0
  106. package/admin-dist/server/_libs/ohash.mjs +1 -0
  107. package/admin-dist/server/_libs/react-day-picker.mjs +2201 -0
  108. package/admin-dist/server/_libs/react-remove-scroll-bar.mjs +82 -0
  109. package/admin-dist/server/_libs/react-remove-scroll.mjs +328 -0
  110. package/admin-dist/server/_libs/react-style-singleton.mjs +69 -0
  111. package/admin-dist/server/_libs/rou3.mjs +8 -0
  112. package/admin-dist/server/_libs/seroval-plugins.mjs +58 -0
  113. package/admin-dist/server/_libs/seroval.mjs +1765 -0
  114. package/admin-dist/server/_libs/srvx.mjs +719 -0
  115. package/admin-dist/server/_libs/tailwind-merge.mjs +3010 -0
  116. package/admin-dist/server/_libs/tiny-invariant.mjs +12 -0
  117. package/admin-dist/server/_libs/tiny-warning.mjs +5 -0
  118. package/admin-dist/server/_libs/tslib.mjs +39 -0
  119. package/admin-dist/server/_libs/ufo.mjs +54 -0
  120. package/admin-dist/server/_libs/unctx.mjs +1 -0
  121. package/admin-dist/server/_libs/unstorage.mjs +1 -0
  122. package/admin-dist/server/_libs/use-callback-ref.mjs +66 -0
  123. package/admin-dist/server/_libs/use-sidecar.mjs +106 -0
  124. package/admin-dist/server/_libs/use-sync-external-store.mjs +139 -0
  125. package/admin-dist/server/_libs/zod.mjs +4223 -0
  126. package/admin-dist/server/_ssr/CmsEmptyState-DU7-7-mV.mjs +290 -0
  127. package/admin-dist/server/_ssr/CmsPageHeader-CseW0AHm.mjs +24 -0
  128. package/admin-dist/server/_ssr/CmsStatusBadge-B_pi4KCp.mjs +127 -0
  129. package/admin-dist/server/_ssr/CmsToolbar-X75ex6ek.mjs +49 -0
  130. package/admin-dist/server/_ssr/ContentEntryEditor-CepusRsA.mjs +3720 -0
  131. package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +89 -0
  132. package/admin-dist/server/_ssr/TaxonomyFilter-Bwrq0-cz.mjs +188 -0
  133. package/admin-dist/server/_ssr/_contentTypeId-BqYKEcLr.mjs +379 -0
  134. package/admin-dist/server/_ssr/_entryId-CRfnqeDf.mjs +161 -0
  135. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +4 -0
  136. package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +92 -0
  137. package/admin-dist/server/_ssr/badge-6BsP37vG.mjs +125 -0
  138. package/admin-dist/server/_ssr/command-fy8epIKf.mjs +128 -0
  139. package/admin-dist/server/_ssr/config.server-D7JHDcDv.mjs +117 -0
  140. package/admin-dist/server/_ssr/content-B5RhL7uW.mjs +532 -0
  141. package/admin-dist/server/_ssr/content-types-BIOqCQYN.mjs +1166 -0
  142. package/admin-dist/server/_ssr/index-DHSHDPt1.mjs +193 -0
  143. package/admin-dist/server/_ssr/index.mjs +1275 -0
  144. package/admin-dist/server/_ssr/label-C8Dko1j7.mjs +22 -0
  145. package/admin-dist/server/_ssr/media-CSx3XttC.mjs +1832 -0
  146. package/admin-dist/server/_ssr/new._contentTypeId-DzanEZQM.mjs +144 -0
  147. package/admin-dist/server/_ssr/router-DDWcF-kt.mjs +1556 -0
  148. package/admin-dist/server/_ssr/scroll-area-bjPYwhXN.mjs +59 -0
  149. package/admin-dist/server/_ssr/select-BUhDDf4T.mjs +142 -0
  150. package/admin-dist/server/_ssr/settings-DAsxnw2q.mjs +348 -0
  151. package/admin-dist/server/_ssr/start-HYkvq4Ni.mjs +4 -0
  152. package/admin-dist/server/_ssr/switch-BgyRtQ1Z.mjs +31 -0
  153. package/admin-dist/server/_ssr/tabs-DzMdRB1A.mjs +628 -0
  154. package/admin-dist/server/_ssr/taxonomies-C8j8g5Q5.mjs +915 -0
  155. package/admin-dist/server/_ssr/textarea-9jNeYJSc.mjs +18 -0
  156. package/admin-dist/server/_ssr/trash-DYMxwhZB.mjs +291 -0
  157. package/admin-dist/server/_ssr/useBreadcrumbLabel-FNSAr2Ha.mjs +16 -0
  158. package/admin-dist/server/_ssr/usePermissions-BJGGahrJ.mjs +68 -0
  159. package/admin-dist/server/favicon.ico +0 -0
  160. package/admin-dist/server/index.mjs +627 -0
  161. package/dist/cli/index.js +0 -0
  162. package/dist/client/admin-config.d.ts +0 -1
  163. package/dist/client/admin-config.d.ts.map +1 -1
  164. package/dist/client/admin-config.js +0 -1
  165. package/dist/client/admin-config.js.map +1 -1
  166. package/dist/client/adminApi.d.ts.map +1 -1
  167. package/dist/client/agentTools.d.ts +1237 -135
  168. package/dist/client/agentTools.d.ts.map +1 -1
  169. package/dist/client/agentTools.js +33 -9
  170. package/dist/client/agentTools.js.map +1 -1
  171. package/dist/client/index.d.ts +1 -1
  172. package/dist/client/index.d.ts.map +1 -1
  173. package/dist/client/index.js.map +1 -1
  174. package/dist/component/_generated/component.d.ts +9 -0
  175. package/dist/component/_generated/component.d.ts.map +1 -1
  176. package/dist/component/mediaAssets.d.ts +35 -0
  177. package/dist/component/mediaAssets.d.ts.map +1 -1
  178. package/dist/component/mediaAssets.js +81 -0
  179. package/dist/component/mediaAssets.js.map +1 -1
  180. package/dist/test.d.ts.map +1 -1
  181. package/dist/test.js +2 -1
  182. package/dist/test.js.map +1 -1
  183. package/package.json +9 -5
  184. package/dist/component/auditLog.d.ts +0 -410
  185. package/dist/component/auditLog.d.ts.map +0 -1
  186. package/dist/component/auditLog.js +0 -607
  187. package/dist/component/auditLog.js.map +0 -1
  188. package/dist/component/types.d.ts +0 -4
  189. package/dist/component/types.d.ts.map +0 -1
  190. package/dist/component/types.js +0 -2
  191. package/dist/component/types.js.map +0 -1
  192. package/src/cli/commands/admin.ts +0 -104
  193. package/src/cli/index.ts +0 -21
  194. package/src/cli/utils/detectConvexUrl.ts +0 -54
  195. package/src/cli/utils/openBrowser.ts +0 -16
  196. package/src/client/admin-config.ts +0 -138
  197. package/src/client/adminApi.ts +0 -942
  198. package/src/client/agentTools.ts +0 -1311
  199. package/src/client/argTypes.ts +0 -316
  200. package/src/client/field-types.ts +0 -187
  201. package/src/client/index.ts +0 -1301
  202. package/src/client/queryBuilder.ts +0 -1100
  203. package/src/client/schema/codegen.ts +0 -500
  204. package/src/client/schema/defineContentType.ts +0 -501
  205. package/src/client/schema/index.ts +0 -169
  206. package/src/client/schema/schemaDrift.ts +0 -574
  207. package/src/client/schema/typedClient.ts +0 -688
  208. package/src/client/schema/types.ts +0 -666
  209. package/src/client/types.ts +0 -723
  210. package/src/client/workflows.ts +0 -141
  211. package/src/client/wrapper.ts +0 -4304
  212. package/src/component/_generated/api.ts +0 -140
  213. package/src/component/_generated/component.ts +0 -5029
  214. package/src/component/_generated/dataModel.ts +0 -60
  215. package/src/component/_generated/server.ts +0 -156
  216. package/src/component/authorization.ts +0 -647
  217. package/src/component/authorizationHooks.ts +0 -668
  218. package/src/component/bulkOperations.ts +0 -687
  219. package/src/component/contentEntries.ts +0 -1976
  220. package/src/component/contentEntryMutations.ts +0 -1223
  221. package/src/component/contentEntryValidation.ts +0 -707
  222. package/src/component/contentLock.ts +0 -550
  223. package/src/component/contentTypeMigration.ts +0 -1064
  224. package/src/component/contentTypeMutations.ts +0 -969
  225. package/src/component/contentTypes.ts +0 -346
  226. package/src/component/convex.config.ts +0 -44
  227. package/src/component/documentTypes.ts +0 -240
  228. package/src/component/eventEmitter.ts +0 -485
  229. package/src/component/exportImport.ts +0 -1169
  230. package/src/component/index.ts +0 -491
  231. package/src/component/lib/deepReferenceResolver.ts +0 -999
  232. package/src/component/lib/errors.ts +0 -816
  233. package/src/component/lib/index.ts +0 -145
  234. package/src/component/lib/mediaReferenceResolver.ts +0 -495
  235. package/src/component/lib/metadataExtractor.ts +0 -792
  236. package/src/component/lib/mutationAuth.ts +0 -199
  237. package/src/component/lib/queries.ts +0 -79
  238. package/src/component/lib/ragContentChunker.ts +0 -1371
  239. package/src/component/lib/referenceResolver.ts +0 -430
  240. package/src/component/lib/slugGenerator.ts +0 -262
  241. package/src/component/lib/slugUniqueness.ts +0 -333
  242. package/src/component/lib/softDelete.ts +0 -44
  243. package/src/component/localeFallbackChain.ts +0 -673
  244. package/src/component/localeFields.ts +0 -896
  245. package/src/component/mediaAssetMutations.ts +0 -725
  246. package/src/component/mediaAssets.ts +0 -932
  247. package/src/component/mediaFolderMutations.ts +0 -1046
  248. package/src/component/mediaUploadMutations.ts +0 -224
  249. package/src/component/mediaVariantMutations.ts +0 -900
  250. package/src/component/mediaVariants.ts +0 -793
  251. package/src/component/ragContentIndexer.ts +0 -1067
  252. package/src/component/rateLimitHooks.ts +0 -572
  253. package/src/component/roles.ts +0 -1360
  254. package/src/component/scheduledPublish.ts +0 -358
  255. package/src/component/schema.ts +0 -617
  256. package/src/component/taxonomies.ts +0 -949
  257. package/src/component/taxonomyMutations.ts +0 -1210
  258. package/src/component/trash.ts +0 -724
  259. package/src/component/userContext.ts +0 -898
  260. package/src/component/validation.ts +0 -1388
  261. package/src/component/validators.ts +0 -949
  262. package/src/component/versionMutations.ts +0 -392
  263. package/src/component/webhookTrigger.ts +0 -1922
  264. package/src/react/index.ts +0 -898
  265. package/src/test.ts +0 -1580
@@ -1,1311 +0,0 @@
1
- /**
2
- * @convex-cms/core Agent Tools
3
- *
4
- * Tool-compatible function wrappers for @convex-dev/agent integration.
5
- * Provides structured tool definitions with clear parameter schemas for
6
- * content creation, querying, and management.
7
- *
8
- * @example
9
- * ```typescript
10
- * import { Agent } from "@convex-dev/agent";
11
- * import { createCmsTools } from "@convex-cms/core";
12
- * import { components } from "./_generated/api";
13
- *
14
- * const cmsTools = createCmsTools(components.convexCms);
15
- *
16
- * const contentAgent = new Agent(components.agent, {
17
- * name: "Content Manager",
18
- * languageModel: openai.chat("gpt-4o"),
19
- * tools: cmsTools,
20
- * });
21
- * ```
22
- *
23
- * @example
24
- * ```typescript
25
- * // Use individual tools
26
- * import { createCmsTools } from "@convex-cms/core";
27
- *
28
- * const { createContentEntry, listContentEntries, publishEntry } = createCmsTools(api);
29
- *
30
- * const agent = new Agent(components.agent, {
31
- * tools: { createContentEntry, publishEntry },
32
- * });
33
- * ```
34
- */
35
-
36
- import { createTool } from "@convex-dev/agent";
37
- import { z } from "zod";
38
-
39
- // =============================================================================
40
- // Component API Type
41
- // =============================================================================
42
-
43
- /**
44
- * The component API type for agent tools.
45
- * This represents the actual structure of `components.convexCms` from the generated API.
46
- *
47
- * Uses `any` for internal function references since the exact types depend on
48
- * the generated Convex types which vary per project.
49
- *
50
- * Note: This matches the actual Convex component module structure:
51
- * - contentTypes: queries in contentTypes.ts (get handles both ID and name lookup via args)
52
- * - contentTypeMutations: mutations in contentTypeMutations.ts
53
- * - contentEntries: queries in contentEntries.ts
54
- * - contentEntryMutations: mutations in contentEntryMutations.ts
55
- * - scheduledPublish: schedule-related mutations in scheduledPublish.ts (separate module)
56
- * - mediaAssets: queries in mediaAssets.ts
57
- * - mediaAssetMutations: mutations in mediaAssetMutations.ts
58
- * - bulkOperations: bulk mutations in bulkOperations.ts
59
- *
60
- * IMPORTANT: This type represents the raw component API shape as exported from
61
- * `components.convexCms`. It differs from the wrapper API (createCmsClient) which
62
- * provides a different, more ergonomic namespace structure.
63
- */
64
- export type AgentComponentApi = {
65
- /**
66
- * Content type queries (contentTypes.ts module)
67
- * @see src/component/contentTypes.ts
68
- */
69
- contentTypes: {
70
- /**
71
- * Get content type by ID or name.
72
- * Supports lookup by either `id` OR `name` argument (not both).
73
- * @example { id: "..." } or { name: "blog_post" }
74
- */
75
- get: any;
76
- /** List content types with filtering and pagination */
77
- list: any;
78
- };
79
- /**
80
- * Content type mutations (contentTypeMutations.ts module)
81
- * @see src/component/contentTypeMutations.ts
82
- */
83
- contentTypeMutations: {
84
- createContentType: any;
85
- updateContentType: any;
86
- deleteContentType: any;
87
- };
88
- /**
89
- * Content entry queries (contentEntries.ts module)
90
- * @see src/component/contentEntries.ts
91
- */
92
- contentEntries: {
93
- /** Get content entry by ID */
94
- get: any;
95
- /** Get content entry by slug and content type ID */
96
- getBySlug: any;
97
- /** Get content entry by slug and content type name */
98
- getBySlugAndTypeName: any;
99
- /** List content entries with filtering and pagination */
100
- list: any;
101
- };
102
- /**
103
- * Content entry mutations (contentEntryMutations.ts module)
104
- * @see src/component/contentEntryMutations.ts
105
- */
106
- contentEntryMutations: {
107
- createEntry: any;
108
- updateEntry: any;
109
- publishEntry: any;
110
- unpublishEntry: any;
111
- deleteEntry: any;
112
- duplicateEntry: any;
113
- restoreEntry: any;
114
- };
115
- /**
116
- * Scheduling-related mutations (scheduledPublish.ts module - SEPARATE from contentEntryMutations)
117
- * @see src/component/scheduledPublish.ts
118
- */
119
- scheduledPublish: {
120
- /** Schedule an entry for future publication */
121
- scheduleEntry: any;
122
- /** Cancel a scheduled publication */
123
- cancelScheduledPublish: any;
124
- };
125
- /**
126
- * Media asset queries (mediaAssets.ts module)
127
- * @see src/component/mediaAssets.ts
128
- */
129
- mediaAssets: {
130
- get: any;
131
- list: any;
132
- };
133
- /**
134
- * Media asset mutations (mediaAssetMutations.ts module)
135
- * @see src/component/mediaAssetMutations.ts
136
- */
137
- mediaAssetMutations: {
138
- createMediaAsset: any;
139
- updateMediaAsset: any;
140
- deleteMediaAsset: any;
141
- };
142
- /**
143
- * Bulk operations (bulkOperations.ts module)
144
- * @see src/component/bulkOperations.ts
145
- */
146
- bulkOperations: {
147
- bulkPublish: any;
148
- bulkUnpublish: any;
149
- bulkDelete: any;
150
- bulkUpdate: any;
151
- bulkRestore: any;
152
- };
153
- };
154
-
155
- // =============================================================================
156
- // Zod Schemas for Tool Arguments
157
- // =============================================================================
158
-
159
- /**
160
- * Supported field types in the CMS.
161
- */
162
- export const fieldTypeSchema = z.enum([
163
- "text",
164
- "richText",
165
- "number",
166
- "boolean",
167
- "date",
168
- "datetime",
169
- "reference",
170
- "media",
171
- "json",
172
- "select",
173
- "multiSelect",
174
- ]);
175
-
176
- /**
177
- * Content entry status values.
178
- */
179
- export const contentStatusSchema = z.enum([
180
- "draft",
181
- "published",
182
- "archived",
183
- "scheduled",
184
- ]);
185
-
186
- /**
187
- * Media type classification.
188
- */
189
- export const mediaTypeSchema = z.enum([
190
- "image",
191
- "video",
192
- "audio",
193
- "document",
194
- "other",
195
- ]);
196
-
197
- /**
198
- * Field-specific configuration options.
199
- */
200
- export const fieldOptionsSchema = z.object({
201
- // Text fields
202
- minLength: z.number().optional().describe("Minimum text length"),
203
- maxLength: z.number().optional().describe("Maximum text length"),
204
- pattern: z.string().optional().describe("Regex pattern for validation"),
205
-
206
- // Number fields
207
- min: z.number().optional().describe("Minimum numeric value"),
208
- max: z.number().optional().describe("Maximum numeric value"),
209
- step: z.number().optional().describe("Step increment for numeric input"),
210
- precision: z.number().optional().describe("Decimal precision"),
211
-
212
- // Reference fields
213
- allowedContentTypes: z
214
- .array(z.string())
215
- .optional()
216
- .describe("Content type names that can be referenced"),
217
- multiple: z
218
- .boolean()
219
- .optional()
220
- .describe("Allow multiple references"),
221
- minItems: z
222
- .number()
223
- .optional()
224
- .describe("Minimum number of references when multiple is true"),
225
-
226
- // Media fields
227
- allowedMimeTypes: z
228
- .array(z.string())
229
- .optional()
230
- .describe("Allowed MIME types (e.g., 'image/*', 'application/pdf')"),
231
- maxFileSize: z
232
- .number()
233
- .optional()
234
- .describe("Maximum file size in bytes"),
235
-
236
- // Select fields
237
- options: z
238
- .array(
239
- z.object({
240
- value: z.string().describe("Option value"),
241
- label: z.string().describe("Display label"),
242
- })
243
- )
244
- .optional()
245
- .describe("Options for select/multiSelect fields"),
246
-
247
- // Rich text fields
248
- allowedBlocks: z
249
- .array(z.string())
250
- .optional()
251
- .describe("Allowed block types in rich text"),
252
- allowedMarks: z
253
- .array(z.string())
254
- .optional()
255
- .describe("Allowed inline marks in rich text"),
256
- }).strict();
257
-
258
- /**
259
- * Field definition schema for content types.
260
- */
261
- export const fieldDefinitionSchema = z.object({
262
- name: z
263
- .string()
264
- .describe("Unique machine-readable field name (e.g., 'author_name')"),
265
- label: z.string().describe("Human-readable label for the field"),
266
- type: fieldTypeSchema.describe("The field data type"),
267
- required: z.boolean().describe("Whether the field is required"),
268
- searchable: z
269
- .boolean()
270
- .optional()
271
- .describe("Index this field for full-text search"),
272
- localized: z
273
- .boolean()
274
- .optional()
275
- .describe("Enable per-locale values for this field"),
276
- description: z
277
- .string()
278
- .optional()
279
- .describe("Help text shown in the editor"),
280
- defaultValue: z.any().optional().describe("Default value for new entries"),
281
- options: fieldOptionsSchema.optional().describe("Field-specific options"),
282
- });
283
-
284
- /**
285
- * Filter operators for content queries.
286
- */
287
- export const filterOperatorSchema = z.enum([
288
- "eq",
289
- "ne",
290
- "gt",
291
- "gte",
292
- "lt",
293
- "lte",
294
- "contains",
295
- "startsWith",
296
- "endsWith",
297
- "in",
298
- "notIn",
299
- ]);
300
-
301
- /**
302
- * Field filter for content queries.
303
- */
304
- export const fieldFilterSchema = z.object({
305
- field: z.string().describe("Field name to filter on"),
306
- operator: filterOperatorSchema.describe("Comparison operator"),
307
- value: z.any().describe("Value to compare against"),
308
- });
309
-
310
- // =============================================================================
311
- // Content Type Tool Schemas
312
- // =============================================================================
313
-
314
- /**
315
- * Arguments for creating a content type.
316
- */
317
- export const createContentTypeArgsSchema = z.object({
318
- name: z
319
- .string()
320
- .describe(
321
- "Unique machine-readable name (e.g., 'blog_post'). Use snake_case."
322
- ),
323
- displayName: z
324
- .string()
325
- .describe("Human-readable name shown in the admin UI (e.g., 'Blog Post')"),
326
- description: z
327
- .string()
328
- .optional()
329
- .describe("Description of what this content type is for"),
330
- fields: z
331
- .array(fieldDefinitionSchema)
332
- .describe("Array of field definitions that make up this content type"),
333
- icon: z
334
- .string()
335
- .optional()
336
- .describe("Icon identifier for the admin UI (e.g., 'document', 'image')"),
337
- singleton: z
338
- .boolean()
339
- .optional()
340
- .describe(
341
- "If true, only one entry of this type can exist (e.g., for settings pages)"
342
- ),
343
- slugField: z
344
- .string()
345
- .optional()
346
- .describe("Field name to auto-generate URL slugs from (e.g., 'title')"),
347
- titleField: z
348
- .string()
349
- .optional()
350
- .describe("Field name to use as the display title in lists"),
351
- sortOrder: z
352
- .number()
353
- .optional()
354
- .describe("Custom sort order in the admin sidebar"),
355
- createdBy: z
356
- .string()
357
- .optional()
358
- .describe("User ID of who created this type"),
359
- });
360
-
361
- /**
362
- * Arguments for updating a content type.
363
- */
364
- export const updateContentTypeArgsSchema = z.object({
365
- id: z.string().describe("The content type ID to update"),
366
- displayName: z.string().optional().describe("New display name"),
367
- description: z.string().optional().describe("New description"),
368
- fields: z
369
- .array(fieldDefinitionSchema)
370
- .optional()
371
- .describe("Updated field definitions (replaces all fields)"),
372
- icon: z.string().optional().describe("New icon identifier"),
373
- singleton: z.boolean().optional().describe("Update singleton setting"),
374
- slugField: z.string().optional().describe("New slug field"),
375
- titleField: z.string().optional().describe("New title field"),
376
- sortOrder: z.number().optional().describe("New sort order"),
377
- isActive: z.boolean().optional().describe("Whether the type is active"),
378
- updatedBy: z.string().optional().describe("User ID performing the update"),
379
- });
380
-
381
- /**
382
- * Arguments for listing content types.
383
- */
384
- export const listContentTypesArgsSchema = z.object({
385
- includeInactive: z
386
- .boolean()
387
- .optional()
388
- .describe("Include inactive content types in results"),
389
- });
390
-
391
- /**
392
- * Arguments for getting a single content type.
393
- */
394
- export const getContentTypeArgsSchema = z.object({
395
- id: z.string().optional().describe("Get content type by ID"),
396
- name: z
397
- .string()
398
- .optional()
399
- .describe("Get content type by name (alternative to ID)"),
400
- });
401
-
402
- // =============================================================================
403
- // Content Entry Tool Schemas
404
- // =============================================================================
405
-
406
- /**
407
- * Arguments for creating a content entry.
408
- */
409
- export const createContentEntryArgsSchema = z.object({
410
- contentTypeId: z
411
- .string()
412
- .describe("The content type ID this entry belongs to"),
413
- slug: z
414
- .string()
415
- .optional()
416
- .describe(
417
- "URL-friendly slug (auto-generated from slugField if not provided)"
418
- ),
419
- data: z
420
- .record(z.string(), z.any())
421
- .describe("The entry's field values as key-value pairs"),
422
- locale: z
423
- .string()
424
- .optional()
425
- .describe("Locale code for localized content (e.g., 'en-US')"),
426
- status: contentStatusSchema
427
- .optional()
428
- .describe("Initial status (defaults to 'draft')"),
429
- createdBy: z.string().optional().describe("User ID of the creator"),
430
- });
431
-
432
- /**
433
- * Arguments for updating a content entry.
434
- */
435
- export const updateContentEntryArgsSchema = z.object({
436
- id: z.string().describe("The content entry ID to update"),
437
- slug: z.string().optional().describe("New URL slug"),
438
- data: z.record(z.string(), z.any()).optional().describe("Updated field values to merge"),
439
- status: contentStatusSchema.optional().describe("New status"),
440
- scheduledPublishAt: z
441
- .number()
442
- .optional()
443
- .describe("Unix timestamp for scheduled publishing"),
444
- updatedBy: z.string().optional().describe("User ID performing the update"),
445
- regenerateSlug: z
446
- .boolean()
447
- .optional()
448
- .describe("Regenerate slug from slugField after update"),
449
- });
450
-
451
- /**
452
- * Arguments for publishing a content entry.
453
- */
454
- export const publishEntryArgsSchema = z.object({
455
- id: z.string().describe("The content entry ID to publish"),
456
- changeDescription: z
457
- .string()
458
- .optional()
459
- .describe("Description of changes for version history"),
460
- updatedBy: z.string().optional().describe("User ID performing the publish"),
461
- });
462
-
463
- /**
464
- * Arguments for unpublishing a content entry.
465
- */
466
- export const unpublishEntryArgsSchema = z.object({
467
- id: z.string().describe("The content entry ID to unpublish (revert to draft)"),
468
- updatedBy: z.string().optional().describe("User ID performing the unpublish"),
469
- });
470
-
471
- /**
472
- * Arguments for scheduling a content entry.
473
- */
474
- export const scheduleEntryArgsSchema = z.object({
475
- id: z.string().describe("The content entry ID to schedule"),
476
- publishAt: z.number().describe("Unix timestamp for when to publish"),
477
- updatedBy: z.string().optional().describe("User ID performing the schedule"),
478
- });
479
-
480
- /**
481
- * Arguments for deleting a content entry.
482
- */
483
- export const deleteContentEntryArgsSchema = z.object({
484
- id: z.string().describe("The content entry ID to delete"),
485
- deletedBy: z.string().optional().describe("User ID performing the deletion"),
486
- hardDelete: z
487
- .boolean()
488
- .optional()
489
- .describe("If true, permanently delete. Otherwise soft delete (default)."),
490
- });
491
-
492
- /**
493
- * Arguments for duplicating a content entry.
494
- */
495
- export const duplicateContentEntryArgsSchema = z.object({
496
- sourceEntryId: z.string().describe("The content entry ID to duplicate"),
497
- slug: z
498
- .string()
499
- .optional()
500
- .describe("Custom slug for the duplicate (auto-generated if not provided)"),
501
- copyMediaReferences: z
502
- .boolean()
503
- .optional()
504
- .describe("Whether to copy media references (default: true)"),
505
- locale: z.string().optional().describe("Locale for the duplicated entry"),
506
- createdBy: z
507
- .string()
508
- .optional()
509
- .describe("User ID performing the duplication"),
510
- });
511
-
512
- /**
513
- * Arguments for listing content entries.
514
- */
515
- export const listContentEntriesArgsSchema = z.object({
516
- contentTypeId: z.string().optional().describe("Filter by content type ID"),
517
- contentTypeName: z
518
- .string()
519
- .optional()
520
- .describe("Filter by content type name (alternative to ID)"),
521
- status: contentStatusSchema.optional().describe("Filter by single status"),
522
- statusIn: z
523
- .array(contentStatusSchema)
524
- .optional()
525
- .describe("Filter by multiple statuses"),
526
- locale: z.string().optional().describe("Filter by locale"),
527
- search: z.string().optional().describe("Full-text search query"),
528
- includeDeleted: z
529
- .boolean()
530
- .optional()
531
- .describe("Include soft-deleted entries"),
532
- fieldFilters: z
533
- .array(fieldFilterSchema)
534
- .optional()
535
- .describe("Field-level filters"),
536
- limit: z
537
- .number()
538
- .optional()
539
- .describe("Maximum number of entries to return (default: 50)"),
540
- cursor: z.string().optional().describe("Pagination cursor from previous page"),
541
- });
542
-
543
- /**
544
- * Arguments for getting a single content entry.
545
- */
546
- export const getContentEntryArgsSchema = z.object({
547
- id: z.string().optional().describe("Get entry by ID"),
548
- slug: z.string().optional().describe("Get entry by slug (requires contentTypeId or contentTypeName)"),
549
- contentTypeId: z.string().optional().describe("Content type ID (required when using slug)"),
550
- contentTypeName: z.string().optional().describe("Content type name (alternative to contentTypeId when using slug)"),
551
- });
552
-
553
- /**
554
- * Arguments for restoring a soft-deleted content entry.
555
- */
556
- export const restoreContentEntryArgsSchema = z.object({
557
- id: z.string().describe("The content entry ID to restore from trash"),
558
- updatedBy: z.string().optional().describe("User ID performing the restore"),
559
- });
560
-
561
- // =============================================================================
562
- // Media Asset Tool Schemas
563
- // =============================================================================
564
-
565
- /**
566
- * Arguments for creating a media asset.
567
- */
568
- export const createMediaAssetArgsSchema = z.object({
569
- storageId: z.string().describe("Convex storage ID from file upload"),
570
- filename: z.string().describe("Original filename"),
571
- mimeType: z.string().describe("MIME type (e.g., 'image/jpeg')"),
572
- size: z.number().describe("File size in bytes"),
573
- type: mediaTypeSchema.describe("Classified media type"),
574
- title: z.string().optional().describe("Human-readable title"),
575
- description: z.string().optional().describe("Description or caption"),
576
- altText: z.string().optional().describe("Alt text for accessibility"),
577
- folderId: z.string().optional().describe("Parent folder ID"),
578
- width: z.number().optional().describe("Image/video width in pixels"),
579
- height: z.number().optional().describe("Image/video height in pixels"),
580
- duration: z.number().optional().describe("Audio/video duration in seconds"),
581
- metadata: z.record(z.string(), z.any()).optional().describe("Additional metadata"),
582
- tags: z.array(z.string()).optional().describe("Tags for organization"),
583
- createdBy: z.string().optional().describe("User ID of the uploader"),
584
- });
585
-
586
- /**
587
- * Arguments for updating a media asset.
588
- */
589
- export const updateMediaAssetArgsSchema = z.object({
590
- id: z.string().describe("The media asset ID to update"),
591
- title: z.string().optional().describe("New title"),
592
- description: z.string().optional().describe("New description"),
593
- altText: z.string().optional().describe("New alt text"),
594
- folderId: z.string().optional().describe("Move to new folder"),
595
- tags: z.array(z.string()).optional().describe("New tags (replaces existing)"),
596
- });
597
-
598
- /**
599
- * Arguments for listing media assets.
600
- */
601
- export const listMediaAssetsArgsSchema = z.object({
602
- folderId: z.string().optional().describe("Filter by folder ID"),
603
- type: mediaTypeSchema.optional().describe("Filter by media type"),
604
- mimeType: z.string().optional().describe("Filter by MIME type"),
605
- search: z.string().optional().describe("Search in filename, title, description"),
606
- tags: z.array(z.string()).optional().describe("Filter by tags (any match)"),
607
- includeDeleted: z.boolean().optional().describe("Include soft-deleted assets"),
608
- limit: z.number().optional().describe("Maximum number of assets to return"),
609
- cursor: z.string().optional().describe("Pagination cursor"),
610
- });
611
-
612
- /**
613
- * Arguments for getting a single media asset.
614
- */
615
- export const getMediaAssetArgsSchema = z.object({
616
- id: z.string().describe("The media asset ID to retrieve"),
617
- });
618
-
619
- /**
620
- * Arguments for deleting a media asset.
621
- */
622
- export const deleteMediaAssetArgsSchema = z.object({
623
- id: z.string().describe("The media asset ID to delete"),
624
- deletedBy: z.string().optional().describe("User ID performing the deletion"),
625
- hardDelete: z.boolean().optional().describe("If true, permanently delete"),
626
- });
627
-
628
- // =============================================================================
629
- // Bulk Operation Tool Schemas
630
- // =============================================================================
631
-
632
- /**
633
- * Arguments for bulk publishing content entries.
634
- */
635
- export const bulkPublishArgsSchema = z.object({
636
- ids: z.array(z.string()).describe("Array of content entry IDs to publish"),
637
- changeDescription: z
638
- .string()
639
- .optional()
640
- .describe("Version history description"),
641
- updatedBy: z.string().optional().describe("User ID performing the operation"),
642
- });
643
-
644
- /**
645
- * Arguments for bulk unpublishing content entries.
646
- */
647
- export const bulkUnpublishArgsSchema = z.object({
648
- ids: z.array(z.string()).describe("Array of content entry IDs to unpublish"),
649
- updatedBy: z.string().optional().describe("User ID performing the operation"),
650
- });
651
-
652
- /**
653
- * Arguments for bulk deleting content entries.
654
- */
655
- export const bulkDeleteArgsSchema = z.object({
656
- ids: z.array(z.string()).describe("Array of content entry IDs to delete"),
657
- deletedBy: z.string().optional().describe("User ID performing the deletion"),
658
- hardDelete: z.boolean().optional().describe("If true, permanently delete"),
659
- });
660
-
661
- // =============================================================================
662
- // Search Tool Schema
663
- // =============================================================================
664
-
665
- /**
666
- * Arguments for searching content.
667
- */
668
- export const searchContentArgsSchema = z.object({
669
- query: z.string().describe("Search query string"),
670
- contentTypeId: z.string().optional().describe("Limit search to content type"),
671
- contentTypeName: z.string().optional().describe("Limit search to content type by name"),
672
- status: contentStatusSchema.optional().describe("Filter by status"),
673
- limit: z.number().optional().describe("Maximum results to return"),
674
- });
675
-
676
- // =============================================================================
677
- // Tool Factory Function
678
- // =============================================================================
679
-
680
- /**
681
- * Options for creating CMS tools.
682
- */
683
- export interface CreateCmsToolsOptions {
684
- /**
685
- * Optional user ID to use as the creator/updater for all operations.
686
- * If not provided, tools will not set createdBy/updatedBy fields.
687
- */
688
- defaultUserId?: string;
689
- }
690
-
691
- /**
692
- * Creates a set of CMS tools compatible with @convex-dev/agent.
693
- *
694
- * These tools provide AI agents with structured access to CMS operations
695
- * including content type management, content entry CRUD, publishing workflows,
696
- * and media asset management.
697
- *
698
- * @param componentApi - The CMS component API from `components.convexCms`
699
- * @param options - Optional configuration for the tools
700
- * @returns An object containing all CMS tools
701
- *
702
- * @example
703
- * ```typescript
704
- * import { Agent } from "@convex-dev/agent";
705
- * import { createCmsTools } from "@convex-cms/core";
706
- * import { components } from "./_generated/api";
707
- *
708
- * // Create all CMS tools
709
- * const cmsTools = createCmsTools(components.convexCms);
710
- *
711
- * // Use with an agent
712
- * const contentAgent = new Agent(components.agent, {
713
- * name: "Content Manager",
714
- * languageModel: openai.chat("gpt-4o"),
715
- * tools: cmsTools,
716
- * });
717
- * ```
718
- *
719
- * @example
720
- * ```typescript
721
- * // Use selected tools with a specialized agent
722
- * const { listContentEntries, searchContent, getContentEntry } = createCmsTools(api);
723
- *
724
- * const researchAgent = new Agent(components.agent, {
725
- * name: "Content Researcher",
726
- * tools: { listContentEntries, searchContent, getContentEntry },
727
- * });
728
- * ```
729
- */
730
- export function createCmsTools(
731
- componentApi: AgentComponentApi,
732
- options: CreateCmsToolsOptions = {}
733
- ) {
734
- const { defaultUserId } = options;
735
-
736
- // ==========================================================================
737
- // Content Type Tools
738
- // ==========================================================================
739
-
740
- /**
741
- * Create a new content type with field definitions.
742
- */
743
- const createContentType = createTool({
744
- description:
745
- "Create a new content type (schema) that defines the structure for content entries. " +
746
- "Content types have a name, display name, and array of field definitions. " +
747
- "Each field has a name, label, type, and validation options.",
748
- args: createContentTypeArgsSchema,
749
- handler: async (ctx, args) => {
750
- const result = await ctx.runMutation(
751
- componentApi.contentTypeMutations.createContentType,
752
- {
753
- ...args,
754
- createdBy: args.createdBy ?? defaultUserId,
755
- }
756
- );
757
- return result;
758
- },
759
- });
760
-
761
- /**
762
- * Update an existing content type.
763
- */
764
- const updateContentType = createTool({
765
- description:
766
- "Update an existing content type's properties or field definitions. " +
767
- "Can modify display name, description, fields, and other settings.",
768
- args: updateContentTypeArgsSchema,
769
- handler: async (ctx, args) => {
770
- const result = await ctx.runMutation(
771
- componentApi.contentTypeMutations.updateContentType,
772
- {
773
- ...args,
774
- id: args.id ,
775
- updatedBy: args.updatedBy ?? defaultUserId,
776
- }
777
- );
778
- return result;
779
- },
780
- });
781
-
782
- /**
783
- * List all content types.
784
- */
785
- const listContentTypes = createTool({
786
- description:
787
- "List all content types defined in the CMS. " +
788
- "Returns an array of content type definitions with their field schemas.",
789
- args: listContentTypesArgsSchema,
790
- handler: async (ctx, args) => {
791
- const result = await ctx.runQuery(
792
- componentApi.contentTypes.list,
793
- args
794
- );
795
- return result;
796
- },
797
- });
798
-
799
- /**
800
- * Get a single content type by ID or name.
801
- */
802
- const getContentType = createTool({
803
- description:
804
- "Get a single content type by ID or by name. " +
805
- "Returns the full content type definition including all field schemas.",
806
- args: getContentTypeArgsSchema,
807
- handler: async (ctx, args) => {
808
- // The contentTypes.get query supports both id and name lookup via args
809
- if (args.id) {
810
- const result = await ctx.runQuery(componentApi.contentTypes.get, {
811
- id: args.id ,
812
- });
813
- return result;
814
- } else if (args.name) {
815
- // Use the same get query with name argument (not a separate getByName)
816
- const result = await ctx.runQuery(componentApi.contentTypes.get, {
817
- name: args.name,
818
- });
819
- return result;
820
- }
821
- throw new Error("Either id or name must be provided");
822
- },
823
- });
824
-
825
- // ==========================================================================
826
- // Content Entry Tools
827
- // ==========================================================================
828
-
829
- /**
830
- * Create a new content entry.
831
- */
832
- const createContentEntry = createTool({
833
- description:
834
- "Create a new content entry for a specific content type. " +
835
- "Entries start as drafts by default. " +
836
- "Provide field values in the 'data' object matching the content type's field definitions.",
837
- args: createContentEntryArgsSchema,
838
- handler: async (ctx, args) => {
839
- const result = await ctx.runMutation(
840
- componentApi.contentEntryMutations.createEntry,
841
- {
842
- ...args,
843
- contentTypeId: args.contentTypeId ,
844
- createdBy: args.createdBy ?? defaultUserId,
845
- }
846
- );
847
- return result;
848
- },
849
- });
850
-
851
- /**
852
- * Update an existing content entry.
853
- */
854
- const updateContentEntry = createTool({
855
- description:
856
- "Update an existing content entry's data, status, or slug. " +
857
- "Only provide the fields you want to update.",
858
- args: updateContentEntryArgsSchema,
859
- handler: async (ctx, args) => {
860
- const result = await ctx.runMutation(
861
- componentApi.contentEntryMutations.updateEntry,
862
- {
863
- ...args,
864
- id: args.id ,
865
- updatedBy: args.updatedBy ?? defaultUserId,
866
- }
867
- );
868
- return result;
869
- },
870
- });
871
-
872
- /**
873
- * Publish a content entry.
874
- */
875
- const publishEntry = createTool({
876
- description:
877
- "Publish a draft content entry, making it publicly visible. " +
878
- "Creates a version snapshot for history tracking.",
879
- args: publishEntryArgsSchema,
880
- handler: async (ctx, args) => {
881
- const result = await ctx.runMutation(
882
- componentApi.contentEntryMutations.publishEntry,
883
- {
884
- ...args,
885
- id: args.id ,
886
- updatedBy: args.updatedBy ?? defaultUserId,
887
- }
888
- );
889
- return result;
890
- },
891
- });
892
-
893
- /**
894
- * Unpublish a content entry.
895
- */
896
- const unpublishEntry = createTool({
897
- description:
898
- "Unpublish a published content entry, reverting it to draft status. " +
899
- "The entry will no longer be publicly visible.",
900
- args: unpublishEntryArgsSchema,
901
- handler: async (ctx, args) => {
902
- const result = await ctx.runMutation(
903
- componentApi.contentEntryMutations.unpublishEntry,
904
- {
905
- ...args,
906
- id: args.id ,
907
- updatedBy: args.updatedBy ?? defaultUserId,
908
- }
909
- );
910
- return result;
911
- },
912
- });
913
-
914
- /**
915
- * Schedule a content entry for future publishing.
916
- */
917
- const scheduleEntry = createTool({
918
- description:
919
- "Schedule a content entry to be published at a specific time. " +
920
- "The entry will automatically be published at the scheduled time.",
921
- args: scheduleEntryArgsSchema,
922
- handler: async (ctx, args) => {
923
- // Note: scheduleEntry is in the scheduledPublish module, NOT contentEntryMutations
924
- const result = await ctx.runMutation(
925
- componentApi.scheduledPublish.scheduleEntry,
926
- {
927
- ...args,
928
- id: args.id ,
929
- updatedBy: args.updatedBy ?? defaultUserId,
930
- }
931
- );
932
- return result;
933
- },
934
- });
935
-
936
- /**
937
- * Delete a content entry.
938
- */
939
- const deleteContentEntry = createTool({
940
- description:
941
- "Delete a content entry. By default performs soft delete (recoverable). " +
942
- "Set hardDelete to true for permanent deletion.",
943
- args: deleteContentEntryArgsSchema,
944
- handler: async (ctx, args) => {
945
- const result = await ctx.runMutation(
946
- componentApi.contentEntryMutations.deleteEntry,
947
- {
948
- ...args,
949
- id: args.id ,
950
- deletedBy: args.deletedBy ?? defaultUserId,
951
- }
952
- );
953
- return result;
954
- },
955
- });
956
-
957
- /**
958
- * Duplicate a content entry.
959
- */
960
- const duplicateContentEntry = createTool({
961
- description:
962
- "Create a copy of an existing content entry with a new unique slug. " +
963
- "Useful for creating templates or variations.",
964
- args: duplicateContentEntryArgsSchema,
965
- handler: async (ctx, args) => {
966
- const result = await ctx.runMutation(
967
- componentApi.contentEntryMutations.duplicateEntry,
968
- {
969
- ...args,
970
- sourceEntryId: args.sourceEntryId ,
971
- createdBy: args.createdBy ?? defaultUserId,
972
- }
973
- );
974
- return result;
975
- },
976
- });
977
-
978
- /**
979
- * List content entries with filtering and pagination.
980
- */
981
- const listContentEntries = createTool({
982
- description:
983
- "List content entries with optional filtering by content type, status, locale, and more. " +
984
- "Supports pagination through cursor and limit parameters. " +
985
- "Use fieldFilters for advanced filtering on entry data fields.",
986
- args: listContentEntriesArgsSchema,
987
- handler: async (ctx, args) => {
988
- const result = await ctx.runQuery(componentApi.contentEntries.list, {
989
- contentTypeId: args.contentTypeId ,
990
- contentTypeName: args.contentTypeName,
991
- status: args.status,
992
- statusIn: args.statusIn,
993
- locale: args.locale,
994
- search: args.search,
995
- includeDeleted: args.includeDeleted,
996
- fieldFilters: args.fieldFilters,
997
- paginationOpts: {
998
- numItems: args.limit ?? 50,
999
- cursor: args.cursor ?? null,
1000
- },
1001
- });
1002
- return result;
1003
- },
1004
- });
1005
-
1006
- /**
1007
- * Get a single content entry.
1008
- */
1009
- const getContentEntry = createTool({
1010
- description:
1011
- "Get a single content entry by ID or by slug. " +
1012
- "When using slug, you must also provide contentTypeId or contentTypeName.",
1013
- args: getContentEntryArgsSchema,
1014
- handler: async (ctx, args) => {
1015
- if (args.id) {
1016
- const result = await ctx.runQuery(componentApi.contentEntries.get, {
1017
- id: args.id ,
1018
- });
1019
- return result;
1020
- } else if (args.slug) {
1021
- if (args.contentTypeId) {
1022
- const result = await ctx.runQuery(
1023
- componentApi.contentEntries.getBySlug,
1024
- {
1025
- slug: args.slug,
1026
- contentTypeId: args.contentTypeId ,
1027
- }
1028
- );
1029
- return result;
1030
- } else if (args.contentTypeName) {
1031
- const result = await ctx.runQuery(
1032
- componentApi.contentEntries.getBySlugAndTypeName,
1033
- {
1034
- slug: args.slug,
1035
- contentTypeName: args.contentTypeName,
1036
- }
1037
- );
1038
- return result;
1039
- }
1040
- throw new Error(
1041
- "When using slug, contentTypeId or contentTypeName must be provided"
1042
- );
1043
- }
1044
- throw new Error("Either id or slug must be provided");
1045
- },
1046
- });
1047
-
1048
- /**
1049
- * Restore a soft-deleted content entry.
1050
- */
1051
- const restoreContentEntry = createTool({
1052
- description:
1053
- "Restore a soft-deleted content entry from the trash. " +
1054
- "Only works on entries that were soft-deleted, not hard-deleted.",
1055
- args: restoreContentEntryArgsSchema,
1056
- handler: async (ctx, args) => {
1057
- const result = await ctx.runMutation(
1058
- componentApi.contentEntryMutations.restoreEntry,
1059
- {
1060
- id: args.id ,
1061
- updatedBy: args.updatedBy ?? defaultUserId,
1062
- }
1063
- );
1064
- return result;
1065
- },
1066
- });
1067
-
1068
- // ==========================================================================
1069
- // Media Asset Tools
1070
- // ==========================================================================
1071
-
1072
- /**
1073
- * Create a media asset record.
1074
- */
1075
- const createMediaAsset = createTool({
1076
- description:
1077
- "Create a media asset record after uploading a file to Convex storage. " +
1078
- "Requires the storageId from the upload, along with file metadata.",
1079
- args: createMediaAssetArgsSchema,
1080
- handler: async (ctx, args) => {
1081
- const result = await ctx.runMutation(
1082
- componentApi.mediaAssetMutations.createMediaAsset,
1083
- {
1084
- ...args,
1085
- storageId: args.storageId ,
1086
- folderId: args.folderId ,
1087
- createdBy: args.createdBy ?? defaultUserId,
1088
- }
1089
- );
1090
- return result;
1091
- },
1092
- });
1093
-
1094
- /**
1095
- * Update a media asset.
1096
- */
1097
- const updateMediaAsset = createTool({
1098
- description:
1099
- "Update a media asset's metadata (title, description, alt text, tags, folder).",
1100
- args: updateMediaAssetArgsSchema,
1101
- handler: async (ctx, args) => {
1102
- const result = await ctx.runMutation(
1103
- componentApi.mediaAssetMutations.updateMediaAsset,
1104
- {
1105
- ...args,
1106
- id: args.id ,
1107
- folderId: args.folderId ,
1108
- }
1109
- );
1110
- return result;
1111
- },
1112
- });
1113
-
1114
- /**
1115
- * List media assets.
1116
- */
1117
- const listMediaAssets = createTool({
1118
- description:
1119
- "List media assets with optional filtering by folder, type, MIME type, tags, and search.",
1120
- args: listMediaAssetsArgsSchema,
1121
- handler: async (ctx, args) => {
1122
- const result = await ctx.runQuery(componentApi.mediaAssets.list, {
1123
- folderId: args.folderId ,
1124
- type: args.type,
1125
- mimeType: args.mimeType,
1126
- search: args.search,
1127
- tags: args.tags,
1128
- includeDeleted: args.includeDeleted,
1129
- cursor: args.cursor,
1130
- limit: args.limit,
1131
- });
1132
- return result;
1133
- },
1134
- });
1135
-
1136
- /**
1137
- * Get a single media asset.
1138
- */
1139
- const getMediaAsset = createTool({
1140
- description:
1141
- "Get a single media asset by ID, including its download URL.",
1142
- args: getMediaAssetArgsSchema,
1143
- handler: async (ctx, args) => {
1144
- const result = await ctx.runQuery(componentApi.mediaAssets.get, {
1145
- id: args.id ,
1146
- });
1147
- return result;
1148
- },
1149
- });
1150
-
1151
- /**
1152
- * Delete a media asset.
1153
- */
1154
- const deleteMediaAsset = createTool({
1155
- description:
1156
- "Delete a media asset. By default performs soft delete (recoverable).",
1157
- args: deleteMediaAssetArgsSchema,
1158
- handler: async (ctx, args) => {
1159
- const result = await ctx.runMutation(
1160
- componentApi.mediaAssetMutations.deleteMediaAsset,
1161
- {
1162
- id: args.id ,
1163
- deletedBy: args.deletedBy ?? defaultUserId,
1164
- hardDelete: args.hardDelete,
1165
- }
1166
- );
1167
- return result;
1168
- },
1169
- });
1170
-
1171
- // ==========================================================================
1172
- // Bulk Operation Tools
1173
- // ==========================================================================
1174
-
1175
- /**
1176
- * Bulk publish multiple content entries.
1177
- */
1178
- const bulkPublish = createTool({
1179
- description:
1180
- "Publish multiple content entries at once. " +
1181
- "More efficient than publishing entries one by one.",
1182
- args: bulkPublishArgsSchema,
1183
- handler: async (ctx, args) => {
1184
- const result = await ctx.runMutation(
1185
- componentApi.bulkOperations.bulkPublish,
1186
- {
1187
- ids: args.ids,
1188
- changeDescription: args.changeDescription,
1189
- updatedBy: args.updatedBy ?? defaultUserId,
1190
- }
1191
- );
1192
- return result;
1193
- },
1194
- });
1195
-
1196
- /**
1197
- * Bulk unpublish multiple content entries.
1198
- */
1199
- const bulkUnpublish = createTool({
1200
- description:
1201
- "Unpublish multiple content entries at once, reverting them to draft status.",
1202
- args: bulkUnpublishArgsSchema,
1203
- handler: async (ctx, args) => {
1204
- const result = await ctx.runMutation(
1205
- componentApi.bulkOperations.bulkUnpublish,
1206
- {
1207
- ids: args.ids,
1208
- updatedBy: args.updatedBy ?? defaultUserId,
1209
- }
1210
- );
1211
- return result;
1212
- },
1213
- });
1214
-
1215
- /**
1216
- * Bulk delete multiple content entries.
1217
- */
1218
- const bulkDelete = createTool({
1219
- description:
1220
- "Delete multiple content entries at once. " +
1221
- "By default performs soft delete. Set hardDelete for permanent deletion.",
1222
- args: bulkDeleteArgsSchema,
1223
- handler: async (ctx, args) => {
1224
- const result = await ctx.runMutation(
1225
- componentApi.bulkOperations.bulkDelete,
1226
- {
1227
- ids: args.ids,
1228
- deletedBy: args.deletedBy ?? defaultUserId,
1229
- hardDelete: args.hardDelete,
1230
- }
1231
- );
1232
- return result;
1233
- },
1234
- });
1235
-
1236
- // ==========================================================================
1237
- // Search Tool
1238
- // ==========================================================================
1239
-
1240
- /**
1241
- * Search content entries.
1242
- */
1243
- const searchContent = createTool({
1244
- description:
1245
- "Search content entries by text query across all searchable fields. " +
1246
- "Optionally filter by content type and status.",
1247
- args: searchContentArgsSchema,
1248
- handler: async (ctx, args) => {
1249
- const result = await ctx.runQuery(componentApi.contentEntries.list, {
1250
- contentTypeId: args.contentTypeId ,
1251
- contentTypeName: args.contentTypeName,
1252
- status: args.status,
1253
- search: args.query,
1254
- paginationOpts: {
1255
- numItems: args.limit ?? 20,
1256
- cursor: null,
1257
- },
1258
- });
1259
- return result;
1260
- },
1261
- });
1262
-
1263
- // ==========================================================================
1264
- // Return all tools
1265
- // ==========================================================================
1266
-
1267
- return {
1268
- // Content Type Tools
1269
- createContentType,
1270
- updateContentType,
1271
- listContentTypes,
1272
- getContentType,
1273
-
1274
- // Content Entry Tools
1275
- createContentEntry,
1276
- updateContentEntry,
1277
- publishEntry,
1278
- unpublishEntry,
1279
- scheduleEntry,
1280
- deleteContentEntry,
1281
- duplicateContentEntry,
1282
- listContentEntries,
1283
- getContentEntry,
1284
- restoreContentEntry,
1285
-
1286
- // Media Asset Tools
1287
- createMediaAsset,
1288
- updateMediaAsset,
1289
- listMediaAssets,
1290
- getMediaAsset,
1291
- deleteMediaAsset,
1292
-
1293
- // Bulk Operations
1294
- bulkPublish,
1295
- bulkUnpublish,
1296
- bulkDelete,
1297
-
1298
- // Search
1299
- searchContent,
1300
- };
1301
- }
1302
-
1303
- /**
1304
- * Type representing all available CMS tools.
1305
- */
1306
- export type CmsTools = ReturnType<typeof createCmsTools>;
1307
-
1308
- /**
1309
- * Tool names available in the CMS tools object.
1310
- */
1311
- export type CmsToolName = keyof CmsTools;