studiocms 0.3.0 → 0.4.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 (263) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/cli/add/index.d.ts +2 -2
  3. package/dist/cli/add/npm-utils.d.ts +6 -6
  4. package/dist/cli/add/tryToInstallPlugins.d.ts +1 -1
  5. package/dist/cli/add/updateStudioCMSConfig.d.ts +1 -1
  6. package/dist/cli/add/validatePlugins.d.ts +1 -1
  7. package/dist/cli/crypto/genJWT/index.d.ts +1 -1
  8. package/dist/cli/crypto/index.d.ts +1 -1
  9. package/dist/cli/init/steps/env.js +12 -2
  10. package/dist/cli/init/steps/next.d.ts +1 -1
  11. package/dist/cli/migrator/index.d.ts +1 -1
  12. package/dist/cli/users/index.d.ts +1 -1
  13. package/dist/cli/users/steps/createUsers.js +3 -3
  14. package/dist/cli/users/steps/next.d.ts +1 -1
  15. package/dist/cli/utils/context.d.ts +1 -1
  16. package/dist/cli/utils/getCliDbClient.d.ts +1 -1
  17. package/dist/cli/utils/intro.d.ts +1 -1
  18. package/dist/cli/utils/loadConfig.d.ts +54 -49
  19. package/dist/cli/utils/loadConfig.js +5 -8
  20. package/dist/cli/utils/user-utils.d.ts +1 -1
  21. package/dist/client/apiClient.d.ts +4923 -0
  22. package/dist/client/apiClient.js +72 -0
  23. package/dist/config.d.ts +1734 -1
  24. package/dist/consts.d.ts +5 -5
  25. package/dist/consts.js +3 -2
  26. package/dist/db/plugins.d.ts +1 -1
  27. package/dist/db/plugins.js +5 -8
  28. package/dist/handlers/frontend/routes.d.ts +4 -18
  29. package/dist/handlers/frontend/routes.js +13 -152
  30. package/dist/handlers/frontend/types.d.ts +1 -1
  31. package/dist/handlers/frontend/utils.js +0 -18
  32. package/dist/handlers/pluginHandler.d.ts +34 -257
  33. package/dist/handlers/pluginHandler.js +92 -46
  34. package/dist/handlers/routeHandler.js +32 -11
  35. package/dist/handlers/setupDbStudio.d.ts +1 -1
  36. package/dist/handlers/storage-manager/core/effectify-astro-context.d.ts +25 -0
  37. package/dist/handlers/storage-manager/core/effectify-astro-context.js +78 -0
  38. package/dist/handlers/storage-manager/no-op.d.ts +2 -2
  39. package/dist/handlers/storage-manager/no-op.js +2 -3
  40. package/dist/index.d.ts +0 -1
  41. package/dist/index.js +9 -5
  42. package/dist/integrations/robots/index.d.ts +2 -2
  43. package/dist/integrations/robots/index.js +1 -3
  44. package/dist/integrations/robots/schema.d.ts +102 -273
  45. package/dist/integrations/robots/schema.js +220 -209
  46. package/dist/plugins/analytics/assets/schemas.d.ts +14 -9
  47. package/dist/plugins/analytics/assets/schemas.js +25 -17
  48. package/dist/plugins/analytics/db-client.d.ts +1 -1
  49. package/dist/plugins/analytics/index.d.ts +823 -3
  50. package/dist/plugins/analytics/index.js +4 -5
  51. package/dist/plugins/analytics/schemas.d.ts +54 -62
  52. package/dist/plugins/analytics/schemas.js +64 -13
  53. package/dist/plugins/analytics/table.d.ts +1 -1
  54. package/dist/plugins.d.ts +0 -1
  55. package/dist/schemas/config/api.d.ts +17 -0
  56. package/dist/schemas/config/api.js +14 -0
  57. package/dist/schemas/config/auth.d.ts +55 -59
  58. package/dist/schemas/config/auth.js +34 -11
  59. package/dist/schemas/config/dashboard.d.ts +43 -79
  60. package/dist/schemas/config/dashboard.js +43 -12
  61. package/dist/schemas/config/db.d.ts +15 -17
  62. package/dist/schemas/config/db.js +13 -5
  63. package/dist/schemas/config/developer.d.ts +33 -45
  64. package/dist/schemas/config/developer.js +22 -5
  65. package/dist/schemas/config/index.d.ts +398 -521
  66. package/dist/schemas/config/index.js +115 -57
  67. package/dist/schemas/config/sdk.d.ts +50 -196
  68. package/dist/schemas/config/sdk.js +61 -73
  69. package/dist/schemas/custom.d.ts +40 -0
  70. package/dist/schemas/custom.js +41 -0
  71. package/dist/schemas/external-schemas.d.ts +171 -0
  72. package/dist/schemas/external-schemas.js +179 -0
  73. package/dist/schemas/index.d.ts +2 -0
  74. package/dist/schemas/index.js +2 -0
  75. package/dist/schemas/plugins/i18n.d.ts +59 -39
  76. package/dist/schemas/plugins/i18n.js +42 -5
  77. package/dist/schemas/plugins/index.d.ts +7126 -10296
  78. package/dist/schemas/plugins/index.js +260 -276
  79. package/dist/schemas/plugins/shared.d.ts +1293 -3718
  80. package/dist/schemas/plugins/shared.js +320 -329
  81. package/dist/test-utils.d.ts +15 -4
  82. package/dist/test-utils.js +27 -11
  83. package/dist/toolbar/db-viewer/db-shared-types.d.ts +6 -6
  84. package/dist/toolbar/db-viewer/viewer.js +20 -21
  85. package/dist/types.d.ts +30 -0
  86. package/dist/utils/effects/smtp.d.ts +1 -1
  87. package/dist/utils/lang-helper.d.ts +10 -2
  88. package/dist/virtual.d.ts +23 -0
  89. package/dist/virtuals/auth/core.d.ts +5 -5
  90. package/dist/virtuals/auth/verify-email.d.ts +6 -6
  91. package/dist/virtuals/components/Generator.astro +2 -2
  92. package/dist/virtuals/components/Renderer.astro +9 -1
  93. package/dist/virtuals/components/renderFn.d.ts +3 -1
  94. package/dist/virtuals/components/renderFn.js +18 -0
  95. package/dist/virtuals/lib/headDefaults.d.ts +4 -2
  96. package/dist/virtuals/lib/headDefaults.js +0 -2
  97. package/dist/virtuals/lib/routeMap.d.ts +0 -12
  98. package/dist/virtuals/lib/routeMap.js +2 -14
  99. package/dist/virtuals/mailer/index.d.ts +3 -3
  100. package/dist/virtuals/notifier/index.d.ts +5 -5
  101. package/dist/virtuals/plugins/dashboard-pages.d.ts +2 -64
  102. package/dist/virtuals/scripts/StorageFileBrowser.d.ts +1 -172
  103. package/dist/virtuals/scripts/StorageFileBrowser.js +216 -119
  104. package/dist/virtuals/template-engine/index.d.ts +4 -4
  105. package/frontend/components/dashboard/configuration/ConfigForm.astro +218 -110
  106. package/frontend/components/dashboard/content-mgmt/ContentSearch.astro +21 -22
  107. package/frontend/components/dashboard/content-mgmt/CreateFolder.astro +66 -54
  108. package/frontend/components/dashboard/content-mgmt/CreatePage.astro +58 -104
  109. package/frontend/components/dashboard/content-mgmt/EditFolder.astro +65 -67
  110. package/frontend/components/dashboard/content-mgmt/EditPage.astro +86 -134
  111. package/frontend/components/dashboard/content-mgmt/InnerSidebarElement.astro +0 -1
  112. package/frontend/components/dashboard/content-mgmt/PageHeader.astro +33 -52
  113. package/frontend/components/dashboard/content-mgmt/PageTypeHandler.astro +2 -2
  114. package/frontend/components/dashboard/profile/APITokens.astro +219 -158
  115. package/frontend/components/dashboard/profile/BasicInfo.astro +165 -106
  116. package/frontend/components/dashboard/profile/Notifications.astro +27 -18
  117. package/frontend/components/dashboard/profile/UpdatePassword.astro +134 -94
  118. package/frontend/components/dashboard/sidebar/VersionCheck.astro +31 -16
  119. package/frontend/components/dashboard/sidebar/VersionCheckChangelog.astro +18 -11
  120. package/frontend/components/dashboard/sidebar-modals/VersionModal.astro +2 -2
  121. package/frontend/components/dashboard/smtp-config/TemplateEditor.astro +14 -14
  122. package/frontend/components/dashboard/taxonomy/InnerSidebarElement.astro +0 -1
  123. package/frontend/components/dashboard/taxonomy/MetaContainer.astro +0 -2
  124. package/frontend/components/dashboard/taxonomy/PageHeader.astro +16 -24
  125. package/frontend/components/dashboard/taxonomy/TaxonomySearch.astro +23 -27
  126. package/frontend/components/dashboard/user-mgmt/InnerSidebarElement.astro +111 -104
  127. package/frontend/components/dashboard/user-mgmt/UserListItem.astro +9 -22
  128. package/frontend/components/dashboard/user-mgmt/UserListItems.astro +18 -0
  129. package/frontend/components/first-time-setup/snippets/{opt2-studiocms.config.diff → studiocms.config.diff} +1 -0
  130. package/frontend/components/shared/Code.astro +1 -4
  131. package/frontend/components/shared/DynamicSettingsRenderer.astro +1 -1
  132. package/frontend/components/shared/SSRUser.astro +2 -4
  133. package/frontend/components/shared/foldertree/FolderTreeNode.astro +0 -6
  134. package/frontend/components/shared/storage-manager/StorageCopyOutput.astro +0 -1
  135. package/frontend/components/shared/taxonomy/TaxonomyTreeNode.astro +0 -6
  136. package/frontend/layouts/DashboardLayout.astro +0 -9
  137. package/frontend/layouts/TaxonomyLayout.astro +0 -1
  138. package/frontend/middleware/index.ts +102 -61
  139. package/frontend/pages/404.astro +0 -1
  140. package/frontend/pages/[dashboard]/[...pluginPage].astro +10 -1
  141. package/frontend/pages/[dashboard]/configuration.astro +10 -1
  142. package/frontend/pages/[dashboard]/content-management/createfolder.astro +10 -1
  143. package/frontend/pages/[dashboard]/content-management/createpage.astro +10 -1
  144. package/frontend/pages/[dashboard]/content-management/diff.astro +39 -14
  145. package/frontend/pages/[dashboard]/content-management/editfolder.astro +10 -1
  146. package/frontend/pages/[dashboard]/content-management/editpage.astro +10 -1
  147. package/frontend/pages/[dashboard]/content-management/index.astro +10 -1
  148. package/frontend/pages/[dashboard]/index.astro +10 -1
  149. package/frontend/pages/[dashboard]/login.astro +86 -25
  150. package/frontend/pages/[dashboard]/password-reset.astro +22 -16
  151. package/frontend/pages/[dashboard]/plugins/[plugin].astro +10 -1
  152. package/frontend/pages/[dashboard]/profile.astro +10 -1
  153. package/frontend/pages/[dashboard]/signup.astro +153 -52
  154. package/frontend/pages/[dashboard]/smtp-configuration.astro +77 -75
  155. package/frontend/pages/[dashboard]/system-management.astro +10 -1
  156. package/frontend/pages/[dashboard]/taxonomy/categories.astro +30 -41
  157. package/frontend/pages/[dashboard]/taxonomy/index.astro +10 -0
  158. package/frontend/pages/[dashboard]/taxonomy/tags.astro +33 -43
  159. package/frontend/pages/[dashboard]/unverified-email.astro +29 -21
  160. package/frontend/pages/[dashboard]/user-management/edit.astro +170 -90
  161. package/frontend/pages/[dashboard]/user-management/index.astro +10 -1
  162. package/frontend/pages/studiocms_api/[...all].ts +106 -0
  163. package/frontend/pages/studiocms_api/_handlers/_utils/auth.ts +26 -0
  164. package/frontend/pages/studiocms_api/_handlers/_utils/changelog.ts +147 -0
  165. package/frontend/pages/studiocms_api/_handlers/_utils/db-studio-driver.ts +46 -0
  166. package/frontend/pages/studiocms_api/_handlers/_utils/parseLogLevel.ts +27 -0
  167. package/frontend/pages/studiocms_api/_handlers/auth/auth.ts +459 -0
  168. package/frontend/pages/studiocms_api/_handlers/auth/index.ts +17 -0
  169. package/frontend/pages/studiocms_api/_handlers/auth/oauth.ts +91 -0
  170. package/frontend/pages/studiocms_api/_handlers/dashboard/_shared.ts +57 -0
  171. package/frontend/pages/studiocms_api/_handlers/dashboard/apiTokens.ts +134 -0
  172. package/frontend/pages/studiocms_api/_handlers/dashboard/config.ts +64 -0
  173. package/frontend/pages/studiocms_api/_handlers/dashboard/content.ts +741 -0
  174. package/frontend/pages/studiocms_api/_handlers/dashboard/create.ts +480 -0
  175. package/frontend/pages/studiocms_api/_handlers/dashboard/emailNotifications.ts +49 -0
  176. package/frontend/pages/studiocms_api/_handlers/dashboard/index.ts +45 -0
  177. package/frontend/pages/studiocms_api/_handlers/dashboard/mailer.ts +136 -0
  178. package/frontend/pages/studiocms_api/_handlers/dashboard/plugins.ts +80 -0
  179. package/frontend/pages/studiocms_api/_handlers/dashboard/profile.ts +275 -0
  180. package/frontend/pages/studiocms_api/_handlers/dashboard/resetPassword.ts +140 -0
  181. package/frontend/pages/studiocms_api/_handlers/dashboard/search.ts +63 -0
  182. package/frontend/pages/studiocms_api/_handlers/dashboard/taxonomy.ts +285 -0
  183. package/frontend/pages/studiocms_api/_handlers/dashboard/templates.ts +75 -0
  184. package/frontend/pages/studiocms_api/_handlers/dashboard/users.ts +312 -0
  185. package/frontend/pages/studiocms_api/_handlers/dashboard/verifyEndpoints.ts +307 -0
  186. package/frontend/pages/studiocms_api/_handlers/integration/dbStudio.ts +98 -0
  187. package/frontend/pages/studiocms_api/_handlers/integration/index.ts +17 -0
  188. package/frontend/pages/studiocms_api/_handlers/integration/storageManager.ts +107 -0
  189. package/frontend/pages/studiocms_api/_handlers/rest-api/index.ts +8 -0
  190. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/_shared.ts +41 -0
  191. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/index.ts +17 -0
  192. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/public.ts +195 -0
  193. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts +1726 -0
  194. package/frontend/pages/studiocms_api/_handlers/sdk.ts +129 -0
  195. package/frontend/pages/studiocms_api/_middleware/astroLocals.ts +36 -0
  196. package/frontend/pages/studiocms_api/_middleware/restApi.ts +56 -0
  197. package/frontend/pages/studiocms_api/integrations/[...all].ts +8 -0
  198. package/frontend/scripts/formdata.ts +219 -0
  199. package/frontend/setup-pages/3-done.astro +4 -20
  200. package/frontend/setup-pages/studiocms_api/dashboard/step-2.ts +3 -6
  201. package/frontend/styles/dashboard-base.css +0 -1
  202. package/frontend/web-vitals/endpoint.ts +2 -1
  203. package/package.json +34 -29
  204. package/dist/global.d.ts +0 -9
  205. package/frontend/components/dashboard/LoginChecker.astro +0 -68
  206. package/frontend/components/dashboard/user-mgmt/RankCheck.astro +0 -57
  207. package/frontend/components/first-time-setup/snippets/opt1-astro.config.diff +0 -14
  208. package/frontend/components/first-time-setup/snippets/opt2-astro.config.diff +0 -9
  209. package/frontend/middleware/_authmap.ts +0 -63
  210. package/frontend/pages/studiocms_api/auth/[path].ts +0 -384
  211. package/frontend/pages/studiocms_api/auth/[provider]/[...id].ts +0 -64
  212. package/frontend/pages/studiocms_api/auth/[provider]/_effects/index.ts +0 -101
  213. package/frontend/pages/studiocms_api/auth/_shared.ts +0 -52
  214. package/frontend/pages/studiocms_api/dashboard/api-tokens.ts +0 -115
  215. package/frontend/pages/studiocms_api/dashboard/config.ts +0 -74
  216. package/frontend/pages/studiocms_api/dashboard/content/diff.ts +0 -73
  217. package/frontend/pages/studiocms_api/dashboard/content/folder.ts +0 -220
  218. package/frontend/pages/studiocms_api/dashboard/content/page.ts +0 -359
  219. package/frontend/pages/studiocms_api/dashboard/create-reset-link.ts +0 -77
  220. package/frontend/pages/studiocms_api/dashboard/create-user-invite.ts +0 -231
  221. package/frontend/pages/studiocms_api/dashboard/create-user.ts +0 -186
  222. package/frontend/pages/studiocms_api/dashboard/email-notification-settings-site.ts +0 -74
  223. package/frontend/pages/studiocms_api/dashboard/mailer/check-email.ts +0 -75
  224. package/frontend/pages/studiocms_api/dashboard/mailer/config.ts +0 -136
  225. package/frontend/pages/studiocms_api/dashboard/plugins/[plugin].ts +0 -80
  226. package/frontend/pages/studiocms_api/dashboard/profile.ts +0 -245
  227. package/frontend/pages/studiocms_api/dashboard/resend-verify-email.ts +0 -77
  228. package/frontend/pages/studiocms_api/dashboard/reset-password.ts +0 -124
  229. package/frontend/pages/studiocms_api/dashboard/search-list.ts +0 -59
  230. package/frontend/pages/studiocms_api/dashboard/taxonomy-search.ts +0 -47
  231. package/frontend/pages/studiocms_api/dashboard/taxonomy.ts +0 -230
  232. package/frontend/pages/studiocms_api/dashboard/templates.ts +0 -74
  233. package/frontend/pages/studiocms_api/dashboard/update-user-notifications.ts +0 -86
  234. package/frontend/pages/studiocms_api/dashboard/users.ts +0 -236
  235. package/frontend/pages/studiocms_api/dashboard/verify-email.ts +0 -83
  236. package/frontend/pages/studiocms_api/dashboard/verify-session.ts +0 -187
  237. package/frontend/pages/studiocms_api/integrations/[type]/[...id].ts +0 -15
  238. package/frontend/pages/studiocms_api/integrations/[type]/_routes/db-studio.ts +0 -173
  239. package/frontend/pages/studiocms_api/integrations/[type]/_routes/storage.ts +0 -88
  240. package/frontend/pages/studiocms_api/partials/editor.astro +0 -74
  241. package/frontend/pages/studiocms_api/partials/render.astro +0 -39
  242. package/frontend/pages/studiocms_api/partials/user-list-items.astro +0 -43
  243. package/frontend/pages/studiocms_api/rest/utils/auth-token.ts +0 -59
  244. package/frontend/pages/studiocms_api/rest/v1/[type]/[...id].ts +0 -23
  245. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/categories.ts +0 -267
  246. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/folders.ts +0 -283
  247. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/pages.ts +0 -505
  248. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/settings.ts +0 -100
  249. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/tags.ts +0 -229
  250. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/users.ts +0 -553
  251. package/frontend/pages/studiocms_api/rest/v1/public/[type]/[...id].ts +0 -19
  252. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/categories.ts +0 -74
  253. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/folders.ts +0 -85
  254. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/pages.ts +0 -103
  255. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/tags.ts +0 -67
  256. package/frontend/pages/studiocms_api/sdk/[...path].ts +0 -97
  257. package/frontend/pages/studiocms_api/sdk/utils/changelog.ts +0 -119
  258. package/frontend/scripts/auth/formListener.ts +0 -81
  259. package/frontend/scripts/formdata-utils.ts +0 -116
  260. package/frontend/utils/build-partial-schema.ts +0 -46
  261. package/frontend/utils/errors.ts +0 -6
  262. package/frontend/utils/param-extractor.ts +0 -83
  263. package/frontend/utils/rest-router.ts +0 -444
@@ -19,7 +19,10 @@ const { config } = Astro.props as Props;
19
19
 
20
20
  const { data } = config;
21
21
 
22
- const ogSelectOptions = validImages.map(({ label, name: value }) => ({ label, value }));
22
+ const ogSelectOptions = validImages.map(({ label, name: value }) => ({
23
+ label,
24
+ value,
25
+ }));
23
26
 
24
27
  const currentLoginPageBg = validImages.find(
25
28
  ({ name }) => name === data.loginPageBackground && name !== 'custom'
@@ -61,39 +64,90 @@ const lang = Astro.locals.StudioCMS.defaultLang;
61
64
  const t = useTranslations(lang, '@studiocms/dashboard:configuration');
62
65
  ---
63
66
 
64
- <form id="site-config-form" action={Astro.locals.StudioCMS.routeMap.endpointLinks.config}>
67
+ <form id="site-config-form">
65
68
  <div class="form-content">
66
-
67
69
  <div class="form-row">
68
- <Input label={t('input-site-title')} name='site-title' placeholder='My Awesome Website' value={data.title} isRequired />
69
- <Input label={t('input-site-description')} name='site-description' placeholder='Built with StudioCMS!' value={data.description} isRequired />
70
+ <Input
71
+ label={t("input-site-title")}
72
+ name="site-title"
73
+ placeholder="My Awesome Website"
74
+ value={data.title}
75
+ isRequired
76
+ />
77
+ <Input
78
+ label={t("input-site-description")}
79
+ name="site-description"
80
+ placeholder="Built with StudioCMS!"
81
+ value={data.description}
82
+ isRequired
83
+ />
70
84
  </div>
71
85
 
72
86
  <div class="form-row">
73
- <StorageInput label={t('input-og-image')} name="default-og-image" placeholder="'https://...' for local, or '/...' for public/ folder" value={data.defaultOgImage} />
74
- <StorageInput label="Site Icon (Public facing Favicon)" name="site-icon" placeholder="'https://...' for local, or '/...' for public/ folder" value={data.siteIcon} />
87
+ <StorageInput
88
+ label={t("input-og-image")}
89
+ name="default-og-image"
90
+ placeholder="'https://...' for local, or '/...' for public/ folder"
91
+ value={data.defaultOgImage}
92
+ />
93
+ <StorageInput
94
+ label="Site Icon (Public facing Favicon)"
95
+ name="site-icon"
96
+ placeholder="'https://...' for local, or '/...' for public/ folder"
97
+ value={data.siteIcon}
98
+ />
75
99
  </div>
76
100
 
77
101
  <div class="form-row">
78
- <Select label={t('select-page-diff-tracking')} name="diff-enabled" defaultValue={`${data.enableDiffs}`} options={[{ label: 'True', value: 'true' }, { label: 'False', value: 'false' }]} fullWidth />
79
- <Input label={t('input-diff-tracking-limit')} name="diff-per-page" placeholder="10" value={data.diffPerPage} />
102
+ <Select
103
+ label={t("select-page-diff-tracking")}
104
+ name="diff-enabled"
105
+ defaultValue={`${data.enableDiffs}`}
106
+ options={[
107
+ { label: "True", value: "true" },
108
+ { label: "False", value: "false" },
109
+ ]}
110
+ fullWidth
111
+ />
112
+ <Input
113
+ label={t("input-diff-tracking-limit")}
114
+ name="diff-per-page"
115
+ placeholder="10"
116
+ value={data.diffPerPage}
117
+ />
80
118
  </div>
81
119
 
82
120
  <div class="form-row">
83
- <Select label={t('select-smtp-mailer')} name="enable-mailer" defaultValue={`${data.enableMailer}`} options={[{ label: 'True', value: 'true' }, { label: 'False', value: 'false' }]} fullWidth />
121
+ <Select
122
+ label={t("select-smtp-mailer")}
123
+ name="enable-mailer"
124
+ defaultValue={`${data.enableMailer}`}
125
+ options={[
126
+ { label: "True", value: "true" },
127
+ { label: "False", value: "false" },
128
+ ]}
129
+ fullWidth
130
+ />
84
131
  </div>
85
132
 
86
133
  <Divider />
87
134
 
88
135
  <span>
89
- <t-config-form key="dashboard-grid-label">{t('dashboard-grid-label')}</t-config-form>
136
+ <t-config-form key="dashboard-grid-label"
137
+ >{t("dashboard-grid-label")}</t-config-form
138
+ >
90
139
  </span>
91
140
 
92
141
  <div class="grid-items-container">
93
142
  {
94
143
  gridItemOptions.map(({ enabled, label, name }) => (
95
144
  <Card style="background-color: var(--background-step-2);">
96
- <Toggle {label} {name} color='primary' defaultChecked={enabled} />
145
+ <Toggle
146
+ {label}
147
+ {name}
148
+ color="primary"
149
+ defaultChecked={enabled}
150
+ />
97
151
  </Card>
98
152
  ))
99
153
  }
@@ -102,16 +156,35 @@ const t = useTranslations(lang, '@studiocms/dashboard:configuration');
102
156
  <Divider />
103
157
 
104
158
  <div class="form-row">
105
- <Select label={t('select-login-page-bg')} name='login-page-background' defaultValue={data.loginPageBackground} options={ogSelectOptions} fullWidth />
106
- <StorageInput label={t('input-custom-login-page')} name="login-page-background-custom" placeholder="'https://...' for local, or '/...' for public/ folder" value={data.loginPageCustomImage} disabled={data.loginPageBackground !== 'custom'} />
159
+ <Select
160
+ label={t("select-login-page-bg")}
161
+ name="login-page-background"
162
+ defaultValue={data.loginPageBackground}
163
+ options={ogSelectOptions}
164
+ fullWidth
165
+ />
166
+ <StorageInput
167
+ label={t("input-custom-login-page")}
168
+ name="login-page-background-custom"
169
+ placeholder="'https://...' for local, or '/...' for public/ folder"
170
+ value={data.loginPageCustomImage}
171
+ disabled={data.loginPageBackground !== "custom"}
172
+ />
107
173
  </div>
108
174
 
109
- <LoginPreview light={currentLoginPageBg?.light} dark={currentLoginPageBg?.dark} />
110
-
175
+ <LoginPreview
176
+ light={currentLoginPageBg?.light}
177
+ dark={currentLoginPageBg?.dark}
178
+ />
111
179
  </div>
112
180
  </form>
113
181
 
114
- <div id="grid-items-data-list" data-items={JSON.stringify(gridItemOptions.map(({ name }) => name))} style="display: none;"></div>
182
+ <div
183
+ id="grid-items-data-list"
184
+ data-items={JSON.stringify(gridItemOptions.map(({ name }) => name))}
185
+ style="display: none;"
186
+ >
187
+ </div>
115
188
 
116
189
  <script>
117
190
  import {
@@ -122,44 +195,49 @@ const t = useTranslations(lang, '@studiocms/dashboard:configuration');
122
195
  makeTranslation,
123
196
  updateElmLabel,
124
197
  updateSelectElmLabel,
125
- updateTrueFalseSelectOptions,
126
- } from 'studiocms:i18n/client';
127
- import { $pluginI18n } from 'studiocms:i18n/plugins';
198
+ updateTrueFalseSelectOptions,
199
+ } from "studiocms:i18n/client";
200
+ import { $pluginI18n } from "studiocms:i18n/plugins";
128
201
 
129
- const gridItemsDataElm = document.getElementById('grid-items-data-list') as HTMLDivElement;
202
+ const gridItemsDataElm = document.getElementById(
203
+ "grid-items-data-list",
204
+ ) as HTMLDivElement;
130
205
  const gridItemsData = gridItemsDataElm.dataset.items as string;
131
206
 
132
207
  const gridItems: `${string}/${string}`[] = JSON.parse(gridItemsData);
133
208
 
134
209
  const gridItemsList = gridItems.map((item) => {
135
- const [id, component] = item.split('/');
136
- return {
137
- id,
138
- // component name should replace underscores with hyphens
139
- component: component.replace(/_/g, '-'),
140
- selector: `label-${item}`
141
- };
210
+ const [id, component] = item.split("/");
211
+ return {
212
+ id,
213
+ // component name should replace underscores with hyphens
214
+ component: component.replace(/_/g, "-"),
215
+ selector: `label-${item}`,
216
+ };
142
217
  });
143
218
 
144
- const currentPage = '@studiocms/dashboard:configuration';
219
+ const currentPage = "@studiocms/dashboard:configuration";
145
220
 
146
221
  let lang = defaultLang;
147
222
 
148
223
  const i18n = $i18n(currentPage, baseTranslation[currentPage]);
149
224
 
150
- const pluginI18n = (pluginId: string, component: string) => $pluginI18n(pluginId, component);
225
+ const pluginI18n = (pluginId: string, component: string) =>
226
+ $pluginI18n(pluginId, component);
151
227
 
152
- function registerGridItemSubscriptions(subscriptions: { id: string, component: string, selector: string }[]) {
153
- for (const subscription of subscriptions) {
154
- const sub = pluginI18n(subscription.id, subscription.component);
228
+ function registerGridItemSubscriptions(
229
+ subscriptions: { id: string; component: string; selector: string }[],
230
+ ) {
231
+ for (const subscription of subscriptions) {
232
+ const sub = pluginI18n(subscription.id, subscription.component);
155
233
 
156
- sub.subscribe(comp => {
157
- const elm = document.getElementById(subscription.selector);
158
- if (elm) {
159
- elm.textContent = comp['title'];
160
- }
161
- })
162
- }
234
+ sub.subscribe((comp) => {
235
+ const elm = document.getElementById(subscription.selector);
236
+ if (elm) {
237
+ elm.textContent = comp["title"];
238
+ }
239
+ });
240
+ }
163
241
  }
164
242
 
165
243
  registerGridItemSubscriptions(gridItemsList);
@@ -168,83 +246,113 @@ updateTrueFalseSelectOptions,
168
246
  lang = locale || defaultLang;
169
247
  });
170
248
 
171
- i18n.subscribe(comp => {
172
- updateElmLabel('site-title', comp['input-site-title']);
173
- updateElmLabel('site-description', comp['input-site-description']);
174
- updateElmLabel('default-og-image', comp['input-og-image']);
175
- updateElmLabel('site-icon', comp['input-site-icon']);
176
- updateElmLabel('diff-per-page', comp['input-diff-tracking-limit']);
177
- updateElmLabel('login-page-background-custom', comp['input-custom-login-page']);
178
- updateSelectElmLabel('login-page-background', comp['select-login-page-bg']);
179
- updateSelectElmLabel('diff-enabled', comp['select-page-diff-tracking']);
180
- updateSelectElmLabel('enable-mailer', comp['select-smtp-mailer']);
181
-
182
- const trueFalseOptions = { true: comp['true-label'], false: comp['false-label'] };
183
-
184
- updateTrueFalseSelectOptions('diff-enabled', trueFalseOptions);
185
- updateTrueFalseSelectOptions('enable-mailer', trueFalseOptions);
249
+ i18n.subscribe((comp) => {
250
+ updateElmLabel("site-title", comp["input-site-title"]);
251
+ updateElmLabel("site-description", comp["input-site-description"]);
252
+ updateElmLabel("default-og-image", comp["input-og-image"]);
253
+ updateElmLabel("site-icon", comp["input-site-icon"]);
254
+ updateElmLabel("diff-per-page", comp["input-diff-tracking-limit"]);
255
+ updateElmLabel(
256
+ "login-page-background-custom",
257
+ comp["input-custom-login-page"],
258
+ );
259
+ updateSelectElmLabel(
260
+ "login-page-background",
261
+ comp["select-login-page-bg"],
262
+ );
263
+ updateSelectElmLabel("diff-enabled", comp["select-page-diff-tracking"]);
264
+ updateSelectElmLabel("enable-mailer", comp["select-smtp-mailer"]);
265
+
266
+ const trueFalseOptions = {
267
+ true: comp["true-label"],
268
+ false: comp["false-label"],
269
+ };
270
+
271
+ updateTrueFalseSelectOptions("diff-enabled", trueFalseOptions);
272
+ updateTrueFalseSelectOptions("enable-mailer", trueFalseOptions);
186
273
  });
187
274
 
188
- if (!customElements.get('t-config-form')) {
189
- customElements.define('t-config-form', makeTranslation(currentPage, i18n));
275
+ if (!customElements.get("t-config-form")) {
276
+ customElements.define(
277
+ "t-config-form",
278
+ makeTranslation(currentPage, i18n),
279
+ );
190
280
  }
191
281
  </script>
192
282
 
193
283
  <script>
194
284
  import { toast } from "studiocms:ui/components/toaster/client";
195
- const configForm = document.querySelector('#site-config-form') as HTMLFormElement;
196
-
197
- configForm.addEventListener('submit', async (e) => {
198
- e.preventDefault();
199
- try {
200
- const formData = new FormData(configForm);
201
- // Scope to grid container to avoid unrelated checkboxes
202
- const gridItems = Array.from(document.querySelectorAll('.grid-items-container input[type="checkbox"]') as NodeListOf<HTMLInputElement>).map((input) => ({
203
- name: input.name,
204
- enabled: input.checked,
205
- }));
206
- const enabledGridItems = gridItems.filter((item) => item.enabled).map((item) => item.name);
207
- const diffPerPageRaw = formData.get('diff-per-page') as string;
208
- const diffPerPageParsed = Number.parseInt(diffPerPageRaw, 10);
209
- const data = {
210
- title: formData.get('site-title') as string,
211
- description: formData.get('site-description') as string,
212
- defaultOgImage: formData.get('default-og-image') ?? null,
213
- siteIcon: formData.get('site-icon') ?? null,
214
- loginPageBackground: formData.get('login-page-background') as string,
215
- loginPageCustomImage: formData.get('login-page-background-custom') ?? null,
216
- enableDiffs: formData.get('diff-enabled') === 'true',
217
- diffPerPage: Number.isNaN(diffPerPageParsed) ? 10 : diffPerPageParsed,
218
- gridItems: enabledGridItems,
219
- enableMailer: formData.get('enable-mailer') === 'true',
220
- };
221
- const response = await fetch(configForm.action, {
222
- method: 'POST',
223
- body: JSON.stringify(data),
224
- headers: { 'Content-Type': 'application/json' },
225
- });
226
- const res: any = await response.json().catch(() => ({}));
227
- if (!response.ok) {
228
- toast({
229
- title: 'Error',
230
- description: res?.error || res?.message || 'Request failed',
231
- type: 'danger'
232
- });
233
- return;
234
- }
235
- toast({
236
- title: 'Success',
237
- description: res?.message || 'Configuration saved',
238
- type: 'success'
239
- });
240
- } catch (err) {
241
- toast({
242
- title: 'Network error',
243
- description: (err as Error)?.message ?? 'Unexpected error',
244
- type: 'danger'
245
- });
246
- }
247
- });
285
+ import { dashboardClient, dashboardSharedCatchTags } from 'studiocms:client/apiClients';
286
+ import * as Effect from 'effect/Effect';
287
+
288
+ const configForm = document.querySelector(
289
+ "#site-config-form",
290
+ ) as HTMLFormElement;
291
+
292
+ configForm.addEventListener("submit", async (e) => {
293
+ e.preventDefault();
294
+
295
+ const formData = new FormData(configForm);
296
+
297
+ // Scope to grid container to avoid unrelated checkboxes
298
+ const gridItems = Array.from(
299
+ document.querySelectorAll(
300
+ '.grid-items-container input[type="checkbox"]',
301
+ ) as NodeListOf<HTMLInputElement>,
302
+ ).map((input) => ({
303
+ name: input.name,
304
+ enabled: input.checked,
305
+ }));
306
+
307
+ const enabledGridItems = gridItems
308
+ .filter((item) => item.enabled)
309
+ .map((item) => item.name);
310
+
311
+ const diffPerPageRaw = formData.get("diff-per-page") as string;
312
+ const diffPerPageParsed = Number.parseInt(diffPerPageRaw, 10);
313
+ const data = {
314
+ title: formData.get("site-title") as string,
315
+ description: formData.get("site-description") as string,
316
+ defaultOgImage: (formData.get("default-og-image") ?? null) as string | null,
317
+ siteIcon: (formData.get("site-icon") ?? null) as string | null,
318
+ loginPageBackground: formData.get(
319
+ "login-page-background",
320
+ ) as string,
321
+ loginPageCustomImage:
322
+ (formData.get("login-page-background-custom") ?? null) as string | null,
323
+ enableDiffs: formData.get("diff-enabled") === "true",
324
+ diffPerPage: Number.isNaN(diffPerPageParsed)
325
+ ? 10
326
+ : diffPerPageParsed,
327
+ gridItems: enabledGridItems,
328
+ enableMailer: formData.get("enable-mailer") === "true",
329
+ };
330
+
331
+ const response = await dashboardClient.pipe(
332
+ Effect.flatMap((client) =>
333
+ client.config.updateSiteConfig({
334
+ payload: data
335
+ })
336
+ ),
337
+ Effect.catchTags(dashboardSharedCatchTags),
338
+ Effect.runPromise
339
+ );
340
+
341
+ if ("error" in response) {
342
+ toast({
343
+ title: "Error",
344
+ description: response.error,
345
+ type: "danger",
346
+ });
347
+ return;
348
+ } else {
349
+ toast({
350
+ title: "Success",
351
+ description: response.message || "Configuration updated successfully",
352
+ type: "success",
353
+ });
354
+ }
355
+ });
248
356
  </script>
249
357
 
250
358
  <style>
@@ -34,6 +34,8 @@ const t = useTranslations(lang, '@studiocms/dashboard:content-sidebar');
34
34
  baseTranslation,
35
35
  updateElmPlaceholder,
36
36
  } from "studiocms:i18n/client";
37
+ import { dashboardClient } from "studiocms:client/apiClients";
38
+ import * as Effect from "effect/Effect";
37
39
 
38
40
  const currentPage = "@studiocms/dashboard:content-sidebar";
39
41
 
@@ -58,14 +60,14 @@ const t = useTranslations(lang, '@studiocms/dashboard:content-sidebar');
58
60
  ) as HTMLDivElement;
59
61
 
60
62
  type SearchItem = {
61
- id: string;
62
- name: string;
63
- slug?: string;
64
- type: "folder" | "page";
65
- isDraft?: boolean;
63
+ readonly id: string;
64
+ readonly name: string;
65
+ readonly slug?: string | undefined;
66
+ readonly type: "folder" | "page";
67
+ readonly isDraft?: boolean | null | undefined;
66
68
  };
67
69
 
68
- type SearchList = SearchItem[];
70
+ type SearchList = readonly SearchItem[];
69
71
 
70
72
  function getIcon(item: SearchItem) {
71
73
  if (item.type === "folder") {
@@ -95,21 +97,18 @@ const t = useTranslations(lang, '@studiocms/dashboard:content-sidebar');
95
97
  <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24" fill="currentColor" class="leaf-icon active"><path fill-rule="evenodd" d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z" clip-rule="evenodd" /><path d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z" /></svg>`;
96
98
  }
97
99
 
98
- async function getSearchList(searchItems: HTMLDivElement) {
99
- console.log(
100
- `Fetching search list from ${searchItems.dataset.searchlist}`,
100
+ async function getSearchList(): Promise<SearchList> {
101
+ return await Effect.runPromise(
102
+ Effect.orElse(
103
+ dashboardClient.pipe(
104
+ Effect.flatMap((client) => client.search.searchList({})),
105
+ Effect.tapError(Effect.logError)
106
+ ),
107
+ () => Effect.log("Failed to fetch search list, returning empty list").pipe(
108
+ Effect.as([] as SearchList)
109
+ ),
110
+ ),
101
111
  );
102
-
103
- const response = await fetch(searchItems.dataset.searchlist as string);
104
-
105
- if (!response.ok) {
106
- console.error("Failed to fetch search list");
107
- return [];
108
- }
109
-
110
- const data: SearchList = await response.json();
111
-
112
- return data;
113
112
  }
114
113
 
115
114
  function clearSearchParams(innerSidebarItemsSearch: HTMLDivElement) {
@@ -147,7 +146,7 @@ const t = useTranslations(lang, '@studiocms/dashboard:content-sidebar');
147
146
  <button class="context-menu-item" role="menuitem" data-action="edit">
148
147
  <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="leaf-icon default"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /></svg>
149
148
  <span>
150
- <t-file-tree-renderer key="${item.type === 'page' ? 'edit-page' : 'edit-folder'}">Edit ${item.type === 'page' ? 'Page' : 'Folder'}</t-file-tree-renderer>
149
+ <t-file-tree-renderer key="${item.type === "page" ? "edit-page" : "edit-folder"}">Edit ${item.type === "page" ? "Page" : "Folder"}</t-file-tree-renderer>
151
150
  </span>
152
151
  </button>
153
152
  </div>
@@ -173,7 +172,7 @@ const t = useTranslations(lang, '@studiocms/dashboard:content-sidebar');
173
172
  currentUrl.searchParams.set("search", searchTerm);
174
173
  window.history.pushState({}, "", currentUrl);
175
174
 
176
- const searchList = await getSearchList(searchItems);
175
+ const searchList = await getSearchList();
177
176
 
178
177
  const fuse = new Fuse(searchList, {
179
178
  keys: ["name", "slug"],