fix type errors

This commit is contained in:
Fuma Nama
2026-04-07 18:50:16 +08:00
parent 40e5813cdc
commit 7c59264cbc
11 changed files with 197 additions and 167 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
---
"fumadocs-typescript": patch
'fumadocs-typescript': patch
---
fix `remarkAutoTypeTable` not serializing `deprecated` field to MDX output
+6
View File
@@ -0,0 +1,6 @@
---
'create-fumadocs-app': patch
'@fumadocs/cli': patch
---
Adopt Fuma CLI
+2 -1
View File
@@ -18,7 +18,8 @@
],
"type": "module",
"exports": {
".": "./dist/config.js",
"./config": "./dist/config.js",
"./registry/installer": "./dist/registry/installer.js",
"./package.json": "./package.json"
},
"publishConfig": {
+3 -53
View File
@@ -1,18 +1,9 @@
import {
isCancel,
autocompleteMultiselect,
outro,
spinner,
confirm,
box,
log,
} from '@clack/prompts';
import { isCancel, autocompleteMultiselect, outro, spinner } from '@clack/prompts';
import picocolors from 'picocolors';
import { UIRegistries } from '@/commands/shared';
import { detect } from 'package-manager-detector';
import { RegistryConnector } from 'fuma-cli/registry/connector';
import { LoadedConfig } from '@/config';
import { FumadocsComponentInstaller } from '@/registry/utils';
import { FumadocsComponentInstaller } from '@/registry/installer';
interface AddOption {
label: string;
@@ -64,49 +55,8 @@ export async function add(input: string[], connector: RegistryConnector, config:
);
}
await install(targets, installer);
}
export async function install(targets: Target[], installer: FumadocsComponentInstaller) {
for (const target of targets) {
const spin = spinner();
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${target.name}`)));
try {
installer.installing = { name: target.name, spin };
const deps = await installer
.install(target.name, target.subRegistry)
.then((res) => res.deps());
spin.stop(picocolors.bold(picocolors.greenBright(`${target.name} installed`)));
if (deps.hasRequired()) {
log.message();
box([...deps.dependencies, ...deps.devDependencies].join('\n'), 'New Dependencies');
const pm = (await detect())?.name ?? 'npm';
const value = await confirm({
message: `Do you want to install with ${pm}?`,
});
if (isCancel(value)) {
outro('Installation terminated');
process.exit(0);
}
if (value) {
const spin = spinner({
errorMessage: 'Failed to install dependencies',
});
spin.start('Installing dependencies');
await deps.installRequired(pm);
spin.stop('Dependencies installed');
} else {
await deps.writeRequired();
}
}
} catch (e) {
spin.error(e instanceof Error ? e.message : String(e));
process.exit(-1);
}
await installer.installInteractive(target.name, target.subRegistry);
}
outro(picocolors.bold(picocolors.greenBright('Successful')));
+8 -5
View File
@@ -1,10 +1,10 @@
import { cancel, group, intro, log, outro, select } from '@clack/prompts';
import picocolors from 'picocolors';
import { install, Target } from '@/commands/add';
import type { Target } from '@/commands/add';
import { UIRegistries } from '@/commands/shared';
import { LoadedConfig } from '@/config';
import { RegistryConnector } from 'fuma-cli/registry/connector';
import { FumadocsComponentInstaller } from '@/registry/utils';
import { FumadocsComponentInstaller } from '@/registry/installer';
interface TargetInfo {
targets: Target[];
@@ -168,9 +168,12 @@ export async function customise(config: LoadedConfig, connector: RegistryConnect
},
);
const target = result.target as TargetInfo;
await install(target.targets, installer);
target.print?.();
const targetInfo = result.target as TargetInfo;
for (const target of targetInfo.targets) {
await installer.installInteractive(target.name, target.subRegistry);
}
targetInfo.print?.();
outro(picocolors.bold('Have fun!'));
}
+98
View File
@@ -0,0 +1,98 @@
import { ComponentInstaller } from 'fuma-cli/registry/installer';
import { pluginPreserveLayouts } from './plugins/preserve';
import { RegistryConnector } from 'fuma-cli/registry/connector';
import type { LoadedConfig } from '@/config';
import { box, confirm, isCancel, log, outro, spinner, SpinnerResult } from '@clack/prompts';
import picocolors from 'picocolors';
import { detect } from 'package-manager-detector';
export class FumadocsComponentInstaller extends ComponentInstaller {
private interactive: {
name: string;
spin: SpinnerResult;
} | null = null;
constructor(connector: RegistryConnector, config: LoadedConfig, cwd?: string) {
super(connector, {
cwd,
framework: config.framework,
outDir: {
base: config.baseDir,
components: config.aliases.componentsDir,
css: config.aliases.cssDir,
layout: config.aliases.layoutDir,
lib: config.aliases.libDir,
ui: config.aliases.uiDir,
},
io: {
onWarn: (message) => {
this.interactive?.spin.message(message);
},
confirmFileOverride: async (options) => {
if (!this.interactive) return true;
const { name, spin } = this.interactive;
spin.clear();
const value = await confirm({
message: `Do you want to override ${options.path}?`,
initialValue: false,
});
if (isCancel(value)) {
outro('Installation terminated');
process.exit(0);
}
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));
return value;
},
onFileDownloaded: (options) => {
this.interactive?.spin.message(options.path);
},
},
plugins: [pluginPreserveLayouts()],
});
}
async installInteractive(name: string, subRegistry?: string): Promise<void> {
if (this.interactive) {
throw new Error(`cannot install while installing another component`);
}
const spin = spinner();
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));
try {
this.interactive = { name, spin };
const deps = await super.install(name, subRegistry).then((res) => res.deps());
spin.stop(picocolors.bold(picocolors.greenBright(`${name} installed`)));
if (deps.hasRequired()) {
log.message();
box([...deps.dependencies, ...deps.devDependencies].join('\n'), 'New Dependencies');
const pm = (await detect())?.name ?? 'npm';
const value = await confirm({
message: `Do you want to install with ${pm}?`,
});
if (isCancel(value)) {
outro('Installation terminated');
process.exit(0);
}
if (value) {
const spin = spinner({
errorMessage: 'Failed to install dependencies',
});
spin.start('Installing dependencies');
await deps.installRequired(pm);
spin.stop('Dependencies installed');
} else {
await deps.writeRequired();
}
}
} catch (e) {
spin.error(e instanceof Error ? e.message : String(e));
process.exit(-1);
} finally {
this.interactive = null;
}
}
}
-51
View File
@@ -1,51 +0,0 @@
import { ComponentInstaller } from 'fuma-cli/registry/installer';
import { pluginPreserveLayouts } from './plugins/preserve';
import { RegistryConnector } from 'fuma-cli/registry/connector';
import type { LoadedConfig } from '@/config';
import { confirm, isCancel, outro, SpinnerResult } from '@clack/prompts';
import picocolors from 'picocolors';
export class FumadocsComponentInstaller extends ComponentInstaller {
installing?: {
name: string;
spin: SpinnerResult;
};
constructor(connector: RegistryConnector, config: LoadedConfig) {
super(connector, {
framework: config.framework,
outDir: {
base: config.baseDir,
components: config.aliases.componentsDir,
css: config.aliases.cssDir,
layout: config.aliases.layoutDir,
lib: config.aliases.libDir,
ui: config.aliases.uiDir,
},
io: {
onWarn: (message) => {
this.installing?.spin.message(message);
},
confirmFileOverride: async (options) => {
if (!this.installing) return true;
const { name, spin } = this.installing;
spin.clear();
const value = await confirm({
message: `Do you want to override ${options.path}?`,
initialValue: false,
});
if (isCancel(value)) {
outro('Installation terminated');
process.exit(0);
}
spin.start(picocolors.bold(picocolors.cyanBright(`Installing ${name}`)));
return value;
},
onFileDownloaded: (options) => {
this.installing?.spin.message(options.path);
},
},
plugins: [pluginPreserveLayouts()],
});
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ import { createConfigSchema } from './src/config';
import { z } from 'zod';
export default defineConfig({
entry: ['./src/{index,config}.ts'],
entry: ['./src/{index,config}.ts', './src/registry/installer.ts'],
format: 'esm',
dts: true,
fixedExtension: false,
+1
View File
@@ -46,6 +46,7 @@
"@commander-js/extra-typings": "^14.0.0",
"@fumadocs/cli": "workspace:*",
"commander": "^14.0.3",
"fuma-cli": "^0.0.2",
"picocolors": "^1.1.1",
"tinyexec": "^1.0.4",
"ts-morph": "^27.0.2"
+20 -32
View File
@@ -1,50 +1,38 @@
import { TemplatePlugin, TemplatePluginContext } from '@/index';
import { ComponentInstaller } from '@fumadocs/cli/registry/installer';
import { getDefaultConfig } from '@fumadocs/cli/config';
import { HttpRegistryClient } from '@fumadocs/cli/registry/client';
import { createSourceFile } from '@/transform/shared';
import path from 'node:path';
import fs from 'node:fs/promises';
import { SyntaxKind } from 'ts-morph';
import { FumadocsComponentInstaller } from '@fumadocs/cli/registry/installer';
import { HttpRegistryConnector } from 'fuma-cli/registry/connector';
import { getDefaultConfig } from '@fumadocs/cli/config';
export function ai(provider: 'openrouter' | 'inkeep'): TemplatePlugin {
return {
async afterWrite() {
const config = await getDefaultConfig(this.dest);
await install(
`ai/${provider}`,
new ComponentInstaller(new HttpRegistryClient('https://fumadocs.dev/registry', config), {
cwd: this.dest,
}),
);
await addAIChat(this);
await fs.writeFile(
path.join(this.dest, '.env.local'),
provider === 'openrouter' ? 'OPENROUTER_API_KEY=' : 'INKEEP_API_KEY=',
const installer = new FumadocsComponentInstaller(
new HttpRegistryConnector('https://fumadocs.dev/registry'),
config,
this.dest,
);
try {
const deps = await installer.install(`ai/${provider}`).then((res) => res.deps());
if (deps.hasRequired()) await deps.writeRequired();
await addAIChat(this);
await fs.writeFile(
path.join(this.dest, '.env.local'),
provider === 'openrouter' ? 'OPENROUTER_API_KEY=' : 'INKEEP_API_KEY=',
);
} catch (e) {
console.error(e);
}
},
};
}
async function install(target: string, installer: ComponentInstaller) {
try {
await installer.install(target, {
onWarn() {},
async confirmFileOverride() {
return true;
},
onFileDownloaded() {},
});
} catch (e) {
console.error(e instanceof Error ? e.message : String(e));
process.exit(-1);
}
const deps = await installer.deps();
if (deps.hasRequired()) await deps.writeRequired();
await installer.onEnd();
}
async function addAIChat({ template, appDir }: TemplatePluginContext) {
let filePath: string;
switch (template.value) {
+57 -23
View File
@@ -148,7 +148,7 @@ importers:
version: 12.38.0([email protected]([email protected]))([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next-themes:
specifier: ^0.4.6
version: 0.4.6([email protected]([email protected]))([email protected])
@@ -254,7 +254,7 @@ importers:
version: 4.0.3
mcp-handler:
specifier: ^1.1.0
version: 1.1.0(@modelcontextprotocol/[email protected]([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]))
version: 1.1.0(@modelcontextprotocol/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]))
next-validate-link:
specifier: ^1.6.4
version: 1.6.4
@@ -348,7 +348,7 @@ importers:
version: 1.7.0([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -397,7 +397,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -443,7 +443,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -480,7 +480,7 @@ importers:
version: 6.0.0(@types/[email protected])([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -529,7 +529,7 @@ importers:
version: 1.7.0([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -578,7 +578,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -627,7 +627,7 @@ importers:
version: 1.7.0([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -682,7 +682,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -728,7 +728,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -780,7 +780,7 @@ importers:
version: link:../../packages/radix-ui
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -1688,7 +1688,7 @@ importers:
version: 12.38.0([email protected]([email protected]))([email protected])
next:
specifier: 16.x.x
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next-themes:
specifier: ^0.4.6
version: 0.4.6([email protected]([email protected]))([email protected])
@@ -1987,7 +1987,7 @@ importers:
version: 1.7.0([email protected])
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
react-router:
specifier: ^7.14.0
version: 7.14.0([email protected]([email protected]))([email protected])
@@ -2030,6 +2030,9 @@ importers:
commander:
specifier: ^14.0.3
version: 14.0.3
fuma-cli:
specifier: ^0.0.2
version: 0.0.2(@emnapi/[email protected])(@emnapi/[email protected])
picocolors:
specifier: ^1.1.1
version: 1.1.1
@@ -2285,7 +2288,7 @@ importers:
version: 3.1.0
next:
specifier: 16.2.2
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react:
specifier: ^19.2.4
version: 19.2.4
@@ -2809,7 +2812,7 @@ importers:
version: 12.38.0([email protected]([email protected]))([email protected])
next:
specifier: 16.x.x
version: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
version: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next-themes:
specifier: ^0.4.6
version: 0.4.6([email protected]([email protected]))([email protected])
@@ -13359,7 +13362,7 @@ snapshots:
dependencies:
'@content-collections/core': 0.14.3([email protected])
'@content-collections/integrations': 0.5.0(@content-collections/[email protected]([email protected]))
next: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
'@dimforge/[email protected]': {}
@@ -18898,7 +18901,7 @@ snapshots:
optionalDependencies:
'@types/mdast': 4.0.4
'@types/mdx': 2.0.13
next: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
react: 19.2.4
vite: 8.0.5(@emnapi/[email protected])(@emnapi/[email protected])(@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected])
vue: 3.5.32([email protected])
@@ -19715,14 +19718,14 @@ snapshots:
[email protected]: {}
[email protected](@modelcontextprotocol/[email protected]([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])):
[email protected](@modelcontextprotocol/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])):
dependencies:
'@modelcontextprotocol/sdk': 1.29.0([email protected])
chalk: 5.6.2
commander: 11.1.0
redis: 4.7.1
optionalDependencies:
next: 16.2.2(@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
next: 16.2.2(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected])
[email protected]:
dependencies:
@@ -20464,7 +20467,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
[email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]):
[email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]):
dependencies:
'@next/env': 16.2.2
'@swc/helpers': 0.5.15
@@ -20473,7 +20476,32 @@ snapshots:
postcss: 8.4.31
react: 19.2.4
react-dom: 19.2.4([email protected])
styled-jsx: 5.1.6(@babel/[email protected])([email protected])([email protected])
styled-jsx: 5.1.6(@babel/[email protected])([email protected])
optionalDependencies:
'@next/swc-darwin-arm64': 16.2.2
'@next/swc-darwin-x64': 16.2.2
'@next/swc-linux-arm64-gnu': 16.2.2
'@next/swc-linux-arm64-musl': 16.2.2
'@next/swc-linux-x64-gnu': 16.2.2
'@next/swc-linux-x64-musl': 16.2.2
'@next/swc-win32-arm64-msvc': 16.2.2
'@next/swc-win32-x64-msvc': 16.2.2
'@opentelemetry/api': 1.9.1
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
[email protected](@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]):
dependencies:
'@next/env': 16.2.2
'@swc/helpers': 0.5.15
baseline-browser-mapping: 2.10.16
caniuse-lite: 1.0.30001786
postcss: 8.4.31
react: 19.2.4
react-dom: 19.2.4([email protected])
styled-jsx: 5.1.6([email protected])([email protected])
optionalDependencies:
'@next/swc-darwin-arm64': 16.2.2
'@next/swc-darwin-x64': 16.2.2
@@ -22180,12 +22208,18 @@ snapshots:
dependencies:
inline-style-parser: 0.2.7
[email protected](@babel/[email protected])([email protected])([email protected]):
[email protected](@babel/[email protected])([email protected]):
dependencies:
client-only: 0.0.1
react: 19.2.4
optionalDependencies:
'@babel/core': 7.29.0
[email protected]([email protected])([email protected]):
dependencies:
client-only: 0.0.1
react: 19.2.4
optionalDependencies:
babel-plugin-macros: 3.1.0
[email protected]: {}