# TypeScript SDK

> 提供 Management API、Content Delivery API 與 Customer API 的型別化客戶端，以及針對 Webhooks、預覽、SEO 檔案與 Edge 的輔助工具。

> Markdown version of https://kanorio.com/zh-HK/developers/sdk. Append `.md` to any developer docs URL for this format. Index: https://kanorio.com/llms.txt · MCP: https://app.kanorio.com/api/mcp
>
> Translated from the English original: https://kanorio.com/en/developers/sdk.md

`@kanorio/sdk` 是一個輕量且完全型別化的客戶端，由三個 OpenAPI 文件生成。路徑、參數、請求內容與回應皆會在編譯時進行檢查。它可在任何支援 `fetch` 的環境中執行：Node.js、Edge Runtime、Deno、Bun 與瀏覽器。

```bash
npm install @kanorio/sdk
```

## 客戶端

| 功能 | API | 憑證 |
|---|---|---|
| `createManagementClient({ token })` | 位於 `https://app.kanorio.com/api/v1` 的 Management API | `knr_pat_` 或 `knr_sa_`。僅限伺服器端使用。 |
| `createDeliveryClient({ siteUrl, previewToken? })` | 單一網站的 Content Delivery API | 無，或用於草稿的 `knr_pv_` |
| `createCustomerClient({ siteUrl, token })` | 單一網站的 Customer API | `knr_cat_` |

每個客戶端皆具備 `get`、`post`、`put`、`patch` 與 `delete` 方法。路徑參數置於 `params`，查詢參數置於 `query`，而 JSON 內容則置於 `body`。

```ts
import { createManagementClient } from "@kanorio/sdk";

const kanorio = createManagementClient({ token: process.env.KANORIO_TOKEN! });

const page = await kanorio.get("/sites/{id}/pages/{pageId}", {
  params: { id: "ws_example123", pageId: "pg_example456" },
});
```

`token` 可以是一個函式，讓您能在每次請求時獲取更新後的權杖。

## 錯誤處理

非 `2xx` 的回應會拋出 `KanorioApiError`，包含 `code`、`status`、`message` 與 `details`。`retryAfter` 會從 `Retry-After` 標頭或 `details.retryAfter` 中填入。

```ts
import { KanorioApiError } from "@kanorio/sdk";

try {
  await kanorio.post("/sites/{id}/posts/{postId}/publish", { params: { id, postId }, body: {} });
} catch (error) {
  if (error instanceof KanorioApiError && error.code === "SITE_NOT_PUBLISHED") {
    await kanorio.post("/sites/{id}/publish", { params: { id }, body: {} });
  } else {
    throw error;
  }
}
```

## 分頁

`paginate` 可將任何列表端點轉換為非同步迭代器，並根據 `nextCursor` 進行處理。`listAll` 則會將所有頁面收集至一個陣列中。

```ts
import { createDeliveryClient, paginate } from "@kanorio/sdk";

const delivery = createDeliveryClient({ siteUrl: "https://s-xxxxxxxxxxxx.kanorio.com" });

for await (const item of paginate((cursor) =>
  delivery.get("/collections/{key}/items", { params: { key: "projects" }, query: { cursor, limit: 100 } })
)) {
  console.log(item.slug);
}
```

## 輔助工具

| 匯入 | 功能說明 |
|---|---|
| `verifyWebhookSignature`, `createRevalidateHandler` | 驗證 `X-Kanorio-Signature` 並重新驗證 `data.cacheTags`（前綴為 `kanorio:`）。請參閱 [Webhooks](https://kanorio.com/zh-HK/developers/webhooks)。 |
| `cacheTag`, `localizeCacheTags`, `prefixCacheTags` | 建立請求應攜帶的快取標籤（`cacheTag.collection("blog")`、`cacheTag.item(id)`、`localizeCacheTags(tags, "fr-FR")`），並加上 Webhook 處理器重新驗證時使用的 `kanorio:` 前綴 |
| `seoRewrites({ siteUrl, framework })` | 從您自己的網域提供網站的 sitemap、robots.txt、llms.txt 及 feeds |
| `fetchDeliveryJsonLd({ siteUrl, path })` | 頁面的 Schema.org JSON-LD |
| `@kanorio/sdk/edge` › `createKanorioMiddleware` | 套用重新導向（精確匹配，接著是 `/*` 萬用字元）、封鎖擁有者設定封鎖的 AI 爬蟲、提供 IndexNow 金鑰檔案，並在多語言網站中處理語言規則：將主要語言前綴重新導向至根目錄、提供 `/{prefix}/llms.txt` 及 `/{prefix}/rss.xml`、匹配無前綴的重新導向，並在 `evaluate()` 中回報請求的語言環境 |
| `requestLocaleOf`, `localizedPath`, `languageSwitcher` | 從路徑名稱解析網站 `locales[]`（`GET /site`）中的語言環境、在另一種語言環境中建立相同的路徑、列出語言選單 |
| `buildAlternates` | 根據 `resolvedLocale` / `availableLocales` 為單一頁面建立 Canonical 及 `hreflang`，並遵循託管網站的規則（各語言環境自定義 Canonical、`x-default` 指向主要語言環境、後備頁面 Canonical 指向主要語言環境） |
| `@kanorio/sdk/preview` › `createPreviewRouteHandler` | 將後台的預覽連結轉換為草稿模式工作階段 |
| `@kanorio/sdk/forms` › `forms.client` | 取得表單、其機器人防護驗證與上傳票證，然後提交 |
| `parseDeliveryCacheTags`, `frameworkCacheTags` | 讀取 Content Delivery API 回應中的 `X-Kanorio-Cache-Tags`，可選擇原始格式或為您的框架快取加上前綴 |

## 內容模型的型別

集合是依網站定義的，因此其欄位型別來自網站本身。請使用 [CLI](https://kanorio.com/zh-HK/developers/cli) 進行生成：

```bash
npx @kanorio/cli types --site https://s-xxxxxxxxxxxx.kanorio.com --out src/kanorio.d.ts
```

## 版本控制

此 SDK 遵循語意化版本控制。其版本資訊會隨每次請求發送，以便 Kanorio 在您呼叫已棄用的操作時發出警告。請參閱 [版本控制](https://kanorio.com/zh-HK/developers/basics/versioning)。
