@routecraft/routecraft 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +65 -0
- package/dist/index.cjs +9 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1454 -0
- package/dist/index.d.ts +1454 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error.ts","../src/logger.ts","../src/queue.ts","../src/route.ts","../src/context.ts","../src/exchange.ts","../src/operations/process.ts","../src/operations/to.ts","../src/operations/split.ts","../src/operations/aggregate.ts","../src/operations/transform.ts","../src/operations/tap.ts","../src/operations/filter.ts","../src/operations/enrich.ts","../src/consumers/simple.ts","../src/consumers/batch.ts","../src/operations/validate.ts","../src/operations/header.ts","../src/builder.ts","../src/adapters/simple.ts","../src/adapters/noop.ts","../src/adapters/log.ts","../src/adapters/direct.ts","../src/adapters/timer.ts","../src/adapters/fetch.ts","../src/dsl.ts"],"names":["DOCS_BASE","RC","RouteCraftError","rc","meta","cause","result","error","overrides","base","parsed","isDev","hasPinoPretty","pino","label","createLogger","context","CraftContext","DefaultRoute","DefaultExchange","logger","InMemoryProcessingQueue","message","handler","q","definition","abortController","event","headers","exchange","queue","lastProcessedExchange","steps","step","remainingSteps","updatedExchange","err","operation","config","key","value","h","set","details","payload","definitions","allIDs","def","hasInternalDuplicates","id","idx","conflictWithExistingRoutes","r","duplicateId","controller","route","results","OperationType","HeadersKeys","options","ProcessStep","adapter","newExchange","ToStep","SplitStep","splitBodies","groupId","splitHierarchy","body","postProcessedExchange","AggregateStep","aggregatedExchange","currentGroupId","aggregationGroup","i","item","remainingHierarchy","TransformStep","newBody","TapStep","exchangeCopy","FilterStep","defaultEnrichAggregator","original","enrichmentData","originalBody","EnrichStep","aggregator","SimpleConsumer","channel","BatchConsumer","messages","batch","resolvers","timer","flushBatch","currentBatch","currentResolvers","merged","finalExchange","resolve","reject","promise","ValidateStep","schema","HeaderStep","setterOrValue","ContextBuilder","eventName","routes","RouteBuilder","ctx","handlers","mapped","source","consumer","processor","destination","splitter","defaultSplitter","transformer","valueOrFn","fieldMappings","targetField","mapperFn","tap","filter","enricher","SimpleAdapter","producer","NoopAdapter","LogAdapter","formatter","DirectAdapter","_DirectAdapter","rawEndpoint","store","mergedOptions","MyChannelType","InMemoryDirectChannel","defaultExchange","_endpoint","_context","TimerAdapter","intervalMs","delayMs","repeatCount","fixedRate","exactTime","jitterMs","baseTime","now","hour","minute","second","scheduled","count","scheduledTime","waitTime","jitter","firedTime","nextScheduledTime","FetchAdapter","method","url","query","resolvedBody","throwOnHttpError","timeoutMs","finalUrl","timeout","res","text","headersRecord","bodyText","parsedBody","val","u","k","v","craft","simple","noop","log","direct","endpoint","fetch"],"mappings":"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","file":"index.cjs","sourcesContent":["export type RCCode =\n | \"RC1001\"\n | \"RC1002\"\n | \"RC2001\"\n | \"RC2002\"\n | \"RC3001\"\n | \"RC3002\"\n | \"RC5001\"\n | \"RC5002\"\n | \"RC5003\"\n | \"RC5004\"\n | \"RC5005\"\n | \"RC5006\"\n | \"RC5007\"\n | \"RC5008\"\n | \"RC5009\"\n | \"RC9901\";\n\nexport type RCMeta = {\n category: \"Definition\" | \"DSL\" | \"Lifecycle\" | \"Adapter\" | \"Runtime\";\n message: string;\n suggestion?: string;\n docs: string;\n};\n\nexport const DOCS_BASE = \"https://routecraft.dev/docs/reference/errors\";\n\nexport const RC: Record<RCCode, RCMeta> = {\n RC1001: {\n category: \"Definition\",\n message: \"Route definition failed validation\",\n suggestion: \"Ensure a source is defined: start with from(adapter)\",\n docs: `${DOCS_BASE}#rc-1001`,\n },\n RC1002: {\n category: \"Definition\",\n message: \"Duplicate route id\",\n suggestion: \"Ensure each route id is unique or set routeOptions.id\",\n docs: `${DOCS_BASE}#rc-1002`,\n },\n RC2001: {\n category: \"DSL\",\n message: \"Invalid operation type\",\n suggestion: \"Use a supported operator and verify the step name\",\n docs: `${DOCS_BASE}#rc-2001`,\n },\n RC2002: {\n category: \"DSL\",\n message: \"Missing from step\",\n suggestion: \"Start the route with from and a valid source adapter\",\n docs: `${DOCS_BASE}#rc-2002`,\n },\n RC3001: {\n category: \"Lifecycle\",\n message: \"Route failed to start\",\n suggestion: \"Ensure the route is not aborted and adapters are configured\",\n docs: `${DOCS_BASE}#rc-3001`,\n },\n RC3002: {\n category: \"Lifecycle\",\n message: \"Context failed to start\",\n suggestion: \"Validate plugin exports and global configuration\",\n docs: `${DOCS_BASE}#rc-3002`,\n },\n RC5001: {\n category: \"Adapter\",\n message: \"Source adapter threw\",\n suggestion: \"Verify connectivity and adapter options\",\n docs: `${DOCS_BASE}#rc-5001`,\n },\n RC5002: {\n category: \"Adapter\",\n message: \"Processing step threw\",\n suggestion: \"Add guards to transforms and processors\",\n docs: `${DOCS_BASE}#rc-5002`,\n },\n RC5003: {\n category: \"Adapter\",\n message: \"Destination adapter threw\",\n suggestion: \"Verify destination connectivity and options\",\n docs: `${DOCS_BASE}#rc-5003`,\n },\n RC5004: {\n category: \"Adapter\",\n message: \"Split operation failed\",\n suggestion: \"Ensure the input is iterable and guarded\",\n docs: `${DOCS_BASE}#rc-5004`,\n },\n RC5005: {\n category: \"Adapter\",\n message: \"Aggregation operation failed\",\n suggestion: \"Validate partial shapes and defaults\",\n docs: `${DOCS_BASE}#rc-5005`,\n },\n RC5006: {\n category: \"Adapter\",\n message: \"Transform function threw\",\n suggestion: \"Narrow input types and add guards\",\n docs: `${DOCS_BASE}#rc-5006`,\n },\n RC5007: {\n category: \"Adapter\",\n message: \"Tap step threw\",\n suggestion: \"Keep tap side effects resilient\",\n docs: `${DOCS_BASE}#rc-5007`,\n },\n RC5008: {\n category: \"Adapter\",\n message: \"Filter predicate threw\",\n suggestion: \"Guard against missing properties and unexpected shapes\",\n docs: `${DOCS_BASE}#rc-5008`,\n },\n RC5009: {\n category: \"Adapter\",\n message: \"Validation failed\",\n suggestion: \"Adjust the schema or coerce input\",\n docs: `${DOCS_BASE}#rc-5009`,\n },\n RC9901: {\n category: \"Runtime\",\n message: \"Unknown error\",\n suggestion: \"Check logs and enable debug level\",\n docs: `${DOCS_BASE}#rc-9901`,\n },\n};\n\nexport class RouteCraftError extends Error {\n constructor(\n public readonly rc: RCCode,\n public readonly meta: RCMeta,\n cause?: unknown,\n ) {\n super(meta.message, { cause });\n this.name = \"RouteCraftError\";\n }\n\n override toString(): string {\n let result = `[${this.rc}] ${this.meta.message}`;\n if (this.meta.suggestion) {\n result += `\\nSuggestion, ${this.meta.suggestion}`;\n }\n result += `\\nDocs, ${this.meta.docs}`;\n if (this.cause instanceof Error) {\n result += `\\nCaused by: ${this.cause.message}`;\n if (this.cause.stack) {\n result += `\\nStack trace:\\n${this.cause.stack}`;\n }\n }\n return result;\n }\n\n static parse(cause: unknown): { message: string; error: Error } {\n return cause instanceof Error\n ? { message: cause.message, error: cause }\n : { message: String(cause), error: new Error(String(cause)) };\n }\n}\n\nexport function error(\n rc: RCCode,\n cause?: unknown,\n overrides?: Partial<Pick<RCMeta, \"message\" | \"suggestion\" | \"docs\">>,\n): RouteCraftError {\n const base = RC[rc];\n const meta: RCMeta = {\n ...base,\n ...(overrides || {}),\n docs: overrides?.docs ?? base.docs,\n };\n const parsed = cause ? RouteCraftError.parse(cause).error : undefined;\n return new RouteCraftError(rc, meta, parsed);\n}\n","import { pino, type Logger } from \"pino\";\nimport { type Route, DefaultRoute } from \"./route.ts\";\nimport { type Exchange, DefaultExchange, HeadersKeys } from \"./exchange.ts\";\nimport { CraftContext } from \"./context.ts\";\nexport type { Logger };\n\n/** Detect development environment for logger configuration */\nconst isDev = process.env[\"NODE_ENV\"] !== \"production\";\n\n/**\n * Check if pino-pretty is available (installed as a devDependency)\n */\nfunction hasPinoPretty(): boolean {\n try {\n // Try to resolve pino-pretty - if it's installed, this won't throw\n // We use a dynamic import check rather than actually importing it\n import.meta.resolve?.(\"pino-pretty\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Base logger configuration with reasonable defaults.\n * In development, uses pino-pretty for readable logs if available.\n * In production, uses standard JSON format for machine processing.\n */\nconst base = pino({\n level: process.env[\"LOG_LEVEL\"] || \"warn\", // Support dynamic log levels\n formatters: {\n level: (label) => ({ level: label.toUpperCase() }), // Ensure consistent casing\n },\n timestamp: () => `,\"time\":\"${new Date().toISOString()}\"`, // Use ISO timestamp format\n ...(isDev && hasPinoPretty()\n ? {\n transport: {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n ignore: \"pid,hostname\",\n translateTime: \"SYS:standard\",\n },\n },\n }\n : {}),\n});\n\n/**\n * Create a context-aware logger with appropriate metadata.\n *\n * This function creates a logger that includes relevant context information:\n * - For CraftContext: Includes contextId\n * - For Route: Includes contextId and routeId\n * - For Exchange: Includes contextId, routeId, exchangeId, and correlationId\n *\n * @param context The context to create a logger for\n * @returns A configured logger instance\n *\n * @example\n * ```typescript\n * // Create a logger for a context\n * const contextLogger = createLogger(myContext);\n * contextLogger.info('Context starting');\n *\n * // Create a logger for a route\n * const routeLogger = createLogger(myRoute);\n * routeLogger.debug('Processing route');\n *\n * // Create a logger for an exchange\n * const exchangeLogger = createLogger(exchange);\n * exchangeLogger.info('Processing data', { data: exchange.body });\n * ```\n */\nexport function createLogger(\n context?: CraftContext | Route | Exchange,\n): Logger {\n if (!context) {\n return base;\n }\n\n if (context instanceof CraftContext) {\n return base.child({\n contextId: context.contextId,\n });\n } else if (context instanceof DefaultRoute) {\n return base.child({\n contextId: context.context.contextId,\n routeId: context.definition.id,\n });\n } else if (context instanceof DefaultExchange) {\n return base.child({\n contextId: context.context.contextId,\n routeId: context.headers[HeadersKeys.ROUTE_ID],\n exchangeId: context.id,\n correlationId: context.headers[HeadersKeys.CORRELATION_ID],\n });\n } else {\n return base;\n }\n}\n\n/**\n * Default global logger instance.\n *\n * Use this for application-level logging when no specific context is available.\n * For context-specific logging, create a logger using createLogger().\n *\n * @example\n * ```typescript\n * // Log application-level messages\n * logger.info('Application starting');\n * logger.error(error, 'Unexpected error occurred');\n * ```\n */\nexport const logger = createLogger();\n","import { type ProcessingQueue } from \"./types.ts\";\nimport { type Exchange } from \"./exchange.ts\";\n// no-op\n\n/**\n * In-memory processing queue used internally by a route to pass\n * messages from the source to the consumer. It's intentionally\n * simpler than the public message channel used by ChannelAdapter.\n */\nexport class InMemoryProcessingQueue<T = unknown>\n implements ProcessingQueue<T>\n{\n private handler: ((message: T) => Promise<Exchange>) | undefined;\n private buffer: T[] = [];\n\n async enqueue(message: T): Promise<Exchange> {\n if (!this.handler) {\n this.buffer.push(message);\n // Resolve immediately when no handler; tests don't use return value here\n return Promise.resolve({} as Exchange);\n }\n return await this.handler(message);\n }\n\n setHandler(handler: (message: T) => Promise<Exchange>): Promise<void> | void {\n this.handler = handler;\n\n const q = this.buffer;\n if (q.length > 0) {\n const deliver = async () => {\n while (q.length > 0) {\n await handler(q.shift()!);\n }\n };\n void deliver();\n this.buffer = [];\n }\n return Promise.resolve();\n }\n\n clear(): Promise<void> {\n this.handler = undefined;\n this.buffer = [];\n return Promise.resolve();\n }\n}\n","import { type CraftContext } from \"./context.ts\";\nimport {\n type Exchange,\n HeadersKeys,\n OperationType,\n type ExchangeHeaders,\n DefaultExchange,\n} from \"./exchange.ts\";\nimport { error as rcError, RouteCraftError, RC } from \"./error.ts\";\nimport { createLogger, type Logger } from \"./logger.ts\";\nimport { type Source } from \"./operations/from.ts\";\nimport {\n type Adapter,\n type Step,\n type Consumer,\n type ConsumerType,\n type Message,\n type ProcessingQueue,\n} from \"./types.ts\";\nimport { InMemoryProcessingQueue } from \"./queue.ts\";\n\n/**\n * Defines the configuration for a route including its source, steps, and consumer.\n *\n * A route definition describes how data flows from a source through processing steps\n * to one or more destinations.\n *\n * @template T The type of data produced by the source\n */\nexport type RouteDefinition<T = unknown> = {\n /** Unique identifier for the route */\n readonly id: string;\n\n /** The source that provides data to the route */\n readonly source: Source<T>;\n\n /** Processing steps that transform, filter, or direct the data */\n readonly steps: Step<Adapter>[];\n\n /** Consumer configuration that determines how data is processed */\n readonly consumer: {\n /** The type of consumer to use */\n type: ConsumerType<Consumer>;\n\n /** Options for the consumer */\n options: unknown;\n };\n};\n\n/**\n * Represents a runnable route that processes data.\n *\n * Routes handle the flow of data from a source through processing steps\n * and can be started and stopped.\n */\nexport interface Route {\n /** The context this route belongs to */\n readonly context: CraftContext;\n\n /** The route's configuration */\n readonly definition: RouteDefinition;\n\n /** Signal that indicates when the route has been aborted */\n readonly signal: AbortSignal;\n\n /** Logger for this route */\n logger: Logger;\n\n /**\n * Start processing data on this route.\n * @returns A promise that resolves when the route has started\n */\n start(): Promise<void>;\n\n /**\n * Stop processing data on this route.\n */\n stop(): void;\n}\n\n/**\n * Default implementation of the Route interface.\n *\n * Handles the lifecycle of a route, managing the message flow from\n * the source through the defined steps.\n */\nexport class DefaultRoute implements Route {\n /** Controls aborting the route's operations */\n private abortController: AbortController;\n\n /** Logger for this route */\n public readonly logger: Logger;\n\n /** Internal queue for passing messages between the source and consumer */\n private messageChannel: ProcessingQueue<Message>;\n\n /** Processes messages from the message channel */\n private consumer: Consumer;\n\n /**\n * Create a new route instance.\n *\n * @param context The context this route belongs to\n * @param definition The route's configuration\n * @param abortController Optional controller for aborting the route\n */\n constructor(\n public readonly context: CraftContext,\n public readonly definition: RouteDefinition,\n abortController?: AbortController,\n ) {\n this.assertNotAborted();\n this.abortController = abortController ?? new AbortController();\n this.logger = createLogger(this);\n this.messageChannel = new InMemoryProcessingQueue<Message>();\n this.consumer = new this.definition.consumer.type(\n this.context,\n this.definition,\n this.messageChannel,\n this.definition.consumer.options,\n );\n\n // Emit routeStopping/routeStopped when the controller is aborted externally\n this.abortController.signal.addEventListener(\"abort\", (event) => {\n try {\n this.context.emit(\"routeStopping\", {\n route: this,\n reason: (event as unknown as { reason?: unknown })?.reason,\n });\n } finally {\n this.context.emit(\"routeStopped\", { route: this });\n }\n });\n }\n\n /**\n * Get the abort signal for this route.\n */\n get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Create a new exchange object from a message and optional headers.\n *\n * @param message The message data\n * @param headers Optional headers to include\n * @returns A new Exchange object\n * @private\n */\n private buildExchange(message: unknown, headers?: ExchangeHeaders): Exchange {\n return new DefaultExchange(this.context, {\n body: message,\n headers: {\n ...headers,\n [HeadersKeys.CORRELATION_ID]: crypto.randomUUID(),\n [HeadersKeys.ROUTE_ID]: this.definition.id,\n [HeadersKeys.OPERATION]: OperationType.FROM,\n },\n });\n }\n\n /**\n * Start processing data on this route.\n *\n * This method:\n * 1. Registers the consumer to process messages\n * 2. Subscribes to the source to receive data\n *\n * @returns A promise that resolves when the route has started\n * @throws {RouteCraftError} If the route has been aborted\n */\n async start(): Promise<void> {\n this.assertNotAborted();\n this.logger.info(`Starting route \"${this.definition.id}\"`);\n\n // Start consuming messages from the internal processing queue\n this.consumer.register((message, headers) => {\n return this.handler(this.buildExchange(message, headers));\n });\n\n // Signal that the route has started successfully (consumer registered)\n this.context.emit(\"routeStarted\", { route: this });\n\n // Subscribe to the source and enqueue messages to the internal processing queue\n return this.definition.source.subscribe(\n this.context,\n (message, headers) => {\n return this.messageChannel.enqueue({\n message,\n headers: headers ?? {},\n });\n },\n this.abortController,\n );\n }\n\n /**\n * Stop processing data on this route.\n *\n * This method:\n * 1. Unsubscribes from the internal processing queue\n * 2. Aborts the route's controller\n */\n stop(): void {\n this.logger.info(`Stopping route \"${this.definition.id}\"`);\n this.messageChannel.clear();\n this.abortController.abort(\"Route stop() called\");\n }\n\n /**\n * Process an exchange through the route's steps.\n *\n * This is the main processing logic that:\n * 1. Takes an initial exchange from the source\n * 2. Processes it through each step in sequence\n * 3. Handles errors that occur during processing\n *\n * @param exchange The initial exchange to process\n * @returns A promise that resolves when processing is complete\n * @private\n */\n private async handler(exchange: Exchange): Promise<Exchange> {\n exchange.logger.debug(\n `Processing initial exchange ${exchange.id} on route \"${this.definition.id}\"`,\n );\n\n // Use a queue to process the steps in FIFO order.\n const queue: { exchange: Exchange; steps: Step<Adapter>[] }[] = [\n { exchange: exchange, steps: [...this.definition.steps] },\n ];\n\n let lastProcessedExchange: Exchange = exchange;\n\n while (queue.length > 0) {\n const { exchange, steps } = queue.shift()!;\n if (steps.length === 0) {\n // No more steps; this is a completed exchange for this branch.\n lastProcessedExchange = exchange;\n continue;\n }\n\n const [step, ...remainingSteps] = steps;\n\n // Update operation type in headers for the current step\n const updatedExchange: Exchange = {\n ...exchange,\n headers: {\n ...exchange.headers,\n [HeadersKeys.OPERATION]: step.operation,\n },\n };\n\n updatedExchange.logger.debug(\n `Processing step ${step.operation} on exchange ${updatedExchange.id}`,\n );\n\n try {\n await step.execute(updatedExchange, remainingSteps, queue);\n } catch (error) {\n const err = this.processError(step.operation, error);\n updatedExchange.logger.warn(\n err,\n `Step ${step.operation} failed for exchange ${updatedExchange.id}`,\n );\n this.context.emit(\"error\", {\n error: err,\n route: this,\n exchange: updatedExchange,\n });\n }\n }\n return lastProcessedExchange;\n }\n\n /**\n * Check if the route has been aborted, and throw an error if it has.\n *\n * @throws {RouteCraftError} If the route has been aborted\n * @private\n */\n private assertNotAborted(): void {\n if (this.abortController?.signal.aborted) {\n throw rcError(\"RC3001\", undefined, {\n message: `${RC[\"RC3001\"].message}: ${this.definition.id}`,\n });\n }\n }\n\n /**\n * Create a RouteCraftError from an operation error.\n *\n * @param operation The operation that caused the error\n * @param code The error code\n * @param error The original error\n * @returns A formatted RouteCraftError\n * @private\n */\n private processError(\n operation: OperationType,\n error: unknown,\n ): RouteCraftError {\n const rc = \"RC5002\" as const; // Processing step threw\n return rcError(rc, error, {\n message: `${RC[rc].message}: op=${operation} route=${this.definition.id}`,\n });\n }\n\n /**\n * Get the documentation URL for operation error codes.\n *\n * @param code The error code\n * @returns The documentation URL\n * @private\n */\n // Docs URL is sourced from the RC registry; no per-operation mapping required.\n}\n","import { DefaultRoute, type Route, type RouteDefinition } from \"./route.ts\";\nimport { error as rcError, RC } from \"./error.ts\";\nimport { createLogger, type Logger } from \"./logger.ts\";\nimport {\n type EventHandler,\n type EventName,\n type EventPayload,\n} from \"./types.ts\";\n\n/**\n * Base store registry that can be extended by adapters\n *\n * @example\n * ```typescript\n * // Extend the store registry with channel adapter types\n * declare module \"@routecraft/routecraft\" {\n * interface StoreRegistry {\n * \"routecraft.adapter.channel.store\": Map<string, import(\"./adapters/channel.ts\").MessageChannel>;\n * \"routecraft.adapter.channel.config\" Partial<ChannelAdapterOptions>;\n * }\n * }\n * ```\n */\nexport interface StoreRegistry {\n [key: `${string}.${string}.${string}`]: unknown;\n}\n\n/**\n * Options with merged configuration support.\n * This type is used for adapters that support both direct options and\n * options that can be merged with context configuration.\n */\nexport type MergedOptions<T> = {\n /** Direct options for configuration */\n options: Partial<T>;\n\n /**\n * Function to merge options with context configuration\n * @param context The CraftContext instance\n * @returns Merged options\n */\n mergedOptions(context: CraftContext): T;\n};\n\n/**\n * Configuration options for creating a CraftContext.\n */\nexport type CraftConfig = {\n /** Initial values for the context store */\n store?: Map<keyof StoreRegistry, StoreRegistry[keyof StoreRegistry]>;\n /** Event handlers to register on context creation */\n on?: Partial<\n Record<EventName, EventHandler<EventName> | EventHandler<EventName>[]>\n >;\n};\n\n/**\n * The main context for running and managing routes.\n *\n * CraftContext is the central runtime environment that:\n * - Manages the lifecycle of routes\n * - Provides a storage system for adapters\n * - Handles startup and shutdown of the application\n *\n * @example\n * ```typescript\n * // Create a context with routes and event handlers\n * const context = new CraftContext({\n * on: {\n * contextStarting: async () => {\n * console.log('Starting application');\n * },\n * contextStopping: async () => {\n * console.log('Shutting down application');\n * }\n * }\n * });\n *\n * // Register routes\n * context.registerRoutes(myRoute1, myRoute2);\n *\n * // Start processing routes\n * await context.start();\n *\n * // Later, stop all routes\n * await context.stop();\n * ```\n */\nexport class CraftContext {\n /** Unique identifier for this context instance */\n public readonly contextId: string = crypto.randomUUID();\n\n /** Routes registered with this context */\n private routes: Route[] = [];\n\n /** Abort controllers for each route */\n private controllers: Map<string, AbortController> = new Map();\n\n /** Storage for adapter configuration and state */\n private store = new Map<\n keyof StoreRegistry,\n StoreRegistry[keyof StoreRegistry]\n >();\n\n /** Logger for this context */\n public readonly logger: Logger;\n\n /** Registered event handlers */\n private readonly handlers: Map<EventName, Set<EventHandler<EventName>>> =\n new Map();\n\n /**\n * Create a new CraftContext instance.\n *\n * @param config Optional configuration for the context\n */\n constructor(config?: CraftConfig) {\n this.logger = createLogger(this);\n if (config) {\n // Initialize store from config\n if (config.store) {\n for (const [key, value] of config.store.entries()) {\n this.store.set(key, value);\n }\n }\n\n // Register event handlers from config\n if (config.on) {\n for (const [event, handler] of Object.entries(config.on)) {\n if (Array.isArray(handler)) {\n handler.forEach((h) => this.on(event as EventName, h));\n } else if (handler) {\n this.on(event as EventName, handler);\n }\n }\n }\n }\n }\n\n /**\n * Subscribe to lifecycle and system events.\n *\n * Handlers receive payloads with shape { ts, context, details }.\n */\n on<K extends EventName>(event: K, handler: EventHandler<K>): () => void {\n const set = this.handlers.get(event) ?? new Set();\n // Force type casting at storage time; retrieval re-casts on emit\n set.add(handler as unknown as EventHandler<EventName>);\n this.handlers.set(event, set);\n return () => {\n set.delete(handler as unknown as EventHandler<EventName>);\n };\n }\n\n /**\n * Emit an event to registered handlers. Public for internal use by routes/adapters.\n */\n emit<K extends EventName>(\n event: K,\n details: EventPayload<K>[\"details\"],\n ): void {\n const payload: EventPayload<K> = {\n ts: new Date().toISOString(),\n context: this,\n details,\n } as EventPayload<K>;\n const set = this.handlers.get(event);\n if (!set || set.size === 0) return;\n for (const handler of Array.from(set)) {\n try {\n void (handler as unknown as EventHandler<K>)(payload);\n } catch (err) {\n // Swallow handler errors but log them and emit system error\n this.logger.warn(err as Error, \"Event handler threw\");\n if (event !== \"error\") {\n this.emit(\"error\", { error: err });\n }\n }\n }\n }\n\n // onStartup/onShutdown removed in favor of event listeners\n\n /**\n * Register routes with this context.\n *\n * @param definitions Route definitions to register\n * @throws {RouteCraftError} If there are duplicate route IDs or invalid route definitions\n *\n * @example\n * ```typescript\n * // Register a single route\n * context.registerRoutes(myRoute);\n *\n * // Register multiple routes\n * context.registerRoutes(route1, route2, route3);\n * ```\n */\n registerRoutes(...definitions: RouteDefinition[]): void {\n // 1) Gather all IDs from the new route definitions\n const allIDs = definitions.map((def) => def.id);\n\n // 2) Check for duplicates within the new route definitions\n const hasInternalDuplicates = allIDs.some(\n (id, idx) => allIDs.indexOf(id) !== idx,\n );\n\n // 3) Check for duplicates against existing routes\n const conflictWithExistingRoutes = definitions.some((def) =>\n this.routes.some((r) => r.definition.id === def.id),\n );\n\n // 4) If either case has duplicates, throw the error\n if (hasInternalDuplicates || conflictWithExistingRoutes) {\n // Identify any one duplicate ID\n const duplicateId =\n allIDs.find((id, idx) => allIDs.indexOf(id) !== idx) ??\n definitions.find((def) =>\n this.routes.some((r) => r.definition.id === def.id),\n )?.id ??\n \"unknown\";\n\n throw rcError(\"RC1002\", undefined, {\n message: `${RC[\"RC1002\"].message}: ${duplicateId}`,\n });\n }\n\n // 5) Register each definition now that there's no duplication\n for (const definition of definitions) {\n if (!definition.source || !definition.source.subscribe) {\n throw rcError(\"RC1001\", undefined, {\n message: `${RC[\"RC1001\"].message}: ${definition.id}`,\n });\n }\n\n // Binder injection removed\n\n const controller = new AbortController();\n this.controllers.set(definition.id, controller);\n const route = new DefaultRoute(this, definition, controller);\n this.routes.push(route);\n // Event: routeRegistered\n this.emit(\"routeRegistered\", { route });\n }\n }\n\n /**\n * Get all routes registered with this context.\n *\n * @returns Array of routes\n */\n getRoutes(): Route[] {\n return this.routes;\n }\n\n /**\n * Get a value from the context store.\n *\n * @template K Store key type\n * @param key The store key to retrieve\n * @returns The stored value or undefined if not found\n *\n * @example\n * ```typescript\n * // Get channel store\n * const channelStore = context.getStore('routecraft.adapter.channel.store');\n * ```\n */\n getStore<K extends keyof StoreRegistry>(\n key: K,\n ): StoreRegistry[K] | undefined {\n const value = this.store.get(key);\n return value as StoreRegistry[K] | undefined;\n }\n\n /**\n * Set a value in the context store.\n *\n * @template K Store key type\n * @param key The store key\n * @param value The value to store\n *\n * @example\n * ```typescript\n * // Set channel store\n * context.setStore('routecraft.adapter.channel.store', new Map());\n * ```\n */\n setStore<K extends keyof StoreRegistry>(\n key: K,\n value: StoreRegistry[K],\n ): void {\n this.store.set(key, value);\n }\n\n /**\n * Find a route by its ID.\n *\n * @param id The route ID to find\n * @returns The matching route or undefined if not found\n */\n getRouteById(id: string): Route | undefined {\n return this.routes.find((route) => route.definition.id === id);\n }\n\n /**\n * Start all routes registered with this context.\n *\n * This will:\n * 1. Run the onStartup handler if defined\n * 2. Start all routes in parallel\n * 3. Wait for all routes to complete if they're not indefinite\n * 4. Automatically stop the context if all routes complete\n *\n * @returns A promise that resolves when all routes have started\n * @throws If any route fails to start\n *\n * @example\n * ```typescript\n * try {\n * await context.start();\n * console.log('All routes started successfully');\n * } catch (error) {\n * console.error('Failed to start routes:', error);\n * }\n * ```\n */\n async start(): Promise<void> {\n this.logger.info(\"Starting Routecraft context\");\n this.emit(\"contextStarting\", {});\n\n this.logger.info(\"Starting all routes\");\n this.emit(\"contextStarted\", {});\n return Promise.allSettled(\n this.routes.map(async (route) => {\n try {\n this.logger.debug(`Starting route \"${route.definition.id}\"`);\n this.emit(\"routeStarting\", { route });\n await route.start();\n this.logger.debug(`Route \"${route.definition.id}\" ended.`);\n return { routeId: route.definition.id, success: true as const };\n } catch (error) {\n this.logger.error(\n error,\n `Failed to start route \"${route.definition.id}\"`,\n );\n this.emit(\"error\", { error, route });\n // Abort just this failing route\n const controller = this.controllers.get(route.definition.id);\n controller?.abort();\n throw error;\n }\n }),\n )\n .then((results) => {\n // Check if all routes completed successfully\n const allFulfilled = results.every((r) => r.status === \"fulfilled\");\n if (allFulfilled) {\n this.logger.info(\"All routes have completed. Stopping context...\");\n return this.stop();\n } else {\n this.logger.info(\n \"Some routes ended or failed, but the context remains active.\\n\" +\n \"Call context.stop() or let other indefinite routes continue.\",\n );\n // Do not stop automatically; let other routes run.\n return;\n }\n })\n .catch((error) => {\n this.logger.error(error, \"Context start failed\");\n this.emit(\"error\", { error });\n throw error;\n });\n }\n\n /**\n * Stop all routes and shut down the context.\n *\n * This will:\n * 1. Abort all route controllers\n * 2. Run the onShutdown handler if defined\n *\n * @returns A promise that resolves when all shutdown operations complete\n *\n * @example\n * ```typescript\n * // Handle shutdown signals\n * process.on('SIGINT', async () => {\n * console.log('Shutting down...');\n * await context.stop();\n * process.exit(0);\n * });\n * ```\n */\n async stop(): Promise<void> {\n this.logger.info(\"Stopping Routecraft context\");\n this.emit(\"contextStopping\", { reason: undefined });\n\n // Abort all route controllers (route emits handled by route abort listener)\n for (const route of this.routes) {\n this.logger.debug(\"Stopping route controller\");\n const controller = this.controllers.get(route.definition.id);\n controller?.abort(\"context.stop()\");\n }\n\n this.logger.info(\"Routecraft context stopped\");\n this.emit(\"contextStopped\", {});\n }\n}\n","import { CraftContext } from \"./context.ts\";\nimport { type Logger, createLogger } from \"./logger.ts\";\n\n/**\n * Types of operations that can be performed on an exchange.\n * These values are used in exchange headers to track the current operation.\n */\nexport enum OperationType {\n /** The exchange was created from a source */\n FROM = \"from\",\n /** The exchange was processed by a processor */\n PROCESS = \"process\",\n /** The exchange was sent to a destination */\n TO = \"to\",\n /** The exchange was split into multiple exchanges */\n SPLIT = \"split\",\n /** The exchange was aggregated from multiple exchanges */\n AGGREGATE = \"aggregate\",\n /** Modify the body of the exchange */\n TRANSFORM = \"transform\",\n /** Tap an exchange without modifying it */\n TAP = \"tap\",\n /** Filter an exchange based on a condition and reject the message if the condition is not met */\n FILTER = \"filter\",\n /** Validate the exchange against a schema and reject the message if the schema is not met */\n VALIDATE = \"validate\",\n /** Enrich the exchange with data from another exchange */\n ENRICH = \"enrich\",\n /** Set or override a header on the exchange */\n HEADER = \"header\",\n}\n\n/**\n * Standard header keys used in exchanges.\n * These keys provide metadata and context for processing exchanges.\n */\nexport enum HeadersKeys {\n /** The operation type (from, process, to) */\n OPERATION = \"routecraft.operation\",\n /** The route id */\n ROUTE_ID = \"routecraft.route\",\n /** The correlation id */\n CORRELATION_ID = \"routecraft.correlation_id\",\n /** The hierarchy of split groups this exchange belongs to */\n SPLIT_HIERARCHY = \"routecraft.split_hierarchy\",\n /** The exact timestamp when the timer fired, in ISO 8601 format */\n TIMER_TIME = \"routecraft.timer.time\",\n /** The timestamp when the exchange was created, in ISO 8601 format */\n TIMER_FIRED_TIME = \"routecraft.timer.firedTime\",\n /** The period in milliseconds between timer firings */\n TIMER_PERIOD_MS = \"routecraft.timer.periodMs\",\n /** The number of times the timer has fired */\n TIMER_COUNTER = \"routecraft.timer.counter\",\n /** The next timestamp when the timer will fire, in ISO 8601 format */\n TIMER_NEXT_RUN = \"routecraft.timer.nextRun\",\n}\n\n/**\n * Standard headers used by the Routecraft framework.\n * These headers provide critical metadata for processing exchanges.\n */\nexport interface RouteCraftHeaders {\n /** The current operation being performed */\n [HeadersKeys.OPERATION]: OperationType;\n\n /** The ID of the route processing this exchange */\n [HeadersKeys.ROUTE_ID]: string;\n\n /** Unique identifier for correlating related exchanges */\n [HeadersKeys.CORRELATION_ID]: string;\n\n /** Hierarchy path for split operations */\n [HeadersKeys.SPLIT_HIERARCHY]?: string[];\n\n /** Timer-specific headers */\n [HeadersKeys.TIMER_TIME]?: string;\n [HeadersKeys.TIMER_FIRED_TIME]?: string;\n [HeadersKeys.TIMER_PERIOD_MS]?: number;\n [HeadersKeys.TIMER_COUNTER]?: number;\n [HeadersKeys.TIMER_NEXT_RUN]?: string;\n}\n\n/**\n * Possible types for header values.\n */\nexport type HeaderValue = string | number | boolean | undefined | string[];\n\n/**\n * Complete set of headers for an exchange.\n * Includes both standard Routecraft headers and custom headers.\n */\nexport type ExchangeHeaders = Partial<RouteCraftHeaders> &\n Record<string, HeaderValue>;\n\n/**\n * Represents a message being processed through a route.\n *\n * An exchange encapsulates:\n * - The data being processed (body)\n * - Metadata about the processing (headers)\n * - A unique identifier\n * - Logging capabilities\n *\n * @template T The type of data in the body\n */\nexport type Exchange<T = unknown> = {\n /** Unique identifier for this exchange */\n readonly id: string;\n\n /** Headers containing metadata */\n readonly headers: ExchangeHeaders;\n\n /** The data being processed */\n body: T;\n\n /** Logger for this exchange */\n logger: Logger;\n};\n\n/**\n * Default implementation of the Exchange interface.\n *\n * Provides standard exchange functionality with automatic\n * ID generation and header initialization.\n *\n * @template T The type of data in the body\n *\n * @example\n * ```typescript\n * // Create a simple exchange with a string body\n * const exchange = new DefaultExchange<string>(context, {\n * body: \"Hello, World!\"\n * });\n *\n * // Access exchange properties\n * console.log(exchange.id); // Unique UUID\n * console.log(exchange.body); // \"Hello, World!\"\n * console.log(exchange.headers); // Headers object with standard fields\n * ```\n */\nexport class DefaultExchange<T = unknown> implements Exchange<T> {\n /** Unique identifier for this exchange */\n readonly id: string;\n\n /** Headers containing metadata */\n readonly headers: ExchangeHeaders;\n\n /** The data being processed */\n body: T;\n\n /** Logger for this exchange */\n public readonly logger: Logger;\n\n /**\n * Create a new exchange.\n *\n * @param context The CraftContext this exchange belongs to\n * @param options Optional configuration for the exchange\n */\n constructor(\n public readonly context: CraftContext,\n options?: Partial<Exchange<T>>,\n ) {\n this.id = options?.id || crypto.randomUUID();\n this.headers = {\n [HeadersKeys.ROUTE_ID]: crypto.randomUUID(),\n [HeadersKeys.OPERATION]: OperationType.FROM,\n [HeadersKeys.CORRELATION_ID]: crypto.randomUUID(),\n ...(options?.headers || {}),\n };\n this.body = options?.body || ({} as T);\n this.logger = createLogger(this);\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange } from \"../exchange.ts\";\nimport { OperationType } from \"../exchange.ts\";\n\n/**\n * Processor: mutate or derive a new Exchange from the current one.\n * - May change body, headers, and type\n * - Prefer pure logic; avoid side effects (use `.to(...)` for IO)\n * - Use when you need access to headers or want to replace the whole exchange\n */\n\nexport type CallableProcessor<T = unknown, R = T> = (\n exchange: Exchange<T>,\n) => Promise<Exchange<R>> | Exchange<R>;\n\nexport interface Processor<T = unknown, R = T> extends Adapter {\n process: CallableProcessor<T, R>;\n}\n\nexport class ProcessStep<T = unknown, R = T> implements Step<Processor<T, R>> {\n operation: OperationType = OperationType.PROCESS;\n adapter: Processor<T, R>;\n\n constructor(adapter: Processor<T, R> | CallableProcessor<T, R>) {\n this.adapter =\n typeof adapter === \"function\" ? { process: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<R>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n const newExchange = await Promise.resolve(this.adapter.process(exchange));\n queue.push({ exchange: newExchange, steps: remainingSteps });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType } from \"../exchange.ts\";\n\n/**\n * To (Destination): side effects/output only.\n * - Sends or persists the current exchange\n * - Must not modify the message; downstream continues unchanged\n * - Use for IO boundaries (DB writes, HTTP emits, queues)\n */\n\nexport type CallableDestination<T = unknown> = (\n exchange: Exchange<T>,\n) => Promise<void> | void;\n\nexport interface Destination<T = unknown> extends Adapter {\n send: CallableDestination<T>;\n}\n\nexport class ToStep<T = unknown> implements Step<Destination<T>> {\n operation: OperationType = OperationType.TO;\n adapter: Destination<T>;\n\n constructor(adapter: Destination<T> | CallableDestination<T>) {\n this.adapter = typeof adapter === \"function\" ? { send: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<T>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n await this.adapter.send(exchange);\n queue.push({ exchange, steps: remainingSteps });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType, HeadersKeys } from \"../exchange.ts\";\n\nexport type CallableSplitter<T = unknown, R = unknown> = (\n body: T,\n) => Promise<R[]> | R[];\n\nexport interface Splitter<T = unknown, R = unknown> extends Adapter {\n split: CallableSplitter<T, R>;\n}\n\nexport class SplitStep<T = unknown, R = unknown>\n implements Step<Splitter<T, R>>\n{\n operation: OperationType = OperationType.SPLIT;\n adapter: Splitter<T, R>;\n\n constructor(adapter: Splitter<T, R> | CallableSplitter<T, R>) {\n this.adapter = typeof adapter === \"function\" ? { split: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<R>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n const splitBodies = await Promise.resolve(\n this.adapter.split(exchange.body),\n );\n const groupId = crypto.randomUUID();\n\n const existingHierarchy =\n (exchange.headers[HeadersKeys.SPLIT_HIERARCHY] as string[]) || [];\n const splitHierarchy = [...existingHierarchy, groupId];\n\n splitBodies.forEach((body) => {\n const postProcessedExchange: Exchange<R> = {\n ...exchange,\n id: crypto.randomUUID(),\n body,\n headers: {\n ...exchange.headers,\n [HeadersKeys.SPLIT_HIERARCHY]: splitHierarchy,\n },\n };\n postProcessedExchange.logger.debug(\n `Pushing split exchange ${postProcessedExchange.id} to queue, splitHierarchy: ${postProcessedExchange.headers[HeadersKeys.SPLIT_HIERARCHY]}`,\n );\n queue.push({\n exchange: postProcessedExchange,\n steps: remainingSteps,\n });\n });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType, HeadersKeys } from \"../exchange.ts\";\n\nexport type CallableAggregator<T = unknown, R = T> = (\n exchanges: Exchange<T>[],\n) => Promise<Exchange<R>> | Exchange<R>;\n\nexport interface Aggregator<T = unknown, R = unknown> extends Adapter {\n aggregate: CallableAggregator<T, R>;\n}\n\nexport class AggregateStep<T = unknown, R = unknown>\n implements Step<Aggregator<T, R>>\n{\n operation: OperationType = OperationType.AGGREGATE;\n adapter: Aggregator<T, R>;\n\n constructor(adapter: Aggregator<T, R> | CallableAggregator<T, R>) {\n this.adapter =\n typeof adapter === \"function\" ? { aggregate: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<R>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n const splitHierarchy = exchange.headers[\n HeadersKeys.SPLIT_HIERARCHY\n ] as string[];\n\n // If there's no split hierarchy, just aggregate the single exchange\n if (!splitHierarchy) {\n const aggregatedExchange = await Promise.resolve(\n this.adapter.aggregate([exchange]),\n );\n queue.push({\n exchange: aggregatedExchange,\n steps: remainingSteps,\n });\n return;\n }\n\n const currentGroupId = splitHierarchy[splitHierarchy.length - 1];\n const aggregationGroup: Exchange[] = [exchange];\n\n for (let i = 0; i < queue.length; ) {\n const item = queue[i];\n const itemHierarchy = item.exchange.headers[\n HeadersKeys.SPLIT_HIERARCHY\n ] as string[];\n if (itemHierarchy?.at(-1) === currentGroupId) {\n aggregationGroup.push(item.exchange);\n queue.splice(i, 1);\n } else {\n i++;\n }\n }\n\n const aggregatedExchange = await Promise.resolve(\n this.adapter.aggregate(aggregationGroup as Exchange<T>[]),\n );\n\n // Remove the current group from hierarchy after aggregation\n const remainingHierarchy = splitHierarchy.slice(0, -1);\n if (remainingHierarchy.length > 0) {\n aggregatedExchange.headers[HeadersKeys.SPLIT_HIERARCHY] =\n remainingHierarchy;\n } else {\n delete aggregatedExchange.headers[HeadersKeys.SPLIT_HIERARCHY];\n }\n\n queue.push({\n exchange: aggregatedExchange,\n steps: remainingSteps,\n });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType } from \"../exchange.ts\";\n\n/**\n * Transform: body-only pure conversion.\n * - Returns a new body; headers and metadata remain unchanged\n * - Prefer this for simple mapping/scalar conversions\n * - Use `.process` instead if you need to modify headers or other Exchange fields\n */\n\nexport type CallableTransformer<T = unknown, R = T> = (\n message: T,\n) => Promise<R> | R;\n\nexport interface Transformer<T = unknown, R = T> extends Adapter {\n transform: CallableTransformer<T, R>;\n}\n\nexport class TransformStep<T = unknown, R = T>\n implements Step<Transformer<T, R>>\n{\n operation: OperationType = OperationType.TRANSFORM;\n adapter: Transformer<T, R>;\n\n constructor(adapter: Transformer<T, R> | CallableTransformer<T, R>) {\n this.adapter =\n typeof adapter === \"function\" ? { transform: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<R>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n const newBody = await Promise.resolve(\n this.adapter.transform(exchange.body),\n );\n queue.push({\n exchange: { ...exchange, body: newBody },\n steps: remainingSteps,\n });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType } from \"../exchange.ts\";\nimport { error as rcError } from \"../error.ts\";\n\nexport type CallableTap<T = unknown> = (\n exchange: Exchange<T>,\n) => Promise<void> | void;\n\nexport interface Tap<T = unknown> extends Adapter {\n tap: CallableTap<T>;\n}\n\nexport class TapStep<T = unknown> implements Step<Tap<T>> {\n operation: OperationType = OperationType.TAP;\n adapter: Tap<T>;\n\n constructor(adapter: Tap<T> | CallableTap<T>) {\n this.adapter = typeof adapter === \"function\" ? { tap: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<T>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n // Create a deep copy of the exchange for the tap\n const exchangeCopy: Exchange<T> = {\n ...exchange,\n body: structuredClone(exchange.body),\n headers: structuredClone(exchange.headers),\n };\n\n try {\n // Tap is not considered a critical step, so we don't want to throw an error\n await this.adapter.tap(exchangeCopy);\n } catch (error: unknown) {\n const err = rcError(\"RC5007\", error, {\n message: `Error tapping exchange ${exchangeCopy.id}`,\n suggestion:\n \"Check the tap function for any errors or wrap it in a try/catch block.\",\n });\n exchangeCopy.logger.info(\n err,\n `Error tapping exchange ${exchangeCopy.id}`,\n );\n }\n queue.push({ exchange, steps: remainingSteps });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType } from \"../exchange.ts\";\nimport { error as rcError } from \"../error.ts\";\n\nexport type CallableFilter<T = unknown> = (\n exchange: Exchange<T>,\n) => Promise<boolean> | boolean;\n\nexport interface Filter<T = unknown> extends Adapter {\n filter: CallableFilter<T>;\n}\n\nexport class FilterStep<T = unknown> implements Step<Filter<T>> {\n operation: OperationType = OperationType.FILTER;\n adapter: Filter<T>;\n\n constructor(adapter: Filter<T> | CallableFilter<T>) {\n this.adapter =\n typeof adapter === \"function\" ? { filter: adapter } : adapter;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<T>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n try {\n const result = await Promise.resolve(this.adapter.filter(exchange));\n if (!result) {\n exchange.logger.debug(`Filter rejected exchange ${exchange.id}`);\n return;\n }\n } catch (error: unknown) {\n const err = rcError(\"RC5008\", error, {\n message: `Error filtering exchange ${exchange.id}`,\n });\n exchange.logger.warn(err, `Error filtering exchange ${exchange.id}`);\n }\n queue.push({ exchange, steps: remainingSteps });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange } from \"../exchange.ts\";\nimport { OperationType } from \"../exchange.ts\";\n\n/**\n * Function that produces enrichment data based on the original exchange.\n * Returns only the enrichment payload (body) which will be combined with the\n * original exchange by the aggregator.\n */\nexport type CallableEnricher<T = unknown, R = unknown> = (\n exchange: Exchange<T>,\n) => Promise<R> | R;\n\n/**\n * Enricher: produce data to merge into the existing exchange.\n * - Does not return a new Exchange; only the enrichment payload\n * - Combine with default or custom aggregator in `.enrich(adapter, aggregator)`\n */\nexport interface Enricher<T = unknown, R = unknown> extends Adapter {\n enrich: CallableEnricher<T, R>;\n adapterId: string;\n}\n\n/**\n * Function that aggregates the original exchange with the enrichment data\n * Similar to CallableAggregator but specifically for the enrich operation\n */\nexport type EnrichAggregator<T = unknown, R = unknown> = (\n original: Exchange<T>,\n enrichmentData: R,\n) => Promise<Exchange<T>> | Exchange<T>;\n\n/**\n * Default aggregator that merges the enrichment data with the original exchange body.\n *\n * This aggregator:\n * 1. Converts the original body to an object if it's not already one (using {value: originalBody})\n * 2. Converts the enrichment data to an object if it's not already one (using {value: enrichmentData})\n * 3. Merges these objects using spread syntax ({...originalBody, ...enrichmentObject})\n *\n * Note: If both the original body and enrichment data have a 'value' property,\n * the enrichment data's 'value' will overwrite the original's 'value'.\n */\nexport const defaultEnrichAggregator = <T = unknown, R = unknown>(\n original: Exchange<T>,\n enrichmentData: R,\n): Exchange<T> => {\n // Convert original body to object if it's not already\n const originalBody =\n typeof original.body === \"object\" && original.body !== null\n ? original.body\n : { value: original.body };\n\n // Convert enrichment data to object if it's not already\n const enrichmentObject =\n typeof enrichmentData === \"object\" && enrichmentData !== null\n ? enrichmentData\n : { value: enrichmentData };\n\n // Merge the objects\n return {\n ...original,\n body: {\n ...originalBody,\n ...enrichmentObject,\n } as T,\n };\n};\n\n/**\n * Step that enriches the exchange with additional data\n */\nexport class EnrichStep<T = unknown, R = unknown>\n implements Step<Enricher<T, R>>\n{\n operation: OperationType = OperationType.ENRICH;\n adapter: Enricher<T, R>;\n aggregator: EnrichAggregator<T, R> | undefined;\n\n constructor(\n adapter: Enricher<T, R> | CallableEnricher<T, R>,\n aggregator?: EnrichAggregator<T, R>,\n ) {\n this.adapter =\n typeof adapter === \"function\"\n ? {\n enrich: adapter,\n adapterId: crypto.randomUUID(),\n }\n : adapter;\n this.aggregator = aggregator;\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n // Get the enrichment data\n const enrichmentData = await Promise.resolve(this.adapter.enrich(exchange));\n\n // Use the provided aggregator or the default one\n const aggregator = this.aggregator || defaultEnrichAggregator;\n\n // Aggregate the original exchange with the enrichment data\n const newExchange = await Promise.resolve(\n aggregator(exchange, enrichmentData),\n );\n\n // Push the new exchange to the queue\n queue.push({ exchange: newExchange, steps: remainingSteps });\n }\n}\n","import { CraftContext } from \"../context.ts\";\nimport { type RouteDefinition } from \"../route.ts\";\nimport { type ProcessingQueue, type Message, type Consumer } from \"../types.ts\";\nimport { type Exchange, type ExchangeHeaders } from \"../exchange.ts\";\n\nexport class SimpleConsumer implements Consumer<never> {\n constructor(\n public readonly context: CraftContext,\n public readonly definition: RouteDefinition,\n public readonly channel: ProcessingQueue<Message>,\n public readonly options: never,\n ) {}\n\n async register(\n handler: (message: unknown, headers?: ExchangeHeaders) => Promise<Exchange>,\n ): Promise<void> {\n this.channel.setHandler(async (message) => {\n return await handler(message.message, message.headers);\n });\n }\n}\n","import { CraftContext } from \"../context.ts\";\nimport { type RouteDefinition } from \"../route.ts\";\nimport { type ProcessingQueue, type Message, type Consumer } from \"../types.ts\";\nimport {\n type Exchange,\n type ExchangeHeaders,\n type HeaderValue,\n} from \"../exchange.ts\";\n\nexport type BatchOptions = {\n /**\n * The size of the batch.\n */\n size?: number;\n /**\n * The timeout between batches in milliseconds.\n */\n time?: number;\n /**\n * The function to merge the produced messages.\n */\n merge?: (exchanges: { message: unknown; headers?: ExchangeHeaders }[]) => {\n message: unknown;\n headers?: ExchangeHeaders;\n };\n};\n\nexport class BatchConsumer implements Consumer<BatchOptions> {\n public readonly options: BatchOptions;\n\n constructor(\n public readonly context: CraftContext,\n public readonly definition: RouteDefinition,\n public readonly channel: ProcessingQueue<Message>,\n options: BatchOptions,\n ) {\n this.options = {\n size: options.size ?? 1000,\n time: options.time ?? 10 * 1000,\n merge:\n options.merge ??\n ((messages) => {\n const headers: Record<string, HeaderValue> = {};\n for (const message of messages) {\n for (const [key, value] of Object.entries(message.headers ?? {})) {\n headers[key] = value;\n }\n }\n return {\n message: messages.map((message) => message.message),\n headers,\n };\n }),\n } as Required<BatchOptions>;\n }\n\n async register(\n handler: (message: unknown, headers?: ExchangeHeaders) => Promise<Exchange>,\n ): Promise<void> {\n let batch: Message[] = [];\n let resolvers: {\n resolve: (ex: Exchange) => void;\n reject: (e: unknown) => void;\n }[] = [];\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const flushBatch = async () => {\n if (batch.length > 0) {\n const currentBatch = batch;\n const currentResolvers = resolvers;\n batch = [];\n resolvers = [];\n try {\n const merged = this.options.merge!(currentBatch);\n const finalExchange = await handler(merged.message, merged.headers);\n for (const { resolve } of currentResolvers) {\n resolve(finalExchange);\n }\n } catch (error) {\n this.context.logger.warn(\n error,\n `Error in batch consumer for route \"${this.definition.id}\":`,\n );\n for (const { reject } of currentResolvers) {\n reject(error);\n }\n }\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n this.channel.setHandler(async (message) => {\n const promise = new Promise<Exchange>((resolve, reject) => {\n batch.push(message);\n resolvers.push({ resolve, reject });\n });\n\n if (batch.length === 1) {\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(async () => {\n await flushBatch();\n }, this.options.time!);\n }\n\n if (batch.length >= this.options.size!) {\n await flushBatch();\n }\n return promise;\n });\n }\n}\n","import { type StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { FilterStep } from \"./filter.ts\";\nimport { OperationType } from \"../exchange.ts\";\nimport { error as rcError } from \"../error.ts\";\n\nexport class ValidateStep<T = unknown> extends FilterStep<T> {\n override operation: OperationType = OperationType.VALIDATE;\n constructor(schema: StandardSchemaV1) {\n super(async (exchange) => {\n let result = schema[\"~standard\"].validate(exchange.body);\n if (result instanceof Promise) result = await result;\n\n // if the `issues` field exists, the validation failed\n if (result.issues) {\n const err = rcError(\"RC5009\", result.issues, {\n message: `Error validating exchange ${exchange.id}`,\n });\n exchange.logger.debug(err, `Error validating exchange ${exchange.id}`);\n return false;\n } else {\n return true;\n }\n });\n }\n}\n","import { type Adapter, type Step } from \"../types.ts\";\nimport { type Exchange, OperationType, type HeaderValue } from \"../exchange.ts\";\n\n/**\n * Header: set or override a single exchange header.\n * - Returns the same body; only headers are changed\n * - Prefer this over `.process` when only a header needs updating\n */\n\nexport type CallableHeaderSetter<T = unknown> = (\n exchange: Exchange<T>,\n) => Promise<HeaderValue> | HeaderValue;\n\nexport interface HeaderSetter<T = unknown> extends Adapter {\n /** Header key to set */\n key: string;\n /** Function that computes the header value from exchange data */\n set: CallableHeaderSetter<T>;\n}\n\nexport class HeaderStep<T = unknown> implements Step<HeaderSetter<T>> {\n operation: OperationType = OperationType.HEADER;\n adapter: HeaderSetter<T>;\n\n constructor(\n key: string,\n setterOrValue: CallableHeaderSetter<T> | HeaderValue,\n ) {\n const set: CallableHeaderSetter<T> =\n typeof setterOrValue === \"function\"\n ? (setterOrValue as CallableHeaderSetter<T>)\n : () => setterOrValue;\n\n this.adapter = { key, set };\n }\n\n async execute(\n exchange: Exchange<T>,\n remainingSteps: Step<Adapter>[],\n queue: { exchange: Exchange<T>; steps: Step<Adapter>[] }[],\n ): Promise<void> {\n const value = await Promise.resolve(this.adapter.set(exchange));\n queue.push({\n exchange: {\n ...exchange,\n headers: {\n ...exchange.headers,\n [this.adapter.key]: value,\n },\n },\n steps: remainingSteps,\n });\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { type RouteDefinition } from \"./route.ts\";\nimport {\n CraftContext,\n type StoreRegistry,\n type CraftConfig,\n} from \"./context.ts\";\nimport { error as rcError } from \"./error.ts\";\nimport { logger } from \"./logger.ts\";\nimport { type EventHandler, type EventName } from \"./types.ts\";\nimport { SimpleConsumer } from \"./consumers/simple.ts\";\nimport { BatchConsumer } from \"./consumers/batch.ts\";\nimport { type Source, type CallableSource } from \"./operations/from.ts\";\nimport {\n type Adapter,\n type Step,\n type Consumer,\n type ConsumerType,\n} from \"./types.ts\";\nimport { type Exchange } from \"./exchange.ts\";\nimport {\n type Processor,\n type CallableProcessor,\n ProcessStep,\n} from \"./operations/process.ts\";\nimport {\n type Destination,\n type CallableDestination,\n ToStep,\n} from \"./operations/to.ts\";\nimport {\n type Splitter,\n type CallableSplitter,\n SplitStep,\n} from \"./operations/split.ts\";\nimport {\n type Aggregator,\n type CallableAggregator,\n AggregateStep,\n} from \"./operations/aggregate.ts\";\nimport {\n type Transformer,\n type CallableTransformer,\n TransformStep,\n} from \"./operations/transform.ts\";\nimport { type Tap, type CallableTap, TapStep } from \"./operations/tap.ts\";\nimport {\n type CallableFilter,\n type Filter,\n FilterStep,\n} from \"./operations/filter.ts\";\nimport { ValidateStep } from \"./operations/validate.ts\";\nimport {\n type EnrichAggregator,\n EnrichStep,\n type Enricher,\n type CallableEnricher,\n} from \"./operations/enrich.ts\";\nimport { HeaderStep } from \"./operations/header.ts\";\nimport { type HeaderValue } from \"./exchange.ts\";\n// Binder mechanism removed\n\n/**\n * Builder for creating a RouteCraft context with routes and configuration.\n *\n * This builder provides a fluent API for configuring and creating a CraftContext\n * with routes, startup/shutdown handlers, and initial store values.\n *\n * @example\n * ```typescript\n * // Create a context with routes and handlers\n * const context = new ContextBuilder()\n * .with({ store: new Map() })\n * .on('contextStarting', ({ ts }) => console.log('Starting at', ts))\n * .store('routecraft.adapter.channel.store', new Map())\n * .routes(routes1)\n * .routes([routes2, routes3])\n * .build();\n *\n * // Start the context to begin processing\n * await context.start();\n * ```\n */\nexport class ContextBuilder {\n protected config?: CraftConfig;\n protected definitions: RouteDefinition[] = [];\n protected initialStores = new Map<\n keyof StoreRegistry,\n StoreRegistry[keyof StoreRegistry]\n >();\n protected eventHandlers = new Map<EventName, Set<EventHandler<EventName>>>();\n // Binder registry removed\n\n constructor() {}\n\n /**\n * Configure the context with the provided config object.\n *\n * @param config The configuration object for the context\n * @returns This builder instance for method chaining\n */\n with(config: CraftConfig): this {\n this.config = config;\n\n // Extract store entries if provided\n if (config.store) {\n for (const [key, value] of config.store.entries()) {\n this.initialStores.set(key, value);\n }\n }\n\n // Extract event handlers if provided\n if (config.on) {\n for (const [event, handler] of Object.entries(config.on)) {\n const eventName = event as EventName;\n if (Array.isArray(handler)) {\n handler.forEach((h) => {\n const set = this.eventHandlers.get(eventName) ?? new Set();\n set.add(h as EventHandler<EventName>);\n this.eventHandlers.set(eventName, set);\n });\n } else if (handler) {\n const set = this.eventHandlers.get(eventName) ?? new Set();\n set.add(handler as EventHandler<EventName>);\n this.eventHandlers.set(eventName, set);\n }\n }\n }\n\n return this;\n }\n\n // binders(...) API removed\n\n /**\n * Register an event listener to be attached to the built context.\n */\n on<K extends EventName>(event: K, handler: EventHandler<K>): this {\n const set = this.eventHandlers.get(event) ?? new Set();\n set.add(handler as unknown as EventHandler<EventName>);\n this.eventHandlers.set(event, set);\n return this;\n }\n\n /**\n * Add an initial value to the context store.\n *\n * @template K The store key type\n * @param key The store key\n * @param value The initial value for the store\n * @returns This builder instance for method chaining\n *\n * @example\n * ```typescript\n * // Add an initial channel store\n * builder.store('routecraft.adapter.channel.store', new Map());\n * ```\n */\n store<K extends keyof StoreRegistry>(key: K, value: StoreRegistry[K]): this {\n this.initialStores.set(key, value);\n return this;\n }\n\n /**\n * Add routes to the context.\n *\n * Routes can be added as individual RouteDefinitions, RouteBuilders, or arrays of either.\n *\n * @param routes Individual or array of route definitions/builders to add\n * @returns This builder instance for method chaining\n *\n * @example\n * ```typescript\n * // Add a single route\n * builder.routes(myRoute);\n *\n * // Add multiple routes\n * builder.routes([route1, route2, route3]);\n *\n * // Add a route builder\n * builder.routes(\n * craft()\n * .from(simple(\"hello\"))\n * .to(log())\n * );\n * ```\n */\n routes(\n routes:\n | RouteDefinition[]\n | RouteBuilder<unknown>[]\n | RouteDefinition\n | RouteBuilder<unknown>,\n ): this {\n if (Array.isArray(routes)) {\n // Handle array of RouteDefinitions or RouteBuilders\n routes.forEach((route) => {\n if (route instanceof RouteBuilder) {\n this.definitions.push(...route.build());\n } else {\n this.definitions.push(route);\n }\n });\n } else if (routes instanceof RouteBuilder) {\n // Handle single RouteBuilder\n this.definitions.push(...routes.build());\n } else {\n // Handle single RouteDefinition\n this.definitions.push(routes);\n }\n return this;\n }\n\n /**\n * Build and return a configured CraftContext instance.\n *\n * This finalizes the configuration and creates a ready-to-use context\n * with all the configured routes, handlers, and store values.\n *\n * @returns A new CraftContext instance\n */\n build(): CraftContext {\n const ctx = new CraftContext(this.config);\n\n // Add stores from builder (config stores already added in constructor)\n for (const [key, value] of this.initialStores) {\n if (!this.config?.store?.has(key)) {\n ctx.setStore(key, value);\n }\n }\n\n // Attach event handlers from builder (config handlers already added in constructor)\n for (const [event, handlers] of this.eventHandlers.entries()) {\n for (const handler of handlers) {\n ctx.on(event as EventName, handler as EventHandler<EventName>);\n }\n }\n\n // Register all routes from builder\n ctx.registerRoutes(...this.definitions);\n\n return ctx;\n }\n}\n\n/**\n * Options for configuring a route.\n */\nexport type RouteOptions = Partial<Pick<RouteDefinition, \"consumer\">> & {\n /**\n * Unique identifier for the route.\n */\n id: string;\n};\n\n/**\n * Builder for creating route definitions with a fluent API.\n *\n * This builder provides methods for defining the steps in a route,\n * including sources, transformations, filters, destinations, and more.\n *\n * The type parameter tracks the data type flowing through the route\n * at each step, providing type safety throughout the route definition.\n *\n * @template Current The type of data currently flowing through the route\n *\n * @example\n * ```typescript\n * // Create a simple route that processes a string\n * const route = craft()\n * .from(simple(\"Hello, World!\"))\n * .transform(msg => msg.toUpperCase())\n * .to(log())\n * ```\n */\nexport class RouteBuilder<Current = unknown> {\n protected currentRoute?: RouteDefinition;\n protected routes: RouteDefinition[] = [];\n\n // Pending options set via .id() / .batch() before .from()\n protected pendingOptions?:\n | {\n id?: string;\n consumer?: {\n type: ConsumerType<Consumer>;\n options?: unknown;\n };\n }\n | undefined;\n\n constructor() {}\n\n /**\n * Internal method to create a new RouteBuilder with an updated type parameter.\n * This is used to propagate type information through the method chain.\n *\n * @template T The new type to use for the RouteBuilder\n * @returns A new RouteBuilder instance with the updated type\n * @private\n */\n private withType<T>(): RouteBuilder<T> {\n // This cast is necessary but safe because we're not changing the instance,\n // just the type parameter\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Set the route id for the next route to be created.\n * This stages the id and does not affect the current route if one exists.\n */\n id(id: string): this {\n this.pendingOptions = { ...(this.pendingOptions ?? {}), id };\n logger.debug(`Staging route id \"${id}\" for next route`);\n return this;\n }\n\n /**\n * Configure batch processing for the next route to be created.\n * This stages the batch consumer and does not affect the current route if one exists.\n */\n batch(options?: { size?: number; flushIntervalMs?: number }): this {\n const mapped = {\n size: options?.size,\n time: options?.flushIntervalMs,\n } as unknown;\n this.pendingOptions = {\n ...(this.pendingOptions ?? {}),\n consumer: {\n type: BatchConsumer as unknown as ConsumerType<Consumer>,\n options: mapped,\n },\n };\n logger.debug(\"Staging batch processing for next route\");\n return this;\n }\n\n /**\n * Define the source of data for this route.\n * This is typically the first step in defining a route.\n *\n * @template T The type of data produced by the source\n * @param source A source adapter or function\n * @returns A RouteBuilder with the specified type T\n * @example\n * // Simple source with inferred type\n * .from<string[]>(httpServer({ path: '/api/data' }))\n *\n * // Source with callable function\n * .from<User[]>(async () => {\n * const response = await fetch('https://api.example.com/users');\n * return response.json();\n * })\n */\n from<T>(source: Source<T> | CallableSource<T>): RouteBuilder<T> {\n const id = this.pendingOptions?.id ?? crypto.randomUUID().toString();\n const consumer = this.pendingOptions?.consumer ?? {\n type: SimpleConsumer as unknown as ConsumerType<Consumer>,\n options: undefined,\n };\n\n logger.debug(`Creating route definition with id \"${id}\"`);\n\n this.currentRoute = {\n id,\n source: typeof source === \"function\" ? { subscribe: source } : source,\n steps: [],\n consumer: {\n type: consumer.type,\n options: consumer.options ?? undefined,\n },\n };\n\n // Clear staged options once used\n this.pendingOptions = undefined;\n\n this.routes.push(this.currentRoute);\n return this.withType<T>();\n }\n\n /**\n * Internal method to ensure a source has been defined for the current route.\n * Throws an error if no source has been defined.\n *\n * @returns The current route definition\n * @throws Error if no source has been defined\n * @private\n */\n private requireSource(): RouteDefinition {\n if (!this.currentRoute) {\n throw rcError(\"RC2002\");\n }\n return this.currentRoute;\n }\n\n /**\n * Internal method to add a step to the current route.\n * This is used by the public methods to build up the route definition.\n *\n * @template T The type of adapter used by the step\n * @param step The step definition to add\n * @returns The current RouteBuilder instance\n * @private\n */\n private addStep<T extends Adapter>(step: Step<T>): RouteBuilder<Current> {\n const route = this.requireSource();\n logger.debug(`Adding ${step.operation} step to route \"${route.id}\"`);\n route.steps.push(step);\n return this.withType<Current>();\n }\n\n /**\n * Process the data with a custom function.\n *\n * @template Return The resulting type after processing (defaults to Current if not specified)\n * @param processor A function that transforms the current exchange to a new exchange with the Return\n * @returns A RouteBuilder with the new type Return\n * @example\n * // Transform string data to number\n * .process<number>((exchange) => {\n * return { ...exchange, body: parseInt(exchange.body) };\n * })\n */\n process<Return = Current>(\n processor: Processor<Current, Return> | CallableProcessor<Current, Return>,\n ): RouteBuilder<Return> {\n this.addStep(new ProcessStep<Current, Return>(processor));\n return this.withType<Return>();\n }\n\n /**\n * Send the processed data to a destination.\n * This is typically the final step in a route.\n * The type remains the same after this operation.\n *\n * @param destination A function or adapter that consumes the data\n * @returns A RouteBuilder with the same type\n * @example\n * // Send data to a database\n * .to(async ({ body }) => {\n * await db.users.insert(body);\n * })\n *\n * // Send to a predefined destination\n * .to(kafkaProducer({ topic: 'processed-data' }))\n */\n to(\n destination: Destination<Current> | CallableDestination<Current>,\n ): RouteBuilder<Current> {\n const route = this.requireSource();\n logger.debug(`Adding destination step to route \"${route.id}\"`);\n route.steps.push(new ToStep<Current>(destination));\n return this.withType<Current>();\n }\n\n /**\n * Split an array into individual items for processing.\n * Each item becomes a separate exchange with a new UUID and copied headers.\n * If no splitter is provided and the current data is an array, it will automatically\n * split the array into individual items.\n *\n * Similar to Apache Camel's Splitter EIP: accepts body, returns array of body items.\n * The framework automatically creates new exchanges for each item.\n *\n * @template ItemType The type of items in the array (inferred from array if not specified)\n * @param splitter Optional function that receives the body and returns an array of items\n * @returns A RouteBuilder with the item type\n * @example\n * // Automatically split an array of numbers\n * .from<number[]>(source)\n * .split() // ItemType is inferred as number\n *\n * // Custom splitting logic - extract nested array\n * .from(source)\n * .split<User>((body) => body.users)\n *\n * // Split a string by delimiter\n * .split<string>((body) => body.split(\",\"))\n */\n split<ItemType = Current extends Array<infer U> ? U : never>(\n splitter?:\n | Splitter<Current, ItemType>\n | CallableSplitter<Current, ItemType>,\n ): RouteBuilder<ItemType> {\n const route = this.requireSource();\n logger.debug(`Adding split step to route \"${route.id}\"`);\n\n // If no splitter is provided and Current is an array, use default array splitter\n if (!splitter) {\n // Create a default array splitter\n const defaultSplitter: CallableSplitter<Current, ItemType> = (body) => {\n // Check if the body is an array\n if (!Array.isArray(body)) {\n throw rcError(\"RC2001\", undefined, {\n message: \"Default splitter can only be used with arrays\",\n suggestion:\n \"Provide a custom splitter or ensure the input is an array\",\n });\n }\n\n // Split the array into individual items\n return body as ItemType[];\n };\n\n route.steps.push(new SplitStep<Current, ItemType>(defaultSplitter));\n } else {\n route.steps.push(new SplitStep<Current, ItemType>(splitter));\n }\n\n return this.withType<ItemType>();\n }\n\n /**\n * Aggregate multiple items into a single result.\n * This is often used after a split operation to collect and combine the results.\n *\n * @template ResultType The resulting type after aggregation\n * @param aggregator A function that combines multiple items into a single result\n * @returns A RouteBuilder with the new aggregated type\n * @example\n * // Aggregate an array of numbers into a sum\n * .split() // Working with individual numbers\n * .process((exchange) => ({ ...exchange, body: exchange.body * 2 })) // Double each number\n * .aggregate<number>((exchanges) => {\n * const sum = exchanges.reduce((acc, ex) => acc + ex.body, 0);\n * return { body: sum, headers: exchanges[0].headers };\n * })\n */\n aggregate<ResultType>(\n aggregator:\n | Aggregator<Current, ResultType>\n | CallableAggregator<Current, ResultType>,\n ): RouteBuilder<ResultType> {\n this.addStep(new AggregateStep<Current, ResultType>(aggregator));\n return this.withType<ResultType>();\n }\n\n /**\n * Transform the current data to a new type using a transformer function.\n * Unlike process, this operates only on the body of the exchange, not the entire exchange.\n *\n * @template Return The resulting type after transformation\n * @param transformer A function that transforms the current body to a new body of type Return\n * @returns A RouteBuilder with the new type Return\n * @example\n * // Transform a string to an object\n * .transform<{ value: string }>((str) => ({ value: str }))\n */\n transform<Return>(\n transformer:\n | Transformer<Current, Return>\n | CallableTransformer<Current, Return>,\n ): RouteBuilder<Return> {\n this.addStep(new TransformStep<Current, Return>(transformer));\n return this.withType<Return>();\n }\n\n /**\n * Set or override a header on the current exchange.\n * The body type remains unchanged.\n *\n * @param key Header key to set\n * @param valueOrFn A static value or a function returning the value from exchange data\n * @returns A RouteBuilder with the same type\n * @example\n * // Static value\n * .header('x-env', 'prod')\n *\n * // Derived from body\n * .header('user.id', (exchange) => exchange.body.id)\n *\n * // Derived from headers\n * .header('correlation', (exchange) => exchange.headers['x-request-id'])\n */\n header(\n key: string,\n valueOrFn:\n | HeaderValue\n | ((exchange: Exchange<Current>) => HeaderValue | Promise<HeaderValue>),\n ): RouteBuilder<Current> {\n this.addStep(new HeaderStep<Current>(key, valueOrFn));\n return this.withType<Current>();\n }\n\n /**\n * Map fields from the current data to create a new object of a specified type.\n * This is a specialized transformer that creates a new object by mapping fields\n * from the source object.\n *\n * @template Return The resulting type after mapping\n * @param fieldMappings An object where keys are field names in the output type and values are\n * functions that extract the corresponding values from the source\n * @returns A RouteBuilder with the new type Return\n * @example\n * // Map from API response to database model\n * .map<DbUser>({\n * id: (apiUser) => apiUser.userId,\n * name: (apiUser) => apiUser.fullName,\n * email: (apiUser) => apiUser.emailAddress\n * })\n */\n map<Return>(\n fieldMappings: Record<keyof Return, (src: Current) => Return[keyof Return]>,\n ): RouteBuilder<Return> {\n // Create a transformer function from the field mappings\n const transformer: CallableTransformer<Current, Return> = (\n message: Current,\n ): Return => {\n const result = {} as Return;\n\n for (const [targetField, mapperFn] of Object.entries(fieldMappings) as [\n keyof Return,\n (src: Current) => Return[keyof Return],\n ][]) {\n result[targetField as keyof Return] = mapperFn(message);\n }\n\n return result;\n };\n\n // Use the transform method with our created transformer\n return this.transform<Return>(transformer);\n }\n\n /**\n * Execute a side effect without changing the data.\n * This is useful for logging, metrics, or other operations that don't modify the data.\n * The type remains the same after tapping.\n *\n * @param tap A function that performs a side effect\n * @returns A RouteBuilder with the same type\n * @example\n * // Log the current data\n * .tap((exchange) => console.log('Processing:', exchange.body))\n *\n * // Send metrics\n * .tap((exchange) => {\n * metrics.increment('items_processed');\n * metrics.gauge('item_size', JSON.stringify(exchange.body).length);\n * })\n */\n tap(tap: Tap<Current> | CallableTap<Current>): RouteBuilder<Current> {\n this.addStep(new TapStep<Current>(tap));\n return this.withType<Current>();\n }\n\n /**\n * Filter data based on a predicate function.\n * Exchanges that don't match the predicate will be dropped.\n *\n * @param filter A function that returns true to keep the exchange, false to drop it\n * @returns A RouteBuilder with the same type\n * @example\n * // Keep only numbers greater than 10\n * .filter((num) => num > 10)\n *\n * // Filter based on a complex condition\n * .filter((user) => user.age >= 18 && user.status === 'active')\n */\n filter(\n filter: Filter<Current> | CallableFilter<Current>,\n ): RouteBuilder<Current> {\n this.addStep(new FilterStep<Current>(filter));\n return this.withType<Current>();\n }\n\n /**\n * Validate data against a schema.\n * Throws an error if validation fails.\n *\n * @param schema A JSON schema to validate against\n * @returns A RouteBuilder with the same type\n * @example\n * // Validate with JSON schema\n * .validate({\n * type: 'object',\n * properties: {\n * name: { type: 'string' },\n * age: { type: 'number', minimum: 0 }\n * },\n * required: ['name', 'age']\n * })\n */\n validate(schema: StandardSchemaV1): RouteBuilder<Current> {\n this.addStep(new ValidateStep(schema));\n return this.withType<Current>();\n }\n\n /**\n * Enrich the current data with additional information.\n * This is useful for adding context or fetching related data.\n *\n * @template R The resulting type after enrichment (defaults to Current if not specified)\n * @param enricher Function that returns additional data to be merged\n * @param aggregator Optional function to control how data is combined\n * @returns A RouteBuilder with the combined type\n * @example\n * // Add user details from an API\n * .enrich<User & { profile: Profile }>(async (user) => {\n * const details = await fetchUserDetails(user.id);\n * return details;\n * })\n *\n * // Custom aggregation strategy\n * .enrich<CustomType>(\n * async (exchange) => ({ extraData: \"value\" }),\n * (original, enrichmentData) => ({\n * ...original,\n * body: customMergeFunction(original.body, enrichmentData)\n * })\n * )\n */\n enrich<R = Current>(\n enricher:\n | Enricher<Current, Partial<R>>\n | CallableEnricher<Current, Partial<R>>,\n aggregator?: EnrichAggregator<Current, Partial<R>>,\n ): RouteBuilder<R> {\n this.addStep(new EnrichStep(enricher, aggregator));\n return this.withType<R>();\n }\n\n /**\n * Finalize the route definition and return it.\n * This method should be called after all steps have been defined.\n *\n * @returns An array of RouteDefinition objects\n * @example\n * // Define a complete route and build it\n * const route = craft()\n * .from<string[]>(source)\n * .split()\n * .process((exchange) => ({ ...exchange, body: exchange.body.toUpperCase() }))\n * .to(destination)\n *\n * // Add the route to a context\n * context()\n * .routes(route)\n * .build();\n */\n build(): RouteDefinition[] {\n logger.debug(`Building ${this.routes.length} routes`);\n return this.routes;\n }\n}\n","import { type Source } from \"../operations/from\";\nimport { type Exchange, type ExchangeHeaders } from \"../exchange\";\nimport { CraftContext } from \"../context\";\n\nexport class SimpleAdapter<T = unknown> implements Source<T> {\n readonly adapterId = \"routecraft.adapter.simple\";\n\n constructor(private producer: () => T | Promise<T>) {}\n\n async subscribe(\n context: CraftContext,\n handler: (message: T, headers?: ExchangeHeaders) => Promise<Exchange>,\n abortController: AbortController,\n ): Promise<void> {\n context.logger.info(\"Producing messages\");\n let result;\n try {\n result = await this.producer();\n } catch (error) {\n context.logger.error(error, \"Failed to produce messages\");\n abortController.abort();\n throw error;\n }\n\n if (Array.isArray(result)) {\n context.logger.debug(`Processing array of ${result.length} messages`);\n try {\n await Promise.all(\n result.map((item) =>\n handler(item).catch((error) => {\n context.logger.error(error, \"Failed to process message\");\n throw error;\n }),\n ),\n );\n } finally {\n context.logger.debug(\"Finished processing array of messages\");\n abortController.abort();\n }\n } else {\n context.logger.debug(\"Processing single message\");\n try {\n await handler(result);\n } catch (error) {\n context.logger.error(error, \"Failed to process message\");\n throw error;\n } finally {\n context.logger.debug(\"Finished processing single message\");\n abortController.abort();\n }\n }\n }\n}\n","import { type Destination } from \"../operations/to\";\nimport { type Exchange } from \"../exchange\";\n\nexport class NoopAdapter<T = unknown> implements Destination<T> {\n readonly adapterId = \"routecraft.adapter.noop\";\n\n send(exchange: Exchange<T>): Promise<void> {\n exchange.logger.info({ id: exchange.id }, \"Discarding message\");\n return Promise.resolve();\n }\n}\n","import { type Destination } from \"../operations/to\";\nimport { type Tap } from \"../operations/tap\";\nimport { type Exchange } from \"../exchange\";\n\nexport class LogAdapter<T = unknown> implements Destination<T>, Tap<T> {\n readonly adapterId = \"routecraft.adapter.log\";\n\n constructor(\n private readonly formatter?: (exchange: Exchange<T>) => unknown,\n ) {}\n\n send(exchange: Exchange<T>): Promise<void> {\n // eslint-disable-next-line no-console\n console.log(\n this.formatter ? this.formatter(exchange) : this.baseExchange(exchange),\n );\n return Promise.resolve();\n }\n\n tap(exchange: Exchange<T>): Promise<void> {\n // eslint-disable-next-line no-console\n console.log(\n this.formatter ? this.formatter(exchange) : this.baseExchange(exchange),\n );\n return Promise.resolve();\n }\n\n private baseExchange(exchange: Exchange<T>): Partial<Exchange<T>> {\n const { id, body, headers } = exchange;\n return { id, body, headers };\n }\n}\n","import {\n type ExchangeHeaders,\n type Exchange,\n type DefaultExchange,\n} from \"../exchange\";\nimport { type Source } from \"../operations/from\";\nimport { CraftContext, type MergedOptions } from \"../context\";\nimport { type Destination } from \"../operations/to\";\n\nexport type DirectChannelType<T extends DirectChannel> = new (\n endpoint: string,\n) => T;\n\n/**\n * DirectChannel interface for synchronous inter-route communication.\n *\n * Implements Apache Camel's direct: component semantics:\n * - Single consumer per endpoint (last subscriber wins)\n * - Synchronous blocking behavior (sender waits for response)\n * - Point-to-point messaging (not pub/sub)\n */\nexport interface DirectChannel<T = unknown> {\n send(endpoint: string, message: T): Promise<T>;\n subscribe(\n context: CraftContext,\n endpoint: string,\n handler: (message: T) => Promise<T>,\n ): Promise<void>;\n unsubscribe(context: CraftContext, endpoint: string): Promise<void>;\n}\n\nexport interface DirectAdapterOptions {\n channelType?: DirectChannelType<DirectChannel>;\n}\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [DirectAdapter.ADAPTER_DIRECT_STORE]: Map<string, DirectChannel<Exchange>>;\n [DirectAdapter.ADAPTER_DIRECT_OPTIONS]: Partial<DirectAdapterOptions>;\n }\n}\n\nexport class DirectAdapter<T = unknown>\n implements Source<T>, Destination<T>, MergedOptions<DirectAdapterOptions>\n{\n readonly adapterId = \"routecraft.adapter.direct\";\n static readonly ADAPTER_DIRECT_STORE =\n \"routecraft.adapter.direct.store\" as const;\n static readonly ADAPTER_DIRECT_OPTIONS =\n \"routecraft.adapter.direct.options\" as const;\n\n private rawEndpoint: string;\n\n constructor(\n rawEndpoint: string,\n public options: Partial<DirectAdapterOptions> = {},\n ) {\n this.rawEndpoint = rawEndpoint;\n }\n\n private get sanitizedEndpoint(): string {\n return this.rawEndpoint.replace(/[^a-zA-Z0-9]/g, \"-\");\n }\n\n async subscribe(\n context: CraftContext,\n handler: (message: T, headers?: ExchangeHeaders) => Promise<Exchange>,\n abortController: AbortController,\n ): Promise<void> {\n context.logger.info(\n `Setting up subscription for direct endpoint \"${this.sanitizedEndpoint}\"`,\n );\n const channel = this.directChannel(context);\n if (abortController.signal.aborted) {\n context.logger.debug(\n `Subscription aborted for direct endpoint \"${this.sanitizedEndpoint}\"`,\n );\n return;\n }\n\n // Set up the subscription\n await channel.subscribe(\n context,\n this.sanitizedEndpoint,\n async (exchange: Exchange<T>) => {\n // Call handler and return the result\n const result = await handler(exchange.body as T, exchange.headers);\n return result as Exchange<T>;\n },\n );\n\n // Set up cleanup on abort\n abortController.signal.addEventListener(\"abort\", async () => {\n await channel.unsubscribe(context, this.sanitizedEndpoint);\n });\n }\n\n private directChannel(context: CraftContext): DirectChannel<Exchange<T>> {\n let store = context.getStore(DirectAdapter.ADAPTER_DIRECT_STORE) as\n | Map<string, DirectChannel<Exchange<T>>>\n | undefined;\n\n // If the store is not set, create a new one\n if (!store) {\n store = new Map<string, DirectChannel<Exchange<T>>>();\n context.setStore(DirectAdapter.ADAPTER_DIRECT_STORE, store);\n }\n\n // If the endpoint is not in the store, create a new one\n if (!store.has(this.sanitizedEndpoint)) {\n const mergedOptions = this.mergedOptions(context);\n if (mergedOptions.channelType) {\n const MyChannelType = mergedOptions.channelType;\n store.set(\n this.sanitizedEndpoint,\n new MyChannelType(this.rawEndpoint) as DirectChannel<Exchange<T>>,\n );\n } else {\n // Fallback to a default in-memory implementation\n store.set(\n this.sanitizedEndpoint,\n new InMemoryDirectChannel<Exchange<T>>(),\n );\n }\n }\n\n return store.get(this.sanitizedEndpoint) as DirectChannel<Exchange<T>>;\n }\n\n async send(exchange: Exchange<T>): Promise<void> {\n // Cast exchange to require the context\n const defaultExchange = exchange as DefaultExchange<T>;\n defaultExchange.logger.debug(\n `Preparing to send message to direct endpoint \"${this.sanitizedEndpoint}\"`,\n );\n const channel = this.directChannel(defaultExchange.context);\n\n // Send and wait for result - this is synchronous blocking behavior\n const result = await channel.send(this.sanitizedEndpoint, defaultExchange);\n\n // Update the original exchange with the result\n if (result && result !== defaultExchange) {\n defaultExchange.body = result.body;\n // Note: headers are readonly, so we can't update them directly\n // The direct adapter maintains the original exchange structure\n }\n }\n\n mergedOptions(context: CraftContext): DirectAdapterOptions {\n const store = context.getStore(DirectAdapter.ADAPTER_DIRECT_OPTIONS) as\n | Partial<DirectAdapterOptions>\n | undefined;\n return {\n ...store,\n ...this.options,\n };\n }\n}\n\n/**\n * Default in-memory implementation of DirectChannel.\n *\n * IMPORTANT: This implements single-consumer semantics where only the\n * last route to subscribe to an endpoint will receive messages.\n * Previous subscribers are automatically replaced (last one wins).\n */\nclass InMemoryDirectChannel<T> implements DirectChannel<T> {\n private handler: ((message: T) => Promise<T>) | null = null;\n\n async send(_endpoint: string, message: T): Promise<T> {\n if (this.handler) {\n // Synchronous behavior - single consumer gets the message and we wait for result\n return await this.handler(message);\n }\n return message; // If no handler, return original message\n }\n\n async subscribe(\n _context: CraftContext,\n _endpoint: string,\n handler: (message: T) => Promise<T>,\n ): Promise<void> {\n // Single consumer - only one handler allowed (Apache Camel direct behavior)\n // This replaces any existing handler (last subscriber wins)\n this.handler = handler;\n }\n\n async unsubscribe(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _context: CraftContext,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _endpoint: string,\n ): Promise<void> {\n this.handler = null;\n }\n}\n","import { HeadersKeys, type Exchange, type ExchangeHeaders } from \"../exchange\";\nimport { type Source } from \"../operations/from\";\nimport { CraftContext } from \"../context\";\n\nexport interface TimerOptions {\n /**\n * Time between executions in milliseconds\n * @default 1000\n */\n intervalMs?: number;\n\n /**\n * Delay before the first execution in milliseconds\n * @default 0\n */\n delayMs?: number;\n\n /**\n * Number of times to trigger before stopping\n * @default Infinity\n */\n repeatCount?: number;\n\n /**\n * Ensures execution happens at exact intervals (ignoring execution time)\n * @default false\n */\n fixedRate?: boolean;\n\n /**\n * Executes at an exact time of day (ISO HH:mm:ss)\n * @default null\n */\n exactTime?: string;\n\n /**\n * Allows custom date formats for execution times\n * @default null\n */\n timePattern?: string;\n\n /**\n * Adds random delay to prevent synchronized execution spikes\n * @default 0\n */\n jitterMs?: number;\n}\n\nexport class TimerAdapter implements Source<undefined> {\n readonly adapterId = \"routecraft.adapter.timer\";\n constructor(private options?: TimerOptions) {}\n\n subscribe(\n _context: CraftContext,\n handler: (\n message: undefined,\n headers?: ExchangeHeaders,\n ) => Promise<Exchange>,\n abortController: AbortController,\n ): Promise<void> {\n const {\n intervalMs = 1000,\n delayMs = 0,\n repeatCount = Infinity,\n fixedRate = false,\n exactTime,\n jitterMs = 0,\n } = this.options || {};\n\n // Determine the start time\n let baseTime: number;\n if (exactTime) {\n // exactTime should be in the format \"HH:mm:ss\"\n const now = new Date();\n const [hour, minute, second] = exactTime.split(\":\").map(Number);\n // Create a Date for today with the provided exact time\n const scheduled = new Date(now);\n scheduled.setHours(hour, minute, second, 0);\n // If the scheduled time already passed today, schedule for tomorrow\n if (scheduled.getTime() <= now.getTime()) {\n scheduled.setDate(scheduled.getDate() + 1);\n }\n baseTime = scheduled.getTime();\n } else {\n baseTime = Date.now() + delayMs;\n }\n\n // Create and return an async promise that runs the timer loop\n return new Promise<void>((resolve) => {\n let count = 0;\n\n const runTimer = async () => {\n while (count < repeatCount && !abortController.signal.aborted) {\n let scheduledTime: number;\n if (fixedRate) {\n if (exactTime) {\n // For exact time scheduling with fixedRate, fire once per day.\n scheduledTime = baseTime + count * 24 * 60 * 60 * 1000;\n } else {\n scheduledTime = baseTime + count * intervalMs;\n }\n } else {\n // Non-fixedRate: the first run uses baseTime; subsequent runs trigger delay after the previous run.\n if (count === 0) {\n scheduledTime = baseTime;\n } else {\n scheduledTime = Date.now() + intervalMs;\n }\n }\n\n // Calculate waiting time until scheduled execution\n const now = Date.now();\n let waitTime = scheduledTime - now;\n if (waitTime < 0) {\n waitTime = 0;\n }\n if (jitterMs > 0) {\n const jitter = Math.floor(Math.random() * jitterMs);\n waitTime += jitter;\n }\n\n await new Promise((r) => setTimeout(r, waitTime));\n if (abortController.signal.aborted) break;\n\n const firedTime = new Date();\n count++;\n\n // Compute the next scheduled time for header information\n let nextScheduledTime: number;\n if (fixedRate) {\n if (exactTime) {\n nextScheduledTime = baseTime + count * 24 * 60 * 60 * 1000;\n } else {\n nextScheduledTime = baseTime + count * intervalMs;\n }\n } else {\n nextScheduledTime = Date.now() + intervalMs;\n }\n\n // Prepare timer-based headers\n const headers: ExchangeHeaders = {\n [HeadersKeys.TIMER_TIME]: firedTime.toISOString(),\n [HeadersKeys.TIMER_FIRED_TIME]: firedTime.toISOString(),\n [HeadersKeys.TIMER_PERIOD_MS]: exactTime\n ? 24 * 60 * 60 * 1000\n : intervalMs,\n [HeadersKeys.TIMER_COUNTER]: count,\n [HeadersKeys.TIMER_NEXT_RUN]: new Date(\n nextScheduledTime,\n ).toISOString(),\n };\n\n // Trigger the handler for this timer tick.\n await handler(undefined, headers);\n }\n resolve();\n };\n\n runTimer();\n });\n }\n}\n","import { type Destination } from \"../operations/to.ts\";\nimport { type Enricher } from \"../operations/enrich.ts\";\nimport { type Exchange } from \"../exchange.ts\";\n\nexport type HttpMethod =\n | \"GET\"\n | \"POST\"\n | \"PUT\"\n | \"PATCH\"\n | \"DELETE\"\n | \"HEAD\"\n | \"OPTIONS\";\n\nexport type QueryParams = Record<string, string | number | boolean>;\n\nexport interface FetchOptions<T = unknown> {\n method?: HttpMethod;\n url: string | ((exchange: Exchange<T>) => string);\n headers?:\n | Record<string, string>\n | ((exchange: Exchange<T>) => Record<string, string>);\n query?: QueryParams | ((exchange: Exchange<T>) => QueryParams);\n body?: unknown | ((exchange: Exchange<T>) => unknown);\n timeoutMs?: number;\n throwOnHttpError?: boolean;\n}\n\nexport type FetchResult<T = string | unknown> = {\n status: number;\n headers: Record<string, string>;\n body: T;\n url: string;\n};\n\n/**\n * FetchAdapter can act as a Processor, Enricher, or Destination.\n * - process: replaces body with FetchResult\n * - enrich: returns FetchResult for aggregation\n * - send: performs request as side effect (ignores body)\n */\nexport class FetchAdapter<T = unknown, R = FetchResult>\n implements Enricher<T, R>, Destination<T>\n{\n readonly adapterId = \"routecraft.adapter.fetch\";\n\n constructor(private readonly options: FetchOptions<T>) {}\n\n async enrich(exchange: Exchange<T>): Promise<R> {\n const result = await this.performFetch(exchange);\n return result as unknown as R;\n }\n\n async send(exchange: Exchange<T>): Promise<void> {\n await this.performFetch(exchange);\n }\n\n private async performFetch(exchange: Exchange<T>): Promise<FetchResult> {\n const method = this.options.method ?? \"GET\";\n const url = this.resolveRequired(this.options.url, exchange);\n const headers = { ...(this.resolve(this.options.headers, exchange) ?? {}) };\n const query = this.resolve(this.options.query, exchange);\n const resolvedBody = this.resolve(this.options.body, exchange);\n const throwOnHttpError = this.options.throwOnHttpError ?? true;\n const timeoutMs = this.options.timeoutMs ?? undefined;\n\n const finalUrl = this.appendQuery(url, query ?? {});\n\n let body: BodyInit | undefined;\n if (resolvedBody !== undefined && resolvedBody !== null) {\n if (\n typeof resolvedBody === \"string\" ||\n resolvedBody instanceof Uint8Array ||\n resolvedBody instanceof ArrayBuffer\n ) {\n body = resolvedBody as BodyInit;\n } else {\n if (!headers[\"Content-Type\"])\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(resolvedBody);\n }\n }\n\n const controller = timeoutMs ? new AbortController() : undefined;\n const timeout = timeoutMs\n ? setTimeout(() => controller!.abort(), timeoutMs)\n : undefined;\n\n try {\n const res = (await globalThis.fetch(finalUrl, {\n method,\n headers,\n body,\n signal: controller?.signal,\n } as RequestInit)) as Response;\n\n if (throwOnHttpError && !res.ok) {\n const text = await res.text();\n throw new Error(`HTTP ${res.status}: ${text}`);\n }\n\n const headersRecord: Record<string, string> = {};\n res.headers.forEach((value, key) => {\n headersRecord[key] = value;\n });\n\n const bodyText = await res.text();\n\n // Auto-parse JSON based on Content-Type\n let parsedBody: string | unknown = bodyText;\n const contentType = headersRecord[\"content-type\"]?.toLowerCase() || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n parsedBody = JSON.parse(bodyText);\n } catch {\n // Parse failed, keep as string\n parsedBody = bodyText;\n }\n }\n\n return {\n status: res.status,\n headers: headersRecord,\n body: parsedBody,\n url: res.url || finalUrl,\n } satisfies FetchResult;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n\n private resolve<V>(\n val: V | ((exchange: Exchange<T>) => V) | undefined,\n exchange: Exchange<T>,\n ): V | undefined {\n if (typeof val === \"function\") {\n return (val as (e: Exchange<T>) => V)(exchange);\n }\n return val as V | undefined;\n }\n\n private resolveRequired<V>(\n val: V | ((exchange: Exchange<T>) => V),\n exchange: Exchange<T>,\n ): V {\n if (typeof val === \"function\") {\n return (val as (e: Exchange<T>) => V)(exchange);\n }\n return val as V;\n }\n\n private appendQuery(url: string, query?: QueryParams): string {\n if (!query || Object.keys(query).length === 0) return url;\n const u = new URL(url, this.base(url));\n for (const [k, v] of Object.entries(query)) {\n u.searchParams.set(k, String(v));\n }\n return u.toString();\n }\n\n private base(url: string): string | undefined {\n try {\n const u = new URL(url);\n return `${u.protocol}//${u.host}`;\n } catch {\n return undefined;\n }\n }\n}\n","import { ContextBuilder, RouteBuilder } from \"./builder.ts\";\nimport { SimpleAdapter } from \"./adapters/simple.ts\";\nimport { NoopAdapter } from \"./adapters/noop.ts\";\nimport { LogAdapter } from \"./adapters/log.ts\";\nimport { DirectAdapter, type DirectAdapterOptions } from \"./adapters/direct.ts\";\nimport { TimerAdapter, type TimerOptions } from \"./adapters/timer.ts\";\nimport { FetchAdapter, type FetchOptions } from \"./adapters/fetch.ts\";\nimport { type Exchange } from \"./exchange.ts\";\n\n/**\n * Create a new context builder.\n *\n * This is the entry point for creating a new application context.\n *\n * @returns A new ContextBuilder instance\n *\n * @example\n * ```typescript\n * // Create and configure a context\n * const ctx = context()\n * .routes(myRoute)\n * .on('contextStarting', () => console.log('Starting...'))\n * .build();\n *\n * // Start processing\n * await ctx.start();\n * ```\n */\nexport function context(): ContextBuilder {\n return new ContextBuilder();\n}\n\n/**\n * Create a new route builder.\n *\n * This is the entry point for defining routes in a fluent way.\n *\n * @returns A new RouteBuilder instance\n *\n * @example\n * ```typescript\n * // Define a route that processes data\n * const myRoute = craft()\n * .from(simple(\"Hello, World!\"))\n * .transform(data => data.toUpperCase())\n * .to(log())\n * ```\n */\nexport function craft(): RouteBuilder {\n return new RouteBuilder();\n}\n\n/**\n * Create a simple adapter that produces static or dynamically generated data.\n *\n * This adapter can be used as a source in a route to provide data.\n *\n * @template T The type of data to produce\n * @param producer A static value or function that produces a value\n * @returns A SimpleAdapter instance\n *\n * @example\n * ```typescript\n * // Static data\n * craft().from(simple(\"Hello, World!\"))\n *\n * // Dynamic data from a function\n * craft().from(simple(() => new Date().toISOString()))\n *\n * // Dynamic data from an async function\n * craft().from(simple(async () => {\n * const response = await fetch('https://api.example.com/data');\n * return response.json();\n * }))\n * ```\n */\nexport function simple<T = unknown>(\n producer: (() => T | Promise<T>) | T,\n): SimpleAdapter<T> {\n return new SimpleAdapter<T>(\n typeof producer === \"function\"\n ? (producer as () => T | Promise<T>)\n : () => producer,\n );\n}\n\n/**\n * Create a no-operation adapter that does nothing.\n *\n * This can be useful for testing or as a placeholder.\n *\n * @template T The type of data this adapter processes\n * @returns A NoopAdapter instance\n *\n * @example\n * ```typescript\n * // Send to a no-op destination during development\n * craft()\n * .from(source)\n * .to(process.env.PROD ? realDestination() : noop())\n * ```\n */\nexport function noop<T = unknown>(): NoopAdapter<T> {\n return new NoopAdapter<T>();\n}\n\n/**\n * Create a logging adapter that logs messages to the console.\n *\n * This is useful for debugging and monitoring data flow in routes.\n *\n * @template T The type of data this adapter processes\n * @param formatter Optional function that takes an exchange and returns the value to log.\n * If not provided, logs exchange ID, body, and headers.\n * @returns A LogAdapter instance\n *\n * @example\n * ```typescript\n * // Log data at different points in the route\n * craft()\n * .from(source)\n * .tap(log()) // Log input data\n * .transform(data => processData(data))\n * .tap(log()) // Log transformed data\n * .to(destination)\n *\n * // Log with custom formatter\n * craft()\n * .from(source)\n * .tap(log((ex) => `Exchange with id: ${ex.id}`))\n * .tap(log((ex) => `Body: ${JSON.stringify(ex.body)}`))\n * .to(destination)\n * ```\n */\nexport function log<T = unknown>(\n formatter?: (exchange: Exchange<T>) => unknown,\n): LogAdapter<T> {\n return new LogAdapter<T>(formatter);\n}\n\n/**\n * Create a direct adapter for synchronous inter-route communication.\n *\n * Direct adapters allow routes to communicate with each other\n * synchronously with single consumer semantics (Apache Camel style).\n *\n * @template T The type of data this adapter processes\n * @param endpoint The name of the direct endpoint to use\n * @param options Optional configuration for the direct adapter\n * @returns A DirectAdapter instance\n *\n * @example\n * ```typescript\n * // Producer route sends to a direct endpoint\n * const producerRoute = craft()\n * .from(source)\n * .to(direct('my-endpoint'))\n *\n * // Consumer route reads from the same endpoint\n * const consumerRoute = craft()\n * .from(direct('my-endpoint'))\n * .to(destination)\n *\n * // Register both routes with the context\n * context().routes([producerRoute, consumerRoute]);\n * ```\n */\nexport function direct<T = unknown>(\n endpoint: string,\n options?: Partial<DirectAdapterOptions>,\n): DirectAdapter<T> {\n return new DirectAdapter<T>(endpoint, options);\n}\n\n/**\n * Create a timer adapter that produces messages at regular intervals.\n *\n * This adapter can be used as a source in a route to trigger processing\n * on a schedule.\n *\n * @param options Configuration for the timer\n * @returns A TimerAdapter instance\n *\n * @example\n * ```typescript\n * // Run every 5 seconds\n * craft()\n * .from(timer({ intervalMs: 5000 }))\n * .to(periodicTask)\n *\n * // Run 10 times, once per second\n * craft()\n * .from(timer({ intervalMs: 1000, repeatCount: 10 }))\n * .to(batchTask)\n * ```\n */\nexport function timer(options?: TimerOptions): TimerAdapter {\n return new TimerAdapter(options);\n}\n\n/**\n * Create an HTTP client adapter for making requests.\n * Acts as processor, enricher, or destination depending on usage site.\n */\nexport function fetch<T = unknown, R = unknown>(\n options: FetchOptions<T>,\n): FetchAdapter<T, R> {\n return new FetchAdapter<T, R>(options);\n}\n"]}
|