Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
  • Loading branch information
Connor Byrne committed May 9, 2026
commit eee72ef273f5d7a32fe961c1c362be83727a675c
97 changes: 97 additions & 0 deletions .github/workflows/extension-api-publish.yml
Original file line number Diff line number Diff line change
@@ -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

Check failure on line 44 in .github/workflows/extension-api-publish.yml

View workflow job for this annotation

GitHub Actions / validate-pins

pinact error

uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
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

Check failure on line 84 in .github/workflows/extension-api-publish.yml

View workflow job for this annotation

GitHub Actions / validate-pins

pinact error

uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
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}`)
65 changes: 65 additions & 0 deletions .github/workflows/extension-api-typecheck.yml
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions packages/extension-api/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
src/
scripts/
tsconfig*.json
typedoc.json
docs-build/
*.test.ts
*.spec.ts
__tests__/
node_modules/
78 changes: 78 additions & 0 deletions packages/extension-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -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'
4 changes: 4 additions & 0 deletions packages/extension-api/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**", "scripts/**"]
}
19 changes: 19 additions & 0 deletions packages/extension-api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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/**"]
}
Loading
Loading