コンテンツへスキップ
Fumadocs

ヘッドレス

UI を含まない、API ページの状態とロジックです。

概要

fumadocs-openapi/ui 以外はすべてヘッドレスです。

パスモジュール
fumadocs-openapiページ: ドキュメント、そのサーバー、独自のコンポーネント
fumadocs-openapi/operationオペレーション: 詳細、リクエスト例、コード例
fumadocs-openapi/playgroundAPI プレイグラウンド: フォーム、認証、リクエスト
fumadocs-openapi/requests例のデータを実際のリクエストにエンコード
fumadocs-openapi/requests/generatorsそのリクエストをコード例に変換
@fumadocs/json-schema/reactスキーマ UI: UI 向けにフラット化された JSON スキーマ
@fumadocs/json-schema/react/clientスキーマ UI の状態

ページ

createOpenAPIRenderer() は独自のコンポーネントを受け取って <OpenAPIPage /> を返します。<OpenAPIPage /> は、生成されたページの props を受け取ります。

components/api-page.tsx
'use client';
import { type CodeBlockProps, createOpenAPIRenderer } from 'fumadocs-openapi';
import { Operation } from '@/components/my-operation';
import { SchemaUI } from '@/components/my-schema';

export const OpenAPIPage = createOpenAPIRenderer({
  components: {
    Operation,
    SchemaUI,
    CodeBlock({ lang, code }: CodeBlockProps) {
      return (
        <pre>
          <code className={`language-${lang}`}>{code}</code>
        </pre>
      );
    },
  },
});
コンポーネントレンダリング対象
Operation各オペレーションと Webhook。詳しくは Operation を参照してください
SchemaUIパラメーター、ボディ、レスポンスの JSON スキーマ。詳しくは スキーマ UI を参照してください
Layout任意。レンダリングされたオペレーションと Webhook をラップします

フック

ページ配下のコンポーネントは、これらのフックでページの状態を読み取れます。

フック戻り値
useOpenAPI()参照解決済みのドキュメント (doc) とリクエストオプション
useComponents()ページに渡されたコンポーネント
useServer()選択中のサーバーとその変数
useTypeScriptDefinitions(schema, options)JSON スキーマの TypeScript 型定義
useRenderContext()playground など、ページのレンダリングオプション

オペレーション

<OperationProvider /> は、オペレーションまたは Webhook の詳細情報を算出し、選択中のリクエスト例を保持します。

components/my-operation.tsx
'use client';
import {
  OperationProvider,
  type PageOperationProps,
  useCodeUsage,
  useOperation,
  useResponseExamples,
} from 'fumadocs-openapi/operation';

export function Operation(props: PageOperationProps) {
  return (
    <OperationProvider {...props}>
      <Content />
    </OperationProvider>
  );
}

function Content() {
  const { title, parameters, codeUsages } = useOperation();
  const responses = useResponseExamples();

  return (
    <>
      <h2>{title}</h2>
      {parameters.map(({ in: location, items }) => (
        <section key={location}>{items.map((param) => param.name).join(', ')}</section>
      ))}
      {Array.from(codeUsages.map().keys(), (id) => (
        <CodeUsage key={id} id={id} />
      ))}
      {responses.map((tab) => (
        <pre key={tab.code}>{JSON.stringify(tab.examples?.[0]?.sample)}</pre>
      ))}
    </>
  );
}

function CodeUsage({ id }: { id: string }) {
  const code = useCodeUsage(id);
  return code && <pre>{code}</pre>;
}
フック戻り値
useOperation()詳細が解決済みのオペレーション
useExampleRequests()リクエスト例の一覧、選択中のリクエスト例、およびそのデータを編集するための select() と update()
useExampleRequest()選択中のリクエスト例のデータ (更新に追従)
useCodeUsage(id)選択中のリクエスト例に対して codeUsages が生成したコード
useResponseExamples()各レスポンスと、その優先メディアタイプにおける例の値

プロパティ

型

スキーマ UI

generateSchemaUI() は JSON スキーマをフラット化します。到達したすべての $ref は refs のエントリーになるため、UI は再帰処理を行わずに $root からマップをたどるだけで済みます。

<SchemaUIProvider /> は、その上で状態を管理します。具体的には、プロパティから開いたスキーマ、ユニオンで選択されたメンバー、プロパティへのリンクです。

components/my-schema.tsx
'use client';
import { useMemo } from 'react';
import { generateSchemaUI } from '@fumadocs/json-schema/react';
import { SchemaUIProvider, useSchemaUI } from '@fumadocs/json-schema/react/client';
import type { OpenAPIComponents } from 'fumadocs-openapi';

export const SchemaUI: OpenAPIComponents['SchemaUI'] = ({ client, ...options }) => {
  const generated = useMemo(() => generateSchemaUI(options), [options.root]);

  return (
    <SchemaUIProvider id={client.rootId} name={client.name} generated={generated}>
      <div id={client.rootId}>
        <Schema />
      </div>
    </SchemaUIProvider>
  );
};

function Schema() {
  const { refs, path, open, back } = useSchemaUI();
  const { schema } = path[path.length - 1];

  return (
    <>
      {path.length > 1 && <button onClick={() => back(path.length - 2)}>Back</button>}
      {schema.type === 'object' && (
        <ul>
          {schema.props.map((prop) => (
            <li key={prop.name}>
              {prop.name}:{' '}
              <button onClick={() => open(prop.name, prop.$type)}>
                {refs[prop.$type].typeName}
              </button>
            </li>
          ))}
        </ul>
      )}
    </>
  );
}
useSchemaUI()内容
pathルートから順に開かれているスキーマ
open(name, $ref), back(index)path 内を移動します
getLink(index, name)パス項目のプロパティを指す URL。アクセスすると再び path が開かれます
highlightedURL が指している、最後のパス項目のプロパティ

path の各項目は、表示する schema と、選択中のメンバーを含む unions を持ちます。ユニオンの select() を呼び出すと、別のメンバーが表示されます。

ページから renderMarkdown と renderCodeblock が渡されるため、説明や例は独自のコンポーネントでレンダリングされます。client はルートのアンカー ID と名前を保持しており、プロパティへのリンクはこれを基準に解決されます。

client のスロットをレンダリングする

ボディとレスポンスは、メディアタイプの選択用に client.selector を、TypeScript の型定義の コピー用に client.actions を渡します。

プレイグラウンド

usePlayground() は、<OperationProvider /> 配下にある API プレイグラウンドの状態を保持します。フォームは選択中のサンプルリクエストを初期値とし、編集内容はサンプルに同期されます。そのため、コード例にも編集内容が反映されます。その際、認証情報はマスクされます。

components/my-playground.tsx
'use client';
import { StfProvider, useFieldValue } from '@fumari/stf';
import { useOperation } from 'fumadocs-openapi/operation';
import { usePlayground } from 'fumadocs-openapi/playground';

export function MyPlayground() {
  const { parameters } = useOperation();
  const { stf, send, isSending, response } = usePlayground();

  return (
    <StfProvider value={stf}>
      {parameters.map(({ in: location, items }) =>
        items.map((param) => (
          <ParameterInput key={`${location}.${param.name}`} location={location} name={param.name} />
        )),
      )}
      <button disabled={isSending} onClick={send}>
        Send
      </button>
      {response?.result.type === 'response' && <pre>{response.result.text()}</pre>}
    </StfProvider>
  );
}

function ParameterInput({ location, name }: { location: string; name: string }) {
  const [value, setValue] = useFieldValue([location, name]);

  return (
    <input
      aria-label={name}
      value={String(value ?? '')}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}
フィールド内容
stfフォーム(@fumari/stf のデータエンジン)。path、query、header、cookie、body を保持し、ページの認証値は auth に保持します
bodyフォームで編集するリクエストボディと、その優先メディアタイプ
auth選択中のセキュリティ要件の認証フィールド。select() で切り替え、authorize() で OAuth 2.0 トークンを取得してフィールドに設定します
send(), isSending, response, clearResponse()フォームをリクエストとして送信する機能と、最後のリクエストの結果

onRequestInit() などでリクエストをカスタマイズする fetchOptions、セキュリティスキームを処理する authProviders(認証を参照)、認証フィールドをカスタマイズする transformAuthInputs を指定できます。

リクエスト

usePlayground() が内部で使用している部品です。これらを使うと、usePlayground() を使わずにリクエストを送信できます。

エクスポート機能
createBrowserFetcher()ブラウザからリクエストを送信します。proxyUrl が設定されている場合はそれを経由します。レスポンスには duration、mediaType、fileName、text() が含まれます
encodeRequestData()サンプルのデータをボディ、ヘッダー、クエリに変換します。fumadocs-openapi/requests からインポートします
resolveMediaAdapter()メディアタイプに対応するアダプターを返します。サポートされていない場合は undefined を返します
useAuthFields()オペレーションの認証フィールドと、それらから生成されるリクエストデータを返します
usePlaygroundAuth()ページの認証値を stf で、ページに戻ってきたフローを returned で返します
useOpenIdConnectFlows()OpenID Connect の設定に含まれる OAuth 2.0 フロー、または検出に失敗した場合の error を返します。読み込み中はサスペンドします
requestOAuthToken()OAuth 2.0 フローを実行します。onUserCode で、デバイス認可時にユーザーが入力するコードを表示します

How is this guide?

最終更新日