@orthacms/content-server 0.0.0-reserve.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 (396) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/define.d.ts +17 -0
  4. package/dist/define.d.ts.map +1 -0
  5. package/dist/define.js +28 -0
  6. package/dist/index.d.ts +48 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +109 -0
  9. package/dist/lib/collection/define.d.ts +35 -0
  10. package/dist/lib/collection/define.d.ts.map +1 -0
  11. package/dist/lib/collection/define.js +217 -0
  12. package/dist/lib/collection/table-builder.d.ts +28 -0
  13. package/dist/lib/collection/table-builder.d.ts.map +1 -0
  14. package/dist/lib/collection/table-builder.js +306 -0
  15. package/dist/lib/content-types/controllers/get-content-schema.controller.d.ts +24 -0
  16. package/dist/lib/content-types/controllers/get-content-schema.controller.d.ts.map +1 -0
  17. package/dist/lib/content-types/controllers/get-content-schema.controller.js +58 -0
  18. package/dist/lib/content-types/controllers/get-filter-fields.controller.d.ts +35 -0
  19. package/dist/lib/content-types/controllers/get-filter-fields.controller.d.ts.map +1 -0
  20. package/dist/lib/content-types/controllers/get-filter-fields.controller.js +74 -0
  21. package/dist/lib/content-types/controllers/list-content-schema.controller.d.ts +15 -0
  22. package/dist/lib/content-types/controllers/list-content-schema.controller.d.ts.map +1 -0
  23. package/dist/lib/content-types/controllers/list-content-schema.controller.js +38 -0
  24. package/dist/lib/content-types/queries/workspace-grants.query.d.ts +25 -0
  25. package/dist/lib/content-types/queries/workspace-grants.query.d.ts.map +1 -0
  26. package/dist/lib/content-types/queries/workspace-grants.query.js +45 -0
  27. package/dist/lib/content.module.d.ts +21 -0
  28. package/dist/lib/content.module.d.ts.map +1 -0
  29. package/dist/lib/content.module.js +264 -0
  30. package/dist/lib/content.tokens.d.ts +5 -0
  31. package/dist/lib/content.tokens.d.ts.map +1 -0
  32. package/dist/lib/content.tokens.js +9 -0
  33. package/dist/lib/copilot/content-tool.provider.d.ts +64 -0
  34. package/dist/lib/copilot/content-tool.provider.d.ts.map +1 -0
  35. package/dist/lib/copilot/content-tool.provider.js +309 -0
  36. package/dist/lib/copilot/diff-snapshots.d.ts +42 -0
  37. package/dist/lib/copilot/diff-snapshots.d.ts.map +1 -0
  38. package/dist/lib/copilot/diff-snapshots.js +77 -0
  39. package/dist/lib/copilot/entry-proposal.applier.d.ts +89 -0
  40. package/dist/lib/copilot/entry-proposal.applier.d.ts.map +1 -0
  41. package/dist/lib/copilot/entry-proposal.applier.js +245 -0
  42. package/dist/lib/copilot/entry-proposal.provider.d.ts +157 -0
  43. package/dist/lib/copilot/entry-proposal.provider.d.ts.map +1 -0
  44. package/dist/lib/copilot/entry-proposal.provider.js +619 -0
  45. package/dist/lib/copilot/filter-schema.d.ts +61 -0
  46. package/dist/lib/copilot/filter-schema.d.ts.map +1 -0
  47. package/dist/lib/copilot/filter-schema.js +139 -0
  48. package/dist/lib/copilot/project-entry.d.ts +23 -0
  49. package/dist/lib/copilot/project-entry.d.ts.map +1 -0
  50. package/dist/lib/copilot/project-entry.js +36 -0
  51. package/dist/lib/copilot/proposal-kinds.d.ts +30 -0
  52. package/dist/lib/copilot/proposal-kinds.d.ts.map +1 -0
  53. package/dist/lib/copilot/proposal-kinds.js +32 -0
  54. package/dist/lib/copilot/revision-tool.provider.d.ts +56 -0
  55. package/dist/lib/copilot/revision-tool.provider.d.ts.map +1 -0
  56. package/dist/lib/copilot/revision-tool.provider.js +215 -0
  57. package/dist/lib/docs/content-schemas.d.ts +34 -0
  58. package/dist/lib/docs/content-schemas.d.ts.map +1 -0
  59. package/dist/lib/docs/content-schemas.js +617 -0
  60. package/dist/lib/docs/describe-content-api.d.ts +22 -0
  61. package/dist/lib/docs/describe-content-api.d.ts.map +1 -0
  62. package/dist/lib/docs/describe-content-api.js +173 -0
  63. package/dist/lib/docs/field-schema.d.ts +28 -0
  64. package/dist/lib/docs/field-schema.d.ts.map +1 -0
  65. package/dist/lib/docs/field-schema.js +214 -0
  66. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts +23 -0
  67. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts.map +1 -0
  68. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.js +77 -0
  69. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts +23 -0
  70. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts.map +1 -0
  71. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.js +66 -0
  72. package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts +43 -0
  73. package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts.map +1 -0
  74. package/dist/lib/entries/application/use-cases/publish-entry.use-case.js +106 -0
  75. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts +30 -0
  76. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts.map +1 -0
  77. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.js +70 -0
  78. package/dist/lib/entries/controllers/bulk-entries.controller.d.ts +26 -0
  79. package/dist/lib/entries/controllers/bulk-entries.controller.d.ts.map +1 -0
  80. package/dist/lib/entries/controllers/create-entry.controller.d.ts +20 -0
  81. package/dist/lib/entries/controllers/create-entry.controller.d.ts.map +1 -0
  82. package/dist/lib/entries/controllers/delete-entry.controller.d.ts +24 -0
  83. package/dist/lib/entries/controllers/delete-entry.controller.d.ts.map +1 -0
  84. package/dist/lib/entries/controllers/get-entry.controller.d.ts +34 -0
  85. package/dist/lib/entries/controllers/get-entry.controller.d.ts.map +1 -0
  86. package/dist/lib/entries/controllers/list-entries.controller.d.ts +20 -0
  87. package/dist/lib/entries/controllers/list-entries.controller.d.ts.map +1 -0
  88. package/dist/lib/entries/controllers/publish-entry.controller.d.ts +19 -0
  89. package/dist/lib/entries/controllers/publish-entry.controller.d.ts.map +1 -0
  90. package/dist/lib/entries/controllers/resolve-type.d.ts +9 -0
  91. package/dist/lib/entries/controllers/resolve-type.d.ts.map +1 -0
  92. package/dist/lib/entries/controllers/update-entry.controller.d.ts +18 -0
  93. package/dist/lib/entries/controllers/update-entry.controller.d.ts.map +1 -0
  94. package/dist/lib/entries/domain/entry-publish-blocked.error.d.ts +13 -0
  95. package/dist/lib/entries/domain/entry-publish-blocked.error.d.ts.map +1 -0
  96. package/dist/lib/entries/domain/entry-publish-blocked.error.js +19 -0
  97. package/dist/lib/entries/domain/entry.d.ts +71 -0
  98. package/dist/lib/entries/domain/entry.d.ts.map +1 -0
  99. package/dist/lib/entries/domain/entry.js +90 -0
  100. package/dist/lib/entries/domain/events/entry-events.d.ts +67 -0
  101. package/dist/lib/entries/domain/events/entry-events.d.ts.map +1 -0
  102. package/dist/lib/entries/domain/events/entry-events.js +100 -0
  103. package/dist/lib/entries/dto/bulk-ids.dto.d.ts +11 -0
  104. package/dist/lib/entries/dto/bulk-ids.dto.d.ts.map +1 -0
  105. package/dist/lib/entries/dto/list-entries-query.dto.d.ts +46 -0
  106. package/dist/lib/entries/dto/list-entries-query.dto.d.ts.map +1 -0
  107. package/dist/lib/entries/dto/relation-delta-map.validator.d.ts +19 -0
  108. package/dist/lib/entries/dto/relation-delta-map.validator.d.ts.map +1 -0
  109. package/dist/lib/entries/dto/save-entry.dto.d.ts +46 -0
  110. package/dist/lib/entries/dto/save-entry.dto.d.ts.map +1 -0
  111. package/dist/lib/entries/entries.constants.d.ts +19 -0
  112. package/dist/lib/entries/entries.constants.d.ts.map +1 -0
  113. package/dist/lib/entries/entries.constants.js +21 -0
  114. package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts +33 -0
  115. package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts.map +1 -0
  116. package/dist/lib/entries/http/controllers/bulk-entries.controller.js +143 -0
  117. package/dist/lib/entries/http/controllers/create-entry.controller.d.ts +21 -0
  118. package/dist/lib/entries/http/controllers/create-entry.controller.d.ts.map +1 -0
  119. package/dist/lib/entries/http/controllers/create-entry.controller.js +52 -0
  120. package/dist/lib/entries/http/controllers/delete-entry.controller.d.ts +25 -0
  121. package/dist/lib/entries/http/controllers/delete-entry.controller.d.ts.map +1 -0
  122. package/dist/lib/entries/http/controllers/delete-entry.controller.js +84 -0
  123. package/dist/lib/entries/http/controllers/get-entry.controller.d.ts +44 -0
  124. package/dist/lib/entries/http/controllers/get-entry.controller.d.ts.map +1 -0
  125. package/dist/lib/entries/http/controllers/get-entry.controller.js +124 -0
  126. package/dist/lib/entries/http/controllers/list-entries.controller.d.ts +20 -0
  127. package/dist/lib/entries/http/controllers/list-entries.controller.d.ts.map +1 -0
  128. package/dist/lib/entries/http/controllers/list-entries.controller.js +52 -0
  129. package/dist/lib/entries/http/controllers/publish-entry.controller.d.ts +22 -0
  130. package/dist/lib/entries/http/controllers/publish-entry.controller.d.ts.map +1 -0
  131. package/dist/lib/entries/http/controllers/publish-entry.controller.js +68 -0
  132. package/dist/lib/entries/http/controllers/resolve-type.d.ts +9 -0
  133. package/dist/lib/entries/http/controllers/resolve-type.d.ts.map +1 -0
  134. package/dist/lib/entries/http/controllers/resolve-type.js +16 -0
  135. package/dist/lib/entries/http/controllers/to-actor.d.ts +13 -0
  136. package/dist/lib/entries/http/controllers/to-actor.d.ts.map +1 -0
  137. package/dist/lib/entries/http/controllers/to-actor.js +15 -0
  138. package/dist/lib/entries/http/controllers/update-entry.controller.d.ts +19 -0
  139. package/dist/lib/entries/http/controllers/update-entry.controller.d.ts.map +1 -0
  140. package/dist/lib/entries/http/controllers/update-entry.controller.js +51 -0
  141. package/dist/lib/entries/http/dto/bulk-ids.dto.d.ts +11 -0
  142. package/dist/lib/entries/http/dto/bulk-ids.dto.d.ts.map +1 -0
  143. package/dist/lib/entries/http/dto/bulk-ids.dto.js +33 -0
  144. package/dist/lib/entries/http/dto/list-entries-query.dto.d.ts +66 -0
  145. package/dist/lib/entries/http/dto/list-entries-query.dto.d.ts.map +1 -0
  146. package/dist/lib/entries/http/dto/list-entries-query.dto.js +192 -0
  147. package/dist/lib/entries/http/dto/relation-delta-map.validator.d.ts +30 -0
  148. package/dist/lib/entries/http/dto/relation-delta-map.validator.d.ts.map +1 -0
  149. package/dist/lib/entries/http/dto/relation-delta-map.validator.js +102 -0
  150. package/dist/lib/entries/http/dto/save-entry.dto.d.ts +48 -0
  151. package/dist/lib/entries/http/dto/save-entry.dto.d.ts.map +1 -0
  152. package/dist/lib/entries/http/dto/save-entry.dto.js +120 -0
  153. package/dist/lib/entries/http/guards/content-grant.guard.d.ts +37 -0
  154. package/dist/lib/entries/http/guards/content-grant.guard.d.ts.map +1 -0
  155. package/dist/lib/entries/http/guards/content-grant.guard.js +67 -0
  156. package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.d.ts +22 -0
  157. package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.d.ts.map +1 -0
  158. package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.js +81 -0
  159. package/dist/lib/entries/infrastructure/persistence/entry-counter.service.d.ts +42 -0
  160. package/dist/lib/entries/infrastructure/persistence/entry-counter.service.d.ts.map +1 -0
  161. package/dist/lib/entries/infrastructure/persistence/entry-counter.service.js +73 -0
  162. package/dist/lib/entries/infrastructure/persistence/entry-row.d.ts +56 -0
  163. package/dist/lib/entries/infrastructure/persistence/entry-row.d.ts.map +1 -0
  164. package/dist/lib/entries/infrastructure/persistence/entry-row.js +185 -0
  165. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts +392 -0
  166. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts.map +1 -0
  167. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.js +1223 -0
  168. package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts +24 -0
  169. package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts.map +1 -0
  170. package/dist/lib/entries/infrastructure/persistence/media-accept.d.ts +23 -0
  171. package/dist/lib/entries/infrastructure/persistence/media-accept.d.ts.map +1 -0
  172. package/dist/lib/entries/infrastructure/persistence/media-accept.js +55 -0
  173. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts +327 -0
  174. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts.map +1 -0
  175. package/dist/lib/entries/infrastructure/persistence/relation-link.service.js +1008 -0
  176. package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.d.ts +19 -0
  177. package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.d.ts.map +1 -0
  178. package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.js +39 -0
  179. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts +64 -0
  180. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts.map +1 -0
  181. package/dist/lib/entries/infrastructure/queries/entries.service.js +202 -0
  182. package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts +40 -0
  183. package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts.map +1 -0
  184. package/dist/lib/entries/infrastructure/queries/entry-filter-surface.d.ts +38 -0
  185. package/dist/lib/entries/infrastructure/queries/entry-filter-surface.d.ts.map +1 -0
  186. package/dist/lib/entries/infrastructure/queries/entry-filter-surface.js +310 -0
  187. package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.d.ts +25 -0
  188. package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.d.ts.map +1 -0
  189. package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.js +51 -0
  190. package/dist/lib/entries/infrastructure/queries/entry-search.d.ts +19 -0
  191. package/dist/lib/entries/infrastructure/queries/entry-search.d.ts.map +1 -0
  192. package/dist/lib/entries/infrastructure/queries/entry-search.js +52 -0
  193. package/dist/lib/entries/infrastructure/queries/media-refs.query.d.ts +21 -0
  194. package/dist/lib/entries/infrastructure/queries/media-refs.query.d.ts.map +1 -0
  195. package/dist/lib/entries/infrastructure/queries/media-refs.query.js +117 -0
  196. package/dist/lib/entries/services/entries.service.d.ts +59 -0
  197. package/dist/lib/entries/services/entries.service.d.ts.map +1 -0
  198. package/dist/lib/entries/services/entry-counter.service.d.ts +31 -0
  199. package/dist/lib/entries/services/entry-counter.service.d.ts.map +1 -0
  200. package/dist/lib/entries/services/entry-filter-schema.d.ts +32 -0
  201. package/dist/lib/entries/services/entry-filter-schema.d.ts.map +1 -0
  202. package/dist/lib/entries/services/entry-row.d.ts +56 -0
  203. package/dist/lib/entries/services/entry-row.d.ts.map +1 -0
  204. package/dist/lib/entries/services/entry-writer.service.d.ts +193 -0
  205. package/dist/lib/entries/services/entry-writer.service.d.ts.map +1 -0
  206. package/dist/lib/entries/services/relation-link.service.d.ts +115 -0
  207. package/dist/lib/entries/services/relation-link.service.d.ts.map +1 -0
  208. package/dist/lib/entries/types/bulk-publish.d.ts +75 -0
  209. package/dist/lib/entries/types/bulk-publish.d.ts.map +1 -0
  210. package/dist/lib/entries/types/bulk-publish.js +22 -0
  211. package/dist/lib/entries/types/entry-list-view.d.ts +205 -0
  212. package/dist/lib/entries/types/entry-list-view.d.ts.map +1 -0
  213. package/dist/lib/entries/types/entry-list-view.js +5 -0
  214. package/dist/lib/entries/types/filter-surface.d.ts +35 -0
  215. package/dist/lib/entries/types/filter-surface.d.ts.map +1 -0
  216. package/dist/lib/entries/types/filter-surface.js +2 -0
  217. package/dist/lib/extension/entry-extension-boot-check.d.ts +16 -0
  218. package/dist/lib/extension/entry-extension-boot-check.d.ts.map +1 -0
  219. package/dist/lib/extension/entry-extension-boot-check.js +42 -0
  220. package/dist/lib/extension/entry-extension.d.ts +225 -0
  221. package/dist/lib/extension/entry-extension.d.ts.map +1 -0
  222. package/dist/lib/extension/entry-extension.js +27 -0
  223. package/dist/lib/extension/media-asset-resolver.d.ts +85 -0
  224. package/dist/lib/extension/media-asset-resolver.d.ts.map +1 -0
  225. package/dist/lib/extension/media-asset-resolver.js +26 -0
  226. package/dist/lib/extension/per-locale-relation.d.ts +18 -0
  227. package/dist/lib/extension/per-locale-relation.d.ts.map +1 -0
  228. package/dist/lib/extension/relation-locale-sync.d.ts +62 -0
  229. package/dist/lib/extension/relation-locale-sync.d.ts.map +1 -0
  230. package/dist/lib/extension/relation-locale-sync.js +88 -0
  231. package/dist/lib/fields/index.d.ts +94 -0
  232. package/dist/lib/fields/index.d.ts.map +1 -0
  233. package/dist/lib/fields/index.js +203 -0
  234. package/dist/lib/insights/http/controllers/content-pipeline.controller.d.ts +16 -0
  235. package/dist/lib/insights/http/controllers/content-pipeline.controller.d.ts.map +1 -0
  236. package/dist/lib/insights/http/controllers/content-pipeline.controller.js +39 -0
  237. package/dist/lib/insights/http/controllers/content-punchcard.controller.d.ts +18 -0
  238. package/dist/lib/insights/http/controllers/content-punchcard.controller.d.ts.map +1 -0
  239. package/dist/lib/insights/http/controllers/content-punchcard.controller.js +42 -0
  240. package/dist/lib/insights/http/controllers/content-stale.controller.d.ts +17 -0
  241. package/dist/lib/insights/http/controllers/content-stale.controller.d.ts.map +1 -0
  242. package/dist/lib/insights/http/controllers/content-stale.controller.js +40 -0
  243. package/dist/lib/insights/http/controllers/content-totals.controller.d.ts +18 -0
  244. package/dist/lib/insights/http/controllers/content-totals.controller.d.ts.map +1 -0
  245. package/dist/lib/insights/http/controllers/content-totals.controller.js +42 -0
  246. package/dist/lib/insights/http/controllers/content-unshipped.controller.d.ts +17 -0
  247. package/dist/lib/insights/http/controllers/content-unshipped.controller.d.ts.map +1 -0
  248. package/dist/lib/insights/http/controllers/content-unshipped.controller.js +40 -0
  249. package/dist/lib/insights/http/controllers/content-velocity.controller.d.ts +17 -0
  250. package/dist/lib/insights/http/controllers/content-velocity.controller.d.ts.map +1 -0
  251. package/dist/lib/insights/http/controllers/content-velocity.controller.js +41 -0
  252. package/dist/lib/insights/http/dto/insights-range-query.dto.d.ts +15 -0
  253. package/dist/lib/insights/http/dto/insights-range-query.dto.d.ts.map +1 -0
  254. package/dist/lib/insights/http/dto/insights-range-query.dto.js +38 -0
  255. package/dist/lib/insights/infrastructure/queries/content-insights.query.d.ts +77 -0
  256. package/dist/lib/insights/infrastructure/queries/content-insights.query.d.ts.map +1 -0
  257. package/dist/lib/insights/infrastructure/queries/content-insights.query.js +380 -0
  258. package/dist/lib/insights/types/content-insights-view.d.ts +134 -0
  259. package/dist/lib/insights/types/content-insights-view.d.ts.map +1 -0
  260. package/dist/lib/insights/types/content-insights-view.js +10 -0
  261. package/dist/lib/mcp/content-tools.provider.d.ts +83 -0
  262. package/dist/lib/mcp/content-tools.provider.d.ts.map +1 -0
  263. package/dist/lib/mcp/content-tools.provider.js +441 -0
  264. package/dist/lib/mcp/tool-input.d.ts +43 -0
  265. package/dist/lib/mcp/tool-input.d.ts.map +1 -0
  266. package/dist/lib/mcp/tool-input.js +117 -0
  267. package/dist/lib/mcp/tool-schemas.d.ts +34 -0
  268. package/dist/lib/mcp/tool-schemas.d.ts.map +1 -0
  269. package/dist/lib/mcp/tool-schemas.js +282 -0
  270. package/dist/lib/public/controllers/get-public-entry.controller.d.ts +26 -0
  271. package/dist/lib/public/controllers/get-public-entry.controller.d.ts.map +1 -0
  272. package/dist/lib/public/controllers/list-public-entries.controller.d.ts +24 -0
  273. package/dist/lib/public/controllers/list-public-entries.controller.d.ts.map +1 -0
  274. package/dist/lib/public/controllers/public-schema.controller.d.ts +18 -0
  275. package/dist/lib/public/controllers/public-schema.controller.d.ts.map +1 -0
  276. package/dist/lib/public-api/http/api-token-request.d.ts +41 -0
  277. package/dist/lib/public-api/http/api-token-request.d.ts.map +1 -0
  278. package/dist/lib/public-api/http/api-token-request.js +2 -0
  279. package/dist/lib/public-api/http/controllers/public-content-types.controller.d.ts +31 -0
  280. package/dist/lib/public-api/http/controllers/public-content-types.controller.d.ts.map +1 -0
  281. package/dist/lib/public-api/http/controllers/public-content-types.controller.js +93 -0
  282. package/dist/lib/public-api/http/controllers/public-entries.controller.d.ts +101 -0
  283. package/dist/lib/public-api/http/controllers/public-entries.controller.d.ts.map +1 -0
  284. package/dist/lib/public-api/http/controllers/public-entries.controller.js +307 -0
  285. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts +76 -0
  286. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts.map +1 -0
  287. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.js +353 -0
  288. package/dist/lib/public-api/http/controllers/resolve-granted-type.d.ts +42 -0
  289. package/dist/lib/public-api/http/controllers/resolve-granted-type.d.ts.map +1 -0
  290. package/dist/lib/public-api/http/controllers/resolve-granted-type.js +25 -0
  291. package/dist/lib/public-api/http/decorators/current-api-token.decorator.d.ts +8 -0
  292. package/dist/lib/public-api/http/decorators/current-api-token.decorator.d.ts.map +1 -0
  293. package/dist/lib/public-api/http/decorators/current-api-token.decorator.js +17 -0
  294. package/dist/lib/public-api/http/dto/public-bulk.dto.d.ts +58 -0
  295. package/dist/lib/public-api/http/dto/public-bulk.dto.d.ts.map +1 -0
  296. package/dist/lib/public-api/http/dto/public-bulk.dto.js +118 -0
  297. package/dist/lib/public-api/http/dto/public-list-entries-query.dto.d.ts +106 -0
  298. package/dist/lib/public-api/http/dto/public-list-entries-query.dto.d.ts.map +1 -0
  299. package/dist/lib/public-api/http/dto/public-list-entries-query.dto.js +297 -0
  300. package/dist/lib/public-api/http/dto/public-save-entry.dto.d.ts +39 -0
  301. package/dist/lib/public-api/http/dto/public-save-entry.dto.d.ts.map +1 -0
  302. package/dist/lib/public-api/http/dto/public-save-entry.dto.js +112 -0
  303. package/dist/lib/public-api/http/guards/api-token-workspace.guard.d.ts +25 -0
  304. package/dist/lib/public-api/http/guards/api-token-workspace.guard.d.ts.map +1 -0
  305. package/dist/lib/public-api/http/guards/api-token-workspace.guard.js +58 -0
  306. package/dist/lib/public-api/http/guards/api-token.guard.d.ts +32 -0
  307. package/dist/lib/public-api/http/guards/api-token.guard.d.ts.map +1 -0
  308. package/dist/lib/public-api/http/guards/api-token.guard.js +92 -0
  309. package/dist/lib/public-api/http/guards/draft-visibility.guard.d.ts +25 -0
  310. package/dist/lib/public-api/http/guards/draft-visibility.guard.d.ts.map +1 -0
  311. package/dist/lib/public-api/http/guards/draft-visibility.guard.js +56 -0
  312. package/dist/lib/public-api/infrastructure/bulk-save-op.d.ts +55 -0
  313. package/dist/lib/public-api/infrastructure/bulk-save-op.d.ts.map +1 -0
  314. package/dist/lib/public-api/infrastructure/bulk-save-op.js +61 -0
  315. package/dist/lib/public-api/infrastructure/field-selection.d.ts +21 -0
  316. package/dist/lib/public-api/infrastructure/field-selection.d.ts.map +1 -0
  317. package/dist/lib/public-api/infrastructure/field-selection.js +72 -0
  318. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts +248 -0
  319. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts.map +1 -0
  320. package/dist/lib/public-api/infrastructure/public-entries.query.js +557 -0
  321. package/dist/lib/public-api/infrastructure/public-entry-row.d.ts +31 -0
  322. package/dist/lib/public-api/infrastructure/public-entry-row.d.ts.map +1 -0
  323. package/dist/lib/public-api/infrastructure/public-entry-row.js +76 -0
  324. package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts +188 -0
  325. package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts.map +1 -0
  326. package/dist/lib/public-api/infrastructure/public-entry-writes.service.js +321 -0
  327. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts +98 -0
  328. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts.map +1 -0
  329. package/dist/lib/public-api/infrastructure/public-expansion.query.js +384 -0
  330. package/dist/lib/public-api/types/public-bulk.d.ts +77 -0
  331. package/dist/lib/public-api/types/public-bulk.d.ts.map +1 -0
  332. package/dist/lib/public-api/types/public-bulk.js +23 -0
  333. package/dist/lib/public-api/types/public-entry.d.ts +97 -0
  334. package/dist/lib/public-api/types/public-entry.d.ts.map +1 -0
  335. package/dist/lib/public-api/types/public-entry.js +8 -0
  336. package/dist/lib/public-api/types/public-expansion.d.ts +92 -0
  337. package/dist/lib/public-api/types/public-expansion.d.ts.map +1 -0
  338. package/dist/lib/public-api/types/public-expansion.js +2 -0
  339. package/dist/lib/registry/content-type-registry.d.ts +103 -0
  340. package/dist/lib/registry/content-type-registry.d.ts.map +1 -0
  341. package/dist/lib/registry/content-type-registry.js +155 -0
  342. package/dist/lib/revisions/application/ports/revision-store.d.ts +71 -0
  343. package/dist/lib/revisions/application/ports/revision-store.d.ts.map +1 -0
  344. package/dist/lib/revisions/application/ports/revision-store.js +9 -0
  345. package/dist/lib/revisions/application/use-cases/publish-revision.use-case.d.ts +40 -0
  346. package/dist/lib/revisions/application/use-cases/publish-revision.use-case.d.ts.map +1 -0
  347. package/dist/lib/revisions/application/use-cases/publish-revision.use-case.js +66 -0
  348. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts +36 -0
  349. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts.map +1 -0
  350. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.js +57 -0
  351. package/dist/lib/revisions/domain/revision-status.d.ts +18 -0
  352. package/dist/lib/revisions/domain/revision-status.d.ts.map +1 -0
  353. package/dist/lib/revisions/domain/revision-status.js +18 -0
  354. package/dist/lib/revisions/domain/revision.d.ts +80 -0
  355. package/dist/lib/revisions/domain/revision.d.ts.map +1 -0
  356. package/dist/lib/revisions/domain/revision.js +84 -0
  357. package/dist/lib/revisions/http/controllers/publish-revision.controller.d.ts +19 -0
  358. package/dist/lib/revisions/http/controllers/publish-revision.controller.d.ts.map +1 -0
  359. package/dist/lib/revisions/http/controllers/publish-revision.controller.js +51 -0
  360. package/dist/lib/revisions/http/controllers/restore-revision.controller.d.ts +17 -0
  361. package/dist/lib/revisions/http/controllers/restore-revision.controller.d.ts.map +1 -0
  362. package/dist/lib/revisions/http/controllers/restore-revision.controller.js +49 -0
  363. package/dist/lib/revisions/http/controllers/revisions.controller.d.ts +20 -0
  364. package/dist/lib/revisions/http/controllers/revisions.controller.d.ts.map +1 -0
  365. package/dist/lib/revisions/http/controllers/revisions.controller.js +76 -0
  366. package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.d.ts +33 -0
  367. package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.d.ts.map +1 -0
  368. package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.js +174 -0
  369. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts +17 -0
  370. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts.map +1 -0
  371. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.js +20 -0
  372. package/dist/lib/revisions/infrastructure/persistence/revision-table.d.ts +228 -0
  373. package/dist/lib/revisions/infrastructure/persistence/revision-table.d.ts.map +1 -0
  374. package/dist/lib/revisions/infrastructure/persistence/revision-table.js +57 -0
  375. package/dist/lib/revisions/infrastructure/queries/revision-refs.query.d.ts +22 -0
  376. package/dist/lib/revisions/infrastructure/queries/revision-refs.query.d.ts.map +1 -0
  377. package/dist/lib/revisions/infrastructure/queries/revision-refs.query.js +66 -0
  378. package/dist/lib/revisions/revisions.constants.d.ts +10 -0
  379. package/dist/lib/revisions/revisions.constants.d.ts.map +1 -0
  380. package/dist/lib/revisions/revisions.constants.js +12 -0
  381. package/dist/lib/revisions/types/revision-view.d.ts +74 -0
  382. package/dist/lib/revisions/types/revision-view.d.ts.map +1 -0
  383. package/dist/lib/revisions/types/revision-view.js +2 -0
  384. package/dist/lib/types/content-type.d.ts +131 -0
  385. package/dist/lib/types/content-type.d.ts.map +1 -0
  386. package/dist/lib/types/content-type.js +28 -0
  387. package/dist/lib/types/fields.d.ts +303 -0
  388. package/dist/lib/types/fields.d.ts.map +1 -0
  389. package/dist/lib/types/fields.js +52 -0
  390. package/dist/lib/utils/content-plugin.d.ts +35 -0
  391. package/dist/lib/utils/content-plugin.d.ts.map +1 -0
  392. package/dist/lib/utils/content-plugin.js +35 -0
  393. package/dist/lib/validation/services/entry-validation.service.d.ts +24 -0
  394. package/dist/lib/validation/services/entry-validation.service.d.ts.map +1 -0
  395. package/dist/lib/validation/services/entry-validation.service.js +35 -0
  396. package/package.json +54 -0
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContentInsightsQuery = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const drizzle_orm_1 = require("drizzle-orm");
7
+ const database_1 = require("@orthacms/database");
8
+ const content_tokens_1 = require("../../../content.tokens");
9
+ const content_type_1 = require("../../../types/content-type");
10
+ const revision_table_1 = require("../../../revisions/infrastructure/persistence/revision-table");
11
+ /** Age boundaries (in days) of the staleness breakdown, freshest first. */
12
+ const STALE_BOUNDS = [
13
+ { id: 'd30', upTo: 30 },
14
+ { id: 'd90', upTo: 90 },
15
+ { id: 'd180', upTo: 180 },
16
+ { id: 'd365', upTo: 365 }
17
+ ];
18
+ /** Sparkline points on the stat tiles — enough to read a shape, no axis. */
19
+ const HISTORY_POINTS = 8;
20
+ /** Reads a generated table's columns by property name. */
21
+ function columnsOf(type) {
22
+ return type.table;
23
+ }
24
+ /**
25
+ * Picks a bucket width for a window.
26
+ *
27
+ * Bounded so a series never returns hundreds of points: a 12-month range grouped
28
+ * by day would be 365 buckets for a sparkline that is 64 pixels wide.
29
+ */
30
+ function granularityFor(days) {
31
+ if (days <= 31)
32
+ return 'day';
33
+ if (days <= 120)
34
+ return 'week';
35
+ return 'month';
36
+ }
37
+ /**
38
+ * The bucket unit as a SQL **literal**, never a bound parameter.
39
+ *
40
+ * This looks like a pointless detour and is load-bearing. Drizzle re-renders a
41
+ * reused `sql` fragment at each call site, so `date_trunc(${granularity}, …)`
42
+ * becomes `$1` in the SELECT and `$4` in the GROUP BY — Postgres then sees two
43
+ * different expressions and rejects the query with "column must appear in the
44
+ * GROUP BY clause". Emitting the unit inline makes the two textually identical,
45
+ * which is what lets it match.
46
+ *
47
+ * Safe to inline because it is not caller data: `Granularity` is a closed union
48
+ * produced only by {@link granularityFor} from a bounded number, and the switch
49
+ * below maps it to a fixed literal rather than interpolating the variable.
50
+ */
51
+ function truncUnit(granularity) {
52
+ switch (granularity) {
53
+ case 'day':
54
+ return (0, drizzle_orm_1.sql) `'day'`;
55
+ case 'week':
56
+ return (0, drizzle_orm_1.sql) `'week'`;
57
+ case 'month':
58
+ return (0, drizzle_orm_1.sql) `'month'`;
59
+ }
60
+ }
61
+ /** The instant a window of `days` starts, relative to now. */
62
+ function windowStart(days) {
63
+ const start = new Date();
64
+ start.setUTCDate(start.getUTCDate() - days);
65
+ return start;
66
+ }
67
+ /**
68
+ * Live read-model for the content Insights widgets.
69
+ *
70
+ * Every figure is aggregated **on demand** from the collection tables rather
71
+ * than folded into a projection. That is a deliberate trade for this stage: the
72
+ * counts are workspace-scoped and hit the existing
73
+ * `(workspace_id, …)` list indexes, so they are cheap at the scale a single
74
+ * workspace's content reaches, and a projection would add a table, migrations
75
+ * and a rebuild path to maintain before anything proved it was needed. The seam
76
+ * to change later is this class alone — the HTTP contract and the widgets don't
77
+ * know where the numbers come from.
78
+ *
79
+ * Each method queries **per content type** and merges in memory. There is no
80
+ * single table to group over: a collection is its own generated
81
+ * `content_<name>` table, so "entries in this workspace" is inherently a fan-out.
82
+ */
83
+ let ContentInsightsQuery = class ContentInsightsQuery {
84
+ db;
85
+ registry;
86
+ constructor(db, registry) {
87
+ this.db = db;
88
+ this.registry = registry;
89
+ }
90
+ /**
91
+ * Restricts a read to one workspace, and to rows that still exist.
92
+ *
93
+ * The soft-delete clause is why this is shared rather than inlined: a
94
+ * tombstoned entry is still a row, and a count that forgets `deleted_at`
95
+ * silently reports deleted content as live — the kind of wrong number a
96
+ * dashboard is believed on.
97
+ */
98
+ scope(type, workspaceId) {
99
+ const columns = columnsOf(type);
100
+ return (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(columns['workspaceId'], workspaceId), type.paranoid ? (0, drizzle_orm_1.isNull)(columns['deletedAt']) : undefined);
101
+ }
102
+ /** Counts rows of one type matching an extra predicate. */
103
+ async countOf(type, workspaceId, extra) {
104
+ const [row] = await this.db
105
+ .select({ n: (0, drizzle_orm_1.sql) `cast(count(*) as int)` })
106
+ .from(type.table)
107
+ .where((0, drizzle_orm_1.and)(this.scope(type, workspaceId), extra));
108
+ return row?.n ?? 0;
109
+ }
110
+ /**
111
+ * Counts rows per time bucket over a window, for one type and one
112
+ * timestamp column. Returns raw buckets — the caller decides whether they
113
+ * are a series or the increments of a cumulative total.
114
+ */
115
+ async bucketed(type, workspaceId, column, days, granularity) {
116
+ const truncated = (0, drizzle_orm_1.sql) `date_trunc(${truncUnit(granularity)}, ${column})`;
117
+ const rows = await this.db
118
+ .select({
119
+ bucket: (0, drizzle_orm_1.sql) `to_char(${truncated}, 'YYYY-MM-DD')`,
120
+ n: (0, drizzle_orm_1.sql) `cast(count(*) as int)`
121
+ })
122
+ .from(type.table)
123
+ .where((0, drizzle_orm_1.and)(this.scope(type, workspaceId), (0, drizzle_orm_1.sql) `${column} >= ${windowStart(days)}`))
124
+ .groupBy(truncated);
125
+ return new Map(rows.map((row) => [row.bucket, row.n]));
126
+ }
127
+ /** Headline counts, deltas and sparkline history for the stat tiles. */
128
+ async totals(workspaceId, days) {
129
+ const types = this.registry.all();
130
+ const granularity = granularityFor(days);
131
+ let entries = 0;
132
+ let published = 0;
133
+ let drafts = 0;
134
+ const createdBuckets = new Map();
135
+ const publishedBuckets = new Map();
136
+ for (const type of types) {
137
+ const columns = columnsOf(type);
138
+ entries += await this.countOf(type, workspaceId);
139
+ // A non-publishable type has no draft stage at all — every row is
140
+ // live. Counting it as "published" is the honest reading; treating
141
+ // it as neither would make the two tiles fail to add up to the total.
142
+ if (type.publishable) {
143
+ published += await this.countOf(type, workspaceId, (0, drizzle_orm_1.eq)(columns['status'], content_type_1.ENTRY_STATUS.Published));
144
+ drafts += await this.countOf(type, workspaceId, (0, drizzle_orm_1.eq)(columns['status'], content_type_1.ENTRY_STATUS.Draft));
145
+ mergeBuckets(publishedBuckets, await this.bucketed(type, workspaceId, columns['publishedAt'], days, granularity));
146
+ }
147
+ else {
148
+ published += await this.countOf(type, workspaceId);
149
+ }
150
+ mergeBuckets(createdBuckets, await this.bucketed(type, workspaceId, columns['createdAt'], days, granularity));
151
+ }
152
+ const entriesDelta = sumOf(createdBuckets);
153
+ const publishedDelta = sumOf(publishedBuckets);
154
+ return {
155
+ entries,
156
+ published,
157
+ drafts,
158
+ entriesDelta,
159
+ publishedDelta,
160
+ entriesHistory: cumulativeFrom(entries - entriesDelta, createdBuckets),
161
+ publishedHistory: cumulativeFrom(published - publishedDelta, publishedBuckets)
162
+ };
163
+ }
164
+ /** Published entries grouped by how long ago they were last edited. */
165
+ async stale(workspaceId) {
166
+ const counts = new Map(STALE_BOUNDS.map((bound) => [bound.id, 0]));
167
+ counts.set('older', 0);
168
+ for (const type of this.registry.all()) {
169
+ const columns = columnsOf(type);
170
+ const updatedAt = columns['updatedAt'];
171
+ // Only live content can be "stale" — an untouched draft is a draft,
172
+ // not a neglected published page, and mixing them would inflate
173
+ // every bucket with work that was never finished in the first place.
174
+ const liveOnly = type.publishable
175
+ ? (0, drizzle_orm_1.eq)(columns['status'], content_type_1.ENTRY_STATUS.Published)
176
+ : undefined;
177
+ const [row] = await this.db
178
+ .select({
179
+ d30: bucketExpression(updatedAt, 0, 30),
180
+ d90: bucketExpression(updatedAt, 30, 90),
181
+ d180: bucketExpression(updatedAt, 90, 180),
182
+ d365: bucketExpression(updatedAt, 180, 365),
183
+ older: (0, drizzle_orm_1.sql) `cast(count(*) filter (
184
+ where ${updatedAt} < now() - make_interval(days => 365)
185
+ ) as int)`
186
+ })
187
+ .from(type.table)
188
+ .where((0, drizzle_orm_1.and)(this.scope(type, workspaceId), liveOnly));
189
+ if (!row)
190
+ continue;
191
+ for (const key of [
192
+ 'd30',
193
+ 'd90',
194
+ 'd180',
195
+ 'd365',
196
+ 'older'
197
+ ]) {
198
+ counts.set(key, (counts.get(key) ?? 0) + (row[key] ?? 0));
199
+ }
200
+ }
201
+ const buckets = [...STALE_BOUNDS.map((b) => b.id), 'older'].map((id) => ({ id, count: counts.get(id) ?? 0 }));
202
+ return {
203
+ buckets,
204
+ total: buckets.reduce((sum, bucket) => sum + bucket.count, 0)
205
+ };
206
+ }
207
+ /** Draft/published split per content type. */
208
+ async pipeline(workspaceId) {
209
+ const types = [];
210
+ for (const type of this.registry.all()) {
211
+ const columns = columnsOf(type);
212
+ const published = type.publishable
213
+ ? await this.countOf(type, workspaceId, (0, drizzle_orm_1.eq)(columns['status'], content_type_1.ENTRY_STATUS.Published))
214
+ : await this.countOf(type, workspaceId);
215
+ const drafts = type.publishable
216
+ ? await this.countOf(type, workspaceId, (0, drizzle_orm_1.eq)(columns['status'], content_type_1.ENTRY_STATUS.Draft))
217
+ : 0;
218
+ // A type the workspace has never used is noise on a chart about
219
+ // where the workspace's weight sits.
220
+ if (published + drafts === 0)
221
+ continue;
222
+ types.push({
223
+ name: type.name,
224
+ label: type.label,
225
+ published,
226
+ drafts
227
+ });
228
+ }
229
+ types.sort((a, b) => b.published + b.drafts - (a.published + a.drafts));
230
+ return { types };
231
+ }
232
+ /**
233
+ * Live content carrying unpublished edits, per type and in total.
234
+ *
235
+ * The three figures come out of **one** grouped query per type rather than
236
+ * three `countOf` calls, because they partition the same rows: a scan that
237
+ * has already found a row can decide which of the three it belongs to.
238
+ *
239
+ * A **non-publishable** type contributes nothing at all — not even to
240
+ * `live`. It has no draft stage, so every row is trivially current, and
241
+ * folding those rows into the denominator would make "3 of 900 live records
242
+ * have pending edits" a number about a workspace's always-live singletons
243
+ * rather than about anything an editor can ship.
244
+ */
245
+ async unshipped(workspaceId) {
246
+ const types = [];
247
+ let modified = 0;
248
+ let live = 0;
249
+ let neverPublished = 0;
250
+ for (const type of this.registry.all()) {
251
+ if (!type.publishable)
252
+ continue;
253
+ const columns = columnsOf(type);
254
+ const status = columns['status'];
255
+ const publishedAt = columns['publishedAt'];
256
+ const [row] = await this.db
257
+ .select({
258
+ modified: (0, drizzle_orm_1.sql) `cast(count(*) filter (
259
+ where ${status} = ${content_type_1.ENTRY_STATUS.Draft}
260
+ and ${publishedAt} is not null
261
+ ) as int)`,
262
+ published: (0, drizzle_orm_1.sql) `cast(count(*) filter (
263
+ where ${status} = ${content_type_1.ENTRY_STATUS.Published}
264
+ ) as int)`,
265
+ neverPublished: (0, drizzle_orm_1.sql) `cast(count(*) filter (
266
+ where ${status} = ${content_type_1.ENTRY_STATUS.Draft}
267
+ and ${publishedAt} is null
268
+ ) as int)`
269
+ })
270
+ .from(type.table)
271
+ .where(this.scope(type, workspaceId));
272
+ if (!row)
273
+ continue;
274
+ modified += row.modified;
275
+ live += row.modified + row.published;
276
+ neverPublished += row.neverPublished;
277
+ // A type with nothing pending is not a row on a chart about what is
278
+ // pending — it would be a permanently empty bar diluting the ones
279
+ // that mean something.
280
+ if (row.modified === 0)
281
+ continue;
282
+ types.push({
283
+ name: type.name,
284
+ label: type.label,
285
+ modified: row.modified,
286
+ published: row.published
287
+ });
288
+ }
289
+ types.sort((a, b) => b.modified - a.modified);
290
+ return { types, modified, live, neverPublished };
291
+ }
292
+ /** Entries published per time bucket across the window. */
293
+ async velocity(workspaceId, days) {
294
+ const granularity = granularityFor(days);
295
+ const merged = new Map();
296
+ for (const type of this.registry.all()) {
297
+ if (!type.publishable)
298
+ continue;
299
+ mergeBuckets(merged, await this.bucketed(type, workspaceId, columnsOf(type)['publishedAt'], days, granularity));
300
+ }
301
+ return { points: toSeries(merged), granularity };
302
+ }
303
+ /**
304
+ * Editing activity by weekday and hour, from the revision store.
305
+ *
306
+ * The one content figure that is a single grouped query rather than a
307
+ * fan-out: `content_entry_revisions` is generic across every type, so the
308
+ * whole workspace's editing history lives in one table.
309
+ *
310
+ * Hours come out in the database session's timezone (UTC in every
311
+ * deployment we run). Rendering them as local time would need each
312
+ * viewer's offset applied to the grouping, not to the labels — shifting
313
+ * the labels alone would silently mislabel the buckets.
314
+ */
315
+ async punchcard(workspaceId, days) {
316
+ const rows = await this.db
317
+ .select({
318
+ weekday: (0, drizzle_orm_1.sql) `cast(extract(isodow from ${revision_table_1.contentEntryRevisions.createdAt}) as int)`,
319
+ hour: (0, drizzle_orm_1.sql) `cast(extract(hour from ${revision_table_1.contentEntryRevisions.createdAt}) as int)`,
320
+ count: (0, drizzle_orm_1.sql) `cast(count(*) as int)`
321
+ })
322
+ .from(revision_table_1.contentEntryRevisions)
323
+ .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(revision_table_1.contentEntryRevisions.workspaceId, workspaceId), (0, drizzle_orm_1.sql) `${revision_table_1.contentEntryRevisions.createdAt} >= ${windowStart(days)}`))
324
+ .groupBy((0, drizzle_orm_1.sql) `extract(isodow from ${revision_table_1.contentEntryRevisions.createdAt})`, (0, drizzle_orm_1.sql) `extract(hour from ${revision_table_1.contentEntryRevisions.createdAt})`);
325
+ return {
326
+ cells: rows,
327
+ max: rows.reduce((peak, row) => Math.max(peak, row.count), 0),
328
+ total: rows.reduce((sum, row) => sum + row.count, 0)
329
+ };
330
+ }
331
+ };
332
+ exports.ContentInsightsQuery = ContentInsightsQuery;
333
+ exports.ContentInsightsQuery = ContentInsightsQuery = tslib_1.__decorate([
334
+ (0, common_1.Injectable)(),
335
+ tslib_1.__param(0, (0, database_1.InjectDatabase)()),
336
+ tslib_1.__param(1, (0, content_tokens_1.InjectContentRegistry)()),
337
+ tslib_1.__metadata("design:paramtypes", [Object, Function])
338
+ ], ContentInsightsQuery);
339
+ /** Counts rows whose timestamp falls in a half-open age window, in days. */
340
+ function bucketExpression(column, fromDays, toDays) {
341
+ return (0, drizzle_orm_1.sql) `cast(count(*) filter (
342
+ where ${column} <= now() - make_interval(days => ${fromDays})
343
+ and ${column} > now() - make_interval(days => ${toDays})
344
+ ) as int)`;
345
+ }
346
+ /** Adds one type's bucket counts into a running total across types. */
347
+ function mergeBuckets(into, from) {
348
+ for (const [bucket, value] of from) {
349
+ into.set(bucket, (into.get(bucket) ?? 0) + value);
350
+ }
351
+ }
352
+ /** Sums every bucket. */
353
+ function sumOf(buckets) {
354
+ let total = 0;
355
+ for (const value of buckets.values())
356
+ total += value;
357
+ return total;
358
+ }
359
+ /** Sorts a bucket map into an ascending series. */
360
+ function toSeries(buckets) {
361
+ return [...buckets.entries()]
362
+ .map(([bucket, value]) => ({ bucket, value }))
363
+ .sort((a, b) => a.bucket.localeCompare(b.bucket));
364
+ }
365
+ /**
366
+ * Turns per-bucket increments into a running total, starting from the count as
367
+ * it stood before the window opened.
368
+ *
369
+ * Trimmed to the last {@link HISTORY_POINTS} so a sparkline gets a readable
370
+ * number of points regardless of the selected range.
371
+ */
372
+ function cumulativeFrom(baseline, buckets) {
373
+ const series = toSeries(buckets);
374
+ let running = Math.max(0, baseline);
375
+ const history = series.map((point) => {
376
+ running += point.value;
377
+ return running;
378
+ });
379
+ return history.slice(-HISTORY_POINTS);
380
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Read-side view shapes for the content Insights widgets.
3
+ *
4
+ * These are **transport contracts**, restated verbatim by `content-admin` (the
5
+ * admin can't import a server package across the module boundary). Every one is
6
+ * derived live from the collection tables — this plugin keeps no projection and
7
+ * owns no insights schema.
8
+ */
9
+ /** A single point on a time series. */
10
+ export interface InsightsSeriesPoint {
11
+ /** Bucket start, `YYYY-MM-DD`. The client formats it. */
12
+ bucket: string;
13
+ /** Measured value for the bucket. */
14
+ value: number;
15
+ }
16
+ /**
17
+ * Headline counts for the stat tiles.
18
+ *
19
+ * `draftsDelta` is deliberately absent while `entriesDelta` and `publishedDelta`
20
+ * are present. A draft's count changes when a row is *published*, and nothing
21
+ * records when that transition happened in reverse — `published_at` tells us
22
+ * when something went live, but a row that moved back to draft leaves no trace
23
+ * on the collection table. Reporting a draft delta would mean inventing one.
24
+ */
25
+ export interface ContentTotalsView {
26
+ /** Every non-deleted entry in the workspace. */
27
+ entries: number;
28
+ /** Entries currently live. */
29
+ published: number;
30
+ /** Entries currently in draft. */
31
+ drafts: number;
32
+ /** Entries created within the window. */
33
+ entriesDelta: number;
34
+ /** Entries first published within the window. */
35
+ publishedDelta: number;
36
+ /** Cumulative entry count across the window, oldest bucket first. */
37
+ entriesHistory: number[];
38
+ /** Cumulative published count across the window, oldest bucket first. */
39
+ publishedHistory: number[];
40
+ }
41
+ /** One age bucket of the staleness breakdown. */
42
+ export interface StaleBucketView {
43
+ /** Bucket key — `d30`, `d90`, `d180`, `d365`, `older`. */
44
+ id: string;
45
+ /** Entries whose last edit falls in this bucket. */
46
+ count: number;
47
+ }
48
+ /** Published entries grouped by how long ago they were last touched. */
49
+ export interface ContentStaleView {
50
+ /** The buckets, freshest first. */
51
+ buckets: StaleBucketView[];
52
+ /** Total across all buckets, so the client needn't re-add them. */
53
+ total: number;
54
+ }
55
+ /** Draft/published split for one content type. */
56
+ export interface PipelineTypeView {
57
+ /** The type's machine name. */
58
+ name: string;
59
+ /** Its human label. */
60
+ label: string;
61
+ /** Entries currently live. */
62
+ published: number;
63
+ /** Entries currently in draft. */
64
+ drafts: number;
65
+ }
66
+ /** Draft/published split across every content type in the workspace. */
67
+ export interface ContentPipelineView {
68
+ /** One row per type that has at least one entry, biggest first. */
69
+ types: PipelineTypeView[];
70
+ }
71
+ /** Entries published per time bucket. */
72
+ export interface ContentVelocityView {
73
+ /** The series, oldest bucket first. */
74
+ points: InsightsSeriesPoint[];
75
+ /** Bucket width, so the client can label the axis correctly. */
76
+ granularity: 'day' | 'week' | 'month';
77
+ }
78
+ /** Live-vs-unpublished-edits split for one content type. */
79
+ export interface UnshippedTypeView {
80
+ /** The type's machine name. */
81
+ name: string;
82
+ /** Its human label. */
83
+ label: string;
84
+ /** Entries live with unpublished edits on top of what is live. */
85
+ modified: number;
86
+ /** Entries live and current — nothing pending. */
87
+ published: number;
88
+ }
89
+ /**
90
+ * Entries whose live version is behind what an editor has saved.
91
+ *
92
+ * The publish state is **two stored values that carry three meanings**, which is
93
+ * the whole reason this endpoint exists: `status` alone cannot separate "never
94
+ * published" from "published, then edited". `published_at` is stamped on the
95
+ * first publish and cleared only by an unpublish, so `draft` + a timestamp is
96
+ * live content with unpublished changes on top — the admin's **Modified** badge
97
+ * — while `draft` + no timestamp is a draft nobody has ever shipped.
98
+ */
99
+ export interface ContentUnshippedView {
100
+ /** One row per publishable type holding at least one modified entry. */
101
+ types: UnshippedTypeView[];
102
+ /** Modified entries across the workspace — live, with edits pending. */
103
+ modified: number;
104
+ /** Entries with a live version at all (`modified` + fully published). */
105
+ live: number;
106
+ /** Drafts that have never gone live. */
107
+ neverPublished: number;
108
+ }
109
+ /** One weekday × hour cell of the editing punchcard. */
110
+ export interface PunchcardCellView {
111
+ /** ISO weekday, 1 = Monday … 7 = Sunday. */
112
+ weekday: number;
113
+ /** Hour of day, 0–23, in the database session's timezone (UTC). */
114
+ hour: number;
115
+ /** Revisions written in that slot. */
116
+ count: number;
117
+ }
118
+ /**
119
+ * Editing activity by weekday and hour.
120
+ *
121
+ * Only non-empty slots are returned — a full 7 × 24 grid is 168 cells and most
122
+ * are zero, so the client fills the gaps. `max` comes with it because the client
123
+ * needs the busiest value to normalise the ramp, and recomputing it from a
124
+ * sparse list would give the wrong denominator whenever the grid is empty.
125
+ */
126
+ export interface ContentPunchcardView {
127
+ /** The non-empty cells. */
128
+ cells: PunchcardCellView[];
129
+ /** The busiest cell's count, or 0 when there is no activity. */
130
+ max: number;
131
+ /** Revisions across the whole window. */
132
+ total: number;
133
+ }
134
+ //# sourceMappingURL=content-insights-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-insights-view.d.ts","sourceRoot":"","sources":["../../../../src/lib/insights/types/content-insights-view.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uCAAuC;AACvC,MAAM,WAAW,mBAAmB;IAChC,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAC9B,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC5B,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC7B,mCAAmC;IACnC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC7B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wEAAwE;AACxE,MAAM,WAAW,mBAAmB;IAChC,mEAAmE;IACnE,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,yCAAyC;AACzC,MAAM,WAAW,mBAAmB;IAChC,uCAAuC;IACvC,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,gEAAgE;IAChE,WAAW,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CACzC;AAED,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAC9B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACjC,wEAAwE;IACxE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAC9B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACjC,2BAA2B;IAC3B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Read-side view shapes for the content Insights widgets.
4
+ *
5
+ * These are **transport contracts**, restated verbatim by `content-admin` (the
6
+ * admin can't import a server package across the module boundary). Every one is
7
+ * derived live from the collection tables — this plugin keeps no projection and
8
+ * owns no insights schema.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,83 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { ToolRegistry, type ResourceContents, type ResourceDefinition, type ToolContext, type ToolDefinition, type ToolProvider } from '@orthacms/tools-server';
3
+ import type { ContentTypeRegistry } from '../registry/content-type-registry';
4
+ import { WorkspaceGrantsQuery } from '../content-types/queries/workspace-grants.query';
5
+ import { PublicEntriesQuery } from '../public-api/infrastructure/public-entries.query';
6
+ import { PublicEntryWritesService } from '../public-api/infrastructure/public-entry-writes.service';
7
+ /**
8
+ * The content plugin's contribution to the shared agent tool registry — the
9
+ * same CRUD the public HTTP API serves, reachable by an MCP client or the
10
+ * copilot's tool loop.
11
+ *
12
+ * **Every handler delegates to the objects the HTTP controllers call**:
13
+ * `resolveGrantedType` for the grant gate, `PublicEntriesQuery` for reads,
14
+ * `PublicEntryWritesService` for writes. That is the whole design. The rules
15
+ * that make the public API safe — published-only by default, soft-deleted rows
16
+ * invisible, an ungranted type indistinguishable from an unknown one, relations
17
+ * that may not cross locales, validation at publish time, revision numbering
18
+ * under an advisory lock, the outbox — are not restated here and therefore
19
+ * cannot drift from the HTTP surface. This class contributes the tool
20
+ * descriptions, argument validation, and the mapping from arguments to those
21
+ * calls, and nothing else.
22
+ *
23
+ * **Authorization is declared, not implemented.** Each tool names the
24
+ * permissions it needs in `requires`, and `ToolRegistry.call` enforces them
25
+ * before dispatch — the analogue of `@RequirePermissions(...)` on a route. A
26
+ * `read`-scoped token cannot reach a write tool, and no handler below contains
27
+ * a line of code saying so. The one authorization decision a handler *does*
28
+ * make is the draft-visibility widening, because it is a rule about an argument
29
+ * rather than about the operation.
30
+ *
31
+ * Registration is `@Optional()`: MCP is a plugin, so a deployment that omits it
32
+ * must still boot. The tools simply go unregistered.
33
+ */
34
+ export declare class ContentToolProvider implements ToolProvider, OnModuleInit {
35
+ private readonly registry;
36
+ private readonly grants;
37
+ private readonly entries;
38
+ private readonly writes;
39
+ private readonly toolRegistry?;
40
+ constructor(registry: ContentTypeRegistry, grants: WorkspaceGrantsQuery, entries: PublicEntriesQuery, writes: PublicEntryWritesService, toolRegistry?: ToolRegistry | undefined);
41
+ /**
42
+ * Register with the tool registry once the DI graph is built. A call rather
43
+ * than a DI binding because Nest has no multi-provider token — see
44
+ * `ToolProvider`.
45
+ */
46
+ onModuleInit(): void;
47
+ /**
48
+ * The sixteen content tools. @see ToolProvider.tools
49
+ *
50
+ * Every one is stamped `surfaces: ['mcp']` below rather than tool by tool:
51
+ * they are uniformly the **public-API** set — published-only reads through
52
+ * `PublicEntriesQuery`, writes through `PublicEntryWritesService` attributed
53
+ * to a token. The copilot's content tools are the admin-scoped counterpart
54
+ * (a viewer must see drafts; a write records the accepting human), so the
55
+ * two sets share the registry and not each other's callers.
56
+ */
57
+ tools(): readonly ToolDefinition[];
58
+ /** The tool definitions themselves, before the surface stamp. */
59
+ private mcpTools;
60
+ /**
61
+ * Each readable content type as a resource, so a client that supports them
62
+ * can pull a schema into context without spending a tool call. Pruned to
63
+ * the workspace's grants, exactly like `content_types_list`.
64
+ */
65
+ resources(context: ToolContext): Promise<readonly ResourceDefinition[]>;
66
+ /** @see ToolProvider.readResource */
67
+ readResource(uri: string, context: ToolContext): Promise<ResourceContents | undefined>;
68
+ /** The workspace's granted type summaries. */
69
+ private grantedSummaries;
70
+ /** Resolve a type through the shared registry + grant gate. */
71
+ private resolve;
72
+ /**
73
+ * One type's serialized schema, plus a JSON Schema for its `values` bag.
74
+ *
75
+ * Both, because they answer different questions: the serialized fields
76
+ * carry the CMS's own vocabulary (which field is a relation, what a select's
77
+ * options are), while the JSON Schema is what a model needs to construct a
78
+ * valid `values` object. `fieldSchema` is the same generator the OpenAPI
79
+ * document uses, so the two descriptions of a type cannot disagree.
80
+ */
81
+ private describeType;
82
+ }
83
+ //# sourceMappingURL=content-tools.provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-tools.provider.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp/content-tools.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,YAAY,EAEf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EACR,mBAAmB,EAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AAEvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,0DAA0D,CAAC;AAoCpG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBACa,mBAAoB,YAAW,YAAY,EAAE,YAAY;IAG9D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAJzB,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,wBAAwB,EACpB,YAAY,CAAC,EAAE,YAAY,YAAA;IAG5D;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAIpB;;;;;;;;;OASG;IACH,KAAK,IAAI,SAAS,cAAc,EAAE;IAOlC,iEAAiE;IACjE,OAAO,CAAC,QAAQ;IA6ZhB;;;;OAIG;IACG,SAAS,CACX,OAAO,EAAE,WAAW,GACrB,OAAO,CAAC,SAAS,kBAAkB,EAAE,CAAC;IAUzC,qCAAqC;IAC/B,YAAY,CACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,GACrB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAgBxC,8CAA8C;YAChC,gBAAgB;IAO9B,+DAA+D;IAC/D,OAAO,CAAC,OAAO;IASf;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;CA6BvB"}