studiocms 0.2.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 (293) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/dist/cli/add/index.d.ts +2 -2
  3. package/dist/cli/add/index.js +4 -3
  4. package/dist/cli/add/npm-utils.d.ts +6 -6
  5. package/dist/cli/add/tryToInstallPlugins.d.ts +1 -1
  6. package/dist/cli/add/tryToInstallPlugins.js +6 -5
  7. package/dist/cli/add/updateStudioCMSConfig.d.ts +1 -1
  8. package/dist/cli/add/updateStudioCMSConfig.js +3 -4
  9. package/dist/cli/add/validatePlugins.d.ts +1 -2
  10. package/dist/cli/add/validatePlugins.js +15 -9
  11. package/dist/cli/crypto/genJWT/index.d.ts +1 -1
  12. package/dist/cli/crypto/genJWT/index.js +8 -9
  13. package/dist/cli/crypto/index.d.ts +1 -1
  14. package/dist/cli/init/steps/env.js +14 -4
  15. package/dist/cli/init/steps/next.d.ts +1 -1
  16. package/dist/cli/init/steps/next.js +6 -5
  17. package/dist/cli/migrator/index.d.ts +1 -1
  18. package/dist/cli/migrator/index.js +2 -2
  19. package/dist/cli/users/index.d.ts +1 -1
  20. package/dist/cli/users/shared.js +2 -2
  21. package/dist/cli/users/steps/createUsers.js +7 -7
  22. package/dist/cli/users/steps/modifyUsers.js +2 -2
  23. package/dist/cli/users/steps/next.d.ts +1 -1
  24. package/dist/cli/utils/checkRequiredEnvVars.js +2 -2
  25. package/dist/cli/utils/context.d.ts +2 -4
  26. package/dist/cli/utils/context.js +1 -3
  27. package/dist/cli/utils/getCliDbClient.d.ts +1 -1
  28. package/dist/cli/utils/intro.d.ts +1 -1
  29. package/dist/cli/utils/loadConfig.d.ts +54 -49
  30. package/dist/cli/utils/loadConfig.js +5 -8
  31. package/dist/cli/utils/logger.js +3 -3
  32. package/dist/cli/utils/user-utils.d.ts +1 -1
  33. package/dist/cli/utils/user-utils.js +4 -3
  34. package/dist/client/apiClient.d.ts +4923 -0
  35. package/dist/client/apiClient.js +72 -0
  36. package/dist/config.d.ts +1734 -1
  37. package/dist/consts.d.ts +5 -5
  38. package/dist/consts.js +3 -2
  39. package/dist/db/plugins.d.ts +1 -1
  40. package/dist/db/plugins.js +5 -8
  41. package/dist/handlers/frontend/routes.d.ts +4 -18
  42. package/dist/handlers/frontend/routes.js +13 -152
  43. package/dist/handlers/frontend/types.d.ts +1 -1
  44. package/dist/handlers/frontend/utils.js +0 -18
  45. package/dist/handlers/pluginHandler.d.ts +34 -257
  46. package/dist/handlers/pluginHandler.js +92 -46
  47. package/dist/handlers/routeHandler.js +32 -11
  48. package/dist/handlers/setupDbStudio.d.ts +3 -1
  49. package/dist/handlers/setupDbStudio.js +19 -10
  50. package/dist/handlers/storage-manager/core/effectify-astro-context.d.ts +25 -0
  51. package/dist/handlers/storage-manager/core/effectify-astro-context.js +78 -0
  52. package/dist/handlers/storage-manager/no-op.d.ts +2 -2
  53. package/dist/handlers/storage-manager/no-op.js +2 -3
  54. package/dist/index.d.ts +0 -1
  55. package/dist/index.js +10 -20
  56. package/dist/integrations/robots/index.d.ts +2 -2
  57. package/dist/integrations/robots/index.js +1 -3
  58. package/dist/integrations/robots/schema.d.ts +102 -273
  59. package/dist/integrations/robots/schema.js +220 -209
  60. package/dist/plugins/analytics/assets/schemas.d.ts +14 -9
  61. package/dist/plugins/analytics/assets/schemas.js +25 -17
  62. package/dist/plugins/analytics/db-client.d.ts +1 -1
  63. package/dist/plugins/analytics/index.d.ts +823 -3
  64. package/dist/plugins/analytics/index.js +4 -5
  65. package/dist/plugins/analytics/schemas.d.ts +54 -62
  66. package/dist/plugins/analytics/schemas.js +64 -13
  67. package/dist/plugins/analytics/table.d.ts +1 -1
  68. package/dist/plugins.d.ts +0 -1
  69. package/dist/schemas/config/api.d.ts +17 -0
  70. package/dist/schemas/config/api.js +14 -0
  71. package/dist/schemas/config/auth.d.ts +55 -59
  72. package/dist/schemas/config/auth.js +34 -11
  73. package/dist/schemas/config/dashboard.d.ts +43 -79
  74. package/dist/schemas/config/dashboard.js +43 -12
  75. package/dist/schemas/config/db.d.ts +15 -17
  76. package/dist/schemas/config/db.js +13 -5
  77. package/dist/schemas/config/developer.d.ts +33 -45
  78. package/dist/schemas/config/developer.js +22 -5
  79. package/dist/schemas/config/index.d.ts +398 -521
  80. package/dist/schemas/config/index.js +115 -57
  81. package/dist/schemas/config/sdk.d.ts +50 -196
  82. package/dist/schemas/config/sdk.js +61 -73
  83. package/dist/schemas/custom.d.ts +40 -0
  84. package/dist/schemas/custom.js +41 -0
  85. package/dist/schemas/external-schemas.d.ts +171 -0
  86. package/dist/schemas/external-schemas.js +179 -0
  87. package/dist/schemas/index.d.ts +2 -0
  88. package/dist/schemas/index.js +2 -0
  89. package/dist/schemas/plugins/i18n.d.ts +59 -39
  90. package/dist/schemas/plugins/i18n.js +42 -5
  91. package/dist/schemas/plugins/index.d.ts +7126 -10296
  92. package/dist/schemas/plugins/index.js +260 -276
  93. package/dist/schemas/plugins/shared.d.ts +1293 -3718
  94. package/dist/schemas/plugins/shared.js +320 -329
  95. package/dist/test-utils.d.ts +15 -4
  96. package/dist/test-utils.js +27 -11
  97. package/dist/toolbar/db-viewer/db-shared-types.d.ts +6 -6
  98. package/dist/toolbar/db-viewer/studio/connection.d.ts +8 -4
  99. package/dist/toolbar/db-viewer/studio/connection.js +2 -28
  100. package/dist/toolbar/db-viewer/studio/env/libsql.d.ts +7 -0
  101. package/dist/toolbar/db-viewer/studio/env/libsql.js +17 -0
  102. package/dist/toolbar/db-viewer/studio/env/mysql.d.ts +7 -0
  103. package/dist/toolbar/db-viewer/studio/env/mysql.js +23 -0
  104. package/dist/toolbar/db-viewer/studio/env/postgres.d.ts +7 -0
  105. package/dist/toolbar/db-viewer/studio/env/postgres.js +23 -0
  106. package/dist/toolbar/db-viewer/studio/index.js +20 -56
  107. package/dist/toolbar/db-viewer/studio/type.d.ts +1 -2
  108. package/dist/toolbar/db-viewer/studio/virtual-connection/libsql.d.ts +3 -0
  109. package/dist/toolbar/db-viewer/studio/virtual-connection/libsql.js +24 -0
  110. package/dist/toolbar/db-viewer/studio/virtual-connection/mysql.d.ts +3 -0
  111. package/dist/toolbar/db-viewer/studio/virtual-connection/mysql.js +9 -0
  112. package/dist/toolbar/db-viewer/studio/virtual-connection/postgres.d.ts +3 -0
  113. package/dist/toolbar/db-viewer/studio/virtual-connection/postgres.js +9 -0
  114. package/dist/toolbar/db-viewer/viewer.js +20 -21
  115. package/dist/types.d.ts +30 -0
  116. package/dist/utils/effects/smtp.d.ts +1 -1
  117. package/dist/utils/lang-helper.d.ts +10 -2
  118. package/dist/virtual.d.ts +35 -28
  119. package/dist/virtuals/auth/core.d.ts +5 -5
  120. package/dist/virtuals/auth/verify-email.d.ts +6 -6
  121. package/dist/virtuals/components/Generator.astro +2 -2
  122. package/dist/virtuals/components/Renderer.astro +9 -1
  123. package/dist/virtuals/components/renderFn.d.ts +3 -1
  124. package/dist/virtuals/components/renderFn.js +18 -0
  125. package/dist/virtuals/lib/headDefaults.d.ts +4 -2
  126. package/dist/virtuals/lib/headDefaults.js +0 -2
  127. package/dist/virtuals/lib/routeMap.d.ts +0 -12
  128. package/dist/virtuals/lib/routeMap.js +2 -14
  129. package/dist/virtuals/mailer/index.d.ts +3 -3
  130. package/dist/virtuals/notifier/index.d.ts +5 -5
  131. package/dist/virtuals/plugins/dashboard-pages.d.ts +2 -64
  132. package/dist/virtuals/scripts/StorageFileBrowser.d.ts +1 -172
  133. package/dist/virtuals/scripts/StorageFileBrowser.js +216 -119
  134. package/dist/virtuals/template-engine/index.d.ts +4 -4
  135. package/frontend/components/dashboard/configuration/ConfigForm.astro +218 -110
  136. package/frontend/components/dashboard/content-mgmt/ContentSearch.astro +21 -22
  137. package/frontend/components/dashboard/content-mgmt/CreateFolder.astro +66 -54
  138. package/frontend/components/dashboard/content-mgmt/CreatePage.astro +58 -104
  139. package/frontend/components/dashboard/content-mgmt/EditFolder.astro +65 -67
  140. package/frontend/components/dashboard/content-mgmt/EditPage.astro +86 -134
  141. package/frontend/components/dashboard/content-mgmt/InnerSidebarElement.astro +0 -1
  142. package/frontend/components/dashboard/content-mgmt/PageHeader.astro +33 -52
  143. package/frontend/components/dashboard/content-mgmt/PageTypeHandler.astro +2 -2
  144. package/frontend/components/dashboard/profile/APITokens.astro +219 -158
  145. package/frontend/components/dashboard/profile/BasicInfo.astro +165 -106
  146. package/frontend/components/dashboard/profile/Notifications.astro +27 -18
  147. package/frontend/components/dashboard/profile/UpdatePassword.astro +134 -94
  148. package/frontend/components/dashboard/sidebar/VersionCheck.astro +31 -16
  149. package/frontend/components/dashboard/sidebar/VersionCheckChangelog.astro +18 -11
  150. package/frontend/components/dashboard/sidebar-modals/VersionModal.astro +2 -2
  151. package/frontend/components/dashboard/smtp-config/TemplateEditor.astro +14 -14
  152. package/frontend/components/dashboard/taxonomy/InnerSidebarElement.astro +0 -1
  153. package/frontend/components/dashboard/taxonomy/MetaContainer.astro +0 -2
  154. package/frontend/components/dashboard/taxonomy/PageHeader.astro +16 -24
  155. package/frontend/components/dashboard/taxonomy/TaxonomySearch.astro +23 -27
  156. package/frontend/components/dashboard/user-mgmt/InnerSidebarElement.astro +111 -104
  157. package/frontend/components/dashboard/user-mgmt/UserListItem.astro +9 -22
  158. package/frontend/components/dashboard/user-mgmt/UserListItems.astro +18 -0
  159. package/frontend/components/first-time-setup/snippets/{opt2-studiocms.config.diff → studiocms.config.diff} +1 -0
  160. package/frontend/components/shared/Code.astro +1 -4
  161. package/frontend/components/shared/DynamicSettingsRenderer.astro +1 -1
  162. package/frontend/components/shared/SSRUser.astro +2 -4
  163. package/frontend/components/shared/foldertree/FolderTreeNode.astro +0 -6
  164. package/frontend/components/shared/storage-manager/StorageCopyOutput.astro +0 -1
  165. package/frontend/components/shared/taxonomy/TaxonomyTreeNode.astro +0 -6
  166. package/frontend/layouts/DashboardLayout.astro +1 -10
  167. package/frontend/layouts/TaxonomyLayout.astro +0 -1
  168. package/frontend/middleware/index.ts +102 -61
  169. package/frontend/pages/404.astro +5 -9
  170. package/frontend/pages/[dashboard]/[...pluginPage].astro +10 -1
  171. package/frontend/pages/[dashboard]/configuration.astro +10 -1
  172. package/frontend/pages/[dashboard]/content-management/createfolder.astro +10 -1
  173. package/frontend/pages/[dashboard]/content-management/createpage.astro +10 -1
  174. package/frontend/pages/[dashboard]/content-management/diff.astro +39 -14
  175. package/frontend/pages/[dashboard]/content-management/editfolder.astro +10 -1
  176. package/frontend/pages/[dashboard]/content-management/editpage.astro +10 -1
  177. package/frontend/pages/[dashboard]/content-management/index.astro +10 -1
  178. package/frontend/pages/[dashboard]/index.astro +10 -1
  179. package/frontend/pages/[dashboard]/login.astro +86 -25
  180. package/frontend/pages/[dashboard]/password-reset.astro +22 -16
  181. package/frontend/pages/[dashboard]/plugins/[plugin].astro +10 -1
  182. package/frontend/pages/[dashboard]/profile.astro +10 -1
  183. package/frontend/pages/[dashboard]/signup.astro +153 -52
  184. package/frontend/pages/[dashboard]/smtp-configuration.astro +77 -75
  185. package/frontend/pages/[dashboard]/system-management.astro +10 -1
  186. package/frontend/pages/[dashboard]/taxonomy/categories.astro +30 -41
  187. package/frontend/pages/[dashboard]/taxonomy/index.astro +10 -0
  188. package/frontend/pages/[dashboard]/taxonomy/tags.astro +33 -43
  189. package/frontend/pages/[dashboard]/unverified-email.astro +29 -21
  190. package/frontend/pages/[dashboard]/user-management/edit.astro +170 -90
  191. package/frontend/pages/[dashboard]/user-management/index.astro +10 -1
  192. package/frontend/pages/studiocms_api/[...all].ts +106 -0
  193. package/frontend/pages/studiocms_api/_handlers/_utils/auth.ts +26 -0
  194. package/frontend/pages/studiocms_api/_handlers/_utils/changelog.ts +147 -0
  195. package/frontend/pages/studiocms_api/_handlers/_utils/db-studio-driver.ts +46 -0
  196. package/frontend/pages/studiocms_api/_handlers/_utils/parseLogLevel.ts +27 -0
  197. package/frontend/pages/studiocms_api/_handlers/auth/auth.ts +459 -0
  198. package/frontend/pages/studiocms_api/_handlers/auth/index.ts +17 -0
  199. package/frontend/pages/studiocms_api/_handlers/auth/oauth.ts +91 -0
  200. package/frontend/pages/studiocms_api/_handlers/dashboard/_shared.ts +57 -0
  201. package/frontend/pages/studiocms_api/_handlers/dashboard/apiTokens.ts +134 -0
  202. package/frontend/pages/studiocms_api/_handlers/dashboard/config.ts +64 -0
  203. package/frontend/pages/studiocms_api/_handlers/dashboard/content.ts +741 -0
  204. package/frontend/pages/studiocms_api/_handlers/dashboard/create.ts +480 -0
  205. package/frontend/pages/studiocms_api/_handlers/dashboard/emailNotifications.ts +49 -0
  206. package/frontend/pages/studiocms_api/_handlers/dashboard/index.ts +45 -0
  207. package/frontend/pages/studiocms_api/_handlers/dashboard/mailer.ts +136 -0
  208. package/frontend/pages/studiocms_api/_handlers/dashboard/plugins.ts +80 -0
  209. package/frontend/pages/studiocms_api/_handlers/dashboard/profile.ts +275 -0
  210. package/frontend/pages/studiocms_api/_handlers/dashboard/resetPassword.ts +140 -0
  211. package/frontend/pages/studiocms_api/_handlers/dashboard/search.ts +63 -0
  212. package/frontend/pages/studiocms_api/_handlers/dashboard/taxonomy.ts +285 -0
  213. package/frontend/pages/studiocms_api/_handlers/dashboard/templates.ts +75 -0
  214. package/frontend/pages/studiocms_api/_handlers/dashboard/users.ts +312 -0
  215. package/frontend/pages/studiocms_api/_handlers/dashboard/verifyEndpoints.ts +307 -0
  216. package/frontend/pages/studiocms_api/_handlers/integration/dbStudio.ts +98 -0
  217. package/frontend/pages/studiocms_api/_handlers/integration/index.ts +17 -0
  218. package/frontend/pages/studiocms_api/_handlers/integration/storageManager.ts +107 -0
  219. package/frontend/pages/studiocms_api/_handlers/rest-api/index.ts +8 -0
  220. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/_shared.ts +41 -0
  221. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/index.ts +17 -0
  222. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/public.ts +195 -0
  223. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts +1726 -0
  224. package/frontend/pages/studiocms_api/_handlers/sdk.ts +129 -0
  225. package/frontend/pages/studiocms_api/_middleware/astroLocals.ts +36 -0
  226. package/frontend/pages/studiocms_api/_middleware/restApi.ts +56 -0
  227. package/frontend/pages/studiocms_api/integrations/[...all].ts +8 -0
  228. package/frontend/scripts/formdata.ts +219 -0
  229. package/frontend/setup-pages/3-done.astro +4 -20
  230. package/frontend/setup-pages/studiocms_api/dashboard/step-2.ts +3 -6
  231. package/frontend/styles/dashboard-base.css +0 -1
  232. package/frontend/web-vitals/endpoint.ts +2 -1
  233. package/package.json +35 -31
  234. package/dist/global.d.ts +0 -9
  235. package/frontend/components/dashboard/LoginChecker.astro +0 -68
  236. package/frontend/components/dashboard/user-mgmt/RankCheck.astro +0 -57
  237. package/frontend/components/first-time-setup/snippets/opt1-astro.config.diff +0 -14
  238. package/frontend/components/first-time-setup/snippets/opt2-astro.config.diff +0 -9
  239. package/frontend/middleware/_authmap.ts +0 -63
  240. package/frontend/pages/studiocms_api/auth/[path].ts +0 -390
  241. package/frontend/pages/studiocms_api/auth/[provider]/[...id].ts +0 -64
  242. package/frontend/pages/studiocms_api/auth/[provider]/_effects/index.ts +0 -101
  243. package/frontend/pages/studiocms_api/auth/_shared.ts +0 -52
  244. package/frontend/pages/studiocms_api/dashboard/api-tokens.ts +0 -115
  245. package/frontend/pages/studiocms_api/dashboard/config.ts +0 -74
  246. package/frontend/pages/studiocms_api/dashboard/content/diff.ts +0 -73
  247. package/frontend/pages/studiocms_api/dashboard/content/folder.ts +0 -220
  248. package/frontend/pages/studiocms_api/dashboard/content/page.ts +0 -359
  249. package/frontend/pages/studiocms_api/dashboard/create-reset-link.ts +0 -77
  250. package/frontend/pages/studiocms_api/dashboard/create-user-invite.ts +0 -231
  251. package/frontend/pages/studiocms_api/dashboard/create-user.ts +0 -186
  252. package/frontend/pages/studiocms_api/dashboard/email-notification-settings-site.ts +0 -74
  253. package/frontend/pages/studiocms_api/dashboard/mailer/check-email.ts +0 -75
  254. package/frontend/pages/studiocms_api/dashboard/mailer/config.ts +0 -136
  255. package/frontend/pages/studiocms_api/dashboard/plugins/[plugin].ts +0 -80
  256. package/frontend/pages/studiocms_api/dashboard/profile.ts +0 -245
  257. package/frontend/pages/studiocms_api/dashboard/resend-verify-email.ts +0 -77
  258. package/frontend/pages/studiocms_api/dashboard/reset-password.ts +0 -124
  259. package/frontend/pages/studiocms_api/dashboard/search-list.ts +0 -59
  260. package/frontend/pages/studiocms_api/dashboard/taxonomy-search.ts +0 -47
  261. package/frontend/pages/studiocms_api/dashboard/taxonomy.ts +0 -230
  262. package/frontend/pages/studiocms_api/dashboard/templates.ts +0 -74
  263. package/frontend/pages/studiocms_api/dashboard/update-user-notifications.ts +0 -86
  264. package/frontend/pages/studiocms_api/dashboard/users.ts +0 -236
  265. package/frontend/pages/studiocms_api/dashboard/verify-email.ts +0 -83
  266. package/frontend/pages/studiocms_api/dashboard/verify-session.ts +0 -187
  267. package/frontend/pages/studiocms_api/integrations/[type]/[...id].ts +0 -15
  268. package/frontend/pages/studiocms_api/integrations/[type]/_routes/db-studio.ts +0 -173
  269. package/frontend/pages/studiocms_api/integrations/[type]/_routes/storage.ts +0 -88
  270. package/frontend/pages/studiocms_api/partials/editor.astro +0 -74
  271. package/frontend/pages/studiocms_api/partials/render.astro +0 -39
  272. package/frontend/pages/studiocms_api/partials/user-list-items.astro +0 -43
  273. package/frontend/pages/studiocms_api/rest/utils/auth-token.ts +0 -59
  274. package/frontend/pages/studiocms_api/rest/v1/[type]/[...id].ts +0 -23
  275. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/categories.ts +0 -267
  276. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/folders.ts +0 -283
  277. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/pages.ts +0 -505
  278. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/settings.ts +0 -100
  279. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/tags.ts +0 -229
  280. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/users.ts +0 -553
  281. package/frontend/pages/studiocms_api/rest/v1/public/[type]/[...id].ts +0 -19
  282. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/categories.ts +0 -74
  283. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/folders.ts +0 -85
  284. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/pages.ts +0 -103
  285. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/tags.ts +0 -67
  286. package/frontend/pages/studiocms_api/sdk/[...path].ts +0 -97
  287. package/frontend/pages/studiocms_api/sdk/utils/changelog.ts +0 -119
  288. package/frontend/scripts/auth/formListener.ts +0 -81
  289. package/frontend/scripts/formdata-utils.ts +0 -116
  290. package/frontend/utils/build-partial-schema.ts +0 -46
  291. package/frontend/utils/errors.ts +0 -6
  292. package/frontend/utils/param-extractor.ts +0 -83
  293. package/frontend/utils/rest-router.ts +0 -444
@@ -1,505 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { Notifications } from 'studiocms:notifier';
3
- import { SDKCore } from 'studiocms:sdk';
4
- import type { tsPageContentSelect, tsPageData, tsPageDataSelect } from 'studiocms:sdk/types';
5
- import {
6
- AllResponse,
7
- createEffectAPIRoutes,
8
- createJsonResponse,
9
- Effect,
10
- genLogger,
11
- OptionsResponse,
12
- readAPIContextJson,
13
- Schema,
14
- } from '@withstudiocms/effect';
15
- import { StudioCMSPageData } from '@withstudiocms/sdk/tables';
16
- import {
17
- type EndpointRoute,
18
- idOrPathRouter,
19
- type SubPathRouter,
20
- } from '../../../../../../utils/rest-router.js';
21
- import { verifyAuthTokenFromHeader } from '../../../utils/auth-token.js';
22
-
23
- type UpdatePageData = Partial<tsPageDataSelect>;
24
- type UpdatePageContent = Partial<tsPageContentSelect>;
25
-
26
- interface UpdatePageJson {
27
- pageId: string;
28
- data?: UpdatePageData;
29
- content?: UpdatePageContent;
30
- }
31
-
32
- interface CreatePageJson {
33
- data?: tsPageDataSelect;
34
- content?: tsPageContentSelect;
35
- }
36
-
37
- const subPathRouter: SubPathRouter = {
38
- history: (id: string, _params?: Record<string, string>) =>
39
- createEffectAPIRoutes(
40
- {
41
- GET: (ctx) =>
42
- genLogger('studioCMS:rest:v1:public:pages:[id]:history:GET')(function* () {
43
- const [sdk, user] = yield* Effect.all([SDKCore, verifyAuthTokenFromHeader(ctx)]);
44
-
45
- if (user instanceof Response) {
46
- return user;
47
- }
48
-
49
- const { rank } = user;
50
-
51
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
52
- return apiResponseLogger(401, 'Unauthorized');
53
- }
54
-
55
- const page = yield* sdk.GET.page.byId(id);
56
-
57
- if (!page) {
58
- return apiResponseLogger(404, 'Page not found');
59
- }
60
-
61
- const searchParams = ctx.url.searchParams;
62
-
63
- const limitParam = searchParams.get('limit');
64
- const parsedLimit = limitParam ? Number.parseInt(limitParam, 10) : undefined;
65
- const limit =
66
- typeof parsedLimit === 'number' && Number.isFinite(parsedLimit) && parsedLimit > 0
67
- ? Math.min(parsedLimit, 100) // clamp to protect backend
68
- : undefined;
69
-
70
- const diffs =
71
- limit !== undefined
72
- ? yield* sdk.diffTracking.get.byPageId.latest(id, limit)
73
- : yield* sdk.diffTracking.get.byPageId.all(id);
74
-
75
- return createJsonResponse(diffs);
76
- }),
77
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET'] })),
78
- ALL: () => Effect.try(() => AllResponse()),
79
- },
80
- {
81
- cors: { methods: ['GET', 'OPTIONS'] },
82
- onError: (error) => {
83
- console.error('API Error:', error);
84
- return createJsonResponse({ error: 'Internal Server Error' }, { status: 500 });
85
- },
86
- }
87
- ),
88
- 'history/[diffId]': (id: string, params?: Record<string, string>) =>
89
- createEffectAPIRoutes(
90
- {
91
- GET: (ctx) =>
92
- genLogger('studioCMS:rest:v1:pages:[id]:history:[diffid]:GET')(function* () {
93
- const sdk = yield* SDKCore;
94
-
95
- const user = yield* verifyAuthTokenFromHeader(ctx);
96
-
97
- if (user instanceof Response) {
98
- return user;
99
- }
100
-
101
- const { rank } = user;
102
-
103
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
104
- return apiResponseLogger(401, 'Unauthorized');
105
- }
106
-
107
- const diffId = params?.diffId;
108
-
109
- if (!id) {
110
- return apiResponseLogger(400, 'Invalid page ID');
111
- }
112
-
113
- if (!diffId) {
114
- return apiResponseLogger(400, 'Invalid diff ID');
115
- }
116
-
117
- const diff = yield* sdk.diffTracking.get.single(diffId);
118
-
119
- if (!diff) {
120
- return apiResponseLogger(404, 'Diff not found');
121
- }
122
-
123
- if (diff.pageId !== id) {
124
- return apiResponseLogger(404, 'Diff not found');
125
- }
126
-
127
- return createJsonResponse(diff);
128
- }),
129
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET'] })),
130
- ALL: () => Effect.try(() => AllResponse()),
131
- },
132
- {
133
- cors: { methods: ['GET', 'OPTIONS'] },
134
- onError: (error) => {
135
- console.error('API Error:', error);
136
- return createJsonResponse({ error: 'Internal Server Error' }, { status: 500 });
137
- },
138
- }
139
- ),
140
- };
141
-
142
- const pageIdRouter = (id: string) =>
143
- createEffectAPIRoutes(
144
- {
145
- GET: (ctx) =>
146
- genLogger('studioCMS:rest:v1:pages:[id]:GET')(function* () {
147
- const [sdk, user] = yield* Effect.all([SDKCore, verifyAuthTokenFromHeader(ctx)]);
148
-
149
- if (user instanceof Response) {
150
- return user;
151
- }
152
-
153
- const { rank } = user;
154
-
155
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
156
- return apiResponseLogger(401, 'Unauthorized');
157
- }
158
-
159
- const page = yield* sdk.GET.page.byId(id);
160
-
161
- if (!page) {
162
- return apiResponseLogger(404, 'Page not found');
163
- }
164
-
165
- return createJsonResponse(page);
166
- }),
167
- PATCH: (ctx) =>
168
- genLogger('studioCMS:rest:v1:pages:[id]:PATCH')(function* () {
169
- const [sdk, user, notifier] = yield* Effect.all([
170
- SDKCore,
171
- verifyAuthTokenFromHeader(ctx),
172
- Notifications,
173
- ]);
174
-
175
- if (user instanceof Response) {
176
- return user;
177
- }
178
-
179
- const { rank, userId } = user;
180
-
181
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
182
- return apiResponseLogger(401, 'Unauthorized');
183
- }
184
-
185
- const jsonData = yield* readAPIContextJson<UpdatePageJson>(ctx);
186
-
187
- const { data, content } = jsonData;
188
-
189
- if (!data) {
190
- return apiResponseLogger(400, 'Invalid form data, data is required');
191
- }
192
-
193
- if (!content) {
194
- return apiResponseLogger(400, 'Invalid form data, content is required');
195
- }
196
-
197
- if (!data.id) {
198
- return apiResponseLogger(400, 'Invalid form data, id is required');
199
- }
200
-
201
- if (!content.id) {
202
- return apiResponseLogger(400, 'Invalid form data, id is required');
203
- }
204
- if (data.id !== id) {
205
- return apiResponseLogger(400, 'Payload id does not match path id');
206
- }
207
-
208
- const currentPageData = yield* sdk.GET.page.byId(id);
209
-
210
- if (!currentPageData) {
211
- return apiResponseLogger(404, 'Page not found');
212
- }
213
-
214
- const { authorId, contributorIds, defaultContent } = currentPageData;
215
-
216
- let AuthorId = authorId;
217
-
218
- if (!authorId) {
219
- AuthorId = userId;
220
- }
221
-
222
- const ContributorIds = contributorIds || [];
223
-
224
- if (!ContributorIds.includes(userId)) {
225
- ContributorIds.push(userId);
226
- }
227
-
228
- const newData: tsPageData['Insert']['Type'] = {
229
- ...(data as tsPageDataSelect),
230
- authorId: AuthorId,
231
- contributorIds: JSON.stringify(ContributorIds),
232
- updatedAt: new Date().toISOString(),
233
- publishedAt:
234
- currentPageData.draft && data.draft === false
235
- ? new Date().toISOString()
236
- : currentPageData.publishedAt?.toISOString() || new Date().toISOString(),
237
- categories: JSON.stringify(data.categories || []),
238
- tags: JSON.stringify(data.tags || []),
239
- augments: JSON.stringify(data.augments || []),
240
- };
241
-
242
- const getMetaData = sdk.dbService.withCodec({
243
- encoder: Schema.String,
244
- decoder: StudioCMSPageData.Select,
245
- callbackFn: (query, input) =>
246
- query((db) =>
247
- db
248
- .selectFrom('StudioCMSPageData')
249
- .selectAll()
250
- .where('id', '=', input)
251
- .executeTakeFirstOrThrow()
252
- ),
253
- });
254
-
255
- const startMetaData = yield* getMetaData(data.id);
256
-
257
- yield* sdk.UPDATE.page.byId(data.id, {
258
- pageData: newData,
259
- pageContent: content as tsPageContentSelect,
260
- });
261
-
262
- const updatedMetaData = yield* getMetaData(data.id);
263
-
264
- const siteConfig = yield* sdk.GET.siteConfig();
265
-
266
- if (!siteConfig) {
267
- return apiResponseLogger(500, 'Site configuration not found');
268
- }
269
-
270
- const { enableDiffs, diffPerPage = 10 } = siteConfig.data;
271
-
272
- if (enableDiffs) {
273
- yield* sdk.diffTracking.insert(
274
- userId,
275
- data.id,
276
- {
277
- content: {
278
- start: defaultContent?.content || '',
279
- end: content.content || '',
280
- },
281
- // biome-ignore lint/style/noNonNullAssertion: This is a valid use case for non-null assertion
282
- metaData: { start: startMetaData!, end: updatedMetaData! },
283
- },
284
- diffPerPage
285
- );
286
- }
287
-
288
- yield* sdk.CLEAR.page.byId(id);
289
-
290
- // biome-ignore lint/style/noNonNullAssertion: This is a valid use case for non-null assertion
291
- yield* notifier.sendEditorNotification('page_updated', updatedMetaData!.title);
292
-
293
- return apiResponseLogger(200, 'Page updated successfully');
294
- }).pipe(Notifications.Provide),
295
- DELETE: (ctx) =>
296
- genLogger('studioCMS:rest:v1:pages:[id]:DELETE')(function* () {
297
- const [sdk, user, notifier] = yield* Effect.all([
298
- SDKCore,
299
- verifyAuthTokenFromHeader(ctx),
300
- Notifications,
301
- ]);
302
-
303
- if (user instanceof Response) {
304
- return user;
305
- }
306
-
307
- const { rank } = user;
308
-
309
- if (rank !== 'owner' && rank !== 'admin') {
310
- return apiResponseLogger(401, 'Unauthorized');
311
- }
312
-
313
- const jsonData = yield* readAPIContextJson<{ slug: string }>(ctx);
314
-
315
- const { slug } = jsonData;
316
-
317
- if (!slug) {
318
- return apiResponseLogger(400, 'Invalid request');
319
- }
320
-
321
- const page = yield* sdk.GET.page.byId(id);
322
-
323
- if (!page) {
324
- return apiResponseLogger(404, 'Page not found');
325
- }
326
-
327
- yield* sdk.DELETE.page(id);
328
- yield* sdk.CLEAR.page.byId(id);
329
-
330
- yield* notifier.sendEditorNotification('page_deleted', page.title);
331
-
332
- return apiResponseLogger(200, 'Page deleted successfully');
333
- }).pipe(Notifications.Provide),
334
- OPTIONS: () =>
335
- Effect.try(() => OptionsResponse({ allowedMethods: ['GET', 'PATCH', 'DELETE'] })),
336
- ALL: () => Effect.try(() => AllResponse()),
337
- },
338
- {
339
- cors: { methods: ['GET', 'PATCH', 'DELETE', 'OPTIONS'] },
340
- onError: (error) => {
341
- console.error('API Error:', error);
342
- return createJsonResponse(
343
- { error: 'Internal Server Error' },
344
- {
345
- status: 500,
346
- }
347
- );
348
- },
349
- }
350
- );
351
-
352
- export const pagesRouter: EndpointRoute = {
353
- __idType: 'string',
354
- __index: createEffectAPIRoutes(
355
- {
356
- GET: (ctx) =>
357
- genLogger('studioCMS:rest:v1:public:pages:GET')(function* () {
358
- const [sdk, user] = yield* Effect.all([SDKCore, verifyAuthTokenFromHeader(ctx)]);
359
-
360
- if (user instanceof Response) {
361
- return user;
362
- }
363
-
364
- const { rank } = user;
365
-
366
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
367
- return apiResponseLogger(401, 'Unauthorized');
368
- }
369
-
370
- const pages = yield* sdk.GET.pages(true);
371
-
372
- const searchParams = ctx.url.searchParams;
373
-
374
- const titleFilter = searchParams.get('title');
375
- const slugFilter = searchParams.get('slug');
376
- const authorFilter = searchParams.get('author');
377
- const draftFilter = searchParams.get('draft') === 'true';
378
- const publishedFilter = searchParams.get('published') === 'true';
379
- const parentFolderFilter = searchParams.get('parentFolder');
380
-
381
- let filteredPages = pages;
382
-
383
- if (titleFilter) {
384
- filteredPages = filteredPages.filter((page) => page.title.includes(titleFilter));
385
- }
386
-
387
- if (slugFilter) {
388
- filteredPages = filteredPages.filter((page) => page.slug.includes(slugFilter));
389
- }
390
-
391
- if (authorFilter) {
392
- filteredPages = filteredPages.filter((page) => page.authorId === authorFilter);
393
- }
394
-
395
- if (draftFilter) {
396
- filteredPages = filteredPages.filter((page) => page.draft === draftFilter);
397
- }
398
-
399
- if (publishedFilter) {
400
- filteredPages = filteredPages.filter((page) => !page.draft);
401
- }
402
-
403
- if (parentFolderFilter) {
404
- filteredPages = filteredPages.filter(
405
- (page) => page.parentFolder === parentFolderFilter
406
- );
407
- }
408
-
409
- return createJsonResponse(filteredPages);
410
- }),
411
- POST: (ctx) =>
412
- genLogger('studioCMS:rest:v1:public:pages:POST')(function* () {
413
- const [sdk, user, notifier] = yield* Effect.all([
414
- SDKCore,
415
- verifyAuthTokenFromHeader(ctx),
416
- Notifications,
417
- ]);
418
-
419
- if (user instanceof Response) {
420
- return user;
421
- }
422
-
423
- const { rank, userId } = user;
424
-
425
- if (rank !== 'owner' && rank !== 'admin' && rank !== 'editor') {
426
- return apiResponseLogger(401, 'Unauthorized');
427
- }
428
-
429
- const jsonData = yield* readAPIContextJson<CreatePageJson>(ctx);
430
-
431
- const { data, content } = jsonData;
432
-
433
- if (!data) {
434
- return apiResponseLogger(400, 'Invalid form data, data is required');
435
- }
436
-
437
- if (!content) {
438
- return apiResponseLogger(400, 'Invalid form data, content is required');
439
- }
440
-
441
- if (!data.title) {
442
- return apiResponseLogger(400, 'Invalid form data, title is required');
443
- }
444
-
445
- const dataId = crypto.randomUUID();
446
-
447
- const {
448
- title,
449
- slug,
450
- description,
451
- categories,
452
- tags,
453
- contributorIds,
454
- augments,
455
- id: ___id,
456
- authorId: __authorId,
457
- updatedAt: __updatedAt,
458
- publishedAt: __publishedAt,
459
- ...restPageData
460
- } = data;
461
-
462
- const { id: ____id, ...contentData } = content;
463
-
464
- yield* sdk.POST.databaseEntry.pages(
465
- {
466
- id: dataId,
467
- title,
468
- slug:
469
- slug ||
470
- title
471
- .toLowerCase()
472
- .replace(/[^a-z0-9\s-]/g, '') // Remove special characters
473
- .replace(/\s+/g, '-') // Replace spaces with hyphens
474
- .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
475
- .replace(/^-|-$/g, ''), // Remove leading/trailing hyphens '-'),
476
- description: description || '',
477
- authorId: userId,
478
- updatedAt: new Date().toISOString(),
479
- publishedAt: new Date().toISOString(),
480
- categories: JSON.stringify(categories || []),
481
- tags: JSON.stringify(tags || []),
482
- contributorIds: JSON.stringify(contributorIds || []),
483
- augments: JSON.stringify(augments || []),
484
- ...restPageData,
485
- },
486
- { ...contentData }
487
- );
488
-
489
- yield* notifier.sendEditorNotification('new_page', data.title);
490
-
491
- return apiResponseLogger(200, `Page created successfully with id: ${dataId}`);
492
- }).pipe(Notifications.Provide),
493
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET', 'POST'] })),
494
- ALL: () => Effect.try(() => AllResponse()),
495
- },
496
- {
497
- cors: { methods: ['GET', 'POST', 'OPTIONS'] },
498
- onError: (error) => {
499
- console.error('API Error:', error);
500
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
501
- },
502
- }
503
- ),
504
- id: (id: string) => idOrPathRouter(id, pageIdRouter, subPathRouter),
505
- };
@@ -1,100 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { SDKCore } from 'studiocms:sdk';
3
- import {
4
- AllResponse,
5
- createEffectAPIRoutes,
6
- createJsonResponse,
7
- Effect,
8
- genLogger,
9
- OptionsResponse,
10
- readAPIContextJson,
11
- } from '@withstudiocms/effect';
12
- import type { EndpointRoute } from './../../../../../../utils/rest-router.js';
13
- import { verifyAuthTokenFromHeader } from '../../../utils/auth-token.js';
14
-
15
- export const settingsRouter: EndpointRoute = {
16
- __idType: 'string',
17
- __index: createEffectAPIRoutes(
18
- {
19
- GET: (ctx) =>
20
- genLogger('studioCMS:rest:v1:settings:GET')(function* () {
21
- const [sdk, user] = yield* Effect.all([SDKCore, verifyAuthTokenFromHeader(ctx)]);
22
-
23
- if (user instanceof Response) {
24
- return user;
25
- }
26
-
27
- const { rank } = user;
28
-
29
- if (rank !== 'owner') {
30
- return apiResponseLogger(401, 'Unauthorized');
31
- }
32
-
33
- const siteConfig = yield* sdk.GET.siteConfig();
34
-
35
- return createJsonResponse(siteConfig);
36
- }),
37
- PATCH: (ctx) =>
38
- genLogger('studioCMS:rest:v1:settings:PATCH')(function* () {
39
- const [sdk, user] = yield* Effect.all([SDKCore, verifyAuthTokenFromHeader(ctx)]);
40
-
41
- if (user instanceof Response) {
42
- return user;
43
- }
44
-
45
- const { rank } = user;
46
-
47
- if (rank !== 'owner') {
48
- return apiResponseLogger(401, 'Unauthorized');
49
- }
50
-
51
- const siteConfig = yield* readAPIContextJson<{
52
- title: string;
53
- description: string;
54
- loginPageBackground: string;
55
- loginPageCustomImage?: string;
56
- }>(ctx);
57
-
58
- if (typeof siteConfig.title !== 'string' || siteConfig.title.trim() === '') {
59
- return apiResponseLogger(400, 'Invalid form data, title is required');
60
- }
61
-
62
- if (typeof siteConfig.description !== 'string' || siteConfig.description.trim() === '') {
63
- return apiResponseLogger(400, 'Invalid form data, description is required');
64
- }
65
-
66
- if (
67
- typeof siteConfig.loginPageBackground !== 'string' ||
68
- siteConfig.loginPageBackground.trim() === ''
69
- ) {
70
- return apiResponseLogger(400, 'Invalid form data, loginPageBackground is required');
71
- }
72
-
73
- if (
74
- siteConfig.loginPageBackground === 'custom' &&
75
- (typeof siteConfig.loginPageCustomImage !== 'string' ||
76
- siteConfig.loginPageCustomImage.trim() === '')
77
- ) {
78
- return apiResponseLogger(400, 'Invalid form data, loginPageCustomImage is required');
79
- }
80
-
81
- yield* sdk.UPDATE.siteConfig(siteConfig);
82
-
83
- return apiResponseLogger(200, 'Site config updated');
84
- }),
85
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET', 'PATCH'] })),
86
- ALL: () => Effect.try(() => AllResponse()),
87
- },
88
- {
89
- cors: { methods: ['GET', 'PATCH', 'OPTIONS'] },
90
- onError: (error) => {
91
- console.error('API Error:', error);
92
- if (error instanceof SyntaxError) {
93
- // Likely invalid JSON in request body
94
- return createJsonResponse({ error: 'Invalid JSON' }, { status: 400 });
95
- }
96
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
97
- },
98
- }
99
- ),
100
- };