# Fumadocs (Framework Mode, Astro): 無頭式
URL: /zh-TW/docs/astro/integrations/asyncapi/headless
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/integrations/asyncapi/headless.zh-TW.mdx

不含 UI 的 AsyncAPI 頁面狀態與邏輯。

## 概覽 [#overview]

除了 `@fumadocs/asyncapi/ui` 之外，其餘皆為無頭式。

| 路徑                              | 模組                        |
| ------------------------------- | ------------------------- |
| `@fumadocs/asyncapi`            | 頁面：文件、其伺服器，以及您的元件         |
| `@fumadocs/asyncapi/operation`  | 單一 operation：其頻道、參數、訊息與回覆 |
| `@fumadocs/asyncapi/playground` | operation 頻道上的工作階段        |

## 頁面 [#page]

`createAsyncAPIRenderer()` 會接收您的元件，並回傳 `<AsyncAPIPage />`，該元件接受所產生頁面的 props。

```tsx title="components/api-page.tsx"
'use client';
import { type CodeBlockProps, createAsyncAPIRenderer } from '@fumadocs/asyncapi';
import { Operation } from '@/components/my-operation';
import { SchemaUI } from '@/components/my-schema';

export const AsyncAPIPage = createAsyncAPIRenderer({
  components: {
    Operation,
    SchemaUI,
    CodeBlock({ lang, code }: CodeBlockProps) {
      return (
        <pre>
          <code className={`language-${lang}`}>{code}</code>
        </pre>
      );
    },
  },
});
```

| 元件          | 算繪內容                                         |
| ----------- | -------------------------------------------- |
| `Operation` | 頁面中的每個 operation，請參閱 [Operation](#operation) |
| `SchemaUI`  | 參數、標頭及訊息酬載的 JSON schema                      |
| `Layout`    | 選用，用來包覆已渲染的 operation                        |

### Hooks [#hooks]

頁面底下的元件可以讀取頁面的狀態。

| Hook                 | 回傳值                   |
| -------------------- | --------------------- |
| `useAsyncAPI()`      | 已解參照的文件 (`doc`) 與頁面選項 |
| `useComponents()`    | 傳入頁面的元件               |
| `useServer()`        | 伺服器列表、目前選取的伺服器及其變數    |
| `useRenderContext()` | 頁面的算繪選項，例如 `content`  |

若要自行算繪 operation，請改為掛載 `<AsyncAPIProvider document={bundled} components={...} />`，以取代 `createAsyncAPIRenderer()`。

## Operation [#operation]

`<OperationProvider />` 只會推導一次 operation 的詳細資訊：套用 traits，並解析其頻道、參數、訊息與回覆。

```tsx title="components/my-operation.tsx"
'use client';
import {
  OperationProvider,
  type PageOperationProps,
  useOperation,
  useOperationSecurity,
} from '@fumadocs/asyncapi/operation';

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

function Content() {
  const { title, channel, parameters, messages } = useOperation();
  const security = useOperationSecurity();

  return (
    <>
      <h2>{title}</h2>
      <code>{channel.address}</code>
      <ul>
        {parameters.map((param) => (
          <li key={param.name}>{param.name}</li>
        ))}
      </ul>
      {messages.map((message) => (
        <section key={message.id}>
          <h3>{message.name}</h3>
          {message.examples.map((example) => (
            <pre key={example.id}>{JSON.stringify(example.payload, null, 2)}</pre>
          ))}
        </section>
      ))}
      <p>{security.operation.map((item) => item.id).join(', ')}</p>
    </>
  );
}
```

| Hook                     | 回傳值                                |
| ------------------------ | ---------------------------------- |
| `useOperation()`         | 已解析詳細資訊的 operation                 |
| `useOperationSecurity()` | 所選伺服器與該 operation 的安全性方案 (兩者皆會套用)  |
| `useChannelMessages()`   | 讀者在該頻道上接收與傳送的訊息，涵蓋該頻道的所有 operation |

### OperationInfo

| Prop           | Type                                    | Description                                                                      |
| -------------- | --------------------------------------- | -------------------------------------------------------------------------------- |
| `id`           | `string`                                |                                                                                  |
| `action`       | `"receive" \| "send"`                   | the action of the application described by the document, readers do the opposite |
| `operation`    | `OperationObject`                       | resolved, with traits applied                                                    |
| `channel`      | `ChannelObject`                         |                                                                                  |
| `title`        | `string`                                |                                                                                  |
| `description?` | `string \| undefined`                   |                                                                                  |
| `parameters`   | `Operation.OperationParameter[]`        | parameters of the channel address                                                |
| `messages`     | `Operation.OperationMessage[]`          |                                                                                  |
| `reply?`       | `Operation.OperationReply \| undefined` |                                                                                  |

訊息範例取自文件本身，或依據其 schema 產生。

### OperationMessage

| Prop           | Type                                   | Description                                                   |
| -------------- | -------------------------------------- | ------------------------------------------------------------- |
| `id`           | `string`                               | the key of message in its channel, unique in the operation    |
| `name`         | `string`                               | display name                                                  |
| `message`      | `MessageObject`                        | resolved, with traits applied                                 |
| `contentType?` | `string \| undefined`                  | falls back to the `defaultContentType` of document            |
| `received`     | `boolean`                              | sent by the application to readers, otherwise readers send it |
| `headers?`     | `Operation.MessageSchema \| undefined` |                                                               |
| `payload?`     | `Operation.MessageSchema \| undefined` |                                                               |
| `examples`     | `ExampleMessageItem[]`                 | example messages, generated from its schemas when it has none |

## 互動測試區 [#playground]

`usePlayground()` 會在 `<OperationProvider />` 之下，透過傳輸層連線至 operation 的頻道。

```tsx
'use client';
import { usePlayground } from '@fumadocs/asyncapi/playground';
import { mqttTransport } from '@/lib/mqtt-transport';

export function Playground() {
  const { url, status, connect, disconnect, send, log } = usePlayground({
    // 疊加在頁面的 `playground.transports` 之上
    transports: { mqtt: mqttTransport },
  });
  if (!url) return null; // 此伺服器沒有可用的傳輸層

  return (
    <>
      <button onClick={status === 'closed' ? connect : disconnect}>{status}</button>
      {send && <button onClick={() => send('{"type":"ping"}')}>Ping</button>}
      {log.map((entry) => (
        <p key={entry.id}>
          {entry.type} {entry.message?.name} {entry.data}
        </p>
      ))}
    </>
  );
}
```

* 位址參數、query 與驗證輸入都屬於表單 `stf`，`url` 會隨其值更新。
* 連線期間即可使用 `send`，除非該連線僅能接收訊息。
* 收到的訊息會與頻道上各訊息的酬載進行比對，`entry.message` 即為對應的文件化訊息；二進位訊息則存放於 `entry.binary`。

### Playground

| Prop         | Type                                                                                         | Description                                                                                                         |
| ------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `stf`        | `Stf`                                                                                        | the form of PlaygroundValues                                                                                        |
| `transport?` | `PlaygroundModule.PlaygroundTransport \| undefined`                                          | the transport connecting to the selected server, `undefined` when none does                                         |
| `url?`       | `string \| undefined`                                                                        | the URL to connect with the values of form, `undefined` without a transport                                         |
| `status`     | `PlaygroundModule.ConnectionStatus`                                                          |                                                                                                                     |
| `connect`    | `() => void`                                                                                 |                                                                                                                     |
| `disconnect` | `() => void`                                                                                 |                                                                                                                     |
| `send?`      | `((data: string \| ArrayBuffer, message?: Operation.OperationMessage) => void) \| undefined` | send a message, with the documented message it is. Absent until connected, and when the connection can only receive |
| `log`        | `PlaygroundModule.LogEntry[]`                                                                |                                                                                                                     |
| `clearLog`   | `() => void`                                                                                 |                                                                                                                     |

### 傳輸層 [#transports]

傳輸層負責連線至某個協定的伺服器，範例請參考 [MQTT 範例](/docs/astro/integrations/asyncapi/api-page#custom-transports)。系統會依序從 `usePlayground()` 的 `transports`、頁面的 `playground.transports` 中選取，最後才使用內建的 WebSocket 傳輸層。

`usePlaygroundTransport()` 接受相同的 `transports`，並回傳所選伺服器對應的傳輸層；若沒有任何傳輸層能連線至該伺服器，則回傳 `undefined`。

### PlaygroundTransport

| Prop      | Type                                                                                                                         | Description                                                                                             |
| --------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `auth?`   | `((scheme: SecuritySchemeObject) => boolean) \| undefined`                                                                   | security schemes it can apply besides API keys in the query, they become inputs of the connection panel |
| `connect` | `(target: PlaygroundModule.ConnectTarget, events: PlaygroundModule.TransportEvents) => PlaygroundModule.TransportConnection` |                                                                                                         |

`connect()` 會透過 `events` 回報：`open()`、`message(data)` (內容為文字或 `ArrayBuffer`) ，以及 `close()` 或 `error()`，後兩者會結束連線。

### ConnectTarget

| Prop      | Type                                                                                            | Description                                                   |
| --------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `url`     | `string`                                                                                        | server URL, address and query, for URL-based protocols        |
| `server`  | `ServerObject`                                                                                  |                                                               |
| `address` | `string`                                                                                        | the channel address with its parameters                       |
| `query`   | `Record<string, unknown>`                                                                       |                                                               |
| `auth`    | `{ scheme: SecuritySchemeObject; value: string \| { username: string; password: string; }; }[]` | values of the auth inputs, for the schemes accepted by `auth` |