@rakun-kit/core 1.4.10 → 1.5.0

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 (652) hide show
  1. package/README.md +1100 -732
  2. package/dist/cjs/api/context.js +1 -0
  3. package/dist/cjs/api/context.js.map +1 -1
  4. package/dist/cjs/api/operations/apiEventLog.js +128 -0
  5. package/dist/cjs/api/operations/apiEventLog.js.map +1 -0
  6. package/dist/cjs/api/operations/index.js +4 -1
  7. package/dist/cjs/api/operations/index.js.map +1 -1
  8. package/dist/cjs/api/operations/manager-contract.js +256 -2
  9. package/dist/cjs/api/operations/manager-contract.js.map +1 -1
  10. package/dist/cjs/api/operations/manager-manifest.js +160 -0
  11. package/dist/cjs/api/operations/manager-manifest.js.map +1 -1
  12. package/dist/cjs/api/operations/manager.js +128 -4
  13. package/dist/cjs/api/operations/manager.js.map +1 -1
  14. package/dist/cjs/api/operations/tracing.js +36 -5
  15. package/dist/cjs/api/operations/tracing.js.map +1 -1
  16. package/dist/cjs/api/routes/manager/auth/externalLogin.js +126 -0
  17. package/dist/cjs/api/routes/manager/auth/externalLogin.js.map +1 -0
  18. package/dist/cjs/api/routes/manager/auth/login.js +51 -54
  19. package/dist/cjs/api/routes/manager/auth/login.js.map +1 -1
  20. package/dist/cjs/api/routes/manager/auth/mfa/regenerateRecoveryCodes.js +46 -0
  21. package/dist/cjs/api/routes/manager/auth/mfa/regenerateRecoveryCodes.js.map +1 -0
  22. package/dist/cjs/api/routes/manager/auth/mfa/verifyRecoveryCode.js +80 -0
  23. package/dist/cjs/api/routes/manager/auth/mfa/verifyRecoveryCode.js.map +1 -0
  24. package/dist/cjs/api/routes/manager/auth/passwordIpBlocks.js +90 -0
  25. package/dist/cjs/api/routes/manager/auth/passwordIpBlocks.js.map +1 -0
  26. package/dist/cjs/api/routes/manager/auth/passwordRecovery.js +147 -0
  27. package/dist/cjs/api/routes/manager/auth/passwordRecovery.js.map +1 -0
  28. package/dist/cjs/api/routes/manager/auth/totp/confirmTotp.js +19 -2
  29. package/dist/cjs/api/routes/manager/auth/totp/confirmTotp.js.map +1 -1
  30. package/dist/cjs/api/routes/manager/auth/totp/enrollTotp.js +2 -2
  31. package/dist/cjs/api/routes/manager/auth/totp/enrollTotp.js.map +1 -1
  32. package/dist/cjs/api/routes/manager/auth/webauthn/webauthnRegisterVerify.js +32 -3
  33. package/dist/cjs/api/routes/manager/auth/webauthn/webauthnRegisterVerify.js.map +1 -1
  34. package/dist/cjs/api/routes/manager/comments.js +120 -8
  35. package/dist/cjs/api/routes/manager/comments.js.map +1 -1
  36. package/dist/cjs/api/routes/manager/contentVersions.js +224 -0
  37. package/dist/cjs/api/routes/manager/contentVersions.js.map +1 -0
  38. package/dist/cjs/api/routes/manager/delete.js +69 -5
  39. package/dist/cjs/api/routes/manager/delete.js.map +1 -1
  40. package/dist/cjs/api/routes/manager/list.js +91 -2
  41. package/dist/cjs/api/routes/manager/list.js.map +1 -1
  42. package/dist/cjs/api/routes/manager/localeVariants.js +234 -18
  43. package/dist/cjs/api/routes/manager/localeVariants.js.map +1 -1
  44. package/dist/cjs/api/routes/manager/logs/cleanup.js +20 -0
  45. package/dist/cjs/api/routes/manager/logs/cleanup.js.map +1 -0
  46. package/dist/cjs/api/routes/manager/logs/list.js +22 -0
  47. package/dist/cjs/api/routes/manager/logs/list.js.map +1 -0
  48. package/dist/cjs/api/routes/manager/notifications.js +140 -0
  49. package/dist/cjs/api/routes/manager/notifications.js.map +1 -0
  50. package/dist/cjs/api/routes/manager/previewSlugRedirects.js +25 -0
  51. package/dist/cjs/api/routes/manager/previewSlugRedirects.js.map +1 -0
  52. package/dist/cjs/api/routes/manager/reviewPolicies.js +109 -0
  53. package/dist/cjs/api/routes/manager/reviewPolicies.js.map +1 -0
  54. package/dist/cjs/api/routes/manager/reviews.js +272 -0
  55. package/dist/cjs/api/routes/manager/reviews.js.map +1 -0
  56. package/dist/cjs/api/routes/manager/routeLayout.js +138 -0
  57. package/dist/cjs/api/routes/manager/routeLayout.js.map +1 -0
  58. package/dist/cjs/api/routes/manager/translateDocument.js +15 -0
  59. package/dist/cjs/api/routes/manager/translateDocument.js.map +1 -1
  60. package/dist/cjs/api/routes/manager/trash.js +72 -39
  61. package/dist/cjs/api/routes/manager/trash.js.map +1 -1
  62. package/dist/cjs/api/routes/manager/uiLocales.js +30 -0
  63. package/dist/cjs/api/routes/manager/uiLocales.js.map +1 -0
  64. package/dist/cjs/api/routes/manager/update.js +87 -0
  65. package/dist/cjs/api/routes/manager/update.js.map +1 -1
  66. package/dist/cjs/api/routes/manager/versions/restore.js +20 -0
  67. package/dist/cjs/api/routes/manager/versions/restore.js.map +1 -1
  68. package/dist/cjs/api/utils/authEvents.js +31 -0
  69. package/dist/cjs/api/utils/authEvents.js.map +1 -0
  70. package/dist/cjs/api/utils/authRateLimit.js +4 -3
  71. package/dist/cjs/api/utils/authRateLimit.js.map +1 -1
  72. package/dist/cjs/api/utils/managerNotifications.js +27 -0
  73. package/dist/cjs/api/utils/managerNotifications.js.map +1 -0
  74. package/dist/cjs/api/utils/recoveryCodes.js +29 -0
  75. package/dist/cjs/api/utils/recoveryCodes.js.map +1 -0
  76. package/dist/cjs/api/utils/redirects/createSlugChangeRedirects.js +145 -0
  77. package/dist/cjs/api/utils/redirects/createSlugChangeRedirects.js.map +1 -0
  78. package/dist/cjs/api/utils/redirects/slugPathChanges.js +137 -0
  79. package/dist/cjs/api/utils/redirects/slugPathChanges.js.map +1 -0
  80. package/dist/cjs/api/utils/requireContentType.js +13 -0
  81. package/dist/cjs/api/utils/requireContentType.js.map +1 -1
  82. package/dist/cjs/api/utils/reviews.js +273 -0
  83. package/dist/cjs/api/utils/reviews.js.map +1 -0
  84. package/dist/cjs/api/utils/routes/routeMapHelpers.js +46 -22
  85. package/dist/cjs/api/utils/routes/routeMapHelpers.js.map +1 -1
  86. package/dist/cjs/api/utils/routes/updateRoutesMap.js +2 -1
  87. package/dist/cjs/api/utils/routes/updateRoutesMap.js.map +1 -1
  88. package/dist/cjs/api/utils/safeManagerQuery.js +1 -0
  89. package/dist/cjs/api/utils/safeManagerQuery.js.map +1 -1
  90. package/dist/cjs/auth/accountRecovery.js +5 -0
  91. package/dist/cjs/auth/accountRecovery.js.map +1 -0
  92. package/dist/cjs/auth/completePrimaryAuthentication.js +50 -0
  93. package/dist/cjs/auth/completePrimaryAuthentication.js.map +1 -0
  94. package/dist/cjs/auth/loginAdapters.js +183 -0
  95. package/dist/cjs/auth/loginAdapters.js.map +1 -0
  96. package/dist/cjs/auth/passwordFail2ban.js +119 -0
  97. package/dist/cjs/auth/passwordFail2ban.js.map +1 -0
  98. package/dist/cjs/auth/passwordResetMailTemplate.js +90 -0
  99. package/dist/cjs/auth/passwordResetMailTemplate.js.map +1 -0
  100. package/dist/cjs/bootstrapState.js.map +1 -1
  101. package/dist/cjs/client.js +5 -1
  102. package/dist/cjs/client.js.map +1 -1
  103. package/dist/cjs/contracts.js +12 -0
  104. package/dist/cjs/contracts.js.map +1 -1
  105. package/dist/cjs/eventLog/index.js +52 -0
  106. package/dist/cjs/eventLog/index.js.map +1 -0
  107. package/dist/cjs/eventLog/mongo.js +115 -0
  108. package/dist/cjs/eventLog/mongo.js.map +1 -0
  109. package/dist/cjs/eventLog/service.js +189 -0
  110. package/dist/cjs/eventLog/service.js.map +1 -0
  111. package/dist/cjs/eventLog/types.js +6 -0
  112. package/dist/cjs/eventLog/types.js.map +1 -0
  113. package/dist/cjs/index.js +62 -3
  114. package/dist/cjs/index.js.map +1 -1
  115. package/dist/cjs/internal-content-types/ContentCommentReadState.js +21 -0
  116. package/dist/cjs/internal-content-types/ContentCommentReadState.js.map +1 -0
  117. package/dist/cjs/internal-content-types/ContentReview.js +34 -0
  118. package/dist/cjs/internal-content-types/ContentReview.js.map +1 -0
  119. package/dist/cjs/internal-content-types/ContentReviewDecision.js +21 -0
  120. package/dist/cjs/internal-content-types/ContentReviewDecision.js.map +1 -0
  121. package/dist/cjs/internal-content-types/ContentReviewPolicy.js +21 -0
  122. package/dist/cjs/internal-content-types/ContentReviewPolicy.js.map +1 -0
  123. package/dist/cjs/internal-content-types/LoginIpBlock.js +20 -0
  124. package/dist/cjs/internal-content-types/LoginIpBlock.js.map +1 -0
  125. package/dist/cjs/internal-content-types/ManagerNotification.js +33 -0
  126. package/dist/cjs/internal-content-types/ManagerNotification.js.map +1 -0
  127. package/dist/cjs/internal-content-types/ManagerUserHooks.js +8 -1
  128. package/dist/cjs/internal-content-types/ManagerUserHooks.js.map +1 -1
  129. package/dist/cjs/internal-content-types/PasswordResetToken.js +50 -0
  130. package/dist/cjs/internal-content-types/PasswordResetToken.js.map +1 -0
  131. package/dist/cjs/internal-content-types/UserMfa.js +35 -1
  132. package/dist/cjs/internal-content-types/UserMfa.js.map +1 -1
  133. package/dist/cjs/internal-content-types/index.js +7 -0
  134. package/dist/cjs/internal-content-types/index.js.map +1 -1
  135. package/dist/cjs/lib/ContentType.js +2 -8
  136. package/dist/cjs/lib/ContentType.js.map +1 -1
  137. package/dist/cjs/lib/Permissions.js +13 -1
  138. package/dist/cjs/lib/Permissions.js.map +1 -1
  139. package/dist/cjs/lib/Registry.js +8 -3
  140. package/dist/cjs/lib/Registry.js.map +1 -1
  141. package/dist/cjs/lib/errors/AppError.js +7 -1
  142. package/dist/cjs/lib/errors/AppError.js.map +1 -1
  143. package/dist/cjs/lib/fields/Fields.js +2 -1
  144. package/dist/cjs/lib/fields/Fields.js.map +1 -1
  145. package/dist/cjs/lib/fields/Link.js +2 -1
  146. package/dist/cjs/lib/fields/Link.js.map +1 -1
  147. package/dist/cjs/lib/localeVariants.js +9 -1
  148. package/dist/cjs/lib/localeVariants.js.map +1 -1
  149. package/dist/cjs/literals/index.js +0 -1
  150. package/dist/cjs/literals/index.js.map +1 -1
  151. package/dist/cjs/mail/adapters.js +3 -0
  152. package/dist/cjs/mail/adapters.js.map +1 -0
  153. package/dist/cjs/mail/index.js +53 -0
  154. package/dist/cjs/mail/index.js.map +1 -0
  155. package/dist/cjs/mail/mailService.js +209 -0
  156. package/dist/cjs/mail/mailService.js.map +1 -0
  157. package/dist/cjs/mail/templates.js +32 -0
  158. package/dist/cjs/mail/templates.js.map +1 -0
  159. package/dist/cjs/orm/createIndexes.js +37 -0
  160. package/dist/cjs/orm/createIndexes.js.map +1 -1
  161. package/dist/cjs/orm/dbService.js +3 -3
  162. package/dist/cjs/orm/dbService.js.map +1 -1
  163. package/dist/cjs/orm/operations/update.js +28 -26
  164. package/dist/cjs/orm/operations/update.js.map +1 -1
  165. package/dist/cjs/plugins.js.map +1 -1
  166. package/dist/cjs/schemas/manager/auth/externalLogin.js +27 -0
  167. package/dist/cjs/schemas/manager/auth/externalLogin.js.map +1 -0
  168. package/dist/cjs/schemas/manager/auth/mfa/recoveryCode.js +27 -0
  169. package/dist/cjs/schemas/manager/auth/mfa/recoveryCode.js.map +1 -0
  170. package/dist/cjs/schemas/manager/auth/passwordIpBlocks.js +32 -0
  171. package/dist/cjs/schemas/manager/auth/passwordIpBlocks.js.map +1 -0
  172. package/dist/cjs/schemas/manager/auth/passwordRecovery.js +21 -0
  173. package/dist/cjs/schemas/manager/auth/passwordRecovery.js.map +1 -0
  174. package/dist/cjs/schemas/manager/auth/totp/confirmTotp.js +4 -7
  175. package/dist/cjs/schemas/manager/auth/totp/confirmTotp.js.map +1 -1
  176. package/dist/cjs/schemas/manager/comments.js +11 -1
  177. package/dist/cjs/schemas/manager/comments.js.map +1 -1
  178. package/dist/cjs/schemas/manager/contentVersions.js +51 -0
  179. package/dist/cjs/schemas/manager/contentVersions.js.map +1 -0
  180. package/dist/cjs/schemas/manager/eventLogs.js +54 -0
  181. package/dist/cjs/schemas/manager/eventLogs.js.map +1 -0
  182. package/dist/cjs/schemas/manager/list.js +1 -0
  183. package/dist/cjs/schemas/manager/list.js.map +1 -1
  184. package/dist/cjs/schemas/manager/localeVariants.js +10 -1
  185. package/dist/cjs/schemas/manager/localeVariants.js.map +1 -1
  186. package/dist/cjs/schemas/manager/notifications.js +51 -0
  187. package/dist/cjs/schemas/manager/notifications.js.map +1 -0
  188. package/dist/cjs/schemas/manager/reviewPolicies.js +33 -0
  189. package/dist/cjs/schemas/manager/reviewPolicies.js.map +1 -0
  190. package/dist/cjs/schemas/manager/reviews.js +93 -0
  191. package/dist/cjs/schemas/manager/reviews.js.map +1 -0
  192. package/dist/cjs/schemas/manager/routeLayout.js +50 -0
  193. package/dist/cjs/schemas/manager/routeLayout.js.map +1 -0
  194. package/dist/cjs/schemas/manager/slugRedirects.js +24 -0
  195. package/dist/cjs/schemas/manager/slugRedirects.js.map +1 -0
  196. package/dist/cjs/schemas/manager/uiLocales.js +29 -0
  197. package/dist/cjs/schemas/manager/uiLocales.js.map +1 -0
  198. package/dist/cjs/schemas/manager/update.js +1 -0
  199. package/dist/cjs/schemas/manager/update.js.map +1 -1
  200. package/dist/docs/index.md +238 -0
  201. package/dist/esm/api/context.d.ts +2 -0
  202. package/dist/esm/api/context.d.ts.map +1 -1
  203. package/dist/esm/api/context.js +1 -0
  204. package/dist/esm/api/context.js.map +1 -1
  205. package/dist/esm/api/operations/apiEventLog.d.ts +25 -0
  206. package/dist/esm/api/operations/apiEventLog.d.ts.map +1 -0
  207. package/dist/esm/api/operations/apiEventLog.js +121 -0
  208. package/dist/esm/api/operations/apiEventLog.js.map +1 -0
  209. package/dist/esm/api/operations/index.d.ts +737 -4
  210. package/dist/esm/api/operations/index.d.ts.map +1 -1
  211. package/dist/esm/api/operations/index.js +1 -0
  212. package/dist/esm/api/operations/index.js.map +1 -1
  213. package/dist/esm/api/operations/manager-contract.d.ts +731 -4
  214. package/dist/esm/api/operations/manager-contract.d.ts.map +1 -1
  215. package/dist/esm/api/operations/manager-contract.js +257 -3
  216. package/dist/esm/api/operations/manager-contract.js.map +1 -1
  217. package/dist/esm/api/operations/manager-manifest.d.ts +160 -0
  218. package/dist/esm/api/operations/manager-manifest.d.ts.map +1 -1
  219. package/dist/esm/api/operations/manager-manifest.js +160 -0
  220. package/dist/esm/api/operations/manager-manifest.js.map +1 -1
  221. package/dist/esm/api/operations/manager.d.ts +731 -4
  222. package/dist/esm/api/operations/manager.d.ts.map +1 -1
  223. package/dist/esm/api/operations/manager.js +126 -2
  224. package/dist/esm/api/operations/manager.js.map +1 -1
  225. package/dist/esm/api/operations/tracing.d.ts.map +1 -1
  226. package/dist/esm/api/operations/tracing.js +36 -5
  227. package/dist/esm/api/operations/tracing.js.map +1 -1
  228. package/dist/esm/api/operations/web-contract.d.ts +5 -0
  229. package/dist/esm/api/operations/web-contract.d.ts.map +1 -1
  230. package/dist/esm/api/operations/web.d.ts +5 -0
  231. package/dist/esm/api/operations/web.d.ts.map +1 -1
  232. package/dist/esm/api/routes/manager/auth/externalLogin.d.ts +11 -0
  233. package/dist/esm/api/routes/manager/auth/externalLogin.d.ts.map +1 -0
  234. package/dist/esm/api/routes/manager/auth/externalLogin.js +121 -0
  235. package/dist/esm/api/routes/manager/auth/externalLogin.js.map +1 -0
  236. package/dist/esm/api/routes/manager/auth/getSession.d.ts +2 -0
  237. package/dist/esm/api/routes/manager/auth/getSession.d.ts.map +1 -1
  238. package/dist/esm/api/routes/manager/auth/login.d.ts.map +1 -1
  239. package/dist/esm/api/routes/manager/auth/login.js +52 -55
  240. package/dist/esm/api/routes/manager/auth/login.js.map +1 -1
  241. package/dist/esm/api/routes/manager/auth/markTourSeen.d.ts +2 -0
  242. package/dist/esm/api/routes/manager/auth/markTourSeen.d.ts.map +1 -1
  243. package/dist/esm/api/routes/manager/auth/mfa/regenerateRecoveryCodes.d.ts +10 -0
  244. package/dist/esm/api/routes/manager/auth/mfa/regenerateRecoveryCodes.d.ts.map +1 -0
  245. package/dist/esm/api/routes/manager/auth/mfa/regenerateRecoveryCodes.js +42 -0
  246. package/dist/esm/api/routes/manager/auth/mfa/regenerateRecoveryCodes.js.map +1 -0
  247. package/dist/esm/api/routes/manager/auth/mfa/verifyRecoveryCode.d.ts +15 -0
  248. package/dist/esm/api/routes/manager/auth/mfa/verifyRecoveryCode.d.ts.map +1 -0
  249. package/dist/esm/api/routes/manager/auth/mfa/verifyRecoveryCode.js +76 -0
  250. package/dist/esm/api/routes/manager/auth/mfa/verifyRecoveryCode.js.map +1 -0
  251. package/dist/esm/api/routes/manager/auth/passwordIpBlocks.d.ts +10 -0
  252. package/dist/esm/api/routes/manager/auth/passwordIpBlocks.d.ts.map +1 -0
  253. package/dist/esm/api/routes/manager/auth/passwordIpBlocks.js +85 -0
  254. package/dist/esm/api/routes/manager/auth/passwordIpBlocks.js.map +1 -0
  255. package/dist/esm/api/routes/manager/auth/passwordRecovery.d.ts +15 -0
  256. package/dist/esm/api/routes/manager/auth/passwordRecovery.d.ts.map +1 -0
  257. package/dist/esm/api/routes/manager/auth/passwordRecovery.js +142 -0
  258. package/dist/esm/api/routes/manager/auth/passwordRecovery.js.map +1 -0
  259. package/dist/esm/api/routes/manager/auth/totp/confirmTotp.d.ts +2 -1
  260. package/dist/esm/api/routes/manager/auth/totp/confirmTotp.d.ts.map +1 -1
  261. package/dist/esm/api/routes/manager/auth/totp/confirmTotp.js +19 -2
  262. package/dist/esm/api/routes/manager/auth/totp/confirmTotp.js.map +1 -1
  263. package/dist/esm/api/routes/manager/auth/totp/enrollTotp.js +2 -2
  264. package/dist/esm/api/routes/manager/auth/totp/enrollTotp.js.map +1 -1
  265. package/dist/esm/api/routes/manager/auth/updateAccount.d.ts +2 -0
  266. package/dist/esm/api/routes/manager/auth/updateAccount.d.ts.map +1 -1
  267. package/dist/esm/api/routes/manager/auth/updateTutorialPreferences.d.ts +2 -0
  268. package/dist/esm/api/routes/manager/auth/updateTutorialPreferences.d.ts.map +1 -1
  269. package/dist/esm/api/routes/manager/auth/webauthn/webauthnRegisterVerify.d.ts +2 -1
  270. package/dist/esm/api/routes/manager/auth/webauthn/webauthnRegisterVerify.d.ts.map +1 -1
  271. package/dist/esm/api/routes/manager/auth/webauthn/webauthnRegisterVerify.js +32 -3
  272. package/dist/esm/api/routes/manager/auth/webauthn/webauthnRegisterVerify.js.map +1 -1
  273. package/dist/esm/api/routes/manager/comments.d.ts +9 -1
  274. package/dist/esm/api/routes/manager/comments.d.ts.map +1 -1
  275. package/dist/esm/api/routes/manager/comments.js +118 -8
  276. package/dist/esm/api/routes/manager/comments.js.map +1 -1
  277. package/dist/esm/api/routes/manager/contentType.d.ts +1 -1
  278. package/dist/esm/api/routes/manager/contentTypes.d.ts +1 -1
  279. package/dist/esm/api/routes/manager/contentVersions.d.ts +15 -0
  280. package/dist/esm/api/routes/manager/contentVersions.d.ts.map +1 -0
  281. package/dist/esm/api/routes/manager/contentVersions.js +218 -0
  282. package/dist/esm/api/routes/manager/contentVersions.js.map +1 -0
  283. package/dist/esm/api/routes/manager/create.d.ts +1 -0
  284. package/dist/esm/api/routes/manager/create.d.ts.map +1 -1
  285. package/dist/esm/api/routes/manager/delete.d.ts.map +1 -1
  286. package/dist/esm/api/routes/manager/delete.js +70 -6
  287. package/dist/esm/api/routes/manager/delete.js.map +1 -1
  288. package/dist/esm/api/routes/manager/duplicate.d.ts +1 -0
  289. package/dist/esm/api/routes/manager/duplicate.d.ts.map +1 -1
  290. package/dist/esm/api/routes/manager/languages.d.ts +1 -0
  291. package/dist/esm/api/routes/manager/languages.d.ts.map +1 -1
  292. package/dist/esm/api/routes/manager/list.d.ts +3 -0
  293. package/dist/esm/api/routes/manager/list.d.ts.map +1 -1
  294. package/dist/esm/api/routes/manager/list.js +93 -4
  295. package/dist/esm/api/routes/manager/list.js.map +1 -1
  296. package/dist/esm/api/routes/manager/localeVariants.d.ts +215 -1
  297. package/dist/esm/api/routes/manager/localeVariants.d.ts.map +1 -1
  298. package/dist/esm/api/routes/manager/localeVariants.js +218 -11
  299. package/dist/esm/api/routes/manager/localeVariants.js.map +1 -1
  300. package/dist/esm/api/routes/manager/logs/cleanup.d.ts +7 -0
  301. package/dist/esm/api/routes/manager/logs/cleanup.d.ts.map +1 -0
  302. package/dist/esm/api/routes/manager/logs/cleanup.js +16 -0
  303. package/dist/esm/api/routes/manager/logs/cleanup.js.map +1 -0
  304. package/dist/esm/api/routes/manager/logs/list.d.ts +7 -0
  305. package/dist/esm/api/routes/manager/logs/list.d.ts.map +1 -0
  306. package/dist/esm/api/routes/manager/logs/list.js +18 -0
  307. package/dist/esm/api/routes/manager/logs/list.js.map +1 -0
  308. package/dist/esm/api/routes/manager/notifications.d.ts +11 -0
  309. package/dist/esm/api/routes/manager/notifications.d.ts.map +1 -0
  310. package/dist/esm/api/routes/manager/notifications.js +135 -0
  311. package/dist/esm/api/routes/manager/notifications.js.map +1 -0
  312. package/dist/esm/api/routes/manager/previewSlugRedirects.d.ts +7 -0
  313. package/dist/esm/api/routes/manager/previewSlugRedirects.d.ts.map +1 -0
  314. package/dist/esm/api/routes/manager/previewSlugRedirects.js +21 -0
  315. package/dist/esm/api/routes/manager/previewSlugRedirects.js.map +1 -0
  316. package/dist/esm/api/routes/manager/reviewPolicies.d.ts +14 -0
  317. package/dist/esm/api/routes/manager/reviewPolicies.d.ts.map +1 -0
  318. package/dist/esm/api/routes/manager/reviewPolicies.js +103 -0
  319. package/dist/esm/api/routes/manager/reviewPolicies.js.map +1 -0
  320. package/dist/esm/api/routes/manager/reviews.d.ts +23 -0
  321. package/dist/esm/api/routes/manager/reviews.d.ts.map +1 -0
  322. package/dist/esm/api/routes/manager/reviews.js +264 -0
  323. package/dist/esm/api/routes/manager/reviews.js.map +1 -0
  324. package/dist/esm/api/routes/manager/routeLayout.d.ts +11 -0
  325. package/dist/esm/api/routes/manager/routeLayout.d.ts.map +1 -0
  326. package/dist/esm/api/routes/manager/routeLayout.js +133 -0
  327. package/dist/esm/api/routes/manager/routeLayout.js.map +1 -0
  328. package/dist/esm/api/routes/manager/translateDocument.d.ts.map +1 -1
  329. package/dist/esm/api/routes/manager/translateDocument.js +15 -0
  330. package/dist/esm/api/routes/manager/translateDocument.js.map +1 -1
  331. package/dist/esm/api/routes/manager/trash.d.ts +19 -0
  332. package/dist/esm/api/routes/manager/trash.d.ts.map +1 -1
  333. package/dist/esm/api/routes/manager/trash.js +70 -38
  334. package/dist/esm/api/routes/manager/trash.js.map +1 -1
  335. package/dist/esm/api/routes/manager/uiLocales.d.ts +17 -0
  336. package/dist/esm/api/routes/manager/uiLocales.d.ts.map +1 -0
  337. package/dist/esm/api/routes/manager/uiLocales.js +25 -0
  338. package/dist/esm/api/routes/manager/uiLocales.js.map +1 -0
  339. package/dist/esm/api/routes/manager/update.d.ts +1 -0
  340. package/dist/esm/api/routes/manager/update.d.ts.map +1 -1
  341. package/dist/esm/api/routes/manager/update.js +87 -0
  342. package/dist/esm/api/routes/manager/update.js.map +1 -1
  343. package/dist/esm/api/routes/manager/versions/restore.d.ts.map +1 -1
  344. package/dist/esm/api/routes/manager/versions/restore.js +20 -0
  345. package/dist/esm/api/routes/manager/versions/restore.js.map +1 -1
  346. package/dist/esm/api/routes/web/previewPage.d.ts +2 -0
  347. package/dist/esm/api/routes/web/previewPage.d.ts.map +1 -1
  348. package/dist/esm/api/utils/authEvents.d.ts +7 -0
  349. package/dist/esm/api/utils/authEvents.d.ts.map +1 -0
  350. package/dist/esm/api/utils/authEvents.js +27 -0
  351. package/dist/esm/api/utils/authEvents.js.map +1 -0
  352. package/dist/esm/api/utils/authRateLimit.d.ts.map +1 -1
  353. package/dist/esm/api/utils/authRateLimit.js +4 -3
  354. package/dist/esm/api/utils/authRateLimit.js.map +1 -1
  355. package/dist/esm/api/utils/getUser.d.ts +2 -0
  356. package/dist/esm/api/utils/getUser.d.ts.map +1 -1
  357. package/dist/esm/api/utils/managerNotifications.d.ts +39 -0
  358. package/dist/esm/api/utils/managerNotifications.d.ts.map +1 -0
  359. package/dist/esm/api/utils/managerNotifications.js +23 -0
  360. package/dist/esm/api/utils/managerNotifications.js.map +1 -0
  361. package/dist/esm/api/utils/recoveryCodes.d.ts +9 -0
  362. package/dist/esm/api/utils/recoveryCodes.d.ts.map +1 -0
  363. package/dist/esm/api/utils/recoveryCodes.js +22 -0
  364. package/dist/esm/api/utils/recoveryCodes.js.map +1 -0
  365. package/dist/esm/api/utils/redirects/createSlugChangeRedirects.d.ts +14 -0
  366. package/dist/esm/api/utils/redirects/createSlugChangeRedirects.d.ts.map +1 -0
  367. package/dist/esm/api/utils/redirects/createSlugChangeRedirects.js +141 -0
  368. package/dist/esm/api/utils/redirects/createSlugChangeRedirects.js.map +1 -0
  369. package/dist/esm/api/utils/redirects/slugPathChanges.d.ts +9 -0
  370. package/dist/esm/api/utils/redirects/slugPathChanges.d.ts.map +1 -0
  371. package/dist/esm/api/utils/redirects/slugPathChanges.js +133 -0
  372. package/dist/esm/api/utils/redirects/slugPathChanges.js.map +1 -0
  373. package/dist/esm/api/utils/requireContentType.d.ts.map +1 -1
  374. package/dist/esm/api/utils/requireContentType.js +13 -0
  375. package/dist/esm/api/utils/requireContentType.js.map +1 -1
  376. package/dist/esm/api/utils/reviews.d.ts +145 -0
  377. package/dist/esm/api/utils/reviews.d.ts.map +1 -0
  378. package/dist/esm/api/utils/reviews.js +253 -0
  379. package/dist/esm/api/utils/reviews.js.map +1 -0
  380. package/dist/esm/api/utils/routes/routeMapHelpers.d.ts +2 -0
  381. package/dist/esm/api/utils/routes/routeMapHelpers.d.ts.map +1 -1
  382. package/dist/esm/api/utils/routes/routeMapHelpers.js +45 -22
  383. package/dist/esm/api/utils/routes/routeMapHelpers.js.map +1 -1
  384. package/dist/esm/api/utils/routes/updateRoutesMap.d.ts +2 -1
  385. package/dist/esm/api/utils/routes/updateRoutesMap.d.ts.map +1 -1
  386. package/dist/esm/api/utils/routes/updateRoutesMap.js +2 -1
  387. package/dist/esm/api/utils/routes/updateRoutesMap.js.map +1 -1
  388. package/dist/esm/api/utils/safeManagerQuery.d.ts.map +1 -1
  389. package/dist/esm/api/utils/safeManagerQuery.js +1 -0
  390. package/dist/esm/api/utils/safeManagerQuery.js.map +1 -1
  391. package/dist/esm/auth/accountRecovery.d.ts +18 -0
  392. package/dist/esm/auth/accountRecovery.d.ts.map +1 -0
  393. package/dist/esm/auth/accountRecovery.js +2 -0
  394. package/dist/esm/auth/accountRecovery.js.map +1 -0
  395. package/dist/esm/auth/completePrimaryAuthentication.d.ts +3 -0
  396. package/dist/esm/auth/completePrimaryAuthentication.d.ts.map +1 -0
  397. package/dist/esm/auth/completePrimaryAuthentication.js +46 -0
  398. package/dist/esm/auth/completePrimaryAuthentication.js.map +1 -0
  399. package/dist/esm/auth/loginAdapters.d.ts +57 -0
  400. package/dist/esm/auth/loginAdapters.d.ts.map +1 -0
  401. package/dist/esm/auth/loginAdapters.js +176 -0
  402. package/dist/esm/auth/loginAdapters.js.map +1 -0
  403. package/dist/esm/auth/passwordFail2ban.d.ts +20 -0
  404. package/dist/esm/auth/passwordFail2ban.d.ts.map +1 -0
  405. package/dist/esm/auth/passwordFail2ban.js +110 -0
  406. package/dist/esm/auth/passwordFail2ban.js.map +1 -0
  407. package/dist/esm/auth/passwordResetMailTemplate.d.ts +3 -0
  408. package/dist/esm/auth/passwordResetMailTemplate.d.ts.map +1 -0
  409. package/dist/esm/auth/passwordResetMailTemplate.js +87 -0
  410. package/dist/esm/auth/passwordResetMailTemplate.js.map +1 -0
  411. package/dist/esm/bootstrapState.d.ts +24 -2
  412. package/dist/esm/bootstrapState.d.ts.map +1 -1
  413. package/dist/esm/bootstrapState.js.map +1 -1
  414. package/dist/esm/client.d.ts +12 -6
  415. package/dist/esm/client.d.ts.map +1 -1
  416. package/dist/esm/client.js +4 -4
  417. package/dist/esm/client.js.map +1 -1
  418. package/dist/esm/contracts.d.ts +12 -0
  419. package/dist/esm/contracts.d.ts.map +1 -1
  420. package/dist/esm/contracts.js +12 -0
  421. package/dist/esm/contracts.js.map +1 -1
  422. package/dist/esm/eventLog/index.d.ts +12 -0
  423. package/dist/esm/eventLog/index.d.ts.map +1 -0
  424. package/dist/esm/eventLog/index.js +28 -0
  425. package/dist/esm/eventLog/index.js.map +1 -0
  426. package/dist/esm/eventLog/mongo.d.ts +5 -0
  427. package/dist/esm/eventLog/mongo.d.ts.map +1 -0
  428. package/dist/esm/eventLog/mongo.js +111 -0
  429. package/dist/esm/eventLog/mongo.js.map +1 -0
  430. package/dist/esm/eventLog/service.d.ts +19 -0
  431. package/dist/esm/eventLog/service.d.ts.map +1 -0
  432. package/dist/esm/eventLog/service.js +180 -0
  433. package/dist/esm/eventLog/service.js.map +1 -0
  434. package/dist/esm/eventLog/types.d.ts +73 -0
  435. package/dist/esm/eventLog/types.d.ts.map +1 -0
  436. package/dist/esm/eventLog/types.js +3 -0
  437. package/dist/esm/eventLog/types.js.map +1 -0
  438. package/dist/esm/index.d.ts +9 -4
  439. package/dist/esm/index.d.ts.map +1 -1
  440. package/dist/esm/index.js +56 -7
  441. package/dist/esm/index.js.map +1 -1
  442. package/dist/esm/internal-content-types/Backup.d.ts.map +1 -1
  443. package/dist/esm/internal-content-types/ContentComment.d.ts +35 -0
  444. package/dist/esm/internal-content-types/ContentComment.d.ts.map +1 -1
  445. package/dist/esm/internal-content-types/ContentCommentReadState.d.ts +3499 -0
  446. package/dist/esm/internal-content-types/ContentCommentReadState.d.ts.map +1 -0
  447. package/dist/esm/internal-content-types/ContentCommentReadState.js +15 -0
  448. package/dist/esm/internal-content-types/ContentCommentReadState.js.map +1 -0
  449. package/dist/esm/internal-content-types/ContentReview.d.ts +10045 -0
  450. package/dist/esm/internal-content-types/ContentReview.d.ts.map +1 -0
  451. package/dist/esm/internal-content-types/ContentReview.js +28 -0
  452. package/dist/esm/internal-content-types/ContentReview.js.map +1 -0
  453. package/dist/esm/internal-content-types/ContentReviewDecision.d.ts +3181 -0
  454. package/dist/esm/internal-content-types/ContentReviewDecision.d.ts.map +1 -0
  455. package/dist/esm/internal-content-types/ContentReviewDecision.js +15 -0
  456. package/dist/esm/internal-content-types/ContentReviewDecision.js.map +1 -0
  457. package/dist/esm/internal-content-types/ContentReviewPolicy.d.ts +1211 -0
  458. package/dist/esm/internal-content-types/ContentReviewPolicy.d.ts.map +1 -0
  459. package/dist/esm/internal-content-types/ContentReviewPolicy.js +15 -0
  460. package/dist/esm/internal-content-types/ContentReviewPolicy.js.map +1 -0
  461. package/dist/esm/internal-content-types/ContentVersion.d.ts.map +1 -1
  462. package/dist/esm/internal-content-types/LinkedIteratorTemplate.d.ts.map +1 -1
  463. package/dist/esm/internal-content-types/LoginIpBlock.d.ts +434 -0
  464. package/dist/esm/internal-content-types/LoginIpBlock.d.ts.map +1 -0
  465. package/dist/esm/internal-content-types/LoginIpBlock.js +14 -0
  466. package/dist/esm/internal-content-types/LoginIpBlock.js.map +1 -0
  467. package/dist/esm/internal-content-types/ManagerFavorite.d.ts +28 -0
  468. package/dist/esm/internal-content-types/ManagerFavorite.d.ts.map +1 -1
  469. package/dist/esm/internal-content-types/ManagerNotification.d.ts +6614 -0
  470. package/dist/esm/internal-content-types/ManagerNotification.d.ts.map +1 -0
  471. package/dist/esm/internal-content-types/ManagerNotification.js +27 -0
  472. package/dist/esm/internal-content-types/ManagerNotification.js.map +1 -0
  473. package/dist/esm/internal-content-types/ManagerUser.d.ts +7 -0
  474. package/dist/esm/internal-content-types/ManagerUser.d.ts.map +1 -1
  475. package/dist/esm/internal-content-types/ManagerUserHooks.d.ts.map +1 -1
  476. package/dist/esm/internal-content-types/ManagerUserHooks.js +8 -1
  477. package/dist/esm/internal-content-types/ManagerUserHooks.js.map +1 -1
  478. package/dist/esm/internal-content-types/MfaChallenge.d.ts +28 -0
  479. package/dist/esm/internal-content-types/MfaChallenge.d.ts.map +1 -1
  480. package/dist/esm/internal-content-types/Migration.d.ts.map +1 -1
  481. package/dist/esm/internal-content-types/PasswordResetToken.d.ts +3181 -0
  482. package/dist/esm/internal-content-types/PasswordResetToken.d.ts.map +1 -0
  483. package/dist/esm/internal-content-types/PasswordResetToken.js +44 -0
  484. package/dist/esm/internal-content-types/PasswordResetToken.js.map +1 -0
  485. package/dist/esm/internal-content-types/RobotsRule.d.ts.map +1 -1
  486. package/dist/esm/internal-content-types/Route.d.ts.map +1 -1
  487. package/dist/esm/internal-content-types/RouteLayoutModule.d.ts.map +1 -1
  488. package/dist/esm/internal-content-types/SchemaState.d.ts.map +1 -1
  489. package/dist/esm/internal-content-types/Session.d.ts +28 -0
  490. package/dist/esm/internal-content-types/Session.d.ts.map +1 -1
  491. package/dist/esm/internal-content-types/UserMfa.d.ts +30 -0
  492. package/dist/esm/internal-content-types/UserMfa.d.ts.map +1 -1
  493. package/dist/esm/internal-content-types/UserMfa.js +35 -1
  494. package/dist/esm/internal-content-types/UserMfa.js.map +1 -1
  495. package/dist/esm/internal-content-types/WebAuthnCredential.d.ts +28 -0
  496. package/dist/esm/internal-content-types/WebAuthnCredential.d.ts.map +1 -1
  497. package/dist/esm/internal-content-types/WebAuthnRegChallenge.d.ts +28 -0
  498. package/dist/esm/internal-content-types/WebAuthnRegChallenge.d.ts.map +1 -1
  499. package/dist/esm/internal-content-types/index.d.ts +7 -0
  500. package/dist/esm/internal-content-types/index.d.ts.map +1 -1
  501. package/dist/esm/internal-content-types/index.js +7 -0
  502. package/dist/esm/internal-content-types/index.js.map +1 -1
  503. package/dist/esm/internal-content-types/syncAdminRole.d.ts +1 -0
  504. package/dist/esm/internal-content-types/syncAdminRole.d.ts.map +1 -1
  505. package/dist/esm/lib/ContentType.d.ts +7 -9
  506. package/dist/esm/lib/ContentType.d.ts.map +1 -1
  507. package/dist/esm/lib/ContentType.js +3 -9
  508. package/dist/esm/lib/ContentType.js.map +1 -1
  509. package/dist/esm/lib/Permissions.d.ts +3 -0
  510. package/dist/esm/lib/Permissions.d.ts.map +1 -1
  511. package/dist/esm/lib/Permissions.js +13 -1
  512. package/dist/esm/lib/Permissions.js.map +1 -1
  513. package/dist/esm/lib/Registry.d.ts +6 -3
  514. package/dist/esm/lib/Registry.d.ts.map +1 -1
  515. package/dist/esm/lib/Registry.js +7 -3
  516. package/dist/esm/lib/Registry.js.map +1 -1
  517. package/dist/esm/lib/errors/AppError.d.ts.map +1 -1
  518. package/dist/esm/lib/errors/AppError.js +7 -1
  519. package/dist/esm/lib/errors/AppError.js.map +1 -1
  520. package/dist/esm/lib/fields/Fields.d.ts +15 -0
  521. package/dist/esm/lib/fields/Fields.d.ts.map +1 -1
  522. package/dist/esm/lib/fields/Fields.js +1 -0
  523. package/dist/esm/lib/fields/Fields.js.map +1 -1
  524. package/dist/esm/lib/fields/Link.d.ts +2 -2
  525. package/dist/esm/lib/fields/Link.d.ts.map +1 -1
  526. package/dist/esm/lib/fields/Link.js +2 -1
  527. package/dist/esm/lib/fields/Link.js.map +1 -1
  528. package/dist/esm/lib/localeVariants.d.ts +3 -0
  529. package/dist/esm/lib/localeVariants.d.ts.map +1 -1
  530. package/dist/esm/lib/localeVariants.js +7 -0
  531. package/dist/esm/lib/localeVariants.js.map +1 -1
  532. package/dist/esm/lib/types/index.d.ts +1 -0
  533. package/dist/esm/lib/types/index.d.ts.map +1 -1
  534. package/dist/esm/literals/index.d.ts +0 -1
  535. package/dist/esm/literals/index.d.ts.map +1 -1
  536. package/dist/esm/literals/index.js +0 -1
  537. package/dist/esm/literals/index.js.map +1 -1
  538. package/dist/esm/mail/adapters.d.ts +34 -0
  539. package/dist/esm/mail/adapters.d.ts.map +1 -0
  540. package/dist/esm/mail/adapters.js +2 -0
  541. package/dist/esm/mail/adapters.js.map +1 -0
  542. package/dist/esm/mail/index.d.ts +11 -0
  543. package/dist/esm/mail/index.d.ts.map +1 -0
  544. package/dist/esm/mail/index.js +31 -0
  545. package/dist/esm/mail/index.js.map +1 -0
  546. package/dist/esm/mail/mailService.d.ts +58 -0
  547. package/dist/esm/mail/mailService.d.ts.map +1 -0
  548. package/dist/esm/mail/mailService.js +202 -0
  549. package/dist/esm/mail/mailService.js.map +1 -0
  550. package/dist/esm/mail/templates.d.ts +26 -0
  551. package/dist/esm/mail/templates.d.ts.map +1 -0
  552. package/dist/esm/mail/templates.js +27 -0
  553. package/dist/esm/mail/templates.js.map +1 -0
  554. package/dist/esm/manager.d.ts +160 -0
  555. package/dist/esm/manager.d.ts.map +1 -1
  556. package/dist/esm/orm/createIndexes.d.ts.map +1 -1
  557. package/dist/esm/orm/createIndexes.js +38 -1
  558. package/dist/esm/orm/createIndexes.js.map +1 -1
  559. package/dist/esm/orm/dbService.js +3 -3
  560. package/dist/esm/orm/dbService.js.map +1 -1
  561. package/dist/esm/orm/operations/update.d.ts.map +1 -1
  562. package/dist/esm/orm/operations/update.js +28 -26
  563. package/dist/esm/orm/operations/update.js.map +1 -1
  564. package/dist/esm/plugins.d.ts +4 -0
  565. package/dist/esm/plugins.d.ts.map +1 -1
  566. package/dist/esm/plugins.js.map +1 -1
  567. package/dist/esm/schemas/manager/auth/externalLogin.d.ts +42 -0
  568. package/dist/esm/schemas/manager/auth/externalLogin.d.ts.map +1 -0
  569. package/dist/esm/schemas/manager/auth/externalLogin.js +21 -0
  570. package/dist/esm/schemas/manager/auth/externalLogin.js.map +1 -0
  571. package/dist/esm/schemas/manager/auth/mfa/recoveryCode.d.ts +22 -0
  572. package/dist/esm/schemas/manager/auth/mfa/recoveryCode.d.ts.map +1 -0
  573. package/dist/esm/schemas/manager/auth/mfa/recoveryCode.js +21 -0
  574. package/dist/esm/schemas/manager/auth/mfa/recoveryCode.js.map +1 -0
  575. package/dist/esm/schemas/manager/auth/passwordIpBlocks.d.ts +36 -0
  576. package/dist/esm/schemas/manager/auth/passwordIpBlocks.d.ts.map +1 -0
  577. package/dist/esm/schemas/manager/auth/passwordIpBlocks.js +26 -0
  578. package/dist/esm/schemas/manager/auth/passwordIpBlocks.js.map +1 -0
  579. package/dist/esm/schemas/manager/auth/passwordRecovery.d.ts +17 -0
  580. package/dist/esm/schemas/manager/auth/passwordRecovery.d.ts.map +1 -0
  581. package/dist/esm/schemas/manager/auth/passwordRecovery.js +15 -0
  582. package/dist/esm/schemas/manager/auth/passwordRecovery.js.map +1 -0
  583. package/dist/esm/schemas/manager/auth/totp/confirmTotp.d.ts +4 -5
  584. package/dist/esm/schemas/manager/auth/totp/confirmTotp.d.ts.map +1 -1
  585. package/dist/esm/schemas/manager/auth/totp/confirmTotp.js +4 -7
  586. package/dist/esm/schemas/manager/auth/totp/confirmTotp.js.map +1 -1
  587. package/dist/esm/schemas/manager/comments.d.ts +15 -0
  588. package/dist/esm/schemas/manager/comments.d.ts.map +1 -1
  589. package/dist/esm/schemas/manager/comments.js +10 -0
  590. package/dist/esm/schemas/manager/comments.js.map +1 -1
  591. package/dist/esm/schemas/manager/contentVersions.d.ts +442 -0
  592. package/dist/esm/schemas/manager/contentVersions.d.ts.map +1 -0
  593. package/dist/esm/schemas/manager/contentVersions.js +45 -0
  594. package/dist/esm/schemas/manager/contentVersions.js.map +1 -0
  595. package/dist/esm/schemas/manager/eventLogs.d.ts +127 -0
  596. package/dist/esm/schemas/manager/eventLogs.d.ts.map +1 -0
  597. package/dist/esm/schemas/manager/eventLogs.js +48 -0
  598. package/dist/esm/schemas/manager/eventLogs.js.map +1 -0
  599. package/dist/esm/schemas/manager/list.d.ts +1 -0
  600. package/dist/esm/schemas/manager/list.d.ts.map +1 -1
  601. package/dist/esm/schemas/manager/list.js +1 -0
  602. package/dist/esm/schemas/manager/list.js.map +1 -1
  603. package/dist/esm/schemas/manager/localeVariants.d.ts +51 -0
  604. package/dist/esm/schemas/manager/localeVariants.d.ts.map +1 -1
  605. package/dist/esm/schemas/manager/localeVariants.js +9 -0
  606. package/dist/esm/schemas/manager/localeVariants.js.map +1 -1
  607. package/dist/esm/schemas/manager/notifications.d.ts +79 -0
  608. package/dist/esm/schemas/manager/notifications.d.ts.map +1 -0
  609. package/dist/esm/schemas/manager/notifications.js +45 -0
  610. package/dist/esm/schemas/manager/notifications.js.map +1 -0
  611. package/dist/esm/schemas/manager/reviewPolicies.d.ts +43 -0
  612. package/dist/esm/schemas/manager/reviewPolicies.d.ts.map +1 -0
  613. package/dist/esm/schemas/manager/reviewPolicies.js +27 -0
  614. package/dist/esm/schemas/manager/reviewPolicies.js.map +1 -0
  615. package/dist/esm/schemas/manager/reviews.d.ts +442 -0
  616. package/dist/esm/schemas/manager/reviews.d.ts.map +1 -0
  617. package/dist/esm/schemas/manager/reviews.js +87 -0
  618. package/dist/esm/schemas/manager/reviews.js.map +1 -0
  619. package/dist/esm/schemas/manager/routeLayout.d.ts +75 -0
  620. package/dist/esm/schemas/manager/routeLayout.d.ts.map +1 -0
  621. package/dist/esm/schemas/manager/routeLayout.js +44 -0
  622. package/dist/esm/schemas/manager/routeLayout.js.map +1 -0
  623. package/dist/esm/schemas/manager/slugRedirects.d.ts +26 -0
  624. package/dist/esm/schemas/manager/slugRedirects.d.ts.map +1 -0
  625. package/dist/esm/schemas/manager/slugRedirects.js +18 -0
  626. package/dist/esm/schemas/manager/slugRedirects.js.map +1 -0
  627. package/dist/esm/schemas/manager/uiLocales.d.ts +33 -0
  628. package/dist/esm/schemas/manager/uiLocales.d.ts.map +1 -0
  629. package/dist/esm/schemas/manager/uiLocales.js +25 -0
  630. package/dist/esm/schemas/manager/uiLocales.js.map +1 -0
  631. package/dist/esm/schemas/manager/update.d.ts +1 -0
  632. package/dist/esm/schemas/manager/update.d.ts.map +1 -1
  633. package/dist/esm/schemas/manager/update.js +1 -0
  634. package/dist/esm/schemas/manager/update.js.map +1 -1
  635. package/dist/esm/schemas/web/page.d.ts +12 -0
  636. package/dist/esm/schemas/web/page.d.ts.map +1 -1
  637. package/dist/esm/schemas/web/previewPage.d.ts +8 -0
  638. package/dist/esm/schemas/web/previewPage.d.ts.map +1 -1
  639. package/dist/tsconfig.build.tsbuildinfo +1 -1
  640. package/package.json +11 -4
  641. package/dist/cjs/literals/manager.js +0 -43
  642. package/dist/cjs/literals/manager.js.map +0 -1
  643. package/dist/cjs/literals/managerLiterals.js +0 -15
  644. package/dist/cjs/literals/managerLiterals.js.map +0 -1
  645. package/dist/esm/literals/manager.d.ts +0 -22
  646. package/dist/esm/literals/manager.d.ts.map +0 -1
  647. package/dist/esm/literals/manager.js +0 -38
  648. package/dist/esm/literals/manager.js.map +0 -1
  649. package/dist/esm/literals/managerLiterals.d.ts +0 -12
  650. package/dist/esm/literals/managerLiterals.d.ts.map +0 -1
  651. package/dist/esm/literals/managerLiterals.js +0 -12
  652. package/dist/esm/literals/managerLiterals.js.map +0 -1
package/README.md CHANGED
@@ -1,732 +1,1100 @@
1
- # @rakun-kit/core
2
-
3
- `@rakun-kit/core` contains Rakun's shared domain model and runtime. It defines content types, fields, Zod schemas, manager/web operations, request context, MongoDB connection handling, media service, permissions, translations, and typed contracts used by adapters (`@rakun-kit/next`, `@rakun-kit/express`, `@rakun-kit/trpc`) and the manager client.
4
-
5
- ## Main Entry
6
-
7
- Typical imports:
8
-
9
- ```ts
10
- import {
11
- ContentType,
12
- Fields,
13
- rakunBootstrap,
14
- ensureRakunInitialized,
15
- } from "@rakun-kit/core";
16
- ```
17
-
18
- The main entrypoint exports:
19
-
20
- - Bootstrap: `rakunBootstrap`, `ensureRakunBootstrap`, `ensureRakunInitialized`, `getRakunBootstrapOptions`.
21
- - Context: `createRequestContext`, `getSessionCookie`, `setSessionCookie`.
22
- - Operations: manager/web contracts and definitions.
23
- - Media: `createMediaService`, `getMediaService`, adapters, and types.
24
- - Permissions, translations, errors, contracts, and public types.
25
- - Basic internal content types: `Language`, `ManagerUser`, `Seo`.
26
-
27
- Relevant subpaths:
28
-
29
- - `@rakun-kit/core/manager`: manager operation metadata and types.
30
- - `@rakun-kit/core/contracts`: shared manager/web payload schemas.
31
- - `@rakun-kit/core/client`: client-facing types and utilities.
32
- - `@rakun-kit/core/logger`: logger.
33
- - `@rakun-kit/core/errors`: application errors.
34
- - `@rakun-kit/core/types`: types derived from content types.
35
-
36
- ## Bootstrap
37
-
38
- `rakunBootstrap(options)` registers global configuration and content types:
39
-
40
- ```ts
41
- rakunBootstrap({
42
- literals,
43
- contentTypes: [Page, Post],
44
- routes,
45
- apiOperations,
46
- mongo: {
47
- MONGO_URI: process.env.MONGO_URI!,
48
- ENVIRONMENT: process.env.NODE_ENV === "test" ? "test" : "production",
49
- },
50
- media,
51
- logger: {
52
- level: "info",
53
- prettify: true,
54
- },
55
- syncRoutes: true,
56
- });
57
- ```
58
-
59
- Options:
60
-
61
- - `literals`: text/translation catalog.
62
- - `contentTypes`: application content types.
63
- - `internalContentTypes`: optional overrides for Rakun internal content types, currently `Page`.
64
- - `routes`: configured routes used to resolve pages.
65
- - `apiOperations`: custom API operations added to the Rakun operation registry.
66
- - `mongo`: MongoDB connection. Required before serving Rakun requests.
67
- - `media`: media adapter/configuration. Optional.
68
- - `logger`: logger configuration. If omitted, an `info` logger with `prettify` is created.
69
- - `syncRoutes`: syncs configured routes during initialization. Enabled by default.
70
-
71
- Content types can define lifecycle `hooks` and opt into manager-selected
72
- `dynamicData` sources.
73
-
74
- Routes can define fixed layout module slots. Rakun syncs those slots and the
75
- manager lets users select an existing entry for each route:
76
-
77
- ```ts
78
- rakunBootstrap({
79
- // ...
80
- routes: [
81
- {
82
- key: "pages",
83
- contentType: "Page",
84
- field: "slug",
85
- hasPage: true,
86
- dynamic: false,
87
- defaultBasePath: "",
88
- layout: [
89
- { key: "header", contentType: "Header" },
90
- { type: "content" },
91
- { key: "footer", contentType: "Footer" },
92
- ],
93
- },
94
- ],
95
- });
96
- ```
97
-
98
- The web page response includes an ordered `layout` array containing module slots
99
- plus the content slot.
100
-
101
- `ensureRakunInitialized()` prepares logger, MongoDB, media, and route syncing. It uses a singleton promise to avoid concurrent initialization; if initialization fails, the promise is cleared so the next call can retry.
102
-
103
- `ensureRakunBootstrap(options)` only calls `rakunBootstrap` if the runtime has not been bootstrapped yet.
104
-
105
- ## Plugins
106
-
107
- Trusted server plugins contribute to the same bootstrap registry without coupling
108
- core to React:
109
-
110
- ```ts
111
- import { defineRakunPlugin, rakunBootstrap } from '@rakun-kit/core'
112
-
113
- export const analyticsPlugin = defineRakunPlugin({
114
- id: '@acme/rakun-analytics',
115
- contentTypes: [AnalyticsEvent],
116
- routes: analyticsRoutes,
117
- apiOperations: analyticsOperations,
118
- permissions: ['plugin.analytics.view'],
119
- literals: {},
120
- initialize: async ({ db }) => {
121
- // Services and migrations are ready here. Keep initialization idempotent.
122
- },
123
- })
124
-
125
- rakunBootstrap({
126
- plugins: [analyticsPlugin],
127
- contentTypes: [],
128
- literals: {},
129
- mongo,
130
- })
131
- ```
132
-
133
- Plugin ids and contributed content types, routes, operations, literals, and
134
- custom field editor ids must be unique. Rakun reports both owners on conflicts.
135
- Visual manager and web facets are registered separately in their browser
136
- runtimes.
137
-
138
- Custom field factories can use `createPluginField`. Their serializable
139
- `meta.editor` must match a field declaration in the server plugin and a React
140
- editor registered by its manager facet.
141
-
142
- ## Content Types
143
-
144
- A `ContentType` defines a logical collection:
145
-
146
- ```ts
147
- const Post = new ContentType({
148
- name: "Post",
149
- comments: true,
150
- menu: {
151
- title: "Posts",
152
- icon: "newspaper",
153
- category: "Content",
154
- },
155
- fields: {
156
- title: Fields.string().required(),
157
- slug: Fields.string().type("Slug").required(),
158
- body: Fields.string().type("RichText"),
159
- published: Fields.boolean(),
160
- },
161
- uniques: [["slug"]],
162
- listFields: ["title", "slug", "published"],
163
- });
164
- ```
165
-
166
- Page-like content types can define ordered page modules with `iterator` outside
167
- `fields`. Rakun persists this generated field as `_iterator`:
168
-
169
- ```ts
170
- const Page = new ContentType({
171
- name: "Page",
172
- fields: {
173
- title: Fields.string().required(),
174
- slug: Fields.string().type("Slug").required(),
175
- },
176
- iterator: [{ contentType: PageSection, type: "existing" }],
177
- linkedIterator: true,
178
- });
179
- ```
180
-
181
- Set `linkedIterator: true` when every document should use one shared module
182
- structure. The manager stores a canonical iterator for the content type, while
183
- dynamic bindings such as `Current document` continue to resolve against the
184
- individual page being rendered. Documents are linked by default and can be
185
- unlinked in the manager to keep a local copy of the iterator.
186
-
187
- Iterator modules can also be made conditional from the manager. A condition is
188
- stored on the shared module entry and evaluated against the current document:
189
-
190
- ```ts
191
- {
192
- name: "Credits",
193
- value: { /* module relation */ },
194
- visibleWhen: {
195
- field: "credits",
196
- operator: "notEmpty",
197
- },
198
- }
199
- ```
200
-
201
- Supported operators are `notEmpty` and `empty`. Conditional modules remain part
202
- of the shared structure but are omitted from web and preview output when their
203
- condition does not match.
204
-
205
- Main properties:
206
-
207
- - `name`: stable type name. Also used as `_type`.
208
- - `fields`: field map.
209
- - `iterator`: page module entries. Generates the reserved `_iterator` field.
210
- - `linkedIterator`: shares that iterator between documents while allowing
211
- explicit per-document overrides.
212
- - `menu`: manager metadata.
213
- - `uniques`: unique field groups.
214
- - `listFields`: preferred fields in lists and relations.
215
- - `hideFromManager()`: hides the content type from manager content type lists.
216
- - `apiOnly()`: applies `.apiOnly()` to every field in the content type.
217
- - `managerOnly()`: applies `.managerOnly()` to every field in the content type.
218
- - `comments: true` or `enableComments()`: enables manager document comments and user mentions for saved entries.
219
- - `withHooks()`: attaches lifecycle hooks such as `beforeInsert`, `beforeUpdate`, and `onGet`.
220
- - Dynamic data bindings are available on manager-visible fields by default; use
221
- field-level `.noDynamic()` to opt out.
222
-
223
- When a content type has a configured route with `hasPage: true`, Rakun also
224
- adds an optional reserved `_seo` relation automatically.
225
-
226
- Hooks run around DB mutations and public output resolution:
227
-
228
- ```ts
229
- const User = new ContentType({
230
- name: "User",
231
- fields: {
232
- email: Fields.string().type("Email").required(),
233
- password: Fields.string().type("Password").required().managerOnly(),
234
- },
235
- }).withHooks({
236
- beforeInsert: ({ data }) => ({
237
- ...data,
238
- password: hashPassword(String(data.password)),
239
- }),
240
- onGet: ({ data }) => ({
241
- ...data,
242
- displayName: String(data.email).split("@")[0],
243
- }),
244
- });
245
- ```
246
-
247
- Dynamic data turns a content type into a reusable layout. The manager can bind
248
- manager-visible fields to another content item field, or to a generated `href`
249
- when a source content type has a page route. Fields are dynamic by default; call
250
- `.noDynamic()` on fields that should not accept bindings or be exported as
251
- source paths. Source content types are hidden by default; set
252
- `dynamicDataSource: true` on content types that should appear in the manager
253
- source selector. Field bindings can also select `Current document` to read values
254
- from the document being edited without marking its content type as a source.
255
-
256
- Source field selectors are type-aware. A string target only offers string-like
257
- source paths, number targets only offer numbers, and boolean targets only offer
258
- booleans. Object-like source fields are traversed so nested leaf fields can be
259
- selected, while reserved SEO metadata is omitted from dynamic data mappings.
260
- The generated `href` source is only shown for content types that have a
261
- configured route with `hasPage: true`.
262
-
263
- ```ts
264
- const Project = new ContentType({
265
- name: "Project",
266
- dynamicDataSource: true,
267
- fields: {
268
- title: Fields.string().required(),
269
- slug: Fields.string().type("Slug").required(),
270
- },
271
- });
272
-
273
- const Carousel = new ContentType({
274
- name: "Carousel",
275
- fields: {
276
- title: Fields.string().required(),
277
- internalNote: Fields.string().noDynamic(),
278
- items: Fields.blocks([
279
- {
280
- name: "CarouselItem",
281
- field: Fields.relation(CarouselItem, "new"),
282
- },
283
- ]),
284
- },
285
- });
286
- ```
287
-
288
- List bindings append dynamic items to manually stored items instead of replacing
289
- the list. If the same stable item id appears in both sources, the dynamically
290
- resolved item wins and the duplicate manual copy is skipped.
291
-
292
- A list inside a nested module can also use a compatible relation or blocks array
293
- from the current document. The manager exposes these sources as
294
- `Current document · <field>`, infers the content type of each array item, and
295
- lets each item be mapped with the same field mapping UI used for collections.
296
- These bindings store a `currentDocument` source alongside the inferred item
297
- content type:
298
-
299
- ```ts
300
- const headerBindings = {
301
- lists: {
302
- categories: {
303
- contentType: LinkItem.name,
304
- source: {
305
- kind: "currentDocument",
306
- contentType: Project.name,
307
- path: "categories",
308
- itemName: "Category",
309
- },
310
- itemName: "Category",
311
- map: {
312
- title: { contentType: LinkItem.name, path: "title" },
313
- href: { contentType: LinkItem.name, path: "href" },
314
- },
315
- },
316
- },
317
- };
318
- ```
319
-
320
- List query conditions can compare a source field with a value from the current
321
- document. The manager exposes this as `Current document`; programmatic bindings
322
- use `{ $current: "path.to.field" }`. For example, a category can query only the
323
- projects whose related category has the same slug:
324
-
325
- ```ts
326
- query: {
327
- filter: {
328
- "category.slug": { $current: "slug" },
329
- },
330
- options: { limit: 10 },
331
- }
332
- ```
333
-
334
- Current-document paths are checked against the content type's dynamic field
335
- rules before the query runs. `_id` is also available for relation queries.
336
-
337
- A list mapping can also collect an array through a reverse relation without
338
- persisting that relation on the source document. For example, a category gallery
339
- can create one item per `Category` and collect the images of its related
340
- `Project` documents:
341
-
342
- ```ts
343
- const Category = new ContentType({
344
- name: "Category",
345
- dynamicDataSource: true,
346
- fields: {
347
- title: Fields.string().required(),
348
- },
349
- });
350
-
351
- const Project = new ContentType({
352
- name: "Project",
353
- dynamicDataSource: true,
354
- fields: {
355
- category: Fields.relation(Category, "existing").required(),
356
- images: Fields.file().type("Image").multiple().required(),
357
- },
358
- });
359
-
360
- const galleryBindings = {
361
- lists: {
362
- items: {
363
- contentType: Category.name,
364
- itemName: "CategoriesGalleryItem",
365
- map: {
366
- title: { contentType: Category.name, path: "title" },
367
- images: {
368
- kind: "relatedCollection",
369
- contentType: Project.name,
370
- relation: "category",
371
- path: "images",
372
- limit: 10,
373
- },
374
- },
375
- },
376
- },
377
- };
378
- ```
379
-
380
- The related collection query matches `Project.category._id` against the current
381
- category, preserves project and image order, and flattens the selected array by
382
- one level. Its numeric limit applies to related projects and is capped at 100.
383
-
384
- Schema and validation methods:
385
-
386
- - `getInputSchema()`: write schema. Includes `_type`, `createdBy`, and `updatedBy`.
387
- - `getSchema()`: persisted schema.
388
- - `getPopulatedSchema()`: output with populated relations and `_id`.
389
- - `getOutputSchema()`: public API output.
390
- - `getOutputSchemaWithoutIterators()`: output variant without iterator fields.
391
- - `validate`, `partialValidate`, `validateOutput`: Zod helpers.
392
-
393
- The registry lives in `lib/Registry`:
394
-
395
- - `registerContentType`, `registerInternalContentType`.
396
- - `getContentTypes`, `getExternalContentTypes`, `getInternalContentTypes`.
397
- - `getContentTypesForManager`: returns serializable content types without Zod schemas and without content types marked with `hideFromManager()`.
398
- - `getContentTypeByName`.
399
-
400
- ## Fields
401
-
402
- Main factory:
403
-
404
- ```ts
405
- Fields.string();
406
- Fields.number();
407
- Fields.boolean();
408
- Fields.date();
409
- Fields.select(["draft", "published"]);
410
- Fields.relation(Post);
411
- Fields.contentReference("Post");
412
- Fields.selfRelation();
413
- Fields.blocks([{ name: "title", field: Fields.string() }]);
414
- Fields.array(Fields.string());
415
- Fields.link();
416
- Fields.file();
417
- ```
418
-
419
- Common modifiers:
420
-
421
- - `.required()`: marks field as required.
422
- - `.translatable()`: stores values per language with shape `{ _tag: "Translatable", ... }`.
423
- - `.apiOnly()`: available for API/persistence, hidden from manager.
424
- - `.managerOnly()`: visible to manager, excluded from API output.
425
-
426
- Notable fields:
427
-
428
- - `StringField`: UI `Text`, `Textarea`, `RichText`, `Email`, `Slug`, `Password`, `Id`, `Url`; supports `.min()` and `.max()`.
429
- - `NumberField`: supports `.min()` and `.max()`.
430
- - `RelationField`: relation to another `ContentType`; accepts existing references or inline creation. `Fields.relation(Post, "existing")` restricts to existing records; `"new"` restricts to new records. `.multiple()` returns a homogeneous array of relations.
431
- - `ContentReferenceField`: reference by content type name.
432
- - `FileField`: integrates media and optimization options.
433
- - `Fields.blocks(...)`: heterogeneous ordered list. Each item stores a `name` and a `value`, and the value can match one of the named field shapes. Use it for block-like content where different item types can appear in the same list.
434
- - `Fields.array(...)`: homogeneous ordered list. Every item uses the same field shape. Multi-value fields such as relation `.multiple()` use this backing model.
435
- - `IteratorField`: repeatable structure based on content type entries.
436
-
437
- ## Derived Types
438
-
439
- `@rakun-kit/core/types` and `lib/types` derive types from `ContentType`:
440
-
441
- - `DataInput<T>`: accepted shape for create/update.
442
- - `DBOutput<T>`: persisted shape with metadata (`_id`, `_type`, timestamps, authorship).
443
- - `DataPopulated<T>`: shape with populated relations.
444
- - `DataFront<T>`: public output without `apiOnly` fields.
445
- - `Filter<T>`, `Query<T>`, `ListInput<T>`, `GetAllInput<T>`: typed filters and list inputs.
446
- - `MaybeTranslatableValue<T>`, `TranslatableValue<T>`.
447
-
448
- ## ORM and Mongo
449
-
450
- `core/src/orm` implements `DBService` on top of MongoDB:
451
-
452
- ```ts
453
- const db = await getMongoService();
454
-
455
- const post = await db.create(Post, {
456
- _type: "Post",
457
- title: "Hello",
458
- slug: "hello",
459
- });
460
- ```
461
-
462
- Operations:
463
-
464
- - `get(contentType, id, fields?)`
465
- - `list(contentType, query)`
466
- - `create(contentType, data)`
467
- - `update(contentType, id, data)`
468
- - `updateMany(contentType, filter, data)`
469
- - `delete(contentType, filter)`
470
- - `find(contentType, filter, fields?)`
471
- - `clear(contentType)`
472
- - `findDependencies(contentType, id)`
473
- - `upsert(contentType, filter, data)`
474
- - `getAll(contentType, query?)`
475
-
476
- Connection:
477
-
478
- - `createMongoConnection(config)`: stores config.
479
- - `createMongoService(config)`: connects and creates handlers.
480
- - `getMongoService()`: returns the singleton or creates it from config.
481
- - `closeMongoService()`: closes the connection and clears the singleton.
482
-
483
- `MongoConfig`:
484
-
485
- ```ts
486
- type MongoConfig = {
487
- MONGO_URI: string;
488
- ENVIRONMENT?: "local" | "development" | "test" | "production";
489
- };
490
- ```
491
-
492
- In environments other than `test`, the connection creates indexes defined by `createIndexes`.
493
-
494
- ## API Operations
495
-
496
- `api/operations` defines typed contracts and handlers for endpoints:
497
-
498
- - Manager: CRUD, auth, MFA, media, literals, settings.
499
- - Manager comments: `manager.comments.list`, `manager.comments.create`, and `manager.users.mentions`.
500
- - Web: page resolution.
501
-
502
- Main helpers:
503
-
504
- - `defineOperationContract`: declares a contract with Zod input/output, method, path, and metadata.
505
- - `defineOperation`: combines a contract with its implementation.
506
- - `createRakunApiClient`: creates a browser/server HTTP client for custom operations.
507
- - `GetClient`: derives a typed client from an operation map.
508
- - `createManagerOperationContracts`, `createWebOperationContracts`.
509
- - `createManagerOperationDefinitions`, `createWebOperationDefinitions`.
510
- - `createRakunOperationDefinitions`: combines manager + web.
511
- - `createOperationManifest`: serializable metadata for clients.
512
- - `createOperationPath`: HTTP path from operation name.
513
- - `mergeOperationContracts`: combines maps.
514
-
515
- `@rakun-kit/core/manager` exposes the manifest and name-based types:
516
-
517
- ```ts
518
- import {
519
- managerOperationManifest,
520
- getManagerOperationMeta,
521
- type ManagerOperationInput,
522
- type ManagerOperationOutput,
523
- } from "@rakun-kit/core/manager";
524
- ```
525
-
526
- ### Custom Operations
527
-
528
- Applications can define operations in a separate object, pass that object to
529
- bootstrap, and reuse its type on the frontend:
530
-
531
- ```ts
532
- // server/api-operations.ts
533
- import { defineOperation } from "@rakun-kit/core";
534
- import { z } from "zod";
535
-
536
- export const apiOperations = {
537
- "demo.helloWorld": defineOperation<
538
- { text: string },
539
- { message: string },
540
- "query",
541
- "get",
542
- "public"
543
- >({
544
- access: "public",
545
- kind: "query",
546
- method: "get",
547
- description: "Return a hello world message with the provided text",
548
- input: z.object({
549
- text: z.string().default("world"),
550
- }),
551
- output: z.object({
552
- message: z.string(),
553
- }),
554
- resolve: ({ input }) => ({
555
- message: `Hello ${input.text}`,
556
- }),
557
- }),
558
- };
559
- ```
560
-
561
- ```ts
562
- // bootstrap
563
- import { apiOperations } from "./server/api-operations";
564
-
565
- rakunBootstrap({
566
- // ...
567
- apiOperations,
568
- });
569
- ```
570
-
571
- Operation names define their HTTP path: `demo.helloWorld` becomes
572
- `/demo/helloWorld`.
573
-
574
- Rules:
575
-
576
- - Names must not collide with built-in operations.
577
- - Operations prefixed with `manager.` are included in manager operation routers.
578
- - Operations prefixed with `web.` are included in web operation routers.
579
- - Operations with any other prefix are included when using the combined operation registry.
580
- - Use `access: "public"` for operations called from public web pages.
581
- - Use `access: "auth"` for operations that require a manager session.
582
-
583
- The manager route `manager.apiOperations` returns a JSON-serializable operation
584
- catalog for manager API docs/playgrounds. Input and output Zod schemas are
585
- converted to JSON Schema for display.
586
-
587
- ### Typed API Client
588
-
589
- `@rakun-kit/core/web` exposes a small typed HTTP client for operation maps:
590
-
591
- ```ts
592
- import {
593
- createRakunApiClient,
594
- type GetClient,
595
- } from "@rakun-kit/core/web";
596
- import type { apiOperations } from "./server/api-operations";
597
-
598
- type ApiClient = GetClient<typeof apiOperations>;
599
-
600
- const client: ApiClient = createRakunApiClient<typeof apiOperations>({
601
- baseUrl: "/api",
602
- });
603
-
604
- const result = await client.query("demo.helloWorld", {
605
- text: "Rakun",
606
- });
607
-
608
- result.message;
609
- ```
610
-
611
- The client exposes:
612
-
613
- - `query(name, input?, options?)`: only accepts operations with `kind: "query"`.
614
- - `mutation(name, input?, options?)`: only accepts operations with `kind: "mutation"`.
615
-
616
- The client derives input and output types from the Zod schemas in
617
- `apiOperations`.
618
-
619
- ## Request Context and Auth
620
-
621
- `createRequestContext(input)` normalizes headers, cookies, and response:
622
-
623
- ```ts
624
- const ctx = await createRequestContext({
625
- headers: req.headers,
626
- cookies,
627
- res: {
628
- setHeader: res.setHeader.bind(res),
629
- cookie: res.cookie.bind(res),
630
- },
631
- });
632
- ```
633
-
634
- The resulting context includes:
635
-
636
- - `req.headers`, `req.cookies`
637
- - `res.setHeader`, `res.cookie`
638
- - `user`: manager user or `null`
639
- - `getUser()`: returns the user or throws `AUTH_REQUIRED`
640
-
641
- Session cookies are managed with `getSessionCookie` and `setSessionCookie`.
642
-
643
- ## Media
644
-
645
- Media uses a storage adapter:
646
-
647
- ```ts
648
- createMediaService({
649
- adapter,
650
- defaultAccess: "private",
651
- defaultGetExpiresInSeconds: 300,
652
- uploadUrl: "/api/rakun/manager/media/upload",
653
- });
654
- ```
655
-
656
- APIs:
657
-
658
- - `createMediaConnection(config)`: stores config without creating the service.
659
- - `createMediaService(config)`: creates the singleton with an adapter.
660
- - `getMediaService()`: returns the singleton or creates it from config.
661
- - `handleMediaBinaryUpload`: processes manager binary uploads.
662
-
663
- The service supports prepare/finalize upload, URL generation, folders, and image optimization depending on adapter/configuration.
664
-
665
- ## Literals and Translation
666
-
667
- Bootstrap receives `literals`. Related utilities:
668
-
669
- - `getTranslation`: resolves translatable values.
670
- - `translateObject`: translates objects with translatable fields.
671
- - `managerLiterals`: base manager texts.
672
- - Manager schemas for listing/upserting literals.
673
-
674
- Translatable values use this shape:
675
-
676
- ```ts
677
- {
678
- _tag: "Translatable",
679
- en: "Title",
680
- es: "Titulo"
681
- }
682
- ```
683
-
684
- ## Permissions
685
-
686
- `lib/Permissions` exposes:
687
-
688
- - `getPermissionList`: generates a permission list.
689
- - `hasPermissions`: validates user/role permissions.
690
- - `mapPermissions`: transforms permissions.
691
- - `Permission`: public type.
692
-
693
- Manager routes apply permissions, ownership, and auth through utilities in `api/utils`.
694
-
695
- ## Errors
696
-
697
- Application errors live in `lib/errors`:
698
-
699
- - `AppError`
700
- - `throwAppError`
701
- - `errors`
702
- - `instanceofAppErrorShape`
703
-
704
- Database errors live in `orm/dbService`:
705
-
706
- - `DbError`
707
- - `DbErrorUnknown`
708
- - `DbErrorNotFound`
709
- - `DbErrorInvalidData`
710
- - `DbErrorConflict`
711
- - `DbErrorSimulatedFailure`
712
-
713
- ## Runtime Flow
714
-
715
- 1. The app defines content types with `ContentType` and `Fields`.
716
- 2. The app calls `rakunBootstrap(options)`.
717
- 3. The HTTP adapter calls `ensureRakunInitialized()` before serving Rakun routes.
718
- 4. `ensureRakunInitialized()` configures logger, MongoDB, media, and route syncing.
719
- 5. Each request creates a `RakunRequestContext`.
720
- 6. Manager/web operations validate input, run logic, validate output, and return typed contracts.
721
-
722
- ## Tests and Development Notes
723
-
724
- The package includes targeted tests next to modules (`*.test.ts`), for example ORM, translation, routes, redirects, and populated relations.
725
-
726
- Package build:
727
-
728
- ```sh
729
- bun run build --workspace @rakun-kit/core
730
- ```
731
-
732
- The script generates ESM and CJS in `dist/`, adjusting imports and the CJS `package.json` through repo scripts.
1
+ # @rakun-kit/core
2
+
3
+ `@rakun-kit/core` contains Rakun's shared domain model and runtime. It defines content types, fields, Zod schemas, manager/web operations, request context, MongoDB connection handling, media service, permissions, translations, and typed contracts used by adapters (`@rakun-kit/next`, `@rakun-kit/express`, `@rakun-kit/trpc`) and the manager client.
4
+
5
+ ## Main Entry
6
+
7
+ Typical imports:
8
+
9
+ ```ts
10
+ import {
11
+ ContentType,
12
+ f,
13
+ rakunBootstrap,
14
+ ensureRakunInitialized,
15
+ } from "@rakun-kit/core";
16
+ ```
17
+
18
+ The main entrypoint exports:
19
+
20
+ - Bootstrap: `rakunBootstrap`, `ensureRakunBootstrap`, `ensureRakunInitialized`, `getRakunBootstrapOptions`.
21
+ - Context: `createRequestContext`, `getSessionCookie`, `setSessionCookie`.
22
+ - Operations: manager/web contracts and definitions.
23
+ - Media: `createMediaService`, `getMediaService`, adapters, and types.
24
+ - Mail: `createMailService`, `sendMail`, typed template registries, adapters, and types.
25
+ - Permissions, translations, errors, contracts, and public types.
26
+ - Basic internal content types: `Language`, `ManagerUser`, `Seo`.
27
+
28
+ Relevant subpaths:
29
+
30
+ - `@rakun-kit/core/manager`: manager operation metadata and types.
31
+ - `@rakun-kit/core/contracts`: shared manager/web payload schemas.
32
+ - `@rakun-kit/core/client`: client-facing types and utilities.
33
+ - `@rakun-kit/core/logger`: logger.
34
+ - `@rakun-kit/core/errors`: application errors.
35
+ - `@rakun-kit/core/types`: types derived from content types.
36
+
37
+ ## Bootstrap
38
+
39
+ `rakunBootstrap(options)` registers global configuration and content types:
40
+
41
+ ```ts
42
+ rakunBootstrap({
43
+ literals,
44
+ contentTypes: [Page, Post],
45
+ routes,
46
+ apiOperations,
47
+ mongo: {
48
+ MONGO_URI: process.env.MONGO_URI!,
49
+ ENVIRONMENT: process.env.NODE_ENV === "test" ? "test" : "production",
50
+ },
51
+ media,
52
+ logger: {
53
+ level: "info",
54
+ prettify: true,
55
+ },
56
+ syncRoutes: true,
57
+ });
58
+ ```
59
+
60
+ Options:
61
+
62
+ - `literals`: text/translation catalog.
63
+ - `contentTypes`: application content types.
64
+ - `internalContentTypes`: optional overrides for Rakun internal content types, currently `Page`.
65
+ - `routes`: configured routes used to resolve pages.
66
+ - `apiOperations`: custom API operations added to the Rakun operation registry.
67
+ - `mongo`: MongoDB connection. Required before serving Rakun requests.
68
+ - `media`: media adapter/configuration. Optional.
69
+ - `mail`: outbound mail adapter and default sender configuration. Optional.
70
+ - `accountRecovery`: password-reset URL builder, expiry, and optional custom
71
+ mail template. Requires `mail`; core provides the default template.
72
+ - `login`: manager password-login toggle and external login adapters.
73
+ - `logger`: logger configuration. If omitted, an `info` logger with `prettify` is created.
74
+ - `syncRoutes`: syncs configured routes during initialization. Enabled by default.
75
+
76
+ ## External manager login
77
+
78
+ Configure external login methods in `rakunBootstrap`. The callback URL is the
79
+ manager's public `/login/callback` route.
80
+
81
+ ```ts
82
+ import {
83
+ createGitHubLoginAdapter,
84
+ createGoogleLoginAdapter,
85
+ createMicrosoftLoginAdapter,
86
+ rakunBootstrap,
87
+ } from "@rakun-kit/core";
88
+
89
+ const callbackUrl = "https://cms.example.com/backend/login/callback";
90
+
91
+ rakunBootstrap({
92
+ // ...
93
+ login: {
94
+ password: true,
95
+ adapters: [
96
+ createGitHubLoginAdapter({
97
+ clientId: process.env.GITHUB_CLIENT_ID!,
98
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
99
+ redirectUri: callbackUrl,
100
+ }),
101
+ createGoogleLoginAdapter({
102
+ clientId: process.env.GOOGLE_CLIENT_ID!,
103
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
104
+ redirectUri: callbackUrl,
105
+ }),
106
+ createMicrosoftLoginAdapter({
107
+ clientId: process.env.MICROSOFT_CLIENT_ID!,
108
+ clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
109
+ redirectUri: callbackUrl,
110
+ tenant: "common",
111
+ }),
112
+ ],
113
+ },
114
+ });
115
+ ```
116
+
117
+ Register the exact callback URL in each provider console. External identities
118
+ must return a verified email matching an
119
+ existing manager user. Rakun does not create manager accounts automatically.
120
+ The flow uses an HttpOnly state cookie and PKCE and preserves the existing MFA
121
+ step. Set `password: false` only when at least one adapter is configured.
122
+ Custom providers can be implemented with `defineLoginAdapter`.
123
+
124
+ ### Persistent password-login IP blocking
125
+
126
+ Password login enables persistent fail2ban-style IP blocking by default. Five
127
+ failed attempts block the IP indefinitely; a successful login before reaching
128
+ the limit clears its failed-attempt counter. Configure or disable it through
129
+ `login.fail2ban`:
130
+
131
+ ```ts
132
+ rakunBootstrap({
133
+ // ...
134
+ login: {
135
+ password: true,
136
+ fail2ban: {
137
+ maxAttempts: 5,
138
+ // Optional when the deployment uses a custom trusted proxy:
139
+ // resolveIp: (ctx) => ctx.req?.headers?.['your-trusted-ip-header'] as string,
140
+ },
141
+ },
142
+ })
143
+ ```
144
+
145
+ Users with the `auth.ipBlocks.manage` permission can inspect and remove blocks
146
+ under Manager Settings → Security. Admin roles receive this built-in permission
147
+ automatically. A block can also be removed directly from MongoDB by deleting
148
+ the matching document from the `LoginIpBlock` collection. Set `fail2ban: false`
149
+ to disable this behavior. External login adapters are not affected.
150
+
151
+ ## Account recovery and MFA recovery
152
+
153
+ Password recovery is enabled when both `mail` and `accountRecovery` are
154
+ configured. The reset URL must point to the manager's public
155
+ `/reset-password` screen and preserve the token as the `token` query parameter:
156
+
157
+ ```ts
158
+ import { rakunBootstrap } from "@rakun-kit/core";
159
+ import { createResendMailServiceConfig } from "@rakun-kit/resend";
160
+
161
+ rakunBootstrap({
162
+ // ...
163
+ mail: createResendMailServiceConfig({
164
+ apiKey: process.env.RESEND_API_KEY!,
165
+ defaultFrom: process.env.RAKUN_MAIL_FROM!,
166
+ }),
167
+ accountRecovery: {
168
+ passwordReset: {
169
+ expiresInMs: 60 * 60 * 1000,
170
+ createUrl: (token) =>
171
+ `https://cms.example.com/backend/reset-password?token=${encodeURIComponent(token)}`,
172
+ },
173
+ },
174
+ });
175
+ ```
176
+
177
+ Core uses its branded HTML and plain-text password-reset template by default.
178
+ Pass `accountRecovery.passwordReset.template` only when the application needs
179
+ to replace it with custom branding or copy.
180
+
181
+ Reset tokens are random, stored only as SHA-256 hashes, expire, and are consumed
182
+ once. A successful reset closes every existing session but never disables MFA.
183
+ The request endpoint always returns the same result for known and unknown email
184
+ addresses.
185
+
186
+ Enabling TOTP or the first WebAuthn device returns one-time recovery codes to
187
+ the manager UI. Only their hashes are persisted, each code is consumed after
188
+ one login, and users can replace the entire set from their account after
189
+ confirming their current password. MFA state cannot be disabled through generic
190
+ manager content operations. If a user loses all MFA methods and recovery codes,
191
+ recovery must be handled by an authorized person through a channel outside the
192
+ CMS.
193
+
194
+ Content types can define lifecycle `hooks` and opt into manager-selected
195
+ `dynamicData` sources.
196
+
197
+ Routes can define fixed layout module slots. Rakun syncs those slots and the
198
+ manager lets users select an existing entry for each route:
199
+
200
+ ```ts
201
+ rakunBootstrap({
202
+ // ...
203
+ routes: [
204
+ {
205
+ key: "pages",
206
+ contentType: "Page",
207
+ field: "slug",
208
+ hasPage: true,
209
+ dynamic: false,
210
+ defaultBasePath: "",
211
+ layout: [
212
+ { key: "header", contentType: "Header" },
213
+ { type: "content" },
214
+ { key: "footer", contentType: "Footer" },
215
+ ],
216
+ },
217
+ ],
218
+ });
219
+ ```
220
+
221
+ The web page response includes an ordered `layout` array containing module slots
222
+ plus the content slot.
223
+
224
+ ## Module picker
225
+
226
+ Content types used as iterator modules can customize their card in the manager's
227
+ add-module dialog. `modulePicker.preview` accepts an image URL available to the
228
+ manager browser; relative URLs are also supported:
229
+
230
+ ```ts
231
+ const Hero = new ContentType({
232
+ name: "Hero",
233
+ modulePicker: {
234
+ title: "Hero section",
235
+ description: "Large introduction with heading, copy, and CTA.",
236
+ category: "Marketing",
237
+ icon: "PanelTop",
238
+ preview: "/images/modules/hero.webp",
239
+ keywords: ["banner", "cover"],
240
+ },
241
+ fields: {
242
+ title: f.string().required(),
243
+ },
244
+ });
245
+ ```
246
+
247
+ When `preview` is omitted or cannot be loaded, the picker displays a neutral
248
+ placeholder so module cards keep a consistent height.
249
+
250
+ `ensureRakunInitialized()` prepares logger, MongoDB, media, and route syncing. It uses a singleton promise to avoid concurrent initialization; if initialization fails, the promise is cleared so the next call can retry.
251
+
252
+ `ensureRakunBootstrap(options)` only calls `rakunBootstrap` if the runtime has not been bootstrapped yet.
253
+
254
+ English is built into `@rakun-kit/manager-react`. Install only the extra
255
+ manager UI locales an application needs:
256
+
257
+ ```sh
258
+ bun add @rakun-kit/manager-locales
259
+ # or: npm install @rakun-kit/manager-locales
260
+ ```
261
+
262
+ Import the required language subpath and register it with `managerLanguages`;
263
+ the public `manager.uiLocales` operation returns configured packs to the
264
+ manager client:
265
+
266
+ ```ts
267
+ import { esManagerLocalePack } from "@rakun-kit/manager-locales/es";
268
+
269
+ rakunBootstrap({
270
+ // ...
271
+ managerLanguages: [esManagerLocalePack],
272
+ });
273
+ ```
274
+
275
+ `managerLanguages` may also extend locales with arbitrary project keys. This is
276
+ useful for translatable content-type titles and categories without adding host
277
+ keys to the manager's static `ManagerMessageKey` union:
278
+
279
+ ```ts
280
+ import { extendManagerLanguagePack } from "@rakun-kit/core/contracts";
281
+ import { esManagerLocalePack } from "@rakun-kit/manager-locales/es";
282
+
283
+ rakunBootstrap({
284
+ // ...
285
+ managerLanguages: [
286
+ {
287
+ code: "en",
288
+ name: "English",
289
+ messages: {
290
+ "field.title": "Title",
291
+ "layoutModule.header": "Header",
292
+ "project.contentTypes.article.menu": "Articles",
293
+ },
294
+ },
295
+ extendManagerLanguagePack(esManagerLocalePack, {
296
+ "field.title": "Título",
297
+ "layoutModule.header": "Cabecera",
298
+ "project.contentTypes.article.menu": "Artículos",
299
+ }),
300
+ ],
301
+ });
302
+ ```
303
+
304
+ Content-type field labels automatically use `field.<fieldName>` from these
305
+ project messages. Missing translations fall back to a built-in manager label
306
+ when available and otherwise to the humanized field name.
307
+
308
+ Route layout module labels use `layoutModule.<layoutKey>`, so a slot configured
309
+ with `key: 'header'` resolves `layoutModule.header`.
310
+
311
+ ## Plugins
312
+
313
+ Trusted server plugins contribute to the same bootstrap registry without coupling
314
+ core to React:
315
+
316
+ ```ts
317
+ import { defineRakunPlugin, rakunBootstrap } from "@rakun-kit/core";
318
+
319
+ export const analyticsPlugin = defineRakunPlugin({
320
+ id: "@acme/rakun-analytics",
321
+ contentTypes: [AnalyticsEvent],
322
+ routes: analyticsRoutes,
323
+ apiOperations: analyticsOperations,
324
+ permissions: ["plugin.analytics.view"],
325
+ literals: {},
326
+ initialize: async ({ db }) => {
327
+ // Services and migrations are ready here. Keep initialization idempotent.
328
+ },
329
+ });
330
+
331
+ rakunBootstrap({
332
+ plugins: [analyticsPlugin],
333
+ contentTypes: [],
334
+ literals: {},
335
+ mongo,
336
+ });
337
+ ```
338
+
339
+ Plugin ids and contributed content types, routes, operations, literals, and
340
+ custom field editor ids must be unique. Rakun reports both owners on conflicts.
341
+ Visual manager and web facets are registered separately in their browser
342
+ runtimes.
343
+
344
+ Custom field factories can use `createPluginField`. Their serializable
345
+ `meta.editor` must match a field declaration in the server plugin and a React
346
+ editor registered by its manager facet.
347
+
348
+ ## Content Types
349
+
350
+ A `ContentType` defines a logical collection:
351
+
352
+ ```ts
353
+ const Post = new ContentType({
354
+ name: "Post",
355
+ menu: {
356
+ title: "Posts",
357
+ icon: "newspaper",
358
+ category: "Content",
359
+ },
360
+ fields: {
361
+ title: f.string().required(),
362
+ slug: f.string().type("Slug").required(),
363
+ body: f.string().type("RichText"),
364
+ published: f.boolean(),
365
+ },
366
+ uniques: [["slug"]],
367
+ listFields: ["title", "slug", "published"],
368
+ });
369
+ ```
370
+
371
+ Page-like content types can define ordered page modules with `iterator` outside
372
+ `fields`. Rakun persists this generated field as `_iterator`:
373
+
374
+ ```ts
375
+ const Page = new ContentType({
376
+ name: "Page",
377
+ fields: {
378
+ title: f.string().required(),
379
+ slug: f.string().type("Slug").required(),
380
+ },
381
+ iterator: [{ contentType: PageSection, type: "existing" }],
382
+ linkedIterator: true,
383
+ });
384
+ ```
385
+
386
+ Set `linkedIterator: true` when every document should use one shared module
387
+ structure. The manager stores a canonical iterator for the content type, while
388
+ dynamic bindings such as `Current document` continue to resolve against the
389
+ individual page being rendered. Documents are linked by default and can be
390
+ unlinked in the manager to keep a local copy of the iterator.
391
+
392
+ Iterator modules can also be made conditional from the manager. A condition is
393
+ stored on the shared module entry and evaluated against the current document:
394
+
395
+ ```ts
396
+ {
397
+ name: "Credits",
398
+ value: { /* module relation */ },
399
+ visibleWhen: {
400
+ field: "credits",
401
+ operator: "notEmpty",
402
+ },
403
+ }
404
+ ```
405
+
406
+ Supported operators are `notEmpty` and `empty`. Conditional modules remain part
407
+ of the shared structure but are omitted from web and preview output when their
408
+ condition does not match.
409
+
410
+ Main properties:
411
+
412
+ - `name`: stable type name. Also used as `_type`.
413
+ - `fields`: field map.
414
+ - `iterator`: page module entries. Generates the reserved `_iterator` field.
415
+ - `linkedIterator`: shares that iterator between documents while allowing
416
+ explicit per-document overrides.
417
+ - `menu`: manager metadata.
418
+ - `uniques`: unique field groups.
419
+ - `listFields`: preferred fields in lists and relations.
420
+ - `hideFromManager()`: hides the content type from manager content type lists.
421
+ - `apiOnly()`: applies `.apiOnly()` to every field in the content type.
422
+ - `managerOnly()`: applies `.managerOnly()` to every field in the content type.
423
+ - Saved manager documents support comments and user mentions by default.
424
+ - `withHooks()`: attaches lifecycle hooks such as `beforeInsert`, `beforeUpdate`, and `onGet`.
425
+ - Dynamic data bindings are available on manager-visible fields by default; use
426
+ field-level `.noDynamic()` to opt out.
427
+
428
+ When a content type has a configured route with `hasPage: true`, Rakun also
429
+ adds an optional reserved `_seo` relation automatically.
430
+
431
+ Hooks run around DB mutations and public output resolution:
432
+
433
+ ```ts
434
+ const User = new ContentType({
435
+ name: "User",
436
+ fields: {
437
+ email: f.string().type("Email").required(),
438
+ password: f.string().type("Password").required().managerOnly(),
439
+ },
440
+ }).withHooks({
441
+ beforeInsert: ({ data }) => ({
442
+ ...data,
443
+ password: hashPassword(String(data.password)),
444
+ }),
445
+ onGet: ({ data }) => ({
446
+ ...data,
447
+ displayName: String(data.email).split("@")[0],
448
+ }),
449
+ });
450
+ ```
451
+
452
+ Dynamic data turns a content type into a reusable layout. The manager can bind
453
+ manager-visible fields to another content item field, or to a generated `href`
454
+ when a source content type has a page route. Fields are dynamic by default; call
455
+ `.noDynamic()` on fields that should not accept bindings or be exported as
456
+ source paths. Source content types are hidden by default; set
457
+ `dynamicDataSource: true` on content types that should appear in the manager
458
+ source selector. Field bindings can also select `Current document` to read values
459
+ from the document being edited without marking its content type as a source.
460
+
461
+ Source field selectors are type-aware. A string target only offers string-like
462
+ source paths, number targets only offer numbers, and boolean targets only offer
463
+ booleans. Object-like source fields are traversed so nested leaf fields can be
464
+ selected, while reserved SEO metadata is omitted from dynamic data mappings.
465
+ The generated `href` source is only shown for content types that have a
466
+ configured route with `hasPage: true`.
467
+
468
+ ```ts
469
+ const Project = new ContentType({
470
+ name: "Project",
471
+ dynamicDataSource: true,
472
+ fields: {
473
+ title: f.string().required(),
474
+ slug: f.string().type("Slug").required(),
475
+ },
476
+ });
477
+
478
+ const Carousel = new ContentType({
479
+ name: "Carousel",
480
+ fields: {
481
+ title: f.string().required(),
482
+ internalNote: f.string().noDynamic(),
483
+ items: f.blocks([
484
+ {
485
+ name: "CarouselItem",
486
+ field: f.relation(CarouselItem, "new"),
487
+ },
488
+ ]),
489
+ },
490
+ });
491
+ ```
492
+
493
+ List bindings append dynamic items to manually stored items instead of replacing
494
+ the list. If the same stable item id appears in both sources, the dynamically
495
+ resolved item wins and the duplicate manual copy is skipped.
496
+
497
+ A list inside a nested module can also use a compatible relation or blocks array
498
+ from the current document. The manager exposes these sources as
499
+ `Current document · <field>`, infers the content type of each array item, and
500
+ lets each item be mapped with the same field mapping UI used for collections.
501
+ These bindings store a `currentDocument` source alongside the inferred item
502
+ content type:
503
+
504
+ ```ts
505
+ const headerBindings = {
506
+ lists: {
507
+ categories: {
508
+ contentType: LinkItem.name,
509
+ source: {
510
+ kind: "currentDocument",
511
+ contentType: Project.name,
512
+ path: "categories",
513
+ itemName: "Category",
514
+ },
515
+ itemName: "Category",
516
+ map: {
517
+ title: { contentType: LinkItem.name, path: "title" },
518
+ href: { contentType: LinkItem.name, path: "href" },
519
+ },
520
+ },
521
+ },
522
+ };
523
+ ```
524
+
525
+ List query conditions can compare a source field with a value from the current
526
+ document. The manager exposes this as `Current document`; programmatic bindings
527
+ use `{ $current: "path.to.field" }`. For example, a category can query only the
528
+ projects whose related category has the same slug:
529
+
530
+ ```ts
531
+ query: {
532
+ filter: {
533
+ "category.slug": { $current: "slug" },
534
+ },
535
+ options: { limit: 10 },
536
+ }
537
+ ```
538
+
539
+ Current-document paths are checked against the content type's dynamic field
540
+ rules before the query runs. `_id` is also available for relation queries.
541
+
542
+ A list mapping can also collect an array through a reverse relation without
543
+ persisting that relation on the source document. For example, a category gallery
544
+ can create one item per `Category` and collect the images of its related
545
+ `Project` documents:
546
+
547
+ ```ts
548
+ const Category = new ContentType({
549
+ name: "Category",
550
+ dynamicDataSource: true,
551
+ fields: {
552
+ title: f.string().required(),
553
+ },
554
+ });
555
+
556
+ const Project = new ContentType({
557
+ name: "Project",
558
+ dynamicDataSource: true,
559
+ fields: {
560
+ category: f.relation(Category, "existing").required(),
561
+ images: f.file().type("Image").multiple().required(),
562
+ },
563
+ });
564
+
565
+ const galleryBindings = {
566
+ lists: {
567
+ items: {
568
+ contentType: Category.name,
569
+ itemName: "CategoriesGalleryItem",
570
+ map: {
571
+ title: { contentType: Category.name, path: "title" },
572
+ images: {
573
+ kind: "relatedCollection",
574
+ contentType: Project.name,
575
+ relation: "category",
576
+ path: "images",
577
+ limit: 10,
578
+ },
579
+ },
580
+ },
581
+ },
582
+ };
583
+ ```
584
+
585
+ The related collection query matches `Project.category._id` against the current
586
+ category, preserves project and image order, and flattens the selected array by
587
+ one level. Its numeric limit applies to related projects and is capped at 100.
588
+
589
+ Schema and validation methods:
590
+
591
+ - `getInputSchema()`: write schema. Includes `_type`, `createdBy`, and `updatedBy`.
592
+ - `getSchema()`: persisted schema.
593
+ - `getPopulatedSchema()`: output with populated relations and `_id`.
594
+ - `getOutputSchema()`: public API output.
595
+ - `getOutputSchemaWithoutIterators()`: output variant without iterator fields.
596
+ - `validate`, `partialValidate`, `validateOutput`: Zod helpers.
597
+
598
+ The registry lives in `lib/Registry`:
599
+
600
+ - `registerContentType`, `registerInternalContentType`.
601
+ - `getContentTypes`, `getExternalContentTypes`, `getInternalContentTypes`.
602
+ - `getContentTypesForManager`: returns serializable content types without Zod schemas and without content types marked with `hideFromManager()`.
603
+ - `getContentTypeByName`.
604
+
605
+ ## Fields
606
+
607
+ Use the concise `f` namespace for field factories. `Fields` remains exported as
608
+ a backward-compatible alias and references the same object.
609
+
610
+ Main factories:
611
+
612
+ ```ts
613
+ f.string();
614
+ f.number();
615
+ f.boolean();
616
+ f.date();
617
+ f.select(["draft", "published"]);
618
+ f.relation(Post);
619
+ f.contentReference("Post");
620
+ f.selfRelation();
621
+ f.blocks([{ name: "title", field: f.string() }]);
622
+ f.array(f.string());
623
+ f.link();
624
+ f.file();
625
+ ```
626
+
627
+ Common modifiers:
628
+
629
+ - `.required()`: marks field as required.
630
+ - `.translatable()`: stores values per language with shape `{ _tag: "Translatable", ... }`.
631
+ - `.apiOnly()`: available for API/persistence, hidden from manager.
632
+ - `.managerOnly()`: visible to manager, excluded from API output.
633
+
634
+ Notable fields:
635
+
636
+ - `StringField`: UI `Text`, `Textarea`, `RichText`, `Email`, `Slug`, `Password`, `Id`, `Url`; supports `.min()` and `.max()`.
637
+ - `NumberField`: supports `.min()` and `.max()`.
638
+ - `RelationField`: relation to another `ContentType`; accepts existing references or inline creation. `f.relation(Post, "existing")` restricts to existing records; `"new"` restricts to new records. `.multiple()` returns a homogeneous array of relations.
639
+ - `ContentReferenceField`: reference by content type name.
640
+ - `LinkField`: `f.link()` stores either a direct URL string or an internal
641
+ `{ routeId, contentTypeId }` reference. Internal references resolve to localized
642
+ paths in web output; direct URLs pass through unchanged.
643
+ - `FileField`: integrates media and optimization options.
644
+ - `f.blocks(...)`: heterogeneous ordered list. Each item stores a `name` and a `value`, and the value can match one of the named field shapes. Use it for block-like content where different item types can appear in the same list.
645
+ - `f.array(...)`: homogeneous ordered list. Every item uses the same field shape. Multi-value fields such as relation `.multiple()` use this backing model.
646
+ - `IteratorField`: repeatable structure based on content type entries.
647
+
648
+ ## Derived Types
649
+
650
+ `@rakun-kit/core/types` and `lib/types` derive types from `ContentType`:
651
+
652
+ - `DataInput<T>`: accepted shape for create/update.
653
+ - `DBOutput<T>`: persisted shape with metadata (`_id`, `_type`, timestamps, authorship).
654
+ - `DataPopulated<T>`: shape with populated relations.
655
+ - `DataFront<T>`: public output without `apiOnly` fields.
656
+ - `Filter<T>`, `Query<T>`, `ListInput<T>`, `GetAllInput<T>`: typed filters and list inputs.
657
+ - `MaybeTranslatableValue<T>`, `TranslatableValue<T>`.
658
+
659
+ ## ORM and Mongo
660
+
661
+ `core/src/orm` implements `DBService` on top of MongoDB:
662
+
663
+ ```ts
664
+ const db = await getMongoService();
665
+
666
+ const post = await db.create(Post, {
667
+ _type: "Post",
668
+ title: "Hello",
669
+ slug: "hello",
670
+ });
671
+ ```
672
+
673
+ Operations:
674
+
675
+ - `get(contentType, id, fields?)`
676
+ - `list(contentType, query)`
677
+ - `create(contentType, data)`
678
+ - `update(contentType, id, data)`
679
+ - `updateMany(contentType, filter, data)`
680
+ - `delete(contentType, filter)`
681
+ - `find(contentType, filter, fields?)`
682
+ - `clear(contentType)`
683
+ - `findDependencies(contentType, id)`
684
+ - `upsert(contentType, filter, data)`
685
+ - `getAll(contentType, query?)`
686
+
687
+ Connection:
688
+
689
+ - `createMongoConnection(config)`: stores config.
690
+ - `createMongoService(config)`: connects and creates handlers.
691
+ - `getMongoService()`: returns the singleton or creates it from config.
692
+ - `closeMongoService()`: closes the connection and clears the singleton.
693
+
694
+ `MongoConfig`:
695
+
696
+ ```ts
697
+ type MongoConfig = {
698
+ MONGO_URI: string;
699
+ ENVIRONMENT?: "local" | "development" | "test" | "production";
700
+ };
701
+ ```
702
+
703
+ In environments other than `test`, the connection creates indexes defined by `createIndexes`.
704
+
705
+ ## API Operations
706
+
707
+ `api/operations` defines typed contracts and handlers for endpoints:
708
+
709
+ - Manager: CRUD, auth, MFA, media, literals, settings.
710
+ - Manager comments and mentions: `manager.comments.list`,
711
+ `manager.comments.create`, `manager.comments.toggleReaction`,
712
+ `manager.comments.markRead`, `manager.comments.unreadCount`,
713
+ `manager.users.mentions`,
714
+ `manager.notifications.list`, and `manager.notifications.markRead`.
715
+ - Web: page resolution.
716
+
717
+ Main helpers:
718
+
719
+ - `defineOperationContract`: declares a contract with Zod input/output, method, path, and metadata.
720
+ - `defineOperation`: combines a contract with its implementation.
721
+ - `createRakunApiClient`: creates a browser/server HTTP client for custom operations.
722
+ - `GetClient`: derives a typed client from an operation map.
723
+ - `createManagerOperationContracts`, `createWebOperationContracts`.
724
+ - `createManagerOperationDefinitions`, `createWebOperationDefinitions`.
725
+ - `createRakunOperationDefinitions`: combines manager + web.
726
+ - `createOperationManifest`: serializable metadata for clients.
727
+ - `createOperationPath`: HTTP path from operation name.
728
+ - `mergeOperationContracts`: combines maps.
729
+
730
+ `@rakun-kit/core/manager` exposes the manifest and name-based types:
731
+
732
+ ```ts
733
+ import {
734
+ managerOperationManifest,
735
+ getManagerOperationMeta,
736
+ type ManagerOperationInput,
737
+ type ManagerOperationOutput,
738
+ } from "@rakun-kit/core/manager";
739
+ ```
740
+
741
+ ### Custom Operations
742
+
743
+ Applications can define operations in a separate object, pass that object to
744
+ bootstrap, and reuse its type on the frontend:
745
+
746
+ ```ts
747
+ // server/api-operations.ts
748
+ import { defineOperation } from "@rakun-kit/core";
749
+ import { z } from "zod";
750
+
751
+ export const apiOperations = {
752
+ "demo.helloWorld": defineOperation<
753
+ { text: string },
754
+ { message: string },
755
+ "query",
756
+ "get",
757
+ "public"
758
+ >({
759
+ access: "public",
760
+ kind: "query",
761
+ method: "get",
762
+ description: "Return a hello world message with the provided text",
763
+ input: z.object({
764
+ text: z.string().default("world"),
765
+ }),
766
+ output: z.object({
767
+ message: z.string(),
768
+ }),
769
+ resolve: ({ input }) => ({
770
+ message: `Hello ${input.text}`,
771
+ }),
772
+ }),
773
+ };
774
+ ```
775
+
776
+ ```ts
777
+ // bootstrap
778
+ import { apiOperations } from "./server/api-operations";
779
+
780
+ rakunBootstrap({
781
+ // ...
782
+ apiOperations,
783
+ });
784
+ ```
785
+
786
+ Operation names define their HTTP path: `demo.helloWorld` becomes
787
+ `/demo/helloWorld`.
788
+
789
+ Rules:
790
+
791
+ - Names must not collide with built-in operations.
792
+ - Operations prefixed with `manager.` are included in manager operation routers.
793
+ - Operations prefixed with `web.` are included in web operation routers.
794
+ - Operations with any other prefix are included when using the combined operation registry.
795
+ - Use `access: "public"` for operations called from public web pages.
796
+ - Use `access: "auth"` for operations that require a manager session.
797
+
798
+ The manager route `manager.apiOperations` returns a JSON-serializable operation
799
+ catalog for manager API docs/playgrounds. Input and output Zod schemas are
800
+ converted to JSON Schema for display.
801
+
802
+ ### Typed API Client
803
+
804
+ `@rakun-kit/core/web` exposes a small typed HTTP client for operation maps:
805
+
806
+ ```ts
807
+ import { createRakunApiClient, type GetClient } from "@rakun-kit/core/web";
808
+ import type { apiOperations } from "./server/api-operations";
809
+
810
+ type ApiClient = GetClient<typeof apiOperations>;
811
+
812
+ const client: ApiClient = createRakunApiClient<typeof apiOperations>({
813
+ baseUrl: "/api",
814
+ });
815
+
816
+ const result = await client.query("demo.helloWorld", {
817
+ text: "Rakun",
818
+ });
819
+
820
+ result.message;
821
+ ```
822
+
823
+ The client exposes:
824
+
825
+ - `query(name, input?, options?)`: only accepts operations with `kind: "query"`.
826
+ - `mutation(name, input?, options?)`: only accepts operations with `kind: "mutation"`.
827
+
828
+ The client derives input and output types from the Zod schemas in
829
+ `apiOperations`.
830
+
831
+ ## Request Context and Auth
832
+
833
+ `createRequestContext(input)` normalizes headers, cookies, and response:
834
+
835
+ ```ts
836
+ const ctx = await createRequestContext({
837
+ headers: req.headers,
838
+ cookies,
839
+ res: {
840
+ setHeader: res.setHeader.bind(res),
841
+ cookie: res.cookie.bind(res),
842
+ },
843
+ });
844
+ ```
845
+
846
+ The resulting context includes:
847
+
848
+ - `req.headers`, `req.cookies`
849
+ - `res.setHeader`, `res.cookie`
850
+ - `user`: manager user or `null`
851
+ - `getUser()`: returns the user or throws `AUTH_REQUIRED`
852
+
853
+ Session cookies are managed with `getSessionCookie` and `setSessionCookie`.
854
+
855
+ ## Media
856
+
857
+ Media uses a storage adapter:
858
+
859
+ ```ts
860
+ createMediaService({
861
+ adapter,
862
+ defaultAccess: "private",
863
+ defaultGetExpiresInSeconds: 300,
864
+ uploadUrl: "/api/rakun/manager/media/upload",
865
+ });
866
+ ```
867
+
868
+ APIs:
869
+
870
+ - `createMediaConnection(config)`: stores config without creating the service.
871
+ - `createMediaService(config)`: creates the singleton with an adapter.
872
+ - `getMediaService()`: returns the singleton or creates it from config.
873
+ - `handleMediaBinaryUpload`: processes manager binary uploads.
874
+
875
+ The service supports prepare/finalize upload, URL generation, folders, and image optimization depending on adapter/configuration.
876
+
877
+ ## Persistent Event Log
878
+
879
+ Rakun keeps business/audit events separate from its technical console logger.
880
+ The event log keeps events immutable and defaults to a MongoDB collection
881
+ with indexes for time, type, category, outcome, severity, correlation and tags:
882
+
883
+ ```ts
884
+ import { recordEvent, queryEvents } from "@rakun-kit/core";
885
+
886
+ await recordEvent({
887
+ type: "content.article.published",
888
+ category: "content",
889
+ outcome: "success",
890
+ actor: { type: "manager-user", id: userId },
891
+ resource: { type: "Article", id: articleId },
892
+ correlationId: requestId,
893
+ tags: ["editorial"],
894
+ data: {
895
+ locale: "es",
896
+ changedFields: 3,
897
+ },
898
+ });
899
+
900
+ const page = await queryEvents({
901
+ categories: ["content"],
902
+ outcomes: ["success"],
903
+ from: new Date("2026-01-01T00:00:00.000Z"),
904
+ limit: 50,
905
+ });
906
+ ```
907
+
908
+ `data` accepts nested JSON values. Event queries use cursor pagination and can
909
+ filter by types, categories, severities, outcomes, sources, correlation,
910
+ required tags and a date range. A custom persistence implementation can be
911
+ plugged in globally:
912
+
913
+ ```ts
914
+ import type { EventLogAdapter } from "@rakun-kit/core";
915
+
916
+ const adapter: EventLogAdapter = {
917
+ async append(event) {
918
+ return customStore.append(event);
919
+ },
920
+ async query(filters) {
921
+ return customStore.query(filters);
922
+ },
923
+ async deleteBefore(before) {
924
+ return customStore.deleteBefore(before);
925
+ },
926
+ };
927
+
928
+ rakunBootstrap({
929
+ // ...
930
+ eventLog: { adapter },
931
+ });
932
+ ```
933
+
934
+ Plugins receive the resolved `eventLog` service in their initialization
935
+ context. Reading a shared event stream should be protected with the built-in
936
+ `system.eventLog.read` permission. The built-in `manager.logs.list` operation and the
937
+ manager Settings → Logs screen both enforce it.
938
+
939
+ Retention cleanup is available from the manager Logs screen to users with the
940
+ built-in `system.eventLog.manage` permission. It deletes events strictly older
941
+ than the selected cutoff. Custom adapters must implement `deleteBefore` to
942
+ support this action. The cleanup mutation itself is logged after deletion.
943
+
944
+ Failed API operations are persisted automatically as `api.operation.failed`
945
+ events. This includes expected 4xx application errors and unexpected 5xx
946
+ failures across the core operation wrapper and the Express, Next.js, and tRPC
947
+ adapters. Events include the operation, status, method, kind, correlation ID,
948
+ and authenticated actor when available. Request payloads, application error
949
+ causes, and raw internal error messages are not persisted.
950
+
951
+ Every successful API mutation is also persisted with an operation-specific
952
+ event type such as `manager.create.succeeded` or
953
+ `manager.backups.restore.succeeded`. Successful queries are not recorded by
954
+ default, which keeps the event stream focused on state changes. Mutation
955
+ events contain operation metadata and actor/correlation context, but never
956
+ copy the input payload or result.
957
+
958
+ ## Mail
959
+
960
+ Mail providers receive normalized, already-rendered messages through
961
+ `MailAdapter`, so neither `core` nor an adapter depends on React or a template
962
+ engine:
963
+
964
+ ```ts
965
+ import type { MailAdapter } from "@rakun-kit/core";
966
+
967
+ const adapter: MailAdapter = {
968
+ async send(message) {
969
+ const result = await provider.send(message);
970
+ return { id: result.id };
971
+ },
972
+ };
973
+
974
+ rakunBootstrap({
975
+ // ...
976
+ mail: {
977
+ adapter,
978
+ defaultFrom: "hello@example.com",
979
+ defaultReplyTo: "support@example.com",
980
+ },
981
+ });
982
+ ```
983
+
984
+ Send rendered content directly:
985
+
986
+ ```ts
987
+ import { sendMail } from "@rakun-kit/core";
988
+
989
+ await sendMail({
990
+ to: "ada@example.com",
991
+ subject: "Welcome",
992
+ html: "<p>Hello Ada</p>",
993
+ text: "Hello Ada",
994
+ });
995
+ ```
996
+
997
+ Or create a typed application template registry:
998
+
999
+ ```ts
1000
+ import { createMailSender, defineMailTemplate } from "@rakun-kit/core";
1001
+
1002
+ const mail = createMailSender({
1003
+ templates: {
1004
+ welcome: defineMailTemplate<{ name: string }>({
1005
+ subject: ({ name }) => `Welcome, ${name}`,
1006
+ render: ({ name }) => ({
1007
+ html: `<p>Hello ${name}</p>`,
1008
+ text: `Hello ${name}`,
1009
+ }),
1010
+ }),
1011
+ },
1012
+ });
1013
+
1014
+ await mail.send({
1015
+ template: "welcome",
1016
+ props: { name: "Ada" },
1017
+ to: "ada@example.com",
1018
+ });
1019
+ ```
1020
+
1021
+ The common contract supports To/CC/BCC/Reply-To, custom headers and in-memory
1022
+ `Uint8Array` attachments. Sending is immediate; queues, retries and delivery
1023
+ events belong to application infrastructure.
1024
+
1025
+ Every mail sent through a bootstrapped Rakun mail service creates append-only
1026
+ `mail.send.attempted` and `mail.send.succeeded` or `mail.send.failed` events.
1027
+ They share a correlation id and include only operational counts, provider,
1028
+ template and duration. Recipient addresses, subject, HTML/text, headers,
1029
+ attachment names/content, credentials and raw provider errors are never copied
1030
+ to the persistent event log. If the initial attempt event cannot be persisted,
1031
+ the provider is not called.
1032
+
1033
+ ## Literals and Translation
1034
+
1035
+ Bootstrap receives `literals`. Related utilities:
1036
+
1037
+ - `getTranslation`: resolves translatable values.
1038
+ - `translateObject`: translates objects with translatable fields.
1039
+ - Manager schemas for listing/upserting website literals (not manager UI chrome).
1040
+
1041
+ Translatable values use this shape:
1042
+
1043
+ ```ts
1044
+ {
1045
+ _tag: "Translatable",
1046
+ en: "Title",
1047
+ es: "Titulo"
1048
+ }
1049
+ ```
1050
+
1051
+ ## Permissions
1052
+
1053
+ `lib/Permissions` exposes:
1054
+
1055
+ - `getPermissionList`: generates a permission list.
1056
+ - `hasPermissions`: validates user/role permissions.
1057
+ - `mapPermissions`: transforms permissions.
1058
+ - `Permission`: public type.
1059
+
1060
+ Manager routes apply permissions, ownership, and auth through utilities in `api/utils`.
1061
+
1062
+ ## Errors
1063
+
1064
+ Application errors live in `lib/errors`:
1065
+
1066
+ - `AppError`
1067
+ - `throwAppError`
1068
+ - `errors`
1069
+ - `instanceofAppErrorShape`
1070
+
1071
+ Database errors live in `orm/dbService`:
1072
+
1073
+ - `DbError`
1074
+ - `DbErrorUnknown`
1075
+ - `DbErrorNotFound`
1076
+ - `DbErrorInvalidData`
1077
+ - `DbErrorConflict`
1078
+ - `DbErrorSimulatedFailure`
1079
+
1080
+ ## Runtime Flow
1081
+
1082
+ 1. The app defines content types with `ContentType` and `f`.
1083
+ 2. The app calls `rakunBootstrap(options)`.
1084
+ 3. The HTTP adapter calls `ensureRakunInitialized()` before serving Rakun routes.
1085
+ 4. `ensureRakunInitialized()` configures logger, MongoDB, the persistent event
1086
+ log, media, mail, and route syncing.
1087
+ 5. Each request creates a `RakunRequestContext`.
1088
+ 6. Manager/web operations validate input, run logic, validate output, and return typed contracts.
1089
+
1090
+ ## Tests and Development Notes
1091
+
1092
+ The package includes targeted tests next to modules (`*.test.ts`), for example ORM, translation, routes, redirects, and populated relations.
1093
+
1094
+ Package build:
1095
+
1096
+ ```sh
1097
+ bun run build --workspace @rakun-kit/core
1098
+ ```
1099
+
1100
+ The script generates ESM and CJS in `dist/`, adjusting imports and the CJS `package.json` through repo scripts.