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,101 +0,0 @@
1
- import { type OAuthProviders, oAuthProviders } from 'studiocms:plugins/auth/providers';
2
- import { Effect, genLogger } from '@withstudiocms/effect';
3
- import type { APIContext, APIRoute } from 'astro';
4
- import { StudioCMSAPIError } from '#frontend/utils/errors.js';
5
-
6
- /**
7
- * Creates a standardized HTTP response for authentication provider errors.
8
- *
9
- * @param error - The error message to include in the response body.
10
- * @param status - The HTTP status code for the response.
11
- * @returns A `Response` object with a JSON body containing the error message and the specified status code.
12
- */
13
- export const ProviderResponse = (
14
- error: string,
15
- status: number
16
- ): Effect.Effect<Response, never, never> =>
17
- Effect.succeed(new Response(JSON.stringify({ error }), { status }));
18
-
19
- /**
20
- * Executes the provided API route handler function with the given context and returns its resulting Promise.
21
- *
22
- * @param fn - The API route handler function to execute.
23
- * @param context - The context object to pass to the handler function.
24
- * @returns A Promise that resolves to a Response object returned by the handler.
25
- */
26
- async function promisifyFn(fn: APIRoute, context: APIContext): Promise<Response> {
27
- return await fn(context);
28
- }
29
-
30
- /**
31
- * Wraps an API route handler function in an Effect, converting it into a promise-based effectful computation.
32
- *
33
- * @param fn - The API route handler function to be executed.
34
- * @param context - The API context to be passed to the handler.
35
- * @returns An Effect that resolves with the result of the handler or rejects with an error if execution fails.
36
- *
37
- * @remarks
38
- * If the handler throws an error, it is caught and wrapped in a new `Error` with a descriptive message.
39
- */
40
- const promisify = Effect.fn(function* (fn: APIRoute, context: APIContext) {
41
- return yield* Effect.tryPromise({
42
- try: () => promisifyFn(fn, context),
43
- catch: (error) =>
44
- new StudioCMSAPIError({ message: `Failed to execute API route: ${error}`, cause: error }),
45
- });
46
- });
47
-
48
- /**
49
- * Dispatches an authentication request to the appropriate OAuth provider handler.
50
- *
51
- * This generator function locates the specified provider by its `safeName` from the provided list,
52
- * checks if the provider is enabled, and then invokes the appropriate handler (`initSession` or `initCallback`)
53
- * for the authentication flow. If the provider or handler is not found, or if the provider is not enabled,
54
- * it yields an appropriate error response.
55
- *
56
- * @param context - The API context containing request parameters and other relevant data.
57
- * @param handler - The handler to invoke, either `'initSession'` or `'initCallback'`.
58
- * @param providers - An array of provider configurations, each containing a `safeName`, `enabled` flag,
59
- * and optional `initSession` and `initCallback` route handlers.
60
- * @returns A generator yielding the result of the provider handler or an error response.
61
- */
62
- const dispatchToAuthProvider = (
63
- context: APIContext,
64
- handler: 'initSession' | 'initCallback',
65
- providers: OAuthProviders
66
- ) =>
67
- genLogger('OAuthAPIEffect.dispatchToAuthProvider')(function* () {
68
- const provider = context.params.provider;
69
- const matchedProvider = providers.find((p) => p.safeName === provider);
70
- if (!matchedProvider) {
71
- return yield* ProviderResponse('Provider not found', 404);
72
- }
73
- if (!matchedProvider.enabled) {
74
- return yield* ProviderResponse('Provider is not configured', 403);
75
- }
76
-
77
- const handlerFn = matchedProvider[handler];
78
-
79
- if (!handlerFn) {
80
- return yield* ProviderResponse('Provider handler not found', 501);
81
- }
82
-
83
- return yield* promisify(handlerFn, context);
84
- });
85
-
86
- export class OAuthAPIEffect extends Effect.Service<OAuthAPIEffect>()('OAuthAPIEffect', {
87
- effect: genLogger('studiocms/routes/api/auth/[provider]/_shared')(function* () {
88
- return {
89
- initSession: (context: APIContext) =>
90
- dispatchToAuthProvider(context, 'initSession', oAuthProviders),
91
- initCallback: (context: APIContext) =>
92
- dispatchToAuthProvider(context, 'initCallback', oAuthProviders),
93
- };
94
- }),
95
- }) {
96
- // Export Dependency Providers
97
- /**
98
- * Main Dependencies Provider
99
- */
100
- static Provide = Effect.provide(OAuthAPIEffect.Default);
101
- }
@@ -1,52 +0,0 @@
1
- import {
2
- createJsonResponse,
3
- Effect,
4
- genLogger,
5
- parseFormDataEntryToString,
6
- readAPIContextFormData,
7
- readAPIContextJson,
8
- Schema,
9
- } from '@withstudiocms/effect';
10
- import type { APIContext } from 'astro';
11
- import { AstroError } from 'astro/errors';
12
- import { z } from 'astro/zod';
13
-
14
- export class FormDataEntryFields extends Schema.Class<FormDataEntryFields>('FormDataEntryFields')({
15
- title: Schema.String,
16
- description: Schema.String,
17
- }) {}
18
-
19
- export class AuthAPIUtils extends Effect.Service<AuthAPIUtils>()(
20
- 'studiocms/routes/api/auth/shared/AuthAPIUtils',
21
- {
22
- effect: genLogger('studiocms/routes/api/auth/shared/AuthAPIUtils.effect')(function* () {
23
- return {
24
- parseFormDataEntryToString: parseFormDataEntryToString,
25
- // biome-ignore lint/suspicious/noExplicitAny: This is a generic utility function
26
- readJson: (context: APIContext) => readAPIContextJson<any>(context),
27
- readFormData: (context: APIContext) => readAPIContextFormData(context),
28
- badFormDataEntry: (title: string, description: string) =>
29
- genLogger('studiocms/routes/api/auth/shared/AuthAPIUtils.badFormDataEntry')(function* () {
30
- const error = yield* Schema.decode(FormDataEntryFields)({ title, description });
31
- return createJsonResponse(
32
- { error },
33
- {
34
- status: 400,
35
- statusText: 'Bad Request',
36
- }
37
- );
38
- }),
39
- validateEmail: (email: string) =>
40
- Effect.try({
41
- try: () => {
42
- const emailSchema = z.coerce.string().email({ message: 'Email address is invalid' });
43
- return emailSchema.safeParse(email);
44
- },
45
- catch: () => new AstroError('Failed to parse email with zod.'),
46
- }),
47
- };
48
- }),
49
- }
50
- ) {
51
- static Provide = Effect.provide(this.Default);
52
- }
@@ -1,115 +0,0 @@
1
- import { developerConfig } from 'studiocms:config';
2
- import { apiResponseLogger } from 'studiocms:logger';
3
- import { SDKCore } from 'studiocms:sdk';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- readAPIContextJson,
12
- } from '@withstudiocms/effect';
13
-
14
- export const { POST, DELETE, OPTIONS, ALL } = createEffectAPIRoutes(
15
- {
16
- POST: (ctx) =>
17
- genLogger('studiocms/routes/api/dashboard/api-tokens.POST')(function* () {
18
- const sdk = yield* SDKCore;
19
-
20
- // Check if demo mode is enabled
21
- if (developerConfig.demoMode !== false) {
22
- return apiResponseLogger(403, 'Demo mode is enabled, this action is not allowed.');
23
- }
24
-
25
- // Get user data
26
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
27
-
28
- // Check if user is logged in
29
- if (!userData?.isLoggedIn) {
30
- return apiResponseLogger(403, 'Unauthorized');
31
- }
32
-
33
- // Check if user has permission
34
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;
35
- if (!isAuthorized) {
36
- return apiResponseLogger(403, 'Unauthorized');
37
- }
38
-
39
- // Get Json Data
40
- const jsonData = yield* readAPIContextJson<{
41
- description: string;
42
- user: string;
43
- }>(ctx);
44
-
45
- // Validate form data
46
- if (!jsonData.description) {
47
- return apiResponseLogger(400, 'Invalid form data, description is required');
48
- }
49
-
50
- if (!jsonData.user) {
51
- return apiResponseLogger(400, 'Invalid form data, user is required');
52
- }
53
-
54
- const newToken = yield* sdk.REST_API.tokens.new(jsonData.user, jsonData.description);
55
-
56
- return createJsonResponse({ token: newToken.key });
57
- }),
58
- DELETE: (ctx) =>
59
- genLogger('studiocms/routes/api/dashboard/api-tokens.DELETE')(function* () {
60
- const sdk = yield* SDKCore;
61
-
62
- // Check if demo mode is enabled
63
- if (developerConfig.demoMode !== false) {
64
- return apiResponseLogger(403, 'Demo mode is enabled, this action is not allowed.');
65
- }
66
-
67
- // Get user data
68
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
69
-
70
- // Check if user is logged in
71
- if (!userData?.isLoggedIn) {
72
- return apiResponseLogger(403, 'Unauthorized');
73
- }
74
-
75
- // Check if user has permission
76
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;
77
- if (!isAuthorized) {
78
- return apiResponseLogger(403, 'Unauthorized');
79
- }
80
-
81
- // Get Json Data
82
- const jsonData = yield* readAPIContextJson<{
83
- tokenID: string;
84
- userID: string;
85
- }>(ctx);
86
-
87
- // Validate form data
88
- if (!jsonData.tokenID) {
89
- return apiResponseLogger(400, 'Invalid form data, tokenID is required');
90
- }
91
-
92
- if (!jsonData.userID) {
93
- return apiResponseLogger(400, 'Invalid form data, userID is required');
94
- }
95
-
96
- yield* sdk.REST_API.tokens.delete({ tokenId: jsonData.tokenID, userId: jsonData.userID });
97
-
98
- return apiResponseLogger(200, 'Token deleted');
99
- }),
100
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST', 'DELETE'] })),
101
- ALL: () => Effect.try(() => AllResponse()),
102
- },
103
- {
104
- cors: { methods: ['POST', 'DELETE', 'OPTIONS'] },
105
- onError: (error) => {
106
- console.error('API Error:', error);
107
- return createJsonResponse(
108
- { error: 'Internal Server Error' },
109
- {
110
- status: 500,
111
- }
112
- );
113
- },
114
- }
115
- );
@@ -1,74 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { SDKCore } from 'studiocms:sdk';
3
- import type { StudioCMSSiteConfig } from 'studiocms:sdk/types';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- readAPIContextJson,
12
- } from '@withstudiocms/effect';
13
-
14
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
15
- {
16
- POST: (ctx) =>
17
- genLogger('studiocms/routes/api/dashboard/config.POST')(function* () {
18
- const sdk = yield* SDKCore;
19
-
20
- // Get user data
21
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
22
-
23
- // Check if user is logged in
24
- if (!userData?.isLoggedIn) {
25
- return apiResponseLogger(403, 'Unauthorized');
26
- }
27
-
28
- // Check if user has permission
29
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner;
30
- if (!isAuthorized) {
31
- return apiResponseLogger(403, 'Unauthorized');
32
- }
33
-
34
- // Get Json Data
35
- const siteConfig =
36
- yield* readAPIContextJson<Omit<StudioCMSSiteConfig, '_config_version'>>(ctx);
37
-
38
- // Validate form data
39
- if (!siteConfig.title) {
40
- return apiResponseLogger(400, 'Invalid form data, title is required');
41
- }
42
-
43
- if (!siteConfig.description) {
44
- return apiResponseLogger(400, 'Invalid form data, description is required');
45
- }
46
-
47
- if (!siteConfig.loginPageBackground) {
48
- return apiResponseLogger(400, 'Invalid form data, loginPageBackground is required');
49
- }
50
-
51
- if (siteConfig.loginPageBackground === 'custom' && !siteConfig.loginPageCustomImage) {
52
- return apiResponseLogger(400, 'Invalid form data, loginPageCustomImage is required');
53
- }
54
-
55
- yield* sdk.UPDATE.siteConfig(siteConfig);
56
-
57
- return apiResponseLogger(200, 'Site config updated');
58
- }),
59
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
60
- ALL: () => Effect.try(() => AllResponse()),
61
- },
62
- {
63
- cors: { methods: ['POST', 'OPTIONS'] },
64
- onError: (error) => {
65
- console.error('API Error:', error);
66
- return createJsonResponse(
67
- { error: 'Internal Server Error' },
68
- {
69
- status: 500,
70
- }
71
- );
72
- },
73
- }
74
- );
@@ -1,73 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { Notifications } from 'studiocms:notifier';
3
- import { SDKCore } from 'studiocms:sdk';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- readAPIContextJson,
12
- } from '@withstudiocms/effect';
13
-
14
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
15
- {
16
- POST: (ctx) =>
17
- genLogger('studiocms/routes/api/dashboard/content/diff.POST')(function* () {
18
- const [notify, sdk] = yield* Effect.all([Notifications, SDKCore]);
19
-
20
- // Get user data
21
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
22
-
23
- // Check if user is logged in
24
- if (!userData?.isLoggedIn) {
25
- return apiResponseLogger(403, 'Unauthorized');
26
- }
27
-
28
- // Check if user has permission
29
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;
30
- if (!isAuthorized) {
31
- return apiResponseLogger(403, 'Unauthorized');
32
- }
33
-
34
- const jsonData = yield* readAPIContextJson<{
35
- id: string;
36
- type: 'data' | 'content' | 'both';
37
- }>(ctx);
38
-
39
- const { id, type } = jsonData;
40
-
41
- if (!id || !type) {
42
- return apiResponseLogger(400, 'Invalid ID or Type');
43
- }
44
-
45
- if (!['data', 'content', 'both'].includes(type)) {
46
- return apiResponseLogger(400, 'Invalid Type');
47
- }
48
-
49
- const data = yield* sdk.diffTracking.revertToDiff(id, type);
50
-
51
- yield* Effect.all([
52
- sdk.CLEAR.pages,
53
- notify.sendEditorNotification('page_updated', data.pageMetaData.end.title || ''),
54
- ]);
55
-
56
- return apiResponseLogger(200, 'Page Reverted successfully');
57
- }).pipe(Notifications.Provide),
58
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
59
- ALL: () => Effect.try(() => AllResponse()),
60
- },
61
- {
62
- cors: { methods: ['POST', 'OPTIONS'] },
63
- onError: (error) => {
64
- console.error('Error in diff API:', error);
65
- return createJsonResponse(
66
- { error: 'Internal Server Error' },
67
- {
68
- status: 500,
69
- }
70
- );
71
- },
72
- }
73
- );
@@ -1,220 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { Notifications } from 'studiocms:notifier';
3
- import { SDKCore } from 'studiocms:sdk';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- readAPIContextJson,
12
- Schema,
13
- } from '@withstudiocms/effect';
14
- import { StudioCMSPageData, StudioCMSPageFolderStructure } from '@withstudiocms/sdk/tables';
15
-
16
- interface FolderBase {
17
- folderName: string;
18
- parentFolder: string | null;
19
- }
20
-
21
- interface FolderEdit extends FolderBase {
22
- id: string;
23
- }
24
-
25
- export const { POST, PATCH, DELETE, OPTIONS, ALL } = createEffectAPIRoutes(
26
- {
27
- POST: (ctx) =>
28
- genLogger('studiocms/routes/api/dashboard/content/folder.POST')(function* () {
29
- const [notify, sdk] = yield* Effect.all([Notifications, SDKCore]);
30
-
31
- // Get user data
32
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
33
-
34
- // Check if user is logged in
35
- if (!userData?.isLoggedIn) {
36
- return apiResponseLogger(403, 'Unauthorized');
37
- }
38
-
39
- // Check if user has permission
40
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isAdmin;
41
- if (!isAuthorized) {
42
- return apiResponseLogger(403, 'Unauthorized');
43
- }
44
-
45
- const { folderName, parentFolder } = yield* readAPIContextJson<FolderBase>(ctx);
46
-
47
- if (!folderName) {
48
- return apiResponseLogger(400, 'Invalid form data, folderName is required');
49
- }
50
-
51
- yield* Effect.all([
52
- sdk.POST.folder({
53
- id: crypto.randomUUID(),
54
- name: folderName,
55
- parent: parentFolder || null,
56
- }),
57
- sdk.UPDATE.folderList,
58
- sdk.UPDATE.folderTree,
59
- notify.sendEditorNotification('new_folder', folderName),
60
- ]);
61
-
62
- return apiResponseLogger(200, 'Folder created successfully');
63
- }).pipe(Notifications.Provide),
64
- PATCH: (ctx) =>
65
- genLogger('studiocms/routes/api/dashboard/content/folder.PATCH')(function* () {
66
- const [notify, sdk] = yield* Effect.all([Notifications, SDKCore]);
67
-
68
- // Get user data
69
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
70
-
71
- // Check if user is logged in
72
- if (!userData?.isLoggedIn) {
73
- return apiResponseLogger(403, 'Unauthorized');
74
- }
75
-
76
- // Check if user has permission
77
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;
78
- if (!isAuthorized) {
79
- return apiResponseLogger(403, 'Unauthorized');
80
- }
81
-
82
- const { id, folderName, parentFolder } = yield* readAPIContextJson<FolderEdit>(ctx);
83
-
84
- if (!id) {
85
- return apiResponseLogger(400, 'Invalid form data, id is required');
86
- }
87
-
88
- if (!folderName) {
89
- return apiResponseLogger(400, 'Invalid form data, folderName is required');
90
- }
91
-
92
- // Ensure parent folder is not the same as the folder being edited
93
- if (parentFolder === id) {
94
- return apiResponseLogger(400, 'A folder cannot be its own parent');
95
- }
96
-
97
- yield* Effect.all([
98
- sdk.UPDATE.folder({
99
- id,
100
- name: folderName,
101
- parent: parentFolder || null,
102
- }),
103
- sdk.UPDATE.folderList,
104
- sdk.UPDATE.folderTree,
105
- notify.sendEditorNotification('folder_updated', folderName),
106
- ]);
107
-
108
- return apiResponseLogger(200, 'Folder updated successfully');
109
- }).pipe(Notifications.Provide),
110
- DELETE: (ctx) =>
111
- genLogger('studiocms/routes/api/dashboard/content/folder.DELETE')(function* () {
112
- const [notify, sdk] = yield* Effect.all([Notifications, SDKCore]);
113
-
114
- /**
115
- * Check for child folders before deletion
116
- */
117
- const checkForChildrenFolders = sdk.dbService.withCodec({
118
- encoder: Schema.String,
119
- decoder: Schema.Array(StudioCMSPageFolderStructure),
120
- callbackFn: (client, id) =>
121
- client((db) =>
122
- db
123
- .selectFrom('StudioCMSPageFolderStructure')
124
- .where('parent', '=', id)
125
- .selectAll()
126
- .execute()
127
- ),
128
- });
129
-
130
- /**
131
- * Check for child pages before deletion
132
- */
133
- const checkForChildrenPages = sdk.dbService.withCodec({
134
- encoder: Schema.String,
135
- decoder: Schema.Array(StudioCMSPageData),
136
- callbackFn: (client, id) =>
137
- client((db) =>
138
- db
139
- .selectFrom('StudioCMSPageData')
140
- .where('parentFolder', '=', id)
141
- .selectAll()
142
- .execute()
143
- ),
144
- });
145
-
146
- /**
147
- * Check for any children (folders or pages) before deletion
148
- */
149
- const checkForChildren = Effect.fn((id: string) =>
150
- Effect.all({
151
- folders: checkForChildrenFolders(id),
152
- pages: checkForChildrenPages(id),
153
- }).pipe(
154
- Effect.map(({ folders, pages }) => {
155
- return { hasChildren: folders.length > 0 || pages.length > 0 };
156
- })
157
- )
158
- );
159
-
160
- // Get user data
161
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
162
-
163
- // Check if user is logged in
164
- if (!userData?.isLoggedIn) {
165
- return apiResponseLogger(403, 'Unauthorized');
166
- }
167
-
168
- // Check if user has permission
169
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isAdmin;
170
- if (!isAuthorized) {
171
- return apiResponseLogger(403, 'Unauthorized');
172
- }
173
-
174
- const { id } = yield* readAPIContextJson<{ id: string }>(ctx);
175
-
176
- if (!id) {
177
- return apiResponseLogger(400, 'Invalid form data, id is required');
178
- }
179
-
180
- const { name: folderName } = (yield* sdk.GET.folder(id)) || {};
181
-
182
- if (!folderName) {
183
- return apiResponseLogger(404, 'Folder not found');
184
- }
185
-
186
- const { hasChildren } = yield* checkForChildren(id);
187
-
188
- if (hasChildren) {
189
- return apiResponseLogger(
190
- 400,
191
- 'Folder cannot be deleted because it contains subfolders or pages'
192
- );
193
- }
194
-
195
- yield* Effect.all([
196
- sdk.DELETE.folder(id),
197
- sdk.UPDATE.folderList,
198
- sdk.UPDATE.folderTree,
199
- notify.sendEditorNotification('folder_deleted', folderName),
200
- ]);
201
-
202
- return apiResponseLogger(200, 'Folder deleted successfully');
203
- }).pipe(Notifications.Provide),
204
- OPTIONS: () =>
205
- Effect.try(() => OptionsResponse({ allowedMethods: ['POST', 'PATCH', 'DELETE'] })),
206
- ALL: () => Effect.try(() => AllResponse()),
207
- },
208
- {
209
- cors: { methods: ['POST', 'PATCH', 'DELETE'] },
210
- onError: (error) => {
211
- console.error('Error in folder API:', error);
212
- return createJsonResponse(
213
- { error: 'Internal Server Error' },
214
- {
215
- status: 500,
216
- }
217
- );
218
- },
219
- }
220
- );