플러그인 API 레퍼런스
플러그인 시스템을 사용하면 핵심 publish 파이프라인을 포크하지 않고 pubm을 확장할 수 있습니다.
PubmPlugin
섹션 제목: “PubmPlugin”export interface PubmPlugin { name: string; registries?: PackageRegistry[]; ecosystems?: Ecosystem[]; hooks?: PluginHooks; commands?: PluginCommand[]; credentials?: (ctx: PubmContext) => PluginCredential[]; checks?: (ctx: PubmContext) => PluginCheck[];}credentials- 이 플러그인에 필요한 토큰 목록을 반환합니다. pubm은 초기화 중 한 번 호출해서 누락된 토큰을 프롬프트하고, 환경 변수에 주입하며,--ci-prepare실행 시 GitHub Secrets와 동기화합니다.checks- 핵심 prerequisite/condition 단계와 함께 실행할 preflight check 목록을 반환합니다. 각 check는phase필드로 실행 시점을 선언합니다.
Hooks
섹션 제목: “Hooks”export interface PluginHooks { // 라이프사이클 훅 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;
// asset pipeline 훅 resolveAssets?: AssetPipelineHooks["resolveAssets"]; transformAsset?: AssetPipelineHooks["transformAsset"]; compressAsset?: AssetPipelineHooks["compressAsset"]; nameAsset?: AssetPipelineHooks["nameAsset"]; generateChecksums?: AssetPipelineHooks["generateChecksums"]; uploadAssets?: AssetPipelineHooks["uploadAssets"];}Asset pipeline 훅
섹션 제목: “Asset pipeline 훅”여섯 개의 훅으로 플러그인이 release asset 파이프라인의 각 단계를 가로챌 수 있습니다. 이 훅들은 build 단계와 GitHub Release 업로드 사이에서 실행됩니다.
| Hook | 실행 시점 | 입력 → 출력 |
|---|---|---|
resolveAssets | glob 매칭 직후 | ResolvedAsset[] → ResolvedAsset[] |
transformAsset | asset별, 압축 전 | ResolvedAsset → TransformedAsset | TransformedAsset[] |
compressAsset | asset별, 내장 압축 대체 | TransformedAsset → CompressedAsset |
nameAsset | asset별, 압축 후 | CompressedAsset → string |
generateChecksums | 모든 asset이 이름과 해시를 가진 뒤 | PreparedAsset[] → PreparedAsset[] |
uploadAssets | GitHub Release 업로드 후 | PreparedAsset[] → UploadedAsset[] |
여러 플러그인이 같은 asset pipeline 훅을 등록하면 등록 순서대로 체인됩니다. uploadAssets는 예외입니다. 각 플러그인은 같은 입력을 독립적으로 받고, 결과는 모두 이어 붙입니다.
전체 시그니처, 예제, 조합 규칙은 Asset Pipeline Hooks에서 확인합니다.
Hook 시그니처
섹션 제목: “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
섹션 제목: “PubmContext”훅은 현재 파이프라인 컨텍스트를 받습니다.
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, temp directory 등)ctx.runtime.pluginTokens-PluginCredential.key를 키로 하는 해석된 플러그인 자격 증명 값 맵입니다. 자격 증명 수집 단계 이후 채워지며 이후 모든 hook에서 사용할 수 있습니다.
Rollback API
섹션 제목: “Rollback API”플러그인은 publish 파이프라인이 실패할 때 자동으로 실행되는 롤백 액션을 등록할 수 있습니다. 액션은 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
섹션 제목: “RollbackAction”| 속성 | 타입 | 설명 |
|---|---|---|
label | string | 롤백 중 표시되는 사람이 읽을 수 있는 설명 |
fn | (ctx: PubmContext) => Promise<void> | 부작용을 되돌리는 비동기 함수 |
confirm | boolean? | true이면 TTY 모드에서 실행 전 확인을 요청합니다. CI에서는 자동으로 실행됩니다. |
PluginCredential
섹션 제목: “PluginCredential”플러그인이 필요로 하는 토큰이나 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에서 토큰을 제공하는 환경 변수 이름입니다. |
label | string | 대화형 프롬프트에 표시되는 사람이 읽을 수 있는 라벨입니다. |
tokenUrl | string | 사용자가 토큰을 생성할 수 있는 선택적 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 | 선택적 토큰 검증기입니다. 해석된 토큰과 PluginTaskContext를 받아 false를 반환하면 다시 프롬프트합니다. |
해석 순서: env 환경 변수 -> resolve() -> keyring(SecureStore) -> 대화형 프롬프트.
PluginCheck
섹션 제목: “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"는 레지스트리 연결 확인 후에 실행됩니다. |
task | function | check 구현입니다. 오류를 발생시키면 check가 실패합니다. |
PluginTaskContext
섹션 제목: “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 프롬프트를 실행합니다. 대화형 모드에서만 사용할 수 있습니다.
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>;}커스텀 레지스트리와 생태계
섹션 제목: “커스텀 레지스트리와 생태계”추가 publish 대상을 넣어야 할 때는 커스텀 레지스트리를 사용합니다. 다른 패키지 타입의 version 읽기/쓰기를 pubm에 가르쳐야 할 때는 커스텀 생태계를 사용합니다.