@fumadocs/cli 1.2.2 → 1.2.3
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/build/index.js.map +1 -1
- package/dist/index.js +92 -63
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["fs","path","output: CompiledRegistry","compiler: RegistryCompiler","component: Component","queue: ComponentFile[]","file","resolved: Reference","comp","fs","path"],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n CompiledComponent,\n CompiledFile,\n httpSubComponent,\n NamespaceType,\n registryInfoSchema,\n} from '@/registry/schema';\nimport type { z } from 'zod';\nimport { parse } from 'oxc-parser';\nimport { ResolverFactory } from 'oxc-resolver';\nimport MagicString from 'magic-string';\nimport { transformSpecifiers } from '@/utils/ast';\n\nexport type OnResolve = (reference: SourceReference) => Reference;\n\nexport interface CompiledRegistry {\n name: string;\n components: CompiledComponent[];\n info: z.output<typeof registryInfoSchema>;\n}\n\nexport interface ComponentFile {\n type: NamespaceType;\n path: string;\n target?: string;\n}\n\nexport interface Component {\n name: string;\n title?: string;\n description?: string;\n files: ComponentFile[];\n\n /**\n * Don't list the component in registry index file\n */\n unlisted?: boolean;\n\n /**\n * Map imported file paths, inherit from registry if not defined.\n */\n onResolve?: OnResolve;\n}\n\nexport interface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport interface Registry extends Omit<z.input<typeof registryInfoSchema>, 'indexes'> {\n name: string;\n packageJson: string | PackageJson;\n tsconfigPath: string;\n components: Component[];\n\n /**\n * The directory of registry, used to resolve relative paths\n */\n dir: string;\n\n /**\n * Map import paths of components\n */\n onResolve?: OnResolve;\n /**\n * When a referenced file is not found in component files, this function is called.\n * @returns file, or `false` to mark as external.\n */\n onUnknownFile?: (absolutePath: string) => ComponentFile | false | undefined;\n\n dependencies?: Record<string, string | null>;\n devDependencies?: Record<string, string | null>;\n}\n\nexport class RegistryCompiler {\n readonly raw: Registry;\n resolver!: RegistryResolver;\n\n constructor(registry: Registry) {\n this.raw = registry;\n }\n\n private async readPackageJson(): Promise<PackageJson | undefined> {\n if (typeof this.raw.packageJson !== 'string') return this.raw.packageJson;\n\n return fs\n .readFile(path.join(this.raw.dir, this.raw.packageJson))\n .then((res) => JSON.parse(res.toString()) as PackageJson)\n .catch(() => undefined);\n }\n\n async compile(): Promise<CompiledRegistry> {\n const registry = this.raw;\n this.resolver = new RegistryResolver(this, await this.readPackageJson());\n const output: CompiledRegistry = {\n name: registry.name,\n info: {\n indexes: [],\n env: registry.env,\n variables: registry.variables,\n },\n components: [],\n };\n\n const builtComps = await Promise.all(\n registry.components.map(async (component) => {\n const compiler = new ComponentCompiler(this, component);\n\n return [component, await compiler.build()] as [Component, CompiledComponent];\n }),\n );\n\n for (const [input, comp] of builtComps) {\n if (!input.unlisted) {\n output.info.indexes.push({\n name: input.name,\n title: input.title,\n description: input.description,\n });\n }\n\n output.components.push(comp);\n }\n\n return output;\n }\n}\n\nclass RegistryResolver {\n private readonly deps: Record<string, string | null>;\n private readonly devDeps: Record<string, string | null>;\n private readonly fileToComponent = new Map<string, [Component, ComponentFile]>();\n readonly oxc: ResolverFactory;\n\n constructor(\n private readonly compiler: RegistryCompiler,\n packageJson: PackageJson = {},\n ) {\n const registry = compiler.raw;\n\n for (const comp of registry.components) {\n for (const file of comp.files) {\n if (this.fileToComponent.has(file.path))\n console.warn(\n `the same file ${file.path} exists in multiple component, you should make the shared file a separate component.`,\n );\n this.fileToComponent.set(file.path, [comp, file]);\n }\n }\n\n this.deps = {\n ...packageJson?.dependencies,\n ...registry.dependencies,\n };\n\n this.devDeps = {\n ...packageJson?.devDependencies,\n ...registry.devDependencies,\n };\n\n // resolve anything possible\n this.oxc = new ResolverFactory({\n extensions: ['.js', '.jsx', '.ts', '.tsx', '.node'],\n conditionNames: ['node', 'import', 'require', 'default', 'types'],\n tsconfig: {\n configFile: path.join(registry.dir, registry.tsconfigPath),\n },\n });\n }\n\n getDepFromSpecifier(specifier: string) {\n return specifier.startsWith('@')\n ? specifier.split('/').slice(0, 2).join('/')\n : specifier.split('/')[0];\n }\n\n getDepInfo(name: string):\n | {\n type: 'runtime' | 'dev';\n name: string;\n version: string | null;\n }\n | undefined {\n if (name in this.deps)\n return {\n name,\n type: 'runtime',\n version: this.deps[name],\n };\n\n if (name in this.devDeps)\n return {\n name,\n type: 'dev',\n version: this.devDeps[name],\n };\n\n console.warn(`dep info for ${name} cannot be found`);\n }\n\n getComponentByName(name: string): Component | undefined {\n return this.compiler.raw.components.find((comp) => comp.name === name);\n }\n\n getSubComponent(file: string) {\n const relativeFile = path.relative(this.compiler.raw.dir, file);\n const comp = this.fileToComponent.get(relativeFile);\n\n if (!comp) return;\n return {\n component: comp[0],\n file: comp[1],\n };\n }\n}\n\nexport type SourceReference =\n | {\n type: 'file';\n /**\n * Absolute path\n */\n file: string;\n }\n | {\n type: 'dependency';\n dep: string;\n specifier: string;\n }\n | {\n type: 'sub-component';\n resolved:\n | {\n type: 'local';\n component: Component;\n file: ComponentFile;\n }\n | {\n type: 'remote';\n component: Component;\n file: ComponentFile;\n registryName: string;\n };\n }\n | {\n type: 'unknown-specifier';\n specifier: string;\n };\n\nexport type Reference =\n | SourceReference\n | {\n type: 'custom';\n specifier: string;\n };\n\nexport class ComponentCompiler {\n private readonly processedFiles = new Set<string>();\n private readonly registry: Registry;\n private readonly subComponents = new Map<string, string | z.input<typeof httpSubComponent>>();\n private readonly devDependencies = new Map<string, string | null>();\n private readonly dependencies = new Map<string, string | null>();\n\n constructor(\n private readonly compiler: RegistryCompiler,\n private readonly component: Component,\n ) {\n this.registry = compiler.raw;\n }\n\n // see https://github.com/shadcn-ui/ui/blob/396275e46a58333caa1fa0a991bd9bc5237d2ee3/packages/shadcn/src/utils/updaters/update-files.ts#L585\n // to hit the fast-path step, we need to import `target` path first because it's detected from `fileSet`, a set of output file paths\n private toImportPath(file: ComponentFile): string {\n let filePath = file.target ?? file.path;\n\n if (filePath.startsWith('./')) filePath = filePath.slice(2);\n\n return `@/${filePath.replaceAll(path.sep, '/')}`;\n }\n\n async build(): Promise<CompiledComponent> {\n return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files: (await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))).flat(),\n subComponents: Array.from(this.subComponents.values()),\n dependencies: Object.fromEntries(this.dependencies),\n devDependencies: Object.fromEntries(this.devDependencies),\n };\n }\n\n private async onBuildFile(file: ComponentFile): Promise<CompiledFile[]> {\n if (this.processedFiles.has(file.path)) return [];\n this.processedFiles.add(file.path);\n const resolver = this.compiler.resolver;\n\n const queue: ComponentFile[] = [];\n const result = await this.buildFile(file, (reference) => {\n if (reference.type === 'unknown-specifier') {\n if (!reference.specifier.startsWith('node:')) {\n console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);\n }\n\n return reference.specifier;\n }\n\n if (reference.type === 'custom') return reference.specifier;\n\n if (reference.type === 'file') {\n const refFile = this.registry.onUnknownFile?.(reference.file);\n if (refFile) {\n queue.push(refFile);\n return this.toImportPath(refFile);\n }\n\n if (refFile === false) return;\n\n throw new Error(`Unknown file ${reference.file} referenced by ${file.path}`);\n }\n\n if (reference.type === 'sub-component') {\n const resolved = reference.resolved;\n if (resolved.component.name === this.component.name)\n return this.toImportPath(resolved.file);\n\n if (resolved.type === 'remote') {\n this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {\n type: 'http',\n baseUrl: resolved.registryName,\n component: resolved.component.name,\n });\n } else {\n this.subComponents.set(resolved.component.name, resolved.component.name);\n }\n\n return this.toImportPath(resolved.file);\n }\n\n const dep = resolver.getDepInfo(reference.dep);\n if (dep) {\n const map = dep.type === 'dev' ? this.devDependencies : this.dependencies;\n map.set(dep.name, dep.version);\n }\n\n return reference.specifier;\n });\n\n return [result, ...(await Promise.all(queue.map((file) => this.onBuildFile(file)))).flat()];\n }\n\n private async buildFile(\n file: ComponentFile,\n /**\n * write references back to import specifiers\n *\n * keep original one if `undefined`\n */\n writeReference: (reference: Reference) => string | undefined,\n ): Promise<CompiledFile> {\n const sourceFilePath = path.join(this.registry.dir, file.path);\n const astTypes: Record<string, 'js' | 'ts' | undefined> = {\n '.ts': 'ts',\n '.tsx': 'ts',\n '.js': 'js',\n '.jsx': 'js',\n };\n const astType = astTypes[path.extname(file.path)];\n const content = (await fs.readFile(sourceFilePath)).toString();\n\n if (!astType)\n return {\n content,\n path: file.path,\n type: file.type,\n target: file.target,\n };\n\n const resolver = this.compiler.resolver;\n\n const ast = await parse(sourceFilePath, content, {\n astType,\n });\n\n if (ast.errors.length > 0) {\n throw new Error(`failed to parse file ${sourceFilePath}: \\n${ast.errors.join('\\n')}`);\n }\n\n const s = new MagicString(content);\n /**\n * Process import paths\n */\n transformSpecifiers(ast.program, s, (specifier) => {\n let resolved: Reference = {\n type: 'unknown-specifier',\n specifier: specifier,\n };\n const onResolve = this.component.onResolve ?? this.registry.onResolve;\n const resolvedSpecifier = resolver.oxc.resolveFileSync(sourceFilePath, specifier);\n if (resolvedSpecifier.error || !resolvedSpecifier.path) {\n return writeReference(onResolve ? onResolve(resolved) : resolved);\n }\n\n resolved = {\n type: 'file',\n file: resolvedSpecifier.path,\n };\n\n // outside of registry dir\n if (path.relative(this.registry.dir, resolvedSpecifier.path).startsWith('../')) {\n resolved = {\n type: 'dependency',\n dep: resolver.getDepFromSpecifier(specifier),\n specifier,\n };\n } else {\n const sub = resolver.getSubComponent(resolvedSpecifier.path);\n if (sub) {\n resolved = {\n type: 'sub-component',\n resolved: {\n type: 'local',\n component: sub.component,\n file: sub.file,\n },\n };\n }\n }\n\n return writeReference(onResolve ? onResolve(resolved) : resolved);\n });\n\n return {\n content: s.toString(),\n type: file.type,\n path: file.path,\n target: file.target,\n };\n }\n}\n\nexport function resolveFromRemote(\n r: Registry,\n component: string,\n selectFile: (file: ComponentFile) => boolean,\n): Reference | undefined {\n const comp = r.components.find((comp) => comp.name === component);\n if (!comp) return;\n const file = comp.files.find(selectFile);\n if (!file) return;\n\n return {\n type: 'sub-component',\n resolved: {\n type: 'remote',\n registryName: r.name,\n component: comp,\n file,\n },\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport picocolors from 'picocolors';\nimport type { CompiledRegistry } from '@/build/compiler';\n\nexport * from './compiler';\n\nexport interface MonoRegistry extends CompiledRegistry {\n registries: CompiledRegistry[];\n}\n\nexport function combineRegistry(\n root: CompiledRegistry,\n ...items: CompiledRegistry[]\n): MonoRegistry {\n return {\n ...root,\n info: {\n ...root.info,\n registries: items.map((item) => item.name),\n },\n registries: items,\n };\n}\n\nexport async function writeFumadocsRegistry(\n out: CompiledRegistry | MonoRegistry,\n options: {\n dir: string;\n\n /**\n * Remove previous outputs\n *\n * @defaultValue false\n */\n cleanDir?: boolean;\n\n log?: boolean;\n },\n): Promise<void> {\n const { dir, cleanDir = false, log = true } = options;\n\n if (cleanDir) {\n await fs.rm(dir, {\n recursive: true,\n force: true,\n });\n console.log(picocolors.bold(picocolors.greenBright('Cleaned directory')));\n }\n\n async function writeInfo() {\n const file = path.join(dir, '_registry.json');\n const json = JSON.stringify(out.info, null, 2);\n\n await writeFile(file, json, log);\n }\n\n const write = out.components.map(async (comp) => {\n const file = path.join(dir, `${comp.name}.json`);\n const json = JSON.stringify(comp, null, 2);\n\n await writeFile(file, json, log);\n });\n\n write.push(writeInfo());\n if ('registries' in out) {\n for (const child of out.registries) {\n write.push(\n writeFumadocsRegistry(child, {\n dir: path.join(dir, child.name),\n log: options.log,\n }),\n );\n }\n }\n\n await Promise.all(write);\n}\n\nasync function writeFile(file: string, content: string, log = true): Promise<void> {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n\n if (log) {\n const size = (Buffer.byteLength(content) / 1024).toFixed(2);\n\n console.log(\n `${picocolors.greenBright('+')} ${path.relative(process.cwd(), file)} ${picocolors.dim(`${size} KB`)}`,\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fs","path","file","comp","fs","path"],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n CompiledComponent,\n CompiledFile,\n httpSubComponent,\n NamespaceType,\n registryInfoSchema,\n} from '@/registry/schema';\nimport type { z } from 'zod';\nimport { parse } from 'oxc-parser';\nimport { ResolverFactory } from 'oxc-resolver';\nimport MagicString from 'magic-string';\nimport { transformSpecifiers } from '@/utils/ast';\n\nexport type OnResolve = (reference: SourceReference) => Reference;\n\nexport interface CompiledRegistry {\n name: string;\n components: CompiledComponent[];\n info: z.output<typeof registryInfoSchema>;\n}\n\nexport interface ComponentFile {\n type: NamespaceType;\n path: string;\n target?: string;\n}\n\nexport interface Component {\n name: string;\n title?: string;\n description?: string;\n files: ComponentFile[];\n\n /**\n * Don't list the component in registry index file\n */\n unlisted?: boolean;\n\n /**\n * Map imported file paths, inherit from registry if not defined.\n */\n onResolve?: OnResolve;\n}\n\nexport interface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport interface Registry extends Omit<z.input<typeof registryInfoSchema>, 'indexes'> {\n name: string;\n packageJson: string | PackageJson;\n tsconfigPath: string;\n components: Component[];\n\n /**\n * The directory of registry, used to resolve relative paths\n */\n dir: string;\n\n /**\n * Map import paths of components\n */\n onResolve?: OnResolve;\n /**\n * When a referenced file is not found in component files, this function is called.\n * @returns file, or `false` to mark as external.\n */\n onUnknownFile?: (absolutePath: string) => ComponentFile | false | undefined;\n\n dependencies?: Record<string, string | null>;\n devDependencies?: Record<string, string | null>;\n}\n\nexport class RegistryCompiler {\n readonly raw: Registry;\n resolver!: RegistryResolver;\n\n constructor(registry: Registry) {\n this.raw = registry;\n }\n\n private async readPackageJson(): Promise<PackageJson | undefined> {\n if (typeof this.raw.packageJson !== 'string') return this.raw.packageJson;\n\n return fs\n .readFile(path.join(this.raw.dir, this.raw.packageJson))\n .then((res) => JSON.parse(res.toString()) as PackageJson)\n .catch(() => undefined);\n }\n\n async compile(): Promise<CompiledRegistry> {\n const registry = this.raw;\n this.resolver = new RegistryResolver(this, await this.readPackageJson());\n const output: CompiledRegistry = {\n name: registry.name,\n info: {\n indexes: [],\n env: registry.env,\n variables: registry.variables,\n },\n components: [],\n };\n\n const builtComps = await Promise.all(\n registry.components.map(async (component) => {\n const compiler = new ComponentCompiler(this, component);\n\n return [component, await compiler.build()] as [Component, CompiledComponent];\n }),\n );\n\n for (const [input, comp] of builtComps) {\n if (!input.unlisted) {\n output.info.indexes.push({\n name: input.name,\n title: input.title,\n description: input.description,\n });\n }\n\n output.components.push(comp);\n }\n\n return output;\n }\n}\n\nclass RegistryResolver {\n private readonly deps: Record<string, string | null>;\n private readonly devDeps: Record<string, string | null>;\n private readonly fileToComponent = new Map<string, [Component, ComponentFile]>();\n readonly oxc: ResolverFactory;\n\n constructor(\n private readonly compiler: RegistryCompiler,\n packageJson: PackageJson = {},\n ) {\n const registry = compiler.raw;\n\n for (const comp of registry.components) {\n for (const file of comp.files) {\n if (this.fileToComponent.has(file.path))\n console.warn(\n `the same file ${file.path} exists in multiple component, you should make the shared file a separate component.`,\n );\n this.fileToComponent.set(file.path, [comp, file]);\n }\n }\n\n this.deps = {\n ...packageJson?.dependencies,\n ...registry.dependencies,\n };\n\n this.devDeps = {\n ...packageJson?.devDependencies,\n ...registry.devDependencies,\n };\n\n // resolve anything possible\n this.oxc = new ResolverFactory({\n extensions: ['.js', '.jsx', '.ts', '.tsx', '.node'],\n conditionNames: ['node', 'import', 'require', 'default', 'types'],\n tsconfig: {\n configFile: path.join(registry.dir, registry.tsconfigPath),\n },\n });\n }\n\n getDepFromSpecifier(specifier: string) {\n return specifier.startsWith('@')\n ? specifier.split('/').slice(0, 2).join('/')\n : specifier.split('/')[0];\n }\n\n getDepInfo(name: string):\n | {\n type: 'runtime' | 'dev';\n name: string;\n version: string | null;\n }\n | undefined {\n if (name in this.deps)\n return {\n name,\n type: 'runtime',\n version: this.deps[name],\n };\n\n if (name in this.devDeps)\n return {\n name,\n type: 'dev',\n version: this.devDeps[name],\n };\n\n console.warn(`dep info for ${name} cannot be found`);\n }\n\n getComponentByName(name: string): Component | undefined {\n return this.compiler.raw.components.find((comp) => comp.name === name);\n }\n\n getSubComponent(file: string) {\n const relativeFile = path.relative(this.compiler.raw.dir, file);\n const comp = this.fileToComponent.get(relativeFile);\n\n if (!comp) return;\n return {\n component: comp[0],\n file: comp[1],\n };\n }\n}\n\nexport type SourceReference =\n | {\n type: 'file';\n /**\n * Absolute path\n */\n file: string;\n }\n | {\n type: 'dependency';\n dep: string;\n specifier: string;\n }\n | {\n type: 'sub-component';\n resolved:\n | {\n type: 'local';\n component: Component;\n file: ComponentFile;\n }\n | {\n type: 'remote';\n component: Component;\n file: ComponentFile;\n registryName: string;\n };\n }\n | {\n type: 'unknown-specifier';\n specifier: string;\n };\n\nexport type Reference =\n | SourceReference\n | {\n type: 'custom';\n specifier: string;\n };\n\nexport class ComponentCompiler {\n private readonly processedFiles = new Set<string>();\n private readonly registry: Registry;\n private readonly subComponents = new Map<string, string | z.input<typeof httpSubComponent>>();\n private readonly devDependencies = new Map<string, string | null>();\n private readonly dependencies = new Map<string, string | null>();\n\n constructor(\n private readonly compiler: RegistryCompiler,\n private readonly component: Component,\n ) {\n this.registry = compiler.raw;\n }\n\n // see https://github.com/shadcn-ui/ui/blob/396275e46a58333caa1fa0a991bd9bc5237d2ee3/packages/shadcn/src/utils/updaters/update-files.ts#L585\n // to hit the fast-path step, we need to import `target` path first because it's detected from `fileSet`, a set of output file paths\n private toImportPath(file: ComponentFile): string {\n let filePath = file.target ?? file.path;\n\n if (filePath.startsWith('./')) filePath = filePath.slice(2);\n\n return `@/${filePath.replaceAll(path.sep, '/')}`;\n }\n\n async build(): Promise<CompiledComponent> {\n return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files: (await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))).flat(),\n subComponents: Array.from(this.subComponents.values()),\n dependencies: Object.fromEntries(this.dependencies),\n devDependencies: Object.fromEntries(this.devDependencies),\n };\n }\n\n private async onBuildFile(file: ComponentFile): Promise<CompiledFile[]> {\n if (this.processedFiles.has(file.path)) return [];\n this.processedFiles.add(file.path);\n const resolver = this.compiler.resolver;\n\n const queue: ComponentFile[] = [];\n const result = await this.buildFile(file, (reference) => {\n if (reference.type === 'unknown-specifier') {\n if (!reference.specifier.startsWith('node:')) {\n console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);\n }\n\n return reference.specifier;\n }\n\n if (reference.type === 'custom') return reference.specifier;\n\n if (reference.type === 'file') {\n const refFile = this.registry.onUnknownFile?.(reference.file);\n if (refFile) {\n queue.push(refFile);\n return this.toImportPath(refFile);\n }\n\n if (refFile === false) return;\n\n throw new Error(`Unknown file ${reference.file} referenced by ${file.path}`);\n }\n\n if (reference.type === 'sub-component') {\n const resolved = reference.resolved;\n if (resolved.component.name === this.component.name)\n return this.toImportPath(resolved.file);\n\n if (resolved.type === 'remote') {\n this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {\n type: 'http',\n baseUrl: resolved.registryName,\n component: resolved.component.name,\n });\n } else {\n this.subComponents.set(resolved.component.name, resolved.component.name);\n }\n\n return this.toImportPath(resolved.file);\n }\n\n const dep = resolver.getDepInfo(reference.dep);\n if (dep) {\n const map = dep.type === 'dev' ? this.devDependencies : this.dependencies;\n map.set(dep.name, dep.version);\n }\n\n return reference.specifier;\n });\n\n return [result, ...(await Promise.all(queue.map((file) => this.onBuildFile(file)))).flat()];\n }\n\n private async buildFile(\n file: ComponentFile,\n /**\n * write references back to import specifiers\n *\n * keep original one if `undefined`\n */\n writeReference: (reference: Reference) => string | undefined,\n ): Promise<CompiledFile> {\n const sourceFilePath = path.join(this.registry.dir, file.path);\n const astTypes: Record<string, 'js' | 'ts' | undefined> = {\n '.ts': 'ts',\n '.tsx': 'ts',\n '.js': 'js',\n '.jsx': 'js',\n };\n const astType = astTypes[path.extname(file.path)];\n const content = (await fs.readFile(sourceFilePath)).toString();\n\n if (!astType)\n return {\n content,\n path: file.path,\n type: file.type,\n target: file.target,\n };\n\n const resolver = this.compiler.resolver;\n\n const ast = await parse(sourceFilePath, content, {\n astType,\n });\n\n if (ast.errors.length > 0) {\n throw new Error(`failed to parse file ${sourceFilePath}: \\n${ast.errors.join('\\n')}`);\n }\n\n const s = new MagicString(content);\n /**\n * Process import paths\n */\n transformSpecifiers(ast.program, s, (specifier) => {\n let resolved: Reference = {\n type: 'unknown-specifier',\n specifier: specifier,\n };\n const onResolve = this.component.onResolve ?? this.registry.onResolve;\n const resolvedSpecifier = resolver.oxc.resolveFileSync(sourceFilePath, specifier);\n if (resolvedSpecifier.error || !resolvedSpecifier.path) {\n return writeReference(onResolve ? onResolve(resolved) : resolved);\n }\n\n resolved = {\n type: 'file',\n file: resolvedSpecifier.path,\n };\n\n // outside of registry dir\n if (path.relative(this.registry.dir, resolvedSpecifier.path).startsWith('../')) {\n resolved = {\n type: 'dependency',\n dep: resolver.getDepFromSpecifier(specifier),\n specifier,\n };\n } else {\n const sub = resolver.getSubComponent(resolvedSpecifier.path);\n if (sub) {\n resolved = {\n type: 'sub-component',\n resolved: {\n type: 'local',\n component: sub.component,\n file: sub.file,\n },\n };\n }\n }\n\n return writeReference(onResolve ? onResolve(resolved) : resolved);\n });\n\n return {\n content: s.toString(),\n type: file.type,\n path: file.path,\n target: file.target,\n };\n }\n}\n\nexport function resolveFromRemote(\n r: Registry,\n component: string,\n selectFile: (file: ComponentFile) => boolean,\n): Reference | undefined {\n const comp = r.components.find((comp) => comp.name === component);\n if (!comp) return;\n const file = comp.files.find(selectFile);\n if (!file) return;\n\n return {\n type: 'sub-component',\n resolved: {\n type: 'remote',\n registryName: r.name,\n component: comp,\n file,\n },\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport picocolors from 'picocolors';\nimport type { CompiledRegistry } from '@/build/compiler';\n\nexport * from './compiler';\n\nexport interface MonoRegistry extends CompiledRegistry {\n registries: CompiledRegistry[];\n}\n\nexport function combineRegistry(\n root: CompiledRegistry,\n ...items: CompiledRegistry[]\n): MonoRegistry {\n return {\n ...root,\n info: {\n ...root.info,\n registries: items.map((item) => item.name),\n },\n registries: items,\n };\n}\n\nexport async function writeFumadocsRegistry(\n out: CompiledRegistry | MonoRegistry,\n options: {\n dir: string;\n\n /**\n * Remove previous outputs\n *\n * @defaultValue false\n */\n cleanDir?: boolean;\n\n log?: boolean;\n },\n): Promise<void> {\n const { dir, cleanDir = false, log = true } = options;\n\n if (cleanDir) {\n await fs.rm(dir, {\n recursive: true,\n force: true,\n });\n console.log(picocolors.bold(picocolors.greenBright('Cleaned directory')));\n }\n\n async function writeInfo() {\n const file = path.join(dir, '_registry.json');\n const json = JSON.stringify(out.info, null, 2);\n\n await writeFile(file, json, log);\n }\n\n const write = out.components.map(async (comp) => {\n const file = path.join(dir, `${comp.name}.json`);\n const json = JSON.stringify(comp, null, 2);\n\n await writeFile(file, json, log);\n });\n\n write.push(writeInfo());\n if ('registries' in out) {\n for (const child of out.registries) {\n write.push(\n writeFumadocsRegistry(child, {\n dir: path.join(dir, child.name),\n log: options.log,\n }),\n );\n }\n }\n\n await Promise.all(write);\n}\n\nasync function writeFile(file: string, content: string, log = true): Promise<void> {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n\n if (log) {\n const size = (Buffer.byteLength(content) / 1024).toFixed(2);\n\n console.log(\n `${picocolors.greenBright('+')} ${path.relative(process.cwd(), file)} ${picocolors.dim(`${size} KB`)}`,\n );\n }\n}\n"],"mappings":";;;;;;;;;AA4EA,IAAa,mBAAb,MAA8B;CAI5B,YAAY,UAAoB;AAC9B,OAAK,MAAM;;CAGb,MAAc,kBAAoD;AAChE,MAAI,OAAO,KAAK,IAAI,gBAAgB,SAAU,QAAO,KAAK,IAAI;AAE9D,SAAOA,KACJ,SAASC,OAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,YAAY,CAAC,CACvD,MAAM,QAAQ,KAAK,MAAM,IAAI,UAAU,CAAC,CAAgB,CACxD,YAAY,OAAU;;CAG3B,MAAM,UAAqC;EACzC,MAAM,WAAW,KAAK;AACtB,OAAK,WAAW,IAAI,iBAAiB,MAAM,MAAM,KAAK,iBAAiB,CAAC;EACxE,MAAM,SAA2B;GAC/B,MAAM,SAAS;GACf,MAAM;IACJ,SAAS,EAAE;IACX,KAAK,SAAS;IACd,WAAW,SAAS;IACrB;GACD,YAAY,EAAE;GACf;EAED,MAAM,aAAa,MAAM,QAAQ,IAC/B,SAAS,WAAW,IAAI,OAAO,cAAc;AAG3C,UAAO,CAAC,WAAW,MAFF,IAAI,kBAAkB,MAAM,UAAU,CAErB,OAAO,CAAC;IAC1C,CACH;AAED,OAAK,MAAM,CAAC,OAAO,SAAS,YAAY;AACtC,OAAI,CAAC,MAAM,SACT,QAAO,KAAK,QAAQ,KAAK;IACvB,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,aAAa,MAAM;IACpB,CAAC;AAGJ,UAAO,WAAW,KAAK,KAAK;;AAG9B,SAAO;;;AAIX,IAAM,mBAAN,MAAuB;CAMrB,YACE,AAAiB,UACjB,cAA2B,EAAE,EAC7B;EAFiB;yCAJgB,IAAI,KAAyC;EAO9E,MAAM,WAAW,SAAS;AAE1B,OAAK,MAAM,QAAQ,SAAS,WAC1B,MAAK,MAAM,QAAQ,KAAK,OAAO;AAC7B,OAAI,KAAK,gBAAgB,IAAI,KAAK,KAAK,CACrC,SAAQ,KACN,iBAAiB,KAAK,KAAK,sFAC5B;AACH,QAAK,gBAAgB,IAAI,KAAK,MAAM,CAAC,MAAM,KAAK,CAAC;;AAIrD,OAAK,OAAO;GACV,GAAG,aAAa;GAChB,GAAG,SAAS;GACb;AAED,OAAK,UAAU;GACb,GAAG,aAAa;GAChB,GAAG,SAAS;GACb;AAGD,OAAK,MAAM,IAAI,gBAAgB;GAC7B,YAAY;IAAC;IAAO;IAAQ;IAAO;IAAQ;IAAQ;GACnD,gBAAgB;IAAC;IAAQ;IAAU;IAAW;IAAW;IAAQ;GACjE,UAAU,EACR,YAAYA,OAAK,KAAK,SAAS,KAAK,SAAS,aAAa,EAC3D;GACF,CAAC;;CAGJ,oBAAoB,WAAmB;AACrC,SAAO,UAAU,WAAW,IAAI,GAC5B,UAAU,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,GAC1C,UAAU,MAAM,IAAI,CAAC;;CAG3B,WAAW,MAMG;AACZ,MAAI,QAAQ,KAAK,KACf,QAAO;GACL;GACA,MAAM;GACN,SAAS,KAAK,KAAK;GACpB;AAEH,MAAI,QAAQ,KAAK,QACf,QAAO;GACL;GACA,MAAM;GACN,SAAS,KAAK,QAAQ;GACvB;AAEH,UAAQ,KAAK,gBAAgB,KAAK,kBAAkB;;CAGtD,mBAAmB,MAAqC;AACtD,SAAO,KAAK,SAAS,IAAI,WAAW,MAAM,SAAS,KAAK,SAAS,KAAK;;CAGxE,gBAAgB,MAAc;EAC5B,MAAM,eAAeA,OAAK,SAAS,KAAK,SAAS,IAAI,KAAK,KAAK;EAC/D,MAAM,OAAO,KAAK,gBAAgB,IAAI,aAAa;AAEnD,MAAI,CAAC,KAAM;AACX,SAAO;GACL,WAAW,KAAK;GAChB,MAAM,KAAK;GACZ;;;AA4CL,IAAa,oBAAb,MAA+B;CAO7B,YACE,AAAiB,UACjB,AAAiB,WACjB;EAFiB;EACA;wCARe,IAAI,KAAa;uCAElB,IAAI,KAAwD;yCAC1D,IAAI,KAA4B;sCACnC,IAAI,KAA4B;AAM9D,OAAK,WAAW,SAAS;;CAK3B,AAAQ,aAAa,MAA6B;EAChD,IAAI,WAAW,KAAK,UAAU,KAAK;AAEnC,MAAI,SAAS,WAAW,KAAK,CAAE,YAAW,SAAS,MAAM,EAAE;AAE3D,SAAO,KAAK,SAAS,WAAWA,OAAK,KAAK,IAAI;;CAGhD,MAAM,QAAoC;AACxC,SAAO;GACL,MAAM,KAAK,UAAU;GACrB,OAAO,KAAK,UAAU;GACtB,aAAa,KAAK,UAAU;GAC5B,QAAQ,MAAM,QAAQ,IAAI,KAAK,UAAU,MAAM,KAAK,SAAS,KAAK,YAAY,KAAK,CAAC,CAAC,EAAE,MAAM;GAC7F,eAAe,MAAM,KAAK,KAAK,cAAc,QAAQ,CAAC;GACtD,cAAc,OAAO,YAAY,KAAK,aAAa;GACnD,iBAAiB,OAAO,YAAY,KAAK,gBAAgB;GAC1D;;CAGH,MAAc,YAAY,MAA8C;AACtE,MAAI,KAAK,eAAe,IAAI,KAAK,KAAK,CAAE,QAAO,EAAE;AACjD,OAAK,eAAe,IAAI,KAAK,KAAK;EAClC,MAAM,WAAW,KAAK,SAAS;EAE/B,MAAM,QAAyB,EAAE;AAmDjC,SAAO,CAlDQ,MAAM,KAAK,UAAU,OAAO,cAAc;AACvD,OAAI,UAAU,SAAS,qBAAqB;AAC1C,QAAI,CAAC,UAAU,UAAU,WAAW,QAAQ,CAC1C,SAAQ,KAAK,qBAAqB,UAAU,UAAU,oBAAoB;AAG5E,WAAO,UAAU;;AAGnB,OAAI,UAAU,SAAS,SAAU,QAAO,UAAU;AAElD,OAAI,UAAU,SAAS,QAAQ;IAC7B,MAAM,UAAU,KAAK,SAAS,gBAAgB,UAAU,KAAK;AAC7D,QAAI,SAAS;AACX,WAAM,KAAK,QAAQ;AACnB,YAAO,KAAK,aAAa,QAAQ;;AAGnC,QAAI,YAAY,MAAO;AAEvB,UAAM,IAAI,MAAM,gBAAgB,UAAU,KAAK,iBAAiB,KAAK,OAAO;;AAG9E,OAAI,UAAU,SAAS,iBAAiB;IACtC,MAAM,WAAW,UAAU;AAC3B,QAAI,SAAS,UAAU,SAAS,KAAK,UAAU,KAC7C,QAAO,KAAK,aAAa,SAAS,KAAK;AAEzC,QAAI,SAAS,SAAS,SACpB,MAAK,cAAc,IAAI,GAAG,SAAS,aAAa,GAAG,SAAS,UAAU,QAAQ;KAC5E,MAAM;KACN,SAAS,SAAS;KAClB,WAAW,SAAS,UAAU;KAC/B,CAAC;QAEF,MAAK,cAAc,IAAI,SAAS,UAAU,MAAM,SAAS,UAAU,KAAK;AAG1E,WAAO,KAAK,aAAa,SAAS,KAAK;;GAGzC,MAAM,MAAM,SAAS,WAAW,UAAU,IAAI;AAC9C,OAAI,IAEF,EADY,IAAI,SAAS,QAAQ,KAAK,kBAAkB,KAAK,cACzD,IAAI,IAAI,MAAM,IAAI,QAAQ;AAGhC,UAAO,UAAU;IACjB,EAEc,IAAI,MAAM,QAAQ,IAAI,MAAM,KAAK,WAAS,KAAK,YAAYC,OAAK,CAAC,CAAC,EAAE,MAAM,CAAC;;CAG7F,MAAc,UACZ,MAMA,gBACuB;EACvB,MAAM,iBAAiBD,OAAK,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK;EAO9D,MAAM,UANoD;GACxD,OAAO;GACP,QAAQ;GACR,OAAO;GACP,QAAQ;GACT,CACwBA,OAAK,QAAQ,KAAK,KAAK;EAChD,MAAM,WAAW,MAAMD,KAAG,SAAS,eAAe,EAAE,UAAU;AAE9D,MAAI,CAAC,QACH,QAAO;GACL;GACA,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK;GACd;EAEH,MAAM,WAAW,KAAK,SAAS;EAE/B,MAAM,MAAM,MAAM,MAAM,gBAAgB,SAAS,EAC/C,SACD,CAAC;AAEF,MAAI,IAAI,OAAO,SAAS,EACtB,OAAM,IAAI,MAAM,wBAAwB,eAAe,MAAM,IAAI,OAAO,KAAK,KAAK,GAAG;EAGvF,MAAM,IAAI,IAAI,YAAY,QAAQ;;;;AAIlC,sBAAoB,IAAI,SAAS,IAAI,cAAc;GACjD,IAAI,WAAsB;IACxB,MAAM;IACK;IACZ;GACD,MAAM,YAAY,KAAK,UAAU,aAAa,KAAK,SAAS;GAC5D,MAAM,oBAAoB,SAAS,IAAI,gBAAgB,gBAAgB,UAAU;AACjF,OAAI,kBAAkB,SAAS,CAAC,kBAAkB,KAChD,QAAO,eAAe,YAAY,UAAU,SAAS,GAAG,SAAS;AAGnE,cAAW;IACT,MAAM;IACN,MAAM,kBAAkB;IACzB;AAGD,OAAIC,OAAK,SAAS,KAAK,SAAS,KAAK,kBAAkB,KAAK,CAAC,WAAW,MAAM,CAC5E,YAAW;IACT,MAAM;IACN,KAAK,SAAS,oBAAoB,UAAU;IAC5C;IACD;QACI;IACL,MAAM,MAAM,SAAS,gBAAgB,kBAAkB,KAAK;AAC5D,QAAI,IACF,YAAW;KACT,MAAM;KACN,UAAU;MACR,MAAM;MACN,WAAW,IAAI;MACf,MAAM,IAAI;MACX;KACF;;AAIL,UAAO,eAAe,YAAY,UAAU,SAAS,GAAG,SAAS;IACjE;AAEF,SAAO;GACL,SAAS,EAAE,UAAU;GACrB,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK;GACd;;;AAIL,SAAgB,kBACd,GACA,WACA,YACuB;CACvB,MAAM,OAAO,EAAE,WAAW,MAAM,WAASE,OAAK,SAAS,UAAU;AACjE,KAAI,CAAC,KAAM;CACX,MAAM,OAAO,KAAK,MAAM,KAAK,WAAW;AACxC,KAAI,CAAC,KAAM;AAEX,QAAO;EACL,MAAM;EACN,UAAU;GACR,MAAM;GACN,cAAc,EAAE;GAChB,WAAW;GACX;GACD;EACF;;;;;AClcH,SAAgB,gBACd,MACA,GAAG,OACW;AACd,QAAO;EACL,GAAG;EACH,MAAM;GACJ,GAAG,KAAK;GACR,YAAY,MAAM,KAAK,SAAS,KAAK,KAAK;GAC3C;EACD,YAAY;EACb;;AAGH,eAAsB,sBACpB,KACA,SAYe;CACf,MAAM,EAAE,KAAK,WAAW,OAAO,MAAM,SAAS;AAE9C,KAAI,UAAU;AACZ,QAAMC,KAAG,GAAG,KAAK;GACf,WAAW;GACX,OAAO;GACR,CAAC;AACF,UAAQ,IAAI,WAAW,KAAK,WAAW,YAAY,oBAAoB,CAAC,CAAC;;CAG3E,eAAe,YAAY;AAIzB,QAAM,UAHOC,OAAK,KAAK,KAAK,iBAAiB,EAChC,KAAK,UAAU,IAAI,MAAM,MAAM,EAAE,EAElB,IAAI;;CAGlC,MAAM,QAAQ,IAAI,WAAW,IAAI,OAAO,SAAS;AAI/C,QAAM,UAHOA,OAAK,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO,EACnC,KAAK,UAAU,MAAM,MAAM,EAAE,EAEd,IAAI;GAChC;AAEF,OAAM,KAAK,WAAW,CAAC;AACvB,KAAI,gBAAgB,IAClB,MAAK,MAAM,SAAS,IAAI,WACtB,OAAM,KACJ,sBAAsB,OAAO;EAC3B,KAAKA,OAAK,KAAK,KAAK,MAAM,KAAK;EAC/B,KAAK,QAAQ;EACd,CAAC,CACH;AAIL,OAAM,QAAQ,IAAI,MAAM;;AAG1B,eAAe,UAAU,MAAc,SAAiB,MAAM,MAAqB;AACjF,OAAMD,KAAG,MAAMC,OAAK,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACvD,OAAMD,KAAG,UAAU,MAAM,QAAQ;AAEjC,KAAI,KAAK;EACP,MAAM,QAAQ,OAAO,WAAW,QAAQ,GAAG,MAAM,QAAQ,EAAE;AAE3D,UAAQ,IACN,GAAG,WAAW,YAAY,IAAI,CAAC,GAAGC,OAAK,SAAS,QAAQ,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,IAAI,GAAG,KAAK,KAAK,GACrG"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
import picocolors from "picocolors";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { x } from "tinyexec";
|
|
9
|
-
import { cancel, confirm, group, intro, isCancel, log,
|
|
9
|
+
import { autocompleteMultiselect, box, cancel, confirm, group, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
10
10
|
import { parse } from "oxc-parser";
|
|
11
11
|
import { detect } from "package-manager-detector";
|
|
12
12
|
import MagicString from "magic-string";
|
|
@@ -123,7 +123,7 @@ async function runTree(args) {
|
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
125
|
//#region package.json
|
|
126
|
-
var version = "1.2.
|
|
126
|
+
var version = "1.2.3";
|
|
127
127
|
|
|
128
128
|
//#endregion
|
|
129
129
|
//#region src/registry/schema.ts
|
|
@@ -219,7 +219,7 @@ var HttpRegistryClient = class HttpRegistryClient {
|
|
|
219
219
|
return fetchCache.$value().cached(url.href, async () => {
|
|
220
220
|
const res = await fetch(`${this.baseUrl}/${name}.json`);
|
|
221
221
|
if (!res.ok) {
|
|
222
|
-
|
|
222
|
+
if (res.status === 404) throw new Error(`component ${name} not found at ${url.href}`);
|
|
223
223
|
throw new Error(await res.text());
|
|
224
224
|
}
|
|
225
225
|
return componentSchema.parse(await res.json());
|
|
@@ -250,8 +250,7 @@ var LocalRegistryClient = class LocalRegistryClient {
|
|
|
250
250
|
async fetchComponent(name) {
|
|
251
251
|
const filePath = path.join(this.dir, `${name}.json`);
|
|
252
252
|
const out = await fs.readFile(filePath).then((res) => JSON.parse(res.toString())).catch((e) => {
|
|
253
|
-
|
|
254
|
-
throw e;
|
|
253
|
+
throw new Error(`component ${name} not found at ${filePath}`, { cause: e });
|
|
255
254
|
});
|
|
256
255
|
return componentSchema.parse(out);
|
|
257
256
|
}
|
|
@@ -278,46 +277,43 @@ async function getPackageManager() {
|
|
|
278
277
|
//#endregion
|
|
279
278
|
//#region src/registry/installer/dep-manager.ts
|
|
280
279
|
var DependencyManager = class {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
280
|
+
constructor() {
|
|
281
|
+
this.installedDeps = /* @__PURE__ */ new Map();
|
|
282
|
+
this.dependencies = [];
|
|
283
|
+
this.devDependencies = [];
|
|
284
|
+
this.packageManager = "npm";
|
|
285
|
+
}
|
|
286
|
+
async init(deps, devDeps) {
|
|
287
|
+
this.installedDeps.clear();
|
|
288
|
+
if (await exists("package.json")) {
|
|
289
|
+
const content = await fs.readFile("package.json");
|
|
290
|
+
const parsed = JSON.parse(content.toString());
|
|
291
|
+
if ("dependencies" in parsed && typeof parsed.dependencies === "object") {
|
|
292
|
+
const records = parsed.dependencies;
|
|
293
|
+
for (const [k, v] of Object.entries(records)) this.installedDeps.set(k, v);
|
|
294
|
+
}
|
|
295
|
+
if ("devDependencies" in parsed && typeof parsed.devDependencies === "object") {
|
|
296
|
+
const records = parsed.devDependencies;
|
|
297
|
+
for (const [k, v] of Object.entries(records)) this.installedDeps.set(k, v);
|
|
298
|
+
}
|
|
297
299
|
}
|
|
298
|
-
|
|
300
|
+
this.dependencies = this.resolveRequiredDependencies(deps);
|
|
301
|
+
this.devDependencies = this.resolveRequiredDependencies(devDeps);
|
|
302
|
+
this.packageManager = await getPackageManager();
|
|
299
303
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return Object.entries(deps).filter(([k]) => !cachedInstalledDeps.has(k)).map(([k, v]) => v === null || v.length === 0 ? k : `${k}@${v}`);
|
|
304
|
+
resolveRequiredDependencies(deps) {
|
|
305
|
+
return Object.entries(deps).filter(([k]) => !this.installedDeps.has(k)).map(([k, v]) => v === null || v.length === 0 ? k : `${k}@${v}`);
|
|
303
306
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
${[...items, ...devItems].map((v) => `- ${v}`).join("\n")}` });
|
|
311
|
-
if (isCancel(value) || !value) return;
|
|
312
|
-
const spin = spinner();
|
|
313
|
-
spin.start("Installing dependencies...");
|
|
314
|
-
if (items.length > 0) await x(manager, ["install", ...items]);
|
|
315
|
-
if (devItems.length > 0) await x(manager, [
|
|
307
|
+
hasRequired() {
|
|
308
|
+
return this.dependencies.length > 0 || this.devDependencies.length > 0;
|
|
309
|
+
}
|
|
310
|
+
async installRequired() {
|
|
311
|
+
if (this.dependencies.length > 0) await x(this.packageManager, ["install", ...this.dependencies]);
|
|
312
|
+
if (this.devDependencies.length > 0) await x(this.packageManager, [
|
|
316
313
|
"install",
|
|
317
|
-
...
|
|
314
|
+
...this.devDependencies,
|
|
318
315
|
"-D"
|
|
319
316
|
]);
|
|
320
|
-
spin.stop("Dependencies installed.");
|
|
321
317
|
}
|
|
322
318
|
};
|
|
323
319
|
|
|
@@ -333,7 +329,7 @@ var ComponentInstaller = class {
|
|
|
333
329
|
this.devDependencies = {};
|
|
334
330
|
this.pathToFileCache = createCache();
|
|
335
331
|
}
|
|
336
|
-
async install(name) {
|
|
332
|
+
async install(name, io) {
|
|
337
333
|
let downloaded;
|
|
338
334
|
const info = await this.rootClient.fetchRegistryInfo();
|
|
339
335
|
for (const registry of info.registries ?? []) if (name.startsWith(`${registry}/`)) {
|
|
@@ -349,30 +345,28 @@ var ComponentInstaller = class {
|
|
|
349
345
|
const outPath = this.resolveOutputPath(file);
|
|
350
346
|
if (this.installedFiles.has(outPath)) continue;
|
|
351
347
|
this.installedFiles.add(outPath);
|
|
352
|
-
const output = typescriptExtensions.includes(path.extname(outPath)) ? await this.transform(name, file, comp, downloaded) : file.content;
|
|
348
|
+
const output = typescriptExtensions.includes(path.extname(outPath)) ? await this.transform(io, name, file, comp, downloaded) : file.content;
|
|
353
349
|
const status = await fs.readFile(outPath).then((res) => {
|
|
354
350
|
if (res.toString() === output) return "ignore";
|
|
355
351
|
return "need-update";
|
|
356
352
|
}).catch(() => "write");
|
|
357
353
|
if (status === "ignore") continue;
|
|
358
354
|
if (status === "need-update") {
|
|
359
|
-
|
|
360
|
-
message: `Do you want to override ${outPath}?`,
|
|
361
|
-
initialValue: false
|
|
362
|
-
});
|
|
363
|
-
if (isCancel(override)) {
|
|
364
|
-
outro("Ended");
|
|
365
|
-
process.exit(0);
|
|
366
|
-
}
|
|
367
|
-
if (!override) continue;
|
|
355
|
+
if (!await io.confirmFileOverride({ path: outPath })) continue;
|
|
368
356
|
}
|
|
369
357
|
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
370
358
|
await fs.writeFile(outPath, output);
|
|
371
|
-
|
|
359
|
+
io.onFileDownloaded({
|
|
360
|
+
path: outPath,
|
|
361
|
+
file,
|
|
362
|
+
component: comp
|
|
363
|
+
});
|
|
372
364
|
}
|
|
373
365
|
}
|
|
374
|
-
async
|
|
375
|
-
|
|
366
|
+
async deps() {
|
|
367
|
+
const manager = new DependencyManager();
|
|
368
|
+
await manager.init(this.dependencies, this.devDependencies);
|
|
369
|
+
return manager;
|
|
376
370
|
}
|
|
377
371
|
async onEnd() {
|
|
378
372
|
const config = this.rootClient.config;
|
|
@@ -405,7 +399,7 @@ var ComponentInstaller = class {
|
|
|
405
399
|
variables
|
|
406
400
|
}));
|
|
407
401
|
}
|
|
408
|
-
async transform(taskId, file, component, allComponents) {
|
|
402
|
+
async transform(io, taskId, file, component, allComponents) {
|
|
409
403
|
const filePath = this.resolveOutputPath(file);
|
|
410
404
|
const parsed = await parse(filePath, file.content);
|
|
411
405
|
const s = new MagicString(file.content);
|
|
@@ -422,7 +416,7 @@ var ComponentInstaller = class {
|
|
|
422
416
|
const lookup = specifier.substring(2);
|
|
423
417
|
const target = pathToFile.get(lookup);
|
|
424
418
|
if (target) specifier = toImportSpecifier(filePath, this.resolveOutputPath(target));
|
|
425
|
-
else
|
|
419
|
+
else io.onWarn(`cannot find the referenced file of ${specifier}`);
|
|
426
420
|
}
|
|
427
421
|
return specifier;
|
|
428
422
|
});
|
|
@@ -480,7 +474,7 @@ async function add(input, client) {
|
|
|
480
474
|
hint: item.description
|
|
481
475
|
});
|
|
482
476
|
spin.stop(picocolors.bold(picocolors.greenBright("registry fetched")));
|
|
483
|
-
const value = await
|
|
477
|
+
const value = await autocompleteMultiselect({
|
|
484
478
|
message: "Select components to install",
|
|
485
479
|
options
|
|
486
480
|
});
|
|
@@ -494,17 +488,52 @@ async function add(input, client) {
|
|
|
494
488
|
}
|
|
495
489
|
async function install(target, installer) {
|
|
496
490
|
for (const name of target) {
|
|
497
|
-
|
|
491
|
+
const spin = spinner();
|
|
492
|
+
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));
|
|
498
493
|
try {
|
|
499
|
-
await installer.install(name
|
|
500
|
-
|
|
494
|
+
await installer.install(name, {
|
|
495
|
+
onWarn(message) {
|
|
496
|
+
spin.message(message);
|
|
497
|
+
},
|
|
498
|
+
async confirmFileOverride(options) {
|
|
499
|
+
spin.clear();
|
|
500
|
+
const value = await confirm({
|
|
501
|
+
message: `Do you want to override ${options.path}?`,
|
|
502
|
+
initialValue: false
|
|
503
|
+
});
|
|
504
|
+
if (isCancel(value)) {
|
|
505
|
+
outro("Installation terminated");
|
|
506
|
+
process.exit(0);
|
|
507
|
+
}
|
|
508
|
+
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));
|
|
509
|
+
return value;
|
|
510
|
+
},
|
|
511
|
+
onFileDownloaded(options) {
|
|
512
|
+
spin.message(options.path);
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
spin.stop(picocolors.bold(picocolors.greenBright(`${name} installed`)));
|
|
501
516
|
} catch (e) {
|
|
502
|
-
|
|
503
|
-
|
|
517
|
+
spin.error(e instanceof Error ? e.message : String(e));
|
|
518
|
+
process.exit(-1);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const deps = await installer.deps();
|
|
522
|
+
if (deps.hasRequired()) {
|
|
523
|
+
log.message();
|
|
524
|
+
box([...deps.dependencies, ...deps.devDependencies].join("\n"), "New Dependencies");
|
|
525
|
+
const value = await confirm({ message: `Do you want to install with ${deps.packageManager}?` });
|
|
526
|
+
if (isCancel(value)) {
|
|
527
|
+
outro("Installation terminated");
|
|
528
|
+
process.exit(0);
|
|
529
|
+
}
|
|
530
|
+
if (value) {
|
|
531
|
+
const spin = spinner({ errorMessage: "Failed to install dependencies" });
|
|
532
|
+
spin.start("Installing dependencies");
|
|
533
|
+
await deps.installRequired();
|
|
534
|
+
spin.stop("Dependencies installed");
|
|
504
535
|
}
|
|
505
536
|
}
|
|
506
|
-
intro(picocolors.bold("New Dependencies"));
|
|
507
|
-
await installer.installDeps();
|
|
508
537
|
await installer.onEnd();
|
|
509
538
|
outro(picocolors.bold(picocolors.greenBright("Successful")));
|
|
510
539
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isSrc","baseUrl: string","config: LoadedConfig","dir: string","rootClient: RegistryClient","plugins: ComponentInstallerPlugin[]","downloaded: DownloadedComponent[]","result: DownloadedComponent[]","file","target: string[]","options: {\n label: string;\n value: string;\n hint?: string;\n }[]","packageJson.version","dirShortcuts: Record<string, string>","nodes: JsonTreeNode[]"],"sources":["../src/utils/fs.ts","../src/utils/is-src.ts","../src/config.ts","../src/commands/file-tree.ts","../src/utils/file-tree/run-tree.ts","../package.json","../src/registry/schema.ts","../src/utils/cache.ts","../src/registry/client.ts","../src/utils/get-package-manager.ts","../src/registry/installer/dep-manager.ts","../src/registry/installer/index.ts","../src/commands/shared.ts","../src/commands/add.ts","../src/commands/customise.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function exists(pathLike: string): Promise<boolean> {\n try {\n await fs.access(pathLike);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isRelative(from: string, to: string): boolean {\n return !path.relative(from, to).startsWith(`..${path.sep}`);\n}\n","import { exists } from '@/utils/fs';\n\nexport async function isSrc(): Promise<boolean> {\n return exists('./src');\n}\n","import fs from 'node:fs/promises';\nimport { isSrc } from '@/utils/is-src';\nimport { z } from 'zod';\n\nexport function createConfigSchema(isSrc: boolean) {\n const defaultAliases = {\n uiDir: './components/ui',\n componentsDir: './components',\n blockDir: './components',\n cssDir: './styles',\n libDir: './lib',\n };\n\n return z.object({\n $schema: z\n .string()\n .default(\n isSrc\n ? 'node_modules/@fumadocs/cli/dist/schema/src.json'\n : 'node_modules/@fumadocs/cli/dist/schema/default.json',\n )\n .optional(),\n aliases: z\n .object({\n uiDir: z.string().default(defaultAliases.uiDir),\n componentsDir: z.string().default(defaultAliases.uiDir),\n blockDir: z.string().default(defaultAliases.blockDir),\n cssDir: z.string().default(defaultAliases.componentsDir),\n libDir: z.string().default(defaultAliases.libDir),\n })\n .default(defaultAliases),\n\n baseDir: z.string().default(isSrc ? 'src' : ''),\n uiLibrary: z.enum(['radix-ui', 'base-ui']).default('radix-ui'),\n\n commands: z\n .object({\n /**\n * command to format output code automatically\n */\n format: z.string().optional(),\n })\n .default({}),\n });\n}\n\ntype ConfigSchema = ReturnType<typeof createConfigSchema>;\n\nexport type ConfigInput = z.input<ConfigSchema>;\nexport type LoadedConfig = z.output<ConfigSchema>;\n\nexport async function createOrLoadConfig(file = './cli.json'): Promise<LoadedConfig> {\n const inited = await initConfig(file);\n if (inited) return inited;\n\n const content = (await fs.readFile(file)).toString();\n const src = await isSrc();\n const configSchema = createConfigSchema(src);\n\n return configSchema.parse(JSON.parse(content));\n}\n\n/**\n * Write new config, skip if a config already exists\n *\n * @returns the created config, `undefined` if not created\n */\nexport async function initConfig(\n file = './cli.json',\n src?: boolean,\n): Promise<LoadedConfig | undefined> {\n if (\n await fs\n .stat(file)\n .then(() => true)\n .catch(() => false)\n ) {\n return;\n }\n\n const defaultConfig = createConfigSchema(src ?? (await isSrc())).parse({} satisfies ConfigInput);\n await fs.writeFile(file, JSON.stringify(defaultConfig, null, 2));\n return defaultConfig;\n}\n","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 { z } from 'zod';\n\nexport type NamespaceType = (typeof namespaces)[number];\nexport type CompiledFile = z.input<typeof fileSchema>;\nexport type CompiledComponent = z.input<typeof componentSchema>;\nexport type CompiledRegistryInfo = z.input<typeof registryInfoSchema>;\nexport type DownloadedRegistryInfo = z.output<typeof registryInfoSchema>;\nexport type File = z.output<typeof fileSchema>;\nexport type Component = z.output<typeof componentSchema>;\n\nexport const namespaces = ['components', 'lib', 'css', 'route', 'ui', 'block'] as const;\n\nexport const indexSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n});\n\nexport const fileSchema = z.object({\n type: z.literal(namespaces),\n path: z.string(),\n target: z.string().optional(),\n content: z.string(),\n});\n\nexport const httpSubComponent = z.object({\n type: z.literal('http'),\n baseUrl: z.string(),\n component: z.string(),\n});\n\nexport const componentSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n files: z.array(fileSchema),\n dependencies: z.record(z.string(), z.string().or(z.null())),\n devDependencies: z.record(z.string(), z.string().or(z.null())),\n /**\n * list of sub components, either local (component name) or remote (registry info & component name)\n */\n subComponents: z.array(z.string().or(httpSubComponent)).default([]),\n});\n\nexport const registryInfoSchema = z.object({\n /**\n * define used variables, variables can be referenced in the import specifiers of component files.\n */\n variables: z\n .record(\n z.string(),\n z.object({\n description: z.string().optional(),\n default: z.unknown().optional(),\n }),\n )\n .optional(),\n /**\n * provide variables to sub components\n */\n env: z.record(z.string(), z.unknown()).optional(),\n indexes: z.array(indexSchema).default([]),\n\n registries: z.array(z.string()).optional(),\n});\n","export interface AsyncCache<V> {\n cached: (\n key: string,\n fn: (\n /**\n * set a cache value before the compute function completes.\n *\n * useful to handle recursive access.\n */\n presolve: (v: V) => void,\n ) => V | Promise<V>,\n ) => V | Promise<V>;\n $value: <T>() => AsyncCache<T>;\n invalidate: (key: string) => void;\n}\n\n/**\n * cache for async resources, finished promises will be resolved into original value, otherwise wrapped with a promise.\n */\nexport function createCache<V>(store = new Map<string, V | Promise<V>>()): AsyncCache<V> {\n return {\n cached(key, fn) {\n let cached = store.get(key);\n if (cached) return cached;\n\n cached = fn((v) => store.set(key, v));\n if (cached instanceof Promise) {\n cached = cached.then((out) => {\n // replace with resolved if still exists\n if (store.has(key)) {\n store.set(key, out);\n }\n\n return out;\n });\n }\n store.set(key, cached);\n return cached;\n },\n invalidate(key) {\n store.delete(key);\n },\n $value<T>() {\n return this as unknown as AsyncCache<T>;\n },\n };\n}\n","import {\n type DownloadedRegistryInfo,\n type Component,\n componentSchema,\n registryInfoSchema,\n} from '@/registry/schema';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport type { LoadedConfig } from '@/config';\nimport { log } from '@clack/prompts';\nimport { createCache } from '@/utils/cache';\n\nexport interface RegistryClient {\n readonly registryId: string;\n readonly config: LoadedConfig;\n fetchRegistryInfo: () => Promise<DownloadedRegistryInfo>;\n fetchComponent: (name: string) => Promise<Component>;\n hasComponent: (name: string) => Promise<boolean>;\n createLinkedRegistryClient: (registryName: string) => RegistryClient;\n}\n\nconst fetchCache = createCache<unknown>();\n\nexport class HttpRegistryClient implements RegistryClient {\n readonly registryId: string;\n\n constructor(\n readonly baseUrl: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = baseUrl;\n }\n\n async fetchRegistryInfo(baseUrl = this.baseUrl) {\n const url = new URL('_registry.json', `${baseUrl}/`);\n\n return fetchCache.$value<DownloadedRegistryInfo>().cached(url.href, async () => {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);\n }\n\n return registryInfoSchema.parse(await res.json());\n });\n }\n\n async fetchComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n\n return fetchCache.$value<Component>().cached(url.href, async () => {\n const res = await fetch(`${this.baseUrl}/${name}.json`);\n if (!res.ok) {\n log.error(`component ${name} not found at ${url.href}`);\n throw new Error(await res.text());\n }\n\n return componentSchema.parse(await res.json());\n });\n }\n\n async hasComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok;\n }\n\n createLinkedRegistryClient(name: string) {\n return new HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);\n }\n}\n\nexport class LocalRegistryClient implements RegistryClient {\n readonly registryId: string;\n private registryInfo: DownloadedRegistryInfo | undefined;\n\n constructor(\n private readonly dir: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = dir;\n }\n\n async fetchRegistryInfo(dir = this.dir) {\n if (this.registryInfo) return this.registryInfo;\n\n const filePath = path.join(dir, '_registry.json');\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`failed to resolve local file \"${filePath}\"`, {\n cause: e,\n });\n });\n\n return (this.registryInfo = registryInfoSchema.parse(out));\n }\n\n async fetchComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n log.error(`component ${name} not found at ${filePath}`);\n throw e;\n });\n\n return componentSchema.parse(out);\n }\n\n async hasComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n try {\n await fs.stat(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n createLinkedRegistryClient(name: string) {\n return new LocalRegistryClient(path.join(this.dir, name), this.config);\n }\n}\n","import { detect, type AgentName } from 'package-manager-detector';\n\nexport type PackageManager = AgentName;\n\nexport async function getPackageManager(): Promise<PackageManager> {\n const result = await detect();\n\n return result?.name ?? 'npm';\n}\n","import { exists } from '@/utils/fs';\nimport fs from 'node:fs/promises';\nimport { getPackageManager } from '@/utils/get-package-manager';\nimport { confirm, isCancel, spinner } from '@clack/prompts';\nimport { x } from 'tinyexec';\n\nexport class DependencyManager {\n private cachedInstalledDeps: Map<string, string> | undefined;\n\n /**\n * Get dependencies from `package.json`\n */\n async getDeps(): Promise<Map<string, string>> {\n if (this.cachedInstalledDeps) return this.cachedInstalledDeps;\n const dependencies = new Map<string, string>();\n\n if (!(await exists('package.json'))) return dependencies;\n\n const content = await fs.readFile('package.json');\n const parsed = JSON.parse(content.toString()) as object;\n\n if ('dependencies' in parsed && typeof parsed.dependencies === 'object') {\n const records = parsed.dependencies as Record<string, string>;\n\n for (const [k, v] of Object.entries(records)) {\n dependencies.set(k, v);\n }\n }\n\n if ('devDependencies' in parsed && typeof parsed.devDependencies === 'object') {\n const records = parsed.devDependencies as Record<string, string>;\n\n for (const [k, v] of Object.entries(records)) {\n dependencies.set(k, v);\n }\n }\n\n return (this.cachedInstalledDeps = dependencies);\n }\n\n private async resolveInstallDependencies(deps: Record<string, string | null>): Promise<string[]> {\n const cachedInstalledDeps = await this.getDeps();\n\n return Object.entries(deps)\n .filter(([k]) => !cachedInstalledDeps.has(k))\n .map(([k, v]) => (v === null || v.length === 0 ? k : `${k}@${v}`));\n }\n\n async installDeps(deps: Record<string, string | null>, devDeps: Record<string, string | null>) {\n const items = await this.resolveInstallDependencies(deps);\n const devItems = await this.resolveInstallDependencies(devDeps);\n if (items.length === 0 && devItems.length === 0) return;\n\n const manager = await getPackageManager();\n const value = await confirm({\n message: `Do you want to install with ${manager}?\n${[...items, ...devItems].map((v) => `- ${v}`).join('\\n')}`,\n });\n\n if (isCancel(value) || !value) {\n return;\n }\n\n const spin = spinner();\n spin.start('Installing dependencies...');\n if (items.length > 0) await x(manager, ['install', ...items]);\n if (devItems.length > 0) await x(manager, ['install', ...devItems, '-D']);\n spin.stop('Dependencies installed.');\n }\n}\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { confirm, isCancel, log, outro } from '@clack/prompts';\nimport { typescriptExtensions } from '@/constants';\nimport { toImportSpecifier, transformSpecifiers } from '@/utils/ast';\nimport type { Component, File } from '@/registry/schema';\nimport { HttpRegistryClient, type RegistryClient } from '@/registry/client';\nimport { x } from 'tinyexec';\nimport { DependencyManager } from '@/registry/installer/dep-manager';\nimport { createCache } from '@/utils/cache';\nimport { parse, type ParseResult } from 'oxc-parser';\nimport MagicString from 'magic-string';\n\ninterface DownloadedComponent extends Omit<Component, 'subComponents'> {\n variables?: Record<string, unknown>;\n}\n\nexport interface ComponentInstallerPlugin {\n /**\n * transform file downloaded from components\n */\n transformFile?: (context: {\n s: MagicString;\n parsed: ParseResult;\n\n file: File;\n component: DownloadedComponent;\n }) => void | Promise<void>;\n}\n\nexport class ComponentInstaller {\n private readonly installedFiles = new Set<string>();\n private readonly downloadCache = createCache<DownloadedComponent[]>();\n readonly dependencies: Record<string, string | null> = {};\n readonly devDependencies: Record<string, string | null> = {};\n\n constructor(\n private readonly rootClient: RegistryClient,\n private readonly plugins: ComponentInstallerPlugin[] = [],\n ) {}\n\n async install(name: string) {\n let downloaded: DownloadedComponent[];\n // detect linked registry\n const info = await this.rootClient.fetchRegistryInfo();\n\n for (const registry of info.registries ?? []) {\n if (name.startsWith(`${registry}/`)) {\n downloaded = await this.download(\n name.slice(registry.length + 1),\n this.rootClient.createLinkedRegistryClient(registry),\n );\n break;\n }\n }\n\n downloaded ??= await this.download(name, this.rootClient);\n\n for (const item of downloaded) {\n Object.assign(this.dependencies, item.dependencies);\n Object.assign(this.devDependencies, item.devDependencies);\n }\n\n for (const comp of downloaded) {\n for (const file of comp.files) {\n const outPath = this.resolveOutputPath(file);\n if (this.installedFiles.has(outPath)) continue;\n this.installedFiles.add(outPath);\n\n const output = typescriptExtensions.includes(path.extname(outPath))\n ? await this.transform(name, file, comp, downloaded)\n : file.content;\n\n const status = await fs\n .readFile(outPath)\n .then((res) => {\n if (res.toString() === output) return 'ignore';\n return 'need-update';\n })\n .catch(() => 'write');\n\n if (status === 'ignore') continue;\n\n if (status === 'need-update') {\n const override = await confirm({\n message: `Do you want to override ${outPath}?`,\n initialValue: false,\n });\n\n if (isCancel(override)) {\n outro('Ended');\n process.exit(0);\n }\n\n if (!override) continue;\n }\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, output);\n log.step(`downloaded ${outPath}`);\n }\n }\n }\n\n async installDeps() {\n await new DependencyManager().installDeps(this.dependencies, this.devDependencies);\n }\n\n async onEnd() {\n const config = this.rootClient.config;\n if (config.commands.format) {\n await x(config.commands.format);\n }\n }\n\n /**\n * return a list of components, merged with child components & variables.\n */\n private async download(\n name: string,\n client: RegistryClient,\n contextVariables?: Record<string, unknown>,\n ): Promise<DownloadedComponent[]> {\n const hash = `${client.registryId} ${name}`;\n const info = await client.fetchRegistryInfo();\n const variables = { ...contextVariables, ...info.env };\n for (const [k, v] of Object.entries(info.variables ?? {})) {\n variables[k] ??= v.default;\n }\n\n const out = await this.downloadCache.cached(hash, async (presolve) => {\n const comp = await client.fetchComponent(name);\n const result: DownloadedComponent[] = [comp];\n // place it before downloading child components to avoid recursive downloads\n presolve(result);\n\n const child = await Promise.all(\n comp.subComponents.map((sub) => {\n if (typeof sub === 'string') return this.download(sub, client);\n const baseUrl =\n this.rootClient instanceof HttpRegistryClient\n ? new URL(sub.baseUrl, `${this.rootClient.baseUrl}/`).href\n : sub.baseUrl;\n\n return this.download(\n sub.component,\n new HttpRegistryClient(baseUrl, client.config),\n variables,\n );\n }),\n );\n for (const sub of child) result.push(...sub);\n return result;\n });\n\n return out.map((file) => ({ ...file, variables }));\n }\n\n private readonly pathToFileCache = createCache<Map<string, File>>();\n private async transform(\n taskId: string,\n file: File,\n component: DownloadedComponent,\n allComponents: DownloadedComponent[],\n ): Promise<string> {\n const filePath = this.resolveOutputPath(file);\n const parsed = await parse(filePath, file.content);\n const s = new MagicString(file.content);\n\n // transform alias\n const prefix = '@/';\n const variables = Object.entries(component.variables ?? {});\n const pathToFile = await this.pathToFileCache.cached(taskId, () => {\n const map = new Map<string, File>();\n for (const comp of allComponents) {\n for (const file of comp.files) map.set(file.target ?? file.path, file);\n }\n return map;\n });\n\n transformSpecifiers(parsed.program, s, (specifier) => {\n for (const [k, v] of variables) {\n specifier = specifier.replaceAll(`<${k}>`, v as string);\n }\n\n if (specifier.startsWith(prefix)) {\n const lookup = specifier.substring(prefix.length);\n const target = pathToFile.get(lookup);\n\n if (target) {\n specifier = toImportSpecifier(filePath, this.resolveOutputPath(target));\n } else {\n console.warn(`cannot find the referenced file of ${specifier}`);\n }\n }\n\n return specifier;\n });\n\n for (const plugin of this.plugins) {\n await plugin.transformFile?.({\n s,\n parsed,\n file,\n component,\n });\n }\n\n return s.toString();\n }\n\n private resolveOutputPath(file: File): string {\n const config = this.rootClient.config;\n const dir = (\n {\n components: config.aliases.componentsDir,\n block: config.aliases.blockDir,\n ui: config.aliases.uiDir,\n css: config.aliases.cssDir,\n lib: config.aliases.libDir,\n route: './',\n } as const\n )[file.type];\n if (file.target) {\n return path.join(config.baseDir, file.target.replace('<dir>', dir));\n }\n\n return path.join(config.baseDir, dir, path.basename(file.path));\n }\n}\n","export const UIRegistries = {\n 'base-ui': 'fumadocs/base-ui',\n 'radix-ui': 'fumadocs/radix-ui',\n};\n","import { intro, isCancel, log, multiselect, outro, spinner } from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { ComponentInstaller } from '@/registry/installer';\nimport type { RegistryClient } from '@/registry/client';\nimport { UIRegistries } from '@/commands/shared';\n\nexport async function add(input: string[], client: RegistryClient) {\n const config = client.config;\n let target: string[];\n const installer = new ComponentInstaller(client);\n const registry = UIRegistries[config.uiLibrary];\n\n if (input.length === 0) {\n const spin = spinner();\n spin.start('fetching registry');\n const info = await client.fetchRegistryInfo();\n const options: {\n label: string;\n value: string;\n hint?: string;\n }[] = [];\n\n for (const item of info.indexes) {\n options.push({\n label: item.title ?? item.name,\n value: item.name,\n hint: item.description,\n });\n }\n const { indexes } = await client.createLinkedRegistryClient(registry).fetchRegistryInfo();\n\n for (const item of indexes) {\n options.push({\n label: item.title ?? item.name,\n value: `${registry}/${item.name}`,\n hint: item.description,\n });\n }\n\n spin.stop(picocolors.bold(picocolors.greenBright('registry fetched')));\n const value = await multiselect({\n message: 'Select components to install',\n options,\n });\n\n if (isCancel(value)) {\n outro('Ended');\n return;\n }\n\n target = value;\n } else {\n target = await Promise.all(\n input.map(async (item) => ((await client.hasComponent(item)) ? item : `${registry}/${item}`)),\n );\n }\n\n await install(target, installer);\n}\n\nexport async function install(target: string[], installer: ComponentInstaller) {\n for (const name of target) {\n intro(picocolors.bold(picocolors.inverse(picocolors.cyanBright(`Add Component: ${name}`))));\n\n try {\n await installer.install(name);\n outro(picocolors.bold(picocolors.greenBright(`${name} installed`)));\n } catch (e) {\n log.error(String(e));\n throw e;\n }\n }\n\n intro(picocolors.bold('New Dependencies'));\n\n await installer.installDeps();\n await installer.onEnd();\n\n outro(picocolors.bold(picocolors.greenBright('Successful')));\n}\n","import { cancel, group, intro, log, outro, select } from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { install } from '@/commands/add';\nimport type { RegistryClient } from '@/registry/client';\nimport { ComponentInstaller } from '@/registry/installer';\nimport { UIRegistries } from '@/commands/shared';\n\nexport async function customise(client: RegistryClient) {\n intro(picocolors.bgBlack(picocolors.whiteBright('Customise Fumadocs UI')));\n const config = client.config;\n const installer = new ComponentInstaller(client);\n\n const result = await group(\n {\n target: () =>\n select({\n message: 'What do you want to customise?',\n options: [\n {\n label: 'Docs Layout',\n value: 'docs',\n hint: 'main UI of your docs',\n },\n {\n label: 'Home Layout',\n value: 'home',\n hint: 'the navbar for your other pages',\n },\n ],\n }),\n mode: (v) => {\n if (v.results.target !== 'docs') return;\n\n return select({\n message: 'Which variant do you want to start from?',\n options: [\n {\n label: 'Start from minimal styles',\n value: 'minimal',\n hint: 'for those who want to build their own variant from ground up.',\n },\n {\n label: 'Start from default layout',\n value: 'full-default',\n hint: 'useful for adjusting small details.',\n },\n {\n label: 'Start from Notebook layout',\n value: 'full-notebook',\n hint: 'useful for adjusting small details.',\n },\n ],\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const registry = UIRegistries[config.uiLibrary];\n if (result.target === 'docs') {\n const targets = [];\n if (result.mode === 'minimal') {\n targets.push('fumadocs/ui/layouts/docs-min');\n } else {\n targets.push(\n result.mode === 'full-default'\n ? `${registry}/layouts/docs`\n : `${registry}/layouts/notebook`,\n );\n }\n\n await install(targets, installer);\n const maps: [string, string][] =\n result.mode === 'full-notebook'\n ? [\n ['fumadocs-ui/layouts/notebook', '@/components/layout/notebook'],\n ['fumadocs-ui/layouts/notebook/page', '@/components/layout/notebook/page'],\n ]\n : [\n ['fumadocs-ui/layouts/docs', '@/components/layout/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/components/layout/docs/page'],\n ];\n\n printNext(...maps);\n }\n\n if (result.target === 'home') {\n await install([`${registry}/layouts/home`], installer);\n printNext(['fumadocs-ui/layouts/home', `@/components/layout/home`]);\n }\n\n outro(picocolors.bold('Have fun!'));\n}\n\nfunction printNext(...maps: [from: string, to: string][]) {\n intro(picocolors.bold('What is Next?'));\n\n log.info(\n [\n 'You can check the installed components in `components`.',\n picocolors.dim('---'),\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","#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport picocolors from 'picocolors';\nimport { createOrLoadConfig, initConfig, type LoadedConfig } 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 { HttpRegistryClient, LocalRegistryClient } from '@/registry/client';\n\nconst program = new Command().option('--config <string>');\n\nprogram\n .name('fumadocs')\n .description('CLI to setup Fumadocs, init a config')\n .version(packageJson.version)\n .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\nprogram\n .command('customise')\n .alias('customize')\n .description('simple way to customise layouts with Fumadocs UI')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (options: { config?: string; dir?: string }) => {\n await customise(createClientFromDir(options.dir, await createOrLoadConfig(options.config)));\n });\n\nconst dirShortcuts: Record<string, string> = {\n ':preview': 'https://preview.fumadocs.dev/registry',\n ':dev': 'http://localhost:3000/registry',\n};\n\nprogram\n .command('add')\n .description('add a new component to your docs')\n .argument('[components...]', 'components to download')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (input: string[], options: { config?: string; dir?: string }) => {\n const client = createClientFromDir(options.dir, await createOrLoadConfig(options.config));\n await add(input, client);\n });\n\nprogram\n .command('tree')\n .argument('[json_or_args]', 'JSON output of `tree` command or arguments for the `tree` command')\n .argument('[output]', 'output path of file')\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', config: LoadedConfig) {\n if (dir in dirShortcuts) dir = dirShortcuts[dir];\n\n return dir.startsWith('http://') || dir.startsWith('https://')\n ? new HttpRegistryClient(dir, config)\n : new LocalRegistryClient(dir, config);\n}\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isSrc","file","packageJson.version"],"sources":["../src/utils/fs.ts","../src/utils/is-src.ts","../src/config.ts","../src/commands/file-tree.ts","../src/utils/file-tree/run-tree.ts","../package.json","../src/registry/schema.ts","../src/utils/cache.ts","../src/registry/client.ts","../src/utils/get-package-manager.ts","../src/registry/installer/dep-manager.ts","../src/registry/installer/index.ts","../src/commands/shared.ts","../src/commands/add.ts","../src/commands/customise.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function exists(pathLike: string): Promise<boolean> {\n try {\n await fs.access(pathLike);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isRelative(from: string, to: string): boolean {\n return !path.relative(from, to).startsWith(`..${path.sep}`);\n}\n","import { exists } from '@/utils/fs';\n\nexport async function isSrc(): Promise<boolean> {\n return exists('./src');\n}\n","import fs from 'node:fs/promises';\nimport { isSrc } from '@/utils/is-src';\nimport { z } from 'zod';\n\nexport function createConfigSchema(isSrc: boolean) {\n const defaultAliases = {\n uiDir: './components/ui',\n componentsDir: './components',\n blockDir: './components',\n cssDir: './styles',\n libDir: './lib',\n };\n\n return z.object({\n $schema: z\n .string()\n .default(\n isSrc\n ? 'node_modules/@fumadocs/cli/dist/schema/src.json'\n : 'node_modules/@fumadocs/cli/dist/schema/default.json',\n )\n .optional(),\n aliases: z\n .object({\n uiDir: z.string().default(defaultAliases.uiDir),\n componentsDir: z.string().default(defaultAliases.uiDir),\n blockDir: z.string().default(defaultAliases.blockDir),\n cssDir: z.string().default(defaultAliases.componentsDir),\n libDir: z.string().default(defaultAliases.libDir),\n })\n .default(defaultAliases),\n\n baseDir: z.string().default(isSrc ? 'src' : ''),\n uiLibrary: z.enum(['radix-ui', 'base-ui']).default('radix-ui'),\n\n commands: z\n .object({\n /**\n * command to format output code automatically\n */\n format: z.string().optional(),\n })\n .default({}),\n });\n}\n\ntype ConfigSchema = ReturnType<typeof createConfigSchema>;\n\nexport type ConfigInput = z.input<ConfigSchema>;\nexport type LoadedConfig = z.output<ConfigSchema>;\n\nexport async function createOrLoadConfig(file = './cli.json'): Promise<LoadedConfig> {\n const inited = await initConfig(file);\n if (inited) return inited;\n\n const content = (await fs.readFile(file)).toString();\n const src = await isSrc();\n const configSchema = createConfigSchema(src);\n\n return configSchema.parse(JSON.parse(content));\n}\n\n/**\n * Write new config, skip if a config already exists\n *\n * @returns the created config, `undefined` if not created\n */\nexport async function initConfig(\n file = './cli.json',\n src?: boolean,\n): Promise<LoadedConfig | undefined> {\n if (\n await fs\n .stat(file)\n .then(() => true)\n .catch(() => false)\n ) {\n return;\n }\n\n const defaultConfig = createConfigSchema(src ?? (await isSrc())).parse({} satisfies ConfigInput);\n await fs.writeFile(file, JSON.stringify(defaultConfig, null, 2));\n return defaultConfig;\n}\n","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 { z } from 'zod';\n\nexport type NamespaceType = (typeof namespaces)[number];\nexport type CompiledFile = z.input<typeof fileSchema>;\nexport type CompiledComponent = z.input<typeof componentSchema>;\nexport type CompiledRegistryInfo = z.input<typeof registryInfoSchema>;\nexport type DownloadedRegistryInfo = z.output<typeof registryInfoSchema>;\nexport type File = z.output<typeof fileSchema>;\nexport type Component = z.output<typeof componentSchema>;\n\nexport const namespaces = ['components', 'lib', 'css', 'route', 'ui', 'block'] as const;\n\nexport const indexSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n});\n\nexport const fileSchema = z.object({\n type: z.literal(namespaces),\n path: z.string(),\n target: z.string().optional(),\n content: z.string(),\n});\n\nexport const httpSubComponent = z.object({\n type: z.literal('http'),\n baseUrl: z.string(),\n component: z.string(),\n});\n\nexport const componentSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n files: z.array(fileSchema),\n dependencies: z.record(z.string(), z.string().or(z.null())),\n devDependencies: z.record(z.string(), z.string().or(z.null())),\n /**\n * list of sub components, either local (component name) or remote (registry info & component name)\n */\n subComponents: z.array(z.string().or(httpSubComponent)).default([]),\n});\n\nexport const registryInfoSchema = z.object({\n /**\n * define used variables, variables can be referenced in the import specifiers of component files.\n */\n variables: z\n .record(\n z.string(),\n z.object({\n description: z.string().optional(),\n default: z.unknown().optional(),\n }),\n )\n .optional(),\n /**\n * provide variables to sub components\n */\n env: z.record(z.string(), z.unknown()).optional(),\n indexes: z.array(indexSchema).default([]),\n\n registries: z.array(z.string()).optional(),\n});\n","export interface AsyncCache<V> {\n cached: (\n key: string,\n fn: (\n /**\n * set a cache value before the compute function completes.\n *\n * useful to handle recursive access.\n */\n presolve: (v: V) => void,\n ) => V | Promise<V>,\n ) => V | Promise<V>;\n $value: <T>() => AsyncCache<T>;\n invalidate: (key: string) => void;\n}\n\n/**\n * cache for async resources, finished promises will be resolved into original value, otherwise wrapped with a promise.\n */\nexport function createCache<V>(store = new Map<string, V | Promise<V>>()): AsyncCache<V> {\n return {\n cached(key, fn) {\n let cached = store.get(key);\n if (cached) return cached;\n\n cached = fn((v) => store.set(key, v));\n if (cached instanceof Promise) {\n cached = cached.then((out) => {\n // replace with resolved if still exists\n if (store.has(key)) {\n store.set(key, out);\n }\n\n return out;\n });\n }\n store.set(key, cached);\n return cached;\n },\n invalidate(key) {\n store.delete(key);\n },\n $value<T>() {\n return this as unknown as AsyncCache<T>;\n },\n };\n}\n","import {\n type DownloadedRegistryInfo,\n type Component,\n componentSchema,\n registryInfoSchema,\n} from '@/registry/schema';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport type { LoadedConfig } from '@/config';\nimport { createCache } from '@/utils/cache';\n\nexport interface RegistryClient {\n readonly registryId: string;\n readonly config: LoadedConfig;\n fetchRegistryInfo: () => Promise<DownloadedRegistryInfo>;\n fetchComponent: (name: string) => Promise<Component>;\n hasComponent: (name: string) => Promise<boolean>;\n createLinkedRegistryClient: (registryName: string) => RegistryClient;\n}\n\nconst fetchCache = createCache<unknown>();\n\nexport class HttpRegistryClient implements RegistryClient {\n readonly registryId: string;\n\n constructor(\n readonly baseUrl: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = baseUrl;\n }\n\n async fetchRegistryInfo(baseUrl = this.baseUrl) {\n const url = new URL('_registry.json', `${baseUrl}/`);\n\n return fetchCache.$value<DownloadedRegistryInfo>().cached(url.href, async () => {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);\n }\n\n return registryInfoSchema.parse(await res.json());\n });\n }\n\n async fetchComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n\n return fetchCache.$value<Component>().cached(url.href, async () => {\n const res = await fetch(`${this.baseUrl}/${name}.json`);\n if (!res.ok) {\n if (res.status === 404) {\n throw new Error(`component ${name} not found at ${url.href}`);\n }\n throw new Error(await res.text());\n }\n\n return componentSchema.parse(await res.json());\n });\n }\n\n async hasComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok;\n }\n\n createLinkedRegistryClient(name: string) {\n return new HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);\n }\n}\n\nexport class LocalRegistryClient implements RegistryClient {\n readonly registryId: string;\n private registryInfo: DownloadedRegistryInfo | undefined;\n\n constructor(\n private readonly dir: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = dir;\n }\n\n async fetchRegistryInfo(dir = this.dir) {\n if (this.registryInfo) return this.registryInfo;\n\n const filePath = path.join(dir, '_registry.json');\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`failed to resolve local file \"${filePath}\"`, {\n cause: e,\n });\n });\n\n return (this.registryInfo = registryInfoSchema.parse(out));\n }\n\n async fetchComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`component ${name} not found at ${filePath}`, { cause: e });\n });\n\n return componentSchema.parse(out);\n }\n\n async hasComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n try {\n await fs.stat(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n createLinkedRegistryClient(name: string) {\n return new LocalRegistryClient(path.join(this.dir, name), this.config);\n }\n}\n","import { detect, type AgentName } from 'package-manager-detector';\n\nexport type PackageManager = AgentName;\n\nexport async function getPackageManager(): Promise<PackageManager> {\n const result = await detect();\n\n return result?.name ?? 'npm';\n}\n","import { exists } from '@/utils/fs';\nimport fs from 'node:fs/promises';\nimport { getPackageManager, PackageManager } from '@/utils/get-package-manager';\nimport { x } from 'tinyexec';\n\nexport class DependencyManager {\n private installedDeps = new Map<string, string>();\n dependencies: string[] = [];\n devDependencies: string[] = [];\n packageManager: PackageManager = 'npm';\n\n async init(deps: Record<string, string | null>, devDeps: Record<string, string | null>) {\n this.installedDeps.clear();\n if (await exists('package.json')) {\n const content = await fs.readFile('package.json');\n const parsed = JSON.parse(content.toString()) as object;\n\n if ('dependencies' in parsed && typeof parsed.dependencies === 'object') {\n const records = parsed.dependencies as Record<string, string>;\n\n for (const [k, v] of Object.entries(records)) {\n this.installedDeps.set(k, v);\n }\n }\n\n if ('devDependencies' in parsed && typeof parsed.devDependencies === 'object') {\n const records = parsed.devDependencies as Record<string, string>;\n\n for (const [k, v] of Object.entries(records)) {\n this.installedDeps.set(k, v);\n }\n }\n }\n\n this.dependencies = this.resolveRequiredDependencies(deps);\n this.devDependencies = this.resolveRequiredDependencies(devDeps);\n this.packageManager = await getPackageManager();\n }\n\n private resolveRequiredDependencies(deps: Record<string, string | null>): string[] {\n return Object.entries(deps)\n .filter(([k]) => !this.installedDeps.has(k))\n .map(([k, v]) => (v === null || v.length === 0 ? k : `${k}@${v}`));\n }\n\n hasRequired() {\n return this.dependencies.length > 0 || this.devDependencies.length > 0;\n }\n\n async installRequired() {\n if (this.dependencies.length > 0)\n await x(this.packageManager, ['install', ...this.dependencies]);\n if (this.devDependencies.length > 0)\n await x(this.packageManager, ['install', ...this.devDependencies, '-D']);\n }\n}\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { typescriptExtensions } from '@/constants';\nimport { toImportSpecifier, transformSpecifiers } from '@/utils/ast';\nimport type { Component, File } from '@/registry/schema';\nimport { HttpRegistryClient, type RegistryClient } from '@/registry/client';\nimport { x } from 'tinyexec';\nimport { DependencyManager } from '@/registry/installer/dep-manager';\nimport { createCache } from '@/utils/cache';\nimport { parse, type ParseResult } from 'oxc-parser';\nimport MagicString from 'magic-string';\n\ninterface DownloadedComponent extends Omit<Component, 'subComponents'> {\n variables?: Record<string, unknown>;\n}\n\nexport interface ComponentInstallerPlugin {\n /**\n * transform file downloaded from components\n */\n transformFile?: (context: {\n s: MagicString;\n parsed: ParseResult;\n\n file: File;\n component: DownloadedComponent;\n }) => void | Promise<void>;\n}\n\nexport interface IOInterface {\n onWarn: (message: string) => void;\n confirmFileOverride: (options: { path: string }) => Promise<boolean>;\n onFileDownloaded: (options: { path: string; file: File; component: DownloadedComponent }) => void;\n}\n\nexport class ComponentInstaller {\n private readonly installedFiles = new Set<string>();\n private readonly downloadCache = createCache<DownloadedComponent[]>();\n readonly dependencies: Record<string, string | null> = {};\n readonly devDependencies: Record<string, string | null> = {};\n\n constructor(\n private readonly rootClient: RegistryClient,\n private readonly plugins: ComponentInstallerPlugin[] = [],\n ) {}\n\n async install(name: string, io: IOInterface) {\n let downloaded: DownloadedComponent[];\n // detect linked registry\n const info = await this.rootClient.fetchRegistryInfo();\n\n for (const registry of info.registries ?? []) {\n if (name.startsWith(`${registry}/`)) {\n downloaded = await this.download(\n name.slice(registry.length + 1),\n this.rootClient.createLinkedRegistryClient(registry),\n );\n break;\n }\n }\n\n downloaded ??= await this.download(name, this.rootClient);\n\n for (const item of downloaded) {\n Object.assign(this.dependencies, item.dependencies);\n Object.assign(this.devDependencies, item.devDependencies);\n }\n\n for (const comp of downloaded) {\n for (const file of comp.files) {\n const outPath = this.resolveOutputPath(file);\n if (this.installedFiles.has(outPath)) continue;\n this.installedFiles.add(outPath);\n\n const output = typescriptExtensions.includes(path.extname(outPath))\n ? await this.transform(io, name, file, comp, downloaded)\n : file.content;\n\n const status = await fs\n .readFile(outPath)\n .then((res) => {\n if (res.toString() === output) return 'ignore';\n return 'need-update';\n })\n .catch(() => 'write');\n\n if (status === 'ignore') continue;\n\n if (status === 'need-update') {\n const override = await io.confirmFileOverride({ path: outPath });\n if (!override) continue;\n }\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, output);\n io.onFileDownloaded({ path: outPath, file, component: comp });\n }\n }\n }\n\n async deps() {\n const manager = new DependencyManager();\n await manager.init(this.dependencies, this.devDependencies);\n return manager;\n }\n\n async onEnd() {\n const config = this.rootClient.config;\n if (config.commands.format) {\n await x(config.commands.format);\n }\n }\n\n /**\n * return a list of components, merged with child components & variables.\n */\n private async download(\n name: string,\n client: RegistryClient,\n contextVariables?: Record<string, unknown>,\n ): Promise<DownloadedComponent[]> {\n const hash = `${client.registryId} ${name}`;\n const info = await client.fetchRegistryInfo();\n const variables = { ...contextVariables, ...info.env };\n for (const [k, v] of Object.entries(info.variables ?? {})) {\n variables[k] ??= v.default;\n }\n\n const out = await this.downloadCache.cached(hash, async (presolve) => {\n const comp = await client.fetchComponent(name);\n const result: DownloadedComponent[] = [comp];\n // place it before downloading child components to avoid recursive downloads\n presolve(result);\n\n const child = await Promise.all(\n comp.subComponents.map((sub) => {\n if (typeof sub === 'string') return this.download(sub, client);\n const baseUrl =\n this.rootClient instanceof HttpRegistryClient\n ? new URL(sub.baseUrl, `${this.rootClient.baseUrl}/`).href\n : sub.baseUrl;\n\n return this.download(\n sub.component,\n new HttpRegistryClient(baseUrl, client.config),\n variables,\n );\n }),\n );\n for (const sub of child) result.push(...sub);\n return result;\n });\n\n return out.map((file) => ({ ...file, variables }));\n }\n\n private readonly pathToFileCache = createCache<Map<string, File>>();\n private async transform(\n io: IOInterface,\n taskId: string,\n file: File,\n component: DownloadedComponent,\n allComponents: DownloadedComponent[],\n ): Promise<string> {\n const filePath = this.resolveOutputPath(file);\n const parsed = await parse(filePath, file.content);\n const s = new MagicString(file.content);\n\n // transform alias\n const prefix = '@/';\n const variables = Object.entries(component.variables ?? {});\n const pathToFile = await this.pathToFileCache.cached(taskId, () => {\n const map = new Map<string, File>();\n for (const comp of allComponents) {\n for (const file of comp.files) map.set(file.target ?? file.path, file);\n }\n return map;\n });\n\n transformSpecifiers(parsed.program, s, (specifier) => {\n for (const [k, v] of variables) {\n specifier = specifier.replaceAll(`<${k}>`, v as string);\n }\n\n if (specifier.startsWith(prefix)) {\n const lookup = specifier.substring(prefix.length);\n const target = pathToFile.get(lookup);\n\n if (target) {\n specifier = toImportSpecifier(filePath, this.resolveOutputPath(target));\n } else {\n io.onWarn(`cannot find the referenced file of ${specifier}`);\n }\n }\n\n return specifier;\n });\n\n for (const plugin of this.plugins) {\n await plugin.transformFile?.({\n s,\n parsed,\n file,\n component,\n });\n }\n\n return s.toString();\n }\n\n private resolveOutputPath(file: File): string {\n const config = this.rootClient.config;\n const dir = (\n {\n components: config.aliases.componentsDir,\n block: config.aliases.blockDir,\n ui: config.aliases.uiDir,\n css: config.aliases.cssDir,\n lib: config.aliases.libDir,\n route: './',\n } as const\n )[file.type];\n if (file.target) {\n return path.join(config.baseDir, file.target.replace('<dir>', dir));\n }\n\n return path.join(config.baseDir, dir, path.basename(file.path));\n }\n}\n","export const UIRegistries = {\n 'base-ui': 'fumadocs/base-ui',\n 'radix-ui': 'fumadocs/radix-ui',\n};\n","import {\n isCancel,\n autocompleteMultiselect,\n outro,\n spinner,\n confirm,\n box,\n log,\n} from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { ComponentInstaller } from '@/registry/installer';\nimport type { RegistryClient } from '@/registry/client';\nimport { UIRegistries } from '@/commands/shared';\n\nexport async function add(input: string[], client: RegistryClient) {\n const config = client.config;\n let target: string[];\n const installer = new ComponentInstaller(client);\n const registry = UIRegistries[config.uiLibrary];\n\n if (input.length === 0) {\n const spin = spinner();\n spin.start('fetching registry');\n const info = await client.fetchRegistryInfo();\n const options: {\n label: string;\n value: string;\n hint?: string;\n }[] = [];\n\n for (const item of info.indexes) {\n options.push({\n label: item.title ?? item.name,\n value: item.name,\n hint: item.description,\n });\n }\n const { indexes } = await client.createLinkedRegistryClient(registry).fetchRegistryInfo();\n\n for (const item of indexes) {\n options.push({\n label: item.title ?? item.name,\n value: `${registry}/${item.name}`,\n hint: item.description,\n });\n }\n\n spin.stop(picocolors.bold(picocolors.greenBright('registry fetched')));\n const value = await autocompleteMultiselect({\n message: 'Select components to install',\n options,\n });\n\n if (isCancel(value)) {\n outro('Ended');\n return;\n }\n\n target = value;\n } else {\n target = await Promise.all(\n input.map(async (item) => ((await client.hasComponent(item)) ? item : `${registry}/${item}`)),\n );\n }\n\n await install(target, installer);\n}\n\nexport async function install(target: string[], installer: ComponentInstaller) {\n for (const name of target) {\n const spin = spinner();\n spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));\n\n try {\n await installer.install(name, {\n onWarn(message) {\n spin.message(message);\n },\n async confirmFileOverride(options) {\n spin.clear();\n const value = await confirm({\n message: `Do you want to override ${options.path}?`,\n initialValue: false,\n });\n if (isCancel(value)) {\n outro('Installation terminated');\n process.exit(0);\n }\n spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));\n return value;\n },\n onFileDownloaded(options) {\n spin.message(options.path);\n },\n });\n spin.stop(picocolors.bold(picocolors.greenBright(`${name} installed`)));\n } catch (e) {\n spin.error(e instanceof Error ? e.message : String(e));\n process.exit(-1);\n }\n }\n\n const deps = await installer.deps();\n if (deps.hasRequired()) {\n log.message();\n box([...deps.dependencies, ...deps.devDependencies].join('\\n'), 'New Dependencies');\n const value = await confirm({\n message: `Do you want to install with ${deps.packageManager}?`,\n });\n\n if (isCancel(value)) {\n outro('Installation terminated');\n process.exit(0);\n }\n\n if (value) {\n const spin = spinner({\n errorMessage: 'Failed to install dependencies',\n });\n spin.start('Installing dependencies');\n await deps.installRequired();\n spin.stop('Dependencies installed');\n }\n }\n\n await installer.onEnd();\n outro(picocolors.bold(picocolors.greenBright('Successful')));\n}\n","import { cancel, group, intro, log, outro, select } from '@clack/prompts';\nimport picocolors from 'picocolors';\nimport { install } from '@/commands/add';\nimport type { RegistryClient } from '@/registry/client';\nimport { ComponentInstaller } from '@/registry/installer';\nimport { UIRegistries } from '@/commands/shared';\n\nexport async function customise(client: RegistryClient) {\n intro(picocolors.bgBlack(picocolors.whiteBright('Customise Fumadocs UI')));\n const config = client.config;\n const installer = new ComponentInstaller(client);\n\n const result = await group(\n {\n target: () =>\n select({\n message: 'What do you want to customise?',\n options: [\n {\n label: 'Docs Layout',\n value: 'docs',\n hint: 'main UI of your docs',\n },\n {\n label: 'Home Layout',\n value: 'home',\n hint: 'the navbar for your other pages',\n },\n ],\n }),\n mode: (v) => {\n if (v.results.target !== 'docs') return;\n\n return select({\n message: 'Which variant do you want to start from?',\n options: [\n {\n label: 'Start from minimal styles',\n value: 'minimal',\n hint: 'for those who want to build their own variant from ground up.',\n },\n {\n label: 'Start from default layout',\n value: 'full-default',\n hint: 'useful for adjusting small details.',\n },\n {\n label: 'Start from Notebook layout',\n value: 'full-notebook',\n hint: 'useful for adjusting small details.',\n },\n ],\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const registry = UIRegistries[config.uiLibrary];\n if (result.target === 'docs') {\n const targets = [];\n if (result.mode === 'minimal') {\n targets.push('fumadocs/ui/layouts/docs-min');\n } else {\n targets.push(\n result.mode === 'full-default'\n ? `${registry}/layouts/docs`\n : `${registry}/layouts/notebook`,\n );\n }\n\n await install(targets, installer);\n const maps: [string, string][] =\n result.mode === 'full-notebook'\n ? [\n ['fumadocs-ui/layouts/notebook', '@/components/layout/notebook'],\n ['fumadocs-ui/layouts/notebook/page', '@/components/layout/notebook/page'],\n ]\n : [\n ['fumadocs-ui/layouts/docs', '@/components/layout/docs'],\n ['fumadocs-ui/layouts/docs/page', '@/components/layout/docs/page'],\n ];\n\n printNext(...maps);\n }\n\n if (result.target === 'home') {\n await install([`${registry}/layouts/home`], installer);\n printNext(['fumadocs-ui/layouts/home', `@/components/layout/home`]);\n }\n\n outro(picocolors.bold('Have fun!'));\n}\n\nfunction printNext(...maps: [from: string, to: string][]) {\n intro(picocolors.bold('What is Next?'));\n\n log.info(\n [\n 'You can check the installed components in `components`.',\n picocolors.dim('---'),\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","#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport picocolors from 'picocolors';\nimport { createOrLoadConfig, initConfig, type LoadedConfig } 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 { HttpRegistryClient, LocalRegistryClient } from '@/registry/client';\n\nconst program = new Command().option('--config <string>');\n\nprogram\n .name('fumadocs')\n .description('CLI to setup Fumadocs, init a config')\n .version(packageJson.version)\n .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\nprogram\n .command('customise')\n .alias('customize')\n .description('simple way to customise layouts with Fumadocs UI')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (options: { config?: string; dir?: string }) => {\n await customise(createClientFromDir(options.dir, await createOrLoadConfig(options.config)));\n });\n\nconst dirShortcuts: Record<string, string> = {\n ':preview': 'https://preview.fumadocs.dev/registry',\n ':dev': 'http://localhost:3000/registry',\n};\n\nprogram\n .command('add')\n .description('add a new component to your docs')\n .argument('[components...]', 'components to download')\n .option('--dir <string>', 'the root url or directory to resolve registry')\n .action(async (input: string[], options: { config?: string; dir?: string }) => {\n const client = createClientFromDir(options.dir, await createOrLoadConfig(options.config));\n await add(input, client);\n });\n\nprogram\n .command('tree')\n .argument('[json_or_args]', 'JSON output of `tree` command or arguments for the `tree` command')\n .argument('[output]', 'output path of file')\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', config: LoadedConfig) {\n if (dir in dirShortcuts) dir = dirShortcuts[dir];\n\n return dir.startsWith('http://') || dir.startsWith('https://')\n ? new HttpRegistryClient(dir, config)\n : new LocalRegistryClient(dir, config);\n}\n\nprogram.parse();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fumadocs/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "The CLI tool for Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Docs",
|
|
@@ -28,21 +28,21 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@clack/prompts": "^0.
|
|
31
|
+
"@clack/prompts": "^1.0.0",
|
|
32
32
|
"commander": "^14.0.2",
|
|
33
33
|
"magic-string": "^0.30.21",
|
|
34
|
-
"oxc-parser": "^0.
|
|
35
|
-
"oxc-resolver": "^11.
|
|
34
|
+
"oxc-parser": "^0.111.0",
|
|
35
|
+
"oxc-resolver": "^11.17.0",
|
|
36
36
|
"package-manager-detector": "^1.6.0",
|
|
37
37
|
"picocolors": "^1.1.1",
|
|
38
38
|
"tinyexec": "^1.0.2",
|
|
39
|
-
"zod": "^4.3.
|
|
39
|
+
"zod": "^4.3.6"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oxc-project/types": "^0.
|
|
43
|
-
"@types/node": "
|
|
44
|
-
"shadcn": "3.
|
|
45
|
-
"tsdown": "^0.
|
|
42
|
+
"@oxc-project/types": "^0.111.0",
|
|
43
|
+
"@types/node": "25.1.0",
|
|
44
|
+
"shadcn": "3.7.0",
|
|
45
|
+
"tsdown": "^0.19.0",
|
|
46
46
|
"eslint-config-custom": "0.0.0",
|
|
47
47
|
"tsconfig": "0.0.0"
|
|
48
48
|
},
|