From 12c4b8853b9557f1fae283d7f620795e3b16caab Mon Sep 17 00:00:00 2001 From: jackwener Date: Wed, 18 Mar 2026 15:19:23 +0800 Subject: [PATCH] feat(pipeline): extract STEP_HANDLERS into dynamic PipelineRegistry --- src/pipeline/executor.ts | 30 ++------------------ src/pipeline/registry.ts | 60 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 28 deletions(-) create mode 100644 src/pipeline/registry.ts diff --git a/src/pipeline/executor.ts b/src/pipeline/executor.ts index 0865bec..d00cf59 100644 --- a/src/pipeline/executor.ts +++ b/src/pipeline/executor.ts @@ -4,11 +4,7 @@ import chalk from 'chalk'; import type { IPage } from '../types.js'; -import { stepNavigate, stepClick, stepType, stepWait, stepPress, stepSnapshot, stepEvaluate } from './steps/browser.js'; -import { stepFetch } from './steps/fetch.js'; -import { stepSelect, stepMap, stepFilter, stepSort, stepLimit } from './steps/transform.js'; -import { stepIntercept } from './steps/intercept.js'; -import { stepTap } from './steps/tap.js'; +import { getStep, type StepHandler } from './registry.js'; import { log } from '../logger.js'; export interface PipelineContext { @@ -16,28 +12,6 @@ export interface PipelineContext { debug?: boolean; } -/** Step handler: all steps conform to (page, params, data, args) => Promise */ -type StepHandler = (page: IPage | null, params: any, data: any, args: Record) => Promise; - -/** Registry of all available step handlers */ -const STEP_HANDLERS: Record = { - navigate: stepNavigate, - fetch: stepFetch, - select: stepSelect, - evaluate: stepEvaluate, - snapshot: stepSnapshot, - click: stepClick, - type: stepType, - wait: stepWait, - press: stepPress, - map: stepMap, - filter: stepFilter, - sort: stepSort, - limit: stepLimit, - intercept: stepIntercept, - tap: stepTap, -}; - export async function executePipeline( page: IPage | null, pipeline: any[], @@ -54,7 +28,7 @@ export async function executePipeline( for (const [op, params] of Object.entries(step)) { if (debug) debugStepStart(i + 1, total, op, params); - const handler = STEP_HANDLERS[op]; + const handler = getStep(op); if (handler) { data = await handler(page, params, data, args); } else { diff --git a/src/pipeline/registry.ts b/src/pipeline/registry.ts new file mode 100644 index 0000000..74d8794 --- /dev/null +++ b/src/pipeline/registry.ts @@ -0,0 +1,60 @@ +/** + * Dynamic registry for pipeline steps. + * Allows core and third-party plugins to register custom YAML operations. + */ + +import type { IPage } from '../types.js'; + +// Import core steps +import { stepNavigate, stepClick, stepType, stepWait, stepPress, stepSnapshot, stepEvaluate } from './steps/browser.js'; +import { stepFetch } from './steps/fetch.js'; +import { stepSelect, stepMap, stepFilter, stepSort, stepLimit } from './steps/transform.js'; +import { stepIntercept } from './steps/intercept.js'; +import { stepTap } from './steps/tap.js'; + +/** + * Step handler: all pipeline steps conform to this generic interface. + * TData is the type of the `data` state flowing into the step. + * TResult is the expected return type. + */ +export type StepHandler = ( + page: IPage | null, + params: any, + data: TData, + args: Record +) => Promise; + +const _stepRegistry = new Map(); + +/** + * Get a registered step handler by name. + */ +export function getStep(name: string): StepHandler | undefined { + return _stepRegistry.get(name); +} + +/** + * Register a new custom step handler for the YAML pipeline. + */ +export function registerStep(name: string, handler: StepHandler): void { + _stepRegistry.set(name, handler); +} + +// ------------------------------------------------------------- +// Auto-Register Core Steps +// ------------------------------------------------------------- +registerStep('navigate', stepNavigate); +registerStep('fetch', stepFetch); +registerStep('select', stepSelect); +registerStep('evaluate', stepEvaluate); +registerStep('snapshot', stepSnapshot); +registerStep('click', stepClick); +registerStep('type', stepType); +registerStep('wait', stepWait); +registerStep('press', stepPress); +registerStep('map', stepMap); +registerStep('filter', stepFilter); +registerStep('sort', stepSort); +registerStep('limit', stepLimit); +registerStep('intercept', stepIntercept); +registerStep('tap', stepTap);