# @atcute/client 中文文档

规范地址：https://npmcn.com/package/%40atcute/client/

版本：5\.1\.2
npm 元数据更新时间：2026-09-10T13:44:05.787Z
中文译文更新时间：2026-11-07T01:49:48.061Z
软件包许可：0BSD

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40atcute/client
原文对照：https://npmcn.com/package/%40atcute/client/?lang=original
源码仓库：https://tangled.org/did:plc:pljn5qch4tgadongtc7i6qij

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：43.3 kB，13 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：2 个
- peer 依赖：@atcute/lexicons ^2\.0\.0
- 首次发布：2024-08-18T04:16:40.623Z
- 最新版本发布：2026-09-10T13:44:05.271Z
- 近 30 天下载量：397660（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：30（近 12 个月 10 个）

## 中文简介

aT 协议的轻量级和可爱 API 客户端

## 安装

```sh
npm install @atcute/client
```

也可以使用：`pnpm add @atcute/client`、`yarn add @atcute/client`、`bun add @atcute/client`

## README

# @ tcute/ 客户端

aT协议的轻量级和可爱的API客户端.

```sh
npm install @atcute/client @atcute/bluesky
```

## 先决条件

客户端需要一个定义包,以了解有哪些查询和程序。 安装 与客户一起:

```sh
npm install @atcute/client @atcute/bluesky
```

然后使用其中一种方法登记类型定义:

```jsonc
// tsconfig.json
{
    "compilerOptions": {
        "types": ["@atcute/bluesky"],
    },
}
```

```ts
// env.d.ts
/// <reference types="@atcute/bluesky" />
```

```ts
// or as an import in your entrypoint
import type {} from '@atcute/bluesky';
```

现在,XRPC方法将掌握注册计划的全部类型信息.

可用软件包 :

| 软件包 | 计划 |
| --- | --- |
| [`@atcute/atproto`](https://npmcn.com/package/definitions/atproto) | `com.atproto.*` |
| [`@atcute/bluemoji`](https://npmcn.com/package/definitions/bluemoji) | `blue.moji.*` |
| [`@atcute/bluesky`](https://npmcn.com/package/definitions/bluesky) | `app.bsky.*`, (中文(简体) ), `chat.bsky.*` |
| [`@atcute/frontpage`](https://npmcn.com/package/definitions/frontpage) | `fyi.unravel.frontpage.*` |
| [`@atcute/germ`](https://npmcn.com/package/definitions/germ) | `com.germnetwork.*` |
| [`@atcute/leaflet`](https://npmcn.com/package/definitions/leaflet) | `pub.leaflet.*` |
| [`@atcute/lexicon-community`](https://npmcn.com/package/definitions/lexicon-community) | `community.lexicon.*` |
| [`@atcute/microcosm`](https://npmcn.com/package/definitions/microcosm) | `blue.microcosm.*`, (中文(简体) ), `com.bad-example.*` |
| [`@atcute/ozone`](https://npmcn.com/package/definitions/ozone) | `tools.ozone.*` |
| [`@atcute/pckt`](https://npmcn.com/package/definitions/pckt) | `blog.pckt.*` |
| [`@atcute/standard-site`](https://npmcn.com/package/definitions/standard-site) | `site.standard.*` |
| [`@atcute/tangled`](https://npmcn.com/package/definitions/tangled) | `sh.tangled.*` |
| [`@atcute/whitewind`](https://npmcn.com/package/definitions/whitewind) | `com.whtwnd.*` |

您可以注册多个软件包来组合其类型.

## 使用量

客户端使用 XRPC 与 AT 协议服务进行通信,这是HTTP 之上的一个简单的 RPC 框架. 询问是获取请求,程序是POST请求.

### 提出请求

```ts
import { Client, simpleFetchHandler } from '@atcute/client';
import type {} from '@atcute/bluesky';

// create a client pointing to the Bluesky public API
const rpc = new Client({ handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }) });
```

使用情况 `get()` 查询和查询 `post()` 有关程序。 双向返回响应对象 `ok`, (中文(简体) ), `status`, (中文(简体) ), `headers`,以及 `data` 字段 :

```ts
// queries use get()
const response = await rpc.get('app.bsky.actor.getProfile', {
    params: { actor: 'bsky.app' },
});

if (response.ok) {
    console.log(response.data.displayName);
    // -> "Bluesky"
}
```

```ts
// procedures use post()
const response = await rpc.post('com.atproto.repo.createRecord', {
    input: {
        repo: 'did:plc:1234...',
        collection: 'app.bsky.feed.post',
        record: {
            $type: 'app.bsky.feed.post',
            text: 'hello world!',
            createdAt: new Date().toISOString(),
        },
    },
});
```

### 处理出错

答复总是包括 `ok` 字段表示成功。对于失败的请求, `data` 包含一个 错误对象 `error` (错误名称)和可选 `message` (说明):

```ts
const response = await rpc.get('app.bsky.actor.getProfile', {
    params: { actor: 'nonexistent.invalid' },
});

if (!response.ok) {
    console.log(response.data.error);
    // -> "InvalidRequest"
    console.log(response.data.message);
    // -> "Unable to resolve handle"
}
```

错误名称在词典中定义。 您可以在键入错误处理时切换 :

```ts
if (!response.ok) {
    switch (response.data.error) {
        case 'InvalidRequest':
            // handle or account doesn't exist
            break;
        case 'AccountTakedown':
            // account was taken down
            break;
        case 'AccountDeactivated':
            // account deactivated by user
            break;
    }
}
```

### 乐观的要求

如果你喜欢扔出错误而不是检查 `response.ok`,使用 `ok()` 帮助者 :

```ts
import { Client, ok, simpleFetchHandler } from '@atcute/client';

const rpc = new Client({
    handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }),
});

// throws ClientResponseError if the request fails
const profile = await ok(rpc.get('app.bsky.actor.getProfile', { params: { actor: 'bsky.app' } }));

console.log(profile.displayName);
// -> "Bluesky"
```

捕获错误 `ClientResponseError`数字 :

```ts
import { ClientResponseError } from '@atcute/client';

try {
    const profile = await ok(rpc.get('app.bsky.actor.getProfile', { params: { actor: 'invalid' } }));
} catch (err) {
    if (err instanceof ClientResponseError) {
        console.log(err.error); // error name from server
        console.log(err.description); // error message from server
        console.log(err.status); // HTTP status code
    }
}
```

### 经认证的请求

基于密码的认证, 使用 `PasswordSession` 从 `@atcute/password-session`它管理 符号, 自动刷新已过期的访问符号, 并可以坚持会话 :

```sh
npm install @atcute/password-session
```

```ts
import { Client, ok } from '@atcute/client';
import { PasswordSession } from '@atcute/password-session';

const auth = await PasswordSession.login({
    service: 'https://bsky.social',
    identifier: 'you.bsky.social',
    password: 'your-app-password',
});

const rpc = new Client({ handler: auth });

// requests are now authenticated
const session = await ok(rpc.get('com.atproto.server.getSession'));
console.log(session.did);
// -> "did:plc:..."
```

保存 `auth.session` 可以在应用程序重新启动时持续登录 :

```ts
// after login, save the session
localStorage.setItem('session', JSON.stringify(auth.session));
```

```ts
// later, restore the session
const saved = localStorage.getItem('session');
if (saved) {
    const auth = await PasswordSession.resume(JSON.parse(saved));
    const rpc = new Client({ handler: auth });
}
```

使用回调来保持持续会话同步 :

```ts
const auth = await PasswordSession.login(
    {
        service: 'https://bsky.social',
        identifier: 'you.bsky.social',
        password: 'your-app-password',
    },
    {
        onUpdate(session) {
            // called on login and token refresh
            localStorage.setItem('session', JSON.stringify(session));
        },
        onDelete(session) {
            // called on logout or session invalidation
            localStorage.removeItem('session');
        },
    },
);
```

### 响应格式

默认情况下,回复被解析为JSON. 对于返回二进制数据的终点,指定格式 与 `as`数字 :

```ts
// get response as a Blob
const { data: blob } = await ok(
    rpc.get('com.atproto.sync.getBlob', {
        params: { did: 'did:plc:...', cid: 'bafyrei...' },
        as: 'blob',
    }),
);

// get response as Uint8Array
const { data: bytes } = await ok(
    rpc.get('com.atproto.sync.getBlob', {
        params: { did: 'did:plc:...', cid: 'bafyrei...' },
        as: 'bytes',
    }),
);

// get response as ReadableStream
const { data: stream } = await ok(
    rpc.get('com.atproto.sync.getBlob', {
        params: { did: 'did:plc:...', cid: 'bafyrei...' },
        as: 'stream',
    }),
);

// discard response body
await ok(
    rpc.post('com.atproto.repo.deleteRecord', {
        input: { repo: 'did:plc:...', collection: '...', rkey: '...' },
        as: null,
    }),
);
```

### 运行时间验证

默认情况下,不需验证即可信任响应。 更严格的担保,使用 `call()` 与 定义包中的方案 :

```ts
import { Client, ok, simpleFetchHandler } from '@atcute/client';
import { AppBskyActorGetProfile } from '@atcute/bluesky';

const rpc = new Client({
    handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }),
});

// validates params, input, and output against the schema
const response = await rpc.call(AppBskyActorGetProfile, {
    params: { actor: 'bsky.app' },
});

if (response.ok) {
    // response.data is validated
    console.log(response.data.displayName);
}
```

抛出验证错误 `ClientValidationError`数字 :

```ts
import { ClientValidationError } from '@atcute/client';

try {
    await rpc.call(AppBskyActorGetProfile, { params: { actor: 'invalid!' } });
} catch (err) {
    if (err instanceof ClientValidationError) {
        console.log(err.target); // 'params', 'input', or 'output'
        console.log(err.message); // validation error details
    }
}
```

### 服务代理

服务代理让您通过您的 PDS 向其它服务发送认证请求 。 政务司 以授权标题转发请求,证明它是代表你行事.

```ts
import { Client, ok } from '@atcute/client';
import { PasswordSession } from '@atcute/password-session';

// must be authenticated
const session = await PasswordSession.login({
    service: 'https://bsky.social',
    identifier: 'you.bsky.social',
    password: 'your-app-password',
});

// create a client that proxies requests through your PDS to the chat service
const chatClient = new Client({
    handler: session,
    proxy: {
        did: 'did:web:api.bsky.chat',
        serviceId: '#bsky_chat',
    },
});

// request goes to your PDS, which forwards it to api.bsky.chat with auth headers
const convos = await ok(chatClient.get('chat.bsky.convo.listConvos'));
```

共同事务身份证包括:

-   `#atproto_pds` - 个人数据服务器
-   `#atproto_labeler` - 标签服务
-   `#bsky_chat` - 布鲁斯基聊天服务

### 自定义抓取处理器

页:1 `simpleFetchHandler` 大部分情况下都是工作 对于高级情景,请提供自己的处理器:

```ts
import type { FetchHandler } from '@atcute/client';

const customHandler: FetchHandler = async (pathname, init) => {
    // pathname is like "/xrpc/app.bsky.actor.getProfile?actor=bsky.app"
    const url = new URL(pathname, 'https://public.api.bsky.app');

    // add custom headers, logging, retry logic, etc.
    console.log(`${init.method?.toUpperCase()} ${url}`);

    return fetch(url, init);
};

const rpc = new Client({ handler: customHandler });
```

或执行 `FetchHandlerObject` 用于状态处理器( 如 `PasswordSession` ưμ㼯a

```ts
import type { FetchHandlerObject } from '@atcute/client';

class MyHandler implements FetchHandlerObject {
    async handle(pathname: string, init: RequestInit): Promise<Response> {
        // your implementation
        return fetch(new URL(pathname, 'https://...'), init);
    }
}

const rpc = new Client({ handler: new MyHandler() });
```

### 费率限制

`retryFetchHandler` 将另一个处理器包成重试有速率限制(HTTP 429)的响应. 延迟 从 `Retry-After` 或者说 `RateLimit-Reset` 显示时页眉, 否则为指数 备份.

```ts
import { Client, retryFetchHandler, simpleFetchHandler } from '@atcute/client';

const rpc = new Client({
    handler: retryFetchHandler({
        handler: simpleFetchHandler({ service: 'https://bsky.social' }),
        maxRetries: 3, // attempts before giving up (default 3)
        maxDelay: 60_000, // upper bound on a retry delay, in ms (default 60s)
        fallbackDelay: 1_000, // backoff base when no header is present, or null to not retry (default 1s)
        shouldRetry: (response) => response.status === 429, // widen to retry other statuses
    }),
});
```

`parseRateLimitHeaders` 读取 `RateLimit-*` 头部关闭一个反应 在他们暴露, 返回时 `null` 当他们缺席或畸形时:

```ts
import { parseRateLimitHeaders } from '@atcute/client';

const response = await rpc.post('com.atproto.repo.createRecord', {/* ... */});

const info = parseRateLimitHeaders(response.headers);
if (info) {
    console.log(`${info.remaining}/${info.limit} remaining, resets at ${info.reset.toISOString()}`);
}
```

## 常见问题

### @atcute/client 是什么？

aT 协议的轻量级和可爱 API 客户端

### 如何安装 @atcute/client？

在项目目录运行 npm install @atcute/client，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@atcute/lexicons（^2\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @atcute/client 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/atcute\_\_client 是否存在。

### @atcute/client 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @atcute/client 可以商用吗？

@atcute/client 使用 0BSD 许可。几乎没有限制：可自由使用、修改和分发，连保留版权声明也不要求。以上为概括，不构成法律意见，请以许可原文为准。

### @atcute/client 的下载量有多少？

根据 npm 官方下载统计，@atcute/client 在 2026/10/07 – 2026/11/05 这 30 天内被下载 397,660 次，日均约 13,255 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @atcute/client 还在维护吗？

最新版本 5\.1\.2 发布于 2026/09/10（1 个月前）；至今共发布 30 个版本，其中过去 12 个月发布了 10 个；首次发布于 2024/08/18。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

