首页
/ Supabase Reference Docs 技术解析:DocSpec 文档规范体系与规格驱动的文档生成管线

Supabase Reference Docs 技术解析:DocSpec 文档规范体系与规格驱动的文档生成管线

2026-09-06 12:51:41作者:冯爽妲Honey

Supabase 官方文档站(apps/docs)除了常规教程外,还承载了整个 Supabase 生态工具的参考文档(Reference Docs)。本文围绕该应用的 README 展开,结合 spec 目录generator 源码spec/Makefile,讲清楚其“文档规格(DocSpec)”体系的设计动机、四类规范的定义、从 YAML/JSON 规格到 HTML 文档的完整生成管线,以及工具维护者贡献文档的落地路径。读完本文,你将理解 Supabase 如何用一套严格的模式(schema)同时产出 HTML 文档、manpage 等多种格式,并能独立运行或扩展该生成管线。

Reference Docs 是什么:为生态工具统一供给文档

apps/docs/README.md 对该应用的定位只有两句话:这是 “Supabase Reference Docs”,并且面向 Supabase 生态的工具维护者——如果你维护 Supabase 生态中的任何工具(tools or libraries),可以借助该站点为你提供所维护工具与库的文档。

从仓库结构看,这一承诺体现在 apps/docs 的组成上:

  • content/ 存放手工撰写的指南(约 840 个 MDX 文件),对应 supabase.com/docs 上的 Guides;
  • spec/ 存放全部机器可读的文档规格(OpenAPI JSON、CLISpec/SDKSpec/ConfigSpec YAML 等),这是参考文档的“单一事实来源”;
  • generator/ 是 TypeScript 实现的文档生成器,把规格渲染为 Markdown 片段;
  • app/features/ 是 Next.js 站点本身,负责把生成的参考内容渲染成网页。

README 中“Contributing”部分指出的两条入口文档分别为 开发指南贡献指南,二者分别解决“如何本地跑起文档站”与“仓库组织与写作规范”的问题。

DocSpec 体系:四类文档规格

README 的核心论点是:Supabase 使用“文档规格”(documentation specifications)来生成人类可读的文档,共四类:

规格 类型 用途 仓库中的实际载体
OpenAPI 行业标准 描述 API 端点 api_v1_openapi.jsonapi_v2_openapi.jsonauth_v1_openapi.jsonstorage_v0_openapi.jsonanalytics_v0_config.yaml
SDKSpec Supabase 自定义 描述 SDK 与客户端库 supabase_js_v1.ymlsupabase_dart_v2.ymlsupabase_py_v2.ymlsupabase_kt_v3.ymlsupabase_swift_v2.ymlsupabase_csharp_v1.yml
ConfigSpec Supabase 自定义 描述配置项 cli_v1_config.yamlfunctions_v0_config.yaml
CLISpec Supabase 自定义 描述 CLI 命令与用法 cli_v1_commands.yaml(约 4100 行)

SDKSpec 示例:以 supabase-js 为例

spec/supabase_js_v1.yml 展示了 SDKSpec 的头部结构:以 openref: 0.1 声明规格引用版本,info 段包含文档 id(reference/supabase-js)、标题、描述,以及关键的 definition: spec/enrichments/tsdoc_v1/combined.json 字段——它把 SDK 的 TypeDoc 元数据(API 符号定义)与这份 YAML 挂钩;functions 数组则按功能点组织条目,每个条目通过 $ref 引用具体的 TypeDoc 符号(如 @supabase/supabase-js.index.SupabaseClient.constructor),并内嵌可运行的代码示例:

functions:
  - id: initializing
    title: 'Initializing'
    $ref: '@supabase/supabase-js.index.SupabaseClient.constructor'
    examples:
      - id: create-client
        name: Create Client
        code: |
          ```js
            import { createClient } from '@supabase/supabase-js'

            // Create a single supabase client for interacting with your database
            const supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')
          ```

这套“YAML 骨架 + TypeDoc 符号引用 + 内联示例”的组织方式,使文档条目天然跟随库的真实 API 符号,避免手写文档与代码漂移。

CLISpec 示例:CLI 命令与全局标志

spec/cli_v1_commands.yamlclispec: '001' 开头,info 段声明了 CLI 的 id、当前记录版本(version: 2.98.2)、语言(language: sh)以及 tags(quick-start、local-dev、management-api、other-commands),随后定义了全局标志(如 --agent--create-ticket--debug--dns-resolver <[ native | https ]>--experimental),每个标志都带 descriptiondefault_value 和可选的 accepted_values。这种把“默认值 + 取值范围 + 枚举”全部结构化的做法,正是 README 所说“严格 schema”的落地形态:机器可以据此生成参数表、校验取值,而非仅输出一行描述文本。

为什么用自定义规格:一份 schema,多种产物

README 给出的收益论证是:使用自定义规格后,可以从同一份严格 schema 生成许多其他类型的产物(例如 HTML 与 manpages),并且可以随意切换文档系统——本站使用 Next.js,而 Supabase 官网(supabase.com)使用一套自定义 React 站点,并且只暴露每个工具 API 的一个子集。

这一“一源多产物”能力在仓库中有明确证据:

  • 生成器产物是 Markdown 文档片段(由 EJS 模板渲染后写盘),供 Next.js 站点消费;
  • 同一份 OpenAPI 规格还驱动了额外管线。spec/Makefile 中的 generate.partials.access-control 目标会调用 sections/generateAccessControlPartials.mts,从 v1/v2 管理 API 规格加上 mcp_tools_permissions.json,生成 content/_partials/access-control/ 下的 PAT 权限表格 MDX——即同一份 API 规格既是端点参考的来源,也是权限矩阵的来源。

生成管线:从规格文件到文档的三个环节

1. 下载:make download

spec/README.md 说明进入 apps/docs/spec 后先执行 make init 安装依赖,然后 make 即可完成“下载并转换规格为文档”的全过程。Makefile 的 download 目标并行拉取多个来源:

  • 管理 API:curl https://api.supabase.com/api/v1-json/api/v2-json,落地为 api_v1_openapi.json / api_v2_openapi.json
  • Storage API:从 supabase.github.io/storage/api.json 拉取 storage_v0_openapi.json
  • 客户端库 TypeDoc 元数据(v2):从 supabase.github.io 拉取 supabase-js、auth-js、postgrest-js、realtime-js、storage-js、functions-js 六个包的 spec.json,写入 reference/javascript/v2/
  • 服务端库:server.jsonmiddleware.json 分别写入 reference/server/v1/reference/middleware/v1/
  • MCP 工具权限投影:platform/mcp-tools-permissions

Makefile 中的注释还保留了历史演进痕迹:download.auth.v1(从 gotrue 的 swagger.json 拉取)因“流程需要更新、当前手工维护”而被注释掉,auth 规格现由人工维护——这提醒读者:仓库中的规格文件既有自动下载件,也有人工维护件,贡献前需先确认对应来源。

2. 转换:redocly bundle 消除 $ref

OpenAPI 文件大量使用 $ref 指向共享 schema,直接渲染会导致文档碎片化。transform 目标使用 Redocly CLI 做 bundle(内联引用):

dereference.api.v1:
	npx --package=@redocly/cli redocly bundle -o $(REPO_DIR)/transforms/api_v1_openapi_deparsed.json $(REPO_DIR)/api_v1_openapi.json
	npx --package=@redocly/cli redocly bundle -o $(REPO_DIR)/transforms/api_v2_openapi_deparsed.json $(REPO_DIR)/api_v2_openapi.json

dereference.auth.v1:
	npx --package=@redocly/cli redocly bundle --dereferenced -o $(REPO_DIR)/transforms/auth_v1_openapi_deparsed.json $(REPO_DIR)/auth_v1_openapi.json

注意一个被显式注释记录的实现细节:api_v1/v2 特意不带 --dereferenced,因为 api_v2_openapi.json 存在循环引用(APIErrorObject.issues -> APIErrorObject),Redocly 无法将其展平为 JSON,这些引用改由 writeApiReferenceSections 在生成阶段手工解析。这类“源码级注释”是理解该管线边界条件的可靠依据。

此外,针对 JS 客户端库的 TypeDoc JSON,@supabase/generator 包(packages/generator)提供了一组 tsdoc:dereference:* 脚本(覆盖 supabase/auth/postgrest/realtime/storage/functions 的 v1 与 v2),把含 $ref 的 TypeDoc 输出解析为 *_dereferenced.json,供后续生成器消费。

3. 生成:DocGenerator 按类型分发

生成阶段的统一入口是 generator/index.ts。它使用 node:utilparseArgs 解析命令行参数(--input--output/-n--type/-n--url/-n),对输入、输出与类型做 assert 校验,类型白名单为:

const allowedTypes = ['cli', 'config', 'sdk', 'api', 'legacy'] as const

随后按类型分发到各自的生成函数:ApiGeneratorCliGeneratorConfigGeneratorSdkGeneratorLegacyGeneratorgenerator/legacy.ts 处理旧版规格)。

三个自定义规格生成器共享同一套实现模式,读起来几乎是对称的:

CLISpec 生成器generator/cli.ts):yaml.load 读入规格,依据 spec.clispec 版本字段分发(当前实现 001)。v001 逻辑先用 spec.commands 建立 id -> command 的 Map,为每条命令计算标题层级——有子命令的命令渲染为 ## 二级标题,叶子命令渲染为 ### 三级标题(并附带 [#id] 锚点),再经 ejs.render 套用 templates/CliTemplate 渲染为 Markdown,最后 writeToDisk 写盘。

SDKSpec 生成器generator/sdk.ts):同样按 spec.sdkspec: '001' 分发,v001 把 infofunctionstypes 注入 SdkTemplate 渲染输出。

ConfigSpec 生成器generator/config.ts):按 spec.configspec: '001' 分发,v001 的一个关键步骤是“按 tag 分组参数”——以 spec.info.tags 作为章节骨架,对 spec.parametersparameter.tags[0] === section.id 过滤,把扁平的参数列表组织为带标题的章节,再渲染 ConfigTemplate。这解释了 ConfigSpec 规格文件中 tags 字段的用途:它同时是参数的分类键与文档的章节顺序。

所有生成器都通过 generator/helpers.tswriteToDisk 统一落盘,并在控制台打印保存路径,方便 CI 与本地排查。

生成管线全景

综合以上,apps/docs/spec 的完整流水线为:

make download        # 拉取 OpenAPI / TypeDoc / 权限投影(部分手工维护)
  └─ make transform  # redocly bundle 内联 $ref -> transforms/*_deparsed.json
       └─ make generate
            ├─ sections/generateMgmtApiSections.cts     # v1/v2 管理 API 章节
            └─ sections/generateAccessControlPartials.mts # PAT 权限矩阵 MDX
  └─ make format      # prettier 统一格式,便于 git 追踪变更

其中 generate.sections.api.v1 同时喂入 v1 与 v2 两份 deparsed 规格加 common-api-sections.json,说明章节生成器具备跨版本对比/合并能力;format 目标的存在动机也写在 Makefile 注释里:“让 git 更容易追踪变更”。

站点侧:Next.js 渲染与配套工程实践

README 提到“本站点使用 Next.js”——从 apps/docs/package.jsonDEVELOPERS.md 可以还原本地开发的最小闭环:

  1. 按根目录 DEVELOPERS.md 完成 Turborepo 环境安装;
  2. apps/docs 下创建 .env.local,社区贡献者至少需要 NEXT_PUBLIC_IS_PLATFORM=false(该变量用于区分本地环境与平台环境);
  3. pnpm run dev 启动后访问 http://localhost:3001/docs(必须带 /docs 前缀);
  4. 站点外观应与 supabase.com/docs 完全一致,作为本地正确性的验收标准。

DEVELOPERS.md 还记载了两项值得注意的工程实践,它们与“规格驱动”的思路一脉相承:

  • 面向 AI 的文档产物pnpm build:guides-markdown 会为 /docs/guides/.. 下每个路由生成纯 Markdown 文件到 public/markdown/guides(git 忽略),生产构建时作为 prebuild 任务运行,使 LLM/Agent 能通过 middleware 与 edge functions 直接消费 Markdown 版指南——参考文档的“规格 -> 多产物”理念在指南侧的延伸;
  • 无障碍自动化:文档页面通过 e2e/docs 中的 Playwright + axe-core 套件做 WCAG 2.1 A/AA 扫描,PR 只扫描改动影响的页面(pnpm e2e:docs:a11y,可用 PLAYWRIGHT_BASE_URL 指向 PR 预览环境)。

如何贡献:维护者的落地路径

回到 README 的主旨——“如果你是 Supabase 生态工具的维护者”:

  1. 阅读入口文档DEVELOPERS.md 覆盖环境搭建,CONTRIBUTING.md 覆盖仓库组织与写作风格;
  2. 选择正确的规格类型:API 端点走 OpenAPI(JSON),SDK/库走 SDKSpec(YAML),配置项走 ConfigSpec,CLI 命令走 CLISpec;对应生成器分别位于 generator/api.tsgenerator/sdk.tsgenerator/config.tsgenerator/cli.ts,规格文件统一放在 apps/docs/spec/
  3. 遵循既有的结构惯例:CLISpec 用 clispec: '001' + info.tags + 结构化 flags/commands;SDKSpec 用 functions + $ref 指向 TypeDoc 符号并内嵌代码示例;ConfigSpec 用 info.tags 作为参数分组与章节骨架;
  4. 本地验证:在 apps/docs/spec 下用 Makefile(make init 初始化依赖后按需执行 download/transform/generate/format 各阶段),再在 apps/docspnpm run devlocalhost:3001/docs 目检渲染结果。

小结

Supabase 文档站的 Reference Docs 本质上是一套“规格优先”的文档基础设施:四类规格(OpenAPI、SDKSpec、ConfigSpec、CLISpec)以严格 schema 描述 API 端点、客户端库、配置项与 CLI 命令,apps/docs/spec 下的 Makefile 负责拉取与 Redocly 转换,apps/docs/generator 的 TypeScript 生成器按 clispec/sdkspec/configspec 版本字段分发展现渲染,同一份规格还可衍生出权限矩阵、manpage 等其他产物。这种设计让文档系统与具体渲染框架解耦——Next.js 只是当前消费端之一,这也是 Supabase 能够同时维护文档站与官网两套前端而共享同一事实来源的原因。对生态工具维护者而言,贡献参考文档的正确姿势不是直接写 HTML,而是编写或更新对应的规格文件,让生成管线完成从 schema 到网页的最后一公里。

登录后查看全文
热门项目推荐
相关项目推荐