UNPKG

@baseplate-dev/react-generators

Version:

React Generators for Baseplate

92 lines 4.1 kB
import { TsCodeUtils, tsImportBuilder } from '@baseplate-dev/core-generators'; import { createGenerator, createGeneratorTask } from '@baseplate-dev/sync'; import { quot } from '@baseplate-dev/utils'; import { z } from 'zod'; import { reactAuthRoutesProvider } from '#src/generators/auth/index.js'; import { reactComponentsImportsProvider } from '#src/generators/core/react-components/index.js'; import { reactRoutesProvider } from '#src/providers/index.js'; import { ADMIN_ADMIN_LAYOUT_GENERATED } from './generated/index.js'; const linkItemSchema = z.object({ type: z.literal('link'), label: z.string().min(1), icon: z.string().min(1), path: z.string().min(1), }); const descriptorSchema = z.object({ links: z.array(linkItemSchema).optional(), requiredRoles: z.array(z.string()), }); const ICON_CATEGORY_REGEX = /^[A-Z][a-z]*/; function getIconImport(iconName) { const category = ICON_CATEGORY_REGEX.exec(iconName); if (!category) { throw new Error(`Invalid icon name: ${iconName}`); } return `react-icons/${category[0].toLowerCase()}`; } export const adminLayoutGenerator = createGenerator({ name: 'admin/admin-layout', generatorFileUrl: import.meta.url, descriptorSchema, buildTasks: ({ links = [], requiredRoles }) => ({ paths: ADMIN_ADMIN_LAYOUT_GENERATED.paths.task, renderers: ADMIN_ADMIN_LAYOUT_GENERATED.renderers.task, route: createGeneratorTask({ dependencies: { renderers: ADMIN_ADMIN_LAYOUT_GENERATED.renderers.provider, reactRoutes: reactRoutesProvider, reactAuth: reactAuthRoutesProvider, }, run({ renderers, reactRoutes, reactAuth }) { return { build: async (builder) => { await builder.apply(renderers.adminRoute.render({ variables: { TPL_ROUTE_PATH: quot(reactRoutes.getRouteFilePath()), TPL_LOGIN_URL_PATH: quot(reactAuth.getLoginUrlPath()), TPL_REQUIRED_ROLES: TsCodeUtils.mergeFragmentsAsArrayPresorted(requiredRoles.toSorted().map((role) => quot(role))), }, })); }, }; }, }), layout: createGeneratorTask({ dependencies: { reactComponentsImports: reactComponentsImportsProvider, renderers: ADMIN_ADMIN_LAYOUT_GENERATED.renderers.provider, }, run({ reactComponentsImports, renderers }) { return { build: async (builder) => { const navEntries = Object.fromEntries(links.map((link) => [ link.path, TsCodeUtils.templateWithImports([ reactComponentsImports.SidebarMenuItem.declaration(), reactComponentsImports.SidebarMenuButton.declaration(), tsImportBuilder(['Link']).from('@tanstack/react-router'), ]) ` <SidebarMenuItem> <SidebarMenuButton asChild> <Link to="${link.path}"> <${TsCodeUtils.importFragment(link.icon, getIconImport(link.icon))} /> <span>${link.label}</span> </Link> </SidebarMenuButton> </SidebarMenuItem> `, ])); await builder.apply(renderers.mainGroup.render({ variables: { appSidebar: { TPL_SIDEBAR_LINKS: TsCodeUtils.mergeFragments(navEntries), }, }, })); }, }; }, }), }), }); //# sourceMappingURL=admin-layout.generator.js.map