From 5b05f2b793372645cf4eb18e5e97c6e41365fd20 Mon Sep 17 00:00:00 2001 From: Connor Byrne Date: Tue, 12 May 2026 12:13:34 -0700 Subject: [PATCH] fix(ext-api): add knip entry + @publicAPI tags for v2 surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit knip flagged the new src/extension-api/* files and exports as unused because nothing internal consumes them — by design. They are the public API surface published by PKG2 (#12143). Changes: - knip.config.ts: add src/extension-api/index.ts as entry point (per AGENTS.md, this barrel is the explicit exception to the no-barrel-files-in-src rule because it IS the package entry). - knip.config.ts: ignore src/types/extensionV2.ts (deprecated stub, removed once PKG2 ships). - knip.config.ts: register `-publicAPI` tag. - Tag externally-consumed exports with @publicAPI: - lifecycle.ts: defineNodeExtension/Extension/WidgetExtension declares + back-compat type re-exports - extension-api-service.ts: _setDispatchImplForTesting, NodeInstanceScope - worldInstance.ts: World Verifies the full lint-format CI matrix locally: pnpm lint ✅ pnpm stylelint (unaffected, CSS-only) pnpm format:check ✅ pnpm knip ✅ --- knip.config.ts | 16 ++++++++++++++-- src/extension-api/lifecycle.ts | 10 ++++++++++ src/services/extension-api-service.ts | 9 ++++++++- src/world/worldInstance.ts | 6 ++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/knip.config.ts b/knip.config.ts index b204587958..7b4e05180f 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -9,6 +9,10 @@ const config: KnipConfig = { 'src/assets/css/style.css', 'src/scripts/ui/menu/index.ts', 'src/types/index.ts', + // Public extension API surface — published package entry point. + // Per AGENTS.md, this barrel is the explicit exception to the + // no-barrel-files-in-src rule because it IS the package entry. + 'src/extension-api/index.ts', 'src/storybook/mocks/**/*.ts' ], project: ['**/*.{js,ts,vue}', '*.{js,ts,mts}', '!.claude/**'] @@ -60,7 +64,11 @@ const config: KnipConfig = { // Agent review check config, not part of the build '.agents/checks/eslint.strict.config.js', // Devtools extensions, included dynamically - 'tools/devtools/web/**' + 'tools/devtools/web/**', + // Deprecated stub re-exporting from `@/extension-api`. Will be removed + // once PKG2 (`@comfyorg/extension-api`) ships and downstream imports + // migrate to the package path. + 'src/types/extensionV2.ts' ], vite: { config: ['vite?(.*).config.mts'] @@ -79,7 +87,11 @@ const config: KnipConfig = { tags: [ '-knipIgnoreUnusedButUsedByCustomNodes', '-knipIgnoreUnusedButUsedByVueNodesBranch', - '-knipIgnoreUsedByStackedPR' + '-knipIgnoreUsedByStackedPR', + // Public API surface consumed externally by extension authors and the + // TypeDoc docgen pipeline (PKG2). Mark exports with @publicAPI when they + // are part of `@comfyorg/extension-api` but not internally referenced. + '-publicAPI' ] } diff --git a/src/extension-api/lifecycle.ts b/src/extension-api/lifecycle.ts index aca2ead7b8..b36cdee1e4 100644 --- a/src/extension-api/lifecycle.ts +++ b/src/extension-api/lifecycle.ts @@ -26,6 +26,13 @@ // without forming a circular import. This module re-exports them so the // existing public path `@/extension-api/lifecycle` keeps working. +/** + * @publicAPI + * Back-compat re-exports of the extension option contracts. Prefer importing + * from `@comfyorg/extension-api` (or `@/extension-api`); the + * `@/extension-api/lifecycle` path is preserved for downstream code that + * imported these types from the original module. + */ export type { NodeExtensionOptions, ExtensionOptions, @@ -52,6 +59,7 @@ import type { * extension registration order with a lexicographic tie-break on `name` (D10b). * * @stability stable + * @publicAPI * @example * ```ts * import { defineNodeExtension } from '@comfyorg/extension-api' @@ -82,6 +90,7 @@ export declare function defineNodeExtension( * `init`, `setup`, sidebar tabs, commands, and other app-level concerns. * * @stability stable + * @publicAPI * @example * ```ts * import { defineExtension } from '@comfyorg/extension-api' @@ -103,6 +112,7 @@ export declare function defineExtension( * a new widget kind. * * @stability experimental + * @publicAPI */ export declare function defineWidgetExtension( options: WidgetExtensionOptions diff --git a/src/services/extension-api-service.ts b/src/services/extension-api-service.ts index e3f45cc7ca..2d64aa9801 100644 --- a/src/services/extension-api-service.ts +++ b/src/services/extension-api-service.ts @@ -132,8 +132,10 @@ let _dispatchImpl: ((cmd: Record) => unknown) | null = null /** * @internal + * @publicAPI * Test-only: override dispatch implementation. Pass null to restore the stub. - * DO NOT use in extensions — this is an internal testing hook. + * DO NOT use in extensions — this is an internal testing hook used by the + * test framework PR (#12145) and Phase B ECS dispatch tests. */ export function _setDispatchImplForTesting( impl: ((cmd: Record) => unknown) | null @@ -159,6 +161,11 @@ function dispatch(_command: Record): unknown { // on graph deletion (world entitiesWith diff triggers unmount). // See decisions/D3.5, D10, D12. +/** + * @publicAPI + * Per-(extension, node) scope record. Exposed so the test framework PR + * (#12145) and Phase B dispatch can introspect scope binding. + */ export interface NodeInstanceScope { /** Branded entity ID this scope is bound to. */ readonly nodeEntityId: NodeEntityId diff --git a/src/world/worldInstance.ts b/src/world/worldInstance.ts index dc6c566f62..94a2b30bfe 100644 --- a/src/world/worldInstance.ts +++ b/src/world/worldInstance.ts @@ -4,6 +4,12 @@ import type { ComponentKey } from './componentKey' import type { EntityId } from './entityIds' +/** + * @publicAPI + * ECS World contract. Phase A surface; replaced by Alex's PR #11939 + * (ECS substrate slice 2). Consumed externally by the test framework PR + * (#12145) and Phase B dispatch. + */ export interface World { getComponent( entityId: TEntity,