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,187 +0,0 @@
1
- import { Session } from 'studiocms:auth/lib';
2
- import type { SessionValidationResult, UserSessionData } from 'studiocms:auth/lib/types';
3
- import { logger as _logger } from 'studiocms:logger';
4
- import { SDKCore } from 'studiocms:sdk';
5
- import {
6
- AllResponse,
7
- createEffectAPIRoutes,
8
- createJsonResponse,
9
- Effect,
10
- genLogger,
11
- OptionsResponse,
12
- parseAPIContextJson,
13
- Schema,
14
- } from '@withstudiocms/effect';
15
- import type { APIContext } from 'astro';
16
- import { AuthSessionCookieName } from '#consts';
17
-
18
- /**
19
- * Represents the JSON data structure for verifying a session in the dashboard API.
20
- *
21
- * @remarks
22
- * This class extends a schema definition for type-safe validation.
23
- *
24
- * @property originPathname - The original pathname as a string.
25
- */
26
- export class JsonData extends Schema.Class<JsonData>('JsonData')({
27
- originPathname: Schema.String,
28
- }) {}
29
-
30
- /**
31
- * Represents the response data for verifying a user session on the dashboard API.
32
- *
33
- * @property isLoggedIn - Indicates whether the user is currently logged in.
34
- * @property user - The authenticated user's information, or `null` if not logged in.
35
- * @property user.id - The unique identifier of the user.
36
- * @property user.name - The display name of the user.
37
- * @property user.email - The user's email address, or `null` if not available.
38
- * @property user.avatar - The URL to the user's avatar image, or `null` if not set.
39
- * @property user.username - The user's unique username.
40
- * @property permissionLevel - The user's permission level, as defined in `UserSessionData`.
41
- * @property routes - An object containing route paths relevant to the dashboard.
42
- * @property routes.logout - The route for logging out.
43
- * @property routes.userProfile - The route to the user's profile page.
44
- * @property routes.contentManagement - The route for content management.
45
- * @property routes.dashboardIndex - The route to the dashboard index page.
46
- */
47
- type ResponseData = {
48
- isLoggedIn: boolean;
49
- user: {
50
- id: string;
51
- name: string;
52
- email: string | null;
53
- avatar: string | null;
54
- username: string;
55
- } | null;
56
- permissionLevel: UserSessionData['permissionLevel'];
57
- routes: {
58
- logout: string;
59
- userProfile: string;
60
- contentManagement: string;
61
- dashboardIndex: string;
62
- };
63
- };
64
-
65
- /**
66
- * Builds a JSON HTTP response containing session verification data for the dashboard API.
67
- *
68
- * @param context - The API context containing local route mappings and other request-specific data.
69
- * @param isLoggedIn - Indicates whether the user is currently logged in.
70
- * @param user - The validated user object from the session, or `null` if not logged in.
71
- * @param permissionLevel - The user's permission level within the session.
72
- * @returns A `Response` object with a JSON body containing login status, user info, permission level, and relevant route URLs.
73
- */
74
- const responseBuilder = (
75
- context: APIContext,
76
- isLoggedIn: boolean,
77
- user: SessionValidationResult['user'],
78
- permissionLevel: UserSessionData['permissionLevel']
79
- ) => {
80
- const data: ResponseData = {
81
- isLoggedIn,
82
- user: user
83
- ? {
84
- id: user.id,
85
- name: user.name,
86
- email: user.email || null,
87
- avatar: user.avatar || null,
88
- username: user.username,
89
- }
90
- : null,
91
- permissionLevel: permissionLevel,
92
- routes: {
93
- logout: context.locals.StudioCMS.routeMap.authLinks.logoutAPI,
94
- userProfile: context.locals.StudioCMS.routeMap.mainLinks.userProfile,
95
- contentManagement: context.locals.StudioCMS.routeMap.mainLinks.contentManagement,
96
- dashboardIndex: context.locals.StudioCMS.routeMap.mainLinks.dashboardIndex,
97
- },
98
- };
99
-
100
- return createJsonResponse(data);
101
- };
102
-
103
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
104
- {
105
- POST: (ctx) =>
106
- genLogger('studiocms/routes/api/dashboard/verify-session.POST')(function* () {
107
- const [ses, sdk] = yield* Effect.all([Session, SDKCore]);
108
-
109
- const logger = _logger.fork('studiocms:runtime:api:verify-session');
110
-
111
- const { cookies } = ctx;
112
-
113
- const { originPathname } = yield* parseAPIContextJson(ctx, JsonData);
114
-
115
- const sessionToken = cookies.get(AuthSessionCookieName)?.value ?? null;
116
-
117
- if (!sessionToken) {
118
- logger.info(
119
- `No session token found in cookies, returning unknown session status. Origin: ${originPathname}`
120
- );
121
- return responseBuilder(ctx, false, null, 'unknown');
122
- }
123
-
124
- const { session, user } = yield* ses.validateSessionToken(sessionToken);
125
-
126
- if (session === null) {
127
- yield* ses.deleteSessionTokenCookie(ctx);
128
- logger.info(
129
- `Session token is invalid or expired, deleting cookie. Origin: ${originPathname}`
130
- );
131
- return responseBuilder(ctx, false, null, 'unknown');
132
- }
133
-
134
- if (!user || user === null) {
135
- logger.info(
136
- `No user found for session token, returning unknown session status. Origin: ${originPathname}`
137
- );
138
- return responseBuilder(ctx, false, null, 'unknown');
139
- }
140
-
141
- const result = yield* sdk.AUTH.permission.currentStatus(user.id);
142
-
143
- if (!result) {
144
- logger.error(
145
- `Failed to retrieve permission status for user ${user.id}, returning unknown session status. Origin: ${originPathname}`
146
- );
147
- return responseBuilder(ctx, true, user, 'unknown');
148
- }
149
-
150
- let permissionLevel: UserSessionData['permissionLevel'] = 'unknown';
151
-
152
- switch (result.rank) {
153
- case 'owner':
154
- permissionLevel = 'owner';
155
- break;
156
- case 'admin':
157
- permissionLevel = 'admin';
158
- break;
159
- case 'editor':
160
- permissionLevel = 'editor';
161
- break;
162
- case 'visitor':
163
- permissionLevel = 'visitor';
164
- break;
165
- default:
166
- permissionLevel = 'unknown';
167
- break;
168
- }
169
-
170
- return responseBuilder(ctx, true, user, permissionLevel);
171
- }),
172
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
173
- ALL: () => Effect.try(() => AllResponse()),
174
- },
175
- {
176
- cors: { methods: ['POST', 'OPTIONS'] },
177
- onError: (error) => {
178
- console.error('API Error:', error);
179
- return createJsonResponse(
180
- { error: 'Internal Server Error' },
181
- {
182
- status: 500,
183
- }
184
- );
185
- },
186
- }
187
- );
@@ -1,15 +0,0 @@
1
- import { Schema } from 'effect';
2
- import { createRestRouter, type RouteRegistry } from '#frontend/utils/rest-router.js';
3
- import { dbStudioRoute } from './_routes/db-studio.js';
4
- import { storageRoute } from './_routes/storage.js';
5
-
6
- const registry: RouteRegistry = {
7
- 'db-studio': dbStudioRoute,
8
- storage: storageRoute,
9
- };
10
-
11
- export const ALL = createRestRouter(
12
- 'studiocms:integrations',
13
- Schema.Literal('db-studio', 'storage'),
14
- registry
15
- );
@@ -1,173 +0,0 @@
1
- import config, { developerConfig } from 'studiocms:config';
2
- import {
3
- AllResponse,
4
- CMSLogger,
5
- createEffectAPIRoutes,
6
- createJsonResponse,
7
- genLogger,
8
- type LoggerLevel,
9
- OptionsResponse,
10
- } from '@withstudiocms/effect';
11
- import { Data, Effect } from 'effect';
12
- import { type EndpointRoute, pathRouter, type SubPathRouter } from '#frontend/utils/rest-router.js';
13
- import { type BaseDriver, type DbQueryRequest, getDriver } from '#toolbar/db-studio';
14
-
15
- export class DriverError extends Data.TaggedError('DriverError')<{ message: string }> {}
16
-
17
- let driver: BaseDriver | undefined;
18
-
19
- const useDriverErrorPromise = <T>(_try: () => Promise<T>) =>
20
- Effect.tryPromise({
21
- try: _try,
22
- catch: (error) =>
23
- new DriverError({ message: error instanceof Error ? error.message : String(error) }),
24
- });
25
-
26
- const getDriverInstance = Effect.fn('getDriverInstance')(function* () {
27
- // Return existing driver if already initialized
28
- if (driver) return driver;
29
-
30
- // Attempt to get and initialize the driver
31
- driver = yield* useDriverErrorPromise(() => getDriver()).pipe(
32
- Effect.tap((drv) => useDriverErrorPromise(() => drv.init()))
33
- );
34
-
35
- // If driver is still undefined, return an error
36
- if (!driver) {
37
- return yield* new DriverError({ message: 'Failed to get database driver' });
38
- }
39
-
40
- // Return the initialized driver
41
- return driver;
42
- });
43
-
44
- const parseLogLevel = (
45
- level: 'All' | 'Fatal' | 'Error' | 'Warning' | 'Info' | 'Debug' | 'Trace' | 'None'
46
- ): LoggerLevel => {
47
- switch (level) {
48
- case 'Info':
49
- return 'info';
50
- case 'Warning':
51
- return 'warn';
52
- case 'Error':
53
- return 'error';
54
- case 'All':
55
- case 'Fatal':
56
- case 'Debug':
57
- case 'Trace':
58
- return 'debug';
59
- case 'None':
60
- return 'silent';
61
- }
62
- };
63
-
64
- const jsonResponse = (data: unknown, status = 200): Response =>
65
- new Response(JSON.stringify(data), {
66
- headers: { 'Content-Type': 'application/json' },
67
- status,
68
- });
69
-
70
- const dbStudioSubRouter: SubPathRouter = {
71
- query: (_id: string) =>
72
- createEffectAPIRoutes(
73
- {
74
- POST: ({ request, locals }) =>
75
- genLogger('studiocms:integrations:db-studio:query:POST')(function* () {
76
- // Determine if we are in development mode
77
- const isDev = import.meta.env.DEV;
78
-
79
- const logLevel = parseLogLevel(config.logLevel);
80
-
81
- const log = new CMSLogger({ level: logLevel }, 'studiocms:database/studio');
82
-
83
- // Check if demo mode is enabled
84
- if (developerConfig.demoMode !== false) {
85
- return createJsonResponse(
86
- { error: 'Demo mode is enabled, this action is not allowed.' },
87
- { status: 403 }
88
- );
89
- }
90
-
91
- // Security check: only allow access in the following cases
92
- // 1. In development mode
93
- // 2. In production, only if the user is an owner
94
- if (!isDev && !locals.StudioCMS.security?.userPermissionLevel.isOwner) {
95
- return createJsonResponse({ error: 'Forbidden' }, { status: 403 });
96
- }
97
-
98
- // Parse the request body
99
- const body: DbQueryRequest = yield* Effect.tryPromise({
100
- try: () => request.json(),
101
- catch: (error) =>
102
- new DriverError({
103
- message: `Invalid JSON body: ${error instanceof Error ? error.message : String(error)}`,
104
- }),
105
- });
106
-
107
- // Get the database driver instance
108
- const driver = yield* getDriverInstance();
109
-
110
- log.debug(`Received ${body.type} request`);
111
-
112
- try {
113
- if (body.type === 'query') {
114
- const r = yield* useDriverErrorPromise(() => driver.query(body.statement));
115
- return jsonResponse({
116
- type: body.type,
117
- id: body.id,
118
- data: r,
119
- });
120
- }
121
-
122
- const r = yield* useDriverErrorPromise(() => driver.batch(body.statements));
123
-
124
- log.debug(`${body.type} executed with ${r.length} results`);
125
-
126
- return jsonResponse({
127
- type: body.type,
128
- id: body.id,
129
- data: r,
130
- });
131
- } catch (e) {
132
- log.error(
133
- `Error handling ${body.type} request with ID ${body.id}: ${(e as Error).message}`
134
- );
135
- return jsonResponse(
136
- {
137
- type: body.type,
138
- id: body.id,
139
- error: (e as Error).message,
140
- },
141
- 500
142
- );
143
- }
144
- }),
145
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST', 'OPTIONS'] })),
146
- ALL: () => Effect.try(() => AllResponse()),
147
- },
148
- {
149
- cors: { methods: ['POST', 'OPTIONS'] },
150
- onError: (error) => {
151
- console.error('API Error:', error);
152
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
153
- },
154
- }
155
- ),
156
- };
157
-
158
- export const dbStudioRoute: EndpointRoute = {
159
- __idType: 'string',
160
- __index: createEffectAPIRoutes(
161
- {
162
- ALL: () => Effect.try(() => AllResponse()),
163
- },
164
- {
165
- cors: {},
166
- onError: (error) => {
167
- console.error('API Error:', error);
168
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
169
- },
170
- }
171
- ),
172
- id: (id: string) => pathRouter(id, dbStudioSubRouter),
173
- };
@@ -1,88 +0,0 @@
1
- import APIServiceModule from 'studiocms:storage-manager/module';
2
- import {
3
- AllResponse,
4
- createEffectAPIRoutes,
5
- createJsonResponse,
6
- OptionsResponse,
7
- } from '@withstudiocms/effect';
8
- import type { APIContext } from 'astro';
9
- import { Effect } from 'effect';
10
- import { type EndpointRoute, pathRouter, type SubPathRouter } from '#frontend/utils/rest-router.js';
11
- import APICore from '#storage-manager/core/api-core';
12
- import AstroContextDriver from '#storage-manager/core/astro-context';
13
- import UrlMappingDatabase from '#storage-manager/core/database';
14
- import UrlMappingService from '#storage-manager/core/url-mapping';
15
-
16
- let apiCore: APICore<APIContext, Response>;
17
-
18
- /**
19
- * Retrieves the singleton instance of the APICore.
20
- *
21
- * This function initializes the APICore instance if it hasn't been created yet,
22
- * setting up the necessary context driver, URL mapping service, and API service module.
23
- *
24
- * @returns The singleton APICore instance.
25
- */
26
- function getAPICore() {
27
- if (apiCore) {
28
- return apiCore;
29
- }
30
-
31
- // Instantiate the Astro context driver
32
- const astroContextDriver = new AstroContextDriver();
33
-
34
- // Instantiate the database
35
- const database = new UrlMappingDatabase();
36
-
37
- // Instantiate the URL mapping service
38
- const urlMappingService = new UrlMappingService(database);
39
-
40
- // Instantiate the API service module
41
- const apiService = new APIServiceModule(astroContextDriver, urlMappingService);
42
-
43
- // Instantiate the API core
44
- apiCore = new APICore({
45
- driver: astroContextDriver,
46
- urlMappingService: urlMappingService,
47
- storageDriver: apiService,
48
- });
49
-
50
- return apiCore;
51
- }
52
-
53
- const storageSubRouter: SubPathRouter = {
54
- manager: (_id: string) =>
55
- createEffectAPIRoutes(
56
- {
57
- POST: (ctx) => Effect.tryPromise(async () => getAPICore().getPOST('locals')(ctx)),
58
- PUT: (ctx) => Effect.tryPromise(async () => getAPICore().getPUT('locals')(ctx)),
59
- OPTIONS: () =>
60
- Effect.try(() => OptionsResponse({ allowedMethods: ['POST', 'PUT', 'OPTIONS'] })),
61
- ALL: () => Effect.try(() => AllResponse()),
62
- },
63
- {
64
- cors: { methods: ['POST', 'PUT', 'OPTIONS'] },
65
- onError: (error) => {
66
- console.error('API Error:', error);
67
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
68
- },
69
- }
70
- ),
71
- };
72
-
73
- export const storageRoute: EndpointRoute = {
74
- __idType: 'string',
75
- __index: createEffectAPIRoutes(
76
- {
77
- ALL: () => Effect.try(() => AllResponse()),
78
- },
79
- {
80
- cors: {},
81
- onError: (error) => {
82
- console.error('API Error:', error);
83
- return createJsonResponse({ error: 'Something went wrong' }, { status: 500 });
84
- },
85
- }
86
- ),
87
- id: (id: string) => pathRouter(id, storageSubRouter),
88
- };
@@ -1,74 +0,0 @@
1
- ---
2
- export const partial = true;
3
-
4
- import pluginsList from 'studiocms:plugins';
5
- import { AstroError } from 'astro/errors';
6
-
7
- type RawJsonData = {
8
- content: string | undefined;
9
- editor: string;
10
- };
11
-
12
- type EditorComponent = (_props?: {
13
- content?: string | null | undefined;
14
- // biome-ignore lint/suspicious/noExplicitAny: This is a valid use case for explicit any.
15
- }) => any;
16
-
17
- type EditorComponentItem = {
18
- identifier: string;
19
- Component: EditorComponent;
20
- };
21
-
22
- async function load() {
23
- const jsonData: RawJsonData | undefined = await Astro.request.json();
24
-
25
- const pageTypeComponents: EditorComponentItem[] = [];
26
-
27
- for (const { pageTypes } of pluginsList) {
28
- if (!pageTypes) continue;
29
-
30
- for (const { identifier, pageContentComponent } of pageTypes) {
31
- if (!pageContentComponent) continue;
32
-
33
- pageTypeComponents.push({
34
- identifier,
35
- Component: (await import(/* @vite-ignore */ pageContentComponent)).default,
36
- });
37
- }
38
- }
39
-
40
- let Editor: EditorComponentItem | undefined;
41
-
42
- Editor = pageTypeComponents.find((ed) => ed.identifier === jsonData?.editor);
43
-
44
- if (!Editor) {
45
- const MarkdownEditor = pageTypeComponents.find(
46
- (editor) => editor.identifier === 'studiocms/markdown'
47
- );
48
- if (MarkdownEditor) {
49
- Editor = MarkdownEditor;
50
- } else {
51
- throw new AstroError(
52
- `No editor found for identifier: ${jsonData?.editor}`,
53
- 'StudioCMSDashboardPartialEditorError - No editor found'
54
- );
55
- }
56
- }
57
-
58
- if (jsonData?.content) {
59
- return {
60
- content: jsonData.content,
61
- ActiveEditor: Editor.Component,
62
- };
63
- }
64
-
65
- return {
66
- content: 'No content to display',
67
- ActiveEditor: Editor.Component,
68
- };
69
- }
70
-
71
- const { content, ActiveEditor } = await load();
72
- ---
73
-
74
- <ActiveEditor content={content} />
@@ -1,39 +0,0 @@
1
- ---
2
- export const partial = true;
3
-
4
- import { pipe } from '@withstudiocms/effect';
5
- import { parseMarkdown } from '#utils/tinyMDParser';
6
-
7
- type FullJsonData = { content: string | undefined };
8
-
9
- const html = pipe(
10
- {
11
- queryParam: Astro.url.searchParams.get('content'),
12
- preQuery: Astro.url.searchParams.get('preload-content'),
13
- astroJsonData: await (async () => {
14
- const ct = Astro.request.headers.get('content-type') ?? '';
15
- if (!ct.toLowerCase().includes('application/json')) return undefined;
16
- try {
17
- return (await Astro.request.json()) as FullJsonData;
18
- } catch {
19
- return undefined;
20
- }
21
- })(),
22
- },
23
- (data) => {
24
- const { queryParam, preQuery, astroJsonData } = data;
25
- if (astroJsonData && astroJsonData.content !== undefined) {
26
- return astroJsonData.content;
27
- }
28
- if (queryParam && queryParam !== 'null') {
29
- return queryParam;
30
- }
31
- if (preQuery && preQuery !== 'null') {
32
- return preQuery;
33
- }
34
- return 'No content to display';
35
- },
36
- (content) => parseMarkdown(content)
37
- );
38
- ---
39
- <Fragment set:html={html} />
@@ -1,43 +0,0 @@
1
- ---
2
- export const partial = true;
3
-
4
- import type { AvailablePermissionRanks } from '@withstudiocms/auth-kit/types';
5
- import UserListItem from '../../../components/dashboard/user-mgmt/UserListItem.astro';
6
-
7
- type PermissionsData = {
8
- user: string;
9
- rank: AvailablePermissionRanks;
10
- };
11
-
12
- type Users = {
13
- id: string;
14
- name: string;
15
- email: string | null;
16
- avatar: string | null;
17
- username: string;
18
- permissionsData: PermissionsData | undefined;
19
- };
20
-
21
- type FullJsonData = {
22
- users: Users[];
23
- searchQuery?: string;
24
- };
25
-
26
- async function setData() {
27
- const jsonData: FullJsonData | undefined = await Astro.request.json();
28
-
29
- if (jsonData) return jsonData;
30
-
31
- return 'No Users to display';
32
- }
33
-
34
- const usersData = await setData();
35
- ---
36
-
37
- {
38
- typeof usersData !== "string"
39
- ? usersData.users.map((user) => (
40
- <UserListItem user={user} searchQuery={usersData.searchQuery} />
41
- ))
42
- : usersData
43
- }
@@ -1,59 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { SDKCore } from 'studiocms:sdk';
3
- import { Effect, genLogger } from '@withstudiocms/effect';
4
- import type { APIContext } from 'astro';
5
-
6
- /**
7
- * Extracts the Bearer authentication token from the `Authorization` header of the given API context's request.
8
- *
9
- * This function attempts to retrieve the `Authorization` header from the request, and if present,
10
- * parses it to extract the token part of a Bearer token. If the header is missing, malformed, or does not
11
- * use the Bearer scheme, the function returns `null`.
12
- *
13
- * @param context - The API context containing the request object with headers.
14
- * @returns The extracted Bearer token as a string, or `null` if not found or invalid.
15
- */
16
- const getAuthTokenFromHeader = (context: APIContext) =>
17
- genLogger('routes/rest/utils/auth-token/getAuthTokenFromHeader')(function* () {
18
- const authTokenData = yield* Effect.try(() => context.request.headers.get('Authorization'));
19
-
20
- if (!authTokenData) {
21
- return null;
22
- }
23
-
24
- const parts = authTokenData.split(' ');
25
-
26
- if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') {
27
- return null;
28
- }
29
-
30
- return parts[1];
31
- });
32
-
33
- /**
34
- * Verifies the authentication token from the request header in the given API context.
35
- *
36
- * This generator function attempts to extract an authentication token from the request header,
37
- * verifies it using the SDK's REST API, and returns the associated user if verification succeeds.
38
- * If the token is missing or invalid, it returns a 401 Unauthorized API response.
39
- *
40
- * @param context - The API context containing the request information.
41
- * @returns The verified user object if authentication succeeds, or a 401 Unauthorized response if it fails.
42
- */
43
- export const verifyAuthTokenFromHeader = (context: APIContext) =>
44
- genLogger('routes/rest/utils/auth-token/verifyAuthTokenFromHeader')(function* () {
45
- const sdk = yield* SDKCore;
46
-
47
- const authToken = yield* getAuthTokenFromHeader(context);
48
-
49
- if (!authToken) {
50
- return apiResponseLogger(401, 'Unauthorized');
51
- }
52
-
53
- const user = yield* sdk.REST_API.tokens.verify(authToken);
54
-
55
- if (!user) {
56
- return apiResponseLogger(401, 'Unauthorized');
57
- }
58
- return user;
59
- });