rimecms 0.32.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (497) hide show
  1. package/dist/adapter-sqlite/auth.server.d.ts +2 -2
  2. package/dist/adapter-sqlite/columns.server.js +2 -2
  3. package/dist/adapter-sqlite/connect.server.d.ts +12 -0
  4. package/dist/adapter-sqlite/connect.server.js +31 -0
  5. package/dist/adapter-sqlite/generate-schema/column.server.js +1 -1
  6. package/dist/adapter-sqlite/generate-schema/index.server.js +11 -3
  7. package/dist/adapter-sqlite/generate-schema/root.server.d.ts +13 -4
  8. package/dist/adapter-sqlite/generate-schema/root.server.js +75 -131
  9. package/dist/adapter-sqlite/generate-schema/templates.server.d.ts +27 -6
  10. package/dist/adapter-sqlite/generate-schema/templates.server.js +63 -11
  11. package/dist/adapter-sqlite/index.server.d.ts +13 -5
  12. package/dist/adapter-sqlite/index.server.js +9 -6
  13. package/dist/adapter-sqlite/naming.server.d.ts +6 -8
  14. package/dist/adapter-sqlite/naming.server.js +22 -4
  15. package/dist/adapter-sqlite/paths.server.d.ts +10 -0
  16. package/dist/adapter-sqlite/paths.server.js +122 -0
  17. package/dist/adapter-sqlite/read.server.d.ts +10 -1
  18. package/dist/adapter-sqlite/read.server.js +22 -10
  19. package/dist/adapter-sqlite/select.server.d.ts +19 -0
  20. package/dist/adapter-sqlite/select.server.js +71 -63
  21. package/dist/adapter-sqlite/table.server.d.ts +2 -2
  22. package/dist/adapter-sqlite/transform.server.js +33 -3
  23. package/dist/adapter-sqlite/types.server.d.ts +10 -3
  24. package/dist/adapter-sqlite/where.server.d.ts +2 -3
  25. package/dist/adapter-sqlite/where.server.js +19 -1
  26. package/dist/core/adapter.d.ts +94 -0
  27. package/dist/core/auth/better-auth/config.server.d.ts +3 -3
  28. package/dist/core/auth/better-auth/instance.server.d.ts +6 -6
  29. package/dist/core/auth/handler/index.server.js +1 -1
  30. package/dist/core/auth/staff/derive.js +1 -1
  31. package/dist/core/auth/validate-config.js +3 -5
  32. package/dist/core/boot.server.d.ts +6 -6
  33. package/dist/core/config/types.d.ts +53 -5
  34. package/dist/core/config/validate.server.js +34 -51
  35. package/dist/core/dev/cli/commands/build.js +21 -6
  36. package/dist/core/dev/cli/commands/init.server.d.ts +2 -1
  37. package/dist/core/dev/cli/commands/init.server.js +32 -6
  38. package/dist/core/dev/cli/index.js +1 -0
  39. package/dist/core/dev/cli/templates/init.d.ts +6 -1
  40. package/dist/core/dev/cli/templates/init.js +30 -2
  41. package/dist/core/dev/cli/util/package-manager.server.d.ts +1 -0
  42. package/dist/core/dev/cli/util/package-manager.server.js +11 -8
  43. package/dist/core/dev/cli/util/package.server.d.ts +9 -0
  44. package/dist/core/dev/cli/util/package.server.js +43 -0
  45. package/dist/core/dev/codegen/types/contributions.server.d.ts +3 -2
  46. package/dist/core/dev/codegen/types/contributions.server.js +10 -3
  47. package/dist/core/dev/vite.server.js +4 -3
  48. package/dist/core/fields/blank.d.ts +21 -0
  49. package/dist/core/fields/blank.js +37 -0
  50. package/dist/core/fields/builders/field-builder.d.ts +53 -0
  51. package/dist/core/fields/builders/field-builder.js +14 -1
  52. package/dist/core/fields/builders/form-field-builder.d.ts +8 -0
  53. package/dist/core/fields/builders/form-field-builder.js +14 -1
  54. package/dist/core/fields/util.d.ts +9 -2
  55. package/dist/core/fields/util.js +123 -135
  56. package/dist/core/fields/walk.d.ts +44 -0
  57. package/dist/core/fields/walk.js +55 -0
  58. package/dist/core/handler.server.js +4 -0
  59. package/dist/core/i18n/context.d.ts +5 -0
  60. package/dist/core/i18n/context.js +6 -0
  61. package/dist/core/i18n/en/common.d.ts +71 -0
  62. package/dist/core/i18n/en/common.js +72 -1
  63. package/dist/core/i18n/en/fields.d.ts +68 -0
  64. package/dist/core/i18n/en/fields.js +69 -1
  65. package/dist/core/i18n/fr/common.d.ts +71 -0
  66. package/dist/core/i18n/fr/common.js +72 -1
  67. package/dist/core/i18n/fr/fields.d.ts +68 -0
  68. package/dist/core/i18n/fr/fields.js +69 -1
  69. package/dist/core/i18n/index.d.ts +29 -3
  70. package/dist/core/i18n/index.js +55 -29
  71. package/dist/core/locale/copy.server.js +3 -3
  72. package/dist/core/logger.server.js +15 -6
  73. package/dist/core/pipeline/build-document.server.d.ts +3 -0
  74. package/dist/core/pipeline/build-document.server.js +10 -7
  75. package/dist/core/pipeline/config-map/index.d.ts +9 -0
  76. package/dist/core/pipeline/config-map/index.js +16 -50
  77. package/dist/core/pipeline/hooks/process-document-fields.server.d.ts +3 -0
  78. package/dist/core/pipeline/hooks/process-document-fields.server.js +48 -12
  79. package/dist/core/pipeline/hooks/set-default-values.server.d.ts +1 -0
  80. package/dist/core/pipeline/hooks/set-default-values.server.js +1 -0
  81. package/dist/core/pipeline/persist/blocks/extract.server.js +1 -1
  82. package/dist/core/pipeline/persist/relations/extract.server.js +2 -0
  83. package/dist/core/pipeline/populate-relations.server.d.ts +27 -0
  84. package/dist/core/pipeline/populate-relations.server.js +42 -0
  85. package/dist/core/pipeline/run.server.d.ts +17 -6
  86. package/dist/core/pipeline/run.server.js +44 -30
  87. package/dist/core/plugins/cache/module.server.d.ts +1 -1
  88. package/dist/core/plugins/cache/module.server.js +5 -5
  89. package/dist/core/plugins/defaults/module.server.js +2 -2
  90. package/dist/core/plugins/defaults/types.d.ts +5 -3
  91. package/dist/core/plugins/sse/index.d.ts +1 -1
  92. package/dist/core/plugins/sse/index.server.d.ts +5 -6
  93. package/dist/core/plugins/sse/index.server.js +3 -2
  94. package/dist/core/plugins/sse/types.d.ts +5 -0
  95. package/dist/core/prototype/area/api.server.js +1 -2
  96. package/dist/core/prototype/area/definition.js +1 -10
  97. package/dist/core/prototype/area/definition.server.js +4 -5
  98. package/dist/core/prototype/area/hooks.server.js +3 -2
  99. package/dist/core/prototype/area/operations/find.js +2 -0
  100. package/dist/core/prototype/blank.d.ts +26 -0
  101. package/dist/core/prototype/blank.js +22 -0
  102. package/dist/core/prototype/collection/api.server.d.ts +29 -3
  103. package/dist/core/prototype/collection/api.server.js +47 -4
  104. package/dist/core/prototype/collection/definition.js +0 -3
  105. package/dist/core/prototype/collection/hooks/merge-with-blank.server.d.ts +5 -1
  106. package/dist/core/prototype/collection/hooks/merge-with-blank.server.js +8 -22
  107. package/dist/core/prototype/collection/hooks.server.js +11 -5
  108. package/dist/core/prototype/collection/nested/module.server.js +3 -1
  109. package/dist/core/prototype/collection/nested/tree.d.ts +12 -0
  110. package/dist/core/prototype/collection/nested/tree.js +42 -0
  111. package/dist/core/prototype/collection/operations/find-by-id.js +2 -0
  112. package/dist/core/prototype/collection/operations/find-by-ids.d.ts +19 -0
  113. package/dist/core/prototype/collection/operations/find-by-ids.js +54 -0
  114. package/dist/core/prototype/collection/operations/find.js +21 -27
  115. package/dist/core/prototype/collection/operations/update-slug-by-id.d.ts +20 -0
  116. package/dist/core/prototype/collection/operations/update-slug-by-id.js +53 -0
  117. package/dist/core/prototype/collection/rest/index.server.js +3 -1
  118. package/dist/core/prototype/collection/rest/update-slug-by-id.server.d.ts +2 -0
  119. package/dist/core/prototype/collection/rest/update-slug-by-id.server.js +20 -0
  120. package/dist/core/prototype/collection/thumbnail/find-thumbnail.d.ts +2 -1
  121. package/dist/core/prototype/collection/thumbnail/find-thumbnail.js +4 -27
  122. package/dist/core/prototype/collection/upload/directories/derive.js +3 -1
  123. package/dist/core/prototype/collection/upload/disk/delete.server.js +1 -2
  124. package/dist/core/prototype/define.js +2 -0
  125. package/dist/core/prototype/shared/metas/fields.js +2 -1
  126. package/dist/core/prototype/shared/title/find-title.d.ts +2 -1
  127. package/dist/core/prototype/shared/title/find-title.js +5 -28
  128. package/dist/core/prototype/shared/url/addresses.server.d.ts +26 -0
  129. package/dist/core/prototype/shared/url/addresses.server.js +119 -0
  130. package/dist/core/prototype/shared/url/doc-type.d.ts +6 -0
  131. package/dist/core/prototype/shared/url/doc-type.js +9 -0
  132. package/dist/core/prototype/shared/url/format.server.d.ts +27 -0
  133. package/dist/core/prototype/shared/url/format.server.js +38 -0
  134. package/dist/core/prototype/shared/url/hooks/create-paths.server.d.ts +2 -0
  135. package/dist/core/prototype/shared/url/hooks/create-paths.server.js +9 -0
  136. package/dist/core/prototype/shared/url/hooks/detach-paths.server.d.ts +5 -0
  137. package/dist/core/prototype/shared/url/hooks/detach-paths.server.js +18 -0
  138. package/dist/core/prototype/shared/url/hooks/index.server.d.ts +5 -1
  139. package/dist/core/prototype/shared/url/hooks/index.server.js +5 -1
  140. package/dist/core/prototype/shared/url/hooks/set-area-url.server.d.ts +2 -0
  141. package/dist/core/prototype/shared/url/hooks/set-area-url.server.js +8 -0
  142. package/dist/core/prototype/shared/url/hooks/set-live-url.server.d.ts +5 -0
  143. package/dist/core/prototype/shared/url/hooks/set-live-url.server.js +19 -0
  144. package/dist/core/prototype/shared/url/hooks/sync-paths.server.d.ts +7 -0
  145. package/dist/core/prototype/shared/url/hooks/sync-paths.server.js +37 -0
  146. package/dist/core/prototype/shared/url/refresh.server.d.ts +36 -0
  147. package/dist/core/prototype/shared/url/refresh.server.js +58 -0
  148. package/dist/core/prototype/shared/versions/configure.server.js +3 -0
  149. package/dist/core/routes/context.server.d.ts +2 -1
  150. package/dist/fields/blocks/component/AddBlockButton.svelte +48 -137
  151. package/dist/fields/blocks/component/Block.svelte +153 -117
  152. package/dist/fields/blocks/component/Block.svelte.d.ts +11 -5
  153. package/dist/fields/blocks/component/BlockActions.svelte +76 -26
  154. package/dist/fields/blocks/component/BlockActions.svelte.d.ts +3 -0
  155. package/dist/fields/blocks/component/Blocks.svelte +248 -91
  156. package/dist/fields/blocks/component/focus/BlocksFocus.svelte +680 -0
  157. package/dist/fields/blocks/component/focus/BlocksFocus.svelte.d.ts +7 -0
  158. package/dist/fields/blocks/component/focus/Layers.svelte +145 -0
  159. package/dist/fields/blocks/component/focus/Layers.svelte.d.ts +9 -0
  160. package/dist/fields/blocks/component/focus/LayersList.svelte +304 -0
  161. package/dist/fields/blocks/component/focus/LayersList.svelte.d.ts +10 -0
  162. package/dist/fields/blocks/component/focus/Palette.svelte +135 -0
  163. package/dist/fields/blocks/component/focus/Palette.svelte.d.ts +9 -0
  164. package/dist/fields/blocks/component/focus/RenderPlaceholder.svelte +77 -0
  165. package/dist/fields/blocks/component/focus/RenderPlaceholder.svelte.d.ts +10 -0
  166. package/dist/fields/blocks/component/focus/Renders.svelte +302 -0
  167. package/dist/fields/blocks/component/focus/Renders.svelte.d.ts +11 -0
  168. package/dist/fields/blocks/component/focus/Stage.svelte +190 -0
  169. package/dist/fields/blocks/component/focus/Stage.svelte.d.ts +8 -0
  170. package/dist/fields/blocks/component/focus/StagePlaceholder.svelte +69 -0
  171. package/dist/fields/blocks/component/focus/StagePlaceholder.svelte.d.ts +3 -0
  172. package/dist/fields/blocks/component/focus/focus.svelte.d.ts +140 -0
  173. package/dist/fields/blocks/component/focus/focus.svelte.js +424 -0
  174. package/dist/fields/blocks/component/picker/BlockPicker.svelte +88 -0
  175. package/dist/fields/blocks/component/picker/BlockPicker.svelte.d.ts +10 -0
  176. package/dist/fields/blocks/component/picker/BlockTile.svelte +121 -0
  177. package/dist/fields/blocks/component/picker/BlockTile.svelte.d.ts +12 -0
  178. package/dist/fields/blocks/index.d.ts +49 -7
  179. package/dist/fields/blocks/index.js +61 -12
  180. package/dist/fields/checkbox/component/Checkbox.svelte +11 -37
  181. package/dist/fields/checkbox/component/Checkbox.svelte.d.ts +1 -0
  182. package/dist/fields/combobox/component/ComboBox.svelte +37 -7
  183. package/dist/fields/combobox/component/combobox.css +26 -10
  184. package/dist/fields/date/component/Date.svelte +43 -12
  185. package/dist/fields/group/component/Group.svelte +110 -41
  186. package/dist/fields/group/index.d.ts +5 -1
  187. package/dist/fields/group/index.js +10 -2
  188. package/dist/fields/link/component/Link.svelte +184 -143
  189. package/dist/fields/link/component/RessourceInput.svelte +26 -24
  190. package/dist/fields/link/index.d.ts +1 -0
  191. package/dist/fields/link/module.server.js +2 -4
  192. package/dist/fields/number/component/Number.svelte +38 -20
  193. package/dist/fields/number/component/number.css +22 -20
  194. package/dist/fields/number/index.d.ts +1 -0
  195. package/dist/fields/radio/component/Radio.svelte +12 -0
  196. package/dist/fields/radio/index.js +1 -1
  197. package/dist/fields/relation/component/Relation.svelte +169 -40
  198. package/dist/fields/relation/component/RelationInline.svelte +258 -0
  199. package/dist/fields/relation/component/RelationInline.svelte.d.ts +26 -0
  200. package/dist/fields/relation/component/default/Default.svelte +210 -100
  201. package/dist/fields/relation/component/default/Default.svelte.d.ts +14 -1
  202. package/dist/fields/relation/component/types.d.ts +4 -0
  203. package/dist/fields/relation/component/upload/Browse.svelte +619 -88
  204. package/dist/fields/relation/component/upload/Browse.svelte.d.ts +10 -2
  205. package/dist/fields/relation/component/upload/Create.svelte +41 -0
  206. package/dist/fields/relation/component/upload/Create.svelte.d.ts +13 -0
  207. package/dist/fields/relation/component/upload/Upload.svelte +287 -101
  208. package/dist/fields/relation/component/upload/Upload.svelte.d.ts +6 -1
  209. package/dist/fields/relation/component/upload/upload.css +5 -81
  210. package/dist/fields/relation/module.server.js +7 -1
  211. package/dist/fields/relation/value.d.ts +25 -0
  212. package/dist/fields/relation/value.js +27 -0
  213. package/dist/fields/rich-text/component/RichText.svelte +12 -80
  214. package/dist/fields/rich-text/component/RichText.svelte.d.ts +1 -1
  215. package/dist/fields/rich-text/component/RichTextInline.svelte +28 -0
  216. package/dist/fields/rich-text/component/RichTextInline.svelte.d.ts +11 -0
  217. package/dist/fields/rich-text/component/bubble-menu/bubble-menu.css +4 -3
  218. package/dist/fields/rich-text/component/bubble-menu/bubble-menu.svelte +3 -1
  219. package/dist/fields/rich-text/component/bubble-menu/icon-button/icon-button.css +2 -2
  220. package/dist/fields/rich-text/component/bubble-menu/node-selector/node-selector.css +7 -10
  221. package/dist/fields/rich-text/component/drag-handle/drag-handle.css +0 -2
  222. package/dist/fields/rich-text/component/styles/editor.css +111 -0
  223. package/dist/fields/rich-text/component/styles/field.css +71 -0
  224. package/dist/fields/rich-text/component/suggestion/suggestion.svelte +41 -56
  225. package/dist/fields/rich-text/core/build-editor-config.js +1 -1
  226. package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle-plugin.js +29 -3
  227. package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle.d.ts +1 -0
  228. package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle.js +2 -1
  229. package/dist/fields/rich-text/core/features/fields/fields.css +2 -3
  230. package/dist/fields/rich-text/core/features/hr/hr.css +4 -4
  231. package/dist/fields/rich-text/core/features/link/component/link-selector.css +0 -4
  232. package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +24 -8
  233. package/dist/fields/rich-text/core/features/resource/resource.svelte +20 -6
  234. package/dist/fields/rich-text/core/features/upload/upload.svelte +20 -8
  235. package/dist/fields/rich-text/core/rich-text-editor-core.svelte +103 -0
  236. package/dist/fields/rich-text/core/rich-text-editor-core.svelte.d.ts +15 -0
  237. package/dist/fields/select/component/Select.svelte +67 -28
  238. package/dist/fields/slug/component/Slug.svelte +26 -53
  239. package/dist/fields/slug/index.d.ts +1 -0
  240. package/dist/fields/slug/index.js +1 -1
  241. package/dist/fields/tabs/component/Tabs.svelte +28 -22
  242. package/dist/fields/tabs/index.d.ts +4 -1
  243. package/dist/fields/tabs/index.js +17 -5
  244. package/dist/fields/text/index.d.ts +1 -0
  245. package/dist/fields/textarea/component/TextArea.svelte +28 -13
  246. package/dist/fields/textarea/index.d.ts +1 -0
  247. package/dist/fields/time/component/Time.svelte +9 -2
  248. package/dist/fields/toggle/component/Toggle.svelte +8 -25
  249. package/dist/fields/toggle/component/Toggle.svelte.d.ts +1 -0
  250. package/dist/fields/toggle/index.d.ts +1 -0
  251. package/dist/fields/tree/component/AddItemButton.svelte +18 -5
  252. package/dist/fields/tree/component/Tree.svelte +48 -19
  253. package/dist/fields/tree/component/TreeBlock.svelte +318 -104
  254. package/dist/fields/tree/component/TreeBlockActions.svelte +71 -7
  255. package/dist/fields/tree/component/TreeBlockActions.svelte.d.ts +4 -0
  256. package/dist/fields/tree/component/props.d.ts +2 -1
  257. package/dist/fields/tree/index.d.ts +13 -1
  258. package/dist/fields/tree/index.js +35 -9
  259. package/dist/fields/types.d.ts +3 -1
  260. package/dist/index.d.ts +4 -3
  261. package/dist/index.js +3 -2
  262. package/dist/panel/components/Root.svelte +16 -44
  263. package/dist/panel/components/Root.svelte.d.ts +1 -1
  264. package/dist/panel/components/fields/Error.svelte +18 -3
  265. package/dist/panel/components/fields/FieldsPreview.svelte +30 -17
  266. package/dist/panel/components/fields/FieldsPreviewTrigger.svelte +25 -3
  267. package/dist/panel/components/fields/Hint.svelte +51 -8
  268. package/dist/panel/components/fields/Hint.svelte.d.ts +11 -0
  269. package/dist/panel/components/fields/Label.svelte +2 -0
  270. package/dist/panel/components/fields/LabelFor.svelte +7 -2
  271. package/dist/panel/components/fields/RenderFields.svelte +10 -3
  272. package/dist/panel/components/fields/fieldset.svelte.d.ts +4 -1
  273. package/dist/panel/components/fields/fieldset.svelte.js +9 -2
  274. package/dist/panel/components/fields/index.d.ts +1 -0
  275. package/dist/panel/components/fields/setting.css +82 -0
  276. package/dist/panel/components/sections/auth/AuthForm.svelte +25 -26
  277. package/dist/panel/components/sections/collection/Avatar.svelte +61 -0
  278. package/dist/panel/components/sections/collection/Avatar.svelte.d.ts +9 -0
  279. package/dist/panel/components/sections/collection/DocStatus.svelte +28 -0
  280. package/dist/panel/components/sections/collection/DocStatus.svelte.d.ts +7 -0
  281. package/dist/panel/components/sections/collection/Empty.svelte +3 -3
  282. package/dist/panel/components/sections/collection/StatusDot.svelte +7 -5
  283. package/dist/panel/components/sections/collection/When.svelte +33 -0
  284. package/dist/panel/components/sections/collection/When.svelte.d.ts +8 -0
  285. package/dist/panel/components/sections/collection/bulk-upload/BulkUploadDialog.svelte +65 -21
  286. package/dist/panel/components/sections/collection/bulk-upload/BulkUploadDialog.svelte.d.ts +3 -2
  287. package/dist/panel/components/sections/collection/bulk-upload/DropZone.svelte +45 -162
  288. package/dist/panel/components/sections/collection/bulk-upload/DropZone.svelte.d.ts +3 -2
  289. package/dist/panel/components/sections/collection/bulk-upload/FileDrop.svelte +151 -0
  290. package/dist/panel/components/sections/collection/bulk-upload/FileDrop.svelte.d.ts +17 -0
  291. package/dist/panel/components/sections/collection/bulk-upload/PageDrop.svelte +177 -0
  292. package/dist/panel/components/sections/collection/bulk-upload/PageDrop.svelte.d.ts +12 -0
  293. package/dist/panel/components/sections/collection/bulk-upload/UploadProgress.svelte +75 -0
  294. package/dist/panel/components/sections/collection/bulk-upload/UploadProgress.svelte.d.ts +8 -0
  295. package/dist/panel/components/sections/collection/folder/Folder.svelte +18 -3
  296. package/dist/panel/components/sections/collection/folder/FolderEdit.svelte +26 -18
  297. package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte +98 -58
  298. package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte.d.ts +0 -1
  299. package/dist/panel/components/sections/collection/folder/Folders.svelte +60 -0
  300. package/dist/panel/components/sections/collection/folder/Folders.svelte.d.ts +7 -0
  301. package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte +31 -71
  302. package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte.d.ts +1 -0
  303. package/dist/panel/components/sections/collection/grid/create-directory-dialog/CreateDirectoryDialog.svelte +5 -3
  304. package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte +250 -37
  305. package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte.d.ts +2 -0
  306. package/dist/panel/components/sections/collection/header/ButtonCreate.svelte +43 -18
  307. package/dist/panel/components/sections/collection/header/ButtonCreate.svelte.d.ts +6 -4
  308. package/dist/panel/components/sections/collection/header/DisplayMode.svelte +69 -58
  309. package/dist/panel/components/sections/collection/header/DisplayMode.svelte.d.ts +0 -1
  310. package/dist/panel/components/sections/collection/header/FilterMenu.svelte +60 -0
  311. package/dist/panel/components/sections/collection/header/FilterMenu.svelte.d.ts +14 -0
  312. package/dist/panel/components/sections/collection/header/SearchInput.svelte +17 -26
  313. package/dist/panel/components/sections/collection/header/SelectUI.svelte +19 -34
  314. package/dist/panel/components/sections/collection/list/CollectionList.svelte +99 -68
  315. package/dist/panel/components/sections/collection/list/columns.d.ts +21 -0
  316. package/dist/panel/components/sections/collection/list/columns.js +23 -0
  317. package/dist/panel/components/sections/collection/list/header/Header.svelte +99 -51
  318. package/dist/panel/components/sections/collection/list/row/Row.svelte +165 -82
  319. package/dist/panel/components/sections/collection/list/row/Row.svelte.d.ts +4 -0
  320. package/dist/panel/components/sections/collection/tree/CollectionTree.svelte +92 -44
  321. package/dist/panel/components/sections/collection/tree/CollectionTree.svelte.d.ts +1 -0
  322. package/dist/panel/components/sections/collection/tree/CollectionTreeNode.svelte +139 -43
  323. package/dist/panel/components/sections/collection/tree/CollectionTreeNode.svelte.d.ts +2 -0
  324. package/dist/panel/components/sections/collection/upload-thumb-cell/UploadThumbCell.svelte +1 -1
  325. package/dist/panel/components/sections/commands/CommandButton.svelte +99 -0
  326. package/dist/panel/components/sections/commands/CommandButton.svelte.d.ts +10 -0
  327. package/dist/panel/components/sections/commands/CommandPalette.svelte +275 -0
  328. package/dist/panel/components/sections/commands/CommandPalette.svelte.d.ts +8 -0
  329. package/dist/panel/components/sections/commands/Commands.svelte +18 -0
  330. package/dist/panel/components/sections/commands/Commands.svelte.d.ts +9 -0
  331. package/dist/panel/components/sections/document/AuthAPIKeyDialog.svelte +23 -7
  332. package/dist/panel/components/sections/document/AuthFooter.svelte +31 -12
  333. package/dist/panel/components/sections/document/AutoSaveBanner.svelte +24 -7
  334. package/dist/panel/components/sections/document/ButtonSave.svelte +32 -21
  335. package/dist/panel/components/sections/document/ButtonSave.svelte.d.ts +5 -5
  336. package/dist/panel/components/sections/document/ButtonStatus.svelte +68 -20
  337. package/dist/panel/components/sections/document/ChangeSlugDialog.svelte +199 -0
  338. package/dist/panel/components/sections/document/ChangeSlugDialog.svelte.d.ts +10 -0
  339. package/dist/panel/components/sections/document/CurrentlyEdited.svelte +2 -2
  340. package/dist/panel/components/sections/document/Document.svelte +96 -65
  341. package/dist/panel/components/sections/document/DocumentChildren.svelte +175 -0
  342. package/dist/panel/components/sections/document/DocumentChildren.svelte.d.ts +8 -0
  343. package/dist/panel/components/sections/document/DocumentUrl.svelte +119 -0
  344. package/dist/panel/components/sections/document/DocumentUrl.svelte.d.ts +9 -0
  345. package/dist/panel/components/sections/document/Header.svelte +171 -94
  346. package/dist/panel/components/sections/document/Settings.svelte +255 -110
  347. package/dist/panel/components/sections/document/Settings.svelte.d.ts +0 -1
  348. package/dist/panel/components/sections/document/Versions.svelte +5 -3
  349. package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +112 -53
  350. package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte.d.ts +2 -2
  351. package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte +74 -41
  352. package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte.d.ts +1 -1
  353. package/dist/panel/components/sections/live/LiveEdit.svelte +2 -2
  354. package/dist/panel/components/sections/live/LiveFloatingUI.svelte +30 -11
  355. package/dist/panel/components/sections/live/live-edit-panel.css +2 -2
  356. package/dist/panel/components/sections/page-layout/Page.svelte +13 -1
  357. package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +55 -27
  358. package/dist/panel/components/ui/button/button.svelte +81 -54
  359. package/dist/panel/components/ui/button/index.d.ts +7 -3
  360. package/dist/panel/components/ui/button/index.js +2 -2
  361. package/dist/panel/components/ui/calendar/calendar.css +27 -27
  362. package/dist/panel/components/ui/calendar/calendar.svelte.d.ts +1 -1
  363. package/dist/panel/components/ui/card/card-description.svelte +1 -1
  364. package/dist/panel/components/ui/card/card.svelte +21 -4
  365. package/dist/panel/components/ui/card-document/card-document.svelte +24 -12
  366. package/dist/panel/components/ui/card-resource/card-resource.svelte +26 -8
  367. package/dist/panel/components/ui/checkbox/checkbox.css +8 -10
  368. package/dist/panel/components/ui/command/command-dialog.css +28 -4
  369. package/dist/panel/components/ui/command/command-dialog.svelte +4 -1
  370. package/dist/panel/components/ui/command/command-dialog.svelte.d.ts +2 -0
  371. package/dist/panel/components/ui/command/command-empty.css +1 -1
  372. package/dist/panel/components/ui/command/command-group.css +3 -3
  373. package/dist/panel/components/ui/command/command-input-select.svelte +3 -3
  374. package/dist/panel/components/ui/command/command-input.svelte +38 -14
  375. package/dist/panel/components/ui/command/command-input.svelte.d.ts +6 -1
  376. package/dist/panel/components/ui/command/command-item.css +2 -2
  377. package/dist/panel/components/ui/command/command-list.css +1 -1
  378. package/dist/panel/components/ui/command/command-separator.css +1 -1
  379. package/dist/panel/components/ui/context-menu/context-menu-item.css +2 -2
  380. package/dist/panel/components/ui/context-menu/context-menu.css +6 -7
  381. package/dist/panel/components/ui/dialog/dialog-content.css +8 -10
  382. package/dist/panel/components/ui/dialog/dialog-content.svelte +19 -0
  383. package/dist/panel/components/ui/dialog/dialog-description.css +1 -1
  384. package/dist/panel/components/ui/dialog/dialog-footer.svelte +5 -1
  385. package/dist/panel/components/ui/dialog/dialog-overlay.css +1 -1
  386. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +19 -5
  387. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-content.css +6 -4
  388. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-item.css +1 -1
  389. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-radio-item.css +1 -1
  390. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-separator.css +1 -1
  391. package/dist/panel/components/ui/input/input.svelte +57 -31
  392. package/dist/panel/components/ui/kbd/Kbd.svelte +90 -0
  393. package/dist/panel/components/ui/kbd/Kbd.svelte.d.ts +11 -0
  394. package/dist/panel/components/ui/kbd/index.d.ts +1 -0
  395. package/dist/panel/components/ui/kbd/index.js +1 -0
  396. package/dist/panel/components/ui/label/label.css +5 -3
  397. package/dist/panel/components/ui/language-switcher/LanguageSwitcher.svelte +27 -15
  398. package/dist/panel/components/ui/nav/Nav.svelte +180 -110
  399. package/dist/panel/components/ui/nav/Nav.svelte.d.ts +0 -2
  400. package/dist/panel/components/ui/nav/NavGroup.svelte +87 -73
  401. package/dist/panel/components/ui/nav/NavItemButton.svelte +69 -29
  402. package/dist/panel/components/ui/nav/UserButton.svelte +132 -71
  403. package/dist/panel/components/ui/page-header/PageHeader.svelte +140 -42
  404. package/dist/panel/components/ui/page-header/PageHeader.svelte.d.ts +8 -1
  405. package/dist/panel/components/ui/popover/popover-content.css +4 -3
  406. package/dist/panel/components/ui/radio-group/radio-group.css +4 -6
  407. package/dist/panel/components/ui/radio-row-group/radio-row-group.css +19 -7
  408. package/dist/panel/components/ui/scroll-area/scroll-area.css +2 -2
  409. package/dist/panel/components/ui/separator/separator.svelte +1 -1
  410. package/dist/panel/components/ui/sheet/index.d.ts +4 -4
  411. package/dist/panel/components/ui/sheet/index.js +5 -5
  412. package/dist/panel/components/ui/sheet/sheet.css +50 -11
  413. package/dist/panel/components/ui/sonner/sonner.css +11 -8
  414. package/dist/panel/components/ui/switch/switch.css +13 -18
  415. package/dist/panel/components/ui/tabs/tabs.css +44 -35
  416. package/dist/panel/components/ui/tag/tag.svelte +20 -6
  417. package/dist/panel/components/ui/tooltip/tooltip-content.svelte +14 -4
  418. package/dist/panel/components/ui/tree/tree-rows.css +146 -0
  419. package/dist/panel/context/blocks-ops.d.ts +78 -0
  420. package/dist/panel/context/blocks-ops.js +170 -0
  421. package/dist/panel/context/collection.svelte.d.ts +28 -0
  422. package/dist/panel/context/collection.svelte.js +120 -65
  423. package/dist/panel/context/commands.svelte.d.ts +80 -0
  424. package/dist/panel/context/commands.svelte.js +108 -0
  425. package/dist/panel/context/documentForm.svelte.d.ts +34 -2
  426. package/dist/panel/context/documentForm.svelte.js +105 -102
  427. package/dist/panel/context/live.svelte.js +2 -73
  428. package/dist/panel/context/nav.svelte.d.ts +23 -0
  429. package/dist/panel/context/nav.svelte.js +56 -0
  430. package/dist/panel/fonts/Geist-VariableFont_wght.ttf +0 -0
  431. package/dist/panel/fonts/GeistMono-VariableFont_wght.ttf +0 -0
  432. package/dist/panel/index.d.ts +7 -1
  433. package/dist/panel/index.js +10 -1
  434. package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +16 -1
  435. package/dist/panel/pages/collection/CollectionPage.svelte +236 -61
  436. package/dist/panel/pages/collection/load.server.js +1 -1
  437. package/dist/panel/pages/dashboard/Dashboard.svelte +135 -90
  438. package/dist/panel/pages/dashboard/DashboardCard.svelte +109 -0
  439. package/dist/panel/pages/dashboard/DashboardCard.svelte.d.ts +14 -0
  440. package/dist/panel/pages/dashboard/DashboardCollection.svelte +180 -57
  441. package/dist/panel/pages/dashboard/DashboardCollection.svelte.d.ts +1 -0
  442. package/dist/panel/pages/dashboard/DashboardRow.svelte +93 -0
  443. package/dist/panel/pages/dashboard/DashboardRow.svelte.d.ts +16 -0
  444. package/dist/panel/pages/dashboard/load.server.js +49 -25
  445. package/dist/panel/pages/dashboard/time.d.ts +19 -0
  446. package/dist/panel/pages/dashboard/time.js +29 -0
  447. package/dist/panel/pages/dashboard/types.d.ts +9 -2
  448. package/dist/panel/pages/live/Live.svelte +53 -50
  449. package/dist/panel/style/font.css +21 -32
  450. package/dist/panel/style/index.css +191 -122
  451. package/dist/panel/style/mixins/index.css +14 -0
  452. package/dist/panel/style/palette.css +35 -26
  453. package/dist/panel/style/postcss/size-function.d.ts +4 -0
  454. package/dist/panel/style/postcss/size-function.js +24 -0
  455. package/dist/panel/style/radius.css +4 -5
  456. package/dist/panel/style/scheme.css +111 -0
  457. package/dist/panel/style/size.css +3 -0
  458. package/dist/panel/util/Sortable.js +9 -4
  459. package/dist/panel/util/keys.d.ts +24 -0
  460. package/dist/panel/util/keys.js +63 -0
  461. package/dist/panel/util/populate.d.ts +8 -0
  462. package/dist/panel/util/populate.js +49 -0
  463. package/dist/panel/util/time.d.ts +12 -0
  464. package/dist/panel/util/time.js +35 -0
  465. package/dist/panel/util/upload-file.d.ts +106 -0
  466. package/dist/panel/util/upload-file.js +165 -0
  467. package/dist/types.d.ts +1 -0
  468. package/dist/util/index.d.ts +7 -10
  469. package/dist/util/index.js +7 -8
  470. package/dist/util/object.d.ts +10 -0
  471. package/dist/util/object.js +22 -1
  472. package/dist/util/string.d.ts +17 -0
  473. package/dist/util/string.js +23 -0
  474. package/package.json +1 -3
  475. package/dist/core/pipeline/config-map/build-tree-map.d.ts +0 -4
  476. package/dist/core/pipeline/config-map/build-tree-map.js +0 -30
  477. package/dist/core/prototype/doc.d.ts +0 -31
  478. package/dist/core/prototype/doc.js +0 -118
  479. package/dist/core/prototype/shared/url/augment.d.ts +0 -13
  480. package/dist/core/prototype/shared/url/augment.js +0 -11
  481. package/dist/core/prototype/shared/url/hooks/populate-url.server.d.ts +0 -4
  482. package/dist/core/prototype/shared/url/hooks/populate-url.server.js +0 -120
  483. package/dist/fields/rich-text/component/styles/rich-text.css +0 -183
  484. package/dist/panel/components/sections/collection/header/Header.svelte +0 -17
  485. package/dist/panel/components/sections/collection/header/Header.svelte.d.ts +0 -3
  486. package/dist/panel/components/sections/collection/header/Separator.svelte +0 -8
  487. package/dist/panel/components/sections/collection/header/Separator.svelte.d.ts +0 -26
  488. package/dist/panel/components/sections/collection/tree/util.d.ts +0 -12
  489. package/dist/panel/components/sections/collection/tree/util.js +0 -22
  490. package/dist/panel/fonts/ChivoMono-Italic-VariableFont_wght.ttf +0 -0
  491. package/dist/panel/fonts/ChivoMono-VariableFont_wght.ttf +0 -0
  492. package/dist/panel/fonts/Inter-VariableFont_slnt,wght.ttf +0 -0
  493. package/dist/panel/fonts/Lora-Italic-VariableFont_wght.ttf +0 -0
  494. package/dist/panel/fonts/Lora-VariableFont_wght.ttf +0 -0
  495. package/dist/panel/style/shadow.css +0 -10
  496. package/dist/util/path.d.ts +0 -16
  497. package/dist/util/path.js +0 -19
@@ -43,8 +43,14 @@ const formatMessage = (args) => {
43
43
  /**
44
44
  * Clean up old log files that exceed the maximum retention period
45
45
  */
46
+ // The cleanup lists the log directory; once an hour is plenty, once a line was every request.
47
+ const CLEANUP_INTERVAL_MS = 60 * 60 * 1000;
48
+ let lastCleanup = 0;
49
+
46
50
  const cleanupOldLogs = async () => {
47
51
  if (!LOG_TO_FILE) return;
52
+ if (Date.now() - lastCleanup < CLEANUP_INTERVAL_MS) return;
53
+ lastCleanup = Date.now();
48
54
 
49
55
  try {
50
56
  // Create logs directory if it doesn't exist
@@ -129,13 +135,16 @@ const isLevelEnabled = (level) => {
129
135
  return level >= currentLogLevel;
130
136
  };
131
137
 
138
+ // One formatter, built once: `toLocaleTimeString` with options builds one per call.
139
+ const localTime = new Intl.DateTimeFormat(undefined, {
140
+ hour: 'numeric',
141
+ minute: '2-digit',
142
+ second: '2-digit',
143
+ hour12: true
144
+ });
145
+
132
146
  function getFormattedLocalTime(date) {
133
- return date.toLocaleTimeString(undefined, {
134
- hour: 'numeric',
135
- minute: '2-digit',
136
- second: '2-digit',
137
- hour12: true
138
- });
147
+ return localTime.format(date);
139
148
  }
140
149
 
141
150
  const rimeFormatted = chalk.bold(chalk.gray('[rime]'));
@@ -2,6 +2,7 @@ import type { DocumentRows } from '../adapter.js';
2
2
  import type { BuiltArea, BuiltCollection } from '../config/types.js';
3
3
  import type { GenericDoc } from '../prototype/types.js';
4
4
  import type { RequestEvent } from '@sveltejs/kit';
5
+ import { type Populated } from './populate-relations.server.js';
5
6
  /**
6
7
  * Assembles one document out of the rows it is stored across.
7
8
  *
@@ -15,6 +16,8 @@ export declare const buildDocument: <T extends GenericDoc = GenericDoc>(rows: Do
15
16
  event: RequestEvent;
16
17
  locale?: string | undefined;
17
18
  depth?: number;
19
+ /** What the relations point at, read ahead for the whole list. Read when `depth > 0`. */
20
+ populated?: Populated;
18
21
  /** Merge the blank document, so every field the config declares is present. */
19
22
  withBlank?: boolean;
20
23
  /**
@@ -1,7 +1,7 @@
1
- import { isObjectLiteral, omit } from '../../util/object.js';
2
- import deepmerge from 'deepmerge';
1
+ import { isObjectLiteral, omit, withDefaults } from '../../util/object.js';
3
2
  import { unflatten } from 'flat';
4
3
  import { logger } from '../logger.server.js';
4
+ import { populatedKey } from './populate-relations.server.js';
5
5
  /**
6
6
  * Assembles one document out of the rows it is stored across.
7
7
  *
@@ -11,7 +11,7 @@ import { logger } from '../logger.server.js';
11
11
  * happens to them from here is a question about documents.
12
12
  */
13
13
  export const buildDocument = async (rows, args) => {
14
- const { config, event, locale, depth = 0, withBlank = true, withRowMeta = false } = args;
14
+ const { config, event, locale, depth = 0, populated, withBlank = true, withRowMeta = false } = args;
15
15
  const { rime } = event.locals;
16
16
  const flatDoc = { ...rows.base };
17
17
  for (const block of rows.blocks) {
@@ -40,9 +40,12 @@ export const buildDocument = async (rows, args) => {
40
40
  }
41
41
  let output;
42
42
  if (depth > 0) {
43
- output = await rime
44
- .collection(relation.relationTo)
45
- .findById({ id: relation.documentId, locale: relation.locale, depth: depth - 1 });
43
+ const target = populated?.get(populatedKey(relation.relationTo, relation.locale, relation.documentId));
44
+ // Missing, or not readable by this reader: the relation is left out.
45
+ if (!target)
46
+ continue;
47
+ // A copy per placement: two documents never share an object a hook could change.
48
+ output = structuredClone(target);
46
49
  }
47
50
  else {
48
51
  output = (withRowMeta ? relation : omit(['position', 'ownerId', 'path'], relation));
@@ -54,7 +57,7 @@ export const buildDocument = async (rows, args) => {
54
57
  const blank = rime.config.isCollection(config.slug)
55
58
  ? rime.collection(config.slug).blank()
56
59
  : rime.area(config.slug).blank();
57
- doc = deepmerge(blank, doc, { arrayMerge: (_, incoming) => incoming });
60
+ doc = withDefaults(doc, blank);
58
61
  }
59
62
  return doc;
60
63
  };
@@ -3,4 +3,13 @@ import type { GenericDoc } from '../../prototype/types.js';
3
3
  import type { Field } from '../../../fields/types.js';
4
4
  import type { DeepPartial } from '../../../util/types.js';
5
5
  import type { ConfigMap } from './types.js';
6
+ /**
7
+ * Every field a document carries, keyed by the path its value sits at.
8
+ *
9
+ * The keys are the on-disk path format, so the block type the walk names is stripped:
10
+ *
11
+ * ```
12
+ * layout.0:hero.title -> layout.0.title
13
+ * ```
14
+ */
6
15
  export declare const buildConfigMap: (data: DeepPartial<GenericDoc>, incomingFields: FieldBuilder<Field>[]) => ConfigMap;
@@ -1,54 +1,20 @@
1
1
  import { isFormField } from '../../fields/util.js';
2
- import { BlocksBuilder } from '../../../fields/blocks/index.js';
3
- import { GroupFieldBuilder } from '../../../fields/group/index.js';
4
- import { TabsBuilder } from '../../../fields/tabs/index.js';
5
- import { TreeBuilder } from '../../../fields/tree/index.js';
6
- import { buildTreeFieldsMap } from './build-tree-map.js';
2
+ import { walkValues } from '../../fields/walk.js';
3
+ import { normalizeFieldPath } from '../../../util/string.js';
4
+ /**
5
+ * Every field a document carries, keyed by the path its value sits at.
6
+ *
7
+ * The keys are the on-disk path format, so the block type the walk names is stripped:
8
+ *
9
+ * ```
10
+ * layout.0:hero.title -> layout.0.title
11
+ * ```
12
+ */
7
13
  export const buildConfigMap = (data, incomingFields) => {
8
- let map = {};
9
- const traverseData = (data, fields, basePath) => {
10
- if (!data)
11
- return;
12
- basePath = basePath === '' ? basePath : `${basePath}.`;
13
- for (const field of fields) {
14
- if (field instanceof TabsBuilder) {
15
- for (const tab of field.get.tabs) {
16
- if (tab.name in data) {
17
- traverseData(data[tab.name], tab.get.fields, tab.name);
18
- }
19
- }
20
- continue;
21
- }
22
- if (!isFormField(field))
23
- continue;
24
- if (!(field.name in data))
25
- continue;
26
- const value = data[field.name];
27
- const path = `${basePath}${field.name}`;
28
- map[path] = field;
29
- if (field instanceof BlocksBuilder && value && Array.isArray(value)) {
30
- const blocks = value;
31
- for (const [index, block] of blocks.entries()) {
32
- try {
33
- const blockConfig = field.get.blocks.find((b) => b.name === block.type);
34
- if (blockConfig) {
35
- traverseData(block, blockConfig.get.fields, `${path}.${index}`);
36
- }
37
- }
38
- catch {
39
- console.warn(`block at path ${path} and postition ${index} not found but there are some residual data owned by this block`);
40
- }
41
- }
42
- }
43
- else if (field instanceof TreeBuilder && value && Array.isArray(value)) {
44
- const treeMap = buildTreeFieldsMap(field, value, path);
45
- map = { ...map, ...treeMap };
46
- }
47
- else if (field instanceof GroupFieldBuilder) {
48
- traverseData(value, field.get.fields, path);
49
- }
50
- }
51
- };
52
- traverseData(data, incomingFields, '');
14
+ const map = {};
15
+ for (const { field, path } of walkValues(incomingFields, data)) {
16
+ if (isFormField(field))
17
+ map[normalizeFieldPath(path)] = field;
18
+ }
53
19
  return map;
54
20
  };
@@ -1,5 +1,8 @@
1
1
  /**
2
2
  * Walks every field of the document on the way out: drops what the reader may not see, fills an
3
3
  * empty one from its default, and hands each value to the field's own `hooks.beforeRead`.
4
+ *
5
+ * One copy of the document, walked in place. A config-map key is already normalized, so it is
6
+ * its segments and nothing else; a copy of the document per key was most of this hook.
4
7
  */
5
8
  export declare const processDocumentFields: import("../types.js").Hook<"raw", "read", "before">;
@@ -1,31 +1,35 @@
1
1
  import { Hooks } from '../define-hook.js';
2
2
  import { logger } from '../../logger.server.js';
3
- import { deleteValueAtPath, getValueAtPath, setValueAtPath } from '../../../util/object.js';
4
3
  import { buildConfigMap } from '../config-map/index.js';
5
4
  import { getDefaultValue } from './set-default-values.server.js';
6
5
  /**
7
6
  * Walks every field of the document on the way out: drops what the reader may not see, fills an
8
7
  * empty one from its default, and hands each value to the field's own `hooks.beforeRead`.
8
+ *
9
+ * One copy of the document, walked in place. A config-map key is already normalized, so it is
10
+ * its segments and nothing else; a copy of the document per key was most of this hook.
9
11
  */
10
12
  export const processDocumentFields = Hooks.beforeRead(async function processDocumentFields(args) {
11
13
  const { event } = args;
12
- let doc = args.doc;
14
+ const doc = { ...args.doc };
13
15
  const configMap = buildConfigMap(doc, args.config.fields);
14
16
  for (const [key, config] of Object.entries(configMap)) {
15
- let value = getValueAtPath(key, doc);
16
- let isEmpty;
17
+ const parts = key.split('.');
17
18
  if (!config.use.accessRead(event.locals.user)) {
18
- doc = deleteValueAtPath(doc, key);
19
+ deleteAt(doc, parts);
19
20
  continue;
20
21
  }
21
- if (value !== undefined && value !== null) {
22
+ let value = getAt(doc, parts);
23
+ // A field with no hook has nothing to wait for.
24
+ if (value !== undefined && value !== null && config.get.hooks?.beforeRead?.length) {
22
25
  value = await config.use.beforeRead(value, {
23
26
  event,
24
27
  operation: args.context,
25
28
  documentId: doc.id
26
29
  });
27
- doc = setValueAtPath(key, doc, value);
30
+ setAt(doc, parts, value);
28
31
  }
32
+ let isEmpty;
29
33
  try {
30
34
  isEmpty = config.use.isEmpty(value);
31
35
  }
@@ -35,10 +39,10 @@ export const processDocumentFields = Hooks.beforeRead(async function processDocu
35
39
  }
36
40
  if (isEmpty && config.get.defaultValue !== undefined) {
37
41
  value = await getDefaultValue({ key, config, adapter: args.event.locals.rime.adapter });
38
- doc = setValueAtPath(key, doc, value);
42
+ setAt(doc, parts, value);
39
43
  }
40
44
  if (config.type === 'blocks') {
41
- const value = getValueAtPath(key, doc);
45
+ const blocks = getAt(doc, parts);
42
46
  // Filter out possible undefined block or residual
43
47
  // Case undefined : When in dev mode, if a block table is deleted in a migration, a blocks array value could includes undefined ex :
44
48
  // * blocks: [ { ... }, undefined, { ... } ]
@@ -47,16 +51,48 @@ export const processDocumentFields = Hooks.beforeRead(async function processDocu
47
51
  // * blocks: [ { id:..., values,... }, { image: {...}} ]
48
52
  // ^
49
53
  // * the image has been placed but the block doesn't exist anymore
50
- if (value) {
51
- const withoutResidualBlock = value
54
+ if (blocks) {
55
+ const withoutResidualBlock = blocks
52
56
  .filter((b) => b && 'id' in b) // get only blocks that have .id
53
57
  .map((b, index) => ({
54
58
  ...b,
55
59
  position: index
56
60
  }));
57
- doc = setValueAtPath(key, doc, withoutResidualBlock);
61
+ setAt(doc, parts, withoutResidualBlock);
58
62
  }
59
63
  }
60
64
  }
61
65
  return { ...args, doc };
62
66
  });
67
+ /** The value the segments lead to, `undefined` past a missing one. */
68
+ const getAt = (doc, parts) => {
69
+ let current = doc;
70
+ for (const part of parts) {
71
+ if (current === undefined || current === null)
72
+ return undefined;
73
+ current = current[part];
74
+ }
75
+ return current;
76
+ };
77
+ /** Writes at the segments, opening an object — an array before an index — where one is missing. */
78
+ const setAt = (doc, parts, value) => {
79
+ let current = doc;
80
+ for (let index = 0; index < parts.length - 1; index++) {
81
+ const part = parts[index];
82
+ if (!current[part])
83
+ current[part] = /^\d+$/.test(parts[index + 1]) ? [] : {};
84
+ current = current[part];
85
+ }
86
+ current[parts[parts.length - 1]] = value;
87
+ };
88
+ /** Removes what the segments lead to; nothing, past a missing one. */
89
+ const deleteAt = (doc, parts) => {
90
+ let current = doc;
91
+ for (const part of parts.slice(0, -1)) {
92
+ if (current === undefined || current === null || !(part in current))
93
+ return;
94
+ current = current[part];
95
+ }
96
+ if (current !== undefined && current !== null)
97
+ delete current[parts[parts.length - 1]];
98
+ };
@@ -12,5 +12,6 @@ type GetDefaultValue = (args: {
12
12
  config: FormFieldBuilder;
13
13
  adapter: Adapter;
14
14
  }) => Promise<any>;
15
+ /** A relation's default is ids; they become junction rows, checked against the collection. */
15
16
  export declare const getDefaultValue: GetDefaultValue;
16
17
  export {};
@@ -71,6 +71,7 @@ const defaultRelationValue = async (config, key, adapter) => {
71
71
  };
72
72
  return await buildRelation(config.use.defaultValue({ event: getRequestEvent() }));
73
73
  };
74
+ /** A relation's default is ids; they become junction rows, checked against the collection. */
74
75
  export const getDefaultValue = async ({ key, config, adapter }) => {
75
76
  if (config instanceof RelationFieldBuilder) {
76
77
  return await defaultRelationValue(config, key, adapter);
@@ -1,4 +1,4 @@
1
- import { normalizeFieldPath } from '../../../../util/path.js';
1
+ import { normalizeFieldPath } from '../../../../util/string.js';
2
2
  import { getValueAtPath } from '../../../../util/object.js';
3
3
  export function extractBlocks({ data, configMap }) {
4
4
  const blocks = [];
@@ -2,6 +2,8 @@ import { RelationFieldBuilder } from '../../../../fields/relation/index.js';
2
2
  import { getValueAtPath } from '../../../../util/object.js';
3
3
  export const extractRelations = ({ ownerId, data, configMap, locale }) => {
4
4
  const relations = [];
5
+ // The config map keys every field the document holds; relations are the ones stored as junction
6
+ // rows, and the key is the `path` those rows carry.
5
7
  for (const [path, config] of Object.entries(configMap)) {
6
8
  if (config instanceof RelationFieldBuilder) {
7
9
  const value = getValueAtPath(path, data);
@@ -0,0 +1,27 @@
1
+ import type { DocumentRows } from '../adapter.js';
2
+ import type { GenericDoc } from '../prototype/types.js';
3
+ import type { RequestEvent } from '@sveltejs/kit';
4
+ /**
5
+ * The documents a list's relations point at, keyed by `populatedKey`.
6
+ *
7
+ * Read for one operation, by one reader, and dropped with it.
8
+ */
9
+ export type Populated = Map<string, GenericDoc>;
10
+ export declare const populatedKey: (slug: string, locale: string | undefined, id: string) => string;
11
+ /**
12
+ * Reads what the relations of a whole list point at, one `findByIds` per collection and locale.
13
+ *
14
+ * ```ts
15
+ * // 20 pages, 2 relations each, 22 distinct targets
16
+ * // 40 × findById -> 1 × findByIds({ ids: [...22] })
17
+ * ```
18
+ *
19
+ * A relation row keeps its own locale, or none: the target is read in that locale, else in the
20
+ * request's, as `findById` would. A target that is missing or refused to this reader is absent
21
+ * from the map.
22
+ */
23
+ export declare const populateRelations: (rows: DocumentRows[], args: {
24
+ event: RequestEvent;
25
+ locale?: string;
26
+ depth: number;
27
+ }) => Promise<Populated>;
@@ -0,0 +1,42 @@
1
+ export const populatedKey = (slug, locale, id) => `${slug}:${locale ?? ''}:${id}`;
2
+ /**
3
+ * Reads what the relations of a whole list point at, one `findByIds` per collection and locale.
4
+ *
5
+ * ```ts
6
+ * // 20 pages, 2 relations each, 22 distinct targets
7
+ * // 40 × findById -> 1 × findByIds({ ids: [...22] })
8
+ * ```
9
+ *
10
+ * A relation row keeps its own locale, or none: the target is read in that locale, else in the
11
+ * request's, as `findById` would. A target that is missing or refused to this reader is absent
12
+ * from the map.
13
+ */
14
+ export const populateRelations = async (rows, args) => {
15
+ const { event, locale, depth } = args;
16
+ const groups = new Map();
17
+ for (const relation of rows.flatMap((row) => row.relations)) {
18
+ if (!relation.documentId)
19
+ continue;
20
+ // A row written in another locale is not part of this read.
21
+ if (relation.locale && relation.locale !== locale)
22
+ continue;
23
+ const key = `${relation.relationTo}:${relation.locale ?? ''}`;
24
+ const group = groups.get(key) ?? {
25
+ slug: relation.relationTo,
26
+ locale: relation.locale ?? undefined,
27
+ ids: new Set()
28
+ };
29
+ group.ids.add(relation.documentId);
30
+ groups.set(key, group);
31
+ }
32
+ const populated = new Map();
33
+ await Promise.all([...groups.values()].map(async (group) => {
34
+ const docs = await event.locals.rime
35
+ .collection(group.slug)
36
+ .findByIds({ ids: [...group.ids], locale: group.locale, depth: depth - 1 });
37
+ for (const doc of docs) {
38
+ populated.set(populatedKey(group.slug, group.locale, doc.id), doc);
39
+ }
40
+ }));
41
+ return populated;
42
+ };
@@ -97,12 +97,7 @@ export declare const persistRelational: (args: {
97
97
  config: AnyConfig;
98
98
  locale?: string | undefined;
99
99
  }) => Promise<void>;
100
- /**
101
- * The read tail shared by findById and an area's find: turn a raw adapter row into a document,
102
- * then run the beforeRead chain over it.
103
- */
104
- export declare const readDocument: <S extends DocType, T extends GenericDoc>(args: {
105
- raw: RawDoc;
100
+ type ReadArgs<S extends DocType> = {
106
101
  config: AnyConfig;
107
102
  event: RequestEvent;
108
103
  context: OperationContext<S>;
@@ -110,6 +105,22 @@ export declare const readDocument: <S extends DocType, T extends GenericDoc>(arg
110
105
  localeFallback?: boolean;
111
106
  depth?: number;
112
107
  select?: string[];
108
+ };
109
+ /**
110
+ * The read tail of a list: every raw adapter row turned into rows, what their relations point at
111
+ * read in one pass, then each document built and run through the beforeRead chain.
112
+ *
113
+ * One settled result per raw, in order: a document that fails is the caller's to skip or throw.
114
+ */
115
+ export declare const readDocuments: <S extends DocType, T extends GenericDoc>(args: ReadArgs<S> & {
116
+ raws: RawDoc[];
117
+ }) => Promise<PromiseSettledResult<{
118
+ doc: T;
119
+ context: OperationContext<S>;
120
+ }>[]>;
121
+ /** The read tail of a single document: `readDocuments` over one raw row, its failure thrown. */
122
+ export declare const readDocument: <S extends DocType, T extends GenericDoc>(args: ReadArgs<S> & {
123
+ raw: RawDoc;
113
124
  }) => Promise<{
114
125
  doc: T;
115
126
  context: OperationContext<S>;
@@ -1,6 +1,7 @@
1
1
  import { RimeError } from '../errors/index.js';
2
2
  import { versionsWritePlan } from '../prototype/shared/versions/write-plan.js';
3
3
  import { buildDocument } from './build-document.server.js';
4
+ import { populateRelations } from './populate-relations.server.js';
4
5
  import { saveBlocks } from './persist/blocks/index.server.js';
5
6
  import { saveRelations } from './persist/relations/index.server.js';
6
7
  import { saveTreeBlocks } from './persist/tree/index.server.js';
@@ -133,42 +134,55 @@ export const persistRelational = async (args) => {
133
134
  });
134
135
  };
135
136
  /**
136
- * The read tail shared by findById and an area's find: turn a raw adapter row into a document,
137
- * then run the beforeRead chain over it.
137
+ * The read tail of a list: every raw adapter row turned into rows, what their relations point at
138
+ * read in one pass, then each document built and run through the beforeRead chain.
139
+ *
140
+ * One settled result per raw, in order: a document that fails is the caller's to skip or throw.
138
141
  */
139
- export const readDocument = async (args) => {
140
- const { raw, config, event, locale, localeFallback, depth, select } = args;
142
+ export const readDocuments = async (args) => {
143
+ const { raws, config, event, locale, localeFallback, depth = 0, select } = args;
141
144
  const hasSelect = !!select && Array.isArray(select) && !!select.length;
142
- const rows = await event.locals.rime.adapter.transform.rows({
145
+ const rows = await Promise.allSettled(raws.map((raw) => event.locals.rime.adapter.transform.rows({
143
146
  doc: raw,
144
147
  slug: config.slug,
145
148
  locale,
146
149
  localeFallback
147
- });
148
- const document = await buildDocument(rows, {
149
- config,
150
- event,
151
- locale,
152
- depth,
153
- withBlank: !hasSelect,
154
- /**
155
- * The panel edits blocks and tree nodes in place, so it needs each child row's own
156
- * bookkeeping — `position`, `path`, `ownerId`, `locale` — kept on it.
157
- *
158
- * The adapter used to work this out for itself, by testing `event.params.panel`. Core naming
159
- * the panel here is the last of that coupling (core letting go of `src/lib/panel/`), and it
160
- * is one line rather than four `if`s in the database layer.
161
- */
162
- withRowMeta: event.params.panel !== undefined
163
- });
164
- return runDocHooks({
165
- hooks: config.$hooks?.beforeRead,
166
- doc: document,
167
- config,
168
- event,
169
- operation: 'read',
170
- context: args.context
171
- });
150
+ })));
151
+ const populated = depth > 0
152
+ ? await populateRelations(rows.flatMap((row) => (row.status === 'fulfilled' ? [row.value] : [])), { event, locale, depth })
153
+ : undefined;
154
+ return Promise.allSettled(rows.map(async (row) => {
155
+ if (row.status === 'rejected')
156
+ throw row.reason;
157
+ const document = await buildDocument(row.value, {
158
+ config,
159
+ event,
160
+ locale,
161
+ depth,
162
+ populated,
163
+ withBlank: !hasSelect,
164
+ /**
165
+ * The panel edits blocks and tree nodes in place, so it needs each child row's own
166
+ * bookkeeping — `position`, `path`, `ownerId`, `locale` — kept on it.
167
+ */
168
+ withRowMeta: event.params.panel !== undefined
169
+ });
170
+ return runDocHooks({
171
+ hooks: config.$hooks?.beforeRead,
172
+ doc: document,
173
+ config,
174
+ event,
175
+ operation: 'read',
176
+ context: args.context
177
+ });
178
+ }));
179
+ };
180
+ /** The read tail of a single document: `readDocuments` over one raw row, its failure thrown. */
181
+ export const readDocument = async (args) => {
182
+ const [result] = await readDocuments({ ...args, raws: [args.raw] });
183
+ if (result.status === 'rejected')
184
+ throw result.reason;
185
+ return result.value;
172
186
  };
173
187
  /**
174
188
  * The update pipeline, prototype-parameterized.
@@ -29,7 +29,7 @@ export declare const cache: (options?: CacheOptions) => {
29
29
  readonly configure: <const C extends import("../../config/types.js").Config | import("../../config/types.js").SanitizedConfigClient>(config: C) => C;
30
30
  readonly routes: {
31
31
  readonly '/api/clear-cache': {
32
- readonly POST: () => Response;
32
+ readonly POST: (event: RequestEvent) => Response;
33
33
  };
34
34
  };
35
35
  readonly actions: CacheActions;
@@ -1,4 +1,5 @@
1
- import { json } from '@sveltejs/kit';
1
+ import { isStaff } from '../../auth/access.js';
2
+ import { error, json } from '@sveltejs/kit';
2
3
  import { createHash } from 'node:crypto';
3
4
  import { definePlugin } from '../index.js';
4
5
  import { Cache } from './cache.server.js';
@@ -20,9 +21,7 @@ export const cache = definePlugin((options) => {
20
21
  async function getAction(key, get) {
21
22
  return await Cache.get(key, get);
22
23
  }
23
- /**
24
- * Empty the .cache folder
25
- */
24
+ /** Empties the cache. A config's hook calls it as an action; the route below guards it. */
26
25
  const clearCache = () => {
27
26
  Cache.clear();
28
27
  return json({ message: 'Cache cleared' });
@@ -59,8 +58,9 @@ export const cache = definePlugin((options) => {
59
58
  return config;
60
59
  },
61
60
  routes: {
61
+ // Staff only: the route is public, and an empty cache is a cost.
62
62
  '/api/clear-cache': {
63
- POST: clearCache
63
+ POST: (event) => (isStaff(event.locals.user) ? clearCache() : error(403))
64
64
  }
65
65
  },
66
66
  actions,
@@ -5,8 +5,8 @@ import { mailer } from '../mailer/index.server.js';
5
5
  import { sse } from '../sse/index.server.js';
6
6
  /** The plugins rime adds to every config, server half. Two of the four are conditional. */
7
7
  export const defaultPlugins = (config) => [
8
- // Server Sent Events
9
- sse(),
8
+ // The event stream, `$sse` says which keys an app opens
9
+ sse(config.$sse),
10
10
  // Cache plugin, with default isEnabled: event => !event.locals.user
11
11
  cache(config.$cache || {}),
12
12
  // Init endpoint, dev only
@@ -1,18 +1,20 @@
1
1
  import type { RouteConfig } from '../../config/types.js';
2
2
  import type { CacheConfig } from '../cache/types.js';
3
3
  import type { SMTPConfig } from '../mailer/index.server.js';
4
+ import type { SSEConfig } from '../sse/types.js';
4
5
  import type { Plugin } from '../index.js';
5
6
  /**
6
7
  * What the plugin step reads off a config.
7
8
  *
8
9
  * Both halves of `defaultPlugins` take this rather than `Config` or `SanitizedConfigClient`: the
9
- * step runs on both sides, and naming either one there would pin it to a side. `$cache` and
10
- * `$smtp` are what the server half branches on; a client build reads neither, and still takes the
11
- * argument so the two halves are the same function.
10
+ * step runs on both sides, and naming either one there would pin it to a side. `$cache`, `$smtp`
11
+ * and `$sse` are what the server half reads; a client build reads none of them, and still takes
12
+ * the argument so the two halves are the same function.
12
13
  */
13
14
  export type PluginHost = {
14
15
  plugins?: Plugin[];
15
16
  $routes?: Record<string, RouteConfig>;
16
17
  $cache?: CacheConfig;
17
18
  $smtp?: SMTPConfig;
19
+ $sse?: SSEConfig;
18
20
  };
@@ -7,4 +7,4 @@
7
7
  * - The client's handler is called with that event.
8
8
  */
9
9
  export { openSse } from './client.js';
10
- export type { SSEAccess, SSEEvent, SSEHandler } from './types.js';
10
+ export type { SSEAccess, SSEConfig, SSEEvent, SSEHandler } from './types.js';
@@ -1,7 +1,7 @@
1
1
  import { emit } from './bus.server.js';
2
- import type { SSEAccess } from './types.js';
2
+ import type { SSEConfig } from './types.js';
3
3
  /**
4
- * The event stream, at `/api/sse`.
4
+ * The event stream, at `/api/sse`. Added to every config, configured by its `$sse` key.
5
5
  *
6
6
  * Send with `rime.sse.emit(key, event, payload)`, listen with `openSse(keys, handler)`.
7
7
  *
@@ -9,11 +9,10 @@ import type { SSEAccess } from './types.js';
9
9
  * otherwise, so an app opens its own deliberately rather than by leaving a default alone.
10
10
  *
11
11
  * @example
12
- * sse({ access: (key) => key.startsWith('public:') })
12
+ * // rime.config.server.ts
13
+ * $sse: { access: (key) => key.startsWith('public:') }
13
14
  */
14
- export declare const sse: (options?: {
15
- access?: SSEAccess;
16
- }) => {
15
+ export declare const sse: (options?: SSEConfig) => {
17
16
  readonly name: "sse";
18
17
  readonly actions: {
19
18
  readonly emit: (key: string, event: string, payload?: Record<string, any>) => void;