# @atproto/tap 中文文档

规范地址：https://npmcn.com/package/%40atproto/tap/

版本：0\.4\.19
npm 元数据更新时间：2026-11-06T01:44:44.404Z
中文译文更新时间：2026-11-07T03:55:33.219Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40atproto/tap
原文对照：https://npmcn.com/package/%40atproto/tap/?lang=original
项目主页：https://atproto.com/
源码仓库：https://github.com/bluesky-social/atproto

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

- 包体积（解压后）：106 kB，32 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：7 个
- 首次发布：2025-12-12T15:05:29.940Z
- 最新版本发布：2026-11-06T01:44:44.049Z
- 近 30 天下载量：7780（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：66（近 12 个月 66 个）

## 中文简介

atproto 调试客户端

## 安装

```sh
npm install @atproto/tap
```

也可以使用：`pnpm add @atproto/tap`、`yarn add @atproto/tap`、`bun add @atproto/tap`

## README

# @ atproto/ tap (中文(简体) )

类型脚本客户端库 [磁带](https://github.com/bluesky-social/indigo/tree/main/cmd/tap/README.md),用于AT协议网络的同步工具.

磁盘处理火花连接、密码验证、回填和过滤。 这个客户端库允许您连接到一个 Tap 实例, 并接收简单的 JSON 事件, 用于您所关心的重置 .

[![NPM](https://img.shields.io/npm/v/@atproto/tap)](https://www.npmjs.com/package/@atproto/tap) [![Github CI Status](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml/badge.svg)](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml)

## 快速启动

```bash
npm install @atproto/tap
```

```ts
import { Tap, SimpleIndexer } from '@atproto/tap'

const tap = new Tap('http://localhost:2480', { adminPassword: 'secret' })

const indexer = new SimpleIndexer()

indexer.identity(async (evt) => {
  console.log(`${evt.did} updated identity: ${evt.handle} (${evt.status})`)
})

indexer.record(async (evt) => {
  const uri = `at://${evt.did}/${evt.collection}/${evt.rkey}`
  if (evt.action === 'create' || evt.action === 'update') {
    console.log(`${evt.action}: ${uri}`)
  } else {
    console.log(`deleted: ${uri}`)
  }
})

indexer.error((err) => console.error(err))

const channel = tap.channel(indexer)
channel.start()

await tap.addRepos(['did:plc:ewvi7nxzyoun6zhxrhs64oiz'])

// On shutdown
await channel.destroy()
```

## 运行磁带

见 [磁带读取](https://github.com/bluesky-social/indigo/tree/main/cmd/tap/README.md) 详细信息 踢出和运行。 您的应用程序可以在当地或通过互联网与它通信.

此库旨在与 Tap 运行在默认模式"WebScoket with acks"中使用. 在这种模式下,Tap提供:

-   **至少一次交货**: 如果接通器在接通前下降, 事件可以重新交付
-   **逐项命令**: 同一雷波事件按顺序交付
-   **后补**:当你添加回波时,历史事件会在直播事件之前交付

## API 密码

### `Tap`

与 Tap 服务器互动的主要客户端.

```ts
const tap = new Tap(url: string, config?: TapConfig)
```

**配置选项 :**

-   `adminPassword?: string` - Basic 认证的密码( 如果 Tap 服务器启用了认证, 则需要)

**方法:**

-   `channel(handler: TapHandler, opts?: TapWebsocketOptions): TapChannel` - 创建接收事件的WebSocket频道
-   `addRepos(dids: string[]): Promise<void>` - 在音轨上添加再投放( 触发回填)
-   `removeRepos(dids: string[]): Promise<void>` - 停止跟踪重置
-   `resolveDid(did: string): Promise<DidDocument | null>` - 解决文件问题
-   `getRepoInfo(did: string): Promise<RepoInfo>` - 获取有关追踪回波的信息

### `TapChannel`

接收事件的 WebSocket 连接 。 通过 `tap.channel()`。 。 。 .

```ts
const channel = tap.channel(handler, opts?)
```

**方法:**

-   `start(): Promise<void>` - 开始接收事件 返回在连接被破坏或出错时解析的保证 .
-   `destroy(): Promise<void>` - 关闭连接

该频道会自动处理重联并保持功能. 处理器成功完成后自动确认事件 .

### `SimpleIndexer`

按类型处理事件的便利类. 传入 `tap.channel()` 当与 Tap 打开频道时.

```ts
const indexer = new SimpleIndexer()

indexer.identity(async (evt: IdentityEvent) => { ... })
indexer.record(async (evt: RecordEvent) => { ... })
indexer.error((err: Error) => { ... })
```

如果没有错误处理器被注册,错误会作为未处理的例外抛出.

### `LexIndexer`

使用键入索引器 `@atproto/lex` 类型安全事件处理计划。 特定记录类型和行动的登记处理员:

```ts
import { LexIndexer } from '@atproto/tap'
import * as com from './lexicons/com'

const indexer = new LexIndexer()

// Handle creates for a specific record type
indexer.create(com.example.post, async (evt) => {
  // evt.record is fully typed as com.example.post.Main
  console.log(`New post: ${evt.record.text}`)
})

// Handle updates
indexer.update(com.example.post, async (evt) => {
  console.log(`Updated post: ${evt.record.text}`)
})

// Handle deletes (no record on delete events)
indexer.delete(com.example.post, async (evt) => {
  console.log(`Deleted: at://${evt.did}/${evt.collection}/${evt.rkey}`)
})

// Handle both creates and updates with put()
indexer.put(com.example.like, async (evt) => {
  console.log(`Like ${evt.action}: ${evt.record.subject.uri}`)
})

// Fallback for unhandled record types/actions
indexer.other(async (evt) => {
  console.log(`Unhandled: ${evt.action}, ${evt.collection}`)
})

// Identity and error handlers
indexer.identity(async (evt) => { ... })
indexer.error((err) => { ... })

const channel = tap.channel(indexer)
```

记录在调用处理人员之前,先根据他们的计划加以验证。 如果校验失败, 就会出现错误, 错误会通过 `error` 管理者...

重复处理器注册会丢出一个错误,包括 `put()` 财务报告和审定财务报表 `create()`编号 :`update()` 同样的计划.

### `TapHandler`

您可以通过创建一个执行 `TapHandler` 接口 :

```ts
interface TapHandler {
  onEvent: (evt: TapEvent, opts: HandlerOpts) => void | Promise<void>
  onError: (err: Error) => void
}

interface HandlerOpts {
  signal: AbortSignal
  ack: () => Promise<void>
}
```

执行自定义处理器时,请务必打电话 `ack()` 当你处理完事件后.

## 事件类型

### `RecordEvent`

```ts
type RecordEvent = {
  id: number
  type: 'record'
  action: 'create' | 'update' | 'delete'
  did: string
  rev: string
  collection: string
  rkey: string
  record?: Record<string, unknown> // present for create/update
  cid?: string // present for create/update
  live: boolean // true if from firehose, false if from backfill
}
```

### `IdentityEvent`

```ts
type IdentityEvent = {
  id: number
  type: 'identity'
  did: string
  handle: string
  isActive: boolean
  status: 'active' | 'takendown' | 'suspended' | 'deactivated' | 'deleted'
}
```

## Webhook 模式

如果您的 Tap 服务器配置为 Webhook 发送, 您可以使用 `parseTapEvent` 用于验证所运入的webhook有效载荷:

```ts
import express from 'express'
import { parseTapEvent, assureAdminAuth } from '@atproto/tap'

const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD

const app = express()
app.use(express.json())

app.post('/webhook', async (req, res) => {
  try {
    assureAdminAuth(ADMIN_PASSWORD, req.headers.authorization)
  } catch {
    return res.status(401).json({ error: 'Unauthorized' })
  }

  try {
    const evt = parseTapEvent(req.body)
    // handle event...
    res.sendStatus(200)
  } catch (err) {
    console.error('Failed to process event:', err)
    res.status(500).json({ error: 'Failed to process event' })
  }
})
```

## 公用事业

### 认证助手

```ts
import {
  formatAdminAuthHeader,
  parseAdminAuthHeader,
  assureAdminAuth,
} from '@atproto/tap'

// Format a password into a Basic auth header value
const header = formatAdminAuthHeader('secret')
// => 'Basic YWRtaW46c2VjcmV0'

// Parse an auth header to extract the password (throws if invalid)
const password = parseAdminAuthHeader(header)

// Verify auth header matches expected password (timing-safe, throws if invalid)
assureAdminAuth('secret', req.headers.authorization)
```

### 事件解析

```ts
import { parseTapEvent } from '@atproto/tap'

const evt = parseTapEvent(jsonData) // validates and returns typed TapEvent
```

## 许可证

麻省理工学院

## 常见问题

### @atproto/tap 是什么？

atproto 调试客户端

### 如何安装 @atproto/tap？

在项目目录运行 npm install @atproto/tap，或使用 pnpm add / yarn add / bun add。

### @atproto/tap 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @atproto/tap 支持 ESM 还是 CommonJS？

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

### @atproto/tap 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @atproto/tap 可以商用吗？

@atproto/tap 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @atproto/tap 的下载量有多少？

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

### @atproto/tap 还在维护吗？

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

