# @atproto/lex-server 中文文档

规范地址：https://npmcn.com/package/%40atproto/lex-server/

版本：0\.2\.3
npm 元数据更新时间：2026-11-06T01:44:15.765Z
中文译文更新时间：2026-11-07T03:56:04.711Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：287 kB，36 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：11 个
- 首次发布：2026-01-02T14:15:28.002Z
- 最新版本发布：2026-11-06T01:44:15.434Z
- 近 30 天下载量：6645（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：55（近 12 个月 55 个）

## 中文简介

Atproto Lexicon 协议和计划请求路由器

## 安装

```sh
npm install @atproto/lex-server
```

也可以使用：`pnpm add @atproto/lex-server`、`yarn add @atproto/lex-server`、`bun add @atproto/lex-server`

## README

# @ atproto/ lex- server

Atproto Lexicon 协议和计划请求路由器. 见 [更改日志](https://npmcn.com/package/%40atproto/lex-server/CHANGELOG.md) 用于版本历史.

```bash
npm install @atproto/lex-server
```

-   基于 Lexicon 方案的安全请求路由
-   为查询、程序和WebSocket订阅提供支持
-   建于网络标准 `Request`编号 :`Response` API(跨跑道便携式)
-   自定义认证及证书通过
-   优雅的关闭 `AsyncDisposable` 模式

> \[大
> 
> 此软件包目前处于 **预览**. API 和特性在稳定发布前会有所改变.

**这是什么?**

构建AT协议服务器需要处理XRPC请求,对照Lexicon schemas验证输入,管理认证,并支持实时订阅. `@atproto/lex-server` 以 :

1.  基于 Lexicon 计程器对类型安全处理器的运行请求
2.  自动验证请求参数和正文
3.  提供具有定制战略的灵活认证系统
4.  支持使用后压处理的 WebSocket 订阅

```typescript
import { LexRouter } from '@atproto/lex-server'
import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'
import * as app from './lexicons/app.js'

const router = new LexRouter({ upgradeWebSocket })
  .add(app.bsky.actor.getProfile, async ({ params }) => {
    const profile = await db.getProfile(params.actor)
    return { body: profile }
  })
  .add(app.bsky.feed.post.create, {
    auth: requireAuth,
    handler: async ({ credentials, input }) => {
      const result = await db.createPost(credentials.did, input.body)
      return { body: result }
    },
  })

await serve(router, { port: 3000 })
```

-   [快速启动](https://npmcn.com/package/%40atproto/lex-server/#readme-quick-start)
-   [莱克萨斯路特](https://npmcn.com/package/%40atproto/lex-server/#readme-lexrouter)
    -   [创建路由器](https://npmcn.com/package/%40atproto/lex-server/#readme-creating-a-router)
    -   [添加路由](https://npmcn.com/package/%40atproto/lex-server/#readme-adding-routes)
    -   [处理器上下文](https://npmcn.com/package/%40atproto/lex-server/#readme-handler-context)
    -   [处理器输出](https://npmcn.com/package/%40atproto/lex-server/#readme-handler-output)
-   [查询和程序](https://npmcn.com/package/%40atproto/lex-server/#readme-queries-and-procedures)
    -   [查询处理器](https://npmcn.com/package/%40atproto/lex-server/#readme-query-handler)
    -   [程序处理器](https://npmcn.com/package/%40atproto/lex-server/#readme-procedure-handler)
    -   [二进制有效载荷](https://npmcn.com/package/%40atproto/lex-server/#readme-binary-payloads)
-   [订阅](https://npmcn.com/package/%40atproto/lex-server/#readme-subscriptions)
-   [认证](https://npmcn.com/package/%40atproto/lex-server/#readme-authentication)
    -   [自定义认证](https://npmcn.com/package/%40atproto/lex-server/#readme-custom-authentication)
    -   [WWW- 认证信头](https://npmcn.com/package/%40atproto/lex-server/#readme-www-authenticate-headers)
-   [处理错误](https://npmcn.com/package/%40atproto/lex-server/#readme-error-handling)
    -   [LexServer 错误](https://npmcn.com/package/%40atproto/lex-server/#readme-lexservererror)
    -   [LexServer Auth 错误](https://npmcn.com/package/%40atproto/lex-server/#readme-lexserverautherror)
    -   [处理器召回错误](https://npmcn.com/package/%40atproto/lex-server/#readme-error-handler-callback)
-   [节点.js 服务器](https://npmcn.com/package/%40atproto/lex-server/#readme-nodejs-server)
    -   [服务( )](https://npmcn.com/package/%40atproto/lex-server/#readme-serve)
    -   [创建 Server ()](https://npmcn.com/package/%40atproto/lex-server/#readme-createserver)
    -   [请求收听器 ()](https://npmcn.com/package/%40atproto/lex-server/#readme-torequestlistener)
    -   [升级WebSocket ()](https://npmcn.com/package/%40atproto/lex-server/#readme-upgradewebsocket)
-   [高级使用](https://npmcn.com/package/%40atproto/lex-server/#readme-advanced-usage)
    -   [自定义响应对象](https://npmcn.com/package/%40atproto/lex-server/#readme-custom-response-objects)
    -   [答复信头](https://npmcn.com/package/%40atproto/lex-server/#readme-response-headers)
    -   [连接信息](https://npmcn.com/package/%40atproto/lex-server/#readme-connection-info)
-   [许可证](https://npmcn.com/package/%40atproto/lex-server/#readme-license)

## 快速启动

**1\. 安装软件包**

```bash
npm install @atproto/lex-server
```

**2\. 产生Lexicon计划**

使用 `@atproto/lex` 从 Lexicon 定义生成 TypeScript 计划:

```bash
lex install app.bsky.actor.getProfile
lex build
```

**3\. 创建路由器并添加处理器**

```typescript
import { LexRouter, LexServerError } from '@atproto/lex-server'
import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'
import * as app from './lexicons/app.js'

const router = new LexRouter({ upgradeWebSocket })

// Add a query handler
router.add(app.bsky.actor.getProfile, async ({ params }) => {
  const profile = await db.getProfile(params.actor)
  if (!profile) {
    throw new LexServerError(404, {
      error: 'NotFound',
      message: 'Profile not found',
    })
  }
  return { body: profile }
})

// Start the server
const server = await serve(router, { port: 3000 })
console.log('Server listening on port 3000')
```

## 莱克萨斯路特

这个 `LexRouter` 类是核心 `@atproto/lex-server`它向基于Lexicon schemas的打字安全处理器传递XRPC请求.

### 创建路由器

```typescript
import { LexRouter } from '@atproto/lex-server'
import { upgradeWebSocket } from '@atproto/lex-server/nodejs'

const router = new LexRouter({
  // Required for WebSocket subscriptions (Node.js)
  upgradeWebSocket,

  // Optional: Add logging or error reporting for unexpected errors in handlers
  onHandlerError: ({ error, request, method }) => {
    console.error(`Error in ${method.nsid}:`, error)
  },

  // Optional: WebSocket backpressure settings
  highWaterMark: 250_000, // bytes (default: 250KB)
  lowWaterMark: 50_000, // bytes (default: 50KB)
})
```

### 添加路由

使用 `.add()` 方法,它接受Lexicon的图案和处理器:

```typescript
// Simple handler (no authentication)
router.add(schema, async ({ params, input, request }) => {
  return { body: result }
})

// Handler with authentication
router.add(schema, {
  auth: async ({ request, params }) => credentials,
  handler: async ({ params, input, credentials, request }) => {
    return { body: result }
  },
})
```

路由器支持方法链:

```typescript
const router = new LexRouter()
  .add(app.bsky.actor.getProfile, profileHandler)
  .add(app.bsky.feed.getTimeline, timelineHandler)
  .add(app.bsky.feed.post.create, postHandler)
```

### 处理器上下文

处理器接收具有以下属性的上下文对象:

```typescript
type LexRouterHandlerContext<Method, Credentials> = {
  credentials: Credentials // Result of auth function (undefined if no auth)
  input: InferMethodInput<Method> // Parsed request body (procedures only)
  params: InferMethodParams<Method> // Parsed URL query parameters
  request: Request // Original Web Request object
  connection?: ConnectionInfo // Network connection info
}
```

### 处理器输出

处理器可以返回各种输出格式 :

```typescript
// JSON response (encoding inferred from schema)
return { body: { key: 'value' } }

// With custom encoding
return { encoding: 'text/plain', body: 'Hello, world!' }

// With response headers
return { body: data, headers: { 'x-custom': 'value' } }

// Empty response (200 OK with no body)
return {}

// Custom Response object (full control)
return new Response(body, { status: 201, headers })

// Proxy Response
return fetch('https://example.com/data')
```

## 查询和程序

### 查询处理器

查询手柄 `GET` 请求和接收 URL 查询字符串中的参数 :

```typescript
import * as app from './lexicons/app.js'

router.add(app.bsky.actor.getProfile, async ({ params }) => {
  // params.actor is typed and validated
  const profile = await db.getProfile(params.actor)
  return { body: profile }
})
```

### 程序处理器

程序处理 `POST` 请求和接收请求机构:

```typescript
router.add(app.bsky.feed.post.create, async ({ input }) => {
  // input.body contains the parsed and validated request body
  const post = await db.createPost(input.body)
  return { body: { uri: post.uri, cid: post.cid } }
})
```

### 二进制有效载荷

对于接受或返回二进制数据的终点:

```typescript
// Binary input
router.add(app.example.uploadBlob, async ({ input }) => {
  // input.body is a Request object for streaming
  // input.encoding contains the content-type
  const blob = await input.body.arrayBuffer()
  return { body: { cid: await store(blob) } }
})

// Binary output
router.add(app.example.getBlob, async ({ params }) => {
  const stream = await getBlob(params.cid)
  return {
    encoding: 'application/octet-stream',
    body: stream,
  }
})
```

## 订阅

订阅通过WebSocket连接提供实时数据. 处理器是生成消息的同步生成器:

```typescript
import { LexRouter, LexError } from '@atproto/lex-server'
import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'
import { scheduler } from 'node:timers/promises'

const router = new LexRouter({
  upgradeWebSocket, // Required for WebSocket support in nodejs
})

router.add(com.example.stream, async function* ({ params, request }) {
  const { cursor = 0, limit = 10 } = params
  const { signal } = request

  for (let i = 0; i < limit; i++) {
    // Yield messages to the client
    yield com.example.stream.message.$build({
      data: `Message ${cursor + i}`,
      cursor: cursor + i,
    })

    // Wait between messages (respects abort signal)
    await scheduler.wait(1000, { signal })
  }

  // Throwing a LexError closes the connection with an error frame
  throw new LexError('LimitReached', `Limit of ${limit} messages reached`)
})
```

信件为 CBOR- 编码后作为 WebSocket 二进制框发送 。 路由器处理:

-   WebSocket 升级谈判
-   后压管理
-   优雅的连接清理
-   错误框架编码

## 认证

### 自定义认证

认证通过 `auth` 函数在处理器配置中:

```typescript
import { LexError, LexServerAuthError } from '@atproto/lex-server'

type Credentials = { did: string; scope: string[] }

const requireAuth = async ({
  request,
}: {
  request: Request
}): Promise<Credentials> => {
  const header = request.headers.get('authorization')
  if (!header?.startsWith('Bearer ')) {
    throw new LexServerAuthError(
      'AuthenticationRequired',
      'Bearer token required',
      {
        Bearer: { realm: 'api' },
      },
    )
  }

  const token = header.slice(7)
  const session = await verifyToken(token)
  if (!session) {
    throw new LexServerAuthError(
      'InvalidToken',
      'Token is invalid or expired',
      {
        Bearer: { realm: 'api', error: 'invalid_token' },
      },
    )
  }

  return { did: session.did, scope: session.scope }
}

// Use with handlers
router.add(app.bsky.feed.post.create, {
  auth: requireAuth,
  handler: async ({ credentials, input }) => {
    // credentials.did is available here
    const post = await db.createPost(credentials.did, input.body)
    return { body: post }
  },
})
```

认证函数 :

1.  名为 **在此之前** 解析请求正文
2.  接收 `params`, (中文(简体) ), `request`,以及 `connection` 资讯
3.  应投出 `LexServerError` (或 `LexServerAuthError`关于失败
4.  返回交给处理者的证书

### WWW- 认证信头

使用 `LexServerAuthError` 包括 `WWW-Authenticate` 错误回复中的标题 :

```typescript
import { LexServerAuthError } from '@atproto/lex-server'

// Simple Bearer challenge
throw new LexServerAuthError('AuthenticationRequired', 'Login required', {
  Bearer: { realm: 'api' },
})
// WWW-Authenticate: Bearer realm="api"

// Multiple schemes
throw new LexServerAuthError('AuthenticationRequired', 'Auth required', {
  Bearer: { realm: 'api', scope: 'read write' },
  Basic: { realm: 'api' },
})
// WWW-Authenticate: Bearer realm="api", scope="read write", Basic realm="api"

// Token68 format
throw new LexServerAuthError('AuthenticationRequired', 'Auth required', {
  Bearer: 'token68value',
})
// WWW-Authenticate: Bearer token68value
```

## 处理错误

### LexServer 错误

掷出 `LexServerError` 返回结构化的 XRPC 错误响应 :

```typescript
import { LexServerError } from '@atproto/lex-server'

router.add(app.bsky.actor.getProfile, async ({ params }) => {
  try {
    const profile = await db.getProfile(params.actor)
    return { body: profile }
  } catch (cause) {
    throw new LexServerError(
      404,
      {
        error: 'NotFound',
        message: 'Profile not found',
      },
      {
        'cache-control': 'max-age=600',
      },
      { cause },
    )
  }
})
```

使用 XRPC 格式的错误反应 :

```json
{
  "error": "NotFound",
  "message": "Profile not found"
}
```

### LexServer Auth 错误

`LexServerAuthError` 扩展 `LexServerError` 与 `WWW-Authenticate` 页眉支持 :

```typescript
import { LexServerAuthError } from '@atproto/lex-server'

throw new LexServerAuthError('AuthenticationRequired', 'Invalid credentials', {
  Bearer: { realm: 'api' },
})
```

返回与 $401 的响应 `WWW-Authenticate` 头曰.

### 处理器召回错误

使用 `onHandlerError` 以登录或报告出乎意料的错误 :

```typescript
const router = new LexRouter({
  onHandlerError: async ({ error, request, method }) => {
    // Log errors (excluding expected abort signals)
    console.error(`Error in ${method.nsid}:`, error)
    await reportToSentry(error)
  },
})
```

> \[注\]
> 
> 回调只用于意外错误,而不是用于 `LexError` 实例或请求中止.

## 节点.js 服务器

这个 `@atproto/lex-server/nodejs` 子路径提供Node.js特定公用事业.

### 服务( )

启动服务器并开始监听 :

```typescript
import { serve } from '@atproto/lex-server/nodejs'

const server = await serve(router, { port: 3000 })
console.log('Server listening on port 3000')

// Graceful shutdown
await server.terminate()
```

服务器支持 `AsyncDisposable`数字 :

```typescript
await using server = await serve(router, { port: 3000 })
// Server is automatically terminated when scope exits
```

选项 :

```typescript
type StartServerOptions = {
  port?: number
  host?: string
  gracefulTerminationTimeout?: number // ms to wait for connections to close
}
```

### 创建 Server ()

不启动而创建服务器 :

```typescript
import { createServer } from '@atproto/lex-server/nodejs'

const server = createServer(router, {
  gracefulTerminationTimeout: 5000,
})

server.listen(3000, () => {
  console.log('Server listening')
})
```

### 请求收听器 ()

将处理器转换为快递/连接兼容的中间软件 :

```typescript
import express from 'express'
import { toRequestListener } from '@atproto/lex-server/nodejs'

const app = express()

// Mount the XRPC router
app.use(toRequestListener(router.fetch))

app.listen(3000)
```

### 升级WebSocket ()

在节点.js中需要 WebSocket 订阅支持 :

```typescript
import { LexRouter } from '@atproto/lex-server'
import { upgradeWebSocket } from '@atproto/lex-server/nodejs'

const router = new LexRouter({ upgradeWebSocket })
```

## 高级使用

### 自定义响应对象

还原 a `Response` 用于完全控制响应的对象(任何类型的功能) 该机构的审定:

```typescript
router.add(schema, async ({ params }) => {
  if (params.redirect) {
    return Response.redirect('https://example.com', 302)
  }

  return Response.json(
    { custom: true },
    {
      status: 201,
      headers: {
        'X-Custom-Header': 'value',
      },
    },
  )
})
```

### 答复信头

在回复中添加标题 :

```typescript
router.add(schema, async ({ params }) => {
  return {
    body: { data: 'value' },
    headers: {
      'Cache-Control': 'public, max-age=3600',
      'X-Request-Id': crypto.randomUUID(),
    },
  }
})
```

### 连接信息

访问网络连接信息 :

```typescript
router.add(schema, async ({ connection }) => {
  console.log('Remote address:', connection?.remoteAddr?.hostname)
  console.log('Local address:', connection?.localAddr?.hostname)
  return { body: { status: 'ok' } }
})
```

连接信息结构 :

```typescript
type ConnectionInfo = {
  localAddr?: {
    hostname: string
    port: number
    transport: 'tcp' | 'udp'
  }
  remoteAddr?: {
    hostname: string
    port: number
    transport: 'tcp' | 'udp'
  }
}
```

## 许可证

麻省理工学院或Apachi2

## 常见问题

### @atproto/lex-server 是什么？

Atproto Lexicon 协议和计划请求路由器

### 如何安装 @atproto/lex-server？

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

### @atproto/lex-server 支持 TypeScript 吗？

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

### @atproto/lex-server 支持 ESM 还是 CommonJS？

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

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

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

### @atproto/lex-server 可以商用吗？

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

### @atproto/lex-server 的下载量有多少？

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

### @atproto/lex-server 还在维护吗？

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

