everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 6.18 kB
Source Map (JSON)
{"version":3,"file":"sidebar.cjs","names":[],"sources":["../src/sidebar.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { RuntimeConfig, SidebarItem } from \"./types\";\n\nconst ICON_IMPORTS: Record<string, string> = {\n Home: \"lucide-react\",\n Globe: \"lucide-react\",\n FolderKanban: \"lucide-react\",\n Building2: \"lucide-react\",\n Settings: \"lucide-react\",\n User: \"lucide-react\",\n Users: \"lucide-react\",\n Shield: \"lucide-react\",\n LayoutDashboard: \"lucide-react\",\n CreditCard: \"lucide-react\",\n Bell: \"lucide-react\",\n Key: \"lucide-react\",\n FileText: \"lucide-react\",\n Database: \"lucide-react\",\n Activity: \"lucide-react\",\n BarChart3: \"lucide-react\",\n Zap: \"lucide-react\",\n Terminal: \"lucide-react\",\n Code: \"lucide-react\",\n Package: \"lucide-react\",\n Store: \"lucide-react\",\n ShoppingBag: \"lucide-react\",\n Wallet: \"lucide-react\",\n Coins: \"lucide-react\",\n Plug: \"lucide-react\",\n Link: \"lucide-react\",\n ExternalLink: \"lucide-react\",\n Puzzle: \"lucide-react\",\n Layers: \"lucide-react\",\n Grid3X3: \"lucide-react\",\n AppWindow: \"lucide-react\",\n};\n\nfunction resolveIconModule(iconName: string): string {\n if (ICON_IMPORTS[iconName]) return ICON_IMPORTS[iconName];\n return \"lucide-react\";\n}\n\nfunction collectIconImports(items: SidebarItem[]): Map<string, Set<string>> {\n const moduleMap = new Map<string, Set<string>>();\n for (const item of items) {\n const module = resolveIconModule(item.icon);\n if (!moduleMap.has(module)) moduleMap.set(module, new Set());\n moduleMap.get(module)!.add(item.icon);\n }\n return moduleMap;\n}\n\nexport function generatePluginSidebarContent(runtimeConfig: RuntimeConfig): string {\n const coreItems: SidebarItem[] = [{ icon: \"Home\", label: \"home\", to: \"/\", roleRequired: \"anon\" }];\n\n if (runtimeConfig.auth?.sidebar) {\n for (const item of runtimeConfig.auth.sidebar) {\n coreItems.push({\n ...item,\n to: item.to ?? \"/auth\",\n roleRequired: item.roleRequired ?? \"member\",\n });\n }\n }\n\n const pluginItems: SidebarItem[] = [];\n if (runtimeConfig.plugins) {\n for (const [key, entry] of Object.entries(runtimeConfig.plugins)) {\n const sidebar = entry.sidebar;\n if (!sidebar) continue;\n for (const item of sidebar) {\n pluginItems.push({\n ...item,\n to: item.to ?? `/${key}`,\n roleRequired: item.roleRequired ?? \"member\",\n });\n }\n }\n }\n\n const allItems = [...coreItems, ...pluginItems];\n const moduleMap = collectIconImports(allItems);\n\n const importLines: string[] = [];\n for (const [module, icons] of moduleMap) {\n const iconList = [...icons].join(\", \");\n importLines.push(`import { ${iconList} } from \"${module}\";`);\n }\n\n const itemsCode = allItems\n .map(\n (item) =>\n ` { icon: ${item.icon}, label: \"${item.label}\", to: \"${item.to}\" as const, roleRequired: \"${item.roleRequired}\" as const },`,\n )\n .join(\"\\n\");\n\n return `// Auto-generated by bos sync/pluginAdd/pluginRemove. Do not edit.\n${importLines.join(\"\\n\")}\n\nexport type SidebarRole = \"anon\" | \"member\" | \"admin\";\n\nexport interface SidebarItem {\n icon: React.ComponentType<{ className?: string }>;\n label: string;\n to: string;\n roleRequired: SidebarRole;\n}\n\nexport const pluginSidebarItems: SidebarItem[] = [\n${itemsCode}\n];\n`;\n}\n\nexport function writePluginSidebarGen(configDir: string, runtimeConfig: RuntimeConfig): string {\n const outputPath = join(configDir, \"ui/src/lib/plugin-sidebar.gen.ts\");\n\n const content = generatePluginSidebarContent(runtimeConfig);\n\n const outputDir = dirname(outputPath);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n let existingContent: string | null = null;\n try {\n existingContent = existsSync(outputPath)\n ? // eslint-disable-next-line no-restricted-syntax\n readFileSync(outputPath, \"utf-8\")\n : null;\n } catch {\n // file doesn't exist yet\n }\n\n if (existingContent === content) return outputPath;\n\n writeFileSync(outputPath, content);\n return outputPath;\n}\n"],"mappings":";;;;;AAIA,MAAM,eAAuC;CAC3C,MAAM;CACN,OAAO;CACP,cAAc;CACd,WAAW;CACX,UAAU;CACV,MAAM;CACN,OAAO;CACP,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,MAAM;CACN,KAAK;CACL,UAAU;CACV,UAAU;CACV,UAAU;CACV,WAAW;CACX,KAAK;CACL,UAAU;CACV,MAAM;CACN,SAAS;CACT,OAAO;CACP,aAAa;CACb,QAAQ;CACR,OAAO;CACP,MAAM;CACN,MAAM;CACN,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,WAAW;CACZ;AAED,SAAS,kBAAkB,UAA0B;AACnD,KAAI,aAAa,UAAW,QAAO,aAAa;AAChD,QAAO;;AAGT,SAAS,mBAAmB,OAAgD;CAC1E,MAAM,4BAAY,IAAI,KAA0B;AAChD,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,SAAS,kBAAkB,KAAK,KAAK;AAC3C,MAAI,CAAC,UAAU,IAAI,OAAO,CAAE,WAAU,IAAI,wBAAQ,IAAI,KAAK,CAAC;AAC5D,YAAU,IAAI,OAAO,CAAE,IAAI,KAAK,KAAK;;AAEvC,QAAO;;AAGT,SAAgB,6BAA6B,eAAsC;CACjF,MAAM,YAA2B,CAAC;EAAE,MAAM;EAAQ,OAAO;EAAQ,IAAI;EAAK,cAAc;EAAQ,CAAC;AAEjG,KAAI,cAAc,MAAM,QACtB,MAAK,MAAM,QAAQ,cAAc,KAAK,QACpC,WAAU,KAAK;EACb,GAAG;EACH,IAAI,KAAK,MAAM;EACf,cAAc,KAAK,gBAAgB;EACpC,CAAC;CAIN,MAAM,cAA6B,EAAE;AACrC,KAAI,cAAc,QAChB,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,cAAc,QAAQ,EAAE;EAChE,MAAM,UAAU,MAAM;AACtB,MAAI,CAAC,QAAS;AACd,OAAK,MAAM,QAAQ,QACjB,aAAY,KAAK;GACf,GAAG;GACH,IAAI,KAAK,MAAM,IAAI;GACnB,cAAc,KAAK,gBAAgB;GACpC,CAAC;;CAKR,MAAM,WAAW,CAAC,GAAG,WAAW,GAAG,YAAY;CAC/C,MAAM,YAAY,mBAAmB,SAAS;CAE9C,MAAM,cAAwB,EAAE;AAChC,MAAK,MAAM,CAAC,QAAQ,UAAU,WAAW;EACvC,MAAM,WAAW,CAAC,GAAG,MAAM,CAAC,KAAK,KAAK;AACtC,cAAY,KAAK,YAAY,SAAS,WAAW,OAAO,IAAI;;CAG9D,MAAM,YAAY,SACf,KACE,SACC,aAAa,KAAK,KAAK,YAAY,KAAK,MAAM,UAAU,KAAK,GAAG,6BAA6B,KAAK,aAAa,eAClH,CACA,KAAK,KAAK;AAEb,QAAO;EACP,YAAY,KAAK,KAAK,CAAC;;;;;;;;;;;;EAYvB,UAAU;;;;AAKZ,SAAgB,sBAAsB,WAAmB,eAAsC;CAC7F,MAAM,iCAAkB,WAAW,mCAAmC;CAEtE,MAAM,UAAU,6BAA6B,cAAc;CAE3D,MAAM,mCAAoB,WAAW;AACrC,KAAI,yBAAY,UAAU,CACxB,wBAAU,WAAW,EAAE,WAAW,MAAM,CAAC;CAG3C,IAAI,kBAAiC;AACrC,KAAI;AACF,4CAA6B,WAAW,6BAEvB,YAAY,QAAQ,GACjC;SACE;AAIR,KAAI,oBAAoB,QAAS,QAAO;AAExC,4BAAc,YAAY,QAAQ;AAClC,QAAO"}