@orthacms/content-server 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/dist/index.d.ts +16 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +41 -1
  4. package/dist/lib/content.module.d.ts.map +1 -1
  5. package/dist/lib/content.module.js +31 -1
  6. package/dist/lib/copilot/entry-proposal.applier.d.ts.map +1 -1
  7. package/dist/lib/copilot/entry-proposal.applier.js +5 -4
  8. package/dist/lib/docs/describe-content-api.d.ts +7 -0
  9. package/dist/lib/docs/describe-content-api.d.ts.map +1 -1
  10. package/dist/lib/docs/describe-content-api.js +177 -53
  11. package/dist/lib/docs/describe-views-api.d.ts +19 -0
  12. package/dist/lib/docs/describe-views-api.d.ts.map +1 -0
  13. package/dist/lib/docs/describe-views-api.js +76 -0
  14. package/dist/lib/docs/field-schema.d.ts.map +1 -1
  15. package/dist/lib/docs/field-schema.js +36 -2
  16. package/dist/lib/docs/openapi-writer.d.ts +49 -0
  17. package/dist/lib/docs/openapi-writer.d.ts.map +1 -0
  18. package/dist/lib/docs/openapi-writer.js +76 -0
  19. package/dist/lib/docs/public-api-schemas.d.ts +45 -0
  20. package/dist/lib/docs/public-api-schemas.d.ts.map +1 -0
  21. package/dist/lib/docs/public-api-schemas.js +377 -0
  22. package/dist/lib/docs/views-schemas.d.ts +22 -0
  23. package/dist/lib/docs/views-schemas.d.ts.map +1 -0
  24. package/dist/lib/docs/views-schemas.js +156 -0
  25. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts +8 -2
  26. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts.map +1 -1
  27. package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.js +19 -4
  28. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts +2 -2
  29. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts.map +1 -1
  30. package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.js +14 -4
  31. package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts +6 -8
  32. package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts.map +1 -1
  33. package/dist/lib/entries/application/use-cases/publish-entry.use-case.js +10 -4
  34. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts +2 -5
  35. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts.map +1 -1
  36. package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.js +6 -1
  37. package/dist/lib/entries/domain/entry.d.ts +8 -1
  38. package/dist/lib/entries/domain/entry.d.ts.map +1 -1
  39. package/dist/lib/entries/domain/entry.js +12 -12
  40. package/dist/lib/entries/domain/events/entry-events.d.ts +47 -5
  41. package/dist/lib/entries/domain/events/entry-events.d.ts.map +1 -1
  42. package/dist/lib/entries/domain/events/entry-events.js +26 -10
  43. package/dist/lib/entries/entries.constants.d.ts +10 -2
  44. package/dist/lib/entries/entries.constants.d.ts.map +1 -1
  45. package/dist/lib/entries/entries.constants.js +11 -2
  46. package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts +2 -2
  47. package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts.map +1 -1
  48. package/dist/lib/entries/http/controllers/bulk-entries.controller.js +8 -6
  49. package/dist/lib/entries/http/controllers/create-entry.controller.d.ts.map +1 -1
  50. package/dist/lib/entries/http/controllers/create-entry.controller.js +1 -1
  51. package/dist/lib/entries/http/controllers/update-entry.controller.d.ts.map +1 -1
  52. package/dist/lib/entries/http/controllers/update-entry.controller.js +1 -1
  53. package/dist/lib/entries/http/dto/extension-bag.validator.d.ts +14 -0
  54. package/dist/lib/entries/http/dto/extension-bag.validator.d.ts.map +1 -0
  55. package/dist/lib/entries/http/dto/extension-bag.validator.js +42 -0
  56. package/dist/lib/entries/http/dto/save-entry.dto.d.ts +16 -0
  57. package/dist/lib/entries/http/dto/save-entry.dto.d.ts.map +1 -1
  58. package/dist/lib/entries/http/dto/save-entry.dto.js +30 -0
  59. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts +50 -8
  60. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts.map +1 -1
  61. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.js +183 -32
  62. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts +38 -5
  63. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts.map +1 -1
  64. package/dist/lib/entries/infrastructure/persistence/relation-link.service.js +38 -6
  65. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts +3 -1
  66. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts.map +1 -1
  67. package/dist/lib/entries/infrastructure/queries/entries.service.js +17 -5
  68. package/dist/lib/entries/infrastructure/queries/entry-match.query.d.ts +82 -0
  69. package/dist/lib/entries/infrastructure/queries/entry-match.query.d.ts.map +1 -0
  70. package/dist/lib/entries/infrastructure/queries/entry-match.query.js +152 -0
  71. package/dist/lib/extension/entry-filter-provider.d.ts +79 -0
  72. package/dist/lib/extension/entry-filter-provider.d.ts.map +1 -0
  73. package/dist/lib/extension/entry-filter-provider.js +149 -0
  74. package/dist/lib/extension/entry-write-extension.d.ts +185 -0
  75. package/dist/lib/extension/entry-write-extension.d.ts.map +1 -0
  76. package/dist/lib/extension/entry-write-extension.js +182 -0
  77. package/dist/lib/extension/read-scope.d.ts +107 -0
  78. package/dist/lib/extension/read-scope.d.ts.map +1 -0
  79. package/dist/lib/extension/read-scope.js +131 -0
  80. package/dist/lib/insights/docs/describe-content-insights-api.d.ts +23 -0
  81. package/dist/lib/insights/docs/describe-content-insights-api.d.ts.map +1 -0
  82. package/dist/lib/insights/docs/describe-content-insights-api.js +329 -0
  83. package/dist/lib/mcp/content-tools.provider.d.ts.map +1 -1
  84. package/dist/lib/mcp/content-tools.provider.js +10 -9
  85. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts +14 -13
  86. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts.map +1 -1
  87. package/dist/lib/public-api/http/controllers/public-entry-writes.controller.js +62 -46
  88. package/dist/lib/public-api/http/guards/api-token-workspace.guard.d.ts.map +1 -1
  89. package/dist/lib/public-api/http/guards/api-token-workspace.guard.js +8 -0
  90. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts +14 -1
  91. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts.map +1 -1
  92. package/dist/lib/public-api/infrastructure/public-entries.query.js +20 -3
  93. package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts +10 -9
  94. package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts.map +1 -1
  95. package/dist/lib/public-api/infrastructure/public-entry-writes.service.js +23 -24
  96. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts +16 -4
  97. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts.map +1 -1
  98. package/dist/lib/public-api/infrastructure/public-expansion.query.js +29 -9
  99. package/dist/lib/public-api/infrastructure/token-actor.d.ts +37 -0
  100. package/dist/lib/public-api/infrastructure/token-actor.d.ts.map +1 -0
  101. package/dist/lib/public-api/infrastructure/token-actor.js +58 -0
  102. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts.map +1 -1
  103. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.js +23 -1
  104. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts +7 -1
  105. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts.map +1 -1
  106. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.js +9 -2
  107. package/dist/lib/revisions/infrastructure/purge/revisions-workspace.purger.d.ts +28 -0
  108. package/dist/lib/revisions/infrastructure/purge/revisions-workspace.purger.d.ts.map +1 -0
  109. package/dist/lib/revisions/infrastructure/purge/revisions-workspace.purger.js +52 -0
  110. package/dist/lib/revisions/types/revision-view.d.ts +11 -0
  111. package/dist/lib/revisions/types/revision-view.d.ts.map +1 -1
  112. package/dist/lib/utils/content-plugin.d.ts.map +1 -1
  113. package/dist/lib/utils/content-plugin.js +10 -1
  114. package/dist/lib/utils/content-views-plugin.d.ts +28 -0
  115. package/dist/lib/utils/content-views-plugin.d.ts.map +1 -0
  116. package/dist/lib/utils/content-views-plugin.js +37 -0
  117. package/dist/lib/views/application/queries/saved-views.query.d.ts +16 -0
  118. package/dist/lib/views/application/queries/saved-views.query.d.ts.map +1 -0
  119. package/dist/lib/views/application/queries/saved-views.query.js +46 -0
  120. package/dist/lib/views/application/saved-view-access.service.d.ts +30 -0
  121. package/dist/lib/views/application/saved-view-access.service.d.ts.map +1 -0
  122. package/dist/lib/views/application/saved-view-access.service.js +55 -0
  123. package/dist/lib/views/application/use-cases/create-saved-view.use-case.d.ts +30 -0
  124. package/dist/lib/views/application/use-cases/create-saved-view.use-case.d.ts.map +1 -0
  125. package/dist/lib/views/application/use-cases/create-saved-view.use-case.js +81 -0
  126. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.d.ts +18 -0
  127. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.d.ts.map +1 -0
  128. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.js +56 -0
  129. package/dist/lib/views/application/use-cases/set-default-view.use-case.d.ts +23 -0
  130. package/dist/lib/views/application/use-cases/set-default-view.use-case.d.ts.map +1 -0
  131. package/dist/lib/views/application/use-cases/set-default-view.use-case.js +51 -0
  132. package/dist/lib/views/application/use-cases/update-saved-view.use-case.d.ts +24 -0
  133. package/dist/lib/views/application/use-cases/update-saved-view.use-case.d.ts.map +1 -0
  134. package/dist/lib/views/application/use-cases/update-saved-view.use-case.js +90 -0
  135. package/dist/lib/views/application/view-scope.service.d.ts +25 -0
  136. package/dist/lib/views/application/view-scope.service.d.ts.map +1 -0
  137. package/dist/lib/views/application/view-scope.service.js +45 -0
  138. package/dist/lib/views/content-views.module.d.ts +22 -0
  139. package/dist/lib/views/content-views.module.d.ts.map +1 -0
  140. package/dist/lib/views/content-views.module.js +63 -0
  141. package/dist/lib/views/domain/errors/index.d.ts +6 -0
  142. package/dist/lib/views/domain/errors/index.d.ts.map +1 -0
  143. package/dist/lib/views/domain/errors/index.js +12 -0
  144. package/dist/lib/views/domain/errors/saved-view-forbidden.error.d.ts +10 -0
  145. package/dist/lib/views/domain/errors/saved-view-forbidden.error.d.ts.map +1 -0
  146. package/dist/lib/views/domain/errors/saved-view-forbidden.error.js +16 -0
  147. package/dist/lib/views/domain/errors/saved-view-limit-error.d.ts +9 -0
  148. package/dist/lib/views/domain/errors/saved-view-limit-error.d.ts.map +1 -0
  149. package/dist/lib/views/domain/errors/saved-view-limit-error.js +16 -0
  150. package/dist/lib/views/domain/errors/saved-view-name-taken.error.d.ts +5 -0
  151. package/dist/lib/views/domain/errors/saved-view-name-taken.error.d.ts.map +1 -0
  152. package/dist/lib/views/domain/errors/saved-view-name-taken.error.js +11 -0
  153. package/dist/lib/views/domain/errors/saved-view-not-found.error.d.ts +9 -0
  154. package/dist/lib/views/domain/errors/saved-view-not-found.error.d.ts.map +1 -0
  155. package/dist/lib/views/domain/errors/saved-view-not-found.error.js +15 -0
  156. package/dist/lib/views/domain/events/saved-view-events.d.ts +28 -0
  157. package/dist/lib/views/domain/events/saved-view-events.d.ts.map +1 -0
  158. package/dist/lib/views/domain/events/saved-view-events.js +38 -0
  159. package/dist/lib/views/domain/saved-view.d.ts +66 -0
  160. package/dist/lib/views/domain/saved-view.d.ts.map +1 -0
  161. package/dist/lib/views/domain/saved-view.js +18 -0
  162. package/dist/lib/views/domain/saved-view.repository.d.ts +77 -0
  163. package/dist/lib/views/domain/saved-view.repository.d.ts.map +1 -0
  164. package/dist/lib/views/domain/saved-view.repository.js +5 -0
  165. package/dist/lib/views/http/controllers/saved-views.controller.d.ts +45 -0
  166. package/dist/lib/views/http/controllers/saved-views.controller.d.ts.map +1 -0
  167. package/dist/lib/views/http/controllers/saved-views.controller.js +216 -0
  168. package/dist/lib/views/http/controllers/to-http-error.d.ts +10 -0
  169. package/dist/lib/views/http/controllers/to-http-error.d.ts.map +1 -0
  170. package/dist/lib/views/http/controllers/to-http-error.js +26 -0
  171. package/dist/lib/views/http/dto/save-view.dto.d.ts +54 -0
  172. package/dist/lib/views/http/dto/save-view.dto.d.ts.map +1 -0
  173. package/dist/lib/views/http/dto/save-view.dto.js +230 -0
  174. package/dist/lib/views/http/dto/view-payload.validator.d.ts +20 -0
  175. package/dist/lib/views/http/dto/view-payload.validator.d.ts.map +1 -0
  176. package/dist/lib/views/http/dto/view-payload.validator.js +52 -0
  177. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.d.ts +26 -0
  178. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.d.ts.map +1 -0
  179. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.js +135 -0
  180. package/dist/lib/views/infrastructure/schema/external-refs.d.ts +68 -0
  181. package/dist/lib/views/infrastructure/schema/external-refs.d.ts.map +1 -0
  182. package/dist/lib/views/infrastructure/schema/external-refs.js +29 -0
  183. package/dist/lib/views/infrastructure/schema/index.d.ts +8 -0
  184. package/dist/lib/views/infrastructure/schema/index.d.ts.map +1 -0
  185. package/dist/lib/views/infrastructure/schema/index.js +13 -0
  186. package/dist/lib/views/infrastructure/schema/saved-views.d.ts +275 -0
  187. package/dist/lib/views/infrastructure/schema/saved-views.d.ts.map +1 -0
  188. package/dist/lib/views/infrastructure/schema/saved-views.js +87 -0
  189. package/dist/lib/views/views.constants.d.ts +26 -0
  190. package/dist/lib/views/views.constants.d.ts.map +1 -0
  191. package/dist/lib/views/views.constants.js +28 -0
  192. package/dist/lib/views/views.tokens.d.ts +17 -0
  193. package/dist/lib/views/views.tokens.d.ts.map +1 -0
  194. package/dist/lib/views/views.tokens.js +21 -0
  195. package/migrations/0000_saved_views.sql +29 -0
  196. package/migrations/meta/0000_snapshot.json +256 -0
  197. package/migrations/meta/_journal.json +13 -0
  198. package/package.json +13 -12
  199. package/dist/lib/entries/controllers/bulk-entries.controller.d.ts +0 -26
  200. package/dist/lib/entries/controllers/bulk-entries.controller.d.ts.map +0 -1
  201. package/dist/lib/entries/controllers/create-entry.controller.d.ts +0 -20
  202. package/dist/lib/entries/controllers/create-entry.controller.d.ts.map +0 -1
  203. package/dist/lib/entries/controllers/delete-entry.controller.d.ts +0 -24
  204. package/dist/lib/entries/controllers/delete-entry.controller.d.ts.map +0 -1
  205. package/dist/lib/entries/controllers/get-entry.controller.d.ts +0 -34
  206. package/dist/lib/entries/controllers/get-entry.controller.d.ts.map +0 -1
  207. package/dist/lib/entries/controllers/list-entries.controller.d.ts +0 -20
  208. package/dist/lib/entries/controllers/list-entries.controller.d.ts.map +0 -1
  209. package/dist/lib/entries/controllers/publish-entry.controller.d.ts +0 -19
  210. package/dist/lib/entries/controllers/publish-entry.controller.d.ts.map +0 -1
  211. package/dist/lib/entries/controllers/resolve-type.d.ts +0 -9
  212. package/dist/lib/entries/controllers/resolve-type.d.ts.map +0 -1
  213. package/dist/lib/entries/controllers/update-entry.controller.d.ts +0 -18
  214. package/dist/lib/entries/controllers/update-entry.controller.d.ts.map +0 -1
  215. package/dist/lib/entries/dto/bulk-ids.dto.d.ts +0 -11
  216. package/dist/lib/entries/dto/bulk-ids.dto.d.ts.map +0 -1
  217. package/dist/lib/entries/dto/list-entries-query.dto.d.ts +0 -46
  218. package/dist/lib/entries/dto/list-entries-query.dto.d.ts.map +0 -1
  219. package/dist/lib/entries/dto/relation-delta-map.validator.d.ts +0 -19
  220. package/dist/lib/entries/dto/relation-delta-map.validator.d.ts.map +0 -1
  221. package/dist/lib/entries/dto/save-entry.dto.d.ts +0 -46
  222. package/dist/lib/entries/dto/save-entry.dto.d.ts.map +0 -1
  223. package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts +0 -24
  224. package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts.map +0 -1
  225. package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts +0 -40
  226. package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts.map +0 -1
  227. package/dist/lib/entries/services/entries.service.d.ts +0 -59
  228. package/dist/lib/entries/services/entries.service.d.ts.map +0 -1
  229. package/dist/lib/entries/services/entry-counter.service.d.ts +0 -31
  230. package/dist/lib/entries/services/entry-counter.service.d.ts.map +0 -1
  231. package/dist/lib/entries/services/entry-filter-schema.d.ts +0 -32
  232. package/dist/lib/entries/services/entry-filter-schema.d.ts.map +0 -1
  233. package/dist/lib/entries/services/entry-row.d.ts +0 -56
  234. package/dist/lib/entries/services/entry-row.d.ts.map +0 -1
  235. package/dist/lib/entries/services/entry-writer.service.d.ts +0 -193
  236. package/dist/lib/entries/services/entry-writer.service.d.ts.map +0 -1
  237. package/dist/lib/entries/services/relation-link.service.d.ts +0 -115
  238. package/dist/lib/entries/services/relation-link.service.d.ts.map +0 -1
  239. package/dist/lib/extension/per-locale-relation.d.ts +0 -18
  240. package/dist/lib/extension/per-locale-relation.d.ts.map +0 -1
  241. package/dist/lib/public/controllers/get-public-entry.controller.d.ts +0 -26
  242. package/dist/lib/public/controllers/get-public-entry.controller.d.ts.map +0 -1
  243. package/dist/lib/public/controllers/list-public-entries.controller.d.ts +0 -24
  244. package/dist/lib/public/controllers/list-public-entries.controller.d.ts.map +0 -1
  245. package/dist/lib/public/controllers/public-schema.controller.d.ts +0 -18
  246. package/dist/lib/public/controllers/public-schema.controller.d.ts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"bulk-ids.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/dto/bulk-ids.dto.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,UAAU;IACnB,2BAA2B;IAK3B,GAAG,EAAG,MAAM,EAAE,CAAC;CAClB"}
@@ -1,46 +0,0 @@
1
- /** `?deleted=only` flips the list to the trash view (soft-deleted rows). */
2
- export declare const DELETED_ONLY = "only";
3
- /**
4
- * Query parameters for `GET /api/content/:typeName`. Pagination is 1-based; the
5
- * service applies the defaults (page 1, {@link DEFAULT_PAGE_SIZE}) so the
6
- * contract has one source of truth. `@Type` coerces the raw query strings — the
7
- * host's global `ValidationPipe` transforms but does not implicitly convert.
8
- */
9
- export declare class ListEntriesQueryDto {
10
- /** Free-text search across the type's text-like columns (text/richtext/select). */
11
- search?: string;
12
- /**
13
- * Structured filter tree as a JSON string (`?filter=<json>`), produced by
14
- * the admin query builder and validated against the type's derived filter
15
- * schema by `parseFilterTree`. Length-capped here as a first line of
16
- * defence; the engine's node/depth caps bound the parsed shape.
17
- */
18
- filter?: string;
19
- /** Sort spec: a column id (ascending) or `-`-prefixed (descending). */
20
- sort?: string;
21
- /** 1-based page number. */
22
- page?: number;
23
- /** Rows per page, capped at {@link MAX_PAGE_SIZE}. */
24
- pageSize?: number;
25
- /**
26
- * `only` lists soft-deleted rows (the trash view) instead of live ones.
27
- * Meaningful only for paranoid types; ignored otherwise. Absent (the
28
- * default) lists live rows.
29
- */
30
- deleted?: typeof DELETED_ONLY;
31
- /**
32
- * Locale slug the list targets — an **extension-owned** param this package
33
- * declares (the strict ValidationPipe rejects undeclared keys) but never
34
- * interprets: it's forwarded to the bound `CONTENT_ENTRY_EXTENSION`, which
35
- * validates and applies it. Ignored when no extension is bound or the type
36
- * isn't localized.
37
- */
38
- locale?: string;
39
- /**
40
- * `default` widens the locale scope to fall back to the default locale
41
- * where the requested one is missing (the relation picker's mode).
42
- * Extension-owned, like {@link locale}.
43
- */
44
- localeFallback?: string;
45
- }
46
- //# sourceMappingURL=list-entries-query.dto.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-entries-query.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/dto/list-entries-query.dto.ts"],"names":[],"mappings":"AAYA,4EAA4E;AAC5E,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;;;;GAKG;AACH,qBAAa,mBAAmB;IAC5B,mFAAmF;IAInF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IAIH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,uEAAuE;IAIvE,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,2BAA2B;IAK3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IAMtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IAGH,OAAO,CAAC,EAAE,OAAO,YAAY,CAAC;IAE9B;;;;;;OAMG;IAIH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IAGH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B"}
@@ -1,19 +0,0 @@
1
- import { type ValidationOptions, type ValidatorConstraintInterface } from 'class-validator';
2
- /**
3
- * Validates the `relations` bag of {@link SaveEntryDto}: a map from field name to
4
- * `{ link?, unlink?, order? }`, each an array of uuid strings. class-validator
5
- * can't decorate a `Record`'s dynamic keys, so this constraint checks the shape
6
- * of every value — turning a malformed delta (a non-array `unlink`, a non-uuid
7
- * id, an unknown inner key, or an over-large array) into a clean **400** instead
8
- * of letting it reach `inArray(...)` against a `uuid` column and surface as a
9
- * 500. Unknown inner keys are rejected so the nested `Record` can't slip past
10
- * the app's `forbidNonWhitelisted` posture, and the id arrays and the map itself
11
- * are size-bounded so a single request can't carry an unbounded payload.
12
- */
13
- export declare class RelationDeltaMapConstraint implements ValidatorConstraintInterface {
14
- validate(value: unknown): boolean;
15
- defaultMessage(): string;
16
- }
17
- /** Property decorator applying {@link RelationDeltaMapConstraint}. */
18
- export declare function IsRelationDeltaMap(options?: ValidationOptions): (object: object, propertyName: string) => void;
19
- //# sourceMappingURL=relation-delta-map.validator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"relation-delta-map.validator.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/dto/relation-delta-map.validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EACpC,MAAM,iBAAiB,CAAC;AAmCzB;;;;;;;;;;GAUG;AACH,qBACa,0BACT,YAAW,4BAA4B;IAEvC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAwBjC,cAAc,IAAI,MAAM;CAG3B;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,iBAAiB,IAClD,QAAQ,MAAM,EAAE,cAAc,MAAM,KAAG,IAAI,CAOtD"}
@@ -1,46 +0,0 @@
1
- import type { RelationDelta } from '../types/entry-list-view';
2
- /**
3
- * Body for `POST /api/content/:typeName` (create) and
4
- * `PATCH /api/content/:typeName/:id` (update). The field `values` bag crosses the
5
- * wire, plus optional per-field relation **deltas** (`relations`) — the editor
6
- * stages its many-to-many / inverse link changes locally and sends them here
7
- * with the rest of the document, so a save persists everything in **one
8
- * transaction** without ever transmitting a huge relation whole.
9
- *
10
- * Reserved envelope columns (`status`/`published_at`/`deleted_at`) are owned by
11
- * the service and can't be set from here: `toColumns` projects only keys
12
- * declared on the type, so a reserved (or otherwise unknown) key in the bag is
13
- * silently dropped before storage; on a non-publishable type
14
- * `EntryValidationService` additionally flags unknown keys as a 422. The bag's
15
- * *contents* are validated against the type's field specs by that same service
16
- * (a dynamic, per-type contract class-validator can't express); the relation
17
- * deltas' ids are validated as existing workspace entries by
18
- * `RelationLinkService`. `values` is structurally only "an object" (its contents
19
- * are the per-type contract); the `relations` bag's *shape* — each value a
20
- * `{ link?, unlink?, order? }` of uuid arrays — is enforced here so a malformed
21
- * delta is a clean 400, not a 500 from a bad id hitting the query.
22
- */
23
- export declare class SaveEntryDto {
24
- /** Field values keyed by field name. */
25
- values: Record<string, unknown>;
26
- /**
27
- * Per-field relation deltas (`{ <field>: { link?, unlink?, order? } }`) —
28
- * many/inverse relations only; a single relation is set through `values`.
29
- */
30
- relations?: Record<string, RelationDelta>;
31
- /**
32
- * Locale slug the entry is created in — an **extension-owned** param this
33
- * package declares but never interprets (forwarded to the bound
34
- * `CONTENT_ENTRY_EXTENSION`, which validates it and stamps the envelope
35
- * column). Read on create only; an update never re-homes a row's locale.
36
- */
37
- locale?: string;
38
- /**
39
- * The existing translation group a created row joins (making it a sibling)
40
- * — an **extension-owned**, opaque param, like {@link locale}. Absent → the
41
- * row starts its own fresh group. The bound extension validates it against
42
- * the workspace. Read on create only.
43
- */
44
- localeGroupId?: string;
45
- }
46
- //# sourceMappingURL=save-entry.dto.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"save-entry.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/dto/save-entry.dto.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,YAAY;IACrB,wCAAwC;IAExC,MAAM,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjC;;;OAGG;IAIH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAE1C;;;;;OAKG;IAIH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IAGH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -1,24 +0,0 @@
1
- import type { AnyContentType } from '../../../types/content-type';
2
- /**
3
- * The set of field names a `?fields=` list selects, or `undefined` when the
4
- * caller asked for none (the default — the whole record).
5
- */
6
- export type FieldSelection = ReadonlySet<string> | undefined;
7
- /**
8
- * Parse `?fields=title,slug` into the set {@link toRecord} projects `values`
9
- * down to. Only fields that carry a column are selectable — a many-relation or
10
- * an inverse back-reference has no value on the row (its links live in a join
11
- * table), so naming one is a client error, not a silently empty key.
12
- *
13
- * **Unknown names are rejected with a 400**, deliberately unlike
14
- * `?relationFields=`, which drops them. That list is an internal rendering hint
15
- * where a hidden column legitimately vanishes; this one is an external API
16
- * contract, where silently honouring `?fields=titel` would return records with
17
- * no fields and no explanation. Failing loudly makes the typo obvious.
18
- *
19
- * Envelope data (`id`, timestamps, `status`/`publishedAt`, `locale`) is **not**
20
- * selectable and is always returned — it identifies the record rather than
21
- * describing it, and callers can ignore what they don't need.
22
- */
23
- export declare function parseFieldSelection(type: AnyContentType, raw: string | undefined): FieldSelection;
24
- //# sourceMappingURL=field-selection.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"field-selection.d.ts","sourceRoot":"","sources":["../../../../../src/lib/entries/infrastructure/persistence/field-selection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAC/B,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,GAAG,SAAS,GACxB,cAAc,CAiBhB"}
@@ -1,40 +0,0 @@
1
- import { type FieldSchema, type FilterSchema, type ScalarFieldSchema } from '@ortha-cms/utils-server';
2
- import { type AnyContentType } from '../../../types/content-type';
3
- import { type AnyFieldSpec } from '../../../types/fields';
4
- /**
5
- * The filter scalar type for one content field, or `null` to leave it
6
- * unfilterable. Mirrors the admin's `filterFieldsFromSchema`: text-like fields
7
- * filter as strings, `select` as an enum of its options, numerics as numbers,
8
- * dates as dates. `json`/`multiselect` have no scalar editor, and `relation`
9
- * filtering (by raw FK uuid) has no UI yet — all skipped.
10
- */
11
- export declare function scalarTypeFor(spec: AnyFieldSpec): ScalarFieldSchema | null;
12
- /**
13
- * Whether a field is backed by a comparable scalar column — the single source of
14
- * truth for "can this field be filtered or sorted". `json`/`multiselect` (jsonb)
15
- * and `relation` (FK uuid / join table) are not: they have no scalar editor and
16
- * ordering them is meaningless. The sort whitelist and the filter schema both
17
- * derive from this, so the two can't drift apart.
18
- */
19
- export declare function isScalarField(spec: AnyFieldSpec): boolean;
20
- /**
21
- * Build the query-builder `FilterSchema` for one content type at request time.
22
- * Whitelists the always-present envelope columns (`createdAt`/`updatedAt`),
23
- * plus `status`/`publishedAt` only on publishable types, plus `locale` on i18n
24
- * types, plus every filterable field (those `isScalarField` admits — the same
25
- * set the admin's `filterFieldsFromSchema` offers), keyed by the property
26
- * names the engine resolves to table columns. (`status` has a matching admin
27
- * filter; the timestamp envelopes like `publishedAt` are filterable via the
28
- * API but have no UI control yet.) This is the security boundary: only listed
29
- * fields/ops reach SQL, and the engine's depth/node caps bound payload
30
- * blow-up.
31
- *
32
- * `extensionFields` are **virtual** fields contributed by the bound
33
- * `CONTENT_ENTRY_EXTENSION` (e.g. locale aggregates): their declarations merge
34
- * into `fields` (so the parser can coerce values) and their names are
35
- * registered on the schema's `extensionFields` set, routing them to the
36
- * extension's own SQL resolver instead of a table column. A field column
37
- * always wins a name collision — an extension cannot shadow real data.
38
- */
39
- export declare function buildEntryFilterSchema(type: AnyContentType, extensionFields?: FieldSchema): FilterSchema;
40
- //# sourceMappingURL=entry-filter-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-filter-schema.d.ts","sourceRoot":"","sources":["../../../../../src/lib/entries/infrastructure/queries/entry-filter-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE9E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,GAAG,IAAI,CAsB1E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE,cAAc,EACpB,eAAe,CAAC,EAAE,WAAW,GAC9B,YAAY,CAmCd"}
@@ -1,59 +0,0 @@
1
- import { type Database } from '@ortha-cms/database';
2
- import { type ContentEntryExtension } from '../../extension/entry-extension';
3
- import type { AnyContentType } from '../../types/content-type';
4
- import { type ListEntriesQueryDto } from '../dto/list-entries-query.dto';
5
- import type { EntryListView } from '../types/entry-list-view';
6
- /**
7
- * Reads a collection's entries. Generic over the content type: the physical
8
- * table, the filterable columns, the searchable columns, and the sort whitelist
9
- * are all derived from `type` at request time, so one service backs every
10
- * collection. Owns no schema of its own — it queries the HOST-owned generated
11
- * `content_<name>` tables through the shared Drizzle client.
12
- */
13
- export declare class EntriesService {
14
- private readonly db;
15
- private readonly extension?;
16
- constructor(db: Database, extension?: ContentEntryExtension | undefined);
17
- /**
18
- * One page of a collection's entries: search → filter → sort → paginate, run
19
- * in SQL against the type's generated table, returned as the
20
- * `{ items, total, page, pageSize }` envelope the admin records table renders.
21
- * Scoped to `workspaceId` — only the calling workspace's entries are counted
22
- * or listed.
23
- */
24
- list(type: AnyContentType, query: ListEntriesQueryDto, workspaceId: string): Promise<EntryListView>;
25
- /**
26
- * The full WHERE: the workspace scope AND free-text search AND the
27
- * query-builder `?filter=` tree AND (for paranoid types) the not-deleted
28
- * guard. `and(undefined, …)` collapses empties, so an unfiltered list still
29
- * scans the workspace's whole table. The workspace predicate is always
30
- * present, so an entry never leaks across workspaces. A malformed filter
31
- * throws a `FilterException` (HTTP 400).
32
- */
33
- private listWhere;
34
- /**
35
- * The soft-delete guard for paranoid types: the default list excludes
36
- * tombstoned rows (`deleted_at IS NULL`); `?deleted=only` flips to the trash
37
- * view (`deleted_at IS NOT NULL`). A non-paranoid type has no `deleted_at`,
38
- * so the predicate collapses to `undefined`.
39
- */
40
- private deletedPredicate;
41
- /**
42
- * Case-insensitive `ILIKE` across the type's text-like columns, OR-ed
43
- * together; `undefined` when there's no search term. The needle's LIKE
44
- * metacharacters are escaped so a literal `%`/`_` searches literally.
45
- */
46
- private searchPredicate;
47
- /**
48
- * Translate the `?sort=` spec (`col` asc, `-col` desc) into an ORDER BY,
49
- * always with an `id` tiebreaker so pagination is stable across requests.
50
- * Sortable = the always-present envelope columns + `status` (publishable
51
- * only) + the type's **scalar** fields. Non-scalar fields (`json`/
52
- * `multiselect`, single/many `relation`) are excluded — a many-relation has
53
- * no column on the main table at all, so ordering by it would pass
54
- * `undefined` to `asc`/`desc`; the others have no meaningful order. An
55
- * unknown or excluded column falls back to `updatedAt` desc.
56
- */
57
- private orderBy;
58
- }
59
- //# sourceMappingURL=entries.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entries.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/services/entries.service.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAEH,KAAK,qBAAqB,EAC7B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAiB9D;;;;;;GAMG;AACH,qBACa,cAAc;IAED,OAAO,CAAC,QAAQ,CAAC,EAAE;IAKrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBALQ,EAAE,EAAE,QAAQ,EAK9B,SAAS,CAAC,EAAE,qBAAqB,YAAA;IAGtD;;;;;;OAMG;IACG,IAAI,CACN,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,mBAAmB,EAC1B,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,CAAC;IA8BzB;;;;;;;OAOG;YACW,SAAS;IAqCvB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAcvB;;;;;;;;;OASG;IACH,OAAO,CAAC,OAAO;CAsBlB"}
@@ -1,31 +0,0 @@
1
- import { type Database } from '@ortha-cms/database';
2
- import type { ContentEntryCounter } from '@ortha-cms/identity-server';
3
- import type { ContentTypeRegistry } from '../../registry/content-type-registry';
4
- /**
5
- * Implements identity's {@link ContentEntryCounter} port over the generated
6
- * `content_<name>` tables: counts how many entries of a content type a
7
- * workspace holds. Bound to `CONTENT_ENTRY_COUNTER` in {@link ContentModule},
8
- * so identity's "revoke a content-type grant only when empty" rule resolves
9
- * against the real stored entries.
10
- */
11
- export declare class EntryCounterService implements ContentEntryCounter {
12
- private readonly db;
13
- private readonly registry;
14
- constructor(db: Database, registry: ContentTypeRegistry);
15
- /**
16
- * Every stored row of content type `slug` in `workspaceId`. Counts the
17
- * whole workspace slice of the type's table — including soft-deleted rows
18
- * for paranoid types (data that still exists must keep the grant). An
19
- * unknown slug (no such content type) counts as `0`.
20
- */
21
- countEntries(workspaceId: string, slug: string): Promise<number>;
22
- /**
23
- * Every stored row the workspace holds across **all** content types —
24
- * summed over each type's table. Backs the workspace-delete guard (delete is
25
- * refused until this is zero). The per-type counts run concurrently.
26
- */
27
- countWorkspaceEntries(workspaceId: string): Promise<number>;
28
- /** Counts a single content type's rows in a workspace. */
29
- private countTable;
30
- }
31
- //# sourceMappingURL=entry-counter.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-counter.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/services/entry-counter.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAMhF;;;;;;GAMG;AACH,qBACa,mBAAoB,YAAW,mBAAmB;IAErC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADf,EAAE,EAAE,QAAQ,EACL,QAAQ,EAAE,mBAAmB;IAG3E;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMtE;;;;OAIG;IACG,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASjE,0DAA0D;YAC5C,UAAU;CAW3B"}
@@ -1,32 +0,0 @@
1
- import { type FieldSchema, type FilterSchema } from '@ortha-cms/utils-server';
2
- import { type AnyContentType } from '../../types/content-type';
3
- import { type AnyFieldSpec } from '../../types/fields';
4
- /**
5
- * Whether a field is backed by a comparable scalar column — the single source of
6
- * truth for "can this field be filtered or sorted". `json`/`multiselect` (jsonb)
7
- * and `relation` (FK uuid / join table) are not: they have no scalar editor and
8
- * ordering them is meaningless. The sort whitelist and the filter schema both
9
- * derive from this, so the two can't drift apart.
10
- */
11
- export declare function isScalarField(spec: AnyFieldSpec): boolean;
12
- /**
13
- * Build the query-builder `FilterSchema` for one content type at request time.
14
- * Whitelists the always-present envelope columns (`createdAt`/`updatedAt`),
15
- * plus `status`/`publishedAt` only on publishable types, plus `locale` on i18n
16
- * types, plus every filterable field (those `isScalarField` admits — the same
17
- * set the admin's `filterFieldsFromSchema` offers), keyed by the property
18
- * names the engine resolves to table columns. (`status` has a matching admin
19
- * filter; the timestamp envelopes like `publishedAt` are filterable via the
20
- * API but have no UI control yet.) This is the security boundary: only listed
21
- * fields/ops reach SQL, and the engine's depth/node caps bound payload
22
- * blow-up.
23
- *
24
- * `extensionFields` are **virtual** fields contributed by the bound
25
- * `CONTENT_ENTRY_EXTENSION` (e.g. locale aggregates): their declarations merge
26
- * into `fields` (so the parser can coerce values) and their names are
27
- * registered on the schema's `extensionFields` set, routing them to the
28
- * extension's own SQL resolver instead of a table column. A field column
29
- * always wins a name collision — an extension cannot shadow real data.
30
- */
31
- export declare function buildEntryFilterSchema(type: AnyContentType, extensionFields?: FieldSchema): FilterSchema;
32
- //# sourceMappingURL=entry-filter-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-filter-schema.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/services/entry-filter-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,WAAW,EAChB,KAAK,YAAY,EAEpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiC3E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE,cAAc,EACpB,eAAe,CAAC,EAAE,WAAW,GAC9B,YAAY,CAmCd"}
@@ -1,56 +0,0 @@
1
- /**
2
- * Pure row ↔ entry mappers shared by the read ({@link EntriesService}) and write
3
- * ({@link EntryWriterService}) paths, so the wire shape and the column projection
4
- * have one definition each. No DB access, no NestJS — just shape translation.
5
- */
6
- import type { AnyContentType } from '../../types/content-type';
7
- import type { EntryRecord } from '../types/entry-list-view';
8
- /** A generated content table row seen as a bag of values by property name. */
9
- type Row = Record<string, unknown>;
10
- /**
11
- * Map a raw DB row to the admin {@link EntryRecord}: envelope fields plus a
12
- * `values` bag keyed by field name. `status` is emitted only for publishable
13
- * types. Relations that own no column — many-relations (their links live in join
14
- * tables) and inverse/back-references (they reuse the owning side's storage) —
15
- * aren't selected here; an owning single relation passes through as its FK uuid.
16
- */
17
- export declare function toRecord(type: AnyContentType, row: Row): EntryRecord;
18
- /**
19
- * Normalize the admin's (string-shaped) `values` bag to the proper JS types the
20
- * validator and storage expect — numbers parsed, JSON text parsed, empties
21
- * collapsed to null — keeping every field (so a many-relation array still
22
- * validates). The single coercion point: both {@link toColumns} (storage) and
23
- * the writer's validation run against the result, so they can't disagree on a
24
- * value's type. Datetime/date stay ISO strings (the validator accepts them;
25
- * {@link toColumns} converts datetime to `Date` for `timestamptz`).
26
- */
27
- export declare function coerceValues(type: AnyContentType, values: Record<string, unknown>): Record<string, unknown>;
28
- /**
29
- * Project a (coerced) `values` bag onto the columns of a generated table for an
30
- * insert/update. Includes only keys declared on the type (reserved envelope
31
- * columns — `status`/`published_at`/`deleted_at`/timestamps — are owned by the
32
- * service, never the client), skips relations that own no column (many-relations,
33
- * whose links live in join tables, and inverse/back-references, which reuse the
34
- * owning side's storage), collapses empties to `null`, converts a `datetime` to a `Date` for
35
- * the `timestamptz` column (guarding an invalid date to `null` rather than
36
- * letting `pg` throw), and drops a `NaN` number to `null`. A field absent from
37
- * `values` is written as `null` — the editor submits the full bag, so a write
38
- * replaces the whole document.
39
- */
40
- export declare function toColumns(type: AnyContentType, values: Record<string, unknown>): Record<string, unknown>;
41
- /**
42
- * A human display label for an entry — the first non-empty title-eligible field's
43
- * value (see {@link TITLE_FIELD_TYPES}), falling back to the id. Used to label
44
- * rows in the bulk-publish preview.
45
- */
46
- export declare function entryTitle(type: AnyContentType, row: Row): string;
47
- /**
48
- * The slug handle for an entry — the value of its **slug field**: the first
49
- * field flagged `admin.widget === 'slug'`, else a field literally named `slug`.
50
- * Returns the trimmed value when present and non-empty, otherwise `undefined`
51
- * (the type has no slug field, or the row's slug is blank). Used to give a
52
- * linked relation record a stable `/handle` in the admin.
53
- */
54
- export declare function entrySlug(type: AnyContentType, row: Row): string | undefined;
55
- export {};
56
- //# sourceMappingURL=entry-row.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-row.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/services/entry-row.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,8EAA8E;AAC9E,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,WAAW,CAwBpE;AAKD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CACxB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgCzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAWD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,MAAM,CAOjE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAS5E"}
@@ -1,193 +0,0 @@
1
- import { type Database } from '@ortha-cms/database';
2
- import { type ContentEntryExtension } from '../../extension/entry-extension';
3
- import type { AnyContentType } from '../../types/content-type';
4
- import { EntryValidationService } from '../../validation/services/entry-validation.service';
5
- import type { EntryRecord, RelationDelta, RelationFieldView } from '../types/entry-list-view';
6
- import { type BulkActionResult, type BulkPublishPreview, type BulkPublishResult } from '../types/bulk-publish';
7
- import { RelationLinkService } from './relation-link.service';
8
- /**
9
- * The write half of the entries pipeline — create / read-one / update / publish
10
- * / unpublish / delete / restore / purge, plus their bulk variants. Generic over
11
- * the content type (like {@link EntriesService}): the physical table and its
12
- * envelope columns are derived from `type` at request time, so one service backs
13
- * every collection. {@link EntryValidationService} is the gate — nothing is
14
- * written or published without passing it.
15
- */
16
- export declare class EntryWriterService {
17
- private readonly db;
18
- private readonly validation;
19
- private readonly relations;
20
- private readonly extension?;
21
- constructor(db: Database, validation: EntryValidationService, relations: RelationLinkService, extension?: ContentEntryExtension | undefined);
22
- /**
23
- * Create an entry **owned by `workspaceId`** (stamped onto the row so the
24
- * reader's workspace filter and every later scoped write see it). A
25
- * publishable type starts as a **draft** and may be incomplete — validation
26
- * is deferred to publish. A non-publishable type is always live, so its
27
- * values must validate now.
28
- *
29
- * The insert runs in a transaction that first takes the workspace's *shared*
30
- * content lock ({@link lockWorkspaceShared}): it coordinates with the
31
- * workspace delete / content-revoke guards (which take the lock exclusively),
32
- * so a new entry can't land between their emptiness check and their mutation
33
- * and be orphaned. Shared mode keeps concurrent creates non-blocking.
34
- *
35
- * `locale` / `localeGroupId` are opaque, extension-owned params: the bound
36
- * extension validates them and stamps the envelope columns (a
37
- * `localeGroupId` makes the row a **sibling** in that translation group). A
38
- * duplicate `(group, locale)` surfaces as a **409** via {@link uniqueGuarded}.
39
- */
40
- create(type: AnyContentType, values: Record<string, unknown>, workspaceId: string, relations?: Record<string, RelationDelta>, locale?: string, localeGroupId?: string): Promise<EntryRecord>;
41
- /**
42
- * First page (+ total) of every relation field's links for one live entry,
43
- * keyed by field name — what the editor loads on open. Each field is
44
- * paginated, so a relation with many links contributes only its first page.
45
- * 404 if the entry is missing (or soft-deleted) in this workspace.
46
- */
47
- getRelations(type: AnyContentType, id: string, workspaceId: string): Promise<Record<string, RelationFieldView>>;
48
- /**
49
- * One page of a single relation field's links (infinite-scroll for a
50
- * many/inverse relation). 404 if the entry is missing; 400 if `field` isn't a
51
- * relation on the type.
52
- */
53
- getRelationField(type: AnyContentType, id: string, field: string, page: number, pageSize: number, workspaceId: string): Promise<RelationFieldView>;
54
- /**
55
- * Apply the staged per-field relation deltas of a save, inside the entry's
56
- * transaction — so the row and every link change commit or roll back as one.
57
- * Each field must be a **many/inverse** relation (a single relation is set
58
- * through `values`); a single-relation or unknown key is a 400. `applyDelta`
59
- * validates the linked ids against the workspace (422 on a bad target).
60
- */
61
- private applyRelationDeltas;
62
- /** Resolve a relation field spec on the type, or 400 if it isn't one. */
63
- private relationSpec;
64
- /** Read one live entry in the workspace, or 404. */
65
- getOne(type: AnyContentType, id: string, workspaceId: string): Promise<EntryRecord>;
66
- /**
67
- * Replace a live entry's values, or 404. As with {@link create}, a
68
- * publishable type's values aren't validated here (a draft may be saved
69
- * incomplete; publish enforces the rules) — a non-publishable, always-live
70
- * type validates now.
71
- */
72
- update(type: AnyContentType, id: string, values: Record<string, unknown>, workspaceId: string, relations?: Record<string, RelationDelta>): Promise<EntryRecord>;
73
- /** Validate the stored row, then mark it published (publishable types only). */
74
- publish(type: AnyContentType, id: string, workspaceId: string): Promise<EntryRecord>;
75
- /** Revert a live entry to draft (publishable types only). */
76
- unpublish(type: AnyContentType, id: string, workspaceId: string): Promise<EntryRecord>;
77
- /**
78
- * Delete an entry: soft (stamp `deleted_at`) for a paranoid type, hard
79
- * `DELETE` otherwise. 404 if there's no live row to remove **in this
80
- * workspace** — an id from another workspace is indistinguishable from a
81
- * missing one.
82
- */
83
- remove(type: AnyContentType, id: string, workspaceId: string): Promise<void>;
84
- /**
85
- * Clear a soft-deleted entry's tombstone (paranoid types only), or 404.
86
- * On an i18n type the restore can collide with a row created in the same
87
- * (locale group, locale) slot after the soft delete — the partial unique
88
- * index rejects it, surfaced as a 409 rather than a 500.
89
- */
90
- restore(type: AnyContentType, id: string, workspaceId: string): Promise<EntryRecord>;
91
- /** Permanently delete a tombstoned entry (paranoid types only), or 404. */
92
- purge(type: AnyContentType, id: string, workspaceId: string): Promise<void>;
93
- /**
94
- * Dry-run a publish over a set of ids: validate each live row and report a
95
- * verdict (will-publish / already-published / blocked / not-found) in
96
- * request order. Writes nothing.
97
- */
98
- previewBulkPublish(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkPublishPreview>;
99
- /**
100
- * Commit a bulk publish. The validation gate is **locked**: the candidate
101
- * rows are selected `FOR UPDATE` and re-validated inside one transaction, so
102
- * a concurrent edit can't invalidate a row between the dry run and the write
103
- * (the single-statement preview-then-update split had that TOCTOU window).
104
- * Publishes only the `publishable` ids, reporting which were skipped and why.
105
- */
106
- bulkPublish(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkPublishResult>;
107
- /**
108
- * Compute the per-entry publish verdict (will-publish / already-published /
109
- * blocked / not-found) for `ids` in request order, given the live rows keyed
110
- * by id. Pure — the dry run and the committed {@link bulkPublish} share it so
111
- * they can't disagree on what's publishable.
112
- */
113
- private verdictsFor;
114
- /**
115
- * The per-field publish-gate checklist for one record: every required field
116
- * plus any field that has an issue, each marked pass/fail. Mirrors the
117
- * editor's Publish Gate so a row can show its passed fields, not just the
118
- * failures.
119
- */
120
- private buildChecks;
121
- /** Revert a set of live entries to draft. */
122
- bulkUnpublish(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkActionResult>;
123
- /** Delete a set of entries: soft for paranoid types, hard otherwise. */
124
- bulkRemove(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkActionResult>;
125
- /** Permanently delete a set of tombstoned entries (paranoid types only). */
126
- bulkPurge(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkActionResult>;
127
- /**
128
- * Restore a set of soft-deleted entries (paranoid types only). As with
129
- * {@link restore}, a restored row colliding with a live sibling in its
130
- * (locale group, locale) slot is a 409 — the whole batch rolls back
131
- * (single statement), so the caller can retry without the conflicting id.
132
- */
133
- bulkRestore(type: AnyContentType, ids: string[], workspaceId: string): Promise<BulkActionResult>;
134
- /**
135
- * Run a write, translating a Postgres unique violation (23505) into a 409.
136
- * Only i18n types carry a restore-relevant unique index — the partial
137
- * `(locale_group_id, locale)` one — so the mapping is scoped to them and
138
- * any other type's violation still surfaces as the bug it is.
139
- */
140
- private uniqueGuarded;
141
- /** The type's generated table seen as a column bag (envelope + fields). */
142
- private columns;
143
- /**
144
- * `workspace_id = :workspaceId` — the ownership predicate every read and
145
- * write AND-s in, so a request scoped to one workspace can neither see nor
146
- * mutate another's rows.
147
- */
148
- private scope;
149
- /**
150
- * `id = :id` AND the workspace scope AND (for paranoid types)
151
- * `deleted_at IS NULL`.
152
- */
153
- private liveWhere;
154
- /** Fetch one live row by id in the workspace, or undefined. */
155
- private findLive;
156
- /** Fetch the workspace's live rows for a set of ids, keyed by id. */
157
- private loadLiveByIds;
158
- /**
159
- * Verify every referenced relation target exists **in the same workspace** —
160
- * single FKs, many-to-many links, and the inverse (back-reference) side of a
161
- * two-way relation. Neither the FK column nor the join table has a workspace
162
- * constraint of its own (the target table is workspace-scoped only at the app
163
- * layer), so without this a caller could reference — or probe the existence
164
- * of — an entry in another workspace. Batched one existence query per
165
- * referenced target type; a missing or cross-workspace target surfaces as a
166
- * uniform 422 validation issue (indistinguishable from a plain "invalid id",
167
- * so no not-found-vs-forbidden enumeration signal). Runs on every
168
- * create/update, draft or not, because links are written eagerly either way.
169
- * An inverse-of-single (one-to-many) field owns no writable link from this
170
- * side, so it's skipped.
171
- */
172
- private assertRelationTargets;
173
- /**
174
- * Enforce required **link-managed** relations (an owning many-to-many, or the
175
- * inverse of one) against the entry's actual link set — the check
176
- * {@link EntryValidationService} can't make, because those links never travel
177
- * in the `values` bag it sees. A required such relation with zero links is a
178
- * 422 `is required`, matching how a required scalar field reads. A single FK
179
- * relation is validated in `values` already; an inverse-of-single owns no
180
- * writable link from this side, so it's skipped (it can't be satisfied here).
181
- * `exec` is the write transaction on create/update (so it counts the
182
- * just-written, uncommitted rows) or the root client on publish (committed).
183
- */
184
- private assertRequiredRelations;
185
- /** Throw 422 with the issue list when the values fail validation. */
186
- private assertValid;
187
- /** Reject publish/unpublish on a type with no publish workflow. */
188
- private assertPublishable;
189
- /** Reject restore/purge on a type without soft delete. */
190
- private assertParanoid;
191
- private notFound;
192
- }
193
- //# sourceMappingURL=entry-writer.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-writer.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/entries/services/entry-writer.service.ts"],"names":[],"mappings":"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"}