@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,197 @@
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
+ import { describe, expect, it } from 'vitest';
9
+ import { collectRichTextLeaves, resolvePopulateOnRead, validateRichTextFieldFlags, } from './richtext-populate.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Fixture — a synthetic collection that exercises every nesting type the
12
+ // walker needs to handle: top-level, group, array, blocks (with two block
13
+ // types), and richText nested inside a block's array sub-field.
14
+ // ---------------------------------------------------------------------------
15
+ const richTextValue = (label) => ({ root: { type: 'root', children: [], _label: label } });
16
+ const fields = [
17
+ { name: 'title', type: 'text', label: 'Title' },
18
+ { name: 'body', type: 'richText', label: 'Body' },
19
+ {
20
+ name: 'meta',
21
+ type: 'group',
22
+ label: 'Meta',
23
+ fields: [{ name: 'summary', type: 'richText', label: 'Summary' }],
24
+ },
25
+ {
26
+ name: 'faq',
27
+ type: 'array',
28
+ label: 'FAQ',
29
+ fields: [{ name: 'answer', type: 'richText', label: 'Answer' }],
30
+ },
31
+ {
32
+ name: 'content',
33
+ type: 'blocks',
34
+ label: 'Content',
35
+ blocks: [
36
+ {
37
+ blockType: 'photoBlock',
38
+ fields: [{ name: 'caption', type: 'richText', label: 'Caption' }],
39
+ },
40
+ {
41
+ blockType: 'richTextBlock',
42
+ fields: [{ name: 'richText', type: 'richText', label: 'RichText' }],
43
+ },
44
+ ],
45
+ },
46
+ ];
47
+ const data = {
48
+ title: 'Post',
49
+ body: richTextValue('body'),
50
+ meta: { summary: richTextValue('summary') },
51
+ faq: [{ answer: richTextValue('answer-0') }, { answer: richTextValue('answer-1') }],
52
+ content: [
53
+ { _id: 'a', _type: 'photoBlock', caption: richTextValue('caption') },
54
+ { _id: 'b', _type: 'richTextBlock', richText: richTextValue('rt') },
55
+ ],
56
+ };
57
+ // ---------------------------------------------------------------------------
58
+ // collectRichTextLeaves
59
+ // ---------------------------------------------------------------------------
60
+ describe('collectRichTextLeaves', () => {
61
+ it('yields top-level richText fields', () => {
62
+ const out = Array.from(collectRichTextLeaves(fields, data));
63
+ const paths = out.map((l) => l.fieldPath);
64
+ expect(paths).toContain('body');
65
+ });
66
+ it('recurses through group fields', () => {
67
+ const out = Array.from(collectRichTextLeaves(fields, data));
68
+ const paths = out.map((l) => l.fieldPath);
69
+ expect(paths).toContain('meta.summary');
70
+ });
71
+ it('recurses through array fields with index in path', () => {
72
+ const out = Array.from(collectRichTextLeaves(fields, data));
73
+ const paths = out.map((l) => l.fieldPath);
74
+ expect(paths).toContain('faq.0.answer');
75
+ expect(paths).toContain('faq.1.answer');
76
+ });
77
+ it('dispatches blocks on _type and recurses into matching block schema', () => {
78
+ const out = Array.from(collectRichTextLeaves(fields, data));
79
+ const paths = out.map((l) => l.fieldPath);
80
+ expect(paths).toContain('content.0.caption');
81
+ expect(paths).toContain('content.1.richText');
82
+ });
83
+ it('yields the raw richText value for each leaf', () => {
84
+ const out = Array.from(collectRichTextLeaves(fields, data));
85
+ const bodyLeaf = out.find((l) => l.fieldPath === 'body');
86
+ expect(bodyLeaf?.value).toEqual(richTextValue('body'));
87
+ });
88
+ it('skips missing data without throwing', () => {
89
+ const out = Array.from(collectRichTextLeaves(fields, { title: 'only-title' }));
90
+ // No richText values present in data — walker yields nothing.
91
+ expect(out).toEqual([]);
92
+ });
93
+ it('skips block items with unknown _type', () => {
94
+ const dataWithUnknownBlock = {
95
+ content: [
96
+ { _id: 'x', _type: 'unknownBlock', caption: richTextValue('skipped') },
97
+ { _id: 'b', _type: 'richTextBlock', richText: richTextValue('kept') },
98
+ ],
99
+ };
100
+ const out = Array.from(collectRichTextLeaves(fields, dataWithUnknownBlock));
101
+ const paths = out.map((l) => l.fieldPath);
102
+ expect(paths).toEqual(['content.1.richText']);
103
+ });
104
+ it('skips block items with no _type', () => {
105
+ const dataWithoutType = {
106
+ content: [{ _id: 'a', caption: richTextValue('skipped') }],
107
+ };
108
+ const out = Array.from(collectRichTextLeaves(fields, dataWithoutType));
109
+ expect(out).toEqual([]);
110
+ });
111
+ });
112
+ // ---------------------------------------------------------------------------
113
+ // resolvePopulateOnRead — default-derivation table
114
+ // ---------------------------------------------------------------------------
115
+ describe('resolvePopulateOnRead', () => {
116
+ const baseField = { name: 'body', type: 'richText', label: 'Body' };
117
+ it('defaults populate to false when embed defaults to true', () => {
118
+ expect(resolvePopulateOnRead(baseField)).toBe(false);
119
+ });
120
+ it('derives populate from explicit embedRelationsOnSave: false', () => {
121
+ expect(resolvePopulateOnRead({ ...baseField, embedRelationsOnSave: false })).toBe(true);
122
+ });
123
+ it('honours explicit populateRelationsOnRead: true (belt-and-braces)', () => {
124
+ expect(resolvePopulateOnRead({
125
+ ...baseField,
126
+ embedRelationsOnSave: true,
127
+ populateRelationsOnRead: true,
128
+ })).toBe(true);
129
+ });
130
+ it('honours explicit populateRelationsOnRead: false even when embed is also false', () => {
131
+ // The invalid combination — caller has to validate separately.
132
+ expect(resolvePopulateOnRead({
133
+ ...baseField,
134
+ embedRelationsOnSave: false,
135
+ populateRelationsOnRead: false,
136
+ })).toBe(false);
137
+ });
138
+ });
139
+ // ---------------------------------------------------------------------------
140
+ // validateRichTextFieldFlags
141
+ // ---------------------------------------------------------------------------
142
+ function makeCollection(richTextField) {
143
+ return {
144
+ path: 'pages',
145
+ labels: { singular: 'Page', plural: 'Pages' },
146
+ fields: [
147
+ { name: 'title', type: 'text', label: 'Title' },
148
+ { name: 'body', type: 'richText', label: 'Body', ...richTextField },
149
+ ],
150
+ };
151
+ }
152
+ describe('validateRichTextFieldFlags', () => {
153
+ it('passes when default flags are used and adapter is registered', () => {
154
+ expect(() => validateRichTextFieldFlags([makeCollection({})], true)).not.toThrow();
155
+ });
156
+ it('passes when default flags are used and no adapter is registered (snapshot mode)', () => {
157
+ expect(() => validateRichTextFieldFlags([makeCollection({})], false)).not.toThrow();
158
+ });
159
+ it('throws when both flags are explicitly false', () => {
160
+ expect(() => validateRichTextFieldFlags([makeCollection({ embedRelationsOnSave: false, populateRelationsOnRead: false })], true)).toThrow(/both .* set to false/i);
161
+ });
162
+ it('throws when embedRelationsOnSave: false but no adapter is registered', () => {
163
+ expect(() => validateRichTextFieldFlags([makeCollection({ embedRelationsOnSave: false })], false)).toThrow(/no.*server adapter/i);
164
+ });
165
+ it('throws when belt-and-braces is asked for but no adapter is registered', () => {
166
+ expect(() => validateRichTextFieldFlags([makeCollection({ embedRelationsOnSave: true, populateRelationsOnRead: true })], false)).toThrow(/no.*server adapter/i);
167
+ });
168
+ it('reports nested richText paths inside blocks with the block type tag', () => {
169
+ const collection = {
170
+ path: 'pages',
171
+ labels: { singular: 'Page', plural: 'Pages' },
172
+ fields: [
173
+ {
174
+ name: 'content',
175
+ type: 'blocks',
176
+ label: 'Content',
177
+ blocks: [
178
+ {
179
+ blockType: 'photoBlock',
180
+ fields: [
181
+ {
182
+ name: 'caption',
183
+ type: 'richText',
184
+ label: 'Caption',
185
+ embedRelationsOnSave: false,
186
+ populateRelationsOnRead: false,
187
+ },
188
+ ],
189
+ },
190
+ ],
191
+ },
192
+ ],
193
+ };
194
+ expect(() => validateRichTextFieldFlags([collection], true)).toThrow(/content\.<photoBlock>\.caption/);
195
+ });
196
+ });
197
+ //# sourceMappingURL=richtext-populate.test.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"richtext-populate.test.node.js","sourceRoot":"","sources":["../../src/services/richtext-populate.test.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
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
+ import type { CollectionDefinition } from '../@types/index.js';
9
+ /**
10
+ * Computes a deterministic SHA-256 fingerprint of the data-shape-relevant
11
+ * portion of a `CollectionDefinition`. Two definitions that differ only in
12
+ * cosmetic fields (labels, hooks, admin/search/showStats metadata, helpText,
13
+ * placeholders) produce the same fingerprint. Adding or removing a field,
14
+ * changing a field type, renaming a block variant, altering workflow statuses,
15
+ * or changing a relation target all produce a different fingerprint.
16
+ *
17
+ * Async because `crypto.subtle.digest` is async on every platform. Returned
18
+ * as a lowercase hex string (64 characters).
19
+ */
20
+ export declare function fingerprintCollection(def: CollectionDefinition): Promise<string>;
21
+ //# sourceMappingURL=collection-fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-fingerprint.d.ts","sourceRoot":"","sources":["../../src/storage/collection-fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAEV,oBAAoB,EAIrB,MAAM,oBAAoB,CAAA;AA6K3B;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAKtF"}
@@ -0,0 +1,172 @@
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
+ function canonicalField(field) {
9
+ const base = {
10
+ name: field.name,
11
+ type: field.type,
12
+ optional: field.optional === true,
13
+ localized: field.localized === true,
14
+ };
15
+ switch (field.type) {
16
+ case 'group':
17
+ case 'array':
18
+ base.fields = field.fields.map(canonicalField);
19
+ if (field.type === 'array' && field.validation) {
20
+ base.validation = sortedShallow(field.validation);
21
+ }
22
+ return base;
23
+ case 'blocks':
24
+ base.blocks = field.blocks.map((b) => ({
25
+ blockType: b.blockType,
26
+ fields: b.fields.map(canonicalField),
27
+ }));
28
+ return base;
29
+ case 'select':
30
+ base.options = field.options.map((o) => ({ value: o.value }));
31
+ return base;
32
+ case 'relation':
33
+ base.targetCollection = field.targetCollection;
34
+ if (field.displayField !== undefined)
35
+ base.displayField = field.displayField;
36
+ return base;
37
+ case 'datetime':
38
+ if (field.mode !== undefined)
39
+ base.mode = field.mode;
40
+ return base;
41
+ case 'image':
42
+ case 'file':
43
+ // Per-field upload config affects the read-back contract (mime
44
+ // policy, variant set, storage backend), so it folds into the
45
+ // schema fingerprint. `hooks` is excluded — functions don't
46
+ // canonicalise, and `stableStringify` would drop them anyway.
47
+ // `storage` is also excluded: it's a runtime provider object,
48
+ // not a schema-shape declaration.
49
+ if (field.upload)
50
+ base.upload = canonicalUpload(field.upload);
51
+ return base;
52
+ case 'text':
53
+ case 'textArea':
54
+ case 'richText':
55
+ case 'float':
56
+ case 'integer':
57
+ if (field.validation) {
58
+ base.validation = sortedShallow(field.validation);
59
+ }
60
+ return base;
61
+ default:
62
+ return base;
63
+ }
64
+ }
65
+ function canonicalWorkflow(w) {
66
+ return {
67
+ // Status names only — labels and verbs are presentation.
68
+ statuses: w.statuses.map((s) => ({ name: s.name })),
69
+ ...(w.defaultStatus !== undefined ? { defaultStatus: w.defaultStatus } : {}),
70
+ };
71
+ }
72
+ function canonicalUpload(u) {
73
+ const out = {};
74
+ if (u.mimeTypes !== undefined)
75
+ out.mimeTypes = [...u.mimeTypes].sort();
76
+ if (u.maxFileSize !== undefined)
77
+ out.maxFileSize = u.maxFileSize;
78
+ if (u.sizes !== undefined) {
79
+ out.sizes = u.sizes
80
+ .map((s) => ({
81
+ name: s.name,
82
+ ...(s.width !== undefined ? { width: s.width } : {}),
83
+ ...(s.height !== undefined ? { height: s.height } : {}),
84
+ ...(s.fit !== undefined ? { fit: s.fit } : {}),
85
+ ...(s.format !== undefined ? { format: s.format } : {}),
86
+ ...(s.quality !== undefined ? { quality: s.quality } : {}),
87
+ }))
88
+ .sort((a, b) => a.name.localeCompare(b.name));
89
+ }
90
+ return out;
91
+ }
92
+ function sortedShallow(obj) {
93
+ const out = {};
94
+ for (const key of Object.keys(obj).sort()) {
95
+ const v = obj[key];
96
+ if (v === undefined || typeof v === 'function')
97
+ continue;
98
+ out[key] = v;
99
+ }
100
+ return out;
101
+ }
102
+ function canonicalCollection(def) {
103
+ const out = {
104
+ path: def.path,
105
+ fields: def.fields.map(canonicalField),
106
+ };
107
+ if (def.workflow)
108
+ out.workflow = canonicalWorkflow(def.workflow);
109
+ if (def.useAsPath !== undefined)
110
+ out.useAsPath = def.useAsPath;
111
+ if (def.useAsTitle !== undefined)
112
+ out.useAsTitle = def.useAsTitle;
113
+ return out;
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Deterministic serialisation
117
+ // ---------------------------------------------------------------------------
118
+ // Recursive key-sorted JSON stringify. Skips `undefined` and functions so the
119
+ // presence of hooks / handler callbacks cannot change the output. Arrays
120
+ // preserve order (order is meaningful for fields, blocks, statuses).
121
+ function stableStringify(value) {
122
+ if (value === null)
123
+ return 'null';
124
+ if (typeof value === 'number')
125
+ return Number.isFinite(value) ? String(value) : 'null';
126
+ if (typeof value === 'boolean')
127
+ return value ? 'true' : 'false';
128
+ if (typeof value === 'string')
129
+ return JSON.stringify(value);
130
+ if (typeof value === 'undefined' || typeof value === 'function')
131
+ return 'null';
132
+ if (Array.isArray(value)) {
133
+ return `[${value.map(stableStringify).join(',')}]`;
134
+ }
135
+ if (typeof value === 'object') {
136
+ const obj = value;
137
+ const keys = Object.keys(obj)
138
+ .filter((k) => obj[k] !== undefined && typeof obj[k] !== 'function')
139
+ .sort();
140
+ const body = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',');
141
+ return `{${body}}`;
142
+ }
143
+ return 'null';
144
+ }
145
+ // ---------------------------------------------------------------------------
146
+ // Public API
147
+ // ---------------------------------------------------------------------------
148
+ /**
149
+ * Computes a deterministic SHA-256 fingerprint of the data-shape-relevant
150
+ * portion of a `CollectionDefinition`. Two definitions that differ only in
151
+ * cosmetic fields (labels, hooks, admin/search/showStats metadata, helpText,
152
+ * placeholders) produce the same fingerprint. Adding or removing a field,
153
+ * changing a field type, renaming a block variant, altering workflow statuses,
154
+ * or changing a relation target all produce a different fingerprint.
155
+ *
156
+ * Async because `crypto.subtle.digest` is async on every platform. Returned
157
+ * as a lowercase hex string (64 characters).
158
+ */
159
+ export async function fingerprintCollection(def) {
160
+ const canonical = canonicalCollection(def);
161
+ const serialised = stableStringify(canonical);
162
+ const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(serialised));
163
+ return bytesToHex(new Uint8Array(buffer));
164
+ }
165
+ function bytesToHex(bytes) {
166
+ let out = '';
167
+ for (const byte of bytes) {
168
+ out += byte.toString(16).padStart(2, '0');
169
+ }
170
+ return out;
171
+ }
172
+ //# sourceMappingURL=collection-fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-fingerprint.js","sourceRoot":"","sources":["../../src/storage/collection-fingerprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
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
+ export {};
9
+ //# sourceMappingURL=collection-fingerprint.test.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-fingerprint.test.node.d.ts","sourceRoot":"","sources":["../../src/storage/collection-fingerprint.test.node.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}