feat(extension-api): npm package + TypeDoc→MDX docgen + CI workflows (PKG3/4/5)

- packages/extension-api/: @comfyorg/extension-api npm package wrapper
  (src/, package.json, README.md, tsconfig{,.build,.docs}.json,
  typedoc.json, scripts/build-docs.ts, .npmignore, .gitignore)
- .github/workflows/extension-api-typecheck.yml (PKG4.D3)
- .github/workflows/extension-api-publish.yml (PKG4.D4)
- scripts/generate-docs.sh (PKG5.D6)
- pnpm-lock.yaml: workspace dependency for new package

Sidecar: independent of i-foundation; stacks directly on PR #2.
This commit is contained in:
Connor Byrne
2026-05-08 21:34:38 -07:00
parent c614243e36
commit 2ec4fec8c2
7 changed files with 300 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
# Description: Publish @comfyorg/extension-api to npm with provenance attestation.
#
# Triggered by a tag push matching 'extension-api-v*' (e.g. extension-api-v0.1.0).
# Also supports workflow_dispatch for a manual dry-run (set dry_run: true).
#
# Prerequisites (one-time human setup):
# - NPM_TOKEN secret must be set in the repo/org settings with publish
# access to the @comfyorg scope on npmjs.com.
# - The @comfyorg npm scope already exists (used by @comfyorg/comfyui-frontend).
#
# PKG4.D4 (MIG1 / Phase A — surface-only shim)
name: 'Extension API: Publish'
on:
push:
tags:
- 'extension-api-v*'
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run — build and verify without publishing'
required: false
default: 'true'
type: boolean
permissions:
contents: write # needed to create GitHub Release
id-token: write # needed for npm provenance via OIDC
jobs:
publish:
name: Publish @comfyorg/extension-api
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # full history for release notes
- name: Setup frontend
uses: ./.github/actions/setup-frontend
- name: Setup npm registry
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org/'
- name: Build package
run: pnpm --filter @comfyorg/extension-api build
- name: Typecheck package
run: pnpm --filter @comfyorg/extension-api typecheck
- name: Verify package version matches tag
if: github.event_name == 'push'
run: |
TAG="${GITHUB_REF_NAME}" # e.g. extension-api-v0.1.0
PKG_VERSION=$(node -p "require('./packages/extension-api/package.json').version")
TAG_VERSION="${TAG#extension-api-v}" # strip prefix → 0.1.0
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
echo "::error::Tag '$TAG' implies version '$TAG_VERSION' but packages/extension-api/package.json has '$PKG_VERSION'. Update the package.json before tagging."
exit 1
fi
echo "Version check passed: $PKG_VERSION"
- name: Publish to npm (with provenance)
if: github.event_name == 'push' || inputs.dry_run == 'false'
run: |
cd packages/extension-api
npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Dry-run report
if: inputs.dry_run == 'true'
run: |
echo "=== DRY RUN — would publish ==="
cd packages/extension-api
npm pack --dry-run
echo "=== End dry run ==="
- name: Create GitHub Release
if: github.event_name == 'push'
uses: actions/github-script@v7
with:
script: |
const tag = context.ref.replace('refs/tags/', '')
const { data: release } = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tag,
name: tag,
generate_release_notes: true,
draft: false,
prerelease: context.ref.includes('-alpha') || context.ref.includes('-beta') || context.ref.includes('-rc')
})
console.log(`Release created: ${release.html_url}`)

View File

@@ -0,0 +1,65 @@
# Description: Typecheck and build the @comfyorg/extension-api package.
# Runs on PRs and pushes touching the public type surface, the core .v2.ts
# implementations, or the package scaffold — so regressions in the published
# contract are caught before merge.
#
# PKG4.D3 (MIG1 / Phase A — surface-only shim)
name: 'Extension API: Typecheck'
on:
push:
branches: [main, master, dev*, core/*, extension-v2*]
paths:
- 'src/extension-api/**'
- 'src/extensions/core/*.v2.ts'
- 'src/services/extension-api-service.ts'
- 'packages/extension-api/**'
- '.github/workflows/extension-api-*.yml'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
pull_request:
branches-ignore: [wip/*, draft/*, temp/*]
paths:
- 'src/extension-api/**'
- 'src/extensions/core/*.v2.ts'
- 'src/services/extension-api-service.ts'
- 'packages/extension-api/**'
- '.github/workflows/extension-api-*.yml'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
merge_group:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
typecheck:
name: Build + typecheck @comfyorg/extension-api
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Setup frontend
uses: ./.github/actions/setup-frontend
- name: Build package (emit declarations)
run: pnpm --filter @comfyorg/extension-api build
- name: Typecheck package
run: pnpm --filter @comfyorg/extension-api typecheck
- name: Smoke-test consumer (tsc --noEmit on minimal extension)
# Verifies the published types are consumable from an external module
# that imports from '@comfyorg/extension-api'. Uses a minimal fixture
# checked in to packages/extension-api/test/smoke/.
run: |
cd packages/extension-api
if [ -d test/smoke ]; then
pnpm exec tsc --noEmit --project test/smoke/tsconfig.json
else
echo "No smoke test found — skipping (add packages/extension-api/test/smoke/ to enable)"
fi

View File

@@ -0,0 +1,9 @@
src/
scripts/
tsconfig*.json
typedoc.json
docs-build/
*.test.ts
*.spec.ts
__tests__/
node_modules/

View File

@@ -0,0 +1,78 @@
/**
* @comfyorg/extension-api — Public Extension API for ComfyUI
*
* This is the package entry point compiled to `build/index.js` + `build/index.d.ts`.
* It re-exports the stable public contract from `src/extension-api/` in the main app.
*
* All types and functions exported here are part of the semver-stable surface.
* Do not add internal implementation details to this barrel.
*/
// Re-export everything from the canonical source in the main app tree.
// The tsconfig.json paths alias @/* → ../../src/* so these resolve correctly.
export type {
ExtensionOptions,
NodeExtensionOptions,
WidgetExtensionOptions
} from '@/extension-api/lifecycle'
export {
defineExtension,
defineNodeExtension,
defineWidgetExtension,
onNodeMounted,
onNodeRemoved
} from '@/extension-api/lifecycle'
export type {
NodeHandle,
NodeEntityId,
SlotEntityId,
SlotInfo,
SlotDirection,
NodeMode,
Point,
Size,
NodeExecutedEvent,
NodeConnectedEvent,
NodeDisconnectedEvent,
NodePositionChangedEvent,
NodeSizeChangedEvent,
NodeModeChangedEvent,
NodeBeforeSerializeEvent
} from '@/extension-api/node'
export type {
WidgetHandle,
WidgetEntityId,
WidgetValue,
WidgetOptions,
WidgetValueChangeEvent,
WidgetOptionChangeEvent,
WidgetPropertyChangeEvent,
WidgetBeforeSerializeEvent,
WidgetBeforeQueueEvent
} from '@/extension-api/widget'
export type { Handler, AsyncHandler, Unsubscribe } from '@/extension-api/events'
export type {
SidebarTabExtension,
BottomPanelExtension,
VueExtension,
CustomExtension,
ToastMessageOptions,
ToastManager,
ExtensionManager,
CommandManager
} from '@/extension-api/shell'
export type { NodeLocatorId, NodeExecutionId } from '@/extension-api/identifiers'
export {
isNodeLocatorId,
isNodeExecutionId,
parseNodeLocatorId,
createNodeLocatorId,
parseNodeExecutionId,
createNodeExecutionId
} from '@/extension-api/identifiers'

View File

@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**", "scripts/**"]
}

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"outDir": "build",
"rootDir": "src",
"paths": {
"@/*": ["../../src/*"]
}
},
"include": ["src/**/*.ts"],
"exclude": ["**/*.test.ts", "**/*.spec.ts", "scripts/**"]
}

28
scripts/generate-docs.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# PKG5.D6 — Generate TypeDoc → Mintlify MDX for @comfyorg/extension-api
#
# Output: packages/extension-api/docs-build/mintlify/*.mdx
# packages/extension-api/docs-build/mintlify/nav-snippet.json
#
# Prerequisites: pnpm install must have been run (typedoc, tsx)
# Usage: ./scripts/generate-docs.sh [--watch]
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PKG_DIR="$REPO_ROOT/packages/extension-api"
if [ ! -f "$PKG_DIR/package.json" ]; then
echo "ERROR: $PKG_DIR/package.json not found — run from repo root or ensure packages/extension-api exists." >&2
exit 1
fi
if [ "${1:-}" = "--watch" ]; then
echo "Starting docs watch mode..."
pnpm --filter @comfyorg/extension-api docs:watch
else
echo "Generating extension API docs..."
pnpm --filter @comfyorg/extension-api docs:build
echo ""
echo "Done. MDX files written to: $PKG_DIR/docs-build/mintlify/"
echo "Copy to Comfy-Org/docs: cp -r $PKG_DIR/docs-build/mintlify/* <docs-repo>/extensions/api/"
fi