UNPKG

studiocms

Version:

Astro Native CMS for AstroDB. Built from the ground up by the Astro community.

278 lines (277 loc) 9.89 kB
import { z } from "astro/zod"; import { pluginTranslationsSchema } from "./i18n.js"; import { astroIntegrationSchema, DashboardPageSchema, FrontendNavigationLinksSchema, PageTypesSchema, SettingsPageSchema } from "./shared.js"; const ComponentRenderAugmentSchema = z.object({ type: z.literal("component"), id: z.string(), components: z.record(z.string()) }); const PrefixRenderAugmentSchema = ComponentRenderAugmentSchema.extend({ type: z.literal("prefix"), html: z.string() }); const SuffixRenderAugmentSchema = ComponentRenderAugmentSchema.extend({ type: z.literal("suffix"), html: z.string() }); const RenderAugmentSchema = z.union([ ComponentRenderAugmentSchema, PrefixRenderAugmentSchema, SuffixRenderAugmentSchema ]); const RenderAugmentsSchema = z.array(RenderAugmentSchema).optional(); const StudioCMSSanitizeOptionsSchema = z.object({ /** An Array of strings indicating elements that the sanitizer should not remove. All elements not in the array will be dropped. */ allowElements: z.array(z.string()).optional(), /** An Array of strings indicating elements that the sanitizer should remove. Children will be kept. */ blockElements: z.array(z.string()).optional(), /** An Array of strings indicating elements (including nested elements) that the sanitizer should remove. */ dropElements: z.array(z.string()).optional(), /** An object where each key is the attribute name and the value is an array of allowed tag names. Matching attributes will not be removed. All attributes that are not in the array will be dropped. */ allowAttributes: z.record(z.array(z.string())).optional(), /** An object where each key is the attribute name and the value is an array of dropped tag names. Matching attributes will be removed. */ dropAttributes: z.record(z.array(z.string())).optional(), /** A boolean value to remove components and their children. If set to true, components will be subject to built-in and custom configuration checks (and will be retained or dropped based on those checks). Default is `false`. */ allowComponents: z.boolean().optional(), /** A boolean value to remove custom elements and their children. If set to true, custom elements will be subject to built-in and custom configuration checks (and will be retained or dropped based on those checks). Default is `false` */ allowCustomElements: z.boolean().optional(), /** A boolean value to remove HTML comments. Set to true in order to keep comments. Default is `false`. */ allowComments: z.boolean().optional() }).optional(); const dashboardPagesArray = z.array(DashboardPageSchema).optional(); const astroIntegrationLoggerSchema = z.custom(); const SafePluginListItemSchema = z.object({ /** * Identifier of the plugin from the package.json */ identifier: z.string(), /** * Label of the plugin to be displayed in the StudioCMS Dashboard */ name: z.string(), /** * If this exists, the plugin will have its own setting page */ settingsPage: SettingsPageSchema.optional(), /** * Navigation Links for use with the `@studiocms/frontend` package to display links in the frontend */ frontendNavigationLinks: FrontendNavigationLinksSchema.optional(), /** * Page Type definition. If this is present, the plugin wants to be able to modify the page creation process */ pageTypes: PageTypesSchema.optional() }); const SafePluginListSchema = z.array(SafePluginListItemSchema); const SitemapConfigSchema = z.object({ /** * If this is true, the plugin will enable the Sitemap */ triggerSitemap: z.boolean().optional(), /** * Allows the plugin to add sitemap endpoints */ sitemaps: z.array( z.object({ /** * The name of the plugin */ pluginName: z.string(), /** * The path to the sitemap XML file */ sitemapXMLEndpointPath: z.string().or(z.instanceof(URL)) }) ).optional() }); const DashboardConfigSchema = z.object({ /** * The translations for the plugin in the following format: * * ```json * { * "en": { * "component1": { * "title": "Title", * "description": "Description" * }, * "component2": { * "title": "Title", * "description": "Description" * } * }, * "fr": { * "component1": { * "title": "Titre", * "description": "Description" * }, * "component2": { * "title": "Titre", * "description": "Description" * } * } * } * ``` */ translations: pluginTranslationsSchema, /** * Allows the plugin to add custom dashboard grid items */ dashboardGridItems: z.custom().optional(), /** * Dashboard Pages for the plugin */ dashboardPages: z.object({ /** * Pages for the user role * * These are shown in the "Dashboard" section of the dashboard sidebar */ user: dashboardPagesArray, /** * Pages for the editor role * * These are shown in the "Admin" section of the dashboard sidebar */ admin: dashboardPagesArray }).optional(), /** * If this exists, the plugin will have its own setting page */ settingsPage: SettingsPageSchema }); const FrontendConfigSchema = z.object({ /** * Navigation Links for use with the `@studiocms/frontend` package to display links in the frontend */ frontendNavigationLinks: FrontendNavigationLinksSchema }); const RenderingConfigSchema = z.object({ /** * Page Type definition. If this is present, the plugin wants to be able to modify the page creation process */ pageTypes: PageTypesSchema, /** * Augments to modify component rendering * * When adding new augments, please ensure that the `id` field is unique across all augments. * * the `id` field is also used to identify augment translations from the plugin translations * schema, below is an example of how to add augment translations: * * ```json * { * "en": { * "augments": { * "augment-id": "This is the augment text" * } * }, * "fr": { * "augments": { * "augment-id": "Ceci est le texte d'augmentation" * } * } * } * ``` */ augments: RenderAugmentsSchema }); const ImageServiceConfigSchema = z.object({ imageService: z.object({ /** * Identifier used for the `preferredImageService` setting on StudioCMS */ identifier: z.string(), /** * The Service Path to the file that contains your service, the service must be exported as a default export. * * For an example of a service, checkout `/src/imageServices/cloudinary-js-service.ts` and its plugin `/src/imageServices/cloudinary-js.ts` within the StudioCMS package on GitHub. */ servicePath: z.string().or(z.instanceof(URL)) }).optional() }); const AuthServiceConfigSchema = z.object({ oAuthProvider: z.object({ /** * The name of the OAuth provider, e.g., 'google', 'github', etc. */ name: z.string(), /** * The formatted name of the OAuth provider, e.g., 'Google', 'GitHub', etc. */ formattedName: z.string(), /** * The inline SVG image for the OAuth provider button. * This should be a string containing the SVG markup. * * Note: Please ensure the class `oauth-logo` is included in the SVG for styling purposes. * * @example * `<svg width="24px" height="24px" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg" class="oauth-logo">...</svg>`, */ svg: z.string(), /** * The path to the endpoint file that handles the OAuth authentication for this provider. * This should be a string or URL pointing to the endpoint ts file. * * Note: The endpoint should export two functions: * - `initSession`: Initializes the session for the OAuth provider. * - `initCallback`: Handles the callback from the OAuth provider after authentication. * * @example * `/src/auth/providers/google.ts` */ endpointPath: z.string(), /** * Required environment variables for the OAuth provider. * This is an optional array of strings that specifies which environment variables are required for the OAuth provider to function correctly. * If specified, these variables must be set in the environment for the OAuth provider to work. */ requiredEnvVariables: z.array(z.string()).optional() }) }); const baseHookSchema = z.object({ logger: astroIntegrationLoggerSchema }); const astroConfigHookSchema = baseHookSchema.extend({ addIntegrations: z.function( z.tuple([z.union([astroIntegrationSchema, z.array(astroIntegrationSchema)])]), z.void() ) }); const setSitemapFn = z.function(z.tuple([SitemapConfigSchema]), z.void()); const setDashboardFn = z.function(z.tuple([DashboardConfigSchema]), z.void()); const setFrontendFn = z.function(z.tuple([FrontendConfigSchema]), z.void()); const setRenderingFn = z.function(z.tuple([RenderingConfigSchema]), z.void()); const setImageServiceFn = z.function(z.tuple([ImageServiceConfigSchema]), z.void()); const setAuthServiceFn = z.function(z.tuple([AuthServiceConfigSchema]), z.void()); const studiocmsConfigHookSchema = baseHookSchema.extend({ setSitemap: setSitemapFn, setDashboard: setDashboardFn, setFrontend: setFrontendFn, setRendering: setRenderingFn, setImageService: setImageServiceFn, setAuthService: setAuthServiceFn }); const StudioCMSPluginSchemaInternal = z.array(z.custom()); const exposePluginsFn = z.function(z.tuple([StudioCMSPluginSchemaInternal.optional()]), z.void()); const studiocmsPluginAstroHook = z.object({ exposePlugins: exposePluginsFn }); function definePlugin(options) { return options; } export { RenderAugmentSchema, RenderAugmentsSchema, SafePluginListItemSchema, SafePluginListSchema, StudioCMSSanitizeOptionsSchema, definePlugin };