@elytracms/core 0.0.6

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 (521) hide show
  1. package/LICENSE +21 -0
  2. package/dist/clipboard/build.d.ts +77 -0
  3. package/dist/clipboard/build.js +128 -0
  4. package/dist/clipboard/build.js.map +1 -0
  5. package/dist/clipboard/clipboard.d.ts +33 -0
  6. package/dist/clipboard/clipboard.js +45 -0
  7. package/dist/clipboard/clipboard.js.map +1 -0
  8. package/dist/clipboard/fragment.d.ts +112 -0
  9. package/dist/clipboard/fragment.js +79 -0
  10. package/dist/clipboard/fragment.js.map +1 -0
  11. package/dist/clipboard/html.d.ts +26 -0
  12. package/dist/clipboard/html.js +82 -0
  13. package/dist/clipboard/html.js.map +1 -0
  14. package/dist/clipboard/index.d.ts +15 -0
  15. package/dist/clipboard/index.js +16 -0
  16. package/dist/clipboard/index.js.map +1 -0
  17. package/dist/clipboard/references.d.ts +50 -0
  18. package/dist/clipboard/references.js +0 -0
  19. package/dist/clipboard/references.js.map +1 -0
  20. package/dist/clipboard/serialize.d.ts +69 -0
  21. package/dist/clipboard/serialize.js +130 -0
  22. package/dist/clipboard/serialize.js.map +1 -0
  23. package/dist/cms-core/collections.d.ts +82 -0
  24. package/dist/cms-core/collections.js +187 -0
  25. package/dist/cms-core/collections.js.map +1 -0
  26. package/dist/cms-core/documents.d.ts +71 -0
  27. package/dist/cms-core/documents.js +67 -0
  28. package/dist/cms-core/documents.js.map +1 -0
  29. package/dist/cms-core/envelopes.d.ts +80 -0
  30. package/dist/cms-core/envelopes.js +124 -0
  31. package/dist/cms-core/envelopes.js.map +1 -0
  32. package/dist/cms-core/fields.d.ts +220 -0
  33. package/dist/cms-core/fields.js +250 -0
  34. package/dist/cms-core/fields.js.map +1 -0
  35. package/dist/cms-core/fixtures.d.ts +92 -0
  36. package/dist/cms-core/fixtures.js +357 -0
  37. package/dist/cms-core/fixtures.js.map +1 -0
  38. package/dist/cms-core/hierarchy.d.ts +113 -0
  39. package/dist/cms-core/hierarchy.js +223 -0
  40. package/dist/cms-core/hierarchy.js.map +1 -0
  41. package/dist/cms-core/index.d.ts +25 -0
  42. package/dist/cms-core/index.js +26 -0
  43. package/dist/cms-core/index.js.map +1 -0
  44. package/dist/cms-core/infer.d.ts +103 -0
  45. package/dist/cms-core/infer.js +57 -0
  46. package/dist/cms-core/infer.js.map +1 -0
  47. package/dist/cms-core/issues.d.ts +92 -0
  48. package/dist/cms-core/issues.js +74 -0
  49. package/dist/cms-core/issues.js.map +1 -0
  50. package/dist/cms-core/json-schema.d.ts +25 -0
  51. package/dist/cms-core/json-schema.js +110 -0
  52. package/dist/cms-core/json-schema.js.map +1 -0
  53. package/dist/cms-core/localization.d.ts +51 -0
  54. package/dist/cms-core/localization.js +89 -0
  55. package/dist/cms-core/localization.js.map +1 -0
  56. package/dist/cms-core/routes.d.ts +76 -0
  57. package/dist/cms-core/routes.js +220 -0
  58. package/dist/cms-core/routes.js.map +1 -0
  59. package/dist/cms-core/self-type.d.ts +41 -0
  60. package/dist/cms-core/self-type.js +191 -0
  61. package/dist/cms-core/self-type.js.map +1 -0
  62. package/dist/cms-core/url-for-document.d.ts +39 -0
  63. package/dist/cms-core/url-for-document.js +138 -0
  64. package/dist/cms-core/url-for-document.js.map +1 -0
  65. package/dist/cms-core/validate-document.d.ts +121 -0
  66. package/dist/cms-core/validate-document.js +871 -0
  67. package/dist/cms-core/validate-document.js.map +1 -0
  68. package/dist/cms-core/versions.d.ts +75 -0
  69. package/dist/cms-core/versions.js +97 -0
  70. package/dist/cms-core/versions.js.map +1 -0
  71. package/dist/collaboration/approval.d.ts +68 -0
  72. package/dist/collaboration/approval.js +104 -0
  73. package/dist/collaboration/approval.js.map +1 -0
  74. package/dist/collaboration/collaboration.d.ts +49 -0
  75. package/dist/collaboration/collaboration.js +56 -0
  76. package/dist/collaboration/collaboration.js.map +1 -0
  77. package/dist/collaboration/comments.d.ts +72 -0
  78. package/dist/collaboration/comments.js +118 -0
  79. package/dist/collaboration/comments.js.map +1 -0
  80. package/dist/collaboration/core.d.ts +25 -0
  81. package/dist/collaboration/core.js +26 -0
  82. package/dist/collaboration/core.js.map +1 -0
  83. package/dist/collaboration/index.d.ts +14 -0
  84. package/dist/collaboration/index.js +15 -0
  85. package/dist/collaboration/index.js.map +1 -0
  86. package/dist/collaboration/presence.d.ts +62 -0
  87. package/dist/collaboration/presence.js +85 -0
  88. package/dist/collaboration/presence.js.map +1 -0
  89. package/dist/collaboration/publishing.d.ts +60 -0
  90. package/dist/collaboration/publishing.js +93 -0
  91. package/dist/collaboration/publishing.js.map +1 -0
  92. package/dist/collaboration/versions.d.ts +52 -0
  93. package/dist/collaboration/versions.js +81 -0
  94. package/dist/collaboration/versions.js.map +1 -0
  95. package/dist/component-registry/index.d.ts +3 -0
  96. package/dist/component-registry/index.js +4 -0
  97. package/dist/component-registry/index.js.map +1 -0
  98. package/dist/component-registry/issues.d.ts +6 -0
  99. package/dist/component-registry/issues.js +2 -0
  100. package/dist/component-registry/issues.js.map +1 -0
  101. package/dist/component-registry/manifest.d.ts +164 -0
  102. package/dist/component-registry/manifest.js +129 -0
  103. package/dist/component-registry/manifest.js.map +1 -0
  104. package/dist/component-registry/registry.d.ts +33 -0
  105. package/dist/component-registry/registry.js +90 -0
  106. package/dist/component-registry/registry.js.map +1 -0
  107. package/dist/content/__fixtures__/filterable-collections.d.ts +14 -0
  108. package/dist/content/__fixtures__/filterable-collections.js +15 -0
  109. package/dist/content/__fixtures__/filterable-collections.js.map +1 -0
  110. package/dist/content/__fixtures__/sample-accessor-types.d.ts +56 -0
  111. package/dist/content/__fixtures__/sample-accessor-types.js +5 -0
  112. package/dist/content/__fixtures__/sample-accessor-types.js.map +1 -0
  113. package/dist/content/__fixtures__/sample-delivery-types.d.ts +122 -0
  114. package/dist/content/__fixtures__/sample-delivery-types.js +5 -0
  115. package/dist/content/__fixtures__/sample-delivery-types.js.map +1 -0
  116. package/dist/content/assets.d.ts +53 -0
  117. package/dist/content/assets.js +38 -0
  118. package/dist/content/assets.js.map +1 -0
  119. package/dist/content/binding-sources.d.ts +53 -0
  120. package/dist/content/binding-sources.js +73 -0
  121. package/dist/content/binding-sources.js.map +1 -0
  122. package/dist/content/client.d.ts +90 -0
  123. package/dist/content/client.js +383 -0
  124. package/dist/content/client.js.map +1 -0
  125. package/dist/content/codegen.d.ts +54 -0
  126. package/dist/content/codegen.js +305 -0
  127. package/dist/content/codegen.js.map +1 -0
  128. package/dist/content/context.d.ts +38 -0
  129. package/dist/content/context.js +21 -0
  130. package/dist/content/context.js.map +1 -0
  131. package/dist/content/cursor.d.ts +33 -0
  132. package/dist/content/cursor.js +104 -0
  133. package/dist/content/cursor.js.map +1 -0
  134. package/dist/content/index.d.ts +28 -0
  135. package/dist/content/index.js +29 -0
  136. package/dist/content/index.js.map +1 -0
  137. package/dist/content/locale.d.ts +30 -0
  138. package/dist/content/locale.js +26 -0
  139. package/dist/content/locale.js.map +1 -0
  140. package/dist/content/perspective.d.ts +29 -0
  141. package/dist/content/perspective.js +31 -0
  142. package/dist/content/perspective.js.map +1 -0
  143. package/dist/content/populate.d.ts +25 -0
  144. package/dist/content/populate.js +22 -0
  145. package/dist/content/populate.js.map +1 -0
  146. package/dist/content/query.d.ts +122 -0
  147. package/dist/content/query.js +257 -0
  148. package/dist/content/query.js.map +1 -0
  149. package/dist/content/raw.d.ts +13 -0
  150. package/dist/content/raw.js +14 -0
  151. package/dist/content/raw.js.map +1 -0
  152. package/dist/content/resolve.d.ts +97 -0
  153. package/dist/content/resolve.js +261 -0
  154. package/dist/content/resolve.js.map +1 -0
  155. package/dist/content/serialize.d.ts +30 -0
  156. package/dist/content/serialize.js +57 -0
  157. package/dist/content/serialize.js.map +1 -0
  158. package/dist/content/tags.d.ts +54 -0
  159. package/dist/content/tags.js +40 -0
  160. package/dist/content/tags.js.map +1 -0
  161. package/dist/data-binding/fixtures.d.ts +20 -0
  162. package/dist/data-binding/fixtures.js +47 -0
  163. package/dist/data-binding/fixtures.js.map +1 -0
  164. package/dist/data-binding/index.d.ts +14 -0
  165. package/dist/data-binding/index.js +15 -0
  166. package/dist/data-binding/index.js.map +1 -0
  167. package/dist/data-binding/issues.d.ts +45 -0
  168. package/dist/data-binding/issues.js +46 -0
  169. package/dist/data-binding/issues.js.map +1 -0
  170. package/dist/data-binding/resolve.d.ts +87 -0
  171. package/dist/data-binding/resolve.js +204 -0
  172. package/dist/data-binding/resolve.js.map +1 -0
  173. package/dist/data-binding/sample.d.ts +21 -0
  174. package/dist/data-binding/sample.js +23 -0
  175. package/dist/data-binding/sample.js.map +1 -0
  176. package/dist/data-binding/sources.d.ts +225 -0
  177. package/dist/data-binding/sources.js +154 -0
  178. package/dist/data-binding/sources.js.map +1 -0
  179. package/dist/data-binding/tokens.d.ts +62 -0
  180. package/dist/data-binding/tokens.js +150 -0
  181. package/dist/data-binding/tokens.js.map +1 -0
  182. package/dist/design-tokens/css.d.ts +34 -0
  183. package/dist/design-tokens/css.js +51 -0
  184. package/dist/design-tokens/css.js.map +1 -0
  185. package/dist/design-tokens/index.d.ts +10 -0
  186. package/dist/design-tokens/index.js +11 -0
  187. package/dist/design-tokens/index.js.map +1 -0
  188. package/dist/design-tokens/style-guide.d.ts +30 -0
  189. package/dist/design-tokens/style-guide.js +31 -0
  190. package/dist/design-tokens/style-guide.js.map +1 -0
  191. package/dist/design-tokens/tokens.d.ts +89 -0
  192. package/dist/design-tokens/tokens.js +112 -0
  193. package/dist/design-tokens/tokens.js.map +1 -0
  194. package/dist/export-sync/builder-source.d.ts +85 -0
  195. package/dist/export-sync/builder-source.js +124 -0
  196. package/dist/export-sync/builder-source.js.map +1 -0
  197. package/dist/export-sync/check.d.ts +61 -0
  198. package/dist/export-sync/check.js +126 -0
  199. package/dist/export-sync/check.js.map +1 -0
  200. package/dist/export-sync/cli.d.ts +89 -0
  201. package/dist/export-sync/cli.js +323 -0
  202. package/dist/export-sync/cli.js.map +1 -0
  203. package/dist/export-sync/core.d.ts +58 -0
  204. package/dist/export-sync/core.js +41 -0
  205. package/dist/export-sync/core.js.map +1 -0
  206. package/dist/export-sync/eject.d.ts +28 -0
  207. package/dist/export-sync/eject.js +21 -0
  208. package/dist/export-sync/eject.js.map +1 -0
  209. package/dist/export-sync/fixtures.d.ts +25 -0
  210. package/dist/export-sync/fixtures.js +87 -0
  211. package/dist/export-sync/fixtures.js.map +1 -0
  212. package/dist/export-sync/generate.d.ts +7 -0
  213. package/dist/export-sync/generate.js +505 -0
  214. package/dist/export-sync/generate.js.map +1 -0
  215. package/dist/export-sync/index.d.ts +37 -0
  216. package/dist/export-sync/index.js +39 -0
  217. package/dist/export-sync/index.js.map +1 -0
  218. package/dist/export-sync/init.d.ts +123 -0
  219. package/dist/export-sync/init.js +234 -0
  220. package/dist/export-sync/init.js.map +1 -0
  221. package/dist/export-sync/manifest-host.d.ts +48 -0
  222. package/dist/export-sync/manifest-host.js +73 -0
  223. package/dist/export-sync/manifest-host.js.map +1 -0
  224. package/dist/export-sync/node.d.ts +20 -0
  225. package/dist/export-sync/node.js +101 -0
  226. package/dist/export-sync/node.js.map +1 -0
  227. package/dist/export-sync/push.d.ts +76 -0
  228. package/dist/export-sync/push.js +197 -0
  229. package/dist/export-sync/push.js.map +1 -0
  230. package/dist/export-sync/registry-sync-client.d.ts +59 -0
  231. package/dist/export-sync/registry-sync-client.js +97 -0
  232. package/dist/export-sync/registry-sync-client.js.map +1 -0
  233. package/dist/export-sync/sync.d.ts +47 -0
  234. package/dist/export-sync/sync.js +47 -0
  235. package/dist/export-sync/sync.js.map +1 -0
  236. package/dist/export-sync/typegen.d.ts +40 -0
  237. package/dist/export-sync/typegen.js +45 -0
  238. package/dist/export-sync/typegen.js.map +1 -0
  239. package/dist/export-sync/validate.d.ts +19 -0
  240. package/dist/export-sync/validate.js +102 -0
  241. package/dist/export-sync/validate.js.map +1 -0
  242. package/dist/export-sync/watch.d.ts +66 -0
  243. package/dist/export-sync/watch.js +70 -0
  244. package/dist/export-sync/watch.js.map +1 -0
  245. package/dist/operations/assets.d.ts +198 -0
  246. package/dist/operations/assets.js +75 -0
  247. package/dist/operations/assets.js.map +1 -0
  248. package/dist/operations/authorization.d.ts +49 -0
  249. package/dist/operations/authorization.js +128 -0
  250. package/dist/operations/authorization.js.map +1 -0
  251. package/dist/operations/changesets.d.ts +160 -0
  252. package/dist/operations/changesets.js +442 -0
  253. package/dist/operations/changesets.js.map +1 -0
  254. package/dist/operations/client.d.ts +49 -0
  255. package/dist/operations/client.js +57 -0
  256. package/dist/operations/client.js.map +1 -0
  257. package/dist/operations/core.d.ts +238 -0
  258. package/dist/operations/core.js +269 -0
  259. package/dist/operations/core.js.map +1 -0
  260. package/dist/operations/documents.d.ts +432 -0
  261. package/dist/operations/documents.js +344 -0
  262. package/dist/operations/documents.js.map +1 -0
  263. package/dist/operations/graph.d.ts +138 -0
  264. package/dist/operations/graph.js +78 -0
  265. package/dist/operations/graph.js.map +1 -0
  266. package/dist/operations/index.d.ts +19 -0
  267. package/dist/operations/index.js +20 -0
  268. package/dist/operations/index.js.map +1 -0
  269. package/dist/operations/members.d.ts +87 -0
  270. package/dist/operations/members.js +56 -0
  271. package/dist/operations/members.js.map +1 -0
  272. package/dist/operations/publishing.d.ts +89 -0
  273. package/dist/operations/publishing.js +57 -0
  274. package/dist/operations/publishing.js.map +1 -0
  275. package/dist/operations/references.d.ts +222 -0
  276. package/dist/operations/references.js +177 -0
  277. package/dist/operations/references.js.map +1 -0
  278. package/dist/operations/schema.d.ts +413 -0
  279. package/dist/operations/schema.js +138 -0
  280. package/dist/operations/schema.js.map +1 -0
  281. package/dist/operations/tokens.d.ts +79 -0
  282. package/dist/operations/tokens.js +102 -0
  283. package/dist/operations/tokens.js.map +1 -0
  284. package/dist/persistence/adapter.d.ts +79 -0
  285. package/dist/persistence/adapter.js +55 -0
  286. package/dist/persistence/adapter.js.map +1 -0
  287. package/dist/persistence/assets.d.ts +120 -0
  288. package/dist/persistence/assets.js +141 -0
  289. package/dist/persistence/assets.js.map +1 -0
  290. package/dist/persistence/backend-validation.d.ts +43 -0
  291. package/dist/persistence/backend-validation.js +57 -0
  292. package/dist/persistence/backend-validation.js.map +1 -0
  293. package/dist/persistence/cli-tokens.d.ts +50 -0
  294. package/dist/persistence/cli-tokens.js +66 -0
  295. package/dist/persistence/cli-tokens.js.map +1 -0
  296. package/dist/persistence/cms.d.ts +148 -0
  297. package/dist/persistence/cms.js +232 -0
  298. package/dist/persistence/cms.js.map +1 -0
  299. package/dist/persistence/contract-scenarios.d.ts +73 -0
  300. package/dist/persistence/contract-scenarios.js +496 -0
  301. package/dist/persistence/contract-scenarios.js.map +1 -0
  302. package/dist/persistence/core.d.ts +96 -0
  303. package/dist/persistence/core.js +110 -0
  304. package/dist/persistence/core.js.map +1 -0
  305. package/dist/persistence/graph.d.ts +61 -0
  306. package/dist/persistence/graph.js +98 -0
  307. package/dist/persistence/graph.js.map +1 -0
  308. package/dist/persistence/index.d.ts +22 -0
  309. package/dist/persistence/index.js +23 -0
  310. package/dist/persistence/index.js.map +1 -0
  311. package/dist/persistence/members.d.ts +70 -0
  312. package/dist/persistence/members.js +0 -0
  313. package/dist/persistence/members.js.map +1 -0
  314. package/dist/persistence/publishing.d.ts +59 -0
  315. package/dist/persistence/publishing.js +95 -0
  316. package/dist/persistence/publishing.js.map +1 -0
  317. package/dist/persistence/reference-extraction.d.ts +44 -0
  318. package/dist/persistence/reference-extraction.js +204 -0
  319. package/dist/persistence/reference-extraction.js.map +1 -0
  320. package/dist/persistence/reference-indexing.d.ts +68 -0
  321. package/dist/persistence/reference-indexing.js +112 -0
  322. package/dist/persistence/reference-indexing.js.map +1 -0
  323. package/dist/persistence/references.d.ts +257 -0
  324. package/dist/persistence/references.js +0 -0
  325. package/dist/persistence/references.js.map +1 -0
  326. package/dist/persistence/seed.d.ts +55 -0
  327. package/dist/persistence/seed.js +102 -0
  328. package/dist/persistence/seed.js.map +1 -0
  329. package/dist/persistence/self-maintaining-adapter.d.ts +41 -0
  330. package/dist/persistence/self-maintaining-adapter.js +79 -0
  331. package/dist/persistence/self-maintaining-adapter.js.map +1 -0
  332. package/dist/plugins/asset-storage.d.ts +76 -0
  333. package/dist/plugins/asset-storage.js +104 -0
  334. package/dist/plugins/asset-storage.js.map +1 -0
  335. package/dist/plugins/component-package.d.ts +54 -0
  336. package/dist/plugins/component-package.js +92 -0
  337. package/dist/plugins/component-package.js.map +1 -0
  338. package/dist/plugins/data-sources.d.ts +78 -0
  339. package/dist/plugins/data-sources.js +99 -0
  340. package/dist/plugins/data-sources.js.map +1 -0
  341. package/dist/plugins/examples.d.ts +47 -0
  342. package/dist/plugins/examples.js +205 -0
  343. package/dist/plugins/examples.js.map +1 -0
  344. package/dist/plugins/export-targets.d.ts +47 -0
  345. package/dist/plugins/export-targets.js +78 -0
  346. package/dist/plugins/export-targets.js.map +1 -0
  347. package/dist/plugins/field-types.d.ts +86 -0
  348. package/dist/plugins/field-types.js +93 -0
  349. package/dist/plugins/field-types.js.map +1 -0
  350. package/dist/plugins/hooks.d.ts +60 -0
  351. package/dist/plugins/hooks.js +94 -0
  352. package/dist/plugins/hooks.js.map +1 -0
  353. package/dist/plugins/index.d.ts +27 -0
  354. package/dist/plugins/index.js +28 -0
  355. package/dist/plugins/index.js.map +1 -0
  356. package/dist/plugins/marketplace.d.ts +90 -0
  357. package/dist/plugins/marketplace.js +110 -0
  358. package/dist/plugins/marketplace.js.map +1 -0
  359. package/dist/plugins/plugin.d.ts +107 -0
  360. package/dist/plugins/plugin.js +122 -0
  361. package/dist/plugins/plugin.js.map +1 -0
  362. package/dist/plugins/templates.d.ts +66 -0
  363. package/dist/plugins/templates.js +74 -0
  364. package/dist/plugins/templates.js.map +1 -0
  365. package/dist/project-graph/binding.d.ts +68 -0
  366. package/dist/project-graph/binding.js +39 -0
  367. package/dist/project-graph/binding.js.map +1 -0
  368. package/dist/project-graph/container.d.ts +126 -0
  369. package/dist/project-graph/container.js +221 -0
  370. package/dist/project-graph/container.js.map +1 -0
  371. package/dist/project-graph/edit.d.ts +66 -0
  372. package/dist/project-graph/edit.js +201 -0
  373. package/dist/project-graph/edit.js.map +1 -0
  374. package/dist/project-graph/fixtures.d.ts +51 -0
  375. package/dist/project-graph/fixtures.js +224 -0
  376. package/dist/project-graph/fixtures.js.map +1 -0
  377. package/dist/project-graph/ids.d.ts +17 -0
  378. package/dist/project-graph/ids.js +19 -0
  379. package/dist/project-graph/ids.js.map +1 -0
  380. package/dist/project-graph/index.d.ts +12 -0
  381. package/dist/project-graph/index.js +13 -0
  382. package/dist/project-graph/index.js.map +1 -0
  383. package/dist/project-graph/issues.d.ts +61 -0
  384. package/dist/project-graph/issues.js +44 -0
  385. package/dist/project-graph/issues.js.map +1 -0
  386. package/dist/project-graph/json.d.ts +6 -0
  387. package/dist/project-graph/json.js +10 -0
  388. package/dist/project-graph/json.js.map +1 -0
  389. package/dist/project-graph/node.d.ts +48 -0
  390. package/dist/project-graph/node.js +42 -0
  391. package/dist/project-graph/node.js.map +1 -0
  392. package/dist/project-graph/normalize.d.ts +17 -0
  393. package/dist/project-graph/normalize.js +110 -0
  394. package/dist/project-graph/normalize.js.map +1 -0
  395. package/dist/project-graph/serialize.d.ts +36 -0
  396. package/dist/project-graph/serialize.js +51 -0
  397. package/dist/project-graph/serialize.js.map +1 -0
  398. package/dist/project-graph/structure.d.ts +40 -0
  399. package/dist/project-graph/structure.js +36 -0
  400. package/dist/project-graph/structure.js.map +1 -0
  401. package/dist/project-graph/validate.d.ts +84 -0
  402. package/dist/project-graph/validate.js +158 -0
  403. package/dist/project-graph/validate.js.map +1 -0
  404. package/dist/rich-text/adapter.d.ts +43 -0
  405. package/dist/rich-text/adapter.js +24 -0
  406. package/dist/rich-text/adapter.js.map +1 -0
  407. package/dist/rich-text/dom-editor.d.ts +101 -0
  408. package/dist/rich-text/dom-editor.js +482 -0
  409. package/dist/rich-text/dom-editor.js.map +1 -0
  410. package/dist/rich-text/embed.d.ts +70 -0
  411. package/dist/rich-text/embed.js +70 -0
  412. package/dist/rich-text/embed.js.map +1 -0
  413. package/dist/rich-text/fixtures.d.ts +25 -0
  414. package/dist/rich-text/fixtures.js +115 -0
  415. package/dist/rich-text/fixtures.js.map +1 -0
  416. package/dist/rich-text/html.d.ts +5 -0
  417. package/dist/rich-text/html.js +309 -0
  418. package/dist/rich-text/html.js.map +1 -0
  419. package/dist/rich-text/index.d.ts +19 -0
  420. package/dist/rich-text/index.js +20 -0
  421. package/dist/rich-text/index.js.map +1 -0
  422. package/dist/rich-text/markdown.d.ts +7 -0
  423. package/dist/rich-text/markdown.js +235 -0
  424. package/dist/rich-text/markdown.js.map +1 -0
  425. package/dist/rich-text/portable-text.d.ts +50 -0
  426. package/dist/rich-text/portable-text.js +223 -0
  427. package/dist/rich-text/portable-text.js.map +1 -0
  428. package/dist/rich-text/registry.d.ts +48 -0
  429. package/dist/rich-text/registry.js +16 -0
  430. package/dist/rich-text/registry.js.map +1 -0
  431. package/dist/rich-text/render.d.ts +69 -0
  432. package/dist/rich-text/render.js +205 -0
  433. package/dist/rich-text/render.js.map +1 -0
  434. package/dist/rich-text/schema.d.ts +86 -0
  435. package/dist/rich-text/schema.js +80 -0
  436. package/dist/rich-text/schema.js.map +1 -0
  437. package/dist/rich-text/test-support.d.ts +7 -0
  438. package/dist/rich-text/test-support.js +8 -0
  439. package/dist/rich-text/test-support.js.map +1 -0
  440. package/dist/runtime-renderer/client.d.ts +14 -0
  441. package/dist/runtime-renderer/client.js +15 -0
  442. package/dist/runtime-renderer/client.js.map +1 -0
  443. package/dist/runtime-renderer/condition.d.ts +8 -0
  444. package/dist/runtime-renderer/condition.js +48 -0
  445. package/dist/runtime-renderer/condition.js.map +1 -0
  446. package/dist/runtime-renderer/content-client.d.ts +62 -0
  447. package/dist/runtime-renderer/content-client.js +37 -0
  448. package/dist/runtime-renderer/content-client.js.map +1 -0
  449. package/dist/runtime-renderer/context.d.ts +185 -0
  450. package/dist/runtime-renderer/context.js +7 -0
  451. package/dist/runtime-renderer/context.js.map +1 -0
  452. package/dist/runtime-renderer/fallback.d.ts +39 -0
  453. package/dist/runtime-renderer/fallback.js +45 -0
  454. package/dist/runtime-renderer/fallback.js.map +1 -0
  455. package/dist/runtime-renderer/index.d.ts +13 -0
  456. package/dist/runtime-renderer/index.js +13 -0
  457. package/dist/runtime-renderer/index.js.map +1 -0
  458. package/dist/runtime-renderer/primitives.d.ts +85 -0
  459. package/dist/runtime-renderer/primitives.js +442 -0
  460. package/dist/runtime-renderer/primitives.js.map +1 -0
  461. package/dist/runtime-renderer/render.d.ts +138 -0
  462. package/dist/runtime-renderer/render.js +825 -0
  463. package/dist/runtime-renderer/render.js.map +1 -0
  464. package/dist/runtime-renderer/rich-text.d.ts +26 -0
  465. package/dist/runtime-renderer/rich-text.js +113 -0
  466. package/dist/runtime-renderer/rich-text.js.map +1 -0
  467. package/dist/starter-kits/index.d.ts +13 -0
  468. package/dist/starter-kits/index.js +14 -0
  469. package/dist/starter-kits/index.js.map +1 -0
  470. package/dist/starter-kits/instantiate.d.ts +29 -0
  471. package/dist/starter-kits/instantiate.js +24 -0
  472. package/dist/starter-kits/instantiate.js.map +1 -0
  473. package/dist/starter-kits/kit.d.ts +61 -0
  474. package/dist/starter-kits/kit.js +37 -0
  475. package/dist/starter-kits/kit.js.map +1 -0
  476. package/dist/starter-kits/kits.d.ts +7 -0
  477. package/dist/starter-kits/kits.js +201 -0
  478. package/dist/starter-kits/kits.js.map +1 -0
  479. package/dist/starter-kits/manifests.d.ts +7 -0
  480. package/dist/starter-kits/manifests.js +111 -0
  481. package/dist/starter-kits/manifests.js.map +1 -0
  482. package/dist/starter-kits/upgrade.d.ts +39 -0
  483. package/dist/starter-kits/upgrade.js +54 -0
  484. package/dist/starter-kits/upgrade.js.map +1 -0
  485. package/dist/starter-kits/validate.d.ts +16 -0
  486. package/dist/starter-kits/validate.js +77 -0
  487. package/dist/starter-kits/validate.js.map +1 -0
  488. package/dist/studio-core/context.d.ts +27 -0
  489. package/dist/studio-core/context.js +44 -0
  490. package/dist/studio-core/context.js.map +1 -0
  491. package/dist/studio-core/errors.d.ts +58 -0
  492. package/dist/studio-core/errors.js +74 -0
  493. package/dist/studio-core/errors.js.map +1 -0
  494. package/dist/studio-core/fixtures.d.ts +18 -0
  495. package/dist/studio-core/fixtures.js +83 -0
  496. package/dist/studio-core/fixtures.js.map +1 -0
  497. package/dist/studio-core/ids.d.ts +22 -0
  498. package/dist/studio-core/ids.js +33 -0
  499. package/dist/studio-core/ids.js.map +1 -0
  500. package/dist/studio-core/index.d.ts +11 -0
  501. package/dist/studio-core/index.js +12 -0
  502. package/dist/studio-core/index.js.map +1 -0
  503. package/dist/studio-core/issues.d.ts +50 -0
  504. package/dist/studio-core/issues.js +33 -0
  505. package/dist/studio-core/issues.js.map +1 -0
  506. package/dist/studio-core/metadata.d.ts +109 -0
  507. package/dist/studio-core/metadata.js +74 -0
  508. package/dist/studio-core/metadata.js.map +1 -0
  509. package/dist/studio-core/repository.d.ts +73 -0
  510. package/dist/studio-core/repository.js +202 -0
  511. package/dist/studio-core/repository.js.map +1 -0
  512. package/dist/studio-core/sections.d.ts +73 -0
  513. package/dist/studio-core/sections.js +68 -0
  514. package/dist/studio-core/sections.js.map +1 -0
  515. package/dist/studio-core/validate.d.ts +15 -0
  516. package/dist/studio-core/validate.js +119 -0
  517. package/dist/studio-core/validate.js.map +1 -0
  518. package/dist/studio-core/workspace-config.d.ts +587 -0
  519. package/dist/studio-core/workspace-config.js +434 -0
  520. package/dist/studio-core/workspace-config.js.map +1 -0
  521. package/package.json +104 -0
@@ -0,0 +1,871 @@
1
+ import { documentKey } from './documents';
2
+ import { readAssetId, readDocumentRef } from './envelopes';
3
+ import { isFieldLocalized, resolveField } from './localization';
4
+ import { hasParentCycle, parentRelationField } from './hierarchy';
5
+ import { cmsIssue } from './issues';
6
+ /** Build a `DocumentStore` from a flat list of documents. */
7
+ export function createDocumentStore(docs) {
8
+ const byKey = new Map();
9
+ const issues = [];
10
+ for (const doc of docs) {
11
+ const key = documentKey(doc);
12
+ if (byKey.has(key)) {
13
+ issues.push(cmsIssue({
14
+ code: 'duplicate-document',
15
+ message: `Duplicate document "${doc.id}" in collection "${doc.collection}".`,
16
+ path: ['documents', key],
17
+ collectionId: doc.collection,
18
+ documentId: doc.id,
19
+ }));
20
+ continue;
21
+ }
22
+ byKey.set(key, doc);
23
+ }
24
+ return {
25
+ issues,
26
+ has: (ref) => byKey.has(documentKey(ref)),
27
+ get: (ref) => byKey.get(documentKey(ref)),
28
+ list: () => [...byKey.values()],
29
+ };
30
+ }
31
+ function isEmpty(value) {
32
+ if (value === undefined || value === null)
33
+ return true;
34
+ if (typeof value === 'string')
35
+ return value.length === 0;
36
+ if (Array.isArray(value))
37
+ return value.length === 0;
38
+ // EC-253: a plain object with no keys is empty — so a required `object` field
39
+ // whose value is `{}` is flagged missing. Object-shaped values that DO carry
40
+ // keys (relation refs `{collection,id}`, rich-text envelopes) are never empty.
41
+ if (isPlainObject(value))
42
+ return Object.keys(value).length === 0;
43
+ return false;
44
+ }
45
+ /** A non-null, non-array object — the shape an `object` field value takes (EC-253). */
46
+ function isPlainObject(value) {
47
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
48
+ }
49
+ /**
50
+ * Whether a value must still be validated even though {@link isEmpty} is true
51
+ * (EC-253). A PRESENT plain object of an `object` field is validated even with no
52
+ * keys, so its required subfields surface (`{}` is not the same as absent); every
53
+ * other empty/absent value has nothing to validate — `required` owns presence.
54
+ */
55
+ function isPresentObjectValue(field, value) {
56
+ return field.type === 'object' && isPlainObject(value);
57
+ }
58
+ // EC-277: relation values are self-typed (`{ type:'reference', collection, id }`);
59
+ // `readDocumentRef` unwraps that AND legacy bare `{ collection, id }` (lazy-on-read).
60
+ const coerceRef = readDocumentRef;
61
+ function validateScalarType(ctx, issues) {
62
+ const { field, value, path, collection, documentId } = ctx;
63
+ const bad = (detail) => issues.push(cmsIssue({
64
+ code: 'invalid-field-value',
65
+ message: `Field "${field.name}" ${detail}.`,
66
+ path,
67
+ collectionId: collection.id,
68
+ documentId,
69
+ meta: { field: field.name, type: field.type },
70
+ }));
71
+ switch (field.type) {
72
+ case 'text':
73
+ if (typeof value !== 'string')
74
+ bad('expects a string');
75
+ break;
76
+ case 'richText':
77
+ // A rich-text value is either a plain string (CMS markdown/HTML) or the
78
+ // structured @elytracms/rich-text storage envelope (an object) carrying
79
+ // formatting + composition embeds (EC-159/EC-189). Mirrors the prop-side
80
+ // `checkScalarType`; deep validation is delegated (the renderer parse guard
81
+ // + the injected rich-text-embed validator).
82
+ if (typeof value !== 'string' && !(typeof value === 'object' && value !== null)) {
83
+ bad('expects rich-text content (a string or a rich-text value)');
84
+ }
85
+ break;
86
+ case 'number':
87
+ if (typeof value !== 'number' || Number.isNaN(value))
88
+ bad('expects a number');
89
+ break;
90
+ case 'boolean':
91
+ if (typeof value !== 'boolean')
92
+ bad('expects a boolean');
93
+ break;
94
+ case 'date':
95
+ // Accept ISO date strings or epoch numbers; reject anything unparseable.
96
+ if (typeof value === 'string') {
97
+ if (Number.isNaN(Date.parse(value)))
98
+ bad('expects a valid date string');
99
+ }
100
+ else if (typeof value !== 'number') {
101
+ bad('expects a date (ISO string or epoch number)');
102
+ }
103
+ break;
104
+ case 'select': {
105
+ const allowed = new Set(field.options.map((o) => o.value));
106
+ const values = field.multiple ? (Array.isArray(value) ? value : [value]) : [value];
107
+ for (const v of values) {
108
+ if (typeof v !== 'string' || !allowed.has(v)) {
109
+ bad(`has value "${String(v)}" not among its options`);
110
+ }
111
+ }
112
+ break;
113
+ }
114
+ case 'object':
115
+ // EC-253: only the TOP-LEVEL shape is checked here (an array of objects for
116
+ // `many`, a single object for `one`); recursion into the subfields lives in
117
+ // `validateObject`, which skips malformed items this already reported.
118
+ if (field.cardinality === 'many') {
119
+ if (!Array.isArray(value) || value.some((item) => !isPlainObject(item))) {
120
+ bad('expects a list of objects');
121
+ }
122
+ }
123
+ else if (!isPlainObject(value)) {
124
+ bad('expects an object');
125
+ }
126
+ break;
127
+ case 'relation':
128
+ case 'asset':
129
+ case 'blocks':
130
+ // Validated structurally elsewhere (targets / composition), not as scalars.
131
+ break;
132
+ default: {
133
+ // Exhaustiveness: a new field type must add a case above (EC-253).
134
+ const _exhaustive = field;
135
+ void _exhaustive;
136
+ }
137
+ }
138
+ }
139
+ /**
140
+ * Validate a `blocks` composition field value via the injected callback (EC-188).
141
+ * The composition tree is validated against the field's `allow` vocabulary + the
142
+ * component registry by the studio-supplied `validateComposition`; each finding is
143
+ * wrapped into a field-keyed issue so it surfaces inline like any other field
144
+ * error. A no-op when the field is not a `blocks` field or no validator is wired
145
+ * (e.g. headless contexts without a registry).
146
+ */
147
+ function validateBlocks(ctx, issues, validateComposition) {
148
+ if (ctx.field.type !== 'blocks' || !validateComposition)
149
+ return;
150
+ const { field, value, path, collection, documentId } = ctx;
151
+ for (const finding of validateComposition(value, field)) {
152
+ issues.push(cmsIssue({
153
+ code: 'invalid-field-value',
154
+ severity: finding.severity ?? 'error',
155
+ message: `Field "${field.name}": ${finding.message}`,
156
+ path,
157
+ collectionId: collection.id,
158
+ documentId,
159
+ meta: {
160
+ field: field.name,
161
+ type: 'blocks',
162
+ ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),
163
+ },
164
+ }));
165
+ }
166
+ }
167
+ /**
168
+ * Validate the composition embeds inside a `richText` field value via the injected
169
+ * callback (EC-189). A rich-text value may carry `componentEmbed` nodes, each
170
+ * holding a single `ComponentNode` constrained by the field's `allow` vocabulary —
171
+ * the SAME leash a `blocks` field uses, applied to prose embeds. The studio-supplied
172
+ * `validateRichTextEmbeds` walks the embeds and validates each via
173
+ * `validateCompositionValue`; each finding is wrapped into a field-keyed issue,
174
+ * carrying the rich-text node path. A no-op when the field is not `richText` or no
175
+ * validator is wired (e.g. headless contexts without a registry).
176
+ */
177
+ function validateRichTextEmbeds(ctx, issues, validateRichText) {
178
+ if (ctx.field.type !== 'richText' || !validateRichText)
179
+ return;
180
+ const { field, value, path, collection, documentId } = ctx;
181
+ for (const finding of validateRichText(value, field)) {
182
+ issues.push(cmsIssue({
183
+ code: 'invalid-field-value',
184
+ severity: finding.severity ?? 'error',
185
+ message: `Field "${field.name}": ${finding.message}`,
186
+ path,
187
+ collectionId: collection.id,
188
+ documentId,
189
+ meta: {
190
+ field: field.name,
191
+ type: 'richText',
192
+ ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),
193
+ },
194
+ }));
195
+ }
196
+ }
197
+ function validateConstraints(ctx, issues) {
198
+ const { field, value, path, collection, documentId } = ctx;
199
+ const rules = field.validation;
200
+ if (!rules)
201
+ return;
202
+ const push = (detail) => issues.push(cmsIssue({
203
+ code: 'invalid-field-value',
204
+ message: `Field "${field.name}" ${detail}.`,
205
+ path,
206
+ collectionId: collection.id,
207
+ documentId,
208
+ meta: { field: field.name },
209
+ }));
210
+ if (typeof value === 'string') {
211
+ if (rules.min !== undefined && value.length < rules.min)
212
+ push(`is shorter than min length ${rules.min}`);
213
+ if (rules.max !== undefined && value.length > rules.max)
214
+ push(`is longer than max length ${rules.max}`);
215
+ if (rules.pattern !== undefined) {
216
+ let re;
217
+ try {
218
+ re = new RegExp(rules.pattern);
219
+ }
220
+ catch {
221
+ re = undefined;
222
+ }
223
+ if (re && !re.test(value))
224
+ push(`does not match pattern ${rules.pattern}`);
225
+ }
226
+ }
227
+ else if (typeof value === 'number') {
228
+ if (rules.min !== undefined && value < rules.min)
229
+ push(`is less than min ${rules.min}`);
230
+ if (rules.max !== undefined && value > rules.max)
231
+ push(`is greater than max ${rules.max}`);
232
+ }
233
+ else if (Array.isArray(value)) {
234
+ if (rules.min !== undefined && value.length < rules.min)
235
+ push(`has fewer than ${rules.min} items`);
236
+ if (rules.max !== undefined && value.length > rules.max)
237
+ push(`has more than ${rules.max} items`);
238
+ }
239
+ }
240
+ function validateRelation(ctx, issues) {
241
+ const { field, value, path, collection, registry, store, documentId } = ctx;
242
+ if (field.type !== 'relation')
243
+ return;
244
+ if (!registry.has(field.target)) {
245
+ issues.push(cmsIssue({
246
+ code: 'unknown-relation-target',
247
+ message: `Relation field "${field.name}" targets unknown collection "${field.target}".`,
248
+ path,
249
+ collectionId: collection.id,
250
+ documentId,
251
+ meta: { field: field.name, target: field.target },
252
+ }));
253
+ return;
254
+ }
255
+ const refs = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value];
256
+ if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {
257
+ issues.push(cmsIssue({
258
+ code: 'cardinality-violation',
259
+ message: `Relation field "${field.name}" is single-valued but has ${value.length} targets.`,
260
+ path,
261
+ collectionId: collection.id,
262
+ documentId,
263
+ meta: { field: field.name, cardinality: 'one' },
264
+ }));
265
+ }
266
+ refs.forEach((raw, i) => {
267
+ const ref = coerceRef(raw);
268
+ if (!ref) {
269
+ issues.push(cmsIssue({
270
+ code: 'invalid-field-value',
271
+ message: `Relation field "${field.name}" holds a value that is not a document reference.`,
272
+ path: [...path, i],
273
+ collectionId: collection.id,
274
+ documentId,
275
+ meta: { field: field.name },
276
+ }));
277
+ return;
278
+ }
279
+ if (ref.collection !== field.target) {
280
+ issues.push(cmsIssue({
281
+ code: 'unknown-relation-target',
282
+ message: `Relation field "${field.name}" points at collection "${ref.collection}" but targets "${field.target}".`,
283
+ path: [...path, i],
284
+ collectionId: collection.id,
285
+ documentId,
286
+ meta: { field: field.name, target: field.target, got: ref.collection },
287
+ }));
288
+ return;
289
+ }
290
+ if (store) {
291
+ const target = store.get(ref);
292
+ if (!target) {
293
+ issues.push(cmsIssue({
294
+ code: 'unknown-relation-target',
295
+ message: `Relation field "${field.name}" references missing document "${ref.id}" in "${ref.collection}".`,
296
+ path: [...path, i],
297
+ collectionId: collection.id,
298
+ documentId,
299
+ meta: { field: field.name, target: ref.collection, id: ref.id },
300
+ }));
301
+ }
302
+ else if (ctx.isSourcePublished && !ctx.isPublished(ref)) {
303
+ // EC-173 weak-reference aftermath: the source is published but the
304
+ // target is not, so published delivery serves the declared fallback
305
+ // for this reference. Explicit and visible — but a warning, never an
306
+ // error: weak references must not block saving or re-publishing the
307
+ // source. Re-publishing the target clears it.
308
+ issues.push(cmsIssue({
309
+ code: 'unpublished-relation-target',
310
+ severity: 'warning',
311
+ message: `Relation field "${field.name}" references unpublished document "${ref.id}" in "${ref.collection}" — the published site shows a fallback there.`,
312
+ path: [...path, i],
313
+ collectionId: collection.id,
314
+ documentId,
315
+ meta: { field: field.name, target: ref.collection, id: ref.id },
316
+ }));
317
+ }
318
+ }
319
+ });
320
+ }
321
+ function validateAsset(ctx, issues) {
322
+ const { field, value, path, collection, registry, store, documentId } = ctx;
323
+ if (field.type !== 'asset')
324
+ return;
325
+ const assetCollections = registry.assetCollections();
326
+ if (assetCollections.length === 0) {
327
+ issues.push(cmsIssue({
328
+ code: 'invalid-field-config',
329
+ message: `Asset field "${field.name}" requires an asset collection, but none is registered.`,
330
+ path,
331
+ collectionId: collection.id,
332
+ documentId,
333
+ meta: { field: field.name },
334
+ }));
335
+ return;
336
+ }
337
+ const ids = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value];
338
+ if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {
339
+ issues.push(cmsIssue({
340
+ code: 'cardinality-violation',
341
+ message: `Asset field "${field.name}" is single-valued but has ${value.length} targets.`,
342
+ path,
343
+ collectionId: collection.id,
344
+ documentId,
345
+ meta: { field: field.name, cardinality: 'one' },
346
+ }));
347
+ }
348
+ ids.forEach((rawValue, i) => {
349
+ // An asset value is the id of a document in some asset collection — self-typed
350
+ // (`{ type:'asset', id }`) or legacy bare id (EC-277 lazy-on-read).
351
+ const raw = readAssetId(rawValue);
352
+ if (raw === undefined) {
353
+ issues.push(cmsIssue({
354
+ code: 'invalid-field-value',
355
+ message: `Asset field "${field.name}" expects an asset id.`,
356
+ path: [...path, i],
357
+ collectionId: collection.id,
358
+ documentId,
359
+ meta: { field: field.name },
360
+ }));
361
+ return;
362
+ }
363
+ // Asset existence is checked against the asset library when the caller
364
+ // supplies an oracle (assets live in their own repository, not as CMS
365
+ // documents — EC-212 follow-up); otherwise it falls back to the document
366
+ // store (fixtures that model assets as documents). With neither, existence
367
+ // is simply not checked (`undefined` → skip), never wrongly flagged.
368
+ const exists = ctx.assetExists
369
+ ? ctx.assetExists(raw)
370
+ : store
371
+ ? assetCollections.some((c) => store.has({ collection: c.id, id: raw }))
372
+ : undefined;
373
+ if (exists === false) {
374
+ issues.push(cmsIssue({
375
+ code: 'unknown-asset',
376
+ message: `Asset field "${field.name}" references unknown asset "${raw}".`,
377
+ path: [...path, i],
378
+ collectionId: collection.id,
379
+ documentId,
380
+ meta: { field: field.name, asset: raw },
381
+ }));
382
+ }
383
+ });
384
+ }
385
+ /**
386
+ * Validate an `object` / repeater field value (EC-253) by recursing into each
387
+ * item's subfields. `cardinality: 'many'` is an array of objects (each item keyed
388
+ * by index in the path); `'one'` is a single object. Malformed items (already
389
+ * reported by {@link validateScalarType}) are skipped. The same {@link FieldCtx}
390
+ * (registry/store/asset oracle) is threaded so nested relation/asset subfields get
391
+ * the same target-existence checks they would at the top level.
392
+ */
393
+ function validateObject(ctx, issues, v) {
394
+ const { field } = ctx;
395
+ if (field.type !== 'object')
396
+ return;
397
+ const items = field.cardinality === 'many' ? (Array.isArray(ctx.value) ? ctx.value : []) : [ctx.value];
398
+ items.forEach((item, index) => {
399
+ if (!isPlainObject(item))
400
+ return;
401
+ const itemPath = field.cardinality === 'many' ? [...ctx.path, index] : ctx.path;
402
+ for (const sub of field.fields) {
403
+ const subValue = item[sub.name];
404
+ const subPath = [...itemPath, sub.name];
405
+ if (isEmpty(subValue)) {
406
+ if (sub.validation?.required) {
407
+ issues.push(cmsIssue({
408
+ code: 'missing-required-field',
409
+ message: `Required field "${sub.name}" is missing.`,
410
+ path: subPath,
411
+ collectionId: ctx.collection.id,
412
+ documentId: ctx.documentId,
413
+ meta: { field: sub.name },
414
+ }));
415
+ continue;
416
+ }
417
+ // EC-253 (C1): an optional but PRESENT nested object still recurses so its
418
+ // own required subfields surface; any other empty/absent value is skipped.
419
+ if (!isPresentObjectValue(sub, subValue))
420
+ continue;
421
+ }
422
+ validateFieldValue({ ...ctx, field: sub, value: subValue, path: subPath }, issues, v);
423
+ }
424
+ });
425
+ }
426
+ /**
427
+ * Run every per-field validator for one field/value/path. The single dispatch
428
+ * point shared by the document loop and the {@link validateObject} recursion, so
429
+ * a subfield is validated exactly as a top-level field would be (EC-253).
430
+ */
431
+ function validateFieldValue(ctx, issues, v) {
432
+ validateScalarType(ctx, issues);
433
+ validateConstraints(ctx, issues);
434
+ validateRelation(ctx, issues);
435
+ validateAsset(ctx, issues);
436
+ validateBlocks(ctx, issues, v.validateComposition);
437
+ validateRichTextEmbeds(ctx, issues, v.validateRichText);
438
+ validateObject(ctx, issues, v);
439
+ }
440
+ /**
441
+ * Validate a document against its collection (EC-016/017/018). Returns structured
442
+ * issues; never throws. Checks unknown collection, missing required fields,
443
+ * scalar type correctness, declared constraints, relation targets, asset
444
+ * references, and required localized values across configured locales.
445
+ */
446
+ export function validateDocument(registry, doc, options = {}) {
447
+ const issues = [];
448
+ const collection = registry.get(doc.collection);
449
+ const basePath = ['documents', documentKey(doc)];
450
+ if (!collection) {
451
+ issues.push(cmsIssue({
452
+ code: 'unknown-collection',
453
+ message: `Document "${doc.id}" references unknown collection "${doc.collection}".`,
454
+ path: basePath,
455
+ documentId: doc.id,
456
+ meta: { collection: doc.collection },
457
+ }));
458
+ return issues;
459
+ }
460
+ const { store, localeConfig, validateComposition } = options;
461
+ const validateRichText = options.validateRichTextEmbeds;
462
+ // EC-224: published-ness is the version pointer, supplied by the caller. With
463
+ // no predicate, nothing is treated as published (the EC-173 warning is inert).
464
+ const isPublished = options.isPublished ?? (() => false);
465
+ const isSourcePublished = isPublished({ collection: doc.collection, id: doc.id });
466
+ for (const field of collection.fields) {
467
+ const fieldPath = [...basePath, 'values', field.name];
468
+ const localized = isFieldLocalized(collection, field.name);
469
+ // Determine the locales over which we validate this field's value.
470
+ const locales = localized && localeConfig ? localeConfig.locales : [localeConfig?.default ?? '*'];
471
+ const defaultLocale = localeConfig
472
+ ? doc.defaultLocale ?? localeConfig.default
473
+ : undefined;
474
+ for (const locale of locales) {
475
+ // The fallback-resolved value (what would render) is used for type/constraint
476
+ // checks; the *raw* per-locale value drives the localized-required check so we
477
+ // can distinguish "genuinely missing" from "satisfied via default-locale fallback".
478
+ const resolved = localized
479
+ ? localeConfig
480
+ ? resolveField(collection, doc, field.name, locale, localeConfig).value
481
+ : doc.localized?.[locale]?.[field.name]
482
+ : doc.values[field.name];
483
+ const rawLocaleValue = localized ? doc.localized?.[locale]?.[field.name] : resolved;
484
+ const path = localized ? [...basePath, 'localized', locale, field.name] : fieldPath;
485
+ // Required check.
486
+ if (field.validation?.required) {
487
+ if (!localized) {
488
+ if (isEmpty(resolved)) {
489
+ issues.push(cmsIssue({
490
+ code: 'missing-required-field',
491
+ message: `Required field "${field.name}" is missing.`,
492
+ path,
493
+ collectionId: collection.id,
494
+ documentId: doc.id,
495
+ meta: { field: field.name },
496
+ }));
497
+ continue;
498
+ }
499
+ }
500
+ else {
501
+ const isDefault = locale === defaultLocale;
502
+ if (isDefault && isEmpty(rawLocaleValue)) {
503
+ // A required localized field MUST have a value in the default locale —
504
+ // it is the fallback source for every other locale. Missing here is an
505
+ // error (no fallback can rescue it).
506
+ issues.push(cmsIssue({
507
+ code: 'missing-localized-value',
508
+ message: `Required localized field "${field.name}" is missing for the default locale "${locale}".`,
509
+ path,
510
+ collectionId: collection.id,
511
+ documentId: doc.id,
512
+ meta: { field: field.name, locale },
513
+ }));
514
+ }
515
+ else if (!isDefault && isEmpty(rawLocaleValue) && isEmpty(resolved)) {
516
+ // Non-default locale missing AND no fallback value available.
517
+ issues.push(cmsIssue({
518
+ code: 'missing-localized-value',
519
+ severity: 'warning',
520
+ message: `Localized field "${field.name}" has no value for locale "${locale}" and no fallback.`,
521
+ path,
522
+ collectionId: collection.id,
523
+ documentId: doc.id,
524
+ meta: { field: field.name, locale },
525
+ }));
526
+ }
527
+ if (isEmpty(resolved))
528
+ continue;
529
+ }
530
+ }
531
+ if (isEmpty(resolved) && !isPresentObjectValue(field, resolved))
532
+ continue;
533
+ const value = resolved;
534
+ const ctx = {
535
+ collection,
536
+ field,
537
+ value,
538
+ path,
539
+ registry,
540
+ store,
541
+ documentId: doc.id,
542
+ isSourcePublished,
543
+ isPublished,
544
+ assetExists: options.assetExists,
545
+ };
546
+ validateFieldValue(ctx, issues, { validateComposition, validateRichText });
547
+ }
548
+ }
549
+ // EC-218: a `parent` self-relation must not form a cycle. Needs the store to
550
+ // walk the chain (other documents); the walk is cycle-safe, so this only
551
+ // reports — it never loops. Only checked when the collection declares a parent
552
+ // self-relation and a store is supplied.
553
+ if (store && parentRelationField(collection)) {
554
+ if (hasParentCycle(doc, (id) => store.get({ collection: collection.id, id }))) {
555
+ issues.push(cmsIssue({
556
+ code: 'hierarchy-cycle',
557
+ message: `Document "${doc.id}" is its own ancestor — the parent chain forms a cycle.`,
558
+ path: [...basePath, 'values', 'parent'],
559
+ collectionId: collection.id,
560
+ documentId: doc.id,
561
+ meta: { field: 'parent' },
562
+ }));
563
+ }
564
+ }
565
+ return issues;
566
+ }
567
+ /** Validate every document in a list against the registry. */
568
+ export function validateDocuments(registry, docs, options = {}) {
569
+ return docs.flatMap((d) => validateDocument(registry, d, options));
570
+ }
571
+ // --- EC-190: props as fields -------------------------------------------------
572
+ // Component props are field-defs (the same vocabulary as document fields). The
573
+ // helpers below are the prop-side mirror of the document validators: pure,
574
+ // store-free type/constraint checks plus a prop-keyed `validateComponentProps`.
575
+ // They share field-type semantics with the document path; `fields.test.ts`
576
+ // guards against drift between the two.
577
+ /**
578
+ * Pure scalar/structural type check for a field value (EC-190). Returns a human
579
+ * detail string when the value is the wrong shape for the field type, or null
580
+ * when it is acceptable. Existence checks (relation/asset targets) are NOT done
581
+ * here — they need a document store. Assumes a present value (the `required`
582
+ * check owns presence).
583
+ */
584
+ export function checkScalarType(field, value) {
585
+ switch (field.type) {
586
+ case 'text':
587
+ return typeof value === 'string' ? null : 'expects a string';
588
+ case 'richText':
589
+ // A rich-text value is either a plain string (CMS markdown/HTML) or the
590
+ // structured @elytracms/rich-text storage envelope (an object) used by the
591
+ // canvas RichText component. Deep validation is delegated (the renderer's
592
+ // parse guard / a future injected rich-text validator, mirroring blocks).
593
+ return typeof value === 'string' || (typeof value === 'object' && value !== null)
594
+ ? null
595
+ : 'expects rich-text content (a string or a rich-text value)';
596
+ case 'number':
597
+ return typeof value === 'number' && !Number.isNaN(value) ? null : 'expects a number';
598
+ case 'boolean':
599
+ return typeof value === 'boolean' ? null : 'expects a boolean';
600
+ case 'date':
601
+ if (typeof value === 'string') {
602
+ return Number.isNaN(Date.parse(value)) ? 'expects a valid date string' : null;
603
+ }
604
+ return typeof value === 'number' ? null : 'expects a date (ISO string or epoch number)';
605
+ case 'select': {
606
+ const allowed = new Set(field.options.map((o) => o.value));
607
+ const values = field.multiple ? (Array.isArray(value) ? value : [value]) : [value];
608
+ for (const v of values) {
609
+ if (typeof v !== 'string' || !allowed.has(v)) {
610
+ return `has value "${String(v)}" not among its options`;
611
+ }
612
+ }
613
+ return null;
614
+ }
615
+ case 'object':
616
+ // EC-253: top-level shape only (deep subfield validation lives in
617
+ // `validateComponentProps`, which needs the same per-field machinery).
618
+ if (field.cardinality === 'many') {
619
+ return Array.isArray(value) && value.every((item) => isPlainObject(item))
620
+ ? null
621
+ : 'expects a list of objects';
622
+ }
623
+ return isPlainObject(value) ? null : 'expects an object';
624
+ case 'relation':
625
+ case 'asset':
626
+ case 'blocks':
627
+ // relation / asset / blocks are validated structurally, not as scalars.
628
+ return null;
629
+ default: {
630
+ // Exhaustiveness: a new field type must add a case above (EC-253).
631
+ const _exhaustive = field;
632
+ void _exhaustive;
633
+ return null;
634
+ }
635
+ }
636
+ }
637
+ /**
638
+ * Pure declarative-constraint check (min/max/pattern) for a field value (EC-190).
639
+ * Returns the list of human detail strings for each violation (empty = valid).
640
+ * Mirrors `validateConstraints` without the issue-construction coupling.
641
+ */
642
+ export function checkConstraints(field, value) {
643
+ const out = [];
644
+ const rules = field.validation;
645
+ if (!rules)
646
+ return out;
647
+ if (typeof value === 'string') {
648
+ if (rules.min !== undefined && value.length < rules.min)
649
+ out.push(`is shorter than min length ${rules.min}`);
650
+ if (rules.max !== undefined && value.length > rules.max)
651
+ out.push(`is longer than max length ${rules.max}`);
652
+ if (rules.pattern !== undefined) {
653
+ let re;
654
+ try {
655
+ re = new RegExp(rules.pattern);
656
+ }
657
+ catch {
658
+ re = undefined;
659
+ }
660
+ if (re && !re.test(value))
661
+ out.push(`does not match pattern ${rules.pattern}`);
662
+ }
663
+ }
664
+ else if (typeof value === 'number') {
665
+ if (rules.min !== undefined && value < rules.min)
666
+ out.push(`is less than min ${rules.min}`);
667
+ if (rules.max !== undefined && value > rules.max)
668
+ out.push(`is greater than max ${rules.max}`);
669
+ }
670
+ else if (Array.isArray(value)) {
671
+ if (rules.min !== undefined && value.length < rules.min)
672
+ out.push(`has fewer than ${rules.min} items`);
673
+ if (rules.max !== undefined && value.length > rules.max)
674
+ out.push(`has more than ${rules.max} items`);
675
+ }
676
+ return out;
677
+ }
678
+ function checkRelationStructure(field, value) {
679
+ const out = [];
680
+ if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {
681
+ out.push(`is single-valued but has ${value.length} targets`);
682
+ }
683
+ const refs = Array.isArray(value) ? value : [value];
684
+ for (const raw of refs) {
685
+ const ref = coerceRef(raw);
686
+ if (!ref)
687
+ out.push('holds a value that is not a document reference');
688
+ else if (ref.collection !== field.target) {
689
+ out.push(`points at collection "${ref.collection}" but targets "${field.target}"`);
690
+ }
691
+ }
692
+ return out;
693
+ }
694
+ function checkAssetStructure(field, value) {
695
+ const out = [];
696
+ if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {
697
+ out.push(`is single-valued but has ${value.length} targets`);
698
+ }
699
+ const ids = Array.isArray(value) ? value : [value];
700
+ for (const raw of ids) {
701
+ if (typeof raw !== 'string')
702
+ out.push('expects an asset id string');
703
+ }
704
+ return out;
705
+ }
706
+ /**
707
+ * Build a pure, store-free validator for a single field-def's value (EC-190).
708
+ * Used by the renderer (invalid static prop → EC-015 visible fallback) and the
709
+ * inspector. Returns true when the value is structurally acceptable for the field
710
+ * type; absent values (undefined/null/'') are acceptable — the `required` check
711
+ * owns presence. Relation/asset existence and composition depth are validated
712
+ * elsewhere (they need a store / registry).
713
+ */
714
+ export function fieldValueValidator(field) {
715
+ return (value) => {
716
+ if (isEmpty(value))
717
+ return true;
718
+ return checkScalarType(field, value) === null && checkConstraints(field, value).length === 0;
719
+ };
720
+ }
721
+ /**
722
+ * Lint a field-def used as a component prop (EC-190): document-only attributes
723
+ * (`filterable`, `validation.unique`) make no sense on a prop and surface as
724
+ * structured issues, never silently ignored. Returns [] for a valid prop
725
+ * field-def.
726
+ */
727
+ export function assertPropFieldDef(field) {
728
+ const issues = [];
729
+ if (field.filterable) {
730
+ issues.push(cmsIssue({
731
+ code: 'invalid-field-config',
732
+ message: `Component prop "${field.name}" declares "filterable", which only applies to document fields.`,
733
+ path: ['props', field.name],
734
+ meta: { field: field.name },
735
+ }));
736
+ }
737
+ if (field.validation?.unique) {
738
+ issues.push(cmsIssue({
739
+ code: 'invalid-field-config',
740
+ message: `Component prop "${field.name}" declares "unique", which only applies across a collection's documents.`,
741
+ path: ['props', field.name],
742
+ meta: { field: field.name },
743
+ }));
744
+ }
745
+ // EC-253: a nested object prop's subfields are props too — lint them as well, so
746
+ // a `filterable`/`unique` buried inside a repeater is surfaced, not silently kept.
747
+ if (field.type === 'object') {
748
+ for (const sub of field.fields)
749
+ issues.push(...assertPropFieldDef(sub));
750
+ }
751
+ return issues;
752
+ }
753
+ /**
754
+ * Validate a component's static prop values against its prop field-defs (EC-190).
755
+ * The prop-side mirror of `validateDocument`: the same per-field type / constraint
756
+ * / relation-structure / asset-structure / blocks checks, keyed by prop name,
757
+ * MINUS collection-scoped concerns (uniqueness, filterability, localization) and
758
+ * store-backed existence (relation/asset target *existence* is a where-used /
759
+ * reference-integrity concern handled in EC-190 slice 6). Returns structured
760
+ * issues; never throws. The inspector surfaces these inline exactly like document
761
+ * field issues.
762
+ */
763
+ /**
764
+ * Validate one prop value against its field-def, recursing into `object` subfields
765
+ * (EC-253). The prop-side mirror of {@link validateFieldValue}: pure type +
766
+ * constraint + relation/asset-structure + composition checks, keyed by `path`.
767
+ * Shared by the top-level loop and the object recursion so a repeater item's
768
+ * subfields are validated exactly as a top-level prop would be.
769
+ */
770
+ function validatePropFieldValue(field, value, path, options, issues) {
771
+ const push = (detail, code = 'invalid-field-value') => issues.push(cmsIssue({ code, message: `Prop "${field.name}" ${detail}.`, path, meta: { field: field.name } }));
772
+ if (isEmpty(value)) {
773
+ if (field.validation?.required) {
774
+ issues.push(cmsIssue({
775
+ code: 'missing-required-field',
776
+ message: `Required prop "${field.name}" is missing.`,
777
+ path,
778
+ meta: { field: field.name },
779
+ }));
780
+ return;
781
+ }
782
+ // EC-253 (C1): an optional but PRESENT object prop still recurses so its own
783
+ // required subfields surface; any other empty/absent value has nothing to check.
784
+ if (!isPresentObjectValue(field, value))
785
+ return;
786
+ }
787
+ const typeErr = checkScalarType(field, value);
788
+ if (typeErr)
789
+ push(typeErr);
790
+ for (const detail of checkConstraints(field, value))
791
+ push(detail);
792
+ if (field.type === 'relation') {
793
+ for (const detail of checkRelationStructure(field, value))
794
+ push(detail);
795
+ }
796
+ else if (field.type === 'asset') {
797
+ for (const detail of checkAssetStructure(field, value))
798
+ push(detail);
799
+ }
800
+ else if (field.type === 'blocks' && options.validateComposition) {
801
+ for (const finding of options.validateComposition(value, field)) {
802
+ issues.push(cmsIssue({
803
+ code: 'invalid-field-value',
804
+ severity: finding.severity ?? 'error',
805
+ message: `Prop "${field.name}": ${finding.message}`,
806
+ path,
807
+ meta: {
808
+ field: field.name,
809
+ type: 'blocks',
810
+ ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),
811
+ },
812
+ }));
813
+ }
814
+ }
815
+ else if (field.type === 'richText' && options.validateRichTextEmbeds) {
816
+ // EC-189: validate the composition embeds carried by a richText prop value
817
+ // (e.g. the RichText primitive's `content`) against the prop's `allow`.
818
+ for (const finding of options.validateRichTextEmbeds(value, field)) {
819
+ issues.push(cmsIssue({
820
+ code: 'invalid-field-value',
821
+ severity: finding.severity ?? 'error',
822
+ message: `Prop "${field.name}": ${finding.message}`,
823
+ path,
824
+ meta: {
825
+ field: field.name,
826
+ type: 'richText',
827
+ ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),
828
+ },
829
+ }));
830
+ }
831
+ }
832
+ else if (field.type === 'object') {
833
+ // EC-253: recurse into each item's subfields, mirroring the document path.
834
+ const items = field.cardinality === 'many' ? (Array.isArray(value) ? value : []) : [value];
835
+ items.forEach((item, index) => {
836
+ if (!isPlainObject(item))
837
+ return;
838
+ const itemPath = field.cardinality === 'many' ? [...path, index] : path;
839
+ for (const sub of field.fields) {
840
+ validatePropFieldValue(sub, item[sub.name], [...itemPath, sub.name], options, issues);
841
+ }
842
+ });
843
+ }
844
+ }
845
+ export function validateComponentProps(fieldDefs, props, options = {}) {
846
+ const issues = [];
847
+ for (const field of fieldDefs) {
848
+ issues.push(...assertPropFieldDef(field));
849
+ validatePropFieldValue(field, props[field.name], ['props', field.name], options, issues);
850
+ }
851
+ return issues;
852
+ }
853
+ /** Resolve a relation value into the referenced documents (EC-017). */
854
+ export function resolveRelation(store, value) {
855
+ const raws = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value];
856
+ const out = [];
857
+ for (const raw of raws) {
858
+ const ref = coerceRef(raw);
859
+ if (!ref)
860
+ continue;
861
+ const doc = store.get(ref);
862
+ if (doc)
863
+ out.push(doc);
864
+ }
865
+ return out;
866
+ }
867
+ /** Build a flat values bag (non-localized only) — convenience for tests/consumers. */
868
+ export function plainValues(doc) {
869
+ return { ...doc.values };
870
+ }
871
+ //# sourceMappingURL=validate-document.js.map