convex-cms 0.0.1 → 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 (267) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +99 -0
  3. package/admin-dist/nitro.json +15 -0
  4. package/admin-dist/public/assets/CmsEmptyState-CRswfTzk.js +5 -0
  5. package/admin-dist/public/assets/CmsPageHeader-CirpXndm.js +1 -0
  6. package/admin-dist/public/assets/CmsStatusBadge-CbEUpQu-.js +1 -0
  7. package/admin-dist/public/assets/CmsToolbar-BI2nZOXp.js +1 -0
  8. package/admin-dist/public/assets/ContentEntryEditor-CBeCyK_m.js +4 -0
  9. package/admin-dist/public/assets/ErrorState-BIVaWmom.js +1 -0
  10. package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +1 -0
  11. package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +1 -0
  12. package/admin-dist/public/assets/_entryId-CKU_glsK.js +1 -0
  13. package/admin-dist/public/assets/alert-BXjTqrwQ.js +1 -0
  14. package/admin-dist/public/assets/badge-hvUOzpVZ.js +1 -0
  15. package/admin-dist/public/assets/circle-check-big-CF_pR17r.js +1 -0
  16. package/admin-dist/public/assets/command-DU82cJlt.js +1 -0
  17. package/admin-dist/public/assets/content-_LXl3pp7.js +1 -0
  18. package/admin-dist/public/assets/content-types-KjxaXGxY.js +2 -0
  19. package/admin-dist/public/assets/globals-CS6BZ0zp.css +1 -0
  20. package/admin-dist/public/assets/index-DNGIZHL-.js +1 -0
  21. package/admin-dist/public/assets/label-KNtpL71g.js +1 -0
  22. package/admin-dist/public/assets/link-2-Bw2aI4V4.js +1 -0
  23. package/admin-dist/public/assets/list-sYepHjt_.js +1 -0
  24. package/admin-dist/public/assets/main-CKj5yfEi.js +97 -0
  25. package/admin-dist/public/assets/media-Bkrkffm7.js +1 -0
  26. package/admin-dist/public/assets/new._contentTypeId-C3LstjNs.js +1 -0
  27. package/admin-dist/public/assets/plus-DUn8v_Xf.js +1 -0
  28. package/admin-dist/public/assets/rotate-ccw-DJEoHcRI.js +1 -0
  29. package/admin-dist/public/assets/scroll-area-DfIlT0in.js +1 -0
  30. package/admin-dist/public/assets/search-MuAUDJKR.js +1 -0
  31. package/admin-dist/public/assets/select-BD29IXCI.js +1 -0
  32. package/admin-dist/public/assets/settings-DmMyn_6A.js +1 -0
  33. package/admin-dist/public/assets/switch-h3Rrnl5i.js +1 -0
  34. package/admin-dist/public/assets/tabs-imc8h-Dp.js +1 -0
  35. package/admin-dist/public/assets/taxonomies-dAsrT65H.js +1 -0
  36. package/admin-dist/public/assets/textarea-BTy7nwzR.js +1 -0
  37. package/admin-dist/public/assets/trash-SAWKZZHv.js +1 -0
  38. package/admin-dist/public/assets/triangle-alert-E52Vfeuh.js +1 -0
  39. package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +1 -0
  40. package/admin-dist/public/assets/usePermissions-Basjs9BT.js +1 -0
  41. package/admin-dist/public/favicon.ico +0 -0
  42. package/admin-dist/server/_chunks/_libs/@date-fns/tz.mjs +217 -0
  43. package/admin-dist/server/_chunks/_libs/@floating-ui/core.mjs +719 -0
  44. package/admin-dist/server/_chunks/_libs/@floating-ui/dom.mjs +622 -0
  45. package/admin-dist/server/_chunks/_libs/@floating-ui/react-dom.mjs +292 -0
  46. package/admin-dist/server/_chunks/_libs/@floating-ui/utils.mjs +320 -0
  47. package/admin-dist/server/_chunks/_libs/@radix-ui/number.mjs +6 -0
  48. package/admin-dist/server/_chunks/_libs/@radix-ui/primitive.mjs +11 -0
  49. package/admin-dist/server/_chunks/_libs/@radix-ui/react-arrow.mjs +23 -0
  50. package/admin-dist/server/_chunks/_libs/@radix-ui/react-avatar.mjs +119 -0
  51. package/admin-dist/server/_chunks/_libs/@radix-ui/react-checkbox.mjs +270 -0
  52. package/admin-dist/server/_chunks/_libs/@radix-ui/react-collection.mjs +69 -0
  53. package/admin-dist/server/_chunks/_libs/@radix-ui/react-compose-refs.mjs +39 -0
  54. package/admin-dist/server/_chunks/_libs/@radix-ui/react-context.mjs +137 -0
  55. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dialog.mjs +325 -0
  56. package/admin-dist/server/_chunks/_libs/@radix-ui/react-direction.mjs +9 -0
  57. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dismissable-layer.mjs +210 -0
  58. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dropdown-menu.mjs +253 -0
  59. package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-guards.mjs +29 -0
  60. package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-scope.mjs +206 -0
  61. package/admin-dist/server/_chunks/_libs/@radix-ui/react-id.mjs +14 -0
  62. package/admin-dist/server/_chunks/_libs/@radix-ui/react-label.mjs +23 -0
  63. package/admin-dist/server/_chunks/_libs/@radix-ui/react-menu.mjs +812 -0
  64. package/admin-dist/server/_chunks/_libs/@radix-ui/react-popover.mjs +300 -0
  65. package/admin-dist/server/_chunks/_libs/@radix-ui/react-popper.mjs +286 -0
  66. package/admin-dist/server/_chunks/_libs/@radix-ui/react-portal.mjs +16 -0
  67. package/admin-dist/server/_chunks/_libs/@radix-ui/react-presence.mjs +128 -0
  68. package/admin-dist/server/_chunks/_libs/@radix-ui/react-primitive.mjs +141 -0
  69. package/admin-dist/server/_chunks/_libs/@radix-ui/react-roving-focus.mjs +224 -0
  70. package/admin-dist/server/_chunks/_libs/@radix-ui/react-scroll-area.mjs +721 -0
  71. package/admin-dist/server/_chunks/_libs/@radix-ui/react-select.mjs +1163 -0
  72. package/admin-dist/server/_chunks/_libs/@radix-ui/react-separator.mjs +28 -0
  73. package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +601 -0
  74. package/admin-dist/server/_chunks/_libs/@radix-ui/react-switch.mjs +152 -0
  75. package/admin-dist/server/_chunks/_libs/@radix-ui/react-tabs.mjs +189 -0
  76. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-callback-ref.mjs +11 -0
  77. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-controllable-state.mjs +69 -0
  78. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs +1 -0
  79. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-escape-keydown.mjs +17 -0
  80. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-is-hydrated.mjs +15 -0
  81. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-layout-effect.mjs +6 -0
  82. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-previous.mjs +14 -0
  83. package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-size.mjs +39 -0
  84. package/admin-dist/server/_chunks/_libs/@radix-ui/react-visually-hidden.mjs +33 -0
  85. package/admin-dist/server/_chunks/_libs/@tanstack/history.mjs +409 -0
  86. package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +1711 -0
  87. package/admin-dist/server/_chunks/_libs/@tanstack/react-store.mjs +56 -0
  88. package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +4829 -0
  89. package/admin-dist/server/_chunks/_libs/@tanstack/store.mjs +134 -0
  90. package/admin-dist/server/_chunks/_libs/react-dom.mjs +10781 -0
  91. package/admin-dist/server/_chunks/_libs/react.mjs +513 -0
  92. package/admin-dist/server/_libs/aria-hidden.mjs +122 -0
  93. package/admin-dist/server/_libs/class-variance-authority.mjs +44 -0
  94. package/admin-dist/server/_libs/clsx.mjs +16 -0
  95. package/admin-dist/server/_libs/cmdk.mjs +315 -0
  96. package/admin-dist/server/_libs/convex.mjs +4841 -0
  97. package/admin-dist/server/_libs/cookie-es.mjs +58 -0
  98. package/admin-dist/server/_libs/croner.mjs +1 -0
  99. package/admin-dist/server/_libs/crossws.mjs +1 -0
  100. package/admin-dist/server/_libs/date-fns.mjs +1716 -0
  101. package/admin-dist/server/_libs/detect-node-es.mjs +1 -0
  102. package/admin-dist/server/_libs/get-nonce.mjs +9 -0
  103. package/admin-dist/server/_libs/h3-v2.mjs +277 -0
  104. package/admin-dist/server/_libs/h3.mjs +401 -0
  105. package/admin-dist/server/_libs/hookable.mjs +1 -0
  106. package/admin-dist/server/_libs/isbot.mjs +20 -0
  107. package/admin-dist/server/_libs/lucide-react.mjs +850 -0
  108. package/admin-dist/server/_libs/ohash.mjs +1 -0
  109. package/admin-dist/server/_libs/react-day-picker.mjs +2201 -0
  110. package/admin-dist/server/_libs/react-remove-scroll-bar.mjs +82 -0
  111. package/admin-dist/server/_libs/react-remove-scroll.mjs +328 -0
  112. package/admin-dist/server/_libs/react-style-singleton.mjs +69 -0
  113. package/admin-dist/server/_libs/rou3.mjs +8 -0
  114. package/admin-dist/server/_libs/seroval-plugins.mjs +58 -0
  115. package/admin-dist/server/_libs/seroval.mjs +1765 -0
  116. package/admin-dist/server/_libs/srvx.mjs +719 -0
  117. package/admin-dist/server/_libs/tailwind-merge.mjs +3010 -0
  118. package/admin-dist/server/_libs/tiny-invariant.mjs +12 -0
  119. package/admin-dist/server/_libs/tiny-warning.mjs +5 -0
  120. package/admin-dist/server/_libs/tslib.mjs +39 -0
  121. package/admin-dist/server/_libs/ufo.mjs +54 -0
  122. package/admin-dist/server/_libs/unctx.mjs +1 -0
  123. package/admin-dist/server/_libs/unstorage.mjs +1 -0
  124. package/admin-dist/server/_libs/use-callback-ref.mjs +66 -0
  125. package/admin-dist/server/_libs/use-sidecar.mjs +106 -0
  126. package/admin-dist/server/_libs/use-sync-external-store.mjs +139 -0
  127. package/admin-dist/server/_libs/zod.mjs +4223 -0
  128. package/admin-dist/server/_ssr/CmsEmptyState-DU7-7-mV.mjs +290 -0
  129. package/admin-dist/server/_ssr/CmsPageHeader-CseW0AHm.mjs +24 -0
  130. package/admin-dist/server/_ssr/CmsStatusBadge-B_pi4KCp.mjs +127 -0
  131. package/admin-dist/server/_ssr/CmsToolbar-X75ex6ek.mjs +49 -0
  132. package/admin-dist/server/_ssr/ContentEntryEditor-CepusRsA.mjs +3720 -0
  133. package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +89 -0
  134. package/admin-dist/server/_ssr/TaxonomyFilter-Bwrq0-cz.mjs +188 -0
  135. package/admin-dist/server/_ssr/_contentTypeId-BqYKEcLr.mjs +379 -0
  136. package/admin-dist/server/_ssr/_entryId-CRfnqeDf.mjs +161 -0
  137. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +4 -0
  138. package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +92 -0
  139. package/admin-dist/server/_ssr/badge-6BsP37vG.mjs +125 -0
  140. package/admin-dist/server/_ssr/command-fy8epIKf.mjs +128 -0
  141. package/admin-dist/server/_ssr/config.server-D7JHDcDv.mjs +117 -0
  142. package/admin-dist/server/_ssr/content-B5RhL7uW.mjs +532 -0
  143. package/admin-dist/server/_ssr/content-types-BIOqCQYN.mjs +1166 -0
  144. package/admin-dist/server/_ssr/index-DHSHDPt1.mjs +193 -0
  145. package/admin-dist/server/_ssr/index.mjs +1275 -0
  146. package/admin-dist/server/_ssr/label-C8Dko1j7.mjs +22 -0
  147. package/admin-dist/server/_ssr/media-CSx3XttC.mjs +1832 -0
  148. package/admin-dist/server/_ssr/new._contentTypeId-DzanEZQM.mjs +144 -0
  149. package/admin-dist/server/_ssr/router-DDWcF-kt.mjs +1556 -0
  150. package/admin-dist/server/_ssr/scroll-area-bjPYwhXN.mjs +59 -0
  151. package/admin-dist/server/_ssr/select-BUhDDf4T.mjs +142 -0
  152. package/admin-dist/server/_ssr/settings-DAsxnw2q.mjs +348 -0
  153. package/admin-dist/server/_ssr/start-HYkvq4Ni.mjs +4 -0
  154. package/admin-dist/server/_ssr/switch-BgyRtQ1Z.mjs +31 -0
  155. package/admin-dist/server/_ssr/tabs-DzMdRB1A.mjs +628 -0
  156. package/admin-dist/server/_ssr/taxonomies-C8j8g5Q5.mjs +915 -0
  157. package/admin-dist/server/_ssr/textarea-9jNeYJSc.mjs +18 -0
  158. package/admin-dist/server/_ssr/trash-DYMxwhZB.mjs +291 -0
  159. package/admin-dist/server/_ssr/useBreadcrumbLabel-FNSAr2Ha.mjs +16 -0
  160. package/admin-dist/server/_ssr/usePermissions-BJGGahrJ.mjs +68 -0
  161. package/admin-dist/server/favicon.ico +0 -0
  162. package/admin-dist/server/index.mjs +627 -0
  163. package/dist/cli/index.js +0 -0
  164. package/dist/client/admin-config.d.ts +0 -1
  165. package/dist/client/admin-config.d.ts.map +1 -1
  166. package/dist/client/admin-config.js +0 -1
  167. package/dist/client/admin-config.js.map +1 -1
  168. package/dist/client/adminApi.d.ts.map +1 -1
  169. package/dist/client/agentTools.d.ts +1237 -135
  170. package/dist/client/agentTools.d.ts.map +1 -1
  171. package/dist/client/agentTools.js +33 -9
  172. package/dist/client/agentTools.js.map +1 -1
  173. package/dist/client/index.d.ts +1 -1
  174. package/dist/client/index.d.ts.map +1 -1
  175. package/dist/client/index.js.map +1 -1
  176. package/dist/component/_generated/component.d.ts +9 -0
  177. package/dist/component/_generated/component.d.ts.map +1 -1
  178. package/dist/component/mediaAssets.d.ts +35 -0
  179. package/dist/component/mediaAssets.d.ts.map +1 -1
  180. package/dist/component/mediaAssets.js +81 -0
  181. package/dist/component/mediaAssets.js.map +1 -1
  182. package/dist/test.d.ts.map +1 -1
  183. package/dist/test.js +2 -1
  184. package/dist/test.js.map +1 -1
  185. package/package.json +24 -9
  186. package/dist/component/auditLog.d.ts +0 -410
  187. package/dist/component/auditLog.d.ts.map +0 -1
  188. package/dist/component/auditLog.js +0 -607
  189. package/dist/component/auditLog.js.map +0 -1
  190. package/dist/component/types.d.ts +0 -4
  191. package/dist/component/types.d.ts.map +0 -1
  192. package/dist/component/types.js +0 -2
  193. package/dist/component/types.js.map +0 -1
  194. package/src/cli/commands/admin.ts +0 -104
  195. package/src/cli/index.ts +0 -21
  196. package/src/cli/utils/detectConvexUrl.ts +0 -54
  197. package/src/cli/utils/openBrowser.ts +0 -16
  198. package/src/client/admin-config.ts +0 -138
  199. package/src/client/adminApi.ts +0 -942
  200. package/src/client/agentTools.ts +0 -1311
  201. package/src/client/argTypes.ts +0 -316
  202. package/src/client/field-types.ts +0 -187
  203. package/src/client/index.ts +0 -1301
  204. package/src/client/queryBuilder.ts +0 -1100
  205. package/src/client/schema/codegen.ts +0 -500
  206. package/src/client/schema/defineContentType.ts +0 -501
  207. package/src/client/schema/index.ts +0 -169
  208. package/src/client/schema/schemaDrift.ts +0 -574
  209. package/src/client/schema/typedClient.ts +0 -688
  210. package/src/client/schema/types.ts +0 -666
  211. package/src/client/types.ts +0 -723
  212. package/src/client/workflows.ts +0 -141
  213. package/src/client/wrapper.ts +0 -4304
  214. package/src/component/_generated/api.ts +0 -140
  215. package/src/component/_generated/component.ts +0 -5029
  216. package/src/component/_generated/dataModel.ts +0 -60
  217. package/src/component/_generated/server.ts +0 -156
  218. package/src/component/authorization.ts +0 -647
  219. package/src/component/authorizationHooks.ts +0 -668
  220. package/src/component/bulkOperations.ts +0 -687
  221. package/src/component/contentEntries.ts +0 -1976
  222. package/src/component/contentEntryMutations.ts +0 -1223
  223. package/src/component/contentEntryValidation.ts +0 -707
  224. package/src/component/contentLock.ts +0 -550
  225. package/src/component/contentTypeMigration.ts +0 -1064
  226. package/src/component/contentTypeMutations.ts +0 -969
  227. package/src/component/contentTypes.ts +0 -346
  228. package/src/component/convex.config.ts +0 -44
  229. package/src/component/documentTypes.ts +0 -240
  230. package/src/component/eventEmitter.ts +0 -485
  231. package/src/component/exportImport.ts +0 -1169
  232. package/src/component/index.ts +0 -491
  233. package/src/component/lib/deepReferenceResolver.ts +0 -999
  234. package/src/component/lib/errors.ts +0 -816
  235. package/src/component/lib/index.ts +0 -145
  236. package/src/component/lib/mediaReferenceResolver.ts +0 -495
  237. package/src/component/lib/metadataExtractor.ts +0 -792
  238. package/src/component/lib/mutationAuth.ts +0 -199
  239. package/src/component/lib/queries.ts +0 -79
  240. package/src/component/lib/ragContentChunker.ts +0 -1371
  241. package/src/component/lib/referenceResolver.ts +0 -430
  242. package/src/component/lib/slugGenerator.ts +0 -262
  243. package/src/component/lib/slugUniqueness.ts +0 -333
  244. package/src/component/lib/softDelete.ts +0 -44
  245. package/src/component/localeFallbackChain.ts +0 -673
  246. package/src/component/localeFields.ts +0 -896
  247. package/src/component/mediaAssetMutations.ts +0 -725
  248. package/src/component/mediaAssets.ts +0 -932
  249. package/src/component/mediaFolderMutations.ts +0 -1046
  250. package/src/component/mediaUploadMutations.ts +0 -224
  251. package/src/component/mediaVariantMutations.ts +0 -900
  252. package/src/component/mediaVariants.ts +0 -793
  253. package/src/component/ragContentIndexer.ts +0 -1067
  254. package/src/component/rateLimitHooks.ts +0 -572
  255. package/src/component/roles.ts +0 -1360
  256. package/src/component/scheduledPublish.ts +0 -358
  257. package/src/component/schema.ts +0 -617
  258. package/src/component/taxonomies.ts +0 -949
  259. package/src/component/taxonomyMutations.ts +0 -1210
  260. package/src/component/trash.ts +0 -724
  261. package/src/component/userContext.ts +0 -898
  262. package/src/component/validation.ts +0 -1388
  263. package/src/component/validators.ts +0 -949
  264. package/src/component/versionMutations.ts +0 -392
  265. package/src/component/webhookTrigger.ts +0 -1922
  266. package/src/react/index.ts +0 -898
  267. package/src/test.ts +0 -1580
@@ -1,485 +0,0 @@
1
- /**
2
- * Event Emitter Module
3
- *
4
- * Internal system to emit events on content changes (created, updated, published, deleted).
5
- * Events are stored in the cmsEvents table for async processing by external systems,
6
- * webhooks, audit logging, and other integrations.
7
- *
8
- * Design Philosophy:
9
- * - Events are emitted synchronously within the same transaction as mutations
10
- * - This ensures atomicity: if the mutation fails, no event is created
11
- * - Events are stored for later processing (not real-time pub/sub)
12
- * - Consumers can poll events or use Convex reactivity to process them
13
- *
14
- * Usage:
15
- * ```typescript
16
- * // In a mutation handler:
17
- * await emitEvent(ctx, {
18
- * eventType: "contentEntry.created",
19
- * resourceType: "contentEntry",
20
- * resourceId: entry._id.toString(),
21
- * action: "created",
22
- * payload: { slug: entry.slug, contentTypeName: "blog_post" },
23
- * userId: createdBy,
24
- * });
25
- * ```
26
- */
27
-
28
- import { v } from "convex/values";
29
- import { mutation, query, internalMutation, MutationCtx } from "./_generated/server.js";
30
- import {
31
- eventResourceTypeValidator,
32
- eventActionValidator,
33
- cmsEventDoc,
34
- } from "./validators.js";
35
-
36
- // =============================================================================
37
- // Event Types
38
- // =============================================================================
39
-
40
- /**
41
- * Resource types that can emit events.
42
- */
43
- export type EventResourceType =
44
- | "contentEntry"
45
- | "contentType"
46
- | "mediaAsset"
47
- | "mediaFolder";
48
-
49
- /**
50
- * Actions that can be performed on resources.
51
- */
52
- export type EventAction =
53
- | "created"
54
- | "updated"
55
- | "published"
56
- | "unpublished"
57
- | "deleted"
58
- | "restored"
59
- | "duplicated"
60
- | "scheduled";
61
-
62
- /**
63
- * Full event type combining resource and action.
64
- */
65
- export type EventType = `${EventResourceType}.${EventAction}`;
66
-
67
- /**
68
- * Payload structure for content entry events.
69
- */
70
- export interface ContentEntryEventPayload {
71
- slug: string;
72
- contentTypeName: string;
73
- contentTypeId: string;
74
- status: string;
75
- version: number;
76
- locale?: string;
77
- /** For duplicate events, the source entry ID */
78
- sourceEntryId?: string;
79
- /** For scheduled events, the scheduled publish time */
80
- scheduledPublishAt?: number;
81
- /** Change description if provided */
82
- changeDescription?: string;
83
- }
84
-
85
- /**
86
- * Payload structure for content type events.
87
- */
88
- export interface ContentTypeEventPayload {
89
- name: string;
90
- displayName: string;
91
- fieldCount: number;
92
- isActive: boolean;
93
- /** For update events, list of changed field names */
94
- changedFields?: string[];
95
- }
96
-
97
- /**
98
- * Payload structure for media asset events.
99
- */
100
- export interface MediaAssetEventPayload {
101
- name: string;
102
- mimeType: string;
103
- type: string;
104
- size: number;
105
- parentId?: string;
106
- path?: string;
107
- }
108
-
109
- /**
110
- * Payload structure for media folder events.
111
- */
112
- export interface MediaFolderEventPayload {
113
- name: string;
114
- path: string;
115
- parentId?: string;
116
- }
117
-
118
- /**
119
- * Union type for all event payloads.
120
- */
121
- export type EventPayload =
122
- | ContentEntryEventPayload
123
- | ContentTypeEventPayload
124
- | MediaAssetEventPayload
125
- | MediaFolderEventPayload;
126
-
127
- /**
128
- * Parameters for emitting an event.
129
- */
130
- export interface EmitEventParams {
131
- eventType: EventType;
132
- resourceType: EventResourceType;
133
- resourceId: string;
134
- action: EventAction;
135
- payload: EventPayload;
136
- userId?: string;
137
- correlationId?: string;
138
- metadata?: Record<string, unknown>;
139
- }
140
-
141
- /**
142
- * CMS Event document structure (as stored in the database).
143
- */
144
- export interface CMSEvent {
145
- _id: string;
146
- _creationTime: number;
147
- eventType: string;
148
- resourceType: EventResourceType;
149
- resourceId: string;
150
- action: EventAction;
151
- payload: EventPayload;
152
- userId?: string;
153
- processed: boolean;
154
- processedAt?: number;
155
- correlationId?: string;
156
- metadata?: Record<string, unknown>;
157
- }
158
-
159
- // =============================================================================
160
- // Internal Event Emission Helper
161
- // =============================================================================
162
-
163
- /**
164
- * Internal helper function to emit events within mutation handlers.
165
- *
166
- * This function inserts an event record into the cmsEvents table.
167
- * It's designed to be called from within other mutations to ensure
168
- * the event is part of the same atomic transaction.
169
- *
170
- * @param ctx - The mutation context from Convex
171
- * @param params - Event parameters
172
- * @returns The created event ID as a string
173
- */
174
- export async function emitEvent(
175
- ctx: MutationCtx,
176
- params: EmitEventParams
177
- ): Promise<string> {
178
- const {
179
- eventType,
180
- resourceType,
181
- resourceId,
182
- action,
183
- payload,
184
- userId,
185
- correlationId,
186
- metadata,
187
- } = params;
188
-
189
- const eventId = await ctx.db.insert("cmsEvents", {
190
- eventType,
191
- resourceType,
192
- resourceId,
193
- action,
194
- payload,
195
- userId,
196
- processed: false,
197
- correlationId,
198
- metadata,
199
- });
200
-
201
- return eventId;
202
- }
203
-
204
- // =============================================================================
205
- // Event Query Functions
206
- // =============================================================================
207
-
208
- /**
209
- * Query to list recent events with optional filtering.
210
- *
211
- * @param resourceType - Filter by resource type
212
- * @param action - Filter by action
213
- * @param processed - Filter by processed status
214
- * @param limit - Maximum number of events to return
215
- *
216
- * @returns Array of recent events
217
- */
218
- export const listEvents = query({
219
- args: {
220
- resourceType: v.optional(eventResourceTypeValidator),
221
- action: v.optional(eventActionValidator),
222
- processed: v.optional(v.boolean()),
223
- limit: v.optional(v.number()),
224
- cursor: v.optional(v.string()),
225
- },
226
- returns: v.object({
227
- events: v.array(cmsEventDoc),
228
- hasMore: v.boolean(),
229
- }),
230
- handler: async (ctx, args) => {
231
- const { resourceType, action, processed, limit = 50 } = args;
232
-
233
- // Collect and filter in memory for other filters
234
- // (In a production system, you might want more specific indexes)
235
- let events;
236
- if (processed !== undefined) {
237
- events = await ctx.db
238
- .query("cmsEvents")
239
- .withIndex("by_processed", (q) => q.eq("processed", processed))
240
- .order("desc")
241
- .take(limit * 2);
242
- } else {
243
- events = await ctx.db
244
- .query("cmsEvents")
245
- .order("desc")
246
- .take(limit * 2);
247
- }
248
-
249
- // Apply additional filters
250
- if (resourceType !== undefined) {
251
- events = events.filter((e) => e.resourceType === resourceType);
252
- }
253
- if (action !== undefined) {
254
- events = events.filter((e) => e.action === action);
255
- }
256
-
257
- // Limit results
258
- const limitedEvents = events.slice(0, limit);
259
- const hasMore = events.length > limit;
260
-
261
- return {
262
- events: limitedEvents,
263
- hasMore,
264
- };
265
- },
266
- });
267
-
268
- /**
269
- * Query to get events for a specific resource.
270
- *
271
- * @param resourceType - The resource type
272
- * @param resourceId - The resource ID
273
- * @param limit - Maximum number of events to return
274
- *
275
- * @returns Array of events for the resource
276
- */
277
- export const getResourceEvents = query({
278
- args: {
279
- resourceType: eventResourceTypeValidator,
280
- resourceId: v.string(),
281
- limit: v.optional(v.number()),
282
- },
283
- returns: v.array(cmsEventDoc),
284
- handler: async (ctx, args) => {
285
- const { resourceType, resourceId, limit = 50 } = args;
286
-
287
- const events = await ctx.db
288
- .query("cmsEvents")
289
- .withIndex("by_resource", (q) =>
290
- q.eq("resourceType", resourceType).eq("resourceId", resourceId)
291
- )
292
- .order("desc")
293
- .take(limit);
294
-
295
- return events;
296
- },
297
- });
298
-
299
- /**
300
- * Query to get unprocessed events for async processing.
301
- *
302
- * This is useful for building event processors that handle events
303
- * asynchronously (e.g., sending webhooks, updating search indexes).
304
- *
305
- * @param limit - Maximum number of events to return
306
- *
307
- * @returns Array of unprocessed events
308
- */
309
- export const getUnprocessedEvents = query({
310
- args: {
311
- limit: v.optional(v.number()),
312
- },
313
- returns: v.array(cmsEventDoc),
314
- handler: async (ctx, args) => {
315
- const { limit = 100 } = args;
316
-
317
- const events = await ctx.db
318
- .query("cmsEvents")
319
- .withIndex("by_processed", (q) => q.eq("processed", false))
320
- .order("asc") // Process oldest first
321
- .take(limit);
322
-
323
- return events;
324
- },
325
- });
326
-
327
- // =============================================================================
328
- // Event Mutation Functions
329
- // =============================================================================
330
-
331
- /**
332
- * Mutation to mark events as processed.
333
- *
334
- * This should be called by event processors after successfully
335
- * handling an event. This enables at-least-once processing semantics.
336
- *
337
- * @param eventIds - Array of event IDs to mark as processed
338
- *
339
- * @returns Count of events marked as processed
340
- */
341
- export const markEventsProcessed = mutation({
342
- args: {
343
- eventIds: v.array(v.id("cmsEvents")),
344
- },
345
- returns: v.object({
346
- processedCount: v.number(),
347
- }),
348
- handler: async (ctx, args) => {
349
- const { eventIds } = args;
350
- const now = Date.now();
351
- let processedCount = 0;
352
-
353
- for (const eventId of eventIds) {
354
- const event = await ctx.db.get(eventId);
355
- if (event && !event.processed) {
356
- await ctx.db.patch(eventId, {
357
- processed: true,
358
- processedAt: now,
359
- });
360
- processedCount++;
361
- }
362
- }
363
-
364
- return { processedCount };
365
- },
366
- });
367
-
368
- /**
369
- * Internal mutation to emit an event from scheduled functions.
370
- *
371
- * This is used by internal scheduled functions that need to emit events
372
- * but don't have direct access to the emitEvent helper.
373
- */
374
- export const internalEmitEvent = internalMutation({
375
- args: {
376
- eventType: v.string(),
377
- resourceType: v.union(
378
- v.literal("contentEntry"),
379
- v.literal("contentType"),
380
- v.literal("mediaAsset"),
381
- v.literal("mediaFolder")
382
- ),
383
- resourceId: v.string(),
384
- action: v.union(
385
- v.literal("created"),
386
- v.literal("updated"),
387
- v.literal("published"),
388
- v.literal("unpublished"),
389
- v.literal("deleted"),
390
- v.literal("restored"),
391
- v.literal("duplicated"),
392
- v.literal("scheduled")
393
- ),
394
- payload: v.any(),
395
- userId: v.optional(v.string()),
396
- correlationId: v.optional(v.string()),
397
- metadata: v.optional(v.any()),
398
- },
399
- returns: v.id("cmsEvents"),
400
- handler: async (ctx, args) => {
401
- const eventId = await ctx.db.insert("cmsEvents", {
402
- eventType: args.eventType,
403
- resourceType: args.resourceType,
404
- resourceId: args.resourceId,
405
- action: args.action,
406
- payload: args.payload,
407
- userId: args.userId,
408
- processed: false,
409
- correlationId: args.correlationId,
410
- metadata: args.metadata,
411
- });
412
-
413
- return eventId;
414
- },
415
- });
416
-
417
- /**
418
- * Mutation to clean up old processed events.
419
- *
420
- * Events older than the retention period are permanently deleted.
421
- * This helps prevent unbounded growth of the events table.
422
- *
423
- * @param retentionDays - Number of days to retain processed events (default: 30)
424
- *
425
- * @returns Count of events deleted
426
- */
427
- export const cleanupOldEvents = mutation({
428
- args: {
429
- retentionDays: v.optional(v.number()),
430
- },
431
- returns: v.object({
432
- deletedCount: v.number(),
433
- }),
434
- handler: async (ctx, args) => {
435
- const { retentionDays = 30 } = args;
436
- const cutoffTime = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
437
- let deletedCount = 0;
438
-
439
- // Get old processed events
440
- const oldEvents = await ctx.db
441
- .query("cmsEvents")
442
- .withIndex("by_processed", (q) => q.eq("processed", true))
443
- .filter((q) => q.lt(q.field("_creationTime"), cutoffTime))
444
- .take(1000); // Batch limit for safety
445
-
446
- for (const event of oldEvents) {
447
- await ctx.db.delete(event._id);
448
- deletedCount++;
449
- }
450
-
451
- return { deletedCount };
452
- },
453
- });
454
-
455
- // =============================================================================
456
- // Event Type Builders
457
- // =============================================================================
458
-
459
- /**
460
- * Helper function to build a content entry event type string.
461
- */
462
- export function contentEntryEventType(action: EventAction): EventType {
463
- return `contentEntry.${action}`;
464
- }
465
-
466
- /**
467
- * Helper function to build a content type event type string.
468
- */
469
- export function contentTypeEventType(action: EventAction): EventType {
470
- return `contentType.${action}`;
471
- }
472
-
473
- /**
474
- * Helper function to build a media asset event type string.
475
- */
476
- export function mediaAssetEventType(action: EventAction): EventType {
477
- return `mediaAsset.${action}`;
478
- }
479
-
480
- /**
481
- * Helper function to build a media folder event type string.
482
- */
483
- export function mediaFolderEventType(action: EventAction): EventType {
484
- return `mediaFolder.${action}`;
485
- }