@atcute/identity-resolver

中文文档
2.0.3发布于 2026/10/100BSDES Module近 30 天下载 35万

atproto 处理和文档解析

中文使用文档
文档目录14 节
  1. 使用量
  2. 解析手柄
  3. 决议战略
  4. 解析已执行的文档
  5. 解决行为者
  6. 处理出错
  7. 缓存和中止信号
  8. 自定义抓取函数
  9. 服务器侧分辨率和 SSRF
  10. 自定义 PLC 目录
  11. 解析器类
  12. 处理解析器
  13. D. 文档解析器
  14. 演员解析器

@ atcute/ identity- solover

操作和完成 AT 协议的文档解析.

npm install @atcute/identity-resolver

在AT 协议中,控件(如 alice.bsky.social需要解决DCDs, 而DIDs需要 解析为 DID 文档(其中包含用户的PDS位置和密钥). 此软件包提供了 双方的解决方案.

使用量

解析手柄

手柄可以通过 DNS TXT 记录或 HTTP 知名端点来解决. 使用复合解析器 尝试两种:

import {
    CompositeHandleResolver,
    DohJsonHandleResolver,
    WellKnownHandleResolver,
} from '@atcute/identity-resolver';

const handleResolver = new CompositeHandleResolver({
    methods: {
        dns: new DohJsonHandleResolver({ dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query' }),
        http: new WellKnownHandleResolver(),
    },
});

const did = await handleResolver.resolve('bsky.app');
// -> "did:plc:z72i7hdynmk6r22z27h6tvur"

决议战略

复合解析器支持结合 DNS 和 HTTP 分辨率的不同策略 :

const handleResolver = new CompositeHandleResolver({
    strategy: 'race', // default - first successful response wins
    methods: { dns: dnsResolver, http: httpResolver },
});

现有战略:

  • race - 返回首先成功的方法(默认)
  • dns-first - 先试试DNS,如果失败就回HTTP
  • http-first -先试试HTTP,如果失败就回DNS
  • both - 要求两种方法都同意(投掷) AmbiguousHandleError 如果两者不同)

解析已执行的文档

DID 文档可以解析为 id:plc 和 did:web 方法 :

import {
    CompositeDidDocumentResolver,
    PlcDidDocumentResolver,
    WebDidDocumentResolver,
} from '@atcute/identity-resolver';

const didResolver = new CompositeDidDocumentResolver({
    methods: {
        plc: new PlcDidDocumentResolver(),
        web: new WebDidDocumentResolver(),
    },
});

const doc = await didResolver.resolve('did:plc:z72i7hdynmk6r22z27h6tvur');
// -> { '@context': [...], id: 'did:plc:...', service: [...], ... }

解决行为者

页:1 ActorResolver 界面提供了一种方法,可以解决一个角色标识符(处理或DID)到 需要与它们进行互动的重要信息:它们已经实现的、经过核实的手柄和PDS的终点.

LocalActorResolver 通过将控件和文档解析合并到本地来实现 :

import { LocalActorResolver } from '@atcute/identity-resolver';

const actorResolver = new LocalActorResolver({
    handleResolver,
    didDocumentResolver: didResolver,
});

// resolve from handle
const actor = await actorResolver.resolve('bsky.app');
// -> { did: "did:plc:...", handle: "bsky.app", pds: "https://..." }

// resolve from DID
const actor2 = await actorResolver.resolve('did:plc:z72i7hdynmk6r22z27h6tvur');
// -> { did: "did:plc:...", handle: "bsky.app", pds: "https://..." }

本地解析器执行双向验证: 它检查 DID 中的控点 文档解析为相同的已执行 .

其他执行 ActorResolver 可从专用身份服务处获得此信息( 如 Slingshot),无需取取并解析完整DD文件.

处理出错

每个解析器为不同的失败大小写丢出特定错误类型 :

import {
    DidNotFoundError,
    InvalidResolvedHandleError,
    AmbiguousHandleError,
    FailedHandleResolutionError,
    HandleResolutionError,
} from '@atcute/identity-resolver';

try {
    const did = await handleResolver.resolve('nonexistent.invalid');
} catch (err) {
    if (err instanceof DidNotFoundError) {
        // handle has no DID record
        console.log('handle not found');
    } else if (err instanceof InvalidResolvedHandleError) {
        // handle returned an invalid DID format
        console.log('invalid DID:', err.did);
    } else if (err instanceof AmbiguousHandleError) {
        // multiple different DIDs found (with 'both' strategy)
        console.log('ambiguous handle');
    } else if (err instanceof FailedHandleResolutionError) {
        // network or other unexpected error
        console.log('resolution failed:', err.cause);
    } else if (err instanceof HandleResolutionError) {
        // catch-all for any handle resolution error
    }
}

文件解析错误 :

import {
    DocumentNotFoundError,
    UnsupportedDidMethodError,
    ImproperDidError,
    FailedDocumentResolutionError,
    DidDocumentResolutionError,
} from '@atcute/identity-resolver';

try {
    const doc = await didResolver.resolve('did:example:123');
} catch (err) {
    if (err instanceof DocumentNotFoundError) {
        // DID document doesn't exist
    } else if (err instanceof UnsupportedDidMethodError) {
        // resolver doesn't support this DID method
    } else if (err instanceof ImproperDidError) {
        // DID format is invalid for this method
    } else if (err instanceof FailedDocumentResolutionError) {
        // network or other unexpected error
    } else if (err instanceof DidDocumentResolutionError) {
        // catch-all for any DID resolution error
    }
}

缓存和中止信号

所有解析器接受缓存控制和取消的选项 :

// skip cache
const did = await handleResolver.resolve('bsky.app', { noCache: true });

// with abort signal
const controller = new AbortController();
const did = await handleResolver.resolve('bsky.app', { signal: controller.signal });

// cancel the request
controller.abort();

自定义抓取函数

所有解析器接受自定义获取执行 :

const dnsResolver = new DohJsonHandleResolver({
    dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query',
    fetch: customFetch,
});

const httpResolver = new WellKnownHandleResolver({
    fetch: customFetch,
});

const plcResolver = new PlcDidDocumentResolver({
    fetch: customFetch,
});

服务器侧分辨率和 SSRF

解决服务器上的不可信身份可以将内部服务暴露给服务器侧请求 伪造(SSRF). 例如, did:web:localhost%3a6379 瞄准HTTP上的回回地址 did:web:169.254.169.254 目标为链接本地地址.

解析器不限制目标 IP。通过自定义 fetch 拒绝非公众 连接时的地址。 仅检查主机名是不够的: DNS 可以解决公众 私人IP的主机名 .

const didResolver = new CompositeDidDocumentResolver({
    methods: {
        plc: new PlcDidDocumentResolver({ fetch: safeFetch }),
        web: new WebDidDocumentResolver({ fetch: safeFetch }),
    },
});

关于云旗工人,启用 global_fetch_strictly_public 在朗格勒配置。 打开 节点.js,使用一个获取调度器,在连接时间检查目的地IP.

自定义 PLC 目录

默认情况下, 是否使用: plc 解析度 https://plc.directory。您可以指定不同的目录 :

const plcResolver = new PlcDidDocumentResolver({
    apiUrl: 'https://plc.wtf', // mirror of plc.directory
});

解析器类

处理解析器

类说明
DohJsonHandleResolver通过 DNS- over- HTTPS (TXT 记录于 _atproto.{handle}(中文(简体) )
WellKnownHandleResolver通过 HTTP 解析( L)https://{handle}/.well-known/atproto-did(中文(简体) )
XrpcHandleResolver通过 XRPC 解决(com.atproto.identity.resolveHandle(中文(简体) )
CompositeHandleResolver结合 DNS 和 HTTP 解析器

D. 文档解析器

类说明
PlcDidDocumentResolver解析已实现: plc 从 PLC 目录
WebDidDocumentResolver解析已实现: 来自域名的web
XrpcDidDocumentResolver通过 XRPC 解决(com.atproto.identity.resolveDid(中文(简体) )
CompositeDidDocumentResolver通过 DOD 方法解析器的路径

演员解析器

类说明
LocalActorResolver将处理和DD 解析与双向核查相结合

版本与发布记录

@atcute/identity-resolver 共发布 19 个版本,首次发布于 2025/03/13;过去 12 个月发布了 8 个版本。

版本发布日期距今
2.0.3latest2026/10/1028 天前
2.0.22026/09/121 个月前
2.0.12026/06/294 个月前
2.0.02026/05/095 个月前
1.2.32026/05/086 个月前
1.2.22026/01/0310 个月前

关于 @atcute/identity-resolver 的常见问题

@atcute/identity-resolver 是什么?

atproto 处理和文档解析

如何安装 @atcute/identity-resolver?

在项目目录运行 npm install @atcute/identity-resolver,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@atcute/identity(^2.0.0)、@atcute/lexicons(^2.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@atcute/identity-resolver 支持 TypeScript 吗?

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

@atcute/identity-resolver 支持 ESM 还是 CommonJS?

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

@atcute/identity-resolver 可以商用吗?

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

@atcute/identity-resolver 的下载量有多少?

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

@atcute/identity-resolver 还在维护吗?

最新版本 2.0.3 发布于 2026/10/10(28 天前);至今共发布 19 个版本,其中过去 12 个月发布了 8 个;首次发布于 2025/03/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。