includio-cms 0.1.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/ROADMAP.md +23 -13
  3. package/dist/admin/api/accept-invite.js +1 -5
  4. package/dist/admin/api/invite.js +7 -16
  5. package/dist/admin/client/account/account-page.svelte +20 -50
  6. package/dist/admin/client/account/lang.d.ts +15 -23
  7. package/dist/admin/client/account/lang.js +51 -67
  8. package/dist/admin/client/account/preferences-section.svelte +26 -84
  9. package/dist/admin/client/account/profile-section.svelte +60 -40
  10. package/dist/admin/client/account/schema.d.ts +11 -3
  11. package/dist/admin/client/account/schema.js +25 -16
  12. package/dist/admin/client/account/security-section.svelte +139 -105
  13. package/dist/admin/client/account/sessions-section.svelte +35 -34
  14. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
  15. package/dist/admin/client/admin/admin-layout.svelte +3 -2
  16. package/dist/admin/client/admin/admin-preloader.svelte +36 -0
  17. package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
  18. package/dist/admin/client/admin/dashboard-page.svelte +55 -41
  19. package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
  20. package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
  21. package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
  22. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
  23. package/dist/admin/client/collection/collection-entries.svelte +255 -256
  24. package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
  25. package/dist/admin/client/collection/collection-view.svelte.js +9 -5
  26. package/dist/admin/client/collection/collection.svelte +22 -12
  27. package/dist/admin/client/collection/data-table.svelte +50 -39
  28. package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
  29. package/dist/admin/client/collection/date-cell.svelte +7 -5
  30. package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
  31. package/dist/admin/client/collection/empty-state.svelte +28 -0
  32. package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
  33. package/dist/admin/client/collection/entry-link.svelte +10 -4
  34. package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
  35. package/dist/admin/client/collection/grid-view.svelte +21 -23
  36. package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
  37. package/dist/admin/client/collection/row-actions.svelte +60 -0
  38. package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
  39. package/dist/admin/client/collection/status-badge.svelte +7 -8
  40. package/dist/admin/client/collection/table-pagination.svelte +122 -79
  41. package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
  42. package/dist/admin/client/collection/table-toolbar.svelte +108 -88
  43. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
  44. package/dist/admin/client/entry/entry-form.svelte +109 -1
  45. package/dist/admin/client/entry/entry-header.svelte +96 -37
  46. package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
  47. package/dist/admin/client/entry/entry.svelte +171 -60
  48. package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
  49. package/dist/admin/client/entry/header/a11y-validator.js +311 -0
  50. package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
  51. package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
  52. package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
  53. package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
  54. package/dist/admin/client/entry/header/status-badge.svelte +25 -118
  55. package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
  56. package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
  57. package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
  58. package/dist/admin/client/form/form-submissions.svelte +421 -139
  59. package/dist/admin/client/form/submission-link.svelte +8 -2
  60. package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
  61. package/dist/admin/client/form/submission-status-badge.svelte +18 -4
  62. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
  63. package/dist/admin/client/login/lang.d.ts +32 -0
  64. package/dist/admin/client/login/lang.js +66 -2
  65. package/dist/admin/client/login/login-form.svelte +237 -95
  66. package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
  67. package/dist/admin/client/login/login-page.svelte +34 -98
  68. package/dist/admin/client/login/reset-password-page.svelte +235 -0
  69. package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
  70. package/dist/admin/client/login/schema.d.ts +15 -0
  71. package/dist/admin/client/login/schema.js +21 -0
  72. package/dist/admin/client/users/accept-invite-page.svelte +166 -37
  73. package/dist/admin/client/users/create-user-dialog.svelte +15 -7
  74. package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
  75. package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
  76. package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
  77. package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
  78. package/dist/admin/client/users/lang.d.ts +27 -0
  79. package/dist/admin/client/users/lang.js +64 -10
  80. package/dist/admin/client/users/pending-invitations.svelte +59 -23
  81. package/dist/admin/client/users/users-page.svelte +471 -72
  82. package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
  83. package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
  84. package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
  85. package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
  86. package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
  87. package/dist/admin/components/dashboard/index.d.ts +4 -2
  88. package/dist/admin/components/dashboard/index.js +4 -2
  89. package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
  90. package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
  91. package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
  92. package/dist/admin/components/dashboard/stat-card.svelte +2 -2
  93. package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
  94. package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
  95. package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
  96. package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
  97. package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
  98. package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
  99. package/dist/admin/components/fields/content-field.svelte +27 -0
  100. package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
  101. package/dist/admin/components/fields/field-renderer.svelte +9 -7
  102. package/dist/admin/components/fields/image-field.svelte +2 -2
  103. package/dist/admin/components/fields/media-field.svelte +2 -2
  104. package/dist/admin/components/fields/seo-field.svelte +205 -25
  105. package/dist/admin/components/fields/simple-array-field.svelte +289 -0
  106. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
  107. package/dist/admin/components/fields/slug-field.svelte +3 -2
  108. package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
  109. package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
  111. package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
  112. package/dist/admin/components/fields/url-field.svelte +5 -4
  113. package/dist/admin/components/layout/app-sidebar.svelte +27 -24
  114. package/dist/admin/components/layout/lang.d.ts +6 -0
  115. package/dist/admin/components/layout/lang.js +13 -1
  116. package/dist/admin/components/layout/layout-renderer.svelte +352 -0
  117. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
  118. package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
  119. package/dist/admin/components/layout/nav-collections.svelte +65 -36
  120. package/dist/admin/components/layout/nav-footer.svelte +31 -0
  121. package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
  122. package/dist/admin/components/layout/nav-forms.svelte +55 -30
  123. package/dist/admin/components/layout/nav-main.svelte +14 -52
  124. package/dist/admin/components/layout/nav-search.svelte +4 -3
  125. package/dist/admin/components/layout/nav-singletons.svelte +59 -17
  126. package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
  127. package/dist/admin/components/layout/site-header.svelte +74 -13
  128. package/dist/admin/components/media/alt-input.svelte +32 -22
  129. package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
  130. package/dist/admin/components/media/file/file-details.svelte +299 -217
  131. package/dist/admin/components/media/file/file-miniature.svelte +54 -41
  132. package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
  133. package/dist/admin/components/media/file/file-preview.svelte +1 -1
  134. package/dist/admin/components/media/file-upload.svelte +24 -26
  135. package/dist/admin/components/media/files-list.svelte +112 -40
  136. package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
  137. package/dist/admin/components/media/focal-point-input.svelte +122 -26
  138. package/dist/admin/components/media/media-library.svelte +127 -70
  139. package/dist/admin/components/media/media-search.svelte +6 -6
  140. package/dist/admin/components/media/media-sort.svelte +3 -1
  141. package/dist/admin/components/media/multi-file-summary.svelte +88 -68
  142. package/dist/admin/components/media/tag-combobox.svelte +141 -66
  143. package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/tag-sidebar.svelte +139 -121
  145. package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
  146. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
  147. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
  148. package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
  149. package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
  150. package/dist/admin/components/tiptap/content-editor.svelte +280 -0
  151. package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
  152. package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
  153. package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
  154. package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
  155. package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
  156. package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
  157. package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
  158. package/dist/admin/components/tiptap/inline-block-node.js +98 -0
  159. package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
  160. package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
  161. package/dist/admin/components/tiptap/slash-command.js +181 -0
  162. package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
  163. package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
  164. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
  165. package/dist/admin/email/invite-template.d.ts +8 -0
  166. package/dist/admin/email/invite-template.js +99 -0
  167. package/dist/admin/email/reset-password-template.d.ts +7 -0
  168. package/dist/admin/email/reset-password-template.js +96 -0
  169. package/dist/admin/remote/ai.remote.d.ts +1 -0
  170. package/dist/admin/remote/ai.remote.js +4 -1
  171. package/dist/admin/remote/entry.remote.d.ts +8 -0
  172. package/dist/admin/remote/entry.remote.js +53 -4
  173. package/dist/admin/remote/preview.remote.js +2 -1
  174. package/dist/admin/shared/password-schema.d.ts +5 -0
  175. package/dist/admin/shared/password-schema.js +10 -0
  176. package/dist/admin/styles/admin.css +1530 -151
  177. package/dist/admin/utils/formatDate.d.ts +1 -0
  178. package/dist/admin/utils/formatDate.js +8 -0
  179. package/dist/admin/utils/roleLabel.d.ts +2 -0
  180. package/dist/admin/utils/roleLabel.js +13 -0
  181. package/dist/ai-claude/index.d.ts +2 -0
  182. package/dist/ai-claude/index.js +56 -0
  183. package/dist/cms/runtime/api.d.ts +6 -1
  184. package/dist/cms/runtime/api.js +3 -0
  185. package/dist/cms/runtime/schemas.d.ts +9 -1
  186. package/dist/cms/runtime/schemas.js +8 -0
  187. package/dist/cms/runtime/types.d.ts +82 -10
  188. package/dist/cms/runtime/types.js +4 -0
  189. package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
  190. package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
  191. package/dist/components/ui/alert/alert.stories.svelte +53 -0
  192. package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
  193. package/dist/components/ui/alert/alert.svelte +5 -0
  194. package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
  195. package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
  196. package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
  197. package/dist/components/ui/badge/badge.stories.svelte +33 -0
  198. package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
  200. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
  201. package/dist/components/ui/button/button.stories.svelte +43 -0
  202. package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
  203. package/dist/components/ui/button/button.svelte +1 -2
  204. package/dist/components/ui/button/button.svelte.d.ts +0 -3
  205. package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
  206. package/dist/components/ui/card/card.stories.svelte +42 -0
  207. package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/command/command.stories.svelte +51 -0
  209. package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
  211. package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
  212. package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
  213. package/dist/components/ui/field/field.stories.svelte +21 -0
  214. package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/input/input.stories.svelte +40 -0
  216. package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
  217. package/dist/components/ui/input/input.svelte +2 -4
  218. package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
  219. package/dist/components/ui/label/label.stories.svelte +20 -0
  220. package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
  221. package/dist/components/ui/popover/popover.stories.svelte +29 -0
  222. package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
  223. package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
  224. package/dist/components/ui/select/select.stories.svelte +23 -0
  225. package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
  226. package/dist/components/ui/separator/separator.stories.svelte +24 -0
  227. package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
  228. package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
  229. package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
  230. package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
  231. package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
  232. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
  233. package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
  234. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
  235. package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
  236. package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
  237. package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
  238. package/dist/components/ui/sonner/sonner.svelte +8 -2
  239. package/dist/components/ui/sonner/toast-demo.svelte +29 -0
  240. package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
  241. package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
  242. package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/textarea/textarea.svelte +0 -2
  244. package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
  245. package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
  246. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
  247. package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
  248. package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
  249. package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
  250. package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
  251. package/dist/core/fields/fieldSchemaToTs.js +133 -1
  252. package/dist/core/fields/layoutUtils.d.ts +17 -0
  253. package/dist/core/fields/layoutUtils.js +149 -0
  254. package/dist/core/fields/structuredToHtml.d.ts +9 -0
  255. package/dist/core/fields/structuredToHtml.js +161 -0
  256. package/dist/core/server/entries/operations/create.js +2 -1
  257. package/dist/core/server/entries/operations/get.js +8 -6
  258. package/dist/core/server/entries/operations/update.d.ts +3 -0
  259. package/dist/core/server/entries/operations/update.js +30 -2
  260. package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
  261. package/dist/core/server/fields/queryStructuredContent.js +65 -0
  262. package/dist/core/server/fields/resolveImageFields.js +51 -2
  263. package/dist/core/server/fields/resolveRelationFields.js +2 -2
  264. package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
  265. package/dist/core/server/fields/resolveUrlFields.js +57 -6
  266. package/dist/core/server/fields/slugResolver.d.ts +10 -0
  267. package/dist/core/server/fields/slugResolver.js +34 -0
  268. package/dist/core/server/generator/fields.js +15 -4
  269. package/dist/core/server/generator/generator.js +3 -2
  270. package/dist/files-local/index.js +126 -64
  271. package/dist/paraglide/.prettierignore +3 -0
  272. package/dist/paraglide/messages/_index.d.ts +36 -0
  273. package/dist/paraglide/messages/_index.js +72 -0
  274. package/dist/paraglide/messages/en.d.ts +5 -0
  275. package/dist/paraglide/messages/en.js +14 -0
  276. package/dist/paraglide/messages/pl.d.ts +5 -0
  277. package/dist/paraglide/messages/pl.js +14 -0
  278. package/dist/paraglide/messages.d.ts +2 -0
  279. package/dist/paraglide/messages.js +4 -0
  280. package/dist/paraglide/registry.d.ts +21 -0
  281. package/dist/paraglide/registry.js +31 -0
  282. package/dist/paraglide/runtime.d.ts +583 -0
  283. package/dist/paraglide/runtime.js +1402 -0
  284. package/dist/paraglide/server.d.ts +67 -0
  285. package/dist/paraglide/server.js +175 -0
  286. package/dist/server/auth.d.ts +5 -0
  287. package/dist/server/auth.js +12 -1
  288. package/dist/sveltekit/components/structured-content.svelte +204 -0
  289. package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
  290. package/dist/sveltekit/config.d.ts +13 -3
  291. package/dist/sveltekit/index.d.ts +3 -0
  292. package/dist/sveltekit/index.js +3 -0
  293. package/dist/sveltekit/server/handle.js +1 -0
  294. package/dist/types/config.d.ts +3 -0
  295. package/dist/types/fields.d.ts +19 -2
  296. package/dist/types/index.d.ts +2 -0
  297. package/dist/types/index.js +2 -0
  298. package/dist/types/layout.d.ts +54 -0
  299. package/dist/types/layout.js +6 -0
  300. package/dist/types/structured-content.d.ts +63 -0
  301. package/dist/types/structured-content.js +1 -0
  302. package/dist/updates/0.1.4/index.d.ts +2 -0
  303. package/dist/updates/0.1.4/index.js +11 -0
  304. package/dist/updates/0.1.5/index.d.ts +2 -0
  305. package/dist/updates/0.1.5/index.js +18 -0
  306. package/dist/updates/0.2.0/index.d.ts +2 -0
  307. package/dist/updates/0.2.0/index.js +11 -0
  308. package/dist/updates/0.2.2/index.d.ts +2 -0
  309. package/dist/updates/0.2.2/index.js +13 -0
  310. package/dist/updates/0.5.0/index.d.ts +2 -0
  311. package/dist/updates/0.5.0/index.js +14 -0
  312. package/dist/updates/index.js +6 -1
  313. package/package.json +17 -10
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Server middleware that handles locale-based routing and request processing.
3
+ *
4
+ * This middleware performs several key functions:
5
+ *
6
+ * 1. Determines the locale for the incoming request using configured strategies
7
+ * 2. Handles URL localization and redirects (only for document requests)
8
+ * 3. Maintains locale state using AsyncLocalStorage to prevent request interference
9
+ *
10
+ * When URL strategy is used:
11
+ *
12
+ * - The locale is extracted from the URL for all request types
13
+ * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests)
14
+ * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)
15
+ *
16
+ * @template T - The return type of the resolve function
17
+ *
18
+ * @param {Request} request - The incoming request object
19
+ * @param {(args: { request: Request, locale: import("./runtime.js").Locale }) => T | Promise<T>} resolve - Function to handle the request
20
+ * @param {{ onRedirect:(response: Response) => void }} [callbacks] - Callbacks to handle events from middleware
21
+ * @returns {Promise<Response>}
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Basic usage in metaframeworks like NextJS, SvelteKit, Astro, Nuxt, etc.
26
+ * export const handle = async ({ event, resolve }) => {
27
+ * return serverMiddleware(event.request, ({ request, locale }) => {
28
+ * // let the framework further resolve the request
29
+ * return resolve(request);
30
+ * });
31
+ * };
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Usage in a framework like Express JS or Hono
37
+ * app.use(async (req, res, next) => {
38
+ * const result = await serverMiddleware(req, ({ request, locale }) => {
39
+ * // If a redirect happens this won't be called
40
+ * return next(request);
41
+ * });
42
+ * });
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Usage in serverless environments like Cloudflare Workers
48
+ * // ⚠️ WARNING: This should ONLY be used in serverless environments like Cloudflare Workers.
49
+ * // Disabling AsyncLocalStorage in traditional server environments risks cross-request pollution where state from
50
+ * // one request could leak into another concurrent request.
51
+ * export default {
52
+ * fetch: async (request) => {
53
+ * return serverMiddleware(
54
+ * request,
55
+ * ({ request, locale }) => handleRequest(request, locale),
56
+ * { disableAsyncLocalStorage: true }
57
+ * );
58
+ * }
59
+ * };
60
+ * ```
61
+ */
62
+ export function paraglideMiddleware<T>(request: Request, resolve: (args: {
63
+ request: Request;
64
+ locale: import("./runtime.js").Locale;
65
+ }) => T | Promise<T>, callbacks?: {
66
+ onRedirect: (response: Response) => void;
67
+ }): Promise<Response>;
@@ -0,0 +1,175 @@
1
+ /* eslint-disable */
2
+
3
+ import * as runtime from "./runtime.js";
4
+
5
+ /**
6
+ * Server middleware that handles locale-based routing and request processing.
7
+ *
8
+ * This middleware performs several key functions:
9
+ *
10
+ * 1. Determines the locale for the incoming request using configured strategies
11
+ * 2. Handles URL localization and redirects (only for document requests)
12
+ * 3. Maintains locale state using AsyncLocalStorage to prevent request interference
13
+ *
14
+ * When URL strategy is used:
15
+ *
16
+ * - The locale is extracted from the URL for all request types
17
+ * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests)
18
+ * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)
19
+ *
20
+ * @template T - The return type of the resolve function
21
+ *
22
+ * @param {Request} request - The incoming request object
23
+ * @param {(args: { request: Request, locale: import("./runtime.js").Locale }) => T | Promise<T>} resolve - Function to handle the request
24
+ * @param {{ onRedirect:(response: Response) => void }} [callbacks] - Callbacks to handle events from middleware
25
+ * @returns {Promise<Response>}
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Basic usage in metaframeworks like NextJS, SvelteKit, Astro, Nuxt, etc.
30
+ * export const handle = async ({ event, resolve }) => {
31
+ * return serverMiddleware(event.request, ({ request, locale }) => {
32
+ * // let the framework further resolve the request
33
+ * return resolve(request);
34
+ * });
35
+ * };
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Usage in a framework like Express JS or Hono
41
+ * app.use(async (req, res, next) => {
42
+ * const result = await serverMiddleware(req, ({ request, locale }) => {
43
+ * // If a redirect happens this won't be called
44
+ * return next(request);
45
+ * });
46
+ * });
47
+ * ```
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // Usage in serverless environments like Cloudflare Workers
52
+ * // ⚠️ WARNING: This should ONLY be used in serverless environments like Cloudflare Workers.
53
+ * // Disabling AsyncLocalStorage in traditional server environments risks cross-request pollution where state from
54
+ * // one request could leak into another concurrent request.
55
+ * export default {
56
+ * fetch: async (request) => {
57
+ * return serverMiddleware(
58
+ * request,
59
+ * ({ request, locale }) => handleRequest(request, locale),
60
+ * { disableAsyncLocalStorage: true }
61
+ * );
62
+ * }
63
+ * };
64
+ * ```
65
+ */
66
+ export async function paraglideMiddleware(request, resolve, callbacks) {
67
+ if (!runtime.disableAsyncLocalStorage && !runtime.serverAsyncLocalStorage) {
68
+ const { AsyncLocalStorage } = await import("async_hooks");
69
+ runtime.overwriteServerAsyncLocalStorage(new AsyncLocalStorage());
70
+ }
71
+ else if (!runtime.serverAsyncLocalStorage) {
72
+ runtime.overwriteServerAsyncLocalStorage(createMockAsyncLocalStorage());
73
+ }
74
+ const decision = await runtime.shouldRedirect({ request });
75
+ const locale = decision.locale;
76
+ const origin = new URL(request.url).origin;
77
+ // if the client makes a request to a URL that doesn't match
78
+ // the localizedUrl, redirect the client to the localized URL
79
+ if (request.headers.get("Sec-Fetch-Dest") === "document" &&
80
+ decision.shouldRedirect &&
81
+ decision.redirectUrl) {
82
+ // Create headers object with Vary header if preferredLanguage strategy is used
83
+ /** @type {Record<string, string>} */
84
+ const headers = {};
85
+ if (runtime.strategy.includes("preferredLanguage")) {
86
+ headers["Vary"] = "Accept-Language";
87
+ }
88
+ const response = new Response(null, {
89
+ status: 307,
90
+ headers: {
91
+ Location: decision.redirectUrl.href,
92
+ ...headers,
93
+ },
94
+ });
95
+ callbacks?.onRedirect(response);
96
+ return response;
97
+ }
98
+ // If the strategy includes "url", we need to de-localize the URL
99
+ // before passing it to the server middleware.
100
+ //
101
+ // The middleware is responsible for mapping a localized URL to the
102
+ // de-localized URL e.g. `/en/about` to `/about`. Otherwise,
103
+ // the server can't render the correct page.
104
+ const newRequest = runtime.strategy.includes("url")
105
+ ? new Request(runtime.deLocalizeUrl(request.url), request)
106
+ : // need to create a new request object because some metaframeworks (nextjs!) throw otherwise
107
+ // https://github.com/opral/inlang-paraglide-js/issues/411
108
+ new Request(request);
109
+ // the message functions that have been called in this request
110
+ /** @type {Set<string>} */
111
+ const messageCalls = new Set();
112
+ const response = await runtime.serverAsyncLocalStorage?.run({ locale, origin, messageCalls }, () => resolve({ locale, request: newRequest }));
113
+ // Only modify HTML responses
114
+ if (runtime.experimentalMiddlewareLocaleSplitting &&
115
+ response.headers.get("Content-Type")?.includes("html")) {
116
+ const body = await response.text();
117
+ const messages = [];
118
+ // using .values() to avoid polyfilling in older projects. else the following error is thrown
119
+ // Type 'Set<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
120
+ for (const messageCall of Array.from(messageCalls)) {
121
+ const [id, locale] =
122
+ /** @type {[string, import("./runtime.js").Locale]} */ (messageCall.split(":"));
123
+ messages.push(`${id}: ${compiledBundles[id]?.[locale]}`);
124
+ }
125
+ const script = `<script>globalThis.__paraglide_ssr = { ${messages.join(",")} }</script>`;
126
+ // Insert the script before the closing head tag
127
+ const newBody = body.replace("</head>", `${script}</head>`);
128
+ // Create a new response with the modified body
129
+ // Clone all headers except Content-Length which will be set automatically
130
+ const newHeaders = new Headers(response.headers);
131
+ newHeaders.delete("Content-Length"); // Let the browser calculate the correct length
132
+ return new Response(newBody, {
133
+ status: response.status,
134
+ statusText: response.statusText,
135
+ headers: newHeaders,
136
+ });
137
+ }
138
+ return response;
139
+ }
140
+ /**
141
+ * Creates a mock AsyncLocalStorage implementation for environments where
142
+ * native AsyncLocalStorage is not available or disabled.
143
+ *
144
+ * This mock implementation mimics the behavior of the native AsyncLocalStorage
145
+ * but doesn't require the async_hooks module. It's designed to be used in
146
+ * environments like Cloudflare Workers where AsyncLocalStorage is not available.
147
+ *
148
+ * @returns {import("./runtime.js").ParaglideAsyncLocalStorage}
149
+ */
150
+ function createMockAsyncLocalStorage() {
151
+ /** @type {any} */
152
+ let currentStore = undefined;
153
+ return {
154
+ getStore() {
155
+ return currentStore;
156
+ },
157
+ async run(store, callback) {
158
+ currentStore = store;
159
+ try {
160
+ return await callback();
161
+ }
162
+ finally {
163
+ currentStore = undefined;
164
+ }
165
+ },
166
+ };
167
+ }
168
+ /**
169
+ * The compiled messages for the server middleware.
170
+ *
171
+ * Only populated if `enableMiddlewareOptimizations` is set to `true`.
172
+ *
173
+ * @type {Record<string, Record<import("./runtime.js").Locale, string>>}
174
+ */
175
+ const compiledBundles = {};
@@ -2,6 +2,11 @@ export declare const auth: import("better-auth", { with: { "resolution-mode": "r
2
2
  database: (options: import("better-auth", { with: { "resolution-mode": "require" } }).BetterAuthOptions) => import("better-auth/adapters/drizzle", { with: { "resolution-mode": "require" } }).DBAdapter<import("better-auth", { with: { "resolution-mode": "require" } }).BetterAuthOptions>;
3
3
  emailAndPassword: {
4
4
  enabled: true;
5
+ sendResetPassword({ user, url }: {
6
+ user: import("better-auth", { with: { "resolution-mode": "require" } }).User;
7
+ url: string;
8
+ token: string;
9
+ }, request: Request | undefined): Promise<void>;
5
10
  };
6
11
  plugins: [{
7
12
  id: "admin";
@@ -2,12 +2,23 @@ import { betterAuth } from 'better-auth';
2
2
  import { drizzleAdapter } from 'better-auth/adapters/drizzle';
3
3
  import { db } from './db/index.js';
4
4
  import { admin } from 'better-auth/plugins';
5
+ import { getCMS } from '../core/cms.js';
6
+ import { resetPasswordEmailTemplate } from '../admin/email/reset-password-template.js';
5
7
  export const auth = betterAuth({
6
8
  database: drizzleAdapter(db, {
7
9
  provider: 'pg'
8
10
  }),
9
11
  emailAndPassword: {
10
- enabled: true
12
+ enabled: true,
13
+ async sendResetPassword({ user, url }, request) {
14
+ const emailAdapter = getCMS().emailAdapter;
15
+ if (!emailAdapter) {
16
+ throw new Error('Email adapter not configured');
17
+ }
18
+ const lang = request?.headers.get('Accept-Language')?.startsWith('pl') ? 'pl' : 'en';
19
+ const { subject, html } = resetPasswordEmailTemplate({ resetUrl: url, lang });
20
+ await emailAdapter.sendMail({ to: [user.email], subject, html });
21
+ }
11
22
  },
12
23
  plugins: [admin()]
13
24
  });
@@ -0,0 +1,204 @@
1
+ <script lang="ts" module>
2
+ import type { SCNode, SCMark, StructuredContentDoc, SCInlineBlockAttrs } from '../../types/structured-content.js';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ export interface StructuredContentProps {
6
+ doc: StructuredContentDoc;
7
+ class?: string;
8
+ /** Override rendering for inline blocks. Receives blockType, blockData, blockId. */
9
+ inlineBlock?: Snippet<[string, Record<string, unknown>, string]>;
10
+ /** Override rendering for figure nodes. Receives node attrs. */
11
+ figure?: Snippet<[Record<string, unknown>]>;
12
+ /** Override rendering for video nodes. Receives node attrs. */
13
+ video?: Snippet<[Record<string, unknown>]>;
14
+ /** Override rendering for heading nodes. Receives level and children snippet. */
15
+ heading?: Snippet<[number, Snippet]>;
16
+ /** Override rendering for paragraph nodes. Receives children snippet. */
17
+ paragraph?: Snippet<[Snippet]>;
18
+ /** Override rendering for code block nodes. Receives language and text content. */
19
+ codeBlock?: Snippet<[string | undefined, string]>;
20
+ }
21
+ </script>
22
+
23
+ <script lang="ts">
24
+ import Image from './image.svelte';
25
+
26
+ let {
27
+ doc,
28
+ class: className,
29
+ inlineBlock: inlineBlockSnippet,
30
+ figure: figureSnippet,
31
+ video: videoSnippet,
32
+ heading: headingSnippet,
33
+ paragraph: paragraphSnippet,
34
+ codeBlock: codeBlockSnippet
35
+ }: StructuredContentProps = $props();
36
+
37
+ function getTextContent(node: SCNode): string {
38
+ if (node.type === 'text') return node.text ?? '';
39
+ return node.content?.map(getTextContent).join('') ?? '';
40
+ }
41
+ </script>
42
+
43
+ {#snippet renderMark(text: string, marks: SCMark[], index: number)}
44
+ {#if index >= marks.length}
45
+ {text}
46
+ {:else}
47
+ {@const mark = marks[index]}
48
+ {#if mark.type === 'bold'}
49
+ <strong>{@render renderMark(text, marks, index + 1)}</strong>
50
+ {:else if mark.type === 'italic'}
51
+ <em>{@render renderMark(text, marks, index + 1)}</em>
52
+ {:else if mark.type === 'underline'}
53
+ <u>{@render renderMark(text, marks, index + 1)}</u>
54
+ {:else if mark.type === 'strike'}
55
+ <s>{@render renderMark(text, marks, index + 1)}</s>
56
+ {:else if mark.type === 'code'}
57
+ <code>{@render renderMark(text, marks, index + 1)}</code>
58
+ {:else if mark.type === 'highlight'}
59
+ <mark>{@render renderMark(text, marks, index + 1)}</mark>
60
+ {:else if mark.type === 'link'}
61
+ {@const href = (mark.attrs?.href as string) ?? ''}
62
+ {@const target = mark.attrs?.target as string | undefined}
63
+ {@const title = mark.attrs?.title as string | undefined}
64
+ {@const ariaLabel = mark.attrs?.['aria-label'] as string | undefined}
65
+ <a
66
+ {href}
67
+ target={target ?? undefined}
68
+ rel={target === '_blank' ? 'noopener noreferrer' : undefined}
69
+ {title}
70
+ aria-label={ariaLabel ?? undefined}
71
+ >{@render renderMark(text, marks, index + 1)}</a>
72
+ {:else}
73
+ {@render renderMark(text, marks, index + 1)}
74
+ {/if}
75
+ {/if}
76
+ {/snippet}
77
+
78
+ {#snippet renderNode(node: SCNode)}
79
+ {#if node.type === 'text'}
80
+ {#if node.marks?.length}
81
+ {@render renderMark(node.text ?? '', node.marks, 0)}
82
+ {:else}
83
+ {node.text}
84
+ {/if}
85
+ {:else if node.type === 'paragraph'}
86
+ {#if paragraphSnippet}
87
+ {@render paragraphSnippet(renderChildren)}
88
+ {:else}
89
+ <p>{@render renderChildren()}</p>
90
+ {/if}
91
+ {:else if node.type === 'heading'}
92
+ {@const level = (node.attrs?.level as number) ?? 2}
93
+ {#if headingSnippet}
94
+ {@render headingSnippet(level, renderChildren)}
95
+ {:else if level === 2}
96
+ <h2>{@render renderChildren()}</h2>
97
+ {:else if level === 3}
98
+ <h3>{@render renderChildren()}</h3>
99
+ {/if}
100
+ {:else if node.type === 'blockquote'}
101
+ <blockquote>{@render renderChildren()}</blockquote>
102
+ {:else if node.type === 'bulletList'}
103
+ <ul>{@render renderChildren()}</ul>
104
+ {:else if node.type === 'orderedList'}
105
+ <ol>{@render renderChildren()}</ol>
106
+ {:else if node.type === 'listItem'}
107
+ <li>{@render renderChildren()}</li>
108
+ {:else if node.type === 'codeBlock'}
109
+ {#if codeBlockSnippet}
110
+ {@render codeBlockSnippet(node.attrs?.language as string | undefined, getTextContent(node))}
111
+ {:else}
112
+ {@const lang = node.attrs?.language as string | undefined}
113
+ <pre><code class={lang ? `language-${lang}` : undefined}>{@render renderChildren()}</code></pre>
114
+ {/if}
115
+ {:else if node.type === 'horizontalRule'}
116
+ <hr>
117
+ {:else if node.type === 'hardBreak'}
118
+ <br>
119
+ {:else if node.type === 'figure'}
120
+ {#if figureSnippet}
121
+ {@render figureSnippet(node.attrs ?? {})}
122
+ {:else}
123
+ {@const attrs = node.attrs ?? {}}
124
+ {@const rawMedia = attrs._media as { data: import('../../types/media.js').MediaFile; styles?: Record<string, import('../../types/media.js').ImageStyle>; blurDataUrl?: string | null } | undefined}
125
+ {@const figMedia = rawMedia?.data ? { data: rawMedia.data, styles: rawMedia.styles ?? {}, blurDataUrl: rawMedia.blurDataUrl } : undefined}
126
+ <figure>
127
+ {#if figMedia}
128
+ <Image data={figMedia} alt={attrs.alt as string ?? figMedia.data.alt ?? ''} />
129
+ {:else}
130
+ <img
131
+ src={attrs.src as string}
132
+ alt={(attrs.alt as string) ?? ''}
133
+ width={attrs.width as number ?? undefined}
134
+ height={attrs.height as number ?? undefined}
135
+ loading="lazy"
136
+ >
137
+ {/if}
138
+ {#if attrs.caption}
139
+ <figcaption>{attrs.caption}</figcaption>
140
+ {/if}
141
+ </figure>
142
+ {/if}
143
+ {:else if node.type === 'image'}
144
+ {@const attrs = node.attrs ?? {}}
145
+ {@const rawImgMedia = attrs._media as { data: import('../../types/media.js').MediaFile; styles?: Record<string, import('../../types/media.js').ImageStyle>; blurDataUrl?: string | null } | undefined}
146
+ {@const imgMedia = rawImgMedia?.data ? { data: rawImgMedia.data, styles: rawImgMedia.styles ?? {}, blurDataUrl: rawImgMedia.blurDataUrl } : undefined}
147
+ {#if imgMedia}
148
+ <Image data={imgMedia} alt={attrs.alt as string ?? imgMedia.data.alt ?? ''} />
149
+ {:else}
150
+ <img
151
+ src={attrs.src as string}
152
+ alt={(attrs.alt as string) ?? ''}
153
+ width={attrs.width as number ?? undefined}
154
+ height={attrs.height as number ?? undefined}
155
+ loading="lazy"
156
+ >
157
+ {/if}
158
+ {:else if node.type === 'video'}
159
+ {#if videoSnippet}
160
+ {@render videoSnippet(node.attrs ?? {})}
161
+ {:else}
162
+ {@const attrs = node.attrs ?? {}}
163
+ <video
164
+ controls
165
+ poster={attrs.poster as string ?? undefined}
166
+ width={attrs.width as number ?? undefined}
167
+ height={attrs.height as number ?? undefined}
168
+ >
169
+ <source src={attrs.src as string}>
170
+ </video>
171
+ {/if}
172
+ {:else if node.type === 'table'}
173
+ <table>{@render renderChildren()}</table>
174
+ {:else if node.type === 'tableRow'}
175
+ <tr>{@render renderChildren()}</tr>
176
+ {:else if node.type === 'tableCell'}
177
+ <td>{@render renderChildren()}</td>
178
+ {:else if node.type === 'tableHeader'}
179
+ <th>{@render renderChildren()}</th>
180
+ {:else if node.type === 'inlineBlock'}
181
+ {#if inlineBlockSnippet}
182
+ {@const attrs = node.attrs as unknown as SCInlineBlockAttrs}
183
+ {@render inlineBlockSnippet(attrs.blockType, attrs.blockData, attrs.blockId)}
184
+ {/if}
185
+ {:else}
186
+ {@render renderChildren()}
187
+ {/if}
188
+
189
+ {#snippet renderChildren()}
190
+ {#if node.content}
191
+ {#each node.content as child}
192
+ {@render renderNode(child)}
193
+ {/each}
194
+ {/if}
195
+ {/snippet}
196
+ {/snippet}
197
+
198
+ {#if doc?.content}
199
+ <div class={className}>
200
+ {#each doc.content as node}
201
+ {@render renderNode(node)}
202
+ {/each}
203
+ </div>
204
+ {/if}
@@ -0,0 +1,21 @@
1
+ import type { StructuredContentDoc } from '../../types/structured-content.js';
2
+ import type { Snippet } from 'svelte';
3
+ export interface StructuredContentProps {
4
+ doc: StructuredContentDoc;
5
+ class?: string;
6
+ /** Override rendering for inline blocks. Receives blockType, blockData, blockId. */
7
+ inlineBlock?: Snippet<[string, Record<string, unknown>, string]>;
8
+ /** Override rendering for figure nodes. Receives node attrs. */
9
+ figure?: Snippet<[Record<string, unknown>]>;
10
+ /** Override rendering for video nodes. Receives node attrs. */
11
+ video?: Snippet<[Record<string, unknown>]>;
12
+ /** Override rendering for heading nodes. Receives level and children snippet. */
13
+ heading?: Snippet<[number, Snippet]>;
14
+ /** Override rendering for paragraph nodes. Receives children snippet. */
15
+ paragraph?: Snippet<[Snippet]>;
16
+ /** Override rendering for code block nodes. Receives language and text content. */
17
+ codeBlock?: Snippet<[string | undefined, string]>;
18
+ }
19
+ declare const StructuredContent: import("svelte").Component<StructuredContentProps, {}, "">;
20
+ type StructuredContent = ReturnType<typeof StructuredContent>;
21
+ export default StructuredContent;
@@ -1,10 +1,20 @@
1
1
  import type { CMSConfig } from '../types/cms.js';
2
2
  import type { CollectionConfig } from '../types/collections.js';
3
3
  import type { SingleConfig } from '../types/singles.js';
4
- import type { ObjectField } from '../types/fields.js';
4
+ import type { Field, ObjectField } from '../types/fields.js';
5
5
  import type { FormConfig } from '../types/forms.js';
6
+ import type { Layout } from '../types/layout.js';
7
+ type CollectionInput = Omit<CollectionConfig, 'fields'> & {
8
+ fields: Field[];
9
+ layout?: Layout;
10
+ };
11
+ type SingleInput = Omit<SingleConfig, 'fields'> & {
12
+ fields: Field[];
13
+ layout?: Layout;
14
+ };
6
15
  export declare function defineConfig(config: CMSConfig): CMSConfig;
7
- export declare function defineCollection(config: CollectionConfig): CollectionConfig;
8
- export declare function defineSingle(config: SingleConfig): SingleConfig;
16
+ export declare function defineCollection(config: CollectionInput): CollectionConfig;
17
+ export declare function defineSingle(config: SingleInput): SingleConfig;
9
18
  export declare function defineForm(config: FormConfig): FormConfig;
10
19
  export declare function defineObject(config: Omit<ObjectField, 'type'>): ObjectField;
20
+ export {};
@@ -5,5 +5,8 @@ export { default as HybridTarget } from './components/hybrid-target.svelte';
5
5
  export { default as Image } from './components/image.svelte';
6
6
  export { default as Video } from './components/video.svelte';
7
7
  export { default as Media } from './components/media.svelte';
8
+ export { default as StructuredContent } from './components/structured-content.svelte';
8
9
  export { enableHybridEditing } from './components/hybrid-context.js';
9
10
  export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
11
+ export { structuredToHtml } from '../core/fields/structuredToHtml.js';
12
+ export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../core/server/fields/queryStructuredContent.js';
@@ -5,5 +5,8 @@ export { default as HybridTarget } from './components/hybrid-target.svelte';
5
5
  export { default as Image } from './components/image.svelte';
6
6
  export { default as Video } from './components/video.svelte';
7
7
  export { default as Media } from './components/media.svelte';
8
+ export { default as StructuredContent } from './components/structured-content.svelte';
8
9
  export { enableHybridEditing } from './components/hybrid-context.js';
9
10
  export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
11
+ export { structuredToHtml } from '../core/fields/structuredToHtml.js';
12
+ export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../core/server/fields/queryStructuredContent.js';
@@ -10,6 +10,7 @@ const adminGuard = async ({ event, resolve }) => {
10
10
  !event.url.pathname.startsWith('/api/admin/login') &&
11
11
  !event.url.pathname.startsWith('/admin/accept-invite') &&
12
12
  !event.url.pathname.startsWith('/admin/api/accept-invite') &&
13
+ !event.url.pathname.startsWith('/admin/reset-password') &&
13
14
  (!user || !session)) {
14
15
  setFlash({
15
16
  message: 'You must be logged in to access the admin panel.',
@@ -1,8 +1,11 @@
1
1
  import type { Field } from './fields.js';
2
2
  import type { Icon } from '@tabler/icons-svelte';
3
+ import type { Layout } from './layout.js';
3
4
  export interface ConfigBase {
4
5
  sidebarIcon?: Icon;
5
6
  slug: string;
6
7
  previewUrl?: string;
7
8
  fields: Field[];
9
+ layout?: Layout;
10
+ slugField?: string;
8
11
  }
@@ -1,7 +1,8 @@
1
1
  import type { FormatEnum } from 'sharp';
2
2
  import type { ImageStyle, MediaFile } from './media.js';
3
3
  import type { Localized } from './languages.js';
4
- export type FieldType = 'text' | 'richtext' | 'number' | 'boolean' | 'date' | 'datetime' | 'file' | 'image' | 'media' | 'select' | 'radio' | 'checkboxes' | 'relation' | 'object' | 'array' | 'slug' | 'seo' | 'url';
4
+ import type { StructuredContentDoc } from './structured-content.js';
5
+ export type FieldType = 'text' | 'richtext' | 'content' | 'number' | 'boolean' | 'date' | 'datetime' | 'file' | 'image' | 'media' | 'select' | 'radio' | 'checkboxes' | 'relation' | 'object' | 'array' | 'blocks' | 'slug' | 'seo' | 'url';
5
6
  export interface BaseField {
6
7
  slug: string;
7
8
  label?: Localized;
@@ -25,6 +26,11 @@ export interface RichtextField extends BaseField {
25
26
  allowedFormats?: string[];
26
27
  defaultValue?: string;
27
28
  }
29
+ export interface ContentField extends BaseField {
30
+ type: 'content';
31
+ inlineBlocks?: ObjectField[];
32
+ defaultValue?: StructuredContentDoc;
33
+ }
28
34
  export interface NumberField extends BaseField {
29
35
  type: 'number';
30
36
  min?: number;
@@ -141,8 +147,16 @@ export interface ObjectFieldData {
141
147
  slug?: string;
142
148
  data: Record<string, unknown>;
143
149
  }
150
+ export type SimpleArrayItemType = 'text' | 'number' | 'url';
144
151
  export interface ArrayField extends BaseField {
145
152
  type: 'array';
153
+ of: SimpleArrayItemType;
154
+ minItems?: number;
155
+ maxItems?: number;
156
+ defaultValue?: (string | number | UrlFieldData)[];
157
+ }
158
+ export interface BlocksField extends BaseField {
159
+ type: 'blocks';
146
160
  of: ObjectField[];
147
161
  minItems?: number;
148
162
  maxItems?: number;
@@ -152,10 +166,13 @@ export interface ArrayField extends BaseField {
152
166
  export interface SlugField extends BaseField {
153
167
  type: 'slug';
154
168
  pattern?: string;
169
+ sourceField?: string;
155
170
  defaultValue?: string;
156
171
  }
157
172
  export interface SeoField extends BaseField {
158
173
  type: 'seo';
174
+ slugSource?: string;
175
+ titleSource?: string;
159
176
  }
160
177
  export interface SeoFieldData {
161
178
  slug: string;
@@ -178,4 +195,4 @@ export type UrlFieldData = {
178
195
  text?: Record<string, string>;
179
196
  newTab?: boolean;
180
197
  };
181
- export type Field = TextField | RichtextField | NumberField | BooleanField | DateField | DateTimeField | FileField | ImageField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | SlugField | SeoField | UrlField;
198
+ export type Field = TextField | RichtextField | ContentField | NumberField | BooleanField | DateField | DateTimeField | FileField | ImageField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | BlocksField | SlugField | SeoField | UrlField;
@@ -1,4 +1,5 @@
1
1
  export * from './fields.js';
2
+ export { type StructuredContentDoc, type SCNode, type SCMark, type SCInlineBlockAttrs, type SCFigureAttrs, type SCVideoAttrs } from './structured-content.js';
2
3
  export { type MediaFile, type MediaFileType, type ImageStyle, type MediaTag } from './media.js';
3
4
  export { type ConsentLogData } from './consent.js';
4
5
  export { type Entry, type EntryType, type EntryStatus, type EntryVersionStatus } from './entries.js';
@@ -8,3 +9,4 @@ export { type SingleConfig } from './singles.js';
8
9
  export { type FormConfig, type FormSubmission } from './forms.js';
9
10
  export { type CMSConfig } from './cms.js';
10
11
  export { type Language, type Localized } from './languages.js';
12
+ export { type Layout, type LayoutNode, type LayoutPreset, type LayoutNodeType, type ColumnRatio, type SectionNode, type ColumnsNode, type CardNode, type AccordionNode, type StackNode } from './layout.js';
@@ -1,4 +1,5 @@
1
1
  export * from './fields.js';
2
+ export {} from './structured-content.js';
2
3
  export {} from './media.js';
3
4
  export {} from './consent.js';
4
5
  export {} from './entries.js';
@@ -8,3 +9,4 @@ export {} from './singles.js';
8
9
  export {} from './forms.js';
9
10
  export {} from './cms.js';
10
11
  export {} from './languages.js';
12
+ export {} from './layout.js';