@fumadocs/cli 1.6.1 → 1.6.2
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.
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -66,7 +66,7 @@ async function runTree(args) {
|
|
|
66
66
|
}
|
|
67
67
|
//#endregion
|
|
68
68
|
//#region package.json
|
|
69
|
-
var version = "1.6.
|
|
69
|
+
var version = "1.6.2";
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/commands/customise.ts
|
|
72
72
|
async function customise(config, connector) {
|
|
@@ -475,9 +475,9 @@ async function add(input, connector, config) {
|
|
|
475
475
|
}
|
|
476
476
|
const groups = await Promise.all([
|
|
477
477
|
scan(void 0, "common"),
|
|
478
|
-
scan("
|
|
479
|
-
scan("
|
|
480
|
-
scan("
|
|
478
|
+
scan("sanity", "sanity"),
|
|
479
|
+
scan("openapi", "openapi"),
|
|
480
|
+
scan("api-docs", "api-docs"),
|
|
481
481
|
scan(subRegistry, "ui")
|
|
482
482
|
]);
|
|
483
483
|
spin.stop(picocolors.bold(picocolors.greenBright("registry fetched")));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isCancel","isCancel","packageJson.version"],"sources":["../src/commands/file-tree.ts","../src/utils/file-tree/run-tree.ts","../package.json","../src/commands/customise.ts","../src/commands/add.ts","../src/commands/export-epub.ts","../src/commands/feature.ts","../src/index.ts"],"sourcesContent":["export type JsonTreeNode =\n | {\n type: 'file';\n name: string;\n }\n | {\n type: 'directory';\n name: string;\n contents: JsonTreeNode[];\n }\n | {\n type: 'report';\n }\n | {\n type: 'link';\n name: string;\n };\n\nconst scanned = ['file', 'directory', 'link'];\n\nexport function treeToMdx(input: JsonTreeNode[], noRoot = false): string {\n function toNode(item: JsonTreeNode): string {\n if (item.type === 'file' || item.type === 'link') {\n return `<File name=${JSON.stringify(item.name)} />`;\n }\n\n if (item.type === 'directory') {\n if (item.contents.length === 1 && 'name' in item.contents[0]) {\n const child = item.contents[0];\n\n return toNode({\n ...child,\n name: `${item.name}/${child.name}`,\n });\n }\n\n return `<Folder name=${JSON.stringify(item.name)}>\n${item.contents.map(toNode).filter(Boolean).join('\\n')}\n</Folder>`;\n }\n\n return '';\n }\n\n let children = input.filter((v) => scanned.includes(v.type));\n\n if (noRoot && children.length === 1 && input[0].type === 'directory') {\n children = input[0].contents;\n }\n\n return `<Files>\n${children.map(toNode).filter(Boolean).join('\\n')}\n</Files>`;\n}\n\nexport function treeToJavaScript(\n input: JsonTreeNode[],\n noRoot?: boolean,\n importName = 'fumadocs-ui/components/files',\n): string {\n return `import { File, Files, Folder } from ${JSON.stringify(importName)}\n\nexport default (${treeToMdx(input, noRoot)})`;\n}\n","import { x } from 'tinyexec';\nimport type { JsonTreeNode } from '@/commands/file-tree';\n\nexport async function runTree(args: string): Promise<JsonTreeNode[]> {\n const out = await x('tree', [args, '--gitignore', '--prune', '-J']);\n\n try {\n return JSON.parse(out.stdout) as JsonTreeNode[];\n } catch (e) {\n throw new Error('failed to run `tree` command', {\n cause: e,\n });\n }\n}\n","","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { cancel, group, intro, log, outro, select } from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { parseSourceFile } from '@/codemod';\nimport { frameworks } from '@/project';\nimport type { Target } from '@/commands/add';\nimport { UIRegistries } from '@/commands/shared';\nimport { LoadedConfig } from '@/config';\nimport { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { FumadocsComponentInstaller } from '@/registry/installer';\n\ninterface TargetInfo {\n targets: Target[];\n id: string;\n print?: () => void | Promise<void>;\n}\n\ninterface SlotPrintInfo {\n at: string;\n layoutId: string;\n name: string;\n isPage: boolean;\n uiLibrary: LoadedConfig['uiLibrary'];\n}\n\nexport async function customise(config: LoadedConfig, connector: RegistryConnector) {\n intro(picocolors.bgBlack(picocolors.whiteBright('Customize Fumadocs UI')));\n\n const installer = new FumadocsComponentInstaller(connector, config);\n const subRegistry = UIRegistries[config.uiLibrary];\n const info = await connector.fetchRegistryInfo(subRegistry);\n\n const result = await group(\n {\n layout: (): Promise<TargetInfo | symbol> =>\n select({\n message: 'What do you want to customize?',\n options: [\n {\n label: 'Docs Layout',\n value: {\n id: 'docs',\n targets: [{ subRegistry, name: 'layouts/docs' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/docs', '@/layouts/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/layouts/docs/page'],\n ),\n },\n hint: 'the default docs layout',\n },\n {\n label: 'Notebook Layout',\n value: {\n id: 'notebook',\n targets: [{ subRegistry, name: 'layouts/notebook' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/notebook', '@/layouts/notebook'],\n ['fumadocs-ui/layouts/notebook/page', '@/layouts/notebook/page'],\n ),\n },\n hint: 'a more compact version of docs layout',\n },\n {\n label: 'Flux Layout',\n value: {\n id: 'flux',\n targets: [{ subRegistry, name: 'layouts/flux' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/flux', '@/layouts/flux'],\n ['fumadocs-ui/layouts/flux/page', '@/layouts/flux/page'],\n ),\n },\n hint: 'the experimental variant of docs layout',\n },\n {\n label: 'Glass Layout',\n value: {\n id: 'glass',\n targets: [{ subRegistry, name: 'layouts/glass' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/glass', '@/layouts/glass'],\n ['fumadocs-ui/layouts/glass/page', '@/layouts/glass/page'],\n ),\n },\n hint: 'a docs layout with floating, translucent panels',\n },\n {\n label: 'Home Layout',\n value: {\n id: 'home',\n targets: [{ subRegistry, name: 'layouts/home' }],\n print: () => printLayout(config, ['fumadocs-ui/layouts/home', '@/layouts/home']),\n },\n hint: 'the layout for other non-docs pages',\n },\n ],\n }),\n target: (v): Promise<TargetInfo | symbol> => {\n const selected = v.results.layout!;\n if (selected.id === 'home') return Promise.resolve(selected);\n\n return select<TargetInfo>({\n message: 'Which part do you want to customize?',\n options: [\n {\n label: 'All',\n hint: 'install the entire layout',\n value: selected,\n },\n {\n label: 'Replace & rewrite from minimal styles',\n hint: 'for those who want to build their own UI from ground up',\n value: {\n id: 'docs-min',\n targets: [{ name: 'layouts/docs-min' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/docs', '@/layouts/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/layouts/docs/page'],\n ),\n },\n },\n ...info.unlistedIndexes.flatMap((index) => {\n const prefix = `slots/${selected.id}`;\n if (!index.name.startsWith(prefix)) return [];\n let name = index.name.slice(prefix.length + 1);\n\n if (name.startsWith('page/')) {\n name = name.slice('page/'.length);\n\n return {\n label: `Page: ${name}`,\n hint: \"only replace a part of layout's page, useful for adjusting details\",\n value: {\n id: index.name,\n targets: [{ subRegistry, name: index.name }],\n print() {\n printSlot({\n at: `@/layouts/${selected.id}/page/slots/${name}`,\n layoutId: selected.id,\n name,\n isPage: true,\n uiLibrary: config.uiLibrary,\n });\n },\n } as TargetInfo,\n };\n }\n\n return {\n label: `Layout: ${name}`,\n hint: 'only replace a part of layout, useful for adjusting details',\n value: {\n id: index.name,\n targets: [{ subRegistry, name: index.name }],\n print() {\n printSlot({\n at: `@/layouts/${selected.id}/slots/${name}`,\n layoutId: selected.id,\n name,\n isPage: false,\n uiLibrary: config.uiLibrary,\n });\n },\n } as TargetInfo,\n };\n }),\n ],\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const targetInfo = result.target as TargetInfo;\n for (const target of targetInfo.targets) {\n await installer.installInteractive(target.name, target.subRegistry);\n }\n\n await targetInfo.print?.();\n\n outro(picocolors.bold('Have fun!'));\n}\n\n/** point the imports of route files at the installed layouts */\nexport async function rewriteLayoutImports(config: LoadedConfig, map: Map<string, string>) {\n const dir = path.join(config.baseDir, frameworks[config.framework].routesDir);\n const entries = await fs.readdir(dir, { recursive: true, withFileTypes: true }).catch(() => []);\n const updated: string[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.tsx')) continue;\n const file = path.join(entry.parentPath, entry.name);\n const source = parseSourceFile(file, await fs.readFile(file, 'utf-8'));\n for (const node of source.program.body) {\n if (node.type !== 'ImportDeclaration') continue;\n const to = map.get(node.source.value);\n if (to) source.s.overwrite(node.source.start + 1, node.source.end - 1, to);\n }\n if (!source.s.hasChanged()) continue;\n await source.save();\n updated.push(file);\n }\n\n return updated;\n}\n\nasync function printLayout(config: LoadedConfig, ...maps: [from: string, to: string][]) {\n intro(picocolors.bold('What is Next?'));\n const updated = await rewriteLayoutImports(config, new Map(maps));\n\n log.info(\n [\n 'You can check the installed layouts in `layouts` folder.',\n picocolors.dim('---'),\n updated.length > 0\n ? `Updated the imports of ${updated.join(', ')}.`\n : 'Open your `layout.tsx` files, replace the imports of components:',\n ...maps.map(([from, to]) => picocolors.greenBright(`\"${from}\" -> \"${to}\"`)),\n ].join('\\n'),\n );\n}\n\nfunction printSlot({ at, layoutId, name, isPage, uiLibrary }: SlotPrintInfo) {\n intro(picocolors.bold('What is Next?'));\n\n log.info(`You can check the installed layout slot in \"${at}\".`);\n\n const code = getSlotCode({ at, layoutId, name, isPage, uiLibrary });\n\n if (code) {\n const layoutComponent = layoutId === 'glass' ? '<GlassLayout />' : '<DocsLayout />';\n\n if (isPage) {\n log.info(\n `${picocolors.bold('At your <DocsPage /> component, update your \"slots\" prop:')}\\n\\n${code}`,\n );\n } else {\n log.info(\n `${picocolors.bold(`At your ${layoutComponent} component, update your \"slots\" prop:`)}\\n\\n${code}`,\n );\n }\n }\n}\n\nfunction getSlotCode({ at, layoutId, name, isPage, uiLibrary }: SlotPrintInfo): string | undefined {\n if (layoutId === 'glass') {\n // Glass layout wires its page slots directly, only layout-level slots are swappable.\n if (isPage) return;\n\n switch (name) {\n case 'header':\n return `import { Header } from '${at}';\n\nreturn (\n <GlassLayout\n slots={{\n header: Header,\n }}\n >\n ...\n </GlassLayout>\n);`;\n case 'sidebar': {\n // `sidebar` slot file holds the whole sidebar system (desktop, mobile drawer, provider).\n // Base UI additionally exposes a `drawerHandle` for its swipeable drawer.\n const imports = ['Sidebar', 'SidebarDrawer', 'SidebarProvider', 'useSidebar'];\n if (uiLibrary === 'base-ui') imports.push('drawerHandle');\n\n return `import { ${imports.join(', ')} } from '${at}';\n\nreturn (\n <GlassLayout\n slots={{\n sidebar: {\n main: Sidebar,\n provider: SidebarProvider,\n use: useSidebar,\n drawer: SidebarDrawer,${uiLibrary === 'base-ui' ? '\\n drawerHandle,' : ''}\n },\n }}\n >\n ...\n </GlassLayout>\n);`;\n }\n default:\n return;\n }\n }\n\n if (isPage) {\n switch (name) {\n case 'toc':\n if (layoutId === 'flux') {\n return `import { TOCProvider, TOC } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n toc: {\n provider: TOCProvider,\n main: TOC,\n },\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n\n return `import { TOCProvider, TOC, TOCPopover } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n toc: {\n provider: TOCProvider,\n main: TOC,\n popover: TOCPopover,\n },\n }}\n >\n ...\n </DocsPage>\n);`;\n case 'container': {\n return `import { Container } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n container: Container,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n case 'footer': {\n return `import { Footer } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n footer: Footer,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n case 'breadcrumb': {\n return `import { Breadcrumb } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n breadcrumb: Breadcrumb,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n default:\n return;\n }\n }\n\n switch (name) {\n case 'sidebar': {\n if (layoutId === 'notebook') {\n return `import {\n SidebarProvider,\n Sidebar,\n SidebarTrigger,\n SidebarCollapseTrigger,\n useSidebar,\n} from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n sidebar: {\n provider: SidebarProvider,\n root: Sidebar,\n trigger: SidebarTrigger,\n collapseTrigger: SidebarCollapseTrigger,\n useSidebar: useSidebar,\n },\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n\n return `import { SidebarProvider, Sidebar, SidebarTrigger, useSidebar } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n sidebar: {\n provider: SidebarProvider,\n root: Sidebar,\n trigger: SidebarTrigger,\n useSidebar: useSidebar,\n },\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'container': {\n return `import { Container } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n container: Container,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'header': {\n return `import { Header } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n header: Header,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'tab-dropdown': {\n return `import { TabDropdown } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n tabDropdown: TabDropdown,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n default:\n return;\n }\n}\n","import { autocompleteMultiselect, outro, spinner } from '@clack/prompts';\nimport { isCancel } from '@/utils/prompt';\nimport picocolors from 'picocolors';\nimport { UIRegistries } from '@/commands/shared';\nimport { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { LoadedConfig } from '@/config';\nimport { FumadocsComponentInstaller } from '@/registry/installer';\n\ninterface AddOption {\n label: string;\n value: Target;\n hint?: string;\n}\n\nexport interface Target {\n name: string;\n subRegistry?: string;\n}\n\nexport async function add(input: string[], connector: RegistryConnector, config: LoadedConfig) {\n let targets: Target[];\n const installer = new FumadocsComponentInstaller(connector, config);\n const subRegistry = UIRegistries[config.uiLibrary];\n\n if (input.length === 0) {\n const spin = spinner();\n spin.start('fetching registry');\n\n async function scan(subRegistry?: string, prefix?: string): Promise<AddOption[]> {\n const info = await connector.fetchRegistryInfo(subRegistry);\n\n return info.indexes.map((item) => ({\n label: `${prefix ? `${picocolors.bold(prefix)} - ` : ''}${item.title ?? item.name}`,\n value: { name: item.name, subRegistry },\n hint: item.description,\n }));\n }\n\n const groups = await Promise.all([\n scan(undefined, 'common'),\n scan('fumadocs/sanity', 'sanity'),\n scan('fumadocs/openapi', 'openapi'),\n scan('fumadocs/api-docs', 'api-docs'),\n scan(subRegistry, 'ui'),\n ]);\n\n spin.stop(picocolors.bold(picocolors.greenBright('registry fetched')));\n const value = await autocompleteMultiselect({\n message: 'Select components to install',\n options: groups.flat().sort((a, b) => a.label.localeCompare(b.label)),\n });\n\n if (isCancel(value)) {\n outro('Ended');\n return;\n }\n\n targets = value;\n } else {\n targets = await Promise.all(\n input.map(async (item) =>\n (await connector.hasComponent(item)) ? { name: item } : { subRegistry, name: item },\n ),\n );\n }\n\n for (const target of targets) {\n await installer.installInteractive(target.name, target.subRegistry);\n }\n\n outro(picocolors.bold(picocolors.greenBright('Successful')));\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { exists } from '@/utils/fs';\nimport picocolors from 'picocolors';\nimport { spinner } from '@clack/prompts';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n try {\n const raw = await fs.readFile(path.join(cwd, 'package.json'), 'utf-8');\n return JSON.parse(raw) as PackageJson;\n } catch {\n return null;\n }\n}\n\n/** Path of pre-rendered EPUB, choose one according to your React framework. Next.js fetches from the running server instead. */\nconst EPUB_BUILD_PATHS: Record<string, string> = {\n next: '', // Fetched from /export/epub at runtime; route handlers don't produce static files\n astro: 'dist/export/epub',\n 'tanstack-start': '.output/public/export/epub',\n 'tanstack-start-spa': 'dist/client/export/epub',\n 'react-router': 'build/client/export/epub',\n 'react-router-spa': 'build/client/export/epub',\n waku: 'dist/public/export/epub',\n};\n\nexport async function exportEpub(options: { output?: string; framework: string }) {\n const cwd = process.cwd();\n const outputPath = path.resolve(cwd, options.output ?? 'docs.epub');\n const framework = options.framework;\n\n const spin = spinner();\n\n const buildPath = EPUB_BUILD_PATHS[framework];\n if (!(framework in EPUB_BUILD_PATHS)) {\n const valid = Object.keys(EPUB_BUILD_PATHS).join(', ');\n console.error(picocolors.red(`Invalid --framework \"${framework}\". Must be one of: ${valid}`));\n process.exit(1);\n }\n\n const pkg = await readPackageJson(cwd);\n // Check for fumadocs-epub dependency\n if (!pkg) {\n console.error(\n picocolors.red('Cannot read or parse package.json. Ensure it exists and is valid JSON.'),\n );\n process.exit(1);\n }\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (!deps['fumadocs-epub']) {\n console.log(picocolors.yellow('\\nInstalling fumadocs-epub...'));\n const packageManager = process.env.npm_execpath?.includes('pnpm')\n ? 'pnpm'\n : process.env.npm_execpath?.includes('bun')\n ? 'bun'\n : 'npm';\n const installCmd = `${packageManager} add fumadocs-epub`;\n try {\n await execAsync(installCmd, { cwd });\n } catch (err: unknown) {\n const stderr =\n err && typeof err === 'object' && 'stderr' in err\n ? String((err as { stderr?: string }).stderr)\n : '';\n console.error(picocolors.red(`Failed to install fumadocs-epub. Command: ${installCmd}`));\n if (stderr) console.error(stderr);\n process.exit(1);\n }\n }\n\n if (framework === 'next') {\n const secret = process.env.EXPORT_SECRET;\n if (!secret) {\n console.error(\n picocolors.red('EXPORT_SECRET is required for Next.js export. Set it in your environment.'),\n );\n process.exit(1);\n }\n const port = process.env.PORT || '3000';\n const url = `http://localhost:${port}/export/epub`;\n spin.start('Fetching EPUB from server');\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 30_000);\n try {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${secret}` },\n signal: controller.signal,\n });\n if (!res.ok) {\n if (res.status === 401 || res.status === 403) {\n console.error(\n picocolors.red('Auth failed. Check that EXPORT_SECRET matches the value in your app.'),\n );\n } else if (res.status === 404) {\n console.error(\n picocolors.red('Export route not found, run `fumadocs feature epub` to create it.'),\n );\n } else {\n console.error(\n picocolors.red(\n `Server returned ${res.status}. Ensure the app is running (e.g. pnpm start) on port ${port}.`,\n ),\n );\n }\n process.exit(1);\n }\n const buffer = Buffer.from(await res.arrayBuffer());\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, buffer);\n spin.stop(picocolors.green(`EPUB saved to ${outputPath}`));\n } catch (err: unknown) {\n if (err instanceof Error && err.name === 'AbortError') {\n console.error(picocolors.red('Request timed out after 30 seconds.'));\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(picocolors.red(`Could not fetch EPUB: ${msg}`));\n }\n console.error(\n picocolors.yellow(`Ensure the server is running (e.g. pnpm start) on port ${port}.`),\n );\n process.exit(1);\n } finally {\n clearTimeout(timeoutId);\n }\n return;\n }\n\n const fullBuildPath = path.join(cwd, buildPath);\n if (!(await exists(fullBuildPath))) {\n console.error(\n picocolors.red(\n `EPUB not found at ${buildPath}. Run production build first (e.g. pnpm build).`,\n ),\n );\n process.exit(1);\n }\n\n spin.start('Copying EPUB');\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.copyFile(fullBuildPath, outputPath);\n spin.stop(picocolors.green(`EPUB saved to ${outputPath}`));\n}\n","import type { CAC, Command } from 'cac';\nimport { cancel, confirm, intro, log, note, outro, select, spinner } from '@clack/prompts';\nimport { isCancel } from '@/utils/prompt';\nimport picocolors from 'picocolors';\nimport type { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { createOrLoadConfig } from '@/config';\nimport { loadProject } from '@/project';\nimport { type AnyFeature, type FeatureIO, runFeature } from '@/features';\nimport { features } from '@/features/all';\n\ninterface CommandOptions extends Record<string, string | boolean | undefined> {\n config?: string;\n dir?: string;\n yes?: boolean;\n install?: boolean;\n}\n\nexport function registerFeatureCommands(\n cli: CAC,\n createConnector: (dir?: string) => RegistryConnector,\n) {\n const ids = features.map((feature) => feature.id).join(', ');\n\n register(\n cli.command('feature <id>', `configure a feature on your project (${ids})`),\n features,\n ).action(async (id: string, options: CommandOptions) => {\n const feature = features.find((item) => item.id === id);\n if (!feature) throw new Error(`unknown feature: ${id}, available: ${ids}`);\n\n await run(feature, options, createConnector(options.dir));\n });\n\n register(cli.command('init', 'set up Fumadocs on an existing app, same as `feature docs`'), [\n features[0],\n ]).action(async (options: CommandOptions) => {\n await run(features[0], options, createConnector(options.dir));\n });\n}\n\nfunction register(command: Command, list: AnyFeature[]) {\n command\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .option('-y, --yes', 'skip prompts, overwrite existing files')\n .option('--no-install', 'write dependencies to package.json without installing');\n\n for (const feature of list) {\n for (const [key, option] of Object.entries(feature.options ?? {})) {\n if ('choices' in option) {\n command.option(\n `--${key} <value>`,\n `${option.message} (${option.choices.map((choice) => choice.value).join(', ')})`,\n );\n } else {\n command.option(`--${key}`, option.message);\n }\n }\n }\n\n return command;\n}\n\nasync function run(feature: AnyFeature, options: CommandOptions, connector: RegistryConnector) {\n intro(picocolors.bgBlack(picocolors.whiteBright(feature.title)));\n const config = await createOrLoadConfig(options.config);\n const project = await loadProject(config);\n log.info(`${project.framework}${project.static ? ' (static)' : ''}, ${project.packageManager}`);\n\n const values: Record<string, unknown> = {};\n for (const [key, option] of Object.entries(feature.options ?? {})) {\n const given = options[key];\n if ('choices' in option) {\n if (given !== undefined) {\n if (!option.choices.some((choice) => choice.value === given))\n throw new Error(`invalid value for --${key}: ${given}`);\n values[key] = given;\n continue;\n }\n\n const value = await select({ message: option.message, options: option.choices });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n values[key] = value;\n } else if (given !== undefined) {\n values[key] = given === true;\n } else if (options.yes) {\n values[key] = option.initialValue ?? false;\n } else {\n const value = await confirm({ message: option.message, initialValue: option.initialValue });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n values[key] = value;\n }\n }\n\n const spin = spinner();\n const io: FeatureIO = {\n installDependencies: options.install !== false,\n log: (message) => spin.message(message),\n async confirmOverwrite(file) {\n if (options.yes) return true;\n spin.clear();\n const value = await confirm({ message: `Overwrite ${file}?`, initialValue: false });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n spin.start();\n return value;\n },\n };\n\n spin.start(`Applying ${feature.title}`);\n try {\n const { notes } = await runFeature(feature, values, { project, connector, io });\n spin.stop(`${feature.title} applied`);\n if (notes.length > 0) note(notes.join('\\n\\n'), 'What is Next?');\n } catch (e) {\n spin.error(e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n outro(picocolors.bold(picocolors.greenBright('Done')));\n}\n","#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { cac } from 'cac';\nimport picocolors from 'picocolors';\nimport { createOrLoadConfig, initConfig } from '@/config';\nimport { type JsonTreeNode, treeToJavaScript, treeToMdx } from '@/commands/file-tree';\nimport { runTree } from '@/utils/file-tree/run-tree';\nimport packageJson from '../package.json';\nimport { customise } from '@/commands/customise';\nimport { add } from '@/commands/add';\nimport { exportEpub } from '@/commands/export-epub';\nimport { registerFeatureCommands } from '@/commands/feature';\nimport { HttpRegistryConnector, LocalRegistryConnector } from 'fuma-cli/registry/connector';\n\nconst cli = cac('fumadocs');\ncli.option('--config <string>', 'path to the config file');\n\ncli.command('', 'init a `cli.json` config file').action(async () => {\n if (await initConfig()) {\n console.log(picocolors.green('Initialized a `./cli.json` config file.'));\n } else {\n console.log(picocolors.redBright('A config file already exists.'));\n }\n});\n\ncli\n .command('customise', 'simple way to customize layouts with Fumadocs UI')\n .alias('customize')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (options: { config?: string; dir?: string }) => {\n const config = await createOrLoadConfig(options.config);\n await customise(config, createClientFromDir(options.dir));\n });\n\nconst dirShortcuts: Record<string, string> = {\n ':preview': 'https://preview.fumadocs.dev/registry',\n ':dev': 'http://localhost:3000/registry',\n};\n\ncli\n .command('add [...components]', 'add a new component to your docs')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (input: string[], options: { config?: string; dir?: string }) => {\n const config = await createOrLoadConfig(options.config);\n const client = createClientFromDir(options.dir);\n await add(input, client, config);\n });\n\nregisterFeatureCommands(cli, createClientFromDir);\n\ncli\n .command(\n 'export <format>',\n 'export documentation to various formats (run after production build)',\n )\n .option('--framework <name>', 'framework: next, astro, tanstack-start, react-router, waku')\n .option('--output <path>', 'output file path', { default: 'docs.epub' })\n .action(async (format: string, options: { framework?: string; output: string }) => {\n if (format !== 'epub')\n throw new Error(`unsupported format: ${format}, only \\`epub\\` is supported.`);\n if (!options.framework) throw new Error('option `--framework <name>` is required.');\n\n await exportEpub({ framework: options.framework, output: options.output });\n });\n\ncli\n .command(\n 'tree [json_or_args] [output]',\n 'generate a file tree for the Files component, from a directory or JSON output of `tree`',\n )\n .option('--js', 'output as JavaScript file')\n .option('--no-root', 'remove the root node')\n .option('--import-name <name>', 'where to import components (JS only)')\n .action(\n async (\n str: string | undefined,\n output: string | undefined,\n { js, root, importName }: { js: boolean; root: boolean; importName?: string },\n ) => {\n const jsExtensions = ['.js', '.tsx', '.jsx'];\n const noRoot = !root;\n let nodes: JsonTreeNode[];\n\n try {\n nodes = JSON.parse(str ?? '') as JsonTreeNode[];\n } catch {\n nodes = await runTree(str ?? './');\n }\n\n const out =\n js || (output && jsExtensions.includes(path.extname(output)))\n ? treeToJavaScript(nodes, noRoot, importName)\n : treeToMdx(nodes, noRoot);\n\n if (output) {\n await fs.mkdir(path.dirname(output), { recursive: true });\n await fs.writeFile(output, out);\n } else {\n console.log(out);\n }\n },\n );\n\nfunction createClientFromDir(dir = 'https://fumadocs.dev/registry') {\n if (dir in dirShortcuts) dir = dirShortcuts[dir];\n\n return dir.startsWith('http://') || dir.startsWith('https://')\n ? new HttpRegistryConnector(dir)\n : new LocalRegistryConnector(dir);\n}\n\ncli.help();\ncli.version(packageJson.version);\n\ntry {\n cli.parse(process.argv, { run: false });\n await cli.runMatchedCommand();\n} catch (e) {\n console.error(picocolors.redBright(e instanceof Error ? e.message : String(e)));\n process.exit(1);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isCancel","isCancel","packageJson.version"],"sources":["../src/commands/file-tree.ts","../src/utils/file-tree/run-tree.ts","../package.json","../src/commands/customise.ts","../src/commands/add.ts","../src/commands/export-epub.ts","../src/commands/feature.ts","../src/index.ts"],"sourcesContent":["export type JsonTreeNode =\n | {\n type: 'file';\n name: string;\n }\n | {\n type: 'directory';\n name: string;\n contents: JsonTreeNode[];\n }\n | {\n type: 'report';\n }\n | {\n type: 'link';\n name: string;\n };\n\nconst scanned = ['file', 'directory', 'link'];\n\nexport function treeToMdx(input: JsonTreeNode[], noRoot = false): string {\n function toNode(item: JsonTreeNode): string {\n if (item.type === 'file' || item.type === 'link') {\n return `<File name=${JSON.stringify(item.name)} />`;\n }\n\n if (item.type === 'directory') {\n if (item.contents.length === 1 && 'name' in item.contents[0]) {\n const child = item.contents[0];\n\n return toNode({\n ...child,\n name: `${item.name}/${child.name}`,\n });\n }\n\n return `<Folder name=${JSON.stringify(item.name)}>\n${item.contents.map(toNode).filter(Boolean).join('\\n')}\n</Folder>`;\n }\n\n return '';\n }\n\n let children = input.filter((v) => scanned.includes(v.type));\n\n if (noRoot && children.length === 1 && input[0].type === 'directory') {\n children = input[0].contents;\n }\n\n return `<Files>\n${children.map(toNode).filter(Boolean).join('\\n')}\n</Files>`;\n}\n\nexport function treeToJavaScript(\n input: JsonTreeNode[],\n noRoot?: boolean,\n importName = 'fumadocs-ui/components/files',\n): string {\n return `import { File, Files, Folder } from ${JSON.stringify(importName)}\n\nexport default (${treeToMdx(input, noRoot)})`;\n}\n","import { x } from 'tinyexec';\nimport type { JsonTreeNode } from '@/commands/file-tree';\n\nexport async function runTree(args: string): Promise<JsonTreeNode[]> {\n const out = await x('tree', [args, '--gitignore', '--prune', '-J']);\n\n try {\n return JSON.parse(out.stdout) as JsonTreeNode[];\n } catch (e) {\n throw new Error('failed to run `tree` command', {\n cause: e,\n });\n }\n}\n","","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { cancel, group, intro, log, outro, select } from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { parseSourceFile } from '@/codemod';\nimport { frameworks } from '@/project';\nimport type { Target } from '@/commands/add';\nimport { UIRegistries } from '@/commands/shared';\nimport { LoadedConfig } from '@/config';\nimport { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { FumadocsComponentInstaller } from '@/registry/installer';\n\ninterface TargetInfo {\n targets: Target[];\n id: string;\n print?: () => void | Promise<void>;\n}\n\ninterface SlotPrintInfo {\n at: string;\n layoutId: string;\n name: string;\n isPage: boolean;\n uiLibrary: LoadedConfig['uiLibrary'];\n}\n\nexport async function customise(config: LoadedConfig, connector: RegistryConnector) {\n intro(picocolors.bgBlack(picocolors.whiteBright('Customize Fumadocs UI')));\n\n const installer = new FumadocsComponentInstaller(connector, config);\n const subRegistry = UIRegistries[config.uiLibrary];\n const info = await connector.fetchRegistryInfo(subRegistry);\n\n const result = await group(\n {\n layout: (): Promise<TargetInfo | symbol> =>\n select({\n message: 'What do you want to customize?',\n options: [\n {\n label: 'Docs Layout',\n value: {\n id: 'docs',\n targets: [{ subRegistry, name: 'layouts/docs' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/docs', '@/layouts/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/layouts/docs/page'],\n ),\n },\n hint: 'the default docs layout',\n },\n {\n label: 'Notebook Layout',\n value: {\n id: 'notebook',\n targets: [{ subRegistry, name: 'layouts/notebook' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/notebook', '@/layouts/notebook'],\n ['fumadocs-ui/layouts/notebook/page', '@/layouts/notebook/page'],\n ),\n },\n hint: 'a more compact version of docs layout',\n },\n {\n label: 'Flux Layout',\n value: {\n id: 'flux',\n targets: [{ subRegistry, name: 'layouts/flux' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/flux', '@/layouts/flux'],\n ['fumadocs-ui/layouts/flux/page', '@/layouts/flux/page'],\n ),\n },\n hint: 'the experimental variant of docs layout',\n },\n {\n label: 'Glass Layout',\n value: {\n id: 'glass',\n targets: [{ subRegistry, name: 'layouts/glass' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/glass', '@/layouts/glass'],\n ['fumadocs-ui/layouts/glass/page', '@/layouts/glass/page'],\n ),\n },\n hint: 'a docs layout with floating, translucent panels',\n },\n {\n label: 'Home Layout',\n value: {\n id: 'home',\n targets: [{ subRegistry, name: 'layouts/home' }],\n print: () => printLayout(config, ['fumadocs-ui/layouts/home', '@/layouts/home']),\n },\n hint: 'the layout for other non-docs pages',\n },\n ],\n }),\n target: (v): Promise<TargetInfo | symbol> => {\n const selected = v.results.layout!;\n if (selected.id === 'home') return Promise.resolve(selected);\n\n return select<TargetInfo>({\n message: 'Which part do you want to customize?',\n options: [\n {\n label: 'All',\n hint: 'install the entire layout',\n value: selected,\n },\n {\n label: 'Replace & rewrite from minimal styles',\n hint: 'for those who want to build their own UI from ground up',\n value: {\n id: 'docs-min',\n targets: [{ name: 'layouts/docs-min' }],\n print: () =>\n printLayout(\n config,\n ['fumadocs-ui/layouts/docs', '@/layouts/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/layouts/docs/page'],\n ),\n },\n },\n ...info.unlistedIndexes.flatMap((index) => {\n const prefix = `slots/${selected.id}`;\n if (!index.name.startsWith(prefix)) return [];\n let name = index.name.slice(prefix.length + 1);\n\n if (name.startsWith('page/')) {\n name = name.slice('page/'.length);\n\n return {\n label: `Page: ${name}`,\n hint: \"only replace a part of layout's page, useful for adjusting details\",\n value: {\n id: index.name,\n targets: [{ subRegistry, name: index.name }],\n print() {\n printSlot({\n at: `@/layouts/${selected.id}/page/slots/${name}`,\n layoutId: selected.id,\n name,\n isPage: true,\n uiLibrary: config.uiLibrary,\n });\n },\n } as TargetInfo,\n };\n }\n\n return {\n label: `Layout: ${name}`,\n hint: 'only replace a part of layout, useful for adjusting details',\n value: {\n id: index.name,\n targets: [{ subRegistry, name: index.name }],\n print() {\n printSlot({\n at: `@/layouts/${selected.id}/slots/${name}`,\n layoutId: selected.id,\n name,\n isPage: false,\n uiLibrary: config.uiLibrary,\n });\n },\n } as TargetInfo,\n };\n }),\n ],\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const targetInfo = result.target as TargetInfo;\n for (const target of targetInfo.targets) {\n await installer.installInteractive(target.name, target.subRegistry);\n }\n\n await targetInfo.print?.();\n\n outro(picocolors.bold('Have fun!'));\n}\n\n/** point the imports of route files at the installed layouts */\nexport async function rewriteLayoutImports(config: LoadedConfig, map: Map<string, string>) {\n const dir = path.join(config.baseDir, frameworks[config.framework].routesDir);\n const entries = await fs.readdir(dir, { recursive: true, withFileTypes: true }).catch(() => []);\n const updated: string[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.tsx')) continue;\n const file = path.join(entry.parentPath, entry.name);\n const source = parseSourceFile(file, await fs.readFile(file, 'utf-8'));\n for (const node of source.program.body) {\n if (node.type !== 'ImportDeclaration') continue;\n const to = map.get(node.source.value);\n if (to) source.s.overwrite(node.source.start + 1, node.source.end - 1, to);\n }\n if (!source.s.hasChanged()) continue;\n await source.save();\n updated.push(file);\n }\n\n return updated;\n}\n\nasync function printLayout(config: LoadedConfig, ...maps: [from: string, to: string][]) {\n intro(picocolors.bold('What is Next?'));\n const updated = await rewriteLayoutImports(config, new Map(maps));\n\n log.info(\n [\n 'You can check the installed layouts in `layouts` folder.',\n picocolors.dim('---'),\n updated.length > 0\n ? `Updated the imports of ${updated.join(', ')}.`\n : 'Open your `layout.tsx` files, replace the imports of components:',\n ...maps.map(([from, to]) => picocolors.greenBright(`\"${from}\" -> \"${to}\"`)),\n ].join('\\n'),\n );\n}\n\nfunction printSlot({ at, layoutId, name, isPage, uiLibrary }: SlotPrintInfo) {\n intro(picocolors.bold('What is Next?'));\n\n log.info(`You can check the installed layout slot in \"${at}\".`);\n\n const code = getSlotCode({ at, layoutId, name, isPage, uiLibrary });\n\n if (code) {\n const layoutComponent = layoutId === 'glass' ? '<GlassLayout />' : '<DocsLayout />';\n\n if (isPage) {\n log.info(\n `${picocolors.bold('At your <DocsPage /> component, update your \"slots\" prop:')}\\n\\n${code}`,\n );\n } else {\n log.info(\n `${picocolors.bold(`At your ${layoutComponent} component, update your \"slots\" prop:`)}\\n\\n${code}`,\n );\n }\n }\n}\n\nfunction getSlotCode({ at, layoutId, name, isPage, uiLibrary }: SlotPrintInfo): string | undefined {\n if (layoutId === 'glass') {\n // Glass layout wires its page slots directly, only layout-level slots are swappable.\n if (isPage) return;\n\n switch (name) {\n case 'header':\n return `import { Header } from '${at}';\n\nreturn (\n <GlassLayout\n slots={{\n header: Header,\n }}\n >\n ...\n </GlassLayout>\n);`;\n case 'sidebar': {\n // `sidebar` slot file holds the whole sidebar system (desktop, mobile drawer, provider).\n // Base UI additionally exposes a `drawerHandle` for its swipeable drawer.\n const imports = ['Sidebar', 'SidebarDrawer', 'SidebarProvider', 'useSidebar'];\n if (uiLibrary === 'base-ui') imports.push('drawerHandle');\n\n return `import { ${imports.join(', ')} } from '${at}';\n\nreturn (\n <GlassLayout\n slots={{\n sidebar: {\n main: Sidebar,\n provider: SidebarProvider,\n use: useSidebar,\n drawer: SidebarDrawer,${uiLibrary === 'base-ui' ? '\\n drawerHandle,' : ''}\n },\n }}\n >\n ...\n </GlassLayout>\n);`;\n }\n default:\n return;\n }\n }\n\n if (isPage) {\n switch (name) {\n case 'toc':\n if (layoutId === 'flux') {\n return `import { TOCProvider, TOC } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n toc: {\n provider: TOCProvider,\n main: TOC,\n },\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n\n return `import { TOCProvider, TOC, TOCPopover } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n toc: {\n provider: TOCProvider,\n main: TOC,\n popover: TOCPopover,\n },\n }}\n >\n ...\n </DocsPage>\n);`;\n case 'container': {\n return `import { Container } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n container: Container,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n case 'footer': {\n return `import { Footer } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n footer: Footer,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n case 'breadcrumb': {\n return `import { Breadcrumb } from '${at}';\n\nreturn (\n <DocsPage\n slots={{\n breadcrumb: Breadcrumb,\n }}\n >\n ...\n </DocsPage>\n);`;\n }\n default:\n return;\n }\n }\n\n switch (name) {\n case 'sidebar': {\n if (layoutId === 'notebook') {\n return `import {\n SidebarProvider,\n Sidebar,\n SidebarTrigger,\n SidebarCollapseTrigger,\n useSidebar,\n} from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n sidebar: {\n provider: SidebarProvider,\n root: Sidebar,\n trigger: SidebarTrigger,\n collapseTrigger: SidebarCollapseTrigger,\n useSidebar: useSidebar,\n },\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n\n return `import { SidebarProvider, Sidebar, SidebarTrigger, useSidebar } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n sidebar: {\n provider: SidebarProvider,\n root: Sidebar,\n trigger: SidebarTrigger,\n useSidebar: useSidebar,\n },\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'container': {\n return `import { Container } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n container: Container,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'header': {\n return `import { Header } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n header: Header,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n case 'tab-dropdown': {\n return `import { TabDropdown } from '${at}';\n\nreturn (\n <DocsLayout\n slots={{\n tabDropdown: TabDropdown,\n }}\n >\n ...\n </DocsLayout>\n);`;\n }\n default:\n return;\n }\n}\n","import { autocompleteMultiselect, outro, spinner } from '@clack/prompts';\nimport { isCancel } from '@/utils/prompt';\nimport picocolors from 'picocolors';\nimport { UIRegistries } from '@/commands/shared';\nimport { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { LoadedConfig } from '@/config';\nimport { FumadocsComponentInstaller } from '@/registry/installer';\n\ninterface AddOption {\n label: string;\n value: Target;\n hint?: string;\n}\n\nexport interface Target {\n name: string;\n subRegistry?: string;\n}\n\nexport async function add(input: string[], connector: RegistryConnector, config: LoadedConfig) {\n let targets: Target[];\n const installer = new FumadocsComponentInstaller(connector, config);\n const subRegistry = UIRegistries[config.uiLibrary];\n\n if (input.length === 0) {\n const spin = spinner();\n spin.start('fetching registry');\n\n async function scan(subRegistry?: string, prefix?: string): Promise<AddOption[]> {\n const info = await connector.fetchRegistryInfo(subRegistry);\n\n return info.indexes.map((item) => ({\n label: `${prefix ? `${picocolors.bold(prefix)} - ` : ''}${item.title ?? item.name}`,\n value: { name: item.name, subRegistry },\n hint: item.description,\n }));\n }\n\n const groups = await Promise.all([\n scan(undefined, 'common'),\n scan('sanity', 'sanity'),\n scan('openapi', 'openapi'),\n scan('api-docs', 'api-docs'),\n scan(subRegistry, 'ui'),\n ]);\n\n spin.stop(picocolors.bold(picocolors.greenBright('registry fetched')));\n const value = await autocompleteMultiselect({\n message: 'Select components to install',\n options: groups.flat().sort((a, b) => a.label.localeCompare(b.label)),\n });\n\n if (isCancel(value)) {\n outro('Ended');\n return;\n }\n\n targets = value;\n } else {\n targets = await Promise.all(\n input.map(async (item) =>\n (await connector.hasComponent(item)) ? { name: item } : { subRegistry, name: item },\n ),\n );\n }\n\n for (const target of targets) {\n await installer.installInteractive(target.name, target.subRegistry);\n }\n\n outro(picocolors.bold(picocolors.greenBright('Successful')));\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { exists } from '@/utils/fs';\nimport picocolors from 'picocolors';\nimport { spinner } from '@clack/prompts';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n try {\n const raw = await fs.readFile(path.join(cwd, 'package.json'), 'utf-8');\n return JSON.parse(raw) as PackageJson;\n } catch {\n return null;\n }\n}\n\n/** Path of pre-rendered EPUB, choose one according to your React framework. Next.js fetches from the running server instead. */\nconst EPUB_BUILD_PATHS: Record<string, string> = {\n next: '', // Fetched from /export/epub at runtime; route handlers don't produce static files\n astro: 'dist/export/epub',\n 'tanstack-start': '.output/public/export/epub',\n 'tanstack-start-spa': 'dist/client/export/epub',\n 'react-router': 'build/client/export/epub',\n 'react-router-spa': 'build/client/export/epub',\n waku: 'dist/public/export/epub',\n};\n\nexport async function exportEpub(options: { output?: string; framework: string }) {\n const cwd = process.cwd();\n const outputPath = path.resolve(cwd, options.output ?? 'docs.epub');\n const framework = options.framework;\n\n const spin = spinner();\n\n const buildPath = EPUB_BUILD_PATHS[framework];\n if (!(framework in EPUB_BUILD_PATHS)) {\n const valid = Object.keys(EPUB_BUILD_PATHS).join(', ');\n console.error(picocolors.red(`Invalid --framework \"${framework}\". Must be one of: ${valid}`));\n process.exit(1);\n }\n\n const pkg = await readPackageJson(cwd);\n // Check for fumadocs-epub dependency\n if (!pkg) {\n console.error(\n picocolors.red('Cannot read or parse package.json. Ensure it exists and is valid JSON.'),\n );\n process.exit(1);\n }\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (!deps['fumadocs-epub']) {\n console.log(picocolors.yellow('\\nInstalling fumadocs-epub...'));\n const packageManager = process.env.npm_execpath?.includes('pnpm')\n ? 'pnpm'\n : process.env.npm_execpath?.includes('bun')\n ? 'bun'\n : 'npm';\n const installCmd = `${packageManager} add fumadocs-epub`;\n try {\n await execAsync(installCmd, { cwd });\n } catch (err: unknown) {\n const stderr =\n err && typeof err === 'object' && 'stderr' in err\n ? String((err as { stderr?: string }).stderr)\n : '';\n console.error(picocolors.red(`Failed to install fumadocs-epub. Command: ${installCmd}`));\n if (stderr) console.error(stderr);\n process.exit(1);\n }\n }\n\n if (framework === 'next') {\n const secret = process.env.EXPORT_SECRET;\n if (!secret) {\n console.error(\n picocolors.red('EXPORT_SECRET is required for Next.js export. Set it in your environment.'),\n );\n process.exit(1);\n }\n const port = process.env.PORT || '3000';\n const url = `http://localhost:${port}/export/epub`;\n spin.start('Fetching EPUB from server');\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 30_000);\n try {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${secret}` },\n signal: controller.signal,\n });\n if (!res.ok) {\n if (res.status === 401 || res.status === 403) {\n console.error(\n picocolors.red('Auth failed. Check that EXPORT_SECRET matches the value in your app.'),\n );\n } else if (res.status === 404) {\n console.error(\n picocolors.red('Export route not found, run `fumadocs feature epub` to create it.'),\n );\n } else {\n console.error(\n picocolors.red(\n `Server returned ${res.status}. Ensure the app is running (e.g. pnpm start) on port ${port}.`,\n ),\n );\n }\n process.exit(1);\n }\n const buffer = Buffer.from(await res.arrayBuffer());\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, buffer);\n spin.stop(picocolors.green(`EPUB saved to ${outputPath}`));\n } catch (err: unknown) {\n if (err instanceof Error && err.name === 'AbortError') {\n console.error(picocolors.red('Request timed out after 30 seconds.'));\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(picocolors.red(`Could not fetch EPUB: ${msg}`));\n }\n console.error(\n picocolors.yellow(`Ensure the server is running (e.g. pnpm start) on port ${port}.`),\n );\n process.exit(1);\n } finally {\n clearTimeout(timeoutId);\n }\n return;\n }\n\n const fullBuildPath = path.join(cwd, buildPath);\n if (!(await exists(fullBuildPath))) {\n console.error(\n picocolors.red(\n `EPUB not found at ${buildPath}. Run production build first (e.g. pnpm build).`,\n ),\n );\n process.exit(1);\n }\n\n spin.start('Copying EPUB');\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.copyFile(fullBuildPath, outputPath);\n spin.stop(picocolors.green(`EPUB saved to ${outputPath}`));\n}\n","import type { CAC, Command } from 'cac';\nimport { cancel, confirm, intro, log, note, outro, select, spinner } from '@clack/prompts';\nimport { isCancel } from '@/utils/prompt';\nimport picocolors from 'picocolors';\nimport type { RegistryConnector } from 'fuma-cli/registry/connector';\nimport { createOrLoadConfig } from '@/config';\nimport { loadProject } from '@/project';\nimport { type AnyFeature, type FeatureIO, runFeature } from '@/features';\nimport { features } from '@/features/all';\n\ninterface CommandOptions extends Record<string, string | boolean | undefined> {\n config?: string;\n dir?: string;\n yes?: boolean;\n install?: boolean;\n}\n\nexport function registerFeatureCommands(\n cli: CAC,\n createConnector: (dir?: string) => RegistryConnector,\n) {\n const ids = features.map((feature) => feature.id).join(', ');\n\n register(\n cli.command('feature <id>', `configure a feature on your project (${ids})`),\n features,\n ).action(async (id: string, options: CommandOptions) => {\n const feature = features.find((item) => item.id === id);\n if (!feature) throw new Error(`unknown feature: ${id}, available: ${ids}`);\n\n await run(feature, options, createConnector(options.dir));\n });\n\n register(cli.command('init', 'set up Fumadocs on an existing app, same as `feature docs`'), [\n features[0],\n ]).action(async (options: CommandOptions) => {\n await run(features[0], options, createConnector(options.dir));\n });\n}\n\nfunction register(command: Command, list: AnyFeature[]) {\n command\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .option('-y, --yes', 'skip prompts, overwrite existing files')\n .option('--no-install', 'write dependencies to package.json without installing');\n\n for (const feature of list) {\n for (const [key, option] of Object.entries(feature.options ?? {})) {\n if ('choices' in option) {\n command.option(\n `--${key} <value>`,\n `${option.message} (${option.choices.map((choice) => choice.value).join(', ')})`,\n );\n } else {\n command.option(`--${key}`, option.message);\n }\n }\n }\n\n return command;\n}\n\nasync function run(feature: AnyFeature, options: CommandOptions, connector: RegistryConnector) {\n intro(picocolors.bgBlack(picocolors.whiteBright(feature.title)));\n const config = await createOrLoadConfig(options.config);\n const project = await loadProject(config);\n log.info(`${project.framework}${project.static ? ' (static)' : ''}, ${project.packageManager}`);\n\n const values: Record<string, unknown> = {};\n for (const [key, option] of Object.entries(feature.options ?? {})) {\n const given = options[key];\n if ('choices' in option) {\n if (given !== undefined) {\n if (!option.choices.some((choice) => choice.value === given))\n throw new Error(`invalid value for --${key}: ${given}`);\n values[key] = given;\n continue;\n }\n\n const value = await select({ message: option.message, options: option.choices });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n values[key] = value;\n } else if (given !== undefined) {\n values[key] = given === true;\n } else if (options.yes) {\n values[key] = option.initialValue ?? false;\n } else {\n const value = await confirm({ message: option.message, initialValue: option.initialValue });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n values[key] = value;\n }\n }\n\n const spin = spinner();\n const io: FeatureIO = {\n installDependencies: options.install !== false,\n log: (message) => spin.message(message),\n async confirmOverwrite(file) {\n if (options.yes) return true;\n spin.clear();\n const value = await confirm({ message: `Overwrite ${file}?`, initialValue: false });\n if (isCancel(value)) {\n cancel('Stopped.');\n process.exit(0);\n }\n spin.start();\n return value;\n },\n };\n\n spin.start(`Applying ${feature.title}`);\n try {\n const { notes } = await runFeature(feature, values, { project, connector, io });\n spin.stop(`${feature.title} applied`);\n if (notes.length > 0) note(notes.join('\\n\\n'), 'What is Next?');\n } catch (e) {\n spin.error(e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n outro(picocolors.bold(picocolors.greenBright('Done')));\n}\n","#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { cac } from 'cac';\nimport picocolors from 'picocolors';\nimport { createOrLoadConfig, initConfig } from '@/config';\nimport { type JsonTreeNode, treeToJavaScript, treeToMdx } from '@/commands/file-tree';\nimport { runTree } from '@/utils/file-tree/run-tree';\nimport packageJson from '../package.json';\nimport { customise } from '@/commands/customise';\nimport { add } from '@/commands/add';\nimport { exportEpub } from '@/commands/export-epub';\nimport { registerFeatureCommands } from '@/commands/feature';\nimport { HttpRegistryConnector, LocalRegistryConnector } from 'fuma-cli/registry/connector';\n\nconst cli = cac('fumadocs');\ncli.option('--config <string>', 'path to the config file');\n\ncli.command('', 'init a `cli.json` config file').action(async () => {\n if (await initConfig()) {\n console.log(picocolors.green('Initialized a `./cli.json` config file.'));\n } else {\n console.log(picocolors.redBright('A config file already exists.'));\n }\n});\n\ncli\n .command('customise', 'simple way to customize layouts with Fumadocs UI')\n .alias('customize')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (options: { config?: string; dir?: string }) => {\n const config = await createOrLoadConfig(options.config);\n await customise(config, createClientFromDir(options.dir));\n });\n\nconst dirShortcuts: Record<string, string> = {\n ':preview': 'https://preview.fumadocs.dev/registry',\n ':dev': 'http://localhost:3000/registry',\n};\n\ncli\n .command('add [...components]', 'add a new component to your docs')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (input: string[], options: { config?: string; dir?: string }) => {\n const config = await createOrLoadConfig(options.config);\n const client = createClientFromDir(options.dir);\n await add(input, client, config);\n });\n\nregisterFeatureCommands(cli, createClientFromDir);\n\ncli\n .command(\n 'export <format>',\n 'export documentation to various formats (run after production build)',\n )\n .option('--framework <name>', 'framework: next, astro, tanstack-start, react-router, waku')\n .option('--output <path>', 'output file path', { default: 'docs.epub' })\n .action(async (format: string, options: { framework?: string; output: string }) => {\n if (format !== 'epub')\n throw new Error(`unsupported format: ${format}, only \\`epub\\` is supported.`);\n if (!options.framework) throw new Error('option `--framework <name>` is required.');\n\n await exportEpub({ framework: options.framework, output: options.output });\n });\n\ncli\n .command(\n 'tree [json_or_args] [output]',\n 'generate a file tree for the Files component, from a directory or JSON output of `tree`',\n )\n .option('--js', 'output as JavaScript file')\n .option('--no-root', 'remove the root node')\n .option('--import-name <name>', 'where to import components (JS only)')\n .action(\n async (\n str: string | undefined,\n output: string | undefined,\n { js, root, importName }: { js: boolean; root: boolean; importName?: string },\n ) => {\n const jsExtensions = ['.js', '.tsx', '.jsx'];\n const noRoot = !root;\n let nodes: JsonTreeNode[];\n\n try {\n nodes = JSON.parse(str ?? '') as JsonTreeNode[];\n } catch {\n nodes = await runTree(str ?? './');\n }\n\n const out =\n js || (output && jsExtensions.includes(path.extname(output)))\n ? treeToJavaScript(nodes, noRoot, importName)\n : treeToMdx(nodes, noRoot);\n\n if (output) {\n await fs.mkdir(path.dirname(output), { recursive: true });\n await fs.writeFile(output, out);\n } else {\n console.log(out);\n }\n },\n );\n\nfunction createClientFromDir(dir = 'https://fumadocs.dev/registry') {\n if (dir in dirShortcuts) dir = dirShortcuts[dir];\n\n return dir.startsWith('http://') || dir.startsWith('https://')\n ? new HttpRegistryConnector(dir)\n : new LocalRegistryConnector(dir);\n}\n\ncli.help();\ncli.version(packageJson.version);\n\ntry {\n cli.parse(process.argv, { run: false });\n await cli.runMatchedCommand();\n} catch (e) {\n console.error(picocolors.redBright(e instanceof Error ? e.message : String(e)));\n process.exit(1);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fumadocs/cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "The CLI tool for Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Docs",
|
|
@@ -45,19 +45,19 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@clack/prompts": "^1.8.
|
|
48
|
+
"@clack/prompts": "^1.8.1",
|
|
49
49
|
"cac": "^7.0.0",
|
|
50
50
|
"fuma-cli": "^0.1.1",
|
|
51
|
-
"magic-string": "^1.
|
|
52
|
-
"oxc-parser": "^0.
|
|
51
|
+
"magic-string": "^1.4.1",
|
|
52
|
+
"oxc-parser": "^0.150.0",
|
|
53
53
|
"picocolors": "^1.1.1",
|
|
54
54
|
"tinyexec": "^1.3.1",
|
|
55
|
-
"zod": "^4.5
|
|
55
|
+
"zod": "^4.6.5"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@types/node": "26.
|
|
59
|
-
"
|
|
60
|
-
"
|
|
58
|
+
"@types/node": "26.6.1",
|
|
59
|
+
"tsconfig": "0.0.0",
|
|
60
|
+
"tsdown": "0.23.0"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">=20"
|