convex-cms 0.0.1

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 (379) hide show
  1. package/dist/cli/commands/admin.d.ts +16 -0
  2. package/dist/cli/commands/admin.d.ts.map +1 -0
  3. package/dist/cli/commands/admin.js +88 -0
  4. package/dist/cli/commands/admin.js.map +1 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +18 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/utils/detectConvexUrl.d.ts +13 -0
  10. package/dist/cli/utils/detectConvexUrl.d.ts.map +1 -0
  11. package/dist/cli/utils/detectConvexUrl.js +48 -0
  12. package/dist/cli/utils/detectConvexUrl.js.map +1 -0
  13. package/dist/cli/utils/openBrowser.d.ts +7 -0
  14. package/dist/cli/utils/openBrowser.d.ts.map +1 -0
  15. package/dist/cli/utils/openBrowser.js +17 -0
  16. package/dist/cli/utils/openBrowser.js.map +1 -0
  17. package/dist/client/admin-config.d.ts +126 -0
  18. package/dist/client/admin-config.d.ts.map +1 -0
  19. package/dist/client/admin-config.js +117 -0
  20. package/dist/client/admin-config.js.map +1 -0
  21. package/dist/client/adminApi.d.ts +2273 -0
  22. package/dist/client/adminApi.d.ts.map +1 -0
  23. package/dist/client/adminApi.js +716 -0
  24. package/dist/client/adminApi.js.map +1 -0
  25. package/dist/client/agentTools.d.ts +933 -0
  26. package/dist/client/agentTools.d.ts.map +1 -0
  27. package/dist/client/agentTools.js +1004 -0
  28. package/dist/client/agentTools.js.map +1 -0
  29. package/dist/client/argTypes.d.ts +212 -0
  30. package/dist/client/argTypes.d.ts.map +1 -0
  31. package/dist/client/argTypes.js +5 -0
  32. package/dist/client/argTypes.js.map +1 -0
  33. package/dist/client/field-types.d.ts +55 -0
  34. package/dist/client/field-types.d.ts.map +1 -0
  35. package/dist/client/field-types.js +152 -0
  36. package/dist/client/field-types.js.map +1 -0
  37. package/dist/client/index.d.ts +189 -0
  38. package/dist/client/index.d.ts.map +1 -0
  39. package/dist/client/index.js +668 -0
  40. package/dist/client/index.js.map +1 -0
  41. package/dist/client/queryBuilder.d.ts +765 -0
  42. package/dist/client/queryBuilder.d.ts.map +1 -0
  43. package/dist/client/queryBuilder.js +970 -0
  44. package/dist/client/queryBuilder.js.map +1 -0
  45. package/dist/client/schema/codegen.d.ts +128 -0
  46. package/dist/client/schema/codegen.d.ts.map +1 -0
  47. package/dist/client/schema/codegen.js +318 -0
  48. package/dist/client/schema/codegen.js.map +1 -0
  49. package/dist/client/schema/defineContentType.d.ts +221 -0
  50. package/dist/client/schema/defineContentType.d.ts.map +1 -0
  51. package/dist/client/schema/defineContentType.js +380 -0
  52. package/dist/client/schema/defineContentType.js.map +1 -0
  53. package/dist/client/schema/index.d.ts +85 -0
  54. package/dist/client/schema/index.d.ts.map +1 -0
  55. package/dist/client/schema/index.js +92 -0
  56. package/dist/client/schema/index.js.map +1 -0
  57. package/dist/client/schema/schemaDrift.d.ts +199 -0
  58. package/dist/client/schema/schemaDrift.d.ts.map +1 -0
  59. package/dist/client/schema/schemaDrift.js +340 -0
  60. package/dist/client/schema/schemaDrift.js.map +1 -0
  61. package/dist/client/schema/typedClient.d.ts +401 -0
  62. package/dist/client/schema/typedClient.d.ts.map +1 -0
  63. package/dist/client/schema/typedClient.js +269 -0
  64. package/dist/client/schema/typedClient.js.map +1 -0
  65. package/dist/client/schema/types.d.ts +477 -0
  66. package/dist/client/schema/types.d.ts.map +1 -0
  67. package/dist/client/schema/types.js +39 -0
  68. package/dist/client/schema/types.js.map +1 -0
  69. package/dist/client/types.d.ts +449 -0
  70. package/dist/client/types.d.ts.map +1 -0
  71. package/dist/client/types.js +149 -0
  72. package/dist/client/types.js.map +1 -0
  73. package/dist/client/workflows.d.ts +51 -0
  74. package/dist/client/workflows.d.ts.map +1 -0
  75. package/dist/client/workflows.js +103 -0
  76. package/dist/client/workflows.js.map +1 -0
  77. package/dist/client/wrapper.d.ts +2198 -0
  78. package/dist/client/wrapper.d.ts.map +1 -0
  79. package/dist/client/wrapper.js +2651 -0
  80. package/dist/client/wrapper.js.map +1 -0
  81. package/dist/component/_generated/api.d.ts +124 -0
  82. package/dist/component/_generated/api.d.ts.map +1 -0
  83. package/dist/component/_generated/api.js +31 -0
  84. package/dist/component/_generated/api.js.map +1 -0
  85. package/dist/component/_generated/component.d.ts +4321 -0
  86. package/dist/component/_generated/component.d.ts.map +1 -0
  87. package/dist/component/_generated/component.js +11 -0
  88. package/dist/component/_generated/component.js.map +1 -0
  89. package/dist/component/_generated/dataModel.d.ts +46 -0
  90. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  91. package/dist/component/_generated/dataModel.js +11 -0
  92. package/dist/component/_generated/dataModel.js.map +1 -0
  93. package/dist/component/_generated/server.d.ts +121 -0
  94. package/dist/component/_generated/server.d.ts.map +1 -0
  95. package/dist/component/_generated/server.js +78 -0
  96. package/dist/component/_generated/server.js.map +1 -0
  97. package/dist/component/auditLog.d.ts +410 -0
  98. package/dist/component/auditLog.d.ts.map +1 -0
  99. package/dist/component/auditLog.js +607 -0
  100. package/dist/component/auditLog.js.map +1 -0
  101. package/dist/component/authorization.d.ts +323 -0
  102. package/dist/component/authorization.d.ts.map +1 -0
  103. package/dist/component/authorization.js +464 -0
  104. package/dist/component/authorization.js.map +1 -0
  105. package/dist/component/authorizationHooks.d.ts +184 -0
  106. package/dist/component/authorizationHooks.d.ts.map +1 -0
  107. package/dist/component/authorizationHooks.js +521 -0
  108. package/dist/component/authorizationHooks.js.map +1 -0
  109. package/dist/component/bulkOperations.d.ts +200 -0
  110. package/dist/component/bulkOperations.d.ts.map +1 -0
  111. package/dist/component/bulkOperations.js +568 -0
  112. package/dist/component/bulkOperations.js.map +1 -0
  113. package/dist/component/contentEntries.d.ts +719 -0
  114. package/dist/component/contentEntries.d.ts.map +1 -0
  115. package/dist/component/contentEntries.js +1617 -0
  116. package/dist/component/contentEntries.js.map +1 -0
  117. package/dist/component/contentEntryMutations.d.ts +505 -0
  118. package/dist/component/contentEntryMutations.d.ts.map +1 -0
  119. package/dist/component/contentEntryMutations.js +1009 -0
  120. package/dist/component/contentEntryMutations.js.map +1 -0
  121. package/dist/component/contentEntryValidation.d.ts +115 -0
  122. package/dist/component/contentEntryValidation.d.ts.map +1 -0
  123. package/dist/component/contentEntryValidation.js +546 -0
  124. package/dist/component/contentEntryValidation.js.map +1 -0
  125. package/dist/component/contentLock.d.ts +328 -0
  126. package/dist/component/contentLock.d.ts.map +1 -0
  127. package/dist/component/contentLock.js +471 -0
  128. package/dist/component/contentLock.js.map +1 -0
  129. package/dist/component/contentTypeMigration.d.ts +411 -0
  130. package/dist/component/contentTypeMigration.d.ts.map +1 -0
  131. package/dist/component/contentTypeMigration.js +805 -0
  132. package/dist/component/contentTypeMigration.js.map +1 -0
  133. package/dist/component/contentTypeMutations.d.ts +975 -0
  134. package/dist/component/contentTypeMutations.d.ts.map +1 -0
  135. package/dist/component/contentTypeMutations.js +768 -0
  136. package/dist/component/contentTypeMutations.js.map +1 -0
  137. package/dist/component/contentTypes.d.ts +538 -0
  138. package/dist/component/contentTypes.d.ts.map +1 -0
  139. package/dist/component/contentTypes.js +304 -0
  140. package/dist/component/contentTypes.js.map +1 -0
  141. package/dist/component/convex.config.d.ts +42 -0
  142. package/dist/component/convex.config.d.ts.map +1 -0
  143. package/dist/component/convex.config.js +43 -0
  144. package/dist/component/convex.config.js.map +1 -0
  145. package/dist/component/documentTypes.d.ts +186 -0
  146. package/dist/component/documentTypes.d.ts.map +1 -0
  147. package/dist/component/documentTypes.js +23 -0
  148. package/dist/component/documentTypes.js.map +1 -0
  149. package/dist/component/eventEmitter.d.ts +281 -0
  150. package/dist/component/eventEmitter.d.ts.map +1 -0
  151. package/dist/component/eventEmitter.js +300 -0
  152. package/dist/component/eventEmitter.js.map +1 -0
  153. package/dist/component/exportImport.d.ts +1120 -0
  154. package/dist/component/exportImport.d.ts.map +1 -0
  155. package/dist/component/exportImport.js +931 -0
  156. package/dist/component/exportImport.js.map +1 -0
  157. package/dist/component/index.d.ts +28 -0
  158. package/dist/component/index.d.ts.map +1 -0
  159. package/dist/component/index.js +142 -0
  160. package/dist/component/index.js.map +1 -0
  161. package/dist/component/lib/deepReferenceResolver.d.ts +252 -0
  162. package/dist/component/lib/deepReferenceResolver.d.ts.map +1 -0
  163. package/dist/component/lib/deepReferenceResolver.js +601 -0
  164. package/dist/component/lib/deepReferenceResolver.js.map +1 -0
  165. package/dist/component/lib/errors.d.ts +306 -0
  166. package/dist/component/lib/errors.d.ts.map +1 -0
  167. package/dist/component/lib/errors.js +407 -0
  168. package/dist/component/lib/errors.js.map +1 -0
  169. package/dist/component/lib/index.d.ts +10 -0
  170. package/dist/component/lib/index.d.ts.map +1 -0
  171. package/dist/component/lib/index.js +33 -0
  172. package/dist/component/lib/index.js.map +1 -0
  173. package/dist/component/lib/mediaReferenceResolver.d.ts +217 -0
  174. package/dist/component/lib/mediaReferenceResolver.d.ts.map +1 -0
  175. package/dist/component/lib/mediaReferenceResolver.js +326 -0
  176. package/dist/component/lib/mediaReferenceResolver.js.map +1 -0
  177. package/dist/component/lib/metadataExtractor.d.ts +245 -0
  178. package/dist/component/lib/metadataExtractor.d.ts.map +1 -0
  179. package/dist/component/lib/metadataExtractor.js +548 -0
  180. package/dist/component/lib/metadataExtractor.js.map +1 -0
  181. package/dist/component/lib/mutationAuth.d.ts +95 -0
  182. package/dist/component/lib/mutationAuth.d.ts.map +1 -0
  183. package/dist/component/lib/mutationAuth.js +146 -0
  184. package/dist/component/lib/mutationAuth.js.map +1 -0
  185. package/dist/component/lib/queries.d.ts +17 -0
  186. package/dist/component/lib/queries.d.ts.map +1 -0
  187. package/dist/component/lib/queries.js +49 -0
  188. package/dist/component/lib/queries.js.map +1 -0
  189. package/dist/component/lib/ragContentChunker.d.ts +423 -0
  190. package/dist/component/lib/ragContentChunker.d.ts.map +1 -0
  191. package/dist/component/lib/ragContentChunker.js +897 -0
  192. package/dist/component/lib/ragContentChunker.js.map +1 -0
  193. package/dist/component/lib/referenceResolver.d.ts +175 -0
  194. package/dist/component/lib/referenceResolver.d.ts.map +1 -0
  195. package/dist/component/lib/referenceResolver.js +293 -0
  196. package/dist/component/lib/referenceResolver.js.map +1 -0
  197. package/dist/component/lib/slugGenerator.d.ts +71 -0
  198. package/dist/component/lib/slugGenerator.d.ts.map +1 -0
  199. package/dist/component/lib/slugGenerator.js +207 -0
  200. package/dist/component/lib/slugGenerator.js.map +1 -0
  201. package/dist/component/lib/slugUniqueness.d.ts +131 -0
  202. package/dist/component/lib/slugUniqueness.d.ts.map +1 -0
  203. package/dist/component/lib/slugUniqueness.js +229 -0
  204. package/dist/component/lib/slugUniqueness.js.map +1 -0
  205. package/dist/component/lib/softDelete.d.ts +18 -0
  206. package/dist/component/lib/softDelete.d.ts.map +1 -0
  207. package/dist/component/lib/softDelete.js +29 -0
  208. package/dist/component/lib/softDelete.js.map +1 -0
  209. package/dist/component/localeFallbackChain.d.ts +410 -0
  210. package/dist/component/localeFallbackChain.d.ts.map +1 -0
  211. package/dist/component/localeFallbackChain.js +467 -0
  212. package/dist/component/localeFallbackChain.js.map +1 -0
  213. package/dist/component/localeFields.d.ts +508 -0
  214. package/dist/component/localeFields.d.ts.map +1 -0
  215. package/dist/component/localeFields.js +592 -0
  216. package/dist/component/localeFields.js.map +1 -0
  217. package/dist/component/mediaAssetMutations.d.ts +235 -0
  218. package/dist/component/mediaAssetMutations.d.ts.map +1 -0
  219. package/dist/component/mediaAssetMutations.js +558 -0
  220. package/dist/component/mediaAssetMutations.js.map +1 -0
  221. package/dist/component/mediaAssets.d.ts +168 -0
  222. package/dist/component/mediaAssets.d.ts.map +1 -0
  223. package/dist/component/mediaAssets.js +618 -0
  224. package/dist/component/mediaAssets.js.map +1 -0
  225. package/dist/component/mediaFolderMutations.d.ts +642 -0
  226. package/dist/component/mediaFolderMutations.d.ts.map +1 -0
  227. package/dist/component/mediaFolderMutations.js +849 -0
  228. package/dist/component/mediaFolderMutations.js.map +1 -0
  229. package/dist/component/mediaUploadMutations.d.ts +136 -0
  230. package/dist/component/mediaUploadMutations.d.ts.map +1 -0
  231. package/dist/component/mediaUploadMutations.js +205 -0
  232. package/dist/component/mediaUploadMutations.js.map +1 -0
  233. package/dist/component/mediaVariantMutations.d.ts +468 -0
  234. package/dist/component/mediaVariantMutations.d.ts.map +1 -0
  235. package/dist/component/mediaVariantMutations.js +737 -0
  236. package/dist/component/mediaVariantMutations.js.map +1 -0
  237. package/dist/component/mediaVariants.d.ts +525 -0
  238. package/dist/component/mediaVariants.d.ts.map +1 -0
  239. package/dist/component/mediaVariants.js +661 -0
  240. package/dist/component/mediaVariants.js.map +1 -0
  241. package/dist/component/ragContentIndexer.d.ts +595 -0
  242. package/dist/component/ragContentIndexer.d.ts.map +1 -0
  243. package/dist/component/ragContentIndexer.js +794 -0
  244. package/dist/component/ragContentIndexer.js.map +1 -0
  245. package/dist/component/rateLimitHooks.d.ts +266 -0
  246. package/dist/component/rateLimitHooks.d.ts.map +1 -0
  247. package/dist/component/rateLimitHooks.js +412 -0
  248. package/dist/component/rateLimitHooks.js.map +1 -0
  249. package/dist/component/roles.d.ts +649 -0
  250. package/dist/component/roles.d.ts.map +1 -0
  251. package/dist/component/roles.js +884 -0
  252. package/dist/component/roles.js.map +1 -0
  253. package/dist/component/scheduledPublish.d.ts +182 -0
  254. package/dist/component/scheduledPublish.d.ts.map +1 -0
  255. package/dist/component/scheduledPublish.js +304 -0
  256. package/dist/component/scheduledPublish.js.map +1 -0
  257. package/dist/component/schema.d.ts +4114 -0
  258. package/dist/component/schema.d.ts.map +1 -0
  259. package/dist/component/schema.js +469 -0
  260. package/dist/component/schema.js.map +1 -0
  261. package/dist/component/taxonomies.d.ts +476 -0
  262. package/dist/component/taxonomies.d.ts.map +1 -0
  263. package/dist/component/taxonomies.js +785 -0
  264. package/dist/component/taxonomies.js.map +1 -0
  265. package/dist/component/taxonomyMutations.d.ts +206 -0
  266. package/dist/component/taxonomyMutations.d.ts.map +1 -0
  267. package/dist/component/taxonomyMutations.js +1001 -0
  268. package/dist/component/taxonomyMutations.js.map +1 -0
  269. package/dist/component/trash.d.ts +265 -0
  270. package/dist/component/trash.d.ts.map +1 -0
  271. package/dist/component/trash.js +621 -0
  272. package/dist/component/trash.js.map +1 -0
  273. package/dist/component/types.d.ts +4 -0
  274. package/dist/component/types.d.ts.map +1 -0
  275. package/dist/component/types.js +2 -0
  276. package/dist/component/types.js.map +1 -0
  277. package/dist/component/userContext.d.ts +508 -0
  278. package/dist/component/userContext.d.ts.map +1 -0
  279. package/dist/component/userContext.js +615 -0
  280. package/dist/component/userContext.js.map +1 -0
  281. package/dist/component/validation.d.ts +387 -0
  282. package/dist/component/validation.d.ts.map +1 -0
  283. package/dist/component/validation.js +1052 -0
  284. package/dist/component/validation.js.map +1 -0
  285. package/dist/component/validators.d.ts +4645 -0
  286. package/dist/component/validators.d.ts.map +1 -0
  287. package/dist/component/validators.js +641 -0
  288. package/dist/component/validators.js.map +1 -0
  289. package/dist/component/versionMutations.d.ts +216 -0
  290. package/dist/component/versionMutations.d.ts.map +1 -0
  291. package/dist/component/versionMutations.js +321 -0
  292. package/dist/component/versionMutations.js.map +1 -0
  293. package/dist/component/webhookTrigger.d.ts +770 -0
  294. package/dist/component/webhookTrigger.d.ts.map +1 -0
  295. package/dist/component/webhookTrigger.js +1413 -0
  296. package/dist/component/webhookTrigger.js.map +1 -0
  297. package/dist/react/index.d.ts +316 -0
  298. package/dist/react/index.d.ts.map +1 -0
  299. package/dist/react/index.js +558 -0
  300. package/dist/react/index.js.map +1 -0
  301. package/dist/test.d.ts +2230 -0
  302. package/dist/test.d.ts.map +1 -0
  303. package/dist/test.js +1107 -0
  304. package/dist/test.js.map +1 -0
  305. package/package.json +95 -0
  306. package/src/cli/commands/admin.ts +104 -0
  307. package/src/cli/index.ts +21 -0
  308. package/src/cli/utils/detectConvexUrl.ts +54 -0
  309. package/src/cli/utils/openBrowser.ts +16 -0
  310. package/src/client/admin-config.ts +138 -0
  311. package/src/client/adminApi.ts +942 -0
  312. package/src/client/agentTools.ts +1311 -0
  313. package/src/client/argTypes.ts +316 -0
  314. package/src/client/field-types.ts +187 -0
  315. package/src/client/index.ts +1301 -0
  316. package/src/client/queryBuilder.ts +1100 -0
  317. package/src/client/schema/codegen.ts +500 -0
  318. package/src/client/schema/defineContentType.ts +501 -0
  319. package/src/client/schema/index.ts +169 -0
  320. package/src/client/schema/schemaDrift.ts +574 -0
  321. package/src/client/schema/typedClient.ts +688 -0
  322. package/src/client/schema/types.ts +666 -0
  323. package/src/client/types.ts +723 -0
  324. package/src/client/workflows.ts +141 -0
  325. package/src/client/wrapper.ts +4304 -0
  326. package/src/component/_generated/api.ts +140 -0
  327. package/src/component/_generated/component.ts +5029 -0
  328. package/src/component/_generated/dataModel.ts +60 -0
  329. package/src/component/_generated/server.ts +156 -0
  330. package/src/component/authorization.ts +647 -0
  331. package/src/component/authorizationHooks.ts +668 -0
  332. package/src/component/bulkOperations.ts +687 -0
  333. package/src/component/contentEntries.ts +1976 -0
  334. package/src/component/contentEntryMutations.ts +1223 -0
  335. package/src/component/contentEntryValidation.ts +707 -0
  336. package/src/component/contentLock.ts +550 -0
  337. package/src/component/contentTypeMigration.ts +1064 -0
  338. package/src/component/contentTypeMutations.ts +969 -0
  339. package/src/component/contentTypes.ts +346 -0
  340. package/src/component/convex.config.ts +44 -0
  341. package/src/component/documentTypes.ts +240 -0
  342. package/src/component/eventEmitter.ts +485 -0
  343. package/src/component/exportImport.ts +1169 -0
  344. package/src/component/index.ts +491 -0
  345. package/src/component/lib/deepReferenceResolver.ts +999 -0
  346. package/src/component/lib/errors.ts +816 -0
  347. package/src/component/lib/index.ts +145 -0
  348. package/src/component/lib/mediaReferenceResolver.ts +495 -0
  349. package/src/component/lib/metadataExtractor.ts +792 -0
  350. package/src/component/lib/mutationAuth.ts +199 -0
  351. package/src/component/lib/queries.ts +79 -0
  352. package/src/component/lib/ragContentChunker.ts +1371 -0
  353. package/src/component/lib/referenceResolver.ts +430 -0
  354. package/src/component/lib/slugGenerator.ts +262 -0
  355. package/src/component/lib/slugUniqueness.ts +333 -0
  356. package/src/component/lib/softDelete.ts +44 -0
  357. package/src/component/localeFallbackChain.ts +673 -0
  358. package/src/component/localeFields.ts +896 -0
  359. package/src/component/mediaAssetMutations.ts +725 -0
  360. package/src/component/mediaAssets.ts +932 -0
  361. package/src/component/mediaFolderMutations.ts +1046 -0
  362. package/src/component/mediaUploadMutations.ts +224 -0
  363. package/src/component/mediaVariantMutations.ts +900 -0
  364. package/src/component/mediaVariants.ts +793 -0
  365. package/src/component/ragContentIndexer.ts +1067 -0
  366. package/src/component/rateLimitHooks.ts +572 -0
  367. package/src/component/roles.ts +1360 -0
  368. package/src/component/scheduledPublish.ts +358 -0
  369. package/src/component/schema.ts +617 -0
  370. package/src/component/taxonomies.ts +949 -0
  371. package/src/component/taxonomyMutations.ts +1210 -0
  372. package/src/component/trash.ts +724 -0
  373. package/src/component/userContext.ts +898 -0
  374. package/src/component/validation.ts +1388 -0
  375. package/src/component/validators.ts +949 -0
  376. package/src/component/versionMutations.ts +392 -0
  377. package/src/component/webhookTrigger.ts +1922 -0
  378. package/src/react/index.ts +898 -0
  379. package/src/test.ts +1580 -0
@@ -0,0 +1,471 @@
1
+ /**
2
+ * Content Lock Functions
3
+ *
4
+ * Implements optimistic locking for content entries to prevent concurrent edit conflicts.
5
+ * Provides lock acquisition, release, renewal, and status checking.
6
+ *
7
+ * Lock Lifecycle:
8
+ * 1. User acquires lock when opening content for editing
9
+ * 2. Lock auto-expires after configured duration (default 30 minutes)
10
+ * 3. User can renew lock to extend editing session
11
+ * 4. User releases lock when done editing (or lock auto-expires)
12
+ * 5. Admins can force-release locks when needed
13
+ *
14
+ * Lock Behavior:
15
+ * - Only one user can hold a lock at a time
16
+ * - Locks automatically expire to prevent orphaned locks
17
+ * - The lock holder can update their locked entry
18
+ * - Other users receive an error when trying to update locked content
19
+ */
20
+ import { v } from "convex/values";
21
+ import { isDeleted } from "./lib/softDelete.js";
22
+ import { mutation, query } from "./_generated/server.js";
23
+ import { acquireLockArgs, releaseLockArgs, forceReleaseLockArgs, renewLockArgs, checkLockArgs, listLockedEntriesArgs, lockStatusDoc, lockAcquisitionResult, contentEntryDoc, DEFAULT_LOCK_DURATION_MS, MAX_LOCK_DURATION_MS, } from "./validators.js";
24
+ // =============================================================================
25
+ // Helper Functions
26
+ // =============================================================================
27
+ /**
28
+ * Checks if a lock is currently active (not expired).
29
+ * @param lockExpiresAt - The lock expiration timestamp
30
+ * @returns true if lock is active, false if expired or not set
31
+ */
32
+ function isLockActive(lockExpiresAt) {
33
+ if (lockExpiresAt === undefined) {
34
+ return false;
35
+ }
36
+ return Date.now() < lockExpiresAt;
37
+ }
38
+ /**
39
+ * Calculates the time remaining on a lock.
40
+ * @param lockExpiresAt - The lock expiration timestamp
41
+ * @returns Time remaining in milliseconds, or 0 if expired
42
+ */
43
+ function getTimeRemaining(lockExpiresAt) {
44
+ if (lockExpiresAt === undefined) {
45
+ return 0;
46
+ }
47
+ const remaining = lockExpiresAt - Date.now();
48
+ return remaining > 0 ? remaining : 0;
49
+ }
50
+ /**
51
+ * Validates and clamps lock duration to allowed range.
52
+ * @param requestedDuration - Requested lock duration in ms
53
+ * @returns Clamped duration within allowed range
54
+ */
55
+ function validateLockDuration(requestedDuration) {
56
+ const duration = requestedDuration ?? DEFAULT_LOCK_DURATION_MS;
57
+ if (duration <= 0) {
58
+ return DEFAULT_LOCK_DURATION_MS;
59
+ }
60
+ return Math.min(duration, MAX_LOCK_DURATION_MS);
61
+ }
62
+ // =============================================================================
63
+ // Lock Query Functions
64
+ // =============================================================================
65
+ /**
66
+ * Query to check the lock status of a content entry.
67
+ *
68
+ * Returns detailed information about the current lock state,
69
+ * including whether it's locked, by whom, and how much time remains.
70
+ *
71
+ * @param id - The content entry ID to check
72
+ * @returns Lock status information
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const status = await ctx.runQuery(api.contentLock.checkLock, {
77
+ * id: entryId,
78
+ * });
79
+ * if (status.isLocked && status.lockedBy !== currentUserId) {
80
+ * console.log(`Entry is locked by ${status.lockedBy}`);
81
+ * }
82
+ * ```
83
+ */
84
+ export const checkLock = query({
85
+ args: checkLockArgs.fields,
86
+ returns: lockStatusDoc,
87
+ handler: async (ctx, args) => {
88
+ const { id } = args;
89
+ const entry = await ctx.db.get(id);
90
+ if (!entry) {
91
+ throw new Error(`Content entry not found: ${id}`);
92
+ }
93
+ const _now = Date.now();
94
+ const hasLock = entry.lockedBy !== undefined && entry.lockExpiresAt !== undefined;
95
+ const isActive = hasLock && isLockActive(entry.lockExpiresAt);
96
+ const isExpired = hasLock && !isActive;
97
+ const timeRemaining = isActive
98
+ ? getTimeRemaining(entry.lockExpiresAt)
99
+ : undefined;
100
+ return {
101
+ isLocked: isActive,
102
+ lockedBy: isActive ? entry.lockedBy : undefined,
103
+ lockExpiresAt: isActive ? entry.lockExpiresAt : undefined,
104
+ timeRemaining,
105
+ isExpired,
106
+ };
107
+ },
108
+ });
109
+ /**
110
+ * Query to list all locked content entries.
111
+ *
112
+ * Useful for admin dashboards to see which entries are currently
113
+ * being edited and by whom.
114
+ *
115
+ * @param contentTypeId - Optional filter by content type
116
+ * @param lockedBy - Optional filter by locking user
117
+ * @param paginationOpts - Pagination options
118
+ * @returns Paginated list of locked entries
119
+ */
120
+ export const listLockedEntries = query({
121
+ args: listLockedEntriesArgs.fields,
122
+ returns: v.object({
123
+ page: v.array(v.object({
124
+ ...contentEntryDoc.fields,
125
+ timeRemaining: v.optional(v.number()),
126
+ })),
127
+ continueCursor: v.union(v.string(), v.null()),
128
+ isDone: v.boolean(),
129
+ }),
130
+ handler: async (ctx, args) => {
131
+ const { contentTypeId, lockedBy, paginationOpts } = args;
132
+ const _now = Date.now();
133
+ // Query entries with locks using the by_locked index
134
+ const query = ctx.db.query("contentEntries").withIndex("by_locked");
135
+ // Collect all entries with locks
136
+ const allLocked = await query.collect();
137
+ // Filter to only active (non-expired) locks
138
+ const entries = allLocked.filter((entry) => {
139
+ // Must have lock fields set
140
+ if (entry.lockedBy === undefined || entry.lockExpiresAt === undefined) {
141
+ return false;
142
+ }
143
+ // Must not be expired
144
+ if (!isLockActive(entry.lockExpiresAt)) {
145
+ return false;
146
+ }
147
+ // Must not be deleted
148
+ if (isDeleted(entry)) {
149
+ return false;
150
+ }
151
+ // Apply content type filter if provided
152
+ if (contentTypeId && entry.contentTypeId !== contentTypeId) {
153
+ return false;
154
+ }
155
+ // Apply lockedBy filter if provided
156
+ if (lockedBy && entry.lockedBy !== lockedBy) {
157
+ return false;
158
+ }
159
+ return true;
160
+ });
161
+ // Simple pagination (manual implementation since we filtered in memory)
162
+ const numItems = paginationOpts.numItems ?? 50;
163
+ const cursor = paginationOpts.cursor;
164
+ let startIndex = 0;
165
+ if (cursor) {
166
+ const cursorIndex = entries.findIndex((e) => e._id === cursor);
167
+ if (cursorIndex !== -1) {
168
+ startIndex = cursorIndex + 1;
169
+ }
170
+ }
171
+ const page = entries.slice(startIndex, startIndex + numItems);
172
+ const hasMore = startIndex + numItems < entries.length;
173
+ const nextCursor = hasMore ? page[page.length - 1]?._id ?? null : null;
174
+ // Add time remaining to each entry
175
+ const pageWithRemaining = page.map((entry) => ({
176
+ ...entry,
177
+ timeRemaining: getTimeRemaining(entry.lockExpiresAt),
178
+ }));
179
+ return {
180
+ page: pageWithRemaining,
181
+ continueCursor: nextCursor,
182
+ isDone: !hasMore,
183
+ };
184
+ },
185
+ });
186
+ // =============================================================================
187
+ // Lock Mutation Functions
188
+ // =============================================================================
189
+ /**
190
+ * Mutation to acquire a lock on a content entry.
191
+ *
192
+ * Attempts to acquire an exclusive lock on an entry for editing.
193
+ * The lock will automatically expire after the specified duration.
194
+ *
195
+ * Lock acquisition rules:
196
+ * - If entry is not locked, lock is acquired
197
+ * - If entry is locked by the same user, lock is renewed
198
+ * - If entry is locked by another user and lock is expired, lock is acquired
199
+ * - If entry is locked by another user and lock is active, acquisition fails
200
+ *
201
+ * @param id - The content entry ID to lock
202
+ * @param userId - User ID acquiring the lock
203
+ * @param lockDuration - Optional lock duration (default 30 min, max 4 hours)
204
+ * @returns Lock acquisition result with success status and entry
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const result = await ctx.runMutation(api.contentLock.acquireLock, {
209
+ * id: entryId,
210
+ * userId: currentUserId,
211
+ * lockDuration: 60 * 60 * 1000, // 1 hour
212
+ * });
213
+ *
214
+ * if (result.success) {
215
+ * console.log("Lock acquired, editing enabled");
216
+ * } else {
217
+ * console.log(`Lock held by ${result.currentLockHolder}`);
218
+ * }
219
+ * ```
220
+ */
221
+ export const acquireLock = mutation({
222
+ args: acquireLockArgs.fields,
223
+ returns: lockAcquisitionResult,
224
+ handler: async (ctx, args) => {
225
+ const { id, userId, lockDuration } = args;
226
+ const entry = await ctx.db.get(id);
227
+ if (!entry) {
228
+ return {
229
+ success: false,
230
+ error: `Content entry not found: ${id}`,
231
+ };
232
+ }
233
+ // Check if entry is deleted
234
+ if (isDeleted(entry)) {
235
+ return {
236
+ success: false,
237
+ error: `Content entry has been deleted: ${id}`,
238
+ };
239
+ }
240
+ // Calculate lock expiration
241
+ const validDuration = validateLockDuration(lockDuration);
242
+ const now = Date.now();
243
+ const newLockExpiresAt = now + validDuration;
244
+ // Check current lock status
245
+ const hasExistingLock = entry.lockedBy !== undefined && entry.lockExpiresAt !== undefined;
246
+ const isExistingLockActive = hasExistingLock && isLockActive(entry.lockExpiresAt);
247
+ const isSameUser = entry.lockedBy === userId;
248
+ // Case 1: Entry is locked by another user with an active lock
249
+ if (isExistingLockActive && !isSameUser) {
250
+ return {
251
+ success: false,
252
+ error: `Entry is locked by another user`,
253
+ currentLockHolder: entry.lockedBy,
254
+ currentLockExpiresAt: entry.lockExpiresAt,
255
+ };
256
+ }
257
+ // Case 2: Same user re-acquiring (renew) OR expired lock OR no lock
258
+ // Acquire/renew the lock
259
+ await ctx.db.patch(id, {
260
+ lockedBy: userId,
261
+ lockExpiresAt: newLockExpiresAt,
262
+ });
263
+ // Fetch updated entry
264
+ const updatedEntry = await ctx.db.get(id);
265
+ if (!updatedEntry) {
266
+ return {
267
+ success: false,
268
+ error: "Failed to retrieve updated entry",
269
+ };
270
+ }
271
+ return {
272
+ success: true,
273
+ entry: updatedEntry,
274
+ };
275
+ },
276
+ });
277
+ /**
278
+ * Mutation to release a lock on a content entry.
279
+ *
280
+ * Only the lock owner can release their lock. This should be called
281
+ * when the user finishes editing or navigates away from the editor.
282
+ *
283
+ * @param id - The content entry ID to unlock
284
+ * @param userId - User ID releasing the lock (must match lock owner)
285
+ * @returns The unlocked content entry
286
+ *
287
+ * @throws Error if entry not found
288
+ * @throws Error if entry not locked by this user
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * const entry = await ctx.runMutation(api.contentLock.releaseLock, {
293
+ * id: entryId,
294
+ * userId: currentUserId,
295
+ * });
296
+ * console.log("Lock released");
297
+ * ```
298
+ */
299
+ export const releaseLock = mutation({
300
+ args: releaseLockArgs.fields,
301
+ returns: contentEntryDoc,
302
+ handler: async (ctx, args) => {
303
+ const { id, userId } = args;
304
+ const entry = await ctx.db.get(id);
305
+ if (!entry) {
306
+ throw new Error(`Content entry not found: ${id}`);
307
+ }
308
+ // Verify the user owns the lock
309
+ if (entry.lockedBy !== userId) {
310
+ if (entry.lockedBy === undefined) {
311
+ throw new Error(`Content entry is not locked: ${id}`);
312
+ }
313
+ throw new Error(`Cannot release lock: entry is locked by another user`);
314
+ }
315
+ // Release the lock
316
+ await ctx.db.patch(id, {
317
+ lockedBy: undefined,
318
+ lockExpiresAt: undefined,
319
+ });
320
+ const updatedEntry = await ctx.db.get(id);
321
+ if (!updatedEntry) {
322
+ throw new Error("Failed to retrieve updated entry");
323
+ }
324
+ return updatedEntry;
325
+ },
326
+ });
327
+ /**
328
+ * Mutation to force-release a lock (admin operation).
329
+ *
330
+ * Allows administrators to remove locks from entries locked by other users.
331
+ * This should be used sparingly - only when a user has abandoned an editing
332
+ * session without releasing their lock, and the auto-expiry hasn't occurred yet.
333
+ *
334
+ * @param id - The content entry ID to force unlock
335
+ * @param releasedBy - User ID performing the force release (for audit trail)
336
+ * @returns The unlocked content entry
337
+ *
338
+ * @throws Error if entry not found
339
+ * @throws Error if entry is not locked
340
+ *
341
+ * @example
342
+ * ```typescript
343
+ * // Admin forcing release of abandoned lock
344
+ * const entry = await ctx.runMutation(api.contentLock.forceReleaseLock, {
345
+ * id: entryId,
346
+ * releasedBy: adminUserId,
347
+ * });
348
+ * console.log("Lock forcibly released");
349
+ * ```
350
+ */
351
+ export const forceReleaseLock = mutation({
352
+ args: forceReleaseLockArgs.fields,
353
+ returns: contentEntryDoc,
354
+ handler: async (ctx, args) => {
355
+ const { id, releasedBy } = args;
356
+ const entry = await ctx.db.get(id);
357
+ if (!entry) {
358
+ throw new Error(`Content entry not found: ${id}`);
359
+ }
360
+ // Check if entry is actually locked
361
+ if (entry.lockedBy === undefined) {
362
+ throw new Error(`Content entry is not locked: ${id}`);
363
+ }
364
+ // Force release the lock
365
+ await ctx.db.patch(id, {
366
+ lockedBy: undefined,
367
+ lockExpiresAt: undefined,
368
+ // Track who force-released in updatedBy for audit purposes
369
+ updatedBy: releasedBy,
370
+ });
371
+ const updatedEntry = await ctx.db.get(id);
372
+ if (!updatedEntry) {
373
+ throw new Error("Failed to retrieve updated entry");
374
+ }
375
+ return updatedEntry;
376
+ },
377
+ });
378
+ /**
379
+ * Mutation to renew an existing lock.
380
+ *
381
+ * Extends the lock expiration time for continued editing sessions.
382
+ * Only the lock owner can renew their lock.
383
+ *
384
+ * This is typically called periodically by the client to keep the lock
385
+ * active during long editing sessions.
386
+ *
387
+ * @param id - The content entry ID whose lock to renew
388
+ * @param userId - User ID renewing the lock (must match lock owner)
389
+ * @param lockDuration - Optional new lock duration (default 30 min, max 4 hours)
390
+ * @returns The entry with renewed lock
391
+ *
392
+ * @throws Error if entry not found
393
+ * @throws Error if entry not locked by this user
394
+ *
395
+ * @example
396
+ * ```typescript
397
+ * // Renew lock every 15 minutes during editing
398
+ * setInterval(async () => {
399
+ * await ctx.runMutation(api.contentLock.renewLock, {
400
+ * id: entryId,
401
+ * userId: currentUserId,
402
+ * });
403
+ * }, 15 * 60 * 1000);
404
+ * ```
405
+ */
406
+ export const renewLock = mutation({
407
+ args: renewLockArgs.fields,
408
+ returns: contentEntryDoc,
409
+ handler: async (ctx, args) => {
410
+ const { id, userId, lockDuration } = args;
411
+ const entry = await ctx.db.get(id);
412
+ if (!entry) {
413
+ throw new Error(`Content entry not found: ${id}`);
414
+ }
415
+ // Verify the user owns the lock
416
+ if (entry.lockedBy !== userId) {
417
+ if (entry.lockedBy === undefined) {
418
+ throw new Error(`Content entry is not locked: ${id}`);
419
+ }
420
+ throw new Error(`Cannot renew lock: entry is locked by another user`);
421
+ }
422
+ // Check if lock has already expired
423
+ if (!isLockActive(entry.lockExpiresAt)) {
424
+ throw new Error(`Lock has expired and cannot be renewed. Please acquire a new lock.`);
425
+ }
426
+ // Calculate new lock expiration
427
+ const validDuration = validateLockDuration(lockDuration);
428
+ const now = Date.now();
429
+ const newLockExpiresAt = now + validDuration;
430
+ // Renew the lock
431
+ await ctx.db.patch(id, {
432
+ lockExpiresAt: newLockExpiresAt,
433
+ });
434
+ const updatedEntry = await ctx.db.get(id);
435
+ if (!updatedEntry) {
436
+ throw new Error("Failed to retrieve updated entry");
437
+ }
438
+ return updatedEntry;
439
+ },
440
+ });
441
+ // =============================================================================
442
+ // Internal Helper for Update Validation
443
+ // =============================================================================
444
+ /**
445
+ * Validates that a user can update a locked entry.
446
+ * This is exported for use by contentEntryMutations.
447
+ *
448
+ * @param entry - The content entry to check
449
+ * @param userId - The user attempting the update
450
+ * @returns Object with isAllowed boolean and optional error message
451
+ */
452
+ export function validateLockForUpdate(entry, userId) {
453
+ // If no lock, update is allowed
454
+ if (entry.lockedBy === undefined || entry.lockExpiresAt === undefined) {
455
+ return { isAllowed: true };
456
+ }
457
+ // If lock has expired, update is allowed
458
+ if (!isLockActive(entry.lockExpiresAt)) {
459
+ return { isAllowed: true };
460
+ }
461
+ // If same user holds the lock, update is allowed
462
+ if (userId && entry.lockedBy === userId) {
463
+ return { isAllowed: true };
464
+ }
465
+ // Another user holds an active lock
466
+ return {
467
+ isAllowed: false,
468
+ error: `Cannot update: entry is locked by user ${entry.lockedBy}. Lock expires at ${new Date(entry.lockExpiresAt).toISOString()}`,
469
+ };
470
+ }
471
+ //# sourceMappingURL=contentLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentLock.js","sourceRoot":"","sources":["../../src/component/contentLock.ts"],"names":[],"mappings":"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"}