# Fumadocs (Framework Mode, TanStack Start): ページの生成
URL: /ja/docs/tanstack-start/integrations/asyncapi/generate-files
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/integrations/asyncapi/generate-files.ja.mdx

AsyncAPI スキーマからページを生成します。

`staticSource()` と `dynamicSource()` は [`loader()`](/docs/tanstack-start/integrations/asyncapi#generate-pages) 用のページを生成し、`generateFiles()` はそれらを MDX ファイルとしてコンテンツディレクトリに書き出します。いずれも同じオプションを受け付けます。

ページのコンテンツをレンダリングするのは、これまでどおり `<AsyncAPIPage />` です。ジェネレーターが行うのは、各ページのオペレーションの構成だけです。

## オプション [#options]

### `per` [#per]

ページの内容の分け方をカスタマイズします。デフォルトは `operation` です。

<Callout>
オペレーションとは、`receiveLightMeasurement:receive` のように特定のアクションを持つ AsyncAPI のオペレーションを指します。
</Callout>

| モード       | 内容                  | ファイルパス              |
| --------- | ------------------- | ------------------- |
| tag       | 同じタグを持つオペレーション      | `{tag_name}.mdx`    |
| file      | 同じスキーマファイル内のオペレーション | `{file_name}.mdx`   |
| operation | オペレーションごと           | `{operationId}.mdx` |
| custom    | 後述                  | N/A                 |

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'tag',
});
```

`custom` に設定すると、関数を渡して生成処理を完全にカスタマイズできます：

```ts title="Example"
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'custom',
  toPages(builder) {
    for (const [id, item] of Object.entries(builder.document.operations ?? {})) {
      const operation = builder.dereferenceShallow(item);

      builder.create({
        type: 'operation',
        schemaId: builder.id,
        item: { id, action: operation.action },
        path: `${id}.mdx`,
        info: {
          title: operation.title ?? id,
          description: operation.description,
        },
      });
    }
  },
});
```

`tag` に設定すると、タグは名前で照合されます。タグのページに説明を付けるには `info.tags` でタグを定義し、タイトルを指定するには `x-displayName` を使用します。タグのないオペレーションは `unknown` に分類されます。

```yaml title="asyncapi.yaml"
info:
  tags:
    - name: lighting
      description: Operations related to streetlights.
      x-displayName: Lighting
```

### `groupBy` [#groupby]

`operation` モードでは、出力ファイルをフォルダーごとにグループ化できます。

| 値           | 出力                                |
| ----------- | --------------------------------- |
| tag         | `{tag}/{operationId}.mdx`         |
| channel     | `{channel key}/{operationId}.mdx` |
| none(デフォルト) | `{operationId}.mdx`               |

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'operation',
  groupBy: 'tag',
});
```

### `name` [#name]

生成されるページのファイル名を制御する関数です。

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  name(output) {
    if (output.type === 'operation') {
      const operation = this.dereferenceShallow(this.document.operations?.[output.item.id]);
      console.log(operation);

      return `my-dir/${output.item.id}`;
    }

    return 'my-dir/filename';
  },
});
```

`algorithm` オプションを使用することもできます：

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  // v2(デフォルト): オペレーション ID を使用
  // v1: `{operationId}/{action}` を使用
  name: { algorithm: 'v1' },
});
```

### `meta` [#meta]

[`meta.json`](/docs/tanstack-start/page-conventions#meta) ファイルを自動生成します。

柔軟性を最大限に確保したい場合は、いつでも `meta.json` ファイルを手動で定義できます。

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  meta: true,
});
```

または、フォルダーの表示方法をカスタマイズすることもできます。

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  meta: {
    folderStyle: 'separator',
  },
});
```

## MDX ファイル [#mdx-files]

ページを MDX ファイルとして書き出すには、次のようなスクリプトを作成します。

```ts title="scripts/generate-docs.ts"
import { generateFiles } from '@fumadocs/asyncapi';
import { asyncapi } from '@/lib/asyncapi';

void generateFiles({
  input: asyncapi,
  output: './content/docs',
  // 有効にすることをおすすめします
  // オペレーションの説明が MDX の構文を崩さないように注意してください。
  includeDescription: true,
});
```

スクリプトを実行してドキュメントを生成します：

```bash
bun ./scripts/generate-docs.ts
```

MDX コンポーネントに `AsyncAPIPage` コンポーネントを追加してください。生成されるファイルでは `<AsyncAPIPage />` タグが使用されます。

```tsx title="src/routes/docs/$.tsx"
// [!code ++:4]
import type { MDXComponents } from 'mdx/types';
import { asyncapi } from '@/lib/asyncapi';
import { AsyncAPIPage } from '@/components/api-page';
import type { AsyncAPI } from '@fumadocs/asyncapi';

// [!code ++:7]
// サーバー関数の戻り値に対する型レベルのチェックでは AsyncAPI ドキュメントを検証できないため、
// シリアライズ可能として登録します（`@tanstack/router-core` を解決できない場合はインストールしてください）
declare module '@tanstack/router-core' {
  interface SerializableExtensions {
    asyncapiDocument: AsyncAPI.AsyncAPIObject;
  }
}

const serverLoader = createServerFn({
  method: 'GET',
})
  .validator((slugs: string[]) => slugs)
  .handler(async ({ data: slugs }) => {
    // ...
    return {
      path: page.path,
      pageTree: await source.serializePageTree(source.getPageTree()),
      ...(await asyncapi.preloadAsyncAPIPage(page)), // [!code ++]
    };
  });

// [!code highlight]
function Content({ path, components }: { path: string; components?: MDXComponents }) {
  // ...
  <MDX components={useMDXComponents(components)} />; // [!code highlight]
}

function Page() {
  const { path, pageTree, preloaded } = useFumadocsLoader(Route.useLoaderData()); // [!code highlight]

  return (
    <DocsLayout {...baseOptions()} tree={pageTree}>
      <Suspense>
        <Content
          path={path}
          // [!code ++:3]
          components={{
            AsyncAPIPage: (props) => <AsyncAPIPage {...props} preloaded={preloaded} />,
          }}
        />
      </Suspense>
    </DocsLayout>
  );
}
```

`loader()` にプラグインを追加します。

```ts title="lib/source.ts"
import { asyncapi } from '@/lib/asyncapi';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  // [!code ++:2] 任意: ページツリーの各ページ項目に、メッセージの方向を付加します
  plugins: [asyncapi.loaderPlugin()],
});
```

`generateFiles()` では、以下のオプションも指定できます。

### `index` [#index]

生成されたページへのリンクカードを並べたインデックスファイルを生成します。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  index: {
    // `href` の生成に使用
    url: {
      baseUrl: '/docs',
      contentDir: './content/docs',
    },
    items: [
      {
        // 出力パス
        path: 'index.mdx',
        // 任意: 入力ファイルを限定します(サーバー側の `input` フィールドと同じ)
        only: ['streetlights.yaml'],
        // 任意: フロントマターを設定します
        description: 'All available pages',
      },
    ],
  },
});
```

### `imports` [#imports]

生成される MDX ファイルにカスタムのインポートを追加します。生成されるドキュメントでコンポーネントやユーティリティ、その他の依存関係を使いたい場合に便利です。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  imports: [
    {
      names: ['API_BASE_URL'],
      from: '@/constants',
    },
  ],
});
```

これにより、生成されるすべての MDX ファイルに次のインポートが追加されます。

```ts
import { API_BASE_URL } from '@/constants';
```

### `frontmatter` [#frontmatter]

MDX ファイルのフロントマターをカスタマイズします。

デフォルトでは、次のプロパティが含まれます。

| プロパティ         | 説明                              |
| ------------- | ------------------------------- |
| `title`       | ページのタイトル                        |
| `description` | ページの説明                          |
| `full`        | 常に `true`。Fumadocs UI 向けに追加されます |
| `_asyncapi`   | 内部プロパティ                         |

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  frontmatter: (title, description) => ({
    myProperty: 'hello',
  }),
});
```

### `addGeneratedComment` [#addgeneratedcomment]

生成されたファイルの先頭に、自動生成されたものであることを示すコメントを追加します。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  // デフォルトのコメントを追加
  addGeneratedComment: true,

  // またはカスタムコメントを指定
  addGeneratedComment: 'Custom auto-generated comment',

  // またはコメントを無効化
  addGeneratedComment: false,
});
```