@byline/core 0.9.3

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 (283) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +17 -0
  3. package/dist/@types/admin-types.d.ts +275 -0
  4. package/dist/@types/admin-types.d.ts.map +1 -0
  5. package/dist/@types/admin-types.js +18 -0
  6. package/dist/@types/admin-types.js.map +1 -0
  7. package/dist/@types/collection-types.d.ts +816 -0
  8. package/dist/@types/collection-types.d.ts.map +1 -0
  9. package/dist/@types/collection-types.js +217 -0
  10. package/dist/@types/collection-types.js.map +1 -0
  11. package/dist/@types/db-types.d.ts +463 -0
  12. package/dist/@types/db-types.d.ts.map +1 -0
  13. package/dist/@types/db-types.js +2 -0
  14. package/dist/@types/db-types.js.map +1 -0
  15. package/dist/@types/field-data-types.d.ts +147 -0
  16. package/dist/@types/field-data-types.d.ts.map +1 -0
  17. package/dist/@types/field-data-types.js +38 -0
  18. package/dist/@types/field-data-types.js.map +1 -0
  19. package/dist/@types/field-types.d.ts +579 -0
  20. package/dist/@types/field-types.d.ts.map +1 -0
  21. package/dist/@types/field-types.js +32 -0
  22. package/dist/@types/field-types.js.map +1 -0
  23. package/dist/@types/index.d.ts +18 -0
  24. package/dist/@types/index.d.ts.map +1 -0
  25. package/dist/@types/index.js +18 -0
  26. package/dist/@types/index.js.map +1 -0
  27. package/dist/@types/populate-types.d.ts +54 -0
  28. package/dist/@types/populate-types.d.ts.map +1 -0
  29. package/dist/@types/populate-types.js +9 -0
  30. package/dist/@types/populate-types.js.map +1 -0
  31. package/dist/@types/query-predicate.d.ts +74 -0
  32. package/dist/@types/query-predicate.d.ts.map +1 -0
  33. package/dist/@types/query-predicate.js +9 -0
  34. package/dist/@types/query-predicate.js.map +1 -0
  35. package/dist/@types/site-config.d.ts +212 -0
  36. package/dist/@types/site-config.d.ts.map +1 -0
  37. package/dist/@types/site-config.js +9 -0
  38. package/dist/@types/site-config.js.map +1 -0
  39. package/dist/@types/storage-types.d.ts +86 -0
  40. package/dist/@types/storage-types.d.ts.map +1 -0
  41. package/dist/@types/storage-types.js +9 -0
  42. package/dist/@types/storage-types.js.map +1 -0
  43. package/dist/@types/store-types.d.ts +134 -0
  44. package/dist/@types/store-types.d.ts.map +1 -0
  45. package/dist/@types/store-types.js +24 -0
  46. package/dist/@types/store-types.js.map +1 -0
  47. package/dist/@types/type-utils.d.ts +17 -0
  48. package/dist/@types/type-utils.d.ts.map +1 -0
  49. package/dist/@types/type-utils.js +9 -0
  50. package/dist/@types/type-utils.js.map +1 -0
  51. package/dist/auth/apply-before-read.d.ts +36 -0
  52. package/dist/auth/apply-before-read.d.ts.map +1 -0
  53. package/dist/auth/apply-before-read.js +68 -0
  54. package/dist/auth/apply-before-read.js.map +1 -0
  55. package/dist/auth/apply-before-read.test.node.d.ts +9 -0
  56. package/dist/auth/apply-before-read.test.node.d.ts.map +1 -0
  57. package/dist/auth/apply-before-read.test.node.js +144 -0
  58. package/dist/auth/apply-before-read.test.node.js.map +1 -0
  59. package/dist/auth/assert-actor-can-perform.d.ts +39 -0
  60. package/dist/auth/assert-actor-can-perform.d.ts.map +1 -0
  61. package/dist/auth/assert-actor-can-perform.js +64 -0
  62. package/dist/auth/assert-actor-can-perform.js.map +1 -0
  63. package/dist/auth/assert-actor-can-perform.test.node.d.ts +9 -0
  64. package/dist/auth/assert-actor-can-perform.test.node.d.ts.map +1 -0
  65. package/dist/auth/assert-actor-can-perform.test.node.js +119 -0
  66. package/dist/auth/assert-actor-can-perform.test.node.js.map +1 -0
  67. package/dist/auth/index.d.ts +11 -0
  68. package/dist/auth/index.d.ts.map +1 -0
  69. package/dist/auth/index.js +11 -0
  70. package/dist/auth/index.js.map +1 -0
  71. package/dist/auth/register-collection-abilities.d.ts +40 -0
  72. package/dist/auth/register-collection-abilities.d.ts.map +1 -0
  73. package/dist/auth/register-collection-abilities.js +87 -0
  74. package/dist/auth/register-collection-abilities.js.map +1 -0
  75. package/dist/auth/register-collection-abilities.test.node.d.ts +9 -0
  76. package/dist/auth/register-collection-abilities.test.node.d.ts.map +1 -0
  77. package/dist/auth/register-collection-abilities.test.node.js +124 -0
  78. package/dist/auth/register-collection-abilities.test.node.js.map +1 -0
  79. package/dist/config/config.d.ts +10 -0
  80. package/dist/config/config.d.ts.map +1 -0
  81. package/dist/config/config.js +108 -0
  82. package/dist/config/config.js.map +1 -0
  83. package/dist/config/routes.d.ts +16 -0
  84. package/dist/config/routes.d.ts.map +1 -0
  85. package/dist/config/routes.js +26 -0
  86. package/dist/config/routes.js.map +1 -0
  87. package/dist/config/validate-admin-configs.d.ts +33 -0
  88. package/dist/config/validate-admin-configs.d.ts.map +1 -0
  89. package/dist/config/validate-admin-configs.js +250 -0
  90. package/dist/config/validate-admin-configs.js.map +1 -0
  91. package/dist/config/validate-admin-configs.test.node.d.ts +9 -0
  92. package/dist/config/validate-admin-configs.test.node.d.ts.map +1 -0
  93. package/dist/config/validate-admin-configs.test.node.js +224 -0
  94. package/dist/config/validate-admin-configs.test.node.js.map +1 -0
  95. package/dist/config/validate-collections.d.ts +33 -0
  96. package/dist/config/validate-collections.d.ts.map +1 -0
  97. package/dist/config/validate-collections.js +70 -0
  98. package/dist/config/validate-collections.js.map +1 -0
  99. package/dist/config/validate-collections.test.node.d.ts +9 -0
  100. package/dist/config/validate-collections.test.node.d.ts.map +1 -0
  101. package/dist/config/validate-collections.test.node.js +149 -0
  102. package/dist/config/validate-collections.test.node.js.map +1 -0
  103. package/dist/core.d.ts +89 -0
  104. package/dist/core.d.ts.map +1 -0
  105. package/dist/core.js +99 -0
  106. package/dist/core.js.map +1 -0
  107. package/dist/defaults/default-values.d.ts +13 -0
  108. package/dist/defaults/default-values.d.ts.map +1 -0
  109. package/dist/defaults/default-values.js +60 -0
  110. package/dist/defaults/default-values.js.map +1 -0
  111. package/dist/index.d.ts +20 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +36 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/lib/errors.d.ts +98 -0
  116. package/dist/lib/errors.d.ts.map +1 -0
  117. package/dist/lib/errors.js +134 -0
  118. package/dist/lib/errors.js.map +1 -0
  119. package/dist/lib/logger.d.ts +62 -0
  120. package/dist/lib/logger.d.ts.map +1 -0
  121. package/dist/lib/logger.js +120 -0
  122. package/dist/lib/logger.js.map +1 -0
  123. package/dist/lib/registry.d.ts +65 -0
  124. package/dist/lib/registry.d.ts.map +1 -0
  125. package/dist/lib/registry.js +133 -0
  126. package/dist/lib/registry.js.map +1 -0
  127. package/dist/logger/index.d.ts +3 -0
  128. package/dist/logger/index.d.ts.map +1 -0
  129. package/dist/logger/index.js +3 -0
  130. package/dist/logger/index.js.map +1 -0
  131. package/dist/patches/apply-patches.d.ts +21 -0
  132. package/dist/patches/apply-patches.d.ts.map +1 -0
  133. package/dist/patches/apply-patches.js +357 -0
  134. package/dist/patches/apply-patches.js.map +1 -0
  135. package/dist/patches/index.d.ts +3 -0
  136. package/dist/patches/index.d.ts.map +1 -0
  137. package/dist/patches/index.js +4 -0
  138. package/dist/patches/index.js.map +1 -0
  139. package/dist/patches/patch-types.d.ts +82 -0
  140. package/dist/patches/patch-types.d.ts.map +1 -0
  141. package/dist/patches/patch-types.js +3 -0
  142. package/dist/patches/patch-types.js.map +1 -0
  143. package/dist/patches/patch.test.node.d.ts +2 -0
  144. package/dist/patches/patch.test.node.d.ts.map +1 -0
  145. package/dist/patches/patch.test.node.js +193 -0
  146. package/dist/patches/patch.test.node.js.map +1 -0
  147. package/dist/query/parse-where.d.ts +100 -0
  148. package/dist/query/parse-where.d.ts.map +1 -0
  149. package/dist/query/parse-where.js +352 -0
  150. package/dist/query/parse-where.js.map +1 -0
  151. package/dist/query/parse-where.test.node.d.ts +9 -0
  152. package/dist/query/parse-where.test.node.d.ts.map +1 -0
  153. package/dist/query/parse-where.test.node.js +581 -0
  154. package/dist/query/parse-where.test.node.js.map +1 -0
  155. package/dist/schemas/zod/builder.d.ts +466 -0
  156. package/dist/schemas/zod/builder.d.ts.map +1 -0
  157. package/dist/schemas/zod/builder.js +276 -0
  158. package/dist/schemas/zod/builder.js.map +1 -0
  159. package/dist/schemas/zod/cache.d.ts +14 -0
  160. package/dist/schemas/zod/cache.d.ts.map +1 -0
  161. package/dist/schemas/zod/cache.js +40 -0
  162. package/dist/schemas/zod/cache.js.map +1 -0
  163. package/dist/schemas/zod/index.d.ts +4 -0
  164. package/dist/schemas/zod/index.d.ts.map +1 -0
  165. package/dist/schemas/zod/index.js +4 -0
  166. package/dist/schemas/zod/index.js.map +1 -0
  167. package/dist/schemas/zod/types.d.ts +13 -0
  168. package/dist/schemas/zod/types.d.ts.map +1 -0
  169. package/dist/schemas/zod/types.js +2 -0
  170. package/dist/schemas/zod/types.js.map +1 -0
  171. package/dist/services/collection-bootstrap.d.ts +46 -0
  172. package/dist/services/collection-bootstrap.d.ts.map +1 -0
  173. package/dist/services/collection-bootstrap.js +108 -0
  174. package/dist/services/collection-bootstrap.js.map +1 -0
  175. package/dist/services/collection-bootstrap.test.node.d.ts +9 -0
  176. package/dist/services/collection-bootstrap.test.node.d.ts.map +1 -0
  177. package/dist/services/collection-bootstrap.test.node.js +208 -0
  178. package/dist/services/collection-bootstrap.test.node.js.map +1 -0
  179. package/dist/services/document-lifecycle.d.ts +245 -0
  180. package/dist/services/document-lifecycle.d.ts.map +1 -0
  181. package/dist/services/document-lifecycle.js +481 -0
  182. package/dist/services/document-lifecycle.js.map +1 -0
  183. package/dist/services/document-lifecycle.test.node.d.ts +9 -0
  184. package/dist/services/document-lifecycle.test.node.d.ts.map +1 -0
  185. package/dist/services/document-lifecycle.test.node.js +781 -0
  186. package/dist/services/document-lifecycle.test.node.js.map +1 -0
  187. package/dist/services/document-read.d.ts +26 -0
  188. package/dist/services/document-read.d.ts.map +1 -0
  189. package/dist/services/document-read.js +60 -0
  190. package/dist/services/document-read.js.map +1 -0
  191. package/dist/services/field-upload.d.ts +100 -0
  192. package/dist/services/field-upload.d.ts.map +1 -0
  193. package/dist/services/field-upload.js +328 -0
  194. package/dist/services/field-upload.js.map +1 -0
  195. package/dist/services/field-upload.test.node.d.ts +9 -0
  196. package/dist/services/field-upload.test.node.d.ts.map +1 -0
  197. package/dist/services/field-upload.test.node.js +337 -0
  198. package/dist/services/field-upload.test.node.js.map +1 -0
  199. package/dist/services/index.d.ts +10 -0
  200. package/dist/services/index.d.ts.map +1 -0
  201. package/dist/services/index.js +11 -0
  202. package/dist/services/index.js.map +1 -0
  203. package/dist/services/populate.d.ts +299 -0
  204. package/dist/services/populate.d.ts.map +1 -0
  205. package/dist/services/populate.js +484 -0
  206. package/dist/services/populate.js.map +1 -0
  207. package/dist/services/populate.test.node.d.ts +9 -0
  208. package/dist/services/populate.test.node.d.ts.map +1 -0
  209. package/dist/services/populate.test.node.js +910 -0
  210. package/dist/services/populate.test.node.js.map +1 -0
  211. package/dist/services/relation-projection.d.ts +52 -0
  212. package/dist/services/relation-projection.d.ts.map +1 -0
  213. package/dist/services/relation-projection.js +81 -0
  214. package/dist/services/relation-projection.js.map +1 -0
  215. package/dist/services/richtext-populate.d.ts +87 -0
  216. package/dist/services/richtext-populate.d.ts.map +1 -0
  217. package/dist/services/richtext-populate.js +189 -0
  218. package/dist/services/richtext-populate.js.map +1 -0
  219. package/dist/services/richtext-populate.test.node.d.ts +9 -0
  220. package/dist/services/richtext-populate.test.node.d.ts.map +1 -0
  221. package/dist/services/richtext-populate.test.node.js +197 -0
  222. package/dist/services/richtext-populate.test.node.js.map +1 -0
  223. package/dist/storage/collection-fingerprint.d.ts +21 -0
  224. package/dist/storage/collection-fingerprint.d.ts.map +1 -0
  225. package/dist/storage/collection-fingerprint.js +172 -0
  226. package/dist/storage/collection-fingerprint.js.map +1 -0
  227. package/dist/storage/collection-fingerprint.test.node.d.ts +9 -0
  228. package/dist/storage/collection-fingerprint.test.node.d.ts.map +1 -0
  229. package/dist/storage/collection-fingerprint.test.node.js +256 -0
  230. package/dist/storage/collection-fingerprint.test.node.js.map +1 -0
  231. package/dist/storage/field-store-map.d.ts +59 -0
  232. package/dist/storage/field-store-map.d.ts.map +1 -0
  233. package/dist/storage/field-store-map.js +75 -0
  234. package/dist/storage/field-store-map.js.map +1 -0
  235. package/dist/storage/field-store-map.test.node.d.ts +9 -0
  236. package/dist/storage/field-store-map.test.node.d.ts.map +1 -0
  237. package/dist/storage/field-store-map.test.node.js +117 -0
  238. package/dist/storage/field-store-map.test.node.js.map +1 -0
  239. package/dist/storage/index.d.ts +10 -0
  240. package/dist/storage/index.d.ts.map +1 -0
  241. package/dist/storage/index.js +10 -0
  242. package/dist/storage/index.js.map +1 -0
  243. package/dist/utils/normalise-dates.d.ts +15 -0
  244. package/dist/utils/normalise-dates.d.ts.map +1 -0
  245. package/dist/utils/normalise-dates.js +22 -0
  246. package/dist/utils/normalise-dates.js.map +1 -0
  247. package/dist/utils/slugify.d.ts +56 -0
  248. package/dist/utils/slugify.d.ts.map +1 -0
  249. package/dist/utils/slugify.js +91 -0
  250. package/dist/utils/slugify.js.map +1 -0
  251. package/dist/utils/slugify.test.node.d.ts +9 -0
  252. package/dist/utils/slugify.test.node.d.ts.map +1 -0
  253. package/dist/utils/slugify.test.node.js +86 -0
  254. package/dist/utils/slugify.test.node.js.map +1 -0
  255. package/dist/utils/storage-utils.d.ts +36 -0
  256. package/dist/utils/storage-utils.d.ts.map +1 -0
  257. package/dist/utils/storage-utils.js +38 -0
  258. package/dist/utils/storage-utils.js.map +1 -0
  259. package/dist/utils/utils.general.d.ts +64 -0
  260. package/dist/utils/utils.general.d.ts.map +1 -0
  261. package/dist/utils/utils.general.js +219 -0
  262. package/dist/utils/utils.general.js.map +1 -0
  263. package/dist/validation/index.d.ts +9 -0
  264. package/dist/validation/index.d.ts.map +1 -0
  265. package/dist/validation/index.js +9 -0
  266. package/dist/validation/index.js.map +1 -0
  267. package/dist/validation/shared.d.ts +36 -0
  268. package/dist/validation/shared.d.ts.map +1 -0
  269. package/dist/validation/shared.js +42 -0
  270. package/dist/validation/shared.js.map +1 -0
  271. package/dist/workflow/index.d.ts +2 -0
  272. package/dist/workflow/index.d.ts.map +1 -0
  273. package/dist/workflow/index.js +3 -0
  274. package/dist/workflow/index.js.map +1 -0
  275. package/dist/workflow/workflow.d.ts +40 -0
  276. package/dist/workflow/workflow.d.ts.map +1 -0
  277. package/dist/workflow/workflow.js +96 -0
  278. package/dist/workflow/workflow.js.map +1 -0
  279. package/dist/workflow/workflow.test.node.d.ts +2 -0
  280. package/dist/workflow/workflow.test.node.d.ts.map +1 -0
  281. package/dist/workflow/workflow.test.node.js +198 -0
  282. package/dist/workflow/workflow.test.node.js.map +1 -0
  283. package/package.json +88 -0
@@ -0,0 +1,299 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /**
9
+ * Relationship population service.
10
+ *
11
+ * `populateDocuments` walks a set of reconstructed documents, finds every
12
+ * relation leaf that matches a caller-supplied populate spec, batches
13
+ * fetches against each target collection (one DB round-trip per depth
14
+ * level per target collection), and replaces each leaf in place with the
15
+ * populated document. Missing targets become a `{ _resolved: false }`
16
+ * stub; already-visited targets become a `{ _cycle: true }` stub.
17
+ *
18
+ * Consumed by both `@byline/client` (external read API with `populate`
19
+ * and `depth` options) and the admin webapp's API-preview server fn.
20
+ *
21
+ * A request-scoped `ReadContext` is threaded through the walk. Its
22
+ * `visited` set and `readCount` budget guard against recursive reads —
23
+ * particularly the A→B→A failure mode that appears when future
24
+ * `afterRead` hooks invoke their own reads from within populated
25
+ * documents. The guard is in place from day one so that the hook work
26
+ * in Phase 4+ cannot reintroduce the problem.
27
+ *
28
+ * See docs/analysis/RELATIONSHIPS-ANALYSIS.md for the full design rationale.
29
+ *
30
+ * ---------------------------------------------------------------------
31
+ * DSL summary
32
+ * ---------------------------------------------------------------------
33
+ *
34
+ * The populate DSL has two independent axes:
35
+ *
36
+ * 1. **Scope** — which relations in the *source* document to walk.
37
+ * 2. **Projection** — which fields of each *target* document to load.
38
+ *
39
+ * The top-level `populate` value selects scope + (optionally) a uniform
40
+ * projection across the whole tree:
41
+ *
42
+ * - `populate: true` → walk every relation leaf,
43
+ * default projection at every
44
+ * depth. See below for exactly
45
+ * what the default projection
46
+ * returns.
47
+ * - `populate: '*'` → walk every relation leaf, full
48
+ * document projection at every
49
+ * depth. Symmetric with the
50
+ * sub-spec shorthand and intended
51
+ * for tools like the admin API
52
+ * preview where the whole tree
53
+ * should be visible.
54
+ * - `populate: { name: … }` → walk only the named relations.
55
+ * - `populate: undefined` → skip populate entirely (no-op).
56
+ *
57
+ * Default projection — exactly what comes back for `true` (and for any
58
+ * sub-spec whose `select` is omitted):
59
+ *
60
+ * - **Document row metadata, always present** (lives on the
61
+ * `document_versions` row, not in the `store_*` tables, so it is
62
+ * returned regardless of the `fields` projection):
63
+ * `document_version_id`, `document_id`, `collection_id`, `path`,
64
+ * `status`, `created_at`, `updated_at`.
65
+ * - **The `useAsTitle` field** (schema-declared identity field;
66
+ * falls back to the first declared text field when `useAsTitle`
67
+ * is not set on the `CollectionDefinition`). This is the one
68
+ * entry added to the `fields` object.
69
+ *
70
+ * In effect "default projection" is "enough to identify and label the
71
+ * target" — document metadata for wiring, plus one user-defined field
72
+ * (typically `title`) for a human-readable label. Callers wanting more
73
+ * use `'*'` (full doc) or `{ select: [...] }` (explicit fields).
74
+ *
75
+ * Each matched leaf carries a `PopulateFieldSpec` that selects projection:
76
+ *
77
+ * - `true` → default projection: the target's
78
+ * identity field (`useAsTitle`,
79
+ * falling back to the first text
80
+ * field). Document metadata
81
+ * (`document_id`, `collection_id`,
82
+ * `path`, `status`, timestamps) is
83
+ * always included for free — it
84
+ * lives on the row, not in the
85
+ * store_* tables.
86
+ * - `'*'` → full document: every field of
87
+ * the target is loaded.
88
+ * - `{ select: [...] }` → explicit field list, merged with
89
+ * the identity field so downstream
90
+ * UI always has a label to render.
91
+ * - `{ populate: {...} }` → nested populate for the next
92
+ * depth level. Combinable with
93
+ * `select`.
94
+ *
95
+ * Examples:
96
+ *
97
+ * populate: true
98
+ * → every relation, default projection at every depth level.
99
+ *
100
+ * populate: '*'
101
+ * → every relation, full projection at every depth level
102
+ * (use for API previews / debug views that want the whole tree).
103
+ *
104
+ * populate: { heroImage: true }
105
+ * → only heroImage, default projection. If heroImage's own
106
+ * relations exist, they populate at the next depth with `true`.
107
+ *
108
+ * populate: { heroImage: '*' }
109
+ * → only heroImage, full document. If heroImage's own relations
110
+ * exist, they populate at the next depth with `'*'` (consistent
111
+ * with how `true` propagates).
112
+ *
113
+ * populate: { author: { select: ['name'] } }
114
+ * → only author; fetch `name` + identity field.
115
+ *
116
+ * populate: { author: { select: ['name'], populate: { employer: '*' } } }
117
+ * → author with `name` at depth 1; employer fully populated at depth 2.
118
+ *
119
+ * Notes:
120
+ *
121
+ * - `'*'` belongs on the sub-spec (or as the whole top-level spec),
122
+ * not inside `select`. `select` is always an explicit field list.
123
+ * - Projection defaults are transitive at every depth: `true` propagates
124
+ * `true` into nested levels; `'*'` propagates `'*'`. Explicit
125
+ * `{ populate: {...} }` maps take precedence when declared.
126
+ * - Multiple leaves pointing at the same target document are batched
127
+ * into a single fetch; their projection specs are merged (any `'*'`
128
+ * wins; otherwise selects union together, identity field is always
129
+ * added).
130
+ */
131
+ import type { RequestContext } from '@byline/auth';
132
+ import type { CollectionDefinition, FieldSet, IDbAdapter, PopulateFieldSpec, PopulateSpec, ReadContext, ReadMode, RelatedDocumentValue, RelationField } from '../@types/index.js';
133
+ export type { ReadContext } from '../@types/index.js';
134
+ /** Build a fresh ReadContext. */
135
+ export declare function createReadContext(overrides?: Partial<ReadContext>): ReadContext;
136
+ export type { PopulateFieldOptions, PopulateFieldSpec, PopulateMap, PopulateSpec, } from '../@types/populate-types.js';
137
+ export interface PopulateOptions {
138
+ db: IDbAdapter;
139
+ /** Every collection definition in the app — needed to resolve target fields. */
140
+ collections: CollectionDefinition[];
141
+ /** The source collection id for `documents`. */
142
+ collectionId: string;
143
+ /**
144
+ * Documents to populate, as returned from a read operation. Must carry
145
+ * `document_id` and `fields`. Mutated in place — every relation leaf
146
+ * in `fields` that is walked becomes an envelope: the original
147
+ * `{ targetDocumentId, targetCollectionId, relationshipType?,
148
+ * cascadeDelete? }` refs are preserved, and discriminator fields
149
+ * (`_resolved`, `_cycle`) plus an optional `document` property are
150
+ * layered on top. See the `PopulatedRelationValue` /
151
+ * `UnresolvedRelationValue` / `CycleRelationValue` interfaces below.
152
+ */
153
+ documents: Array<Record<string, any>>;
154
+ /** What to populate. Omit to no-op. */
155
+ populate?: PopulateSpec;
156
+ /**
157
+ * Max walk depth. Defaults to 1 when `populate` is present, 0 otherwise.
158
+ * Clamped to `readContext.maxDepth`.
159
+ */
160
+ depth?: number;
161
+ /** Locale forwarded to the batch fetch. */
162
+ locale?: string;
163
+ /**
164
+ * Read mode forwarded to `getDocumentsByDocumentIds`. Selects whether
165
+ * populated targets are resolved from `current_documents` (default,
166
+ * `'any'`) or `current_published_documents` (`'published'`). Public
167
+ * consumers of `@byline/client` typically want `'published'` so a
168
+ * populated target that currently has a newer draft still resolves to
169
+ * its last published version rather than leaking a draft.
170
+ */
171
+ readMode?: ReadMode;
172
+ /**
173
+ * Request-scoped recursion guard. Omit to create a fresh context for
174
+ * this top-level call. Threaded through by future read-side hooks to
175
+ * prevent A→B→A infinite loops.
176
+ */
177
+ readContext?: ReadContext;
178
+ /**
179
+ * Request-scoped auth context. Required when any target collection in the
180
+ * walk has a `beforeRead` hook configured. Each target's hook is invoked
181
+ * (and cached on `readContext.beforeReadCache`) before its batch fetch,
182
+ * and the resulting predicate is ANDed onto the fetch's WHERE. When
183
+ * omitted — most synthetic / test call paths — `beforeRead` hooks are
184
+ * skipped entirely; the production read paths all forward this through
185
+ * from `CollectionHandle`.
186
+ */
187
+ requestContext?: RequestContext;
188
+ /**
189
+ * Skip `beforeRead` hook resolution on every target collection. The
190
+ * top-level read's `_bypassBeforeRead` flag rides through to populate
191
+ * here so admin tooling sees the same unscoped tree on populated
192
+ * relations as it does on the source document.
193
+ */
194
+ bypassBeforeRead?: true;
195
+ /**
196
+ * Registered richtext server-side populate function (typically resolved
197
+ * once at the top level from `ServerConfig.fields.richText.populate`).
198
+ * Threaded through populate so each materialised target also gets its
199
+ * rich-text leaves populated before its `afterRead` hook fires —
200
+ * ensuring user-land hooks observe fully populated content regardless
201
+ * of whether the target arrived via a relation field on the source or
202
+ * via a richtext document link / inline image. Omit when no richtext
203
+ * adapter is registered.
204
+ */
205
+ richTextPopulate?: import('../@types/index.js').RichTextPopulateFn;
206
+ }
207
+ /** Marker placed in a relation leaf when the target was already materialised earlier in this request. */
208
+ export interface CycleRelationValue extends RelatedDocumentValue {
209
+ _resolved: true;
210
+ _cycle: true;
211
+ }
212
+ /** Marker placed in a relation leaf when the target was not found (deleted). */
213
+ export interface UnresolvedRelationValue extends RelatedDocumentValue {
214
+ _resolved: false;
215
+ }
216
+ /**
217
+ * Envelope placed in a relation leaf when populate successfully fetched
218
+ * the target document. The `document` field carries the raw storage-shape
219
+ * doc (`@byline/client` then reshapes it to `ClientDocument` during
220
+ * response shaping).
221
+ */
222
+ export interface PopulatedRelationValue extends RelatedDocumentValue {
223
+ _resolved: true;
224
+ document: Record<string, any>;
225
+ }
226
+ /**
227
+ * Populate relation leaves in `opts.documents` in place, one DB
228
+ * round-trip per depth level per target collection.
229
+ */
230
+ export declare function populateDocuments(opts: PopulateOptions): Promise<void>;
231
+ declare function visitedKey(collectionId: string, documentId: string): string;
232
+ /**
233
+ * A single relation leaf pending populate. `parent[key]` currently holds a
234
+ * `RelatedDocumentValue`; after processing it holds either a populated
235
+ * document or a stub (cycle / unresolved).
236
+ */
237
+ interface RelationLeafRef {
238
+ parent: Record<string, any>;
239
+ key: string;
240
+ field: RelationField;
241
+ value: RelatedDocumentValue;
242
+ /**
243
+ * Per-leaf populate sub-spec resolved from the PopulateMap.
244
+ *
245
+ * - `true` → default projection (identity field only).
246
+ * - `'*'` → full document (all fields).
247
+ * - object → explicit `select` and/or nested `populate`.
248
+ */
249
+ sub: PopulateFieldSpec;
250
+ }
251
+ /**
252
+ * Walk `fields` against `fieldDefs` and collect every relation leaf whose
253
+ * name matches `populate`. Recurses through `group` / `array` / `blocks`
254
+ * using the same populate spec (structure field names do not scope the
255
+ * match — if `populate: { author: true }` is given, every `author`
256
+ * relation found in the tree matches).
257
+ */
258
+ declare function collectRelationLeaves(fields: Record<string, any>, fieldDefs: FieldSet, populate: PopulateSpec, acc: RelationLeafRef[]): void;
259
+ declare function matchesPopulate(fieldName: string, populate: PopulateSpec): PopulateFieldSpec | undefined;
260
+ /**
261
+ * Build the `fields` array for a batch fetch against a single target
262
+ * collection.
263
+ *
264
+ * - Any leaf with `sub === '*'` → `undefined` (fetch all fields).
265
+ * - Otherwise → union of explicit `select` lists from each leaf,
266
+ * merged with the target's identity field (`useAsTitle`, falling
267
+ * back to the first text field). `sub === true` contributes no
268
+ * selects, so a batch of only-`true` leaves collapses to the
269
+ * identity field alone — the default projection.
270
+ *
271
+ * Document metadata (`document_id`, `collection_id`, `path`, `status`,
272
+ * timestamps) lives on the row itself and is always returned — it does
273
+ * not need to appear in the `fields` list.
274
+ */
275
+ declare function buildBatchSelect(leaves: RelationLeafRef[], targetDef: CollectionDefinition | undefined): string[] | undefined;
276
+ /**
277
+ * Merge the per-leaf sub-populate specs for all leaves pointing at a
278
+ * single (now-populated) target document into a single PopulateSpec for
279
+ * the next level's walk of that document. Returns `undefined` if the
280
+ * leaves don't request any nested population (in which case the populated
281
+ * document's own relations stay as raw refs).
282
+ *
283
+ * Sub-spec semantics at the next level:
284
+ * - `'*'` → propagate `'*'` (scope=all, full projection, recursive).
285
+ * `'*'` wins over `true` when both appear in the same batch
286
+ * so the caller's "full document" intent is preserved.
287
+ * - `true` → recurse into every relation of the target (scope=all,
288
+ * default projection).
289
+ * - object → forward any nested `populate` map; ignore `select`.
290
+ */
291
+ declare function reduceChildPopulate(leaves: RelationLeafRef[], targetDocumentId: string): PopulateSpec | undefined;
292
+ export declare const __internal: {
293
+ collectRelationLeaves: typeof collectRelationLeaves;
294
+ matchesPopulate: typeof matchesPopulate;
295
+ buildBatchSelect: typeof buildBatchSelect;
296
+ reduceChildPopulate: typeof reduceChildPopulate;
297
+ visitedKey: typeof visitedKey;
298
+ };
299
+ //# sourceMappingURL=populate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"populate.d.ts","sourceRoot":"","sources":["../../src/services/populate.ts"],"names":[],"mappings":"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"}