Plugins API 参考
插件系统让你可以在不 fork 核心发布流程的前提下扩展 pubm。
PubmPlugin
Section titled “PubmPlugin”export interface PubmPlugin { name: string; registries?: PackageRegistry[]; ecosystems?: Ecosystem[]; hooks?: PluginHooks; commands?: PluginCommand[]; credentials?: (ctx: PubmContext) => PluginCredential[]; checks?: (ctx: PubmContext) => PluginCheck[];}credentials- 返回这个插件需要的 token 列表。pubm 会在初始化时调用一次,用来提示缺失的 token、注入环境变量,并在执行--ci-prepare时同步到 GitHub Secrets。checks- 返回与核心 prerequisite/condition 阶段一起运行的 preflight check。每个 check 通过phase字段声明执行时机。
export interface PluginHooks { // 生命周期 hooks beforeTest?: HookFn; afterTest?: HookFn; beforeBuild?: HookFn; afterBuild?: HookFn; beforeVersion?: HookFn; afterVersion?: HookFn; beforePublish?: HookFn; afterPublish?: HookFn; beforePush?: HookFn; afterPush?: HookFn; afterRelease?: AfterReleaseHookFn; onError?: ErrorHookFn; onSuccess?: HookFn;
// 资产流水线 hooks resolveAssets?: AssetPipelineHooks["resolveAssets"]; transformAsset?: AssetPipelineHooks["transformAsset"]; compressAsset?: AssetPipelineHooks["compressAsset"]; nameAsset?: AssetPipelineHooks["nameAsset"]; generateChecksums?: AssetPipelineHooks["generateChecksums"]; uploadAssets?: AssetPipelineHooks["uploadAssets"];}资产流水线 hooks
Section titled “资产流水线 hooks”六个 hooks 让插件可以拦截发布资产流水线的每个阶段。它们运行在 build 步骤和上传到 GitHub Release 之间。
| Hook | 运行时机 | 输入 → 输出 |
|---|---|---|
resolveAssets | glob 匹配之后 | ResolvedAsset[] → ResolvedAsset[] |
transformAsset | 每个资产、压缩之前 | ResolvedAsset → TransformedAsset | TransformedAsset[] |
compressAsset | 每个资产,替换内建压缩 | TransformedAsset → CompressedAsset |
nameAsset | 每个资产,压缩之后 | CompressedAsset → string |
generateChecksums | 所有资产完成命名和哈希之后 | PreparedAsset[] → PreparedAsset[] |
uploadAssets | GitHub Release 上传之后 | PreparedAsset[] → UploadedAsset[] |
当多个插件注册同一个资产流水线 hook 时,它们会按注册顺序串联。uploadAssets 是例外:每个插件都会独立接收同一份输入,结果再统一拼接。
阅读 Asset Pipeline Hooks 了解完整签名、示例和组合规则。
Hook 签名
Section titled “Hook 签名”type HookFn = (ctx: PubmContext) => Promise<void> | void;type ErrorHookFn = (ctx: PubmContext, error: Error) => Promise<void> | void;type AfterReleaseHookFn = ( ctx: PubmContext, releaseCtx: ReleaseContext,) => Promise<void> | void;PubmContext
Section titled “PubmContext”Hooks 会接收当前的流程上下文:
export interface PubmContext { readonly config: ResolvedPubmConfig; readonly options: ResolvedOptions; readonly cwd: string; runtime: { tag: string; promptEnabled: boolean; cleanWorkingTree: boolean; pluginRunner: PluginRunner; versionPlan?: VersionPlan; releaseContext?: ReleaseContext; tempDir?: string; pluginTokens?: Record<string, string>; };}关键字段:
ctx.config:解析后的 pubm 配置(packages、registries、plugins、releaseAssets 等)ctx.options:解析后的 CLI 选项(version、tag、mode、dryRun 等)ctx.cwd:工作目录ctx.runtime:可变的运行时状态(version plan、临时目录等)ctx.runtime.pluginTokens:以PluginCredential.key为键的已解析插件凭证值映射。它会在凭证收集步骤之后填充,后续所有 hooks 都能用。
Rollback API
Section titled “Rollback API”插件可以注册回滚操作,当发布流水线失败时会自动执行。操作按 LIFO(后进先出)顺序执行。
在任何 hook 中使用 ctx.runtime.rollback.add() 注册回滚操作:
hooks: { afterVersion: async (ctx) => { // Perform side effect const backup = readFileSync(filePath, "utf-8"); modifyFile(filePath);
// Register rollback to undo it ctx.runtime.rollback.add({ label: `Restore ${filePath}`, fn: async () => { writeFileSync(filePath, backup, "utf-8"); }, }); },}RollbackAction
Section titled “RollbackAction”| 属性 | 类型 | 说明 |
|---|---|---|
label | string | 回滚期间显示的人类可读描述 |
fn | (ctx: PubmContext) => Promise<void> | 用于撤销副作用的异步函数 |
confirm | boolean? | 为 true 时,在 TTY 模式下执行前会请求确认。在 CI 中自动执行。 |
PluginCredential
Section titled “PluginCredential”用于声明插件所需 token 或 secret 的描述类型。
export interface PluginCredential { key: string; env: string; label: string; tokenUrl?: string; tokenUrlLabel?: string; ghSecretName?: string; required?: boolean; resolve?: () => Promise<string | null>; validate?: (token: string, task: PluginTaskContext) => Promise<boolean>;}| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 用于在 ctx.runtime.pluginTokens 中查找值的内部标识符。 |
env | string | 在 CI 中提供该 token 的环境变量名。 |
label | string | 在交互式提示中展示的人类可读标签。 |
tokenUrl | string | 用户可创建该 token 的可选 URL。 |
tokenUrlLabel | string | tokenUrl 的可选展示标签。 |
ghSecretName | string | --ci-prepare 同步时应写入的 GitHub Secret 名称。 |
required | boolean | 为 true 时,如果无法解析该凭证,pubm 会报错。默认值为 true。 |
resolve | function | 可选的自定义 resolver,不接收参数,返回 Promise<string | null>。会在 keyring/prompt fallback 之前调用。 |
validate | function | 可选的 token 校验器。接收已解析 token 和 PluginTaskContext;返回 false 时会重新提示。 |
解析顺序:env 环境变量 -> resolve() -> keyring(SecureStore)-> 交互式提示。
PluginCheck
Section titled “PluginCheck”用于描述插件提供的 preflight check。
export interface PluginCheck { title: string; phase: "prerequisites" | "conditions"; task: (ctx: PubmContext, task: PluginTaskContext) => Promise<void> | void;}| 字段 | 类型 | 说明 |
|---|---|---|
title | string | 在任务列表 UI 中显示的标签。 |
phase | "prerequisites" | "conditions" | 执行时机:"prerequisites" 在网络调用之前运行;"conditions" 在确认 registry 连通性之后运行。 |
task | function | check 的实现。抛出错误即可让该 check 失败。 |
PluginTaskContext
Section titled “PluginTaskContext”作为第二个参数传给 PluginCheck.task 的 listr2 无关包装器。
export interface PluginTaskContext { output: string; title: string; prompt<T = unknown>(options: { type: string; message: string; [key: string]: unknown; }): Promise<T>;}output- 在任务列表 UI 中于 check 标题下显示状态行。title- 动态修改任务标题。prompt()- 运行 enquirer prompt,仅在交互模式下可用。
const notifyPlugin = { name: "notify-plugin", hooks: { async afterPublish(ctx) { const label = ctx.versions && ctx.versions.size > 0 ? [...ctx.versions].map(([name, version]) => `${name}@${version}`).join(", ") : `v${ctx.version}`;
console.log(`Published ${label}`); }, },};export interface PluginCommand { name: string; description: string; subcommands?: PluginSubcommand[];}
export interface PluginSubcommand { name: string; description: string; options?: PluginCommandOption[]; action: (args: Record<string, unknown>) => Promise<void>;}自定义 registries 和 ecosystems
Section titled “自定义 registries 和 ecosystems”当你需要额外的发布目标时,使用自定义 registry。当你需要让 pubm 学会读写另一种 package 类型的版本时,使用自定义 ecosystem。