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
@@ -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
- );