sitero 0.5.0 → 0.7.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 (373) hide show
  1. package/dist/export/cms/client/components/index.js +6 -2
  2. package/dist/export/cms/client/index.js +2 -0
  3. package/dist/export/cms/client/pages/index.js +1 -3
  4. package/dist/export/cms/server/index.js +1 -0
  5. package/dist/export/core/server/index.js +2 -0
  6. package/dist/export/index.js +1 -0
  7. package/dist/export/web/server/index.js +1 -0
  8. package/dist/prisma/generated/internal/class.js +4 -4
  9. package/dist/src/cms/client/applications/create-applications.js +5 -0
  10. package/dist/src/cms/client/applications/resources/page/form-data.js +56 -0
  11. package/dist/src/cms/client/applications/resources/page/use-page-update-form-data.js +30 -0
  12. package/dist/src/cms/client/applications/resources/post/use-create-form-data.js +5 -5
  13. package/dist/src/cms/client/applications/resources/post/use-update-form-data.js +1 -1
  14. package/dist/src/cms/client/applications/resources/seo-metadata/build-seo-metadata-translations.js +35 -0
  15. package/dist/src/cms/client/applications/resources/seo-metadata/use-upsert-form-data.js +15 -31
  16. package/dist/src/cms/client/applications/ui/use-nav-items.js +28 -39
  17. package/dist/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.js +5 -4
  18. package/dist/src/cms/client/infrastructure/i18n/messages/en-US/resources/index.js +7 -0
  19. package/dist/src/cms/client/infrastructure/i18n/messages/en-US/resources/post.js +32 -1
  20. package/dist/src/cms/client/infrastructure/i18n/messages/en-US/ui/index.js +8 -1
  21. package/dist/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.js +6 -5
  22. package/dist/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/index.js +7 -0
  23. package/dist/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/post.js +18 -1
  24. package/dist/src/cms/client/infrastructure/i18n/messages/zh-TW/ui/index.js +7 -2
  25. package/dist/src/cms/client/infrastructure/operation-result/presentation/message.js +15 -0
  26. package/dist/src/cms/client/interfaces/components/create-components.js +4 -8
  27. package/dist/src/cms/client/interfaces/components/create-page-contents.js +28 -0
  28. package/dist/src/cms/client/interfaces/components/resources/page/content/field-groups.js +16 -0
  29. package/dist/src/cms/client/interfaces/components/resources/page/content/page-edit-content.js +216 -0
  30. package/dist/src/cms/client/interfaces/components/resources/page/content/page-show-content.js +114 -0
  31. package/dist/src/cms/client/interfaces/components/resources/page/content/types.js +12 -0
  32. package/dist/src/cms/client/interfaces/components/resources/post/category/category-card.js +5 -3
  33. package/dist/src/cms/client/interfaces/components/resources/post/category/category-table.js +6 -4
  34. package/dist/src/cms/client/interfaces/components/resources/post/content/post-create-content.js +13 -8
  35. package/dist/src/cms/client/interfaces/components/resources/post/content/post-edit-content.js +11 -7
  36. package/dist/src/cms/client/interfaces/components/resources/post/content/post-show-content.js +7 -2
  37. package/dist/src/cms/client/interfaces/components/resources/post/post-card.js +5 -3
  38. package/dist/src/cms/client/interfaces/components/resources/post/post-list.js +45 -10
  39. package/dist/src/cms/client/interfaces/components/resources/post/post-state-icons.js +17 -1
  40. package/dist/src/cms/client/interfaces/components/resources/post/post-table.js +8 -4
  41. package/dist/src/cms/client/interfaces/components/resources/post/search/control-fields-filters.js +5 -1
  42. package/dist/src/cms/client/interfaces/components/resources/seo-metadata/seo-form/seo-form.js +90 -67
  43. package/dist/src/cms/client/interfaces/components/resources/seo-metadata/seo-metadata-dialog.js +11 -1
  44. package/dist/src/cms/client/interfaces/components/ui/blocks/list-container/list-container.js +1 -1
  45. package/dist/src/cms/client/interfaces/components/ui/blocks/list-container/pagination.js +9 -9
  46. package/dist/src/cms/client/interfaces/components/ui/features/accordion/accordion-header.js +15 -3
  47. package/dist/src/cms/client/interfaces/components/ui/features/accordion/accordion.js +5 -7
  48. package/dist/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-display.js +1 -1
  49. package/dist/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-input.js +1 -1
  50. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/category/_id_/edit/page.js +11 -11
  51. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/category/_id_/page.js +12 -16
  52. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/category/_id_/relations/page.js +6 -2
  53. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/category/create/page.js +15 -16
  54. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/page.js +18 -41
  55. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/post/_id_/edit/page.js +10 -11
  56. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/post/_id_/page.js +11 -16
  57. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/post/_id_/relations/page.js +1 -0
  58. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/post/create/page.js +14 -16
  59. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/subcategory/_id_/edit/page.js +11 -11
  60. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/subcategory/_id_/page.js +12 -16
  61. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/subcategory/_id_/relations/page.js +1 -0
  62. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/subcategory/create/page.js +15 -16
  63. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/page.js +18 -32
  64. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/_id_/edit/page.js +2 -2
  65. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/_id_/page.js +9 -9
  66. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/_id_/relations/page.js +6 -2
  67. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/create/page.js +2 -2
  68. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/trash/page.js +204 -0
  69. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/_id_/admin-refresh-token/page.js +1 -0
  70. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/_id_/page.js +1 -0
  71. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/_id_/relations/page.js +8 -3
  72. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/file/_id_/page.js +3 -2
  73. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/file/_id_/relations/page.js +41 -30
  74. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/file/delete-many/page.js +3 -3
  75. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/file/page.js +1 -1
  76. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/trash/page.js +3 -2
  77. package/dist/src/cms/client/interfaces/pages/dashboard/website/website-page/_slug_/edit/page.js +19 -11
  78. package/dist/src/cms/client/interfaces/pages/dashboard/website/website-page/_slug_/page.js +23 -10
  79. package/dist/src/cms/client/interfaces/pages/dashboard/website/website-page/page.js +7 -7
  80. package/dist/src/cms/server/create-cms-server.js +2 -0
  81. package/dist/src/cms/server/resources/page/actions.js +31 -0
  82. package/dist/src/cms/server/resources/post/actions.js +27 -6
  83. package/dist/src/cms/server/resources/seo-metadata/actions.js +7 -16
  84. package/dist/src/config/content-ui.js +24 -0
  85. package/dist/src/config/topics.js +1 -1
  86. package/dist/src/constants/paths/cms-paths.js +2 -2
  87. package/dist/src/core/infrastructure/prisma/file/include.js +44 -0
  88. package/dist/src/core/infrastructure/prisma/file/mappers.js +51 -3
  89. package/dist/src/core/infrastructure/prisma/helpers/active-file-references.js +2 -1
  90. package/dist/src/core/infrastructure/prisma/page/include.js +20 -0
  91. package/dist/src/core/infrastructure/prisma/page/mappers.js +44 -0
  92. package/dist/src/core/infrastructure/prisma/page/page-prisma-ports.js +91 -0
  93. package/dist/src/core/infrastructure/prisma/post/include.js +10 -10
  94. package/dist/src/core/infrastructure/prisma/post/lifecycle.js +108 -0
  95. package/dist/src/core/infrastructure/prisma/post/mappers.js +9 -6
  96. package/dist/src/core/infrastructure/prisma/post/post-prisma-ports.js +76 -24
  97. package/dist/src/core/infrastructure/prisma/post/read-scope.js +45 -0
  98. package/dist/src/core/infrastructure/prisma/seo-metadata/mappers.js +6 -1
  99. package/dist/src/core/infrastructure/prisma/seo-metadata/seo-metadata-prisma-ports.js +32 -11
  100. package/dist/src/core/seeders/page/seeder.js +9 -29
  101. package/dist/src/core/seeders/seed.js +0 -3
  102. package/dist/src/core/sitero-server/create-sitero-server.js +10 -0
  103. package/dist/src/web/server/create-web-server.js +5 -1
  104. package/dist/src/web/server/resources/page/actions.js +20 -0
  105. package/dist/src/web/server/resources/post/actions.js +7 -37
  106. package/dist/src/web/server/seo/sitemap/get-page-items.js +7 -6
  107. package/dist/src/web/server/seo/sitemap/get-post-items.js +2 -2
  108. package/dist/src/web/server/seo/sitemap/get-subcategory-items.js +1 -1
  109. package/dist/types/export/cms/client/components/index.d.ts +3 -0
  110. package/dist/types/export/cms/client/components/index.d.ts.map +1 -1
  111. package/dist/types/export/cms/client/index.d.ts +2 -0
  112. package/dist/types/export/cms/client/index.d.ts.map +1 -1
  113. package/dist/types/export/cms/client/pages/index.d.ts +2 -1
  114. package/dist/types/export/cms/client/pages/index.d.ts.map +1 -1
  115. package/dist/types/export/cms/server/index.d.ts +2 -1
  116. package/dist/types/export/cms/server/index.d.ts.map +1 -1
  117. package/dist/types/export/index.d.ts +1 -1
  118. package/dist/types/export/index.d.ts.map +1 -1
  119. package/dist/types/export/web/server/index.d.ts +2 -1
  120. package/dist/types/export/web/server/index.d.ts.map +1 -1
  121. package/dist/types/src/cms/client/applications/create-applications.d.ts.map +1 -1
  122. package/dist/types/src/cms/client/applications/index.d.ts +1 -0
  123. package/dist/types/src/cms/client/applications/index.d.ts.map +1 -1
  124. package/dist/types/src/cms/client/applications/resources/index.d.ts +1 -0
  125. package/dist/types/src/cms/client/applications/resources/index.d.ts.map +1 -1
  126. package/dist/types/src/cms/client/applications/resources/page/form-data.d.ts +21 -0
  127. package/dist/types/src/cms/client/applications/resources/page/form-data.d.ts.map +1 -0
  128. package/dist/types/src/cms/client/applications/resources/page/index.d.ts +3 -0
  129. package/dist/types/src/cms/client/applications/resources/page/index.d.ts.map +1 -0
  130. package/dist/types/src/cms/client/applications/resources/page/use-page-update-form-data.d.ts +12 -0
  131. package/dist/types/src/cms/client/applications/resources/page/use-page-update-form-data.d.ts.map +1 -0
  132. package/dist/types/src/cms/client/applications/resources/post/use-create-form-data.d.ts +3 -5
  133. package/dist/types/src/cms/client/applications/resources/post/use-create-form-data.d.ts.map +1 -1
  134. package/dist/types/src/cms/client/applications/resources/post/use-update-form-data.d.ts.map +1 -1
  135. package/dist/types/src/cms/client/applications/resources/seo-metadata/build-seo-metadata-translations.d.ts +6 -0
  136. package/dist/types/src/cms/client/applications/resources/seo-metadata/build-seo-metadata-translations.d.ts.map +1 -0
  137. package/dist/types/src/cms/client/applications/resources/seo-metadata/use-upsert-form-data.d.ts +5 -4
  138. package/dist/types/src/cms/client/applications/resources/seo-metadata/use-upsert-form-data.d.ts.map +1 -1
  139. package/dist/types/src/cms/client/applications/types.d.ts +2 -1
  140. package/dist/types/src/cms/client/applications/types.d.ts.map +1 -1
  141. package/dist/types/src/cms/client/applications/ui/use-nav-items.d.ts +3 -4
  142. package/dist/types/src/cms/client/applications/ui/use-nav-items.d.ts.map +1 -1
  143. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/index.d.ts +86 -0
  144. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/index.d.ts.map +1 -1
  145. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.d.ts +3 -0
  146. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.d.ts.map +1 -1
  147. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/index.d.ts +71 -0
  148. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/index.d.ts.map +1 -1
  149. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/post.d.ts +51 -0
  150. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/post.d.ts.map +1 -1
  151. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/ui/index.d.ts +15 -0
  152. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/ui/index.d.ts.map +1 -1
  153. package/dist/types/src/cms/client/infrastructure/i18n/messages/index.d.ts +172 -0
  154. package/dist/types/src/cms/client/infrastructure/i18n/messages/index.d.ts.map +1 -1
  155. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/index.d.ts +86 -0
  156. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/index.d.ts.map +1 -1
  157. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.d.ts +3 -0
  158. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.d.ts.map +1 -1
  159. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/index.d.ts +71 -0
  160. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/index.d.ts.map +1 -1
  161. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/post.d.ts +51 -0
  162. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/post.d.ts.map +1 -1
  163. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/ui/index.d.ts +15 -0
  164. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/ui/index.d.ts.map +1 -1
  165. package/dist/types/src/cms/client/infrastructure/operation-result/presentation/message.d.ts.map +1 -1
  166. package/dist/types/src/cms/client/interfaces/components/create-components.d.ts +6 -3
  167. package/dist/types/src/cms/client/interfaces/components/create-components.d.ts.map +1 -1
  168. package/dist/types/src/cms/client/interfaces/components/create-page-contents.d.ts +30 -0
  169. package/dist/types/src/cms/client/interfaces/components/create-page-contents.d.ts.map +1 -0
  170. package/dist/types/src/cms/client/interfaces/components/resources/index.d.ts +1 -1
  171. package/dist/types/src/cms/client/interfaces/components/resources/index.d.ts.map +1 -1
  172. package/dist/types/src/cms/client/interfaces/components/resources/page/content/field-groups.d.ts +3 -0
  173. package/dist/types/src/cms/client/interfaces/components/resources/page/content/field-groups.d.ts.map +1 -0
  174. package/dist/types/src/cms/client/interfaces/components/resources/page/content/page-edit-content.d.ts +14 -0
  175. package/dist/types/src/cms/client/interfaces/components/resources/page/content/page-edit-content.d.ts.map +1 -0
  176. package/dist/types/src/cms/client/interfaces/components/resources/page/content/page-show-content.d.ts +7 -0
  177. package/dist/types/src/cms/client/interfaces/components/resources/page/content/page-show-content.d.ts.map +1 -0
  178. package/dist/types/src/cms/client/interfaces/components/resources/page/content/types.d.ts +27 -0
  179. package/dist/types/src/cms/client/interfaces/components/resources/page/content/types.d.ts.map +1 -0
  180. package/dist/types/src/cms/client/interfaces/components/resources/page/index.d.ts +4 -0
  181. package/dist/types/src/cms/client/interfaces/components/resources/page/index.d.ts.map +1 -0
  182. package/dist/types/src/cms/client/interfaces/components/resources/post/category/category-card.d.ts +3 -1
  183. package/dist/types/src/cms/client/interfaces/components/resources/post/category/category-card.d.ts.map +1 -1
  184. package/dist/types/src/cms/client/interfaces/components/resources/post/category/category-table.d.ts +1 -1
  185. package/dist/types/src/cms/client/interfaces/components/resources/post/category/category-table.d.ts.map +1 -1
  186. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-create-content.d.ts +3 -5
  187. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-create-content.d.ts.map +1 -1
  188. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-edit-content.d.ts.map +1 -1
  189. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-show-content.d.ts.map +1 -1
  190. package/dist/types/src/cms/client/interfaces/components/resources/post/content/types.d.ts +1 -1
  191. package/dist/types/src/cms/client/interfaces/components/resources/post/content/types.d.ts.map +1 -1
  192. package/dist/types/src/cms/client/interfaces/components/resources/post/post-card.d.ts +3 -1
  193. package/dist/types/src/cms/client/interfaces/components/resources/post/post-card.d.ts.map +1 -1
  194. package/dist/types/src/cms/client/interfaces/components/resources/post/post-list.d.ts +6 -3
  195. package/dist/types/src/cms/client/interfaces/components/resources/post/post-list.d.ts.map +1 -1
  196. package/dist/types/src/cms/client/interfaces/components/resources/post/post-state-icons.d.ts.map +1 -1
  197. package/dist/types/src/cms/client/interfaces/components/resources/post/post-table.d.ts +3 -1
  198. package/dist/types/src/cms/client/interfaces/components/resources/post/post-table.d.ts.map +1 -1
  199. package/dist/types/src/cms/client/interfaces/components/resources/post/search/control-fields-filters.d.ts.map +1 -1
  200. package/dist/types/src/cms/client/interfaces/components/resources/seo-metadata/seo-form/seo-form.d.ts +5 -2
  201. package/dist/types/src/cms/client/interfaces/components/resources/seo-metadata/seo-form/seo-form.d.ts.map +1 -1
  202. package/dist/types/src/cms/client/interfaces/components/resources/seo-metadata/seo-metadata-dialog.d.ts +2 -1
  203. package/dist/types/src/cms/client/interfaces/components/resources/seo-metadata/seo-metadata-dialog.d.ts.map +1 -1
  204. package/dist/types/src/cms/client/interfaces/components/ui/blocks/list-container/list-container.d.ts.map +1 -1
  205. package/dist/types/src/cms/client/interfaces/components/ui/features/accordion/accordion-header.d.ts +3 -1
  206. package/dist/types/src/cms/client/interfaces/components/ui/features/accordion/accordion-header.d.ts.map +1 -1
  207. package/dist/types/src/cms/client/interfaces/components/ui/features/accordion/accordion.d.ts +2 -1
  208. package/dist/types/src/cms/client/interfaces/components/ui/features/accordion/accordion.d.ts.map +1 -1
  209. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-display.d.ts.map +1 -1
  210. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-input.d.ts.map +1 -1
  211. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/edit/page.d.ts +1 -1
  212. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/edit/page.d.ts.map +1 -1
  213. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/page.d.ts +3 -1
  214. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/page.d.ts.map +1 -1
  215. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/relations/page.d.ts +3 -1
  216. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/[id]/relations/page.d.ts.map +1 -1
  217. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/create/page.d.ts +4 -7
  218. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/category/create/page.d.ts.map +1 -1
  219. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/page.d.ts +1 -4
  220. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/page.d.ts.map +1 -1
  221. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/post/[id]/edit/page.d.ts.map +1 -1
  222. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/post/[id]/page.d.ts.map +1 -1
  223. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/post/[id]/relations/page.d.ts.map +1 -1
  224. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/post/create/page.d.ts +4 -7
  225. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/post/create/page.d.ts.map +1 -1
  226. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/[id]/edit/page.d.ts +1 -1
  227. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/[id]/edit/page.d.ts.map +1 -1
  228. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/[id]/page.d.ts +3 -1
  229. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/[id]/page.d.ts.map +1 -1
  230. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/[id]/relations/page.d.ts.map +1 -1
  231. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/create/page.d.ts +4 -7
  232. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/subcategory/create/page.d.ts.map +1 -1
  233. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/page.d.ts +1 -3
  234. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/page.d.ts.map +1 -1
  235. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/[id]/page.d.ts.map +1 -1
  236. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/[id]/relations/page.d.ts +3 -1
  237. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/[id]/relations/page.d.ts.map +1 -1
  238. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/trash/index.d.ts +2 -0
  239. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/trash/index.d.ts.map +1 -0
  240. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/trash/page.d.ts +18 -0
  241. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/trash/page.d.ts.map +1 -0
  242. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/relations/page.d.ts +3 -1
  243. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/relations/page.d.ts.map +1 -1
  244. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/storage/file/[id]/relations/page.d.ts +5 -6
  245. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/storage/file/[id]/relations/page.d.ts.map +1 -1
  246. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/storage/trash/page.d.ts.map +1 -1
  247. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/[slug]/edit/page.d.ts +7 -9
  248. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/[slug]/edit/page.d.ts.map +1 -1
  249. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/[slug]/page.d.ts +7 -9
  250. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/[slug]/page.d.ts.map +1 -1
  251. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/page.d.ts +3 -3
  252. package/dist/types/src/cms/client/interfaces/pages/dashboard/website/website-page/page.d.ts.map +1 -1
  253. package/dist/types/src/cms/client/interfaces/pages/index.d.ts +1 -1
  254. package/dist/types/src/cms/client/interfaces/pages/index.d.ts.map +1 -1
  255. package/dist/types/src/cms/contracts/resources/page/actions.d.ts +7 -0
  256. package/dist/types/src/cms/contracts/resources/page/actions.d.ts.map +1 -0
  257. package/dist/types/src/cms/contracts/resources/post/actions.d.ts +2 -0
  258. package/dist/types/src/cms/contracts/resources/post/actions.d.ts.map +1 -1
  259. package/dist/types/src/cms/contracts/resources/post/form-data.d.ts +1 -1
  260. package/dist/types/src/cms/contracts/resources/post/form-data.d.ts.map +1 -1
  261. package/dist/types/src/cms/contracts/resources/seo-metadata/form-data.d.ts +2 -2
  262. package/dist/types/src/cms/contracts/resources/seo-metadata/form-data.d.ts.map +1 -1
  263. package/dist/types/src/cms/server/create-cms-server.d.ts +7 -0
  264. package/dist/types/src/cms/server/create-cms-server.d.ts.map +1 -1
  265. package/dist/types/src/cms/server/index.d.ts +1 -1
  266. package/dist/types/src/cms/server/index.d.ts.map +1 -1
  267. package/dist/types/src/cms/server/resources/index.d.ts +1 -0
  268. package/dist/types/src/cms/server/resources/index.d.ts.map +1 -1
  269. package/dist/types/src/cms/server/resources/page/actions.d.ts +8 -0
  270. package/dist/types/src/cms/server/resources/page/actions.d.ts.map +1 -0
  271. package/dist/types/src/cms/server/resources/post/actions.d.ts +2 -0
  272. package/dist/types/src/cms/server/resources/post/actions.d.ts.map +1 -1
  273. package/dist/types/src/cms/server/resources/seo-metadata/actions.d.ts.map +1 -1
  274. package/dist/types/src/config/content-ui.d.ts +14 -0
  275. package/dist/types/src/config/content-ui.d.ts.map +1 -0
  276. package/dist/types/src/config/index.d.ts +2 -0
  277. package/dist/types/src/config/index.d.ts.map +1 -1
  278. package/dist/types/src/config/page.d.ts +4 -0
  279. package/dist/types/src/config/page.d.ts.map +1 -0
  280. package/dist/types/src/config/topics.d.ts +2 -2
  281. package/dist/types/src/config/topics.d.ts.map +1 -1
  282. package/dist/types/src/constants/paths/cms-paths.d.ts +3 -3
  283. package/dist/types/src/core/infrastructure/index.d.ts +1 -0
  284. package/dist/types/src/core/infrastructure/index.d.ts.map +1 -1
  285. package/dist/types/src/core/infrastructure/prisma/file/include.d.ts +121 -0
  286. package/dist/types/src/core/infrastructure/prisma/file/include.d.ts.map +1 -1
  287. package/dist/types/src/core/infrastructure/prisma/file/mappers.d.ts.map +1 -1
  288. package/dist/types/src/core/infrastructure/prisma/helpers/active-file-references.d.ts +1 -1
  289. package/dist/types/src/core/infrastructure/prisma/helpers/active-file-references.d.ts.map +1 -1
  290. package/dist/types/src/core/infrastructure/prisma/index.d.ts +1 -0
  291. package/dist/types/src/core/infrastructure/prisma/index.d.ts.map +1 -1
  292. package/dist/types/src/core/infrastructure/prisma/page/include.d.ts +63 -0
  293. package/dist/types/src/core/infrastructure/prisma/page/include.d.ts.map +1 -0
  294. package/dist/types/src/core/infrastructure/prisma/page/index.d.ts +4 -0
  295. package/dist/types/src/core/infrastructure/prisma/page/index.d.ts.map +1 -0
  296. package/dist/types/src/core/infrastructure/prisma/page/mappers.d.ts +9 -0
  297. package/dist/types/src/core/infrastructure/prisma/page/mappers.d.ts.map +1 -0
  298. package/dist/types/src/core/infrastructure/prisma/page/page-prisma-ports.d.ts +7 -0
  299. package/dist/types/src/core/infrastructure/prisma/page/page-prisma-ports.d.ts.map +1 -0
  300. package/dist/types/src/core/infrastructure/prisma/page/types.d.ts +10 -0
  301. package/dist/types/src/core/infrastructure/prisma/page/types.d.ts.map +1 -0
  302. package/dist/types/src/core/infrastructure/prisma/post/include.d.ts +37 -23
  303. package/dist/types/src/core/infrastructure/prisma/post/include.d.ts.map +1 -1
  304. package/dist/types/src/core/infrastructure/prisma/post/lifecycle.d.ts +66 -0
  305. package/dist/types/src/core/infrastructure/prisma/post/lifecycle.d.ts.map +1 -0
  306. package/dist/types/src/core/infrastructure/prisma/post/mappers.d.ts +3 -2
  307. package/dist/types/src/core/infrastructure/prisma/post/mappers.d.ts.map +1 -1
  308. package/dist/types/src/core/infrastructure/prisma/post/post-prisma-ports.d.ts.map +1 -1
  309. package/dist/types/src/core/infrastructure/prisma/post/read-scope.d.ts +271 -0
  310. package/dist/types/src/core/infrastructure/prisma/post/read-scope.d.ts.map +1 -0
  311. package/dist/types/src/core/infrastructure/prisma/post/types.d.ts +4 -1
  312. package/dist/types/src/core/infrastructure/prisma/post/types.d.ts.map +1 -1
  313. package/dist/types/src/core/infrastructure/prisma/seo-metadata/mappers.d.ts +1 -1
  314. package/dist/types/src/core/infrastructure/prisma/seo-metadata/mappers.d.ts.map +1 -1
  315. package/dist/types/src/core/infrastructure/prisma/seo-metadata/seo-metadata-prisma-ports.d.ts +2 -2
  316. package/dist/types/src/core/infrastructure/prisma/seo-metadata/seo-metadata-prisma-ports.d.ts.map +1 -1
  317. package/dist/types/src/core/seeders/page/seeder.d.ts +3 -3
  318. package/dist/types/src/core/seeders/page/seeder.d.ts.map +1 -1
  319. package/dist/types/src/core/seeders/seed.d.ts +2 -3
  320. package/dist/types/src/core/seeders/seed.d.ts.map +1 -1
  321. package/dist/types/src/core/sitero-server/create-sitero-server.d.ts.map +1 -1
  322. package/dist/types/src/core/sitero-server/types.d.ts +2 -0
  323. package/dist/types/src/core/sitero-server/types.d.ts.map +1 -1
  324. package/dist/types/src/shared/list-item.d.ts +1 -0
  325. package/dist/types/src/shared/list-item.d.ts.map +1 -1
  326. package/dist/types/src/web/contracts/index.d.ts +1 -0
  327. package/dist/types/src/web/contracts/index.d.ts.map +1 -1
  328. package/dist/types/src/web/contracts/resources/page/actions.d.ts +5 -0
  329. package/dist/types/src/web/contracts/resources/page/actions.d.ts.map +1 -0
  330. package/dist/types/src/web/contracts/resources/post/actions.d.ts +2 -3
  331. package/dist/types/src/web/contracts/resources/post/actions.d.ts.map +1 -1
  332. package/dist/types/src/web/server/create-web-server.d.ts.map +1 -1
  333. package/dist/types/src/web/server/index.d.ts +1 -1
  334. package/dist/types/src/web/server/index.d.ts.map +1 -1
  335. package/dist/types/src/web/server/resources/index.d.ts +1 -0
  336. package/dist/types/src/web/server/resources/index.d.ts.map +1 -1
  337. package/dist/types/src/web/server/resources/page/actions.d.ts +17 -0
  338. package/dist/types/src/web/server/resources/page/actions.d.ts.map +1 -0
  339. package/dist/types/src/web/server/resources/post/actions.d.ts +1 -6
  340. package/dist/types/src/web/server/resources/post/actions.d.ts.map +1 -1
  341. package/dist/types/src/web/server/seo/metadata/build-metadata.d.ts +5 -2
  342. package/dist/types/src/web/server/seo/metadata/build-metadata.d.ts.map +1 -1
  343. package/dist/types/src/web/server/seo/sitemap/build-entries.d.ts +2 -2
  344. package/dist/types/src/web/server/seo/sitemap/build-entries.d.ts.map +1 -1
  345. package/dist/types/src/web/server/seo/sitemap/get-page-items.d.ts +6 -2
  346. package/dist/types/src/web/server/seo/sitemap/get-page-items.d.ts.map +1 -1
  347. package/dist/types/src/web/server/seo/sitemap/get-post-items.d.ts.map +1 -1
  348. package/dist/types/src/web/server/seo/sitemap/get-subcategory-items.d.ts.map +1 -1
  349. package/dist/types/src/web/server/types.d.ts +6 -2
  350. package/dist/types/src/web/server/types.d.ts.map +1 -1
  351. package/package.json +3 -3
  352. package/dist/src/cms/client/interfaces/components/resources/post/topic/topic-card.js +0 -81
  353. package/dist/src/cms/client/interfaces/components/resources/post/topic/topic-table.js +0 -120
  354. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/_id_/edit/page.js +0 -110
  355. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/_id_/page.js +0 -161
  356. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/page.js +0 -103
  357. package/dist/src/core/seeders/topic/seeder.js +0 -47
  358. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/index.d.ts +0 -3
  359. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/index.d.ts.map +0 -1
  360. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/topic-card.d.ts +0 -5
  361. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/topic-card.d.ts.map +0 -1
  362. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/topic-table.d.ts +0 -3
  363. package/dist/types/src/cms/client/interfaces/components/resources/post/topic/topic-table.d.ts.map +0 -1
  364. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/[id]/edit/page.d.ts +0 -20
  365. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/[id]/edit/page.d.ts.map +0 -1
  366. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/[id]/page.d.ts +0 -20
  367. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/[id]/page.d.ts.map +0 -1
  368. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/index.d.ts +0 -4
  369. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/index.d.ts.map +0 -1
  370. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/page.d.ts +0 -14
  371. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/page.d.ts.map +0 -1
  372. package/dist/types/src/core/seeders/topic/seeder.d.ts +0 -10
  373. package/dist/types/src/core/seeders/topic/seeder.d.ts.map +0 -1
@@ -0,0 +1,108 @@
1
+ import { POST_ERROR_CODES, OperationError } from 'sitero-server';
2
+
3
+ async function lockPostWrites(tx) {
4
+ await tx.$queryRaw`SELECT pg_advisory_xact_lock(1936286821, 1)::text`;
5
+ }
6
+ function fail(code, ids = []) {
7
+ throw new OperationError({ code, details: { postIds: ids } });
8
+ }
9
+ async function requirePost(tx, id, deleted = false) {
10
+ const post = await tx.post.findUnique({ where: { id } });
11
+ if (!post) fail(POST_ERROR_CODES.NOT_FOUND);
12
+ if (!!post.deletedAt !== deleted) fail(POST_ERROR_CODES.INVALID_STATE);
13
+ return post;
14
+ }
15
+ async function assertNoPostReferences(tx, id) {
16
+ const references = await tx.post.findMany({
17
+ where: {
18
+ id: { not: id },
19
+ OR: [
20
+ { parents: { some: { id } } },
21
+ { tags: { some: { id } } },
22
+ { relatedPosts: { some: { id } } }
23
+ ]
24
+ },
25
+ select: { id: true }
26
+ });
27
+ if (references.length)
28
+ fail(
29
+ POST_ERROR_CODES.IN_USE,
30
+ references.map(({ id: id2 }) => id2)
31
+ );
32
+ }
33
+ async function assertPublishedAncestors(tx, ids) {
34
+ const visited = /* @__PURE__ */ new Set();
35
+ let pending = ids;
36
+ while (pending.length) {
37
+ const batch = [...new Set(pending)].filter((id) => !visited.has(id));
38
+ if (!batch.length) break;
39
+ batch.forEach((id) => visited.add(id));
40
+ const parents = await tx.post.findMany({
41
+ where: { id: { in: batch } },
42
+ include: { parents: { select: { id: true } } }
43
+ });
44
+ const unavailable = batch.filter(
45
+ (id) => !parents.some((p) => p.id === id && p.isActive && !p.deletedAt)
46
+ );
47
+ if (unavailable.length)
48
+ fail(POST_ERROR_CODES.PARENT_UNPUBLISHED, unavailable);
49
+ pending = parents.flatMap((p) => p.parents.map(({ id }) => id));
50
+ }
51
+ }
52
+ async function assertNoPublishedDescendants(tx, id) {
53
+ const visited = /* @__PURE__ */ new Set([id]);
54
+ let pending = [id];
55
+ while (pending.length) {
56
+ const children = await tx.post.findMany({
57
+ where: { parents: { some: { id: { in: pending } } } },
58
+ select: { id: true, isActive: true, deletedAt: true }
59
+ });
60
+ const published = children.filter(
61
+ (child) => child.isActive && !child.deletedAt
62
+ );
63
+ if (published.length)
64
+ fail(
65
+ POST_ERROR_CODES.HAS_PUBLISHED_CHILDREN,
66
+ published.map(({ id: id2 }) => id2)
67
+ );
68
+ pending = children.map(({ id: id2 }) => id2).filter((id2) => !visited.has(id2));
69
+ pending.forEach((id2) => visited.add(id2));
70
+ }
71
+ }
72
+ async function assertPostWrite(tx, input, id, previous) {
73
+ const type = previous?.type ?? input.type;
74
+ const topicKey = previous ? previous.topicKey : input.topicKey;
75
+ const slug = input.slug?.trim() || id;
76
+ const conflict = await tx.post.findFirst({
77
+ where: { type, topicKey, slug, id: { not: id } },
78
+ select: { id: true }
79
+ });
80
+ if (conflict) fail(POST_ERROR_CODES.SLUG_CONFLICT, [conflict.id]);
81
+ const ids = [
82
+ ...new Set(
83
+ [...input.parents, ...input.tags, ...input.relatedPosts].map(
84
+ ({ id: id2 }) => id2
85
+ )
86
+ )
87
+ ];
88
+ if (ids.length) {
89
+ const records = await tx.post.findMany({
90
+ where: { id: { in: ids }, deletedAt: null },
91
+ select: { id: true }
92
+ });
93
+ const unavailable = ids.filter(
94
+ (id2) => !records.some((record) => record.id === id2)
95
+ );
96
+ if (unavailable.length)
97
+ fail(POST_ERROR_CODES.REFERENCE_UNAVAILABLE, unavailable);
98
+ }
99
+ if (input.isActive)
100
+ await assertPublishedAncestors(
101
+ tx,
102
+ input.parents.map(({ id: id2 }) => id2)
103
+ );
104
+ if (!input.isActive && (type === "CATEGORY" || type === "SUBCATEGORY"))
105
+ await assertNoPublishedDescendants(tx, id);
106
+ }
107
+
108
+ export { assertNoPostReferences, assertPostWrite, lockPostWrites, requirePost };
@@ -18,24 +18,27 @@ function postReferenceToDomain(post) {
18
18
  translations: post.translations.map(translationToDomain)
19
19
  };
20
20
  }
21
- function postListCardToDomain(post) {
21
+ function postReferenceWithCoverToDomain(post) {
22
22
  return {
23
23
  ...postReferenceToDomain(post),
24
- topic: post.topic ? postReferenceToDomain(post.topic) : null,
25
24
  coverImage: post.coverImage ? fileToCard(post.coverImage) : null
26
25
  };
27
26
  }
27
+ function postListCardToDomain(post) {
28
+ return {
29
+ ...postReferenceWithCoverToDomain(post),
30
+ parents: post.parents.map(postReferenceWithCoverToDomain)
31
+ };
32
+ }
28
33
  function postDetailToDomain(post) {
29
34
  const author = post.author ? adminListCardToDomain(post.author) : null;
30
35
  return {
31
36
  ...postListCardToDomain(post),
32
37
  author,
33
- postsInTopic: post.postsInTopic.map(postReferenceToDomain),
34
- parents: post.parents.map(postReferenceToDomain),
35
38
  children: post.children.map(postReferenceToDomain),
36
39
  tags: post.tags.map(postReferenceToDomain),
37
40
  taggedPosts: post.taggedPosts.map(postReferenceToDomain),
38
- relatedPosts: post.relatedPosts.map(postReferenceToDomain),
41
+ relatedPosts: post.relatedPosts.map(postListCardToDomain),
39
42
  referencingPosts: post.referencingPosts.map(postReferenceToDomain),
40
43
  contentImages: post.contentImages.map(fileToCard),
41
44
  files1: post.files1.map(fileToCard),
@@ -66,4 +69,4 @@ function postRelationsToDomain(post) {
66
69
  };
67
70
  }
68
71
 
69
- export { postDetailToDomain, postListCardToDomain, postReferenceToDomain, postRelationsToDomain };
72
+ export { postDetailToDomain, postListCardToDomain, postReferenceToDomain, postReferenceWithCoverToDomain, postRelationsToDomain };
@@ -1,10 +1,13 @@
1
+ import { OperationError, POST_ERROR_CODES } from 'sitero-server';
1
2
  import { ulid } from 'ulid';
2
3
  import { withActiveFileReferences } from '../helpers/active-file-references.js';
3
4
  import { connectOrDisconnectOne, setMany, connectOne, connectMany } from '../helpers/relation-writes.js';
4
5
  import { createSearchWhere } from '../helpers/search-where.js';
5
6
  import { postToDomain } from './base-mappers.js';
6
- import { POST_RELATIONS_INCLUDE, POST_DETAIL_INCLUDE, POST_LIST_CARD_INCLUDE, POST_REFERENCE_INCLUDE } from './include.js';
7
+ import { POST_RELATIONS_INCLUDE, POST_REFERENCE_INCLUDE } from './include.js';
8
+ import { lockPostWrites, requirePost, assertNoPostReferences, assertPostWrite } from './lifecycle.js';
7
9
  import { postRelationsToDomain, postListCardToDomain, postDetailToDomain, postReferenceToDomain } from './mappers.js';
10
+ import { postReadWhere, postDetailInclude, postListInclude } from './read-scope.js';
8
11
 
9
12
  const SEARCH_TEXT_FIELDS = [
10
13
  "text1",
@@ -55,6 +58,7 @@ function createPostPrismaPorts(prisma) {
55
58
  // ------------------------------------------------------------
56
59
  postCommandPort: {
57
60
  async create(input) {
61
+ const id = ulid();
58
62
  return withActiveFileReferences(
59
63
  prisma,
60
64
  [
@@ -68,10 +72,8 @@ function createPostPrismaPorts(prisma) {
68
72
  input.file4
69
73
  ],
70
74
  async (transaction) => {
71
- const id = ulid();
72
75
  const {
73
76
  author,
74
- topic,
75
77
  parents,
76
78
  tags,
77
79
  relatedPosts,
@@ -88,7 +90,6 @@ function createPostPrismaPorts(prisma) {
88
90
  ...scalars
89
91
  } = input;
90
92
  const authorWrite = connectOne(author);
91
- const topicWrite = connectOne(topic);
92
93
  const coverImageWrite = connectOne(coverImage);
93
94
  const file1Write = connectOne(file1);
94
95
  const file2Write = connectOne(file2);
@@ -100,7 +101,6 @@ function createPostPrismaPorts(prisma) {
100
101
  id,
101
102
  slug: slug?.trim() || id,
102
103
  ...authorWrite ? { author: authorWrite } : {},
103
- ...topicWrite ? { topic: topicWrite } : {},
104
104
  parents: connectMany(parents),
105
105
  tags: connectMany(tags),
106
106
  relatedPosts: connectMany(relatedPosts),
@@ -116,6 +116,10 @@ function createPostPrismaPorts(prisma) {
116
116
  }
117
117
  });
118
118
  return postToDomain(post);
119
+ },
120
+ async (tx) => {
121
+ await lockPostWrites(tx);
122
+ await assertPostWrite(tx, input, id);
119
123
  }
120
124
  );
121
125
  },
@@ -136,7 +140,6 @@ function createPostPrismaPorts(prisma) {
136
140
  const {
137
141
  id,
138
142
  author,
139
- topic,
140
143
  parents,
141
144
  tags,
142
145
  relatedPosts,
@@ -153,12 +156,11 @@ function createPostPrismaPorts(prisma) {
153
156
  ...scalars
154
157
  } = input;
155
158
  const post = await transaction.post.update({
156
- where: { id },
159
+ where: { id, deletedAt: null },
157
160
  data: {
158
161
  ...scalars,
159
162
  slug: slug?.trim() || id,
160
163
  author: connectOrDisconnectOne(author),
161
- topic: connectOrDisconnectOne(topic),
162
164
  parents: setMany(parents),
163
165
  tags: setMany(tags),
164
166
  relatedPosts: setMany(relatedPosts),
@@ -182,13 +184,54 @@ function createPostPrismaPorts(prisma) {
182
184
  }
183
185
  });
184
186
  return postToDomain(post);
187
+ },
188
+ async (tx) => {
189
+ await lockPostWrites(tx);
190
+ const previous = await requirePost(tx, input.id);
191
+ await assertPostWrite(tx, input, input.id, previous);
185
192
  }
186
193
  );
187
194
  },
188
195
  async delete({ id }) {
189
- return postToDomain(
190
- await prisma.post.delete({ where: { id, isLocked: false } })
191
- );
196
+ return prisma.$transaction(async (tx) => {
197
+ await lockPostWrites(tx);
198
+ const post = await requirePost(tx, id);
199
+ if (post.isLocked)
200
+ throw new OperationError({ code: POST_ERROR_CODES.DELETE_LOCKED });
201
+ await assertNoPostReferences(tx, id);
202
+ return postToDomain(
203
+ await tx.post.update({
204
+ where: { id, deletedAt: null, isLocked: false },
205
+ data: { deletedAt: /* @__PURE__ */ new Date(), isActive: false }
206
+ })
207
+ );
208
+ });
209
+ },
210
+ async restore({ id }) {
211
+ return prisma.$transaction(async (tx) => {
212
+ await lockPostWrites(tx);
213
+ await requirePost(tx, id, true);
214
+ return postToDomain(
215
+ await tx.post.update({
216
+ where: { id, deletedAt: { not: null } },
217
+ data: { deletedAt: null, isActive: false }
218
+ })
219
+ );
220
+ });
221
+ },
222
+ async purge({ id }) {
223
+ return prisma.$transaction(async (tx) => {
224
+ await lockPostWrites(tx);
225
+ const post = await requirePost(tx, id, true);
226
+ if (post.isLocked)
227
+ throw new OperationError({ code: POST_ERROR_CODES.DELETE_LOCKED });
228
+ await assertNoPostReferences(tx, id);
229
+ return postToDomain(
230
+ await tx.post.delete({
231
+ where: { id, deletedAt: { not: null }, isLocked: false }
232
+ })
233
+ );
234
+ });
192
235
  }
193
236
  },
194
237
  // ------------------------------------------------------------
@@ -198,8 +241,9 @@ function createPostPrismaPorts(prisma) {
198
241
  async findMany(input) {
199
242
  const posts = await prisma.post.findMany({
200
243
  where: {
244
+ ...postReadWhere(input),
201
245
  ...input?.type ? { type: input.type } : {},
202
- ...input?.topicId === void 0 ? {} : { topicId: input.topicId },
246
+ ...input?.topicKey === void 0 ? {} : { topicKey: input.topicKey },
203
247
  ...input?.postIds ? { id: { in: input.postIds } } : {}
204
248
  },
205
249
  orderBy,
@@ -227,10 +271,8 @@ function createPostPrismaPorts(prisma) {
227
271
  const where = {
228
272
  ...customStateFilters,
229
273
  ...input.type ? { type: input.type } : {},
230
- ...input.topicId === void 0 ? {} : { topicId: input.topicId },
231
- ...input.topicSlug ? { topic: { slug: input.topicSlug } } : {},
232
- ...input.parentId ? { parents: { some: { id: input.parentId } } } : {},
233
- ...input.parentSlug ? { parents: { some: { slug: input.parentSlug } } } : {},
274
+ ...input.topicKey === void 0 ? {} : { topicKey: input.topicKey },
275
+ ...input.topicSlug ? { AND: [{ topicKey: input.topicSlug }] } : {},
234
276
  ...input.authorId ? { authorId: input.authorId } : {},
235
277
  ...input.postIds || input.excludeIds ? {
236
278
  id: {
@@ -253,16 +295,24 @@ function createPostPrismaPorts(prisma) {
253
295
  })
254
296
  };
255
297
  const pagination = input.page && input.pageSize ? { skip: (input.page - 1) * input.pageSize, take: input.pageSize } : {};
298
+ const scopedWhere = {
299
+ AND: [
300
+ where,
301
+ postReadWhere(input),
302
+ ...input.parentId ? [{ parents: { some: { id: input.parentId } } }] : [],
303
+ ...input.parentSlug ? [{ parents: { some: { slug: input.parentSlug } } }] : []
304
+ ]
305
+ };
256
306
  const findManyInput = {
257
- where,
307
+ where: scopedWhere,
258
308
  orderBy,
259
- include: POST_LIST_CARD_INCLUDE,
309
+ include: postListInclude(input),
260
310
  ...pagination
261
311
  };
262
312
  const result = await prisma.$transaction(async (transaction) => {
263
313
  const [items, total] = await Promise.all([
264
314
  transaction.post.findMany(findManyInput),
265
- transaction.post.count({ where })
315
+ transaction.post.count({ where: scopedWhere })
266
316
  ]);
267
317
  return { items, total };
268
318
  });
@@ -274,17 +324,19 @@ function createPostPrismaPorts(prisma) {
274
324
  async findDetail(input) {
275
325
  const lookup = "id" in input ? { id: input.id } : { type: input.type, slug: input.slug };
276
326
  const scope = {
327
+ AND: [postReadWhere(input)],
277
328
  ...input.isActive === void 0 ? {} : { isActive: input.isActive },
278
- ...input.topicSlug ? { topic: { slug: input.topicSlug } } : {}
329
+ ...input.topicSlug ? { topicKey: input.topicSlug } : {}
279
330
  };
280
331
  const post = await prisma.post.findFirst({
281
332
  where: { ...scope, ...lookup },
282
- include: POST_DETAIL_INCLUDE
333
+ include: postDetailInclude(input)
283
334
  });
284
335
  if (!post) return { post: null, previous: null, next: null };
285
336
  const adjacentWhere = {
286
337
  ...scope,
287
- ..."id" in input ? {} : { type: input.type }
338
+ type: post.type,
339
+ topicKey: post.topicKey
288
340
  };
289
341
  const [previous, next] = await Promise.all([
290
342
  prisma.post.findFirst({
@@ -292,14 +344,14 @@ function createPostPrismaPorts(prisma) {
292
344
  orderBy: orderBy.map(reverseOrderBy),
293
345
  cursor: { id: post.id },
294
346
  skip: 1,
295
- include: POST_LIST_CARD_INCLUDE
347
+ include: postListInclude(input)
296
348
  }),
297
349
  prisma.post.findFirst({
298
350
  where: adjacentWhere,
299
351
  orderBy,
300
352
  cursor: { id: post.id },
301
353
  skip: 1,
302
- include: POST_LIST_CARD_INCLUDE
354
+ include: postListInclude(input)
303
355
  })
304
356
  ]);
305
357
  return {
@@ -0,0 +1,45 @@
1
+ import { POST_DETAIL_INCLUDE, POST_REFERENCE_INCLUDE, POST_LIST_CARD_INCLUDE, POST_REFERENCE_WITH_COVER_INCLUDE } from './include.js';
2
+
3
+ const active = { isActive: true, deletedAt: null };
4
+ const publishedParent = {
5
+ ...active,
6
+ parents: { every: active }
7
+ };
8
+ const PUBLIC_POST_WHERE = {
9
+ ...active,
10
+ parents: { every: publishedParent }
11
+ };
12
+ function postReadWhere(scope) {
13
+ const deletion = scope?.deletion === "all" ? {} : {
14
+ deletedAt: scope?.deletion === "deleted" ? { not: null } : null
15
+ };
16
+ return scope?.visibility === "public" ? { AND: [PUBLIC_POST_WHERE, deletion] } : deletion;
17
+ }
18
+ function postListInclude(scope) {
19
+ if (scope?.visibility !== "public") return POST_LIST_CARD_INCLUDE;
20
+ return {
21
+ ...POST_LIST_CARD_INCLUDE,
22
+ parents: {
23
+ where: PUBLIC_POST_WHERE,
24
+ include: POST_REFERENCE_WITH_COVER_INCLUDE
25
+ }
26
+ };
27
+ }
28
+ function postDetailInclude(scope) {
29
+ if (scope?.visibility !== "public") return POST_DETAIL_INCLUDE;
30
+ const reference = {
31
+ where: PUBLIC_POST_WHERE,
32
+ include: POST_REFERENCE_INCLUDE
33
+ };
34
+ return {
35
+ ...POST_DETAIL_INCLUDE,
36
+ ...postListInclude(scope),
37
+ children: reference,
38
+ tags: reference,
39
+ taggedPosts: reference,
40
+ relatedPosts: { where: PUBLIC_POST_WHERE, include: postListInclude(scope) },
41
+ referencingPosts: reference
42
+ };
43
+ }
44
+
45
+ export { PUBLIC_POST_WHERE, postDetailInclude, postListInclude, postReadWhere };
@@ -6,8 +6,13 @@ function seoMetadataToWrite(data) {
6
6
  };
7
7
  }
8
8
  function seoMetadataToDomain(seoMetadata) {
9
+ const { postId, pageId, ...data } = seoMetadata;
10
+ if (postId != null === (pageId != null))
11
+ throw new Error("Invalid SEO metadata owner");
12
+ const owner = postId != null ? { postId, pageId: null } : { pageId, postId: null };
9
13
  return {
10
- ...seoMetadata,
14
+ ...data,
15
+ ...owner,
11
16
  alternate: seoMetadata.alternate,
12
17
  jsonLd: seoMetadata.jsonLd
13
18
  };
@@ -1,3 +1,4 @@
1
+ import { lockPostWrites, requirePost } from '../post/lifecycle.js';
1
2
  import { seoMetadataToWrite, seoMetadataToDomain } from './mappers.js';
2
3
 
3
4
  function createSeoMetadataPrismaPorts(prisma) {
@@ -6,17 +7,37 @@ function createSeoMetadataPrismaPorts(prisma) {
6
7
  // Command
7
8
  // ------------------------------------------------------------
8
9
  seoMetadataCommandPort: {
9
- async upsert({ postId, translations }) {
10
- const seoMetadatas = await prisma.$transaction(
11
- translations.map((translation) => {
12
- const data = seoMetadataToWrite(translation);
13
- return prisma.seoMetadata.upsert({
14
- where: { postId_locale: { postId, locale: translation.locale } },
15
- update: data,
16
- create: { postId, ...data }
17
- });
18
- })
19
- );
10
+ async upsert(input) {
11
+ const { translations } = input;
12
+ const seoMetadatas = await prisma.$transaction(async (tx) => {
13
+ if (input.postId !== void 0) {
14
+ await lockPostWrites(tx);
15
+ await requirePost(tx, input.postId);
16
+ }
17
+ return Promise.all(
18
+ translations.map((translation) => {
19
+ const data = seoMetadataToWrite(translation);
20
+ return tx.seoMetadata.upsert({
21
+ where: input.postId !== void 0 ? {
22
+ postId_locale: {
23
+ postId: input.postId,
24
+ locale: translation.locale
25
+ }
26
+ } : {
27
+ pageId_locale: {
28
+ pageId: input.pageId,
29
+ locale: translation.locale
30
+ }
31
+ },
32
+ update: data,
33
+ create: {
34
+ ...data,
35
+ ...input.postId !== void 0 ? { postId: input.postId, pageId: null } : { pageId: input.pageId, postId: null }
36
+ }
37
+ });
38
+ })
39
+ );
40
+ });
20
41
  return seoMetadatas.map(seoMetadataToDomain);
21
42
  }
22
43
  }
@@ -1,39 +1,19 @@
1
- import { POST_TYPES } from 'sitero-domain';
2
-
3
1
  function pageSeeder({
4
2
  prisma,
5
- pages: staticPages,
3
+ pages,
6
4
  locales
7
5
  }) {
8
- async function checkExistence(slug) {
9
- const page = await prisma.post.findFirst({
10
- where: { type: POST_TYPES.PAGE, slug },
11
- select: { id: true }
12
- });
13
- return page ? true : false;
14
- }
15
6
  async function seed() {
16
- const pages = Object.entries(staticPages).map(([slug, data]) => ({
17
- slug,
18
- ...data
19
- }));
20
- for (const [i, item] of pages.entries()) {
21
- const exists = await checkExistence(item.slug);
22
- if (exists) continue;
23
- await prisma.post.create({
24
- data: {
25
- type: POST_TYPES.PAGE,
26
- // states
27
- isActive: true,
28
- isSlugActive: true,
29
- slug: item.slug,
30
- isIndexActive: true,
31
- index: i + 1,
32
- // translation
7
+ for (const [key, page] of Object.entries(pages)) {
8
+ await prisma.page.upsert({
9
+ where: { key },
10
+ update: {},
11
+ create: {
12
+ key,
33
13
  translations: {
34
- create: locales.map((locale) => ({
14
+ create: [...new Set(locales)].map((locale) => ({
35
15
  locale,
36
- title: item.title[locale]
16
+ title: page.title[locale] ?? null
37
17
  }))
38
18
  }
39
19
  }
@@ -1,20 +1,17 @@
1
1
  import { adminSeeder } from './admin/seeder.js';
2
2
  import { configSeeder } from './config/seeder.js';
3
3
  import { pageSeeder } from './page/seeder.js';
4
- import { topicSeeder } from './topic/seeder.js';
5
4
 
6
5
  async function seed({
7
6
  prisma,
8
7
  webLocales: locales,
9
8
  admins,
10
9
  pages,
11
- topics,
12
10
  configs
13
11
  }) {
14
12
  const siteroPrisma = prisma;
15
13
  await adminSeeder({ prisma: siteroPrisma, locales, admins }).seed();
16
14
  await pageSeeder({ prisma: siteroPrisma, locales, pages }).seed();
17
- await topicSeeder({ prisma: siteroPrisma, locales, topics }).seed();
18
15
  await configSeeder({ prisma: siteroPrisma, locales, configs }).seed();
19
16
  }
20
17
 
@@ -10,6 +10,8 @@ import { createFilePrismaPorts } from '../infrastructure/prisma/file/file-prisma
10
10
  import { createInquiryPrismaPorts } from '../infrastructure/prisma/inquiry/inquiry-prisma-ports.js';
11
11
  import { createPostPrismaPorts } from '../infrastructure/prisma/post/post-prisma-ports.js';
12
12
  import { createSeoMetadataPrismaPorts } from '../infrastructure/prisma/seo-metadata/seo-metadata-prisma-ports.js';
13
+ import { createPagePrismaPorts } from '../infrastructure/prisma/page/page-prisma-ports.js';
14
+ import '../infrastructure/prisma/page/include.js';
13
15
  import { createRedisRateLimiterPort } from '../infrastructure/rate-limiter/create-redis-rate-limiter-port.js';
14
16
  import { getRedisClient } from '../infrastructure/redis/create-redis-client.js';
15
17
  import { createEmailComposition } from './email.js';
@@ -51,12 +53,19 @@ function createSiteroServer(input) {
51
53
  const prisma = input.prisma;
52
54
  const adminPrismaPorts = createAdminPrismaPorts(prisma);
53
55
  const adminRefreshTokenPrismaPorts = createAdminRefreshTokenPrismaPorts(prisma);
56
+ const pagePrismaPorts = createPagePrismaPorts(prisma);
54
57
  const configPrismaPorts = createConfigPrismaPorts(prisma);
55
58
  const filePrismaPorts = createFilePrismaPorts(prisma);
56
59
  const inquiryPrismaPorts = createInquiryPrismaPorts(prisma);
57
60
  const postPrismaPorts = createPostPrismaPorts(prisma);
58
61
  const seoMetadataPrismaPorts = createSeoMetadataPrismaPorts(prisma);
59
62
  return createSiteroServer$1({
63
+ topics: Object.fromEntries(
64
+ Object.entries(input.topics).map(([key, { roles }]) => [
65
+ key,
66
+ { roles: [...roles] }
67
+ ])
68
+ ),
60
69
  authentication: {
61
70
  admin: {
62
71
  refreshTokenTtlSeconds: input.authentication?.refreshTokenTtlSeconds
@@ -79,6 +88,7 @@ function createSiteroServer(input) {
79
88
  }
80
89
  },
81
90
  resources: {
91
+ page: pagePrismaPorts,
82
92
  admin: {
83
93
  adminCommandPort: adminPrismaPorts.adminCommandPort,
84
94
  adminInquiryNotificationRecipientQueryPort: adminPrismaPorts.adminInquiryNotificationRecipientQueryPort,
@@ -5,11 +5,13 @@ import 'zod';
5
5
  import { createWebInquiryActions } from './features/inquiry/actions.js';
6
6
  import { createWebConfigActions } from './resources/config/actions.js';
7
7
  import { createWebPostActions } from './resources/post/actions.js';
8
+ import { createWebPageActions } from './resources/page/actions.js';
8
9
 
9
10
  function createWebServer({
10
11
  siteroServer,
11
12
  staticTopics
12
13
  }) {
14
+ const page = createWebPageActions({ siteroServer });
13
15
  const config = createWebConfigActions({ siteroServer });
14
16
  const inquiry = createWebInquiryActions({
15
17
  siteroServer,
@@ -22,13 +24,15 @@ function createWebServer({
22
24
  inquiry
23
25
  },
24
26
  resources: {
27
+ page: page.actions,
25
28
  config: config.actions,
26
29
  post: post.actions
27
30
  }
28
31
  },
29
32
  loaders: {
30
33
  ...config.loaders,
31
- ...post.loaders
34
+ ...post.loaders,
35
+ ...page.loaders
32
36
  }
33
37
  };
34
38
  }
@@ -0,0 +1,20 @@
1
+ import { operationResult, PageUnavailableError } from 'sitero-server';
2
+
3
+ function createWebPageActions({
4
+ siteroServer
5
+ }) {
6
+ const findDetail = async (input) => {
7
+ const page = siteroServer.resources.page;
8
+ if (!page) return operationResult.failure(new PageUnavailableError());
9
+ return siteroServer.executor.execute(page.findDetail, input, {});
10
+ };
11
+ const loadPage = async ({ pageSlug }) => {
12
+ const result = await findDetail({ key: pageSlug });
13
+ if (result.success) return { page: result.data.page };
14
+ if (result.error.code === "PAGE_NOT_FOUND") return { page: void 0 };
15
+ throw new Error(`[page.loadPage] ${result.error.code}`);
16
+ };
17
+ return { actions: { findDetail }, loaders: { loadPage } };
18
+ }
19
+
20
+ export { createWebPageActions };