查询注册表

本页内容

这是一个高级主题,用于针对插件注册表构建您自己的软件。如果您只想在 EmDash 站点上安装插件,则不需要这些——在配置中启用注册表并使用管理仪表板即可。

注册表的发现端是一个公开的只读 API。@emdash-cms/registry-client 包对其进行封装,这样您就可以在 EmDash 之外构建插件目录、搜索页面或发布订阅源。客户端可在任何 fetch 可用的地方运行——Node、Workers、浏览器或 Astro 站点。

安装

discovery 子路径没有认证或 OAuth 依赖。安装客户端并固定到确切版本:

npm install @emdash-cms/[email protected]

列出和解析包

以下 Astro 页面列出注册表中的所有插件:

---
import { DiscoveryClient } from "@emdash-cms/registry-client/discovery";

const discovery = new DiscoveryClient({
  aggregatorUrl: "https://registry.emdashcms.com",
});

const { packages } = await discovery.searchPackages({ q: "", limit: 50 });
---

<ul>
  {
    packages.map((pkg) => (
      <li>
        <a href={`/plugins/${pkg.did}/${pkg.slug}`}>
          {pkg.profile?.name ?? pkg.slug}
        </a>
        {pkg.latestVersion && <span>v{pkg.latestVersion}</span>}
        <p>{pkg.profile?.description}</p>
      </li>
    ))
  }
</ul>

链接使用始终存在的 pkg.did。发布者 handle 是尽力而为的,可能不存在,因此不要从中构建 URL。

包详情页通过 DID 和 slug 获取插件,然后获取最新发布:

import { DiscoveryClient } from "@emdash-cms/registry-client/discovery";

const discovery = new DiscoveryClient({
  aggregatorUrl: "https://registry.emdashcms.com",
});

export async function getPlugin(did: string, slug: string) {
  const pkg = await discovery.getPackage({ did, slug });
  const latest = await discovery.getLatestRelease({
    did: pkg.did,
    package: pkg.slug,
  });
  return { pkg, latest };
}

发现方法

客户端为每个聚合器查询公开一个方法:

  • searchPackages({ q, capability?, limit?, cursor? }) — 自由文本搜索,可选择过滤到声明了给定访问类别的包。返回 { packages, cursor? }
  • resolvePackage({ handle, slug }) — 通过 handle 和 slug 解析包。
  • getPackage({ did, slug }) — 通过 DID 和 slug 获取包。
  • listReleases({ did, package, limit?, cursor? }) — 包的所有发布,最新版本优先。
  • getLatestRelease({ did, package }) — 未撤回的最高发布版本。

处理不可信记录

聚合器是一个不可信的索引,它转发不是自己编写的记录,因此客户端在边界处验证每一条记录。由此产生两条规则:

  • profilerelease 字段可以是 null 当转发的记录验证失败时,客户端将其呈现为 null 而不是让整个调用失败,这样一条格式错误的记录不会清空搜索页面。在读取 pkg.profile?.namelatest.release?.artifacts.package 之前始终进行空值检查。
  • 在渲染之前自行验证 URL 方案。 验证检查结构,而不是 URL 安全性——uri 字段可以携带 javascript: 方案。在将注册表提供的任何 URL 放入 hrefsrc 之前,应用您自己的 http/https 许可列表。

非 2xx 响应会抛出 ClientResponseError(从包中重新导出),包含 .error.description.status.headers

按主机兼容性过滤

发布可以在其 requires 块中声明环境要求(EmDash 或 Astro 版本范围)。@emdash-cms/registry-client/env 子路径对其进行评估,这样目录可以标记不会在给定主机上运行的发布:

import { checkEnvCompatibility, hostEnvFromVersions } from "@emdash-cms/registry-client/env";
import type { ValidatedReleaseView } from "@emdash-cms/registry-client/discovery";

const host = hostEnvFromVersions("0.17.0", "5.6.0");

// 传入 getLatestRelease() 结果。当发布在此主机上运行时,
// 返回的数组为空。
export function envMismatches(latest: ValidatedReleaseView) {
  return checkEnvCompatibility(latest.release?.requires, host);
}

接下来阅读