@stackwright-services/runtime 0.2.0 → 0.4.0
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/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -856,6 +856,7 @@ var OpenApiDataSourceProvider = class {
|
|
|
856
856
|
this.config = config;
|
|
857
857
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
858
858
|
}
|
|
859
|
+
config;
|
|
859
860
|
name = "openapi";
|
|
860
861
|
sourcesMap;
|
|
861
862
|
listSources() {
|
|
@@ -903,6 +904,7 @@ var PulseDataSourceProvider = class {
|
|
|
903
904
|
this.config = config;
|
|
904
905
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
905
906
|
}
|
|
907
|
+
config;
|
|
906
908
|
name = "pulse";
|
|
907
909
|
sourcesMap;
|
|
908
910
|
listSources() {
|
|
@@ -950,6 +952,7 @@ var StreamingDataSourceProvider = class {
|
|
|
950
952
|
this.config = config;
|
|
951
953
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
952
954
|
}
|
|
955
|
+
config;
|
|
953
956
|
name = "streaming";
|
|
954
957
|
sourcesMap;
|
|
955
958
|
listSources() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/messaging/sqs-sns.ts","../src/index.ts","../src/triggers/http.ts","../src/triggers/event.ts","../src/triggers/schedule.ts","../src/triggers/queue.ts","../src/observability/noop.ts","../src/observability/otel.ts","../src/observability/factory.ts","../src/observability/audit-noop.ts","../src/observability/audit-console.ts","../src/observability/audit-factory.ts","../src/observability/audit-hash.ts","../src/messaging/noop.ts","../src/messaging/index.ts","../src/messaging/factory.ts","../src/notifications/noop.ts","../src/notifications/factory.ts","../src/auth/noop.ts","../src/auth/factory.ts","../src/datasource/noop.ts","../src/datasource/openapi-adapter.ts","../src/datasource/pulse-adapter.ts","../src/datasource/streaming-adapter.ts","../src/datasource/factory.ts","../src/datasource/scan.ts","../src/prebuild/register.ts"],"sourcesContent":["/**\n * SQS/SNS MessageBusProvider — the first concrete adapter.\n *\n * Architecture:\n * - PUBLISH: Uses SNS Publish to deliver messages to a topic ARN.\n * - SUBSCRIBE: Uses SQS long-polling (ReceiveMessage) to consume from a queue URL.\n *\n * Topic/queue resolution:\n * - Logical topic name → SNS Topic ARN via config map or env var:\n * BUS_TOPIC_{UPPER_SNAKE_NAME}_ARN (e.g. BUS_TOPIC_EQUIPMENT_STATUS_ARN)\n * - Logical queue name → SQS Queue URL via config map or env var:\n * BUS_QUEUE_{UPPER_SNAKE_NAME}_URL (e.g. BUS_QUEUE_EQUIPMENT_STATUS_URL)\n *\n * Trace propagation:\n * - traceContext serialized as SNS/SQS MessageAttributes (StringValue)\n * - metadata fields (timestamp, source, correlationId) also as MessageAttributes\n *\n * Graceful shutdown:\n * - Each subscription has a polling loop with an `active` flag\n * - stop()/unsubscribe() sets active=false, polling loop exits after current\n * ReceiveMessage returns\n *\n * AWS credentials:\n * - Uses standard AWS SDK v3 credential chain (env vars, instance profile, etc.)\n * - NO credential handling in this adapter\n *\n * Design note: This is a thin wrapper. No retry logic beyond SDK defaults,\n * no DLQ support, no batch processing. Production hardening is a separate bead.\n */\n\nimport {\n SNSClient,\n PublishCommand,\n type PublishCommandInput,\n type MessageAttributeValue as SNSMessageAttributeValue,\n} from '@aws-sdk/client-sns';\nimport {\n SQSClient,\n ReceiveMessageCommand,\n DeleteMessageCommand,\n type Message,\n type MessageAttributeValue as SQSMessageAttributeValue,\n} from '@aws-sdk/client-sqs';\nimport type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:messaging';\n\nexport interface SqsSnsConfig {\n /** AWS region (defaults to AWS_REGION env var or 'us-east-1') */\n region?: string;\n /** SNS Topic ARN mapping: logical name → ARN. Overrides env vars. */\n topicArns?: Record<string, string>;\n /** SQS Queue URL mapping: logical name → URL. Overrides env vars. */\n queueUrls?: Record<string, string>;\n /** SQS long-poll wait time in seconds (default: 20, max for long-polling) */\n waitTimeSeconds?: number;\n /** Max messages per ReceiveMessage call (default: 10) */\n maxMessages?: number;\n /**\n * Minimum delay between poll cycles in ms (default: 100).\n * Prevents tight-spinning when waitTimeSeconds is low or the queue is\n * empty and the SDK resolves instantly. In production with\n * waitTimeSeconds=20 the 100ms gap is negligible.\n */\n pollIntervalMs?: number;\n /** Optional SNS client (for testing/DI) */\n snsClient?: SNSClient;\n /** Optional SQS client (for testing/DI) */\n sqsClient?: SQSClient;\n}\n\n/** Convert a logical topic name to UPPER_SNAKE_CASE for env var lookup. */\nexport function toUpperSnake(name: string): string {\n return name.replace(/[-.]/g, '_').toUpperCase();\n}\n\ninterface PollingState {\n active: boolean;\n}\n\nexport class SqsSnsMessageBusProvider implements MessageBusProvider {\n private readonly snsClient: SNSClient;\n private readonly sqsClient: SQSClient;\n private readonly topicArns: Record<string, string>;\n private readonly queueUrls: Record<string, string>;\n private readonly waitTimeSeconds: number;\n private readonly maxMessages: number;\n private readonly pollIntervalMs: number;\n private readonly pollingStates = new Map<string, PollingState>();\n\n constructor(config: SqsSnsConfig = {}) {\n const region = config.region ?? process.env['AWS_REGION'] ?? 'us-east-1';\n this.snsClient = config.snsClient ?? new SNSClient({ region });\n this.sqsClient = config.sqsClient ?? new SQSClient({ region });\n this.topicArns = config.topicArns ?? {};\n this.queueUrls = config.queueUrls ?? {};\n this.waitTimeSeconds = config.waitTimeSeconds ?? 20;\n this.maxMessages = config.maxMessages ?? 10;\n this.pollIntervalMs = config.pollIntervalMs ?? 100;\n }\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const topicArn = this.resolveTopicArn(topic);\n const attributes = this.buildSnsAttributes(message);\n\n const input: PublishCommandInput = {\n TopicArn: topicArn,\n Message: JSON.stringify(message.payload),\n MessageAttributes: attributes,\n };\n\n const response = await this.snsClient.send(new PublishCommand(input));\n const messageId = response.MessageId ?? `sns-${Date.now()}`;\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const queueUrl = this.resolveQueueUrl(topic);\n const id = `sqs-sub-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const state: PollingState = { active: true };\n this.pollingStates.set(id, state);\n\n // Fire-and-forget: polling loop runs in background\n this.poll(queueUrl, handler, state);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const state = this.pollingStates.get(subscription.id);\n if (state) {\n state.active = false;\n this.pollingStates.delete(subscription.id);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private resolveTopicArn(topic: string): string {\n const fromConfig = this.topicArns[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_TOPIC_${toUpperSnake(topic)}_ARN`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SNS Topic ARN found for \"${topic}\". ` +\n `Set config.topicArns[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private resolveQueueUrl(topic: string): string {\n const fromConfig = this.queueUrls[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_QUEUE_${toUpperSnake(topic)}_URL`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SQS Queue URL found for \"${topic}\". ` +\n `Set config.queueUrls[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private buildSnsAttributes(message: BusMessage): Record<string, SNSMessageAttributeValue> {\n const attrs: Record<string, SNSMessageAttributeValue> = {};\n\n // Serialize traceContext fields\n if (message.traceContext) {\n for (const [key, value] of Object.entries(message.traceContext)) {\n attrs[`trace.${key}`] = { DataType: 'String', StringValue: value };\n }\n }\n\n // Serialize metadata fields\n if (message.metadata) {\n const { timestamp, source, correlationId } = message.metadata;\n if (timestamp) {\n attrs['meta.timestamp'] = { DataType: 'String', StringValue: timestamp };\n }\n if (source) {\n attrs['meta.source'] = { DataType: 'String', StringValue: source };\n }\n if (correlationId) {\n attrs['meta.correlationId'] = { DataType: 'String', StringValue: correlationId };\n }\n }\n\n return attrs;\n }\n\n private async poll(\n queueUrl: string,\n handler: MessageHandler,\n state: PollingState,\n ): Promise<void> {\n while (state.active) {\n // Delay between poll cycles to prevent tight-spinning when\n // waitTimeSeconds is low or the mock/SDK resolves instantly.\n await new Promise<void>((resolve) => setTimeout(resolve, this.pollIntervalMs));\n if (!state.active) break;\n\n try {\n const response = await this.sqsClient.send(\n new ReceiveMessageCommand({\n QueueUrl: queueUrl,\n WaitTimeSeconds: this.waitTimeSeconds,\n MaxNumberOfMessages: this.maxMessages,\n MessageAttributeNames: ['All'],\n }),\n );\n\n for (const sqsMessage of response.Messages ?? []) {\n if (!state.active) break;\n\n const busMessage = this.parseSqsMessage(sqsMessage);\n try {\n await handler(busMessage);\n } catch (handlerError) {\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'handler_error',\n error: handlerError instanceof Error ? handlerError.message : String(handlerError),\n queueUrl,\n }),\n );\n // Continue processing — don't crash the polling loop\n continue;\n }\n\n // Delete only after successful handler invocation\n if (sqsMessage.ReceiptHandle) {\n await this.sqsClient.send(\n new DeleteMessageCommand({\n QueueUrl: queueUrl,\n ReceiptHandle: sqsMessage.ReceiptHandle,\n }),\n );\n }\n }\n } catch (pollError) {\n // Log polling errors but keep the loop alive\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'poll_error',\n error: pollError instanceof Error ? pollError.message : String(pollError),\n queueUrl,\n }),\n );\n }\n }\n }\n\n private parseSqsMessage(sqsMessage: Message): BusMessage {\n const payload = sqsMessage.Body ? JSON.parse(sqsMessage.Body) : null;\n const traceContext = this.extractTraceContext(sqsMessage.MessageAttributes);\n const metadata = this.extractMetadata(sqsMessage.MessageAttributes);\n\n return {\n payload,\n ...(traceContext !== undefined && { traceContext }),\n ...(metadata !== undefined && { metadata }),\n };\n }\n\n private extractTraceContext(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): Record<string, string> | undefined {\n if (!attrs) return undefined;\n\n const trace: Record<string, string> = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith('trace.') && value.StringValue) {\n trace[key.slice('trace.'.length)] = value.StringValue;\n }\n }\n\n return Object.keys(trace).length > 0 ? trace : undefined;\n }\n\n private extractMetadata(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): BusMessage['metadata'] {\n if (!attrs) return undefined;\n\n const timestamp = attrs['meta.timestamp']?.StringValue;\n const source = attrs['meta.source']?.StringValue;\n const correlationId = attrs['meta.correlationId']?.StringValue;\n\n if (!timestamp && !source && !correlationId) return undefined;\n\n return {\n ...(timestamp && { timestamp }),\n ...(source && { source }),\n ...(correlationId && { correlationId }),\n };\n }\n}\n","// @stackwright-services/runtime\n// Runtime layer for Stackwright Services -- Hono HTTP server, trigger adapters, observability.\n\nexport {\n createHttpTrigger,\n type HttpTriggerOptions,\n type ServiceError,\n type TriggerAdapter,\n EventTriggerAdapter,\n type EventTriggerOptions,\n ScheduleTriggerAdapter,\n type ScheduleTriggerOptions,\n QueueTriggerAdapter,\n type QueueTriggerOptions,\n} from './triggers';\n\nexport {\n type ObservabilityProvider,\n type SpanHandle,\n NoopObservabilityProvider,\n noopProvider,\n OtelObservabilityProvider,\n createObservabilityProvider,\n type AuditEvent,\n type AuditProvider,\n NoopAuditProvider,\n noopAuditProvider,\n ConsoleAuditProvider,\n createAuditProvider,\n auditHash,\n} from './observability';\n\nexport {\n type MessageBusProvider,\n type BusMessage,\n type MessageMetadata,\n type PublishResult,\n type MessageHandler,\n type Subscription,\n InMemoryMessageBusProvider,\n inMemoryBusProvider,\n SqsSnsMessageBusProvider,\n type SqsSnsConfig,\n createMessageBusProvider,\n} from './messaging';\n\nexport {\n type NotificationProvider,\n type NotificationMessage,\n type NotificationMetadata,\n type NotificationChannel,\n type SendResult,\n InMemoryNotificationProvider,\n inMemoryNotificationProvider,\n createNotificationProvider,\n} from './notifications';\n\nexport {\n type AuthProvider,\n type AuthClaims,\n type TokenValidationResult,\n NoopAuthProvider,\n noopAuthProvider,\n createAuthProvider,\n type AuthProviderType,\n} from './auth';\n\nexport {\n type DataSourceProvider,\n type DataSourceDescriptor,\n type DataSourceResult,\n type DataSourceScanResult,\n NoopDataSourceProvider,\n noopDataSourceProvider,\n createDataSourceProvider,\n scanDataSources,\n OpenApiDataSourceProvider,\n createOpenApiDataSourceProvider,\n listOpenApiDataSources,\n type OpenApiAdapterConfig,\n type OpenApiSourceRegistration,\n type OpenApiOperationHandler,\n PulseDataSourceProvider,\n createPulseDataSourceProvider,\n listPulseDataSources,\n type PulseAdapterConfig,\n type PulseSourceRegistration,\n type PulseOperationHandler,\n} from './datasource';\n\nexport {\n registerServices,\n type PrebuildRegistration,\n type TriggerTypeDescriptor,\n type CapabilityDescriptor,\n type DataSourceDescriptorEntry,\n} from './prebuild';\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { HttpTrigger } from '@stackwright-services/types';\nimport { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport type { z } from 'zod';\n\n/**\n * Options for creating an HTTP trigger runtime.\n */\nexport interface HttpTriggerOptions {\n /** The HTTP trigger configuration from the flow */\n trigger: HttpTrigger;\n /** Flow handler function */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional input validation schema */\n inputSchema?: z.ZodType;\n /** Optional output validation schema */\n outputSchema?: z.ZodType;\n}\n\n/**\n * Typed error response for consistent error handling.\n */\nexport interface ServiceError {\n error: string;\n code: string;\n details?: unknown;\n}\n\n/**\n * Create a Hono app for an HTTP trigger.\n *\n * This is the runtime entry point for HTTP-triggered flows.\n * The same code works on:\n * - Node.js (via @hono/node-server)\n * - AWS Lambda (via Lambda Web Adapter)\n * - Edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport function createHttpTrigger(options: HttpTriggerOptions): Hono {\n const { trigger, handler, inputSchema, outputSchema } = options;\n const app = new Hono();\n\n // Health check\n app.get('/health', (c) => c.json({ status: 'ok', trigger: 'http' }));\n\n // Register the flow route\n const method = trigger.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n\n app[method](trigger.path, async (c: Context) => {\n // Extract input based on method\n let input: unknown;\n if (trigger.method === 'GET') {\n input = Object.fromEntries(new URL(c.req.url).searchParams);\n } else {\n try {\n input = await c.req.json();\n } catch {\n return c.json<ServiceError>(\n { error: 'Invalid JSON body', code: 'INVALID_REQUEST_BODY' },\n 400,\n );\n }\n }\n\n // Validate input if schema provided\n if (inputSchema) {\n const result = inputSchema.safeParse(input);\n if (!result.success) {\n return c.json<ServiceError>(\n {\n error: 'Input validation failed',\n code: 'VALIDATION_ERROR',\n details: result.error.issues,\n },\n 400,\n );\n }\n input = result.data;\n }\n\n // Create context\n const context: CapabilityContext = {\n traceId: c.req.header('x-trace-id') ?? c.req.header('x-request-id') ?? crypto.randomUUID(),\n logger: createLogger(),\n };\n\n // Execute flow\n try {\n const result = await handler(input, context);\n\n // Validate output if schema provided\n if (outputSchema) {\n const outputResult = outputSchema.safeParse(result);\n if (!outputResult.success) {\n return c.json<ServiceError>(\n { error: 'Output validation failed', code: 'OUTPUT_VALIDATION_ERROR' },\n 500,\n );\n }\n return c.json(outputResult.data);\n }\n\n return c.json(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return c.json<ServiceError>({ error: message, code: 'FLOW_EXECUTION_ERROR' }, 500);\n }\n });\n\n return app;\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { EventTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating an event trigger adapter.\n */\nexport interface EventTriggerOptions {\n /** The event trigger configuration from the flow */\n trigger: EventTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * EventTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class EventTriggerAdapter implements TriggerAdapter {\n readonly type = 'event';\n readonly topic: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: EventTriggerOptions) {\n this.topic = options.trigger.source.replace(/^bus:/, '');\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.topic, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Event payload validation failed', {\n topic: this.topic,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Event handler failed', {\n topic: this.topic,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { ScheduleTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a schedule trigger adapter.\n */\nexport interface ScheduleTriggerOptions {\n /** The schedule trigger configuration from the flow */\n trigger: ScheduleTrigger;\n /** Flow handler function invoked on each tick */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation */\n inputSchema?: z.ZodType;\n /**\n * Override interval in milliseconds for local dev / testing.\n * When not provided, defaults to 60_000ms and logs a warning that\n * cron parsing is not built-in. In production, scheduling is handled\n * by infrastructure (EventBridge, CronJob on K8s, etc.).\n */\n intervalMs?: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 60_000;\n\n/**\n * ScheduleTriggerAdapter — local-dev / test scheduler that fires the flow\n * handler on a fixed interval.\n *\n * NOT a production cron implementation. In production the cron expression\n * is consumed by infrastructure (EventBridge rules, K8s CronJobs, etc.)\n * and this adapter is not used.\n *\n * Handler errors are caught and logged — the scheduler never crashes.\n */\nexport class ScheduleTriggerAdapter implements TriggerAdapter {\n readonly type = 'schedule';\n readonly cron: string;\n\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private readonly intervalMs: number;\n private timer: ReturnType<typeof setInterval> | undefined;\n\n constructor(options: ScheduleTriggerOptions) {\n this.cron = options.trigger.cron;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n }\n\n async start(): Promise<void> {\n if (this.intervalMs === DEFAULT_INTERVAL_MS) {\n const logger = createLogger();\n logger.warn('Cron parsing not built-in; using default 60s interval for local dev', {\n cron: this.cron,\n intervalMs: this.intervalMs,\n });\n }\n\n this.timer = setInterval(() => {\n void this.tick();\n }, this.intervalMs);\n }\n\n async stop(): Promise<void> {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }\n\n private async tick(): Promise<void> {\n const traceId = crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler({}, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Schedule handler failed', {\n cron: this.cron,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { QueueTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a queue trigger adapter.\n */\nexport interface QueueTriggerOptions {\n /** The queue trigger configuration from the flow */\n trigger: QueueTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * QueueTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Semantically represents point-to-point delivery (single consumer), unlike\n * the fan-out semantics of EventTriggerAdapter. At the runtime adapter level\n * both use messageBus.subscribe() — the distinction lives in the concrete\n * bus implementation (SQS vs SNS+SQS, competing consumers vs broadcast).\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class QueueTriggerAdapter implements TriggerAdapter {\n readonly type = 'queue';\n readonly queueName: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: QueueTriggerOptions) {\n this.queueName = options.trigger.name;\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.queueName, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Queue payload validation failed', {\n queueName: this.queueName,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Queue handler failed', {\n queueName: this.queueName,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\nconst NOOP_SPAN: SpanHandle = {\n setAttribute: () => {},\n setError: () => {},\n end: () => {},\n};\n\n/**\n * No-op observability provider -- zero runtime cost.\n * Used when OTel is not configured (the default).\n * All methods are no-ops that return immediately.\n */\nexport class NoopObservabilityProvider implements ObservabilityProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n return NOOP_SPAN;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n // Intentionally empty -- zero cost when disabled\n }\n}\n\n/** Singleton no-op provider */\nexport const noopProvider = new NoopObservabilityProvider();\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\n/**\n * OpenTelemetry-compatible observability provider.\n *\n * In Phase 1, this uses structured console logging with span semantics.\n * In Phase 2+, this wraps @opentelemetry/api (trace + metrics).\n *\n * The interface is stable -- upgrading to real OTel is a drop-in replacement.\n */\nexport class OtelObservabilityProvider implements ObservabilityProvider {\n private readonly serviceName: string;\n\n constructor(serviceName: string = 'stackwright-service') {\n this.serviceName = serviceName;\n }\n\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n const spanId = crypto.randomUUID().slice(0, 16);\n const startTime = Date.now();\n\n console.info(\n JSON.stringify({\n type: 'span_start',\n spanId,\n name,\n service: this.serviceName,\n attributes,\n timestamp: new Date().toISOString(),\n }),\n );\n\n const spanAttributes: Record<string, string | number | boolean> = { ...attributes };\n\n return {\n setAttribute(key: string, value: string | number | boolean): void {\n spanAttributes[key] = value;\n },\n setError(error: Error): void {\n spanAttributes['error'] = true;\n spanAttributes['error.message'] = error.message;\n console.error(\n JSON.stringify({\n type: 'span_error',\n spanId,\n name,\n error: error.message,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n end(): void {\n const duration = Date.now() - startTime;\n console.info(\n JSON.stringify({\n type: 'span_end',\n spanId,\n name,\n duration,\n attributes: spanAttributes,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n };\n }\n\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n console.info(\n JSON.stringify({\n type: 'metric',\n name,\n value,\n tags,\n service: this.serviceName,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n}\n","import type { ObservabilityProvider } from './provider';\nimport { noopProvider } from './noop';\nimport { OtelObservabilityProvider } from './otel';\n\n/**\n * Create an observability provider based on environment configuration.\n *\n * - OTEL_ENABLED=true (or \"1\") -> OtelObservabilityProvider\n * - Otherwise -> NoopObservabilityProvider (zero cost)\n *\n * The provider is injected into compiled flow code, not imported.\n * This means zero runtime overhead when observability is disabled.\n */\nexport function createObservabilityProvider(options?: {\n serviceName?: string;\n}): ObservabilityProvider {\n const otelEnabled = process.env['OTEL_ENABLED'];\n\n if (otelEnabled === 'true' || otelEnabled === '1') {\n return new OtelObservabilityProvider(options?.serviceName);\n }\n\n return noopProvider;\n}\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/** No-op audit provider -- zero runtime cost when auditing is disabled */\nexport class NoopAuditProvider implements AuditProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n record(_event: AuditEvent): void {\n // Intentionally empty\n }\n\n async flush(): Promise<void> {\n // Nothing to flush\n }\n}\n\n/** Singleton no-op audit provider */\nexport const noopAuditProvider = new NoopAuditProvider();\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/**\n * Console audit provider -- writes events to stderr as JSON Lines.\n *\n * Works in Lambda (stderr -> CloudWatch), containers (stderr -> log collector),\n * and local dev (stderr -> terminal).\n *\n * Uses stderr to avoid mixing with application stdout.\n */\nexport class ConsoleAuditProvider implements AuditProvider {\n record(event: AuditEvent): void {\n process.stderr.write(JSON.stringify(event) + '\\n');\n }\n\n async flush(): Promise<void> {\n // Console writes are synchronous -- nothing to flush\n }\n}\n","import type { AuditProvider } from './audit';\nimport { noopAuditProvider } from './audit-noop';\nimport { ConsoleAuditProvider } from './audit-console';\n\n/**\n * Create an audit provider based on environment configuration.\n *\n * - STACKWRIGHT_AUDIT=true (or \"1\") -> ConsoleAuditProvider (stderr JSON Lines)\n * - Otherwise -> NoopAuditProvider (zero cost)\n *\n * Defaults to OFF in production, can be enabled with env var.\n */\nexport function createAuditProvider(): AuditProvider {\n const auditEnabled = process.env['STACKWRIGHT_AUDIT'];\n if (auditEnabled === 'true' || auditEnabled === '1') {\n return new ConsoleAuditProvider();\n }\n return noopAuditProvider;\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Compute a truncated SHA-256 hash of a value.\n *\n * Used for audit events -- captures enough to detect \"did the input/output change?\"\n * without storing full payloads (which may be large or contain PII).\n *\n * Returns first 16 hex characters of SHA-256.\n * Deterministic: same input always produces same hash.\n */\nexport function auditHash(value: unknown): string {\n const serialized = JSON.stringify(value, (_key, val) => {\n // Handle non-serializable types gracefully\n if (typeof val === 'bigint') return val.toString();\n if (val instanceof Error) return { message: val.message, name: val.name };\n if (typeof val === 'function') return '[function]';\n if (typeof val === 'symbol') return val.toString();\n if (val === undefined) return null;\n return val;\n });\n return createHash('sha256')\n .update(serialized ?? 'undefined')\n .digest('hex')\n .slice(0, 16);\n}\n","import type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\n/**\n * In-memory MessageBusProvider — delivers messages locally within the process.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external bus is configured\n *\n * Messages published to a topic are delivered synchronously to all\n * subscribed handlers for that topic.\n */\nexport class InMemoryMessageBusProvider implements MessageBusProvider {\n private subscriptions = new Map<string, Map<string, MessageHandler>>();\n private nextId = 0;\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const messageId = message.metadata?.messageId ?? `mem-${++this.nextId}`;\n const topicHandlers = this.subscriptions.get(topic);\n\n if (topicHandlers) {\n const enrichedMessage: BusMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n messageId,\n timestamp: message.metadata?.timestamp ?? new Date().toISOString(),\n },\n };\n\n // Deliver to all subscribers\n const handlers = Array.from(topicHandlers.values());\n await Promise.all(handlers.map((handler) => handler(enrichedMessage)));\n }\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const id = `sub-${++this.nextId}`;\n\n let topicHandlers = this.subscriptions.get(topic);\n if (!topicHandlers) {\n topicHandlers = new Map();\n this.subscriptions.set(topic, topicHandlers);\n }\n topicHandlers.set(id, handler);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const topicHandlers = this.subscriptions.get(subscription.topic);\n if (topicHandlers) {\n topicHandlers.delete(subscription.id);\n if (topicHandlers.size === 0) {\n this.subscriptions.delete(subscription.topic);\n }\n }\n }\n\n /** Helper for testing: get count of active subscriptions for a topic */\n getSubscriptionCount(topic: string): number {\n return this.subscriptions.get(topic)?.size ?? 0;\n }\n\n /** Helper for testing: clear all subscriptions */\n clear(): void {\n this.subscriptions.clear();\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryBusProvider = new InMemoryMessageBusProvider();\n","export type {\n MessageBusProvider,\n BusMessage,\n MessageMetadata,\n PublishResult,\n MessageHandler,\n Subscription,\n} from './provider';\nexport { InMemoryMessageBusProvider, inMemoryBusProvider } from './noop';\nexport { SqsSnsMessageBusProvider, type SqsSnsConfig } from './sqs-sns';\nexport { createMessageBusProvider } from './factory';\n","import type { MessageBusProvider } from './provider';\nimport { inMemoryBusProvider } from './noop';\n\n/**\n * Create a MessageBusProvider based on environment configuration.\n *\n * - MESSAGE_BUS_PROVIDER=memory (or unset) -> InMemoryMessageBusProvider\n * - MESSAGE_BUS_PROVIDER=sqs -> SQS/SNS adapter\n *\n * Same pattern as createObservabilityProvider().\n */\nexport function createMessageBusProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n /** Provider-specific config (e.g. SqsSnsConfig for 'sqs') */\n config?: Record<string, unknown>;\n}): MessageBusProvider {\n const providerType = options?.provider ?? process.env['MESSAGE_BUS_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryBusProvider;\n case 'sqs': {\n // Dynamic require to avoid bundling AWS SDK when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SqsSnsMessageBusProvider } = require('./sqs-sns') as typeof import('./sqs-sns');\n return new SqsSnsMessageBusProvider(options?.config);\n }\n default:\n console.warn(\n `stackwright-services:messaging Unknown MESSAGE_BUS_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryBusProvider;\n }\n}\n","import type { NotificationMessage, NotificationProvider, SendResult } from './provider';\n\n/**\n * In-memory NotificationProvider — records notifications locally for inspection.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external notification service is configured\n *\n * Notifications are stored in-memory and can be inspected via helper methods.\n */\nexport class InMemoryNotificationProvider implements NotificationProvider {\n private notifications: Array<NotificationMessage & { notificationId: string }> = [];\n private nextId = 0;\n\n async send(notification: NotificationMessage): Promise<SendResult> {\n const notificationId = `notif-${++this.nextId}`;\n\n this.notifications.push({\n ...notification,\n notificationId,\n metadata: {\n ...notification.metadata,\n timestamp: notification.metadata?.timestamp ?? new Date().toISOString(),\n },\n });\n\n return {\n notificationId,\n channel: notification.channel,\n success: true,\n };\n }\n\n /** Helper for testing: get all sent notifications */\n getSentNotifications(): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return [...this.notifications];\n }\n\n /** Helper for testing: get notifications filtered by channel */\n getByChannel(channel: string): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.channel === channel);\n }\n\n /** Helper for testing: get notifications filtered by recipient */\n getByRecipient(\n recipient: string,\n ): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.recipient === recipient);\n }\n\n /** Helper for testing: get count of sent notifications */\n get sentCount(): number {\n return this.notifications.length;\n }\n\n /** Helper for testing: clear all recorded notifications */\n clear(): void {\n this.notifications = [];\n this.nextId = 0;\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryNotificationProvider = new InMemoryNotificationProvider();\n","import type { NotificationProvider } from './provider';\nimport { inMemoryNotificationProvider } from './noop';\n\n/**\n * Create a NotificationProvider based on environment configuration.\n *\n * - NOTIFICATION_PROVIDER=memory (or unset) -> InMemoryNotificationProvider\n * - NOTIFICATION_PROVIDER=sendgrid -> (future: SendGrid adapter)\n * - NOTIFICATION_PROVIDER=twilio -> (future: Twilio adapter)\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createNotificationProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n}): NotificationProvider {\n const providerType = options?.provider ?? process.env['NOTIFICATION_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryNotificationProvider;\n // Future: case 'sendgrid' -> SendGrid adapter\n // Future: case 'twilio' -> Twilio/SNS adapter\n // Future: case 'fcm' -> Firebase Cloud Messaging adapter\n default:\n console.warn(\n `stackwright-services:notifications Unknown NOTIFICATION_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryNotificationProvider;\n }\n}\n","import type { AuthClaims, AuthProvider, TokenValidationResult } from './provider';\n\n/**\n * No-op AuthProvider — fail-closed default.\n *\n * Used when no auth provider is configured:\n * - validateToken() always returns { valid: false } (reject all tokens)\n * - extractClaims() throws (no claims without a real provider)\n * - checkRole() always returns false (deny all role checks)\n *\n * This is intentionally fail-closed: if you forget to install a real\n * auth provider, every auth check fails rather than silently passing.\n */\nexport class NoopAuthProvider implements AuthProvider {\n readonly name = 'noop';\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async validateToken(token: string): Promise<TokenValidationResult> {\n return { valid: false, error: 'No auth provider configured' };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async extractClaims(token: string): Promise<AuthClaims> {\n throw new Error('No auth provider configured');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n checkRole(claims: AuthClaims, role: string): boolean {\n return false;\n }\n}\n\n/** Singleton no-op provider */\nexport const noopAuthProvider = new NoopAuthProvider();\n","import type { AuthProvider } from './provider';\nimport { noopAuthProvider } from './noop';\n\nexport type AuthProviderType = 'noop' | 'oidc' | 'cac';\n\n/**\n * Create an AuthProvider based on the requested type.\n *\n * - 'noop' (or unset) -> NoopAuthProvider (fail-closed default)\n * - 'oidc' -> Future: lazy require('@stackwright-pro/auth-oidc')\n * - 'cac' -> Future: lazy require('@stackwright-pro/auth-cac')\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createAuthProvider(type?: AuthProviderType): AuthProvider {\n switch (type) {\n case 'oidc':\n // Future: lazy require('@stackwright-pro/auth-oidc')\n throw new Error(\n 'OIDC auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'cac':\n // Future: lazy require('@stackwright-pro/auth-cac')\n throw new Error(\n 'CAC/PKI auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'noop':\n default:\n return noopAuthProvider;\n }\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\n/**\n * NoopDataSourceProvider — used when no data source provider is installed.\n *\n * listSources() returns an empty array (no sources available to the schema expander).\n * execute() throws a descriptive error pointing to the correct package to install.\n *\n * This is the fail-closed default, consistent with NoopAuthProvider.\n */\nexport class NoopDataSourceProvider implements DataSourceProvider {\n readonly name = 'noop';\n\n listSources(): DataSourceDescriptor[] {\n return [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(_source: string, _operation: string, _params: unknown): Promise<DataSourceResult> {\n return Promise.reject(\n new Error(\n 'No DataSourceProvider is configured. ' +\n 'Install @stackwright-pro/openapi or @stackwright-pro/pulse and register an adapter, ' +\n 'or set DATA_SOURCE_PROVIDER in your environment.',\n ),\n );\n }\n}\n\nexport const noopDataSourceProvider = new NoopDataSourceProvider();\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:openapi';\n\n/**\n * A typed operation handler for a single OpenAPI operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type OpenApiOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single OpenAPI-backed data source.\n */\nexport interface OpenApiSourceRegistration {\n /** Source ID — matches the id in `source: openapi:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, OpenApiOperationHandler>;\n}\n\n/**\n * Configuration for OpenApiDataSourceProvider.\n */\nexport interface OpenApiAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: OpenApiSourceRegistration[];\n}\n\n/**\n * OpenApiDataSourceProvider — wraps registered OpenAPI operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed OpenAPI client methods (from @stackwright-pro/openapi),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/openapi` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class OpenApiDataSourceProvider implements DataSourceProvider {\n readonly name = 'openapi';\n\n private readonly sourcesMap: Map<string, OpenApiSourceRegistration>;\n\n constructor(private readonly config: OpenApiAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'openapi' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in OpenApiAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates an OpenApiDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/openapi's datasource-adapter when installed.\n */\nexport function createOpenApiDataSourceProvider(config: OpenApiAdapterConfig): DataSourceProvider {\n return new OpenApiDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/openapi's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: openapi:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:pulse';\n\n/**\n * A typed operation handler for a single Pulse operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type PulseOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single Pulse-backed data source.\n */\nexport interface PulseSourceRegistration {\n /** Source ID — matches the id in `source: pulse:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, PulseOperationHandler>;\n}\n\n/**\n * Configuration for PulseDataSourceProvider.\n */\nexport interface PulseAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: PulseSourceRegistration[];\n}\n\n/**\n * PulseDataSourceProvider — wraps registered Pulse operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed Pulse client methods (from @stackwright-pro/pulse),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/pulse` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Usage example:\n * ```typescript\n * const provider = createPulseDataSourceProvider({\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryMetrics: pulseClient.queryMetrics },\n * }],\n * });\n * // Matches `source: pulse:fleet-db` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class PulseDataSourceProvider implements DataSourceProvider {\n readonly name = 'pulse';\n\n private readonly sourcesMap: Map<string, PulseSourceRegistration>;\n\n constructor(private readonly config: PulseAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'pulse' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in PulseAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a PulseDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/pulse's datasource-adapter when installed.\n */\nexport function createPulseDataSourceProvider(config: PulseAdapterConfig): DataSourceProvider {\n return new PulseDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/pulse's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: pulse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:streaming';\n\n/**\n * A typed operation handler for a single streaming (WebSocket / SSE) operation.\n * Receives caller-supplied params and returns the operation result.\n *\n * For WebSocket/SSE sources the typical patterns are:\n * - Request-response over WebSocket (send + await reply)\n * - Snapshot of last-known state from an in-process subscription cache\n * - Publish a message to the stream\n *\n * Implementations are responsible for managing the underlying transport connection.\n */\nexport type StreamingOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single streaming data source.\n */\nexport interface StreamingSourceRegistration {\n /** Source ID — matches the id in `source: websocket:<id>` or `source: sse:<id>` YAML references */\n id: string;\n /**\n * Transport protocol for this source.\n * - `websocket`: bidirectional, binary-capable, suitable for most real-time feeds\n * - `sse`: unidirectional server→client, HTTP-compatible, firewall-friendly\n */\n transport: 'websocket' | 'sse';\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, StreamingOperationHandler>;\n}\n\n/**\n * Configuration for StreamingDataSourceProvider.\n */\nexport interface StreamingAdapterConfig {\n /** Data sources to register. Each source declares its transport + named operation handlers. */\n sources: StreamingSourceRegistration[];\n}\n\n/**\n * StreamingDataSourceProvider — wraps registered WebSocket/SSE operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a transport type and operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically typed client methods wrapping `useStreaming` subscriptions\n * (from `@stackwright-pro/pulse`), but any async function with the right signature works.\n *\n * Design rationale:\n * - Same registry pattern as `PulseDataSourceProvider` — swapping 'pulse' for 'websocket'/'sse'.\n * - Transport-agnostic at this layer: the handler decides how to communicate over the socket.\n * - `@stackwright-pro/pulse` registers streaming clients here when installed; the adapter\n * does NOT hard-import that package (IoC at factory time).\n *\n * Usage example:\n * ```typescript\n * const provider = createStreamingDataSourceProvider({\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * });\n * // Matches `source: websocket:ais-vessels` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error.\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is.\n */\nexport class StreamingDataSourceProvider implements DataSourceProvider {\n readonly name = 'streaming';\n\n private readonly sourcesMap: Map<string, StreamingSourceRegistration>;\n\n constructor(private readonly config: StreamingAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: s.transport,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in StreamingAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a StreamingDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by `@stackwright-pro/pulse`'s streaming datasource adapter when installed.\n */\nexport function createStreamingDataSourceProvider(\n config: StreamingAdapterConfig,\n): DataSourceProvider {\n return new StreamingDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * `@stackwright-pro/pulse`'s streaming-datasource-adapter overrides this with a\n * static manifest of all generated streaming clients, enabling the compiler to\n * validate `source: websocket:*` and `source: sse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceProvider } from './provider';\nimport { noopDataSourceProvider } from './noop';\nimport type { OpenApiAdapterConfig } from './openapi-adapter';\nimport { createOpenApiDataSourceProvider } from './openapi-adapter';\nimport type { PulseAdapterConfig } from './pulse-adapter';\nimport { createPulseDataSourceProvider } from './pulse-adapter';\nimport type { StreamingAdapterConfig } from './streaming-adapter';\nimport { createStreamingDataSourceProvider } from './streaming-adapter';\n\n/**\n * Create a DataSourceProvider based on installed packages and environment configuration.\n *\n * Resolution order (first match wins):\n * 1. `options.provider` — explicit code-level override\n * 2. `DATA_SOURCE_PROVIDER` env var — environment-level override\n * 3. IoC auto-discovery — scans for installed adapter packages via require.resolve()\n * a. `@stackwright-pro/openapi/datasource-adapter` (checked first)\n * b. `@stackwright-pro/pulse/datasource-adapter`\n * 4. NoopDataSourceProvider — fail-closed default, throws on execute()\n *\n * Same pattern as createMessageBusProvider() and createAuthProvider().\n *\n * @example Default (IoC — install the package, nothing else needed)\n * ```typescript\n * // With @stackwright-pro/pulse in node_modules:\n * const provider = createDataSourceProvider();\n * // → PulseDataSourceProvider (auto-discovered)\n *\n * // With nothing installed:\n * const provider = createDataSourceProvider();\n * // → NoopDataSourceProvider (execute() will throw)\n * ```\n *\n * @example Explicit override with config (useful in tests and custom setups)\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'pulse',\n * config: {\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryGeneratorStatus: mockHandler },\n * }],\n * },\n * });\n * ```\n *\n * @example Streaming WebSocket/SSE provider\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'websocket',\n * config: {\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * },\n * });\n * ```\n *\n * @example Environment-level override (force noop in isolated tests)\n * ```bash\n * DATA_SOURCE_PROVIDER=noop node my-service.js\n * DATA_SOURCE_PROVIDER=pulse node my-service.js # force pulse even if openapi is installed\n * DATA_SOURCE_PROVIDER=websocket node my-service.js # force streaming (WebSocket)\n * DATA_SOURCE_PROVIDER=sse node my-service.js # force streaming (SSE)\n * ```\n */\nexport function createDataSourceProvider(options?: {\n /** Override the provider type ('openapi' | 'pulse' | 'websocket' | 'sse' | 'noop') */\n provider?: string;\n /** Provider-specific config passed through to the adapter */\n config?: Record<string, unknown>;\n}): DataSourceProvider {\n const providerType = options?.provider ?? process.env['DATA_SOURCE_PROVIDER'] ?? _autoDiscover();\n\n switch (providerType) {\n case 'noop':\n return noopDataSourceProvider;\n\n case 'openapi': {\n // Local OpenAPI adapter — always present, no dynamic require needed.\n // @stackwright-pro/openapi can supplement this via auto-discovery when installed.\n return createOpenApiDataSourceProvider(\n (options?.config as OpenApiAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'pulse': {\n // Local Pulse adapter — always present, no dynamic require needed.\n // @stackwright-pro/pulse can supplement this via auto-discovery when installed.\n return createPulseDataSourceProvider(\n (options?.config as PulseAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'websocket':\n case 'sse': {\n // Streaming adapter — handles both WebSocket and SSE sources.\n // @stackwright-pro/pulse ships a streaming-datasource-adapter entry point that\n // auto-registers generated streaming clients when installed.\n return createStreamingDataSourceProvider(\n (options?.config as StreamingAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n default:\n if (providerType !== 'noop') {\n console.warn(\n `stackwright-services:datasource Unknown DATA_SOURCE_PROVIDER \"${providerType}\", falling back to noop`,\n );\n }\n return noopDataSourceProvider;\n }\n}\n\n/**\n * Auto-discover installed providers via require.resolve().\n * Returns the first provider type found, or 'noop' if none are installed.\n *\n * This is a pure filesystem probe — no module is loaded here, no side effects.\n * Actual provider construction happens in createDataSourceProvider() after this returns.\n *\n * Discovery convention: each adapter package ships a `datasource-adapter` subpath export\n * (`<package>/datasource-adapter`) that this probe checks for. The local OpenApiDataSourceProvider\n * and PulseDataSourceProvider do NOT trigger auto-discovery — they require explicit source\n * registration via factory config. Only the Pro adapter packages auto-register.\n *\n * Check order matters when both are installed: openapi wins. Override with\n * DATA_SOURCE_PROVIDER env var or explicit options.provider to change this.\n */\nfunction _autoDiscover(): string {\n const candidates: Array<{ pkg: string; providerType: string }> = [\n // @stackwright-pro/openapi ships its own datasource-adapter entry point that\n // auto-registers all generated clients — when that package is installed, 'openapi'\n // is returned here. The local OpenApiDataSourceProvider requires explicit source\n // registration and does NOT trigger auto-discovery.\n { pkg: '@stackwright-pro/openapi/datasource-adapter', providerType: 'openapi' },\n // @stackwright-pro/pulse follows the same pattern for Pulse-backed data sources.\n { pkg: '@stackwright-pro/pulse/datasource-adapter', providerType: 'pulse' },\n // @stackwright-pro/pulse also ships a streaming-datasource-adapter for WebSocket/SSE sources.\n // websocket wins if both pulse and streaming are installed (use DATA_SOURCE_PROVIDER to override).\n { pkg: '@stackwright-pro/pulse/streaming-datasource-adapter', providerType: 'websocket' },\n ];\n\n for (const { pkg, providerType } of candidates) {\n try {\n require.resolve(pkg);\n return providerType;\n } catch {\n // not installed — try next\n }\n }\n\n // Nothing found — createDataSourceProvider() will use NoopDataSourceProvider.\n // Any flow step that calls provider.execute() will receive a descriptive error\n // pointing to the correct package to install.\n return 'noop';\n}\n","import type { DataSourceDescriptor } from './provider';\n\n/**\n * Result of a prebuild-time data source scan.\n */\nexport interface DataSourceScanResult {\n /** All sources discovered across all installed providers */\n sources: DataSourceDescriptor[];\n /** Which provider packages were found (for logging/diagnostics) */\n detectedProviders: string[];\n}\n\n/**\n * Scan installed packages at prebuild time to discover available data sources.\n *\n * This is called by the compiler and prebuild hook (yo8) to expand the valid\n * `source:` schema surface. If @stackwright-pro/openapi or @stackwright-pro/pulse\n * are installed and expose an adapter registry, their sources are enumerated here.\n *\n * This is a pure filesystem/module-resolution operation — no network, no side effects.\n * It is safe to call at build time (no running server required).\n *\n * Returns an empty sources array if no providers are installed, which causes the\n * compiler to emit a warning (not an error) when a `source:` reference is encountered.\n */\nexport function scanDataSources(): DataSourceScanResult {\n const sources: DataSourceDescriptor[] = [];\n const detectedProviders: string[] = [];\n\n // Try @stackwright-pro/openapi\n try {\n require.resolve('@stackwright-pro/openapi/datasource-adapter');\n detectedProviders.push('@stackwright-pro/openapi');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/openapi/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/openapi sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/openapi not installed\n }\n\n // Try @stackwright-pro/pulse\n try {\n require.resolve('@stackwright-pro/pulse/datasource-adapter');\n detectedProviders.push('@stackwright-pro/pulse');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/pulse/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/pulse sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/pulse not installed\n }\n\n return { sources, detectedProviders };\n}\n","/**\n * Core prebuild registration function.\n * Discovers and enumerates the complete services schema surface.\n */\nimport { CapabilityRegistry, registerAllCapabilities } from '@stackwright-services/capabilities';\nimport { scanDataSources } from '../datasource/scan';\nimport type {\n CapabilityDescriptor,\n DataSourceDescriptorEntry,\n PrebuildRegistration,\n TriggerTypeDescriptor,\n} from './types';\n\n// Read version from package.json at build time\nconst PACKAGE_VERSION = '0.0.1'; // Synced with package.json via sync-versions.mjs\n\n/**\n * Enumerate all known trigger types.\n * The trigger type set is closed and small per VISION.md.\n */\nfunction enumerateTriggers(): TriggerTypeDescriptor[] {\n return [\n {\n type: 'http',\n description:\n 'HTTP request/response trigger — becomes API Gateway route (Lambda) or Ingress (k8s)',\n inputSchema: {\n type: 'object',\n properties: {\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] },\n path: { type: 'string', pattern: '^/' },\n input_schema: { type: 'string' },\n },\n required: ['method', 'path'],\n },\n example: {\n type: 'http',\n method: 'POST',\n path: '/api/patients/at-risk',\n input_schema: 'AtRiskRequest',\n },\n },\n {\n type: 'event',\n description: 'Pub/sub event trigger — subscribes to a message bus topic',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^bus:' },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'event',\n source: 'bus:equipment-status',\n input_schema: 'EquipmentStatusEvent',\n },\n },\n {\n type: 'schedule',\n description: 'Cron-style scheduled trigger — periodic invocation',\n inputSchema: {\n type: 'object',\n properties: {\n cron: { type: 'string' },\n input_schema: { type: 'string' },\n },\n required: ['cron'],\n },\n example: { type: 'schedule', cron: '0 */6 * * *', input_schema: 'ScheduledCheckInput' },\n },\n {\n type: 'queue',\n description: 'Durable point-to-point queue trigger — processes messages sequentially',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^queue:' },\n batch_size: { type: 'number', minimum: 1, maximum: 10 },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'queue',\n source: 'queue:approvals',\n batch_size: 1,\n input_schema: 'ApprovalMessage',\n },\n },\n ];\n}\n\n/**\n * Walk the capability registry and extract descriptors.\n */\nfunction enumerateCapabilities(): CapabilityDescriptor[] {\n const registry = new CapabilityRegistry();\n registerAllCapabilities(registry);\n\n return registry.listAll().map((cap) => {\n const descriptor: CapabilityDescriptor = {\n name: cap.definition.name,\n kind: cap.definition.kind,\n description: cap.definition.description,\n inputSchema: cap.definition.inputSchema,\n outputSchema: cap.definition.outputSchema,\n };\n\n if (cap.definition.kind === 'effect') {\n descriptor.requiredPermissions = cap.definition.requiredPermissions;\n }\n\n return descriptor;\n });\n}\n\n/**\n * Discover installed data sources.\n * Maps from runtime's DataSourceDescriptor (transport field) to prebuild's\n * DataSourceDescriptorEntry (provider field).\n */\nfunction enumerateDataSources(): DataSourceDescriptorEntry[] {\n const scanResult = scanDataSources();\n return scanResult.sources.map((source) => ({\n id: source.id,\n provider: source.transport,\n operations: source.operations,\n }));\n}\n\n/**\n * Main prebuild registration function.\n * Called by @stackwright/scaffold-core at prebuild time.\n *\n * This is safe to call at build time — no running server required,\n * no network calls, no side effects beyond module resolution for data source scanning.\n */\nexport function registerServices(): PrebuildRegistration {\n return {\n pluginId: '@stackwright-services/runtime',\n version: PACKAGE_VERSION,\n triggers: enumerateTriggers(),\n capabilities: enumerateCapabilities(),\n dataSources: enumerateDataSources(),\n registeredAt: new Date().toISOString(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8EO,SAAS,aAAa,MAAsB;AACjD,SAAO,KAAK,QAAQ,SAAS,GAAG,EAAE,YAAY;AAChD;AAhFA,IA8BA,mBAMA,mBAeM,YAmCO;AAtFb;AAAA;AAAA;AA8BA,wBAKO;AACP,wBAMO;AASP,IAAM,aAAa;AAmCZ,IAAM,2BAAN,MAA6D;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,oBAAI,IAA0B;AAAA,MAE/D,YAAY,SAAuB,CAAC,GAAG;AACrC,cAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,YAAY,KAAK;AAC7D,aAAK,YAAY,OAAO,aAAa,IAAI,4BAAU,EAAE,OAAO,CAAC;AAC7D,aAAK,YAAY,OAAO,aAAa,IAAI,4BAAU,EAAE,OAAO,CAAC;AAC7D,aAAK,YAAY,OAAO,aAAa,CAAC;AACtC,aAAK,YAAY,OAAO,aAAa,CAAC;AACtC,aAAK,kBAAkB,OAAO,mBAAmB;AACjD,aAAK,cAAc,OAAO,eAAe;AACzC,aAAK,iBAAiB,OAAO,kBAAkB;AAAA,MACjD;AAAA,MAEA,MAAM,QAAQ,OAAe,SAA6C;AACxE,cAAM,WAAW,KAAK,gBAAgB,KAAK;AAC3C,cAAM,aAAa,KAAK,mBAAmB,OAAO;AAElD,cAAM,QAA6B;AAAA,UACjC,UAAU;AAAA,UACV,SAAS,KAAK,UAAU,QAAQ,OAAO;AAAA,UACvC,mBAAmB;AAAA,QACrB;AAEA,cAAM,WAAW,MAAM,KAAK,UAAU,KAAK,IAAI,iCAAe,KAAK,CAAC;AACpE,cAAM,YAAY,SAAS,aAAa,OAAO,KAAK,IAAI,CAAC;AAEzD,eAAO,EAAE,WAAW,OAAO,SAAS,KAAK;AAAA,MAC3C;AAAA,MAEA,MAAM,UAAU,OAAe,SAAgD;AAC7E,cAAM,WAAW,KAAK,gBAAgB,KAAK;AAC3C,cAAM,KAAK,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC1E,cAAM,QAAsB,EAAE,QAAQ,KAAK;AAC3C,aAAK,cAAc,IAAI,IAAI,KAAK;AAGhC,aAAK,KAAK,UAAU,SAAS,KAAK;AAElC,cAAM,SAAS,YAA2B;AACxC,gBAAM,KAAK,YAAY,EAAE,IAAI,OAAO,QAAQ,YAAY;AAAA,UAAC,EAAE,CAAC;AAAA,QAC9D;AAEA,eAAO,EAAE,IAAI,OAAO,OAAO;AAAA,MAC7B;AAAA,MAEA,MAAM,YAAY,cAA2C;AAC3D,cAAM,QAAQ,KAAK,cAAc,IAAI,aAAa,EAAE;AACpD,YAAI,OAAO;AACT,gBAAM,SAAS;AACf,eAAK,cAAc,OAAO,aAAa,EAAE;AAAA,QAC3C;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAMQ,gBAAgB,OAAuB;AAC7C,cAAM,aAAa,KAAK,UAAU,KAAK;AACvC,YAAI,WAAY,QAAO;AAEvB,cAAM,SAAS,aAAa,aAAa,KAAK,CAAC;AAC/C,cAAM,UAAU,QAAQ,IAAI,MAAM;AAClC,YAAI,QAAS,QAAO;AAEpB,cAAM,IAAI;AAAA,UACR,GAAG,UAAU,gCAAgC,KAAK,4BACvB,KAAK,iBAAiB,MAAM;AAAA,QACzD;AAAA,MACF;AAAA,MAEQ,gBAAgB,OAAuB;AAC7C,cAAM,aAAa,KAAK,UAAU,KAAK;AACvC,YAAI,WAAY,QAAO;AAEvB,cAAM,SAAS,aAAa,aAAa,KAAK,CAAC;AAC/C,cAAM,UAAU,QAAQ,IAAI,MAAM;AAClC,YAAI,QAAS,QAAO;AAEpB,cAAM,IAAI;AAAA,UACR,GAAG,UAAU,gCAAgC,KAAK,4BACvB,KAAK,iBAAiB,MAAM;AAAA,QACzD;AAAA,MACF;AAAA,MAEQ,mBAAmB,SAA+D;AACxF,cAAM,QAAkD,CAAC;AAGzD,YAAI,QAAQ,cAAc;AACxB,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,YAAY,GAAG;AAC/D,kBAAM,SAAS,GAAG,EAAE,IAAI,EAAE,UAAU,UAAU,aAAa,MAAM;AAAA,UACnE;AAAA,QACF;AAGA,YAAI,QAAQ,UAAU;AACpB,gBAAM,EAAE,WAAW,QAAQ,cAAc,IAAI,QAAQ;AACrD,cAAI,WAAW;AACb,kBAAM,gBAAgB,IAAI,EAAE,UAAU,UAAU,aAAa,UAAU;AAAA,UACzE;AACA,cAAI,QAAQ;AACV,kBAAM,aAAa,IAAI,EAAE,UAAU,UAAU,aAAa,OAAO;AAAA,UACnE;AACA,cAAI,eAAe;AACjB,kBAAM,oBAAoB,IAAI,EAAE,UAAU,UAAU,aAAa,cAAc;AAAA,UACjF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,MAAc,KACZ,UACA,SACA,OACe;AACf,eAAO,MAAM,QAAQ;AAGnB,gBAAM,IAAI,QAAc,CAAC,YAAY,WAAW,SAAS,KAAK,cAAc,CAAC;AAC7E,cAAI,CAAC,MAAM,OAAQ;AAEnB,cAAI;AACF,kBAAM,WAAW,MAAM,KAAK,UAAU;AAAA,cACpC,IAAI,wCAAsB;AAAA,gBACxB,UAAU;AAAA,gBACV,iBAAiB,KAAK;AAAA,gBACtB,qBAAqB,KAAK;AAAA,gBAC1B,uBAAuB,CAAC,KAAK;AAAA,cAC/B,CAAC;AAAA,YACH;AAEA,uBAAW,cAAc,SAAS,YAAY,CAAC,GAAG;AAChD,kBAAI,CAAC,MAAM,OAAQ;AAEnB,oBAAM,aAAa,KAAK,gBAAgB,UAAU;AAClD,kBAAI;AACF,sBAAM,QAAQ,UAAU;AAAA,cAC1B,SAAS,cAAc;AACrB,wBAAQ;AAAA,kBACN,KAAK,UAAU;AAAA,oBACb,QAAQ;AAAA,oBACR,OAAO;AAAA,oBACP,OAAO,wBAAwB,QAAQ,aAAa,UAAU,OAAO,YAAY;AAAA,oBACjF;AAAA,kBACF,CAAC;AAAA,gBACH;AAEA;AAAA,cACF;AAGA,kBAAI,WAAW,eAAe;AAC5B,sBAAM,KAAK,UAAU;AAAA,kBACnB,IAAI,uCAAqB;AAAA,oBACvB,UAAU;AAAA,oBACV,eAAe,WAAW;AAAA,kBAC5B,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,YACF;AAAA,UACF,SAAS,WAAW;AAElB,oBAAQ;AAAA,cACN,KAAK,UAAU;AAAA,gBACb,QAAQ;AAAA,gBACR,OAAO;AAAA,gBACP,OAAO,qBAAqB,QAAQ,UAAU,UAAU,OAAO,SAAS;AAAA,gBACxE;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,gBAAgB,YAAiC;AACvD,cAAM,UAAU,WAAW,OAAO,KAAK,MAAM,WAAW,IAAI,IAAI;AAChE,cAAM,eAAe,KAAK,oBAAoB,WAAW,iBAAiB;AAC1E,cAAM,WAAW,KAAK,gBAAgB,WAAW,iBAAiB;AAElE,eAAO;AAAA,UACL;AAAA,UACA,GAAI,iBAAiB,UAAa,EAAE,aAAa;AAAA,UACjD,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,QAC3C;AAAA,MACF;AAAA,MAEQ,oBACN,OACoC;AACpC,YAAI,CAAC,MAAO,QAAO;AAEnB,cAAM,QAAgC,CAAC;AACvC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,cAAI,IAAI,WAAW,QAAQ,KAAK,MAAM,aAAa;AACjD,kBAAM,IAAI,MAAM,SAAS,MAAM,CAAC,IAAI,MAAM;AAAA,UAC5C;AAAA,QACF;AAEA,eAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,MACjD;AAAA,MAEQ,gBACN,OACwB;AACxB,YAAI,CAAC,MAAO,QAAO;AAEnB,cAAM,YAAY,MAAM,gBAAgB,GAAG;AAC3C,cAAM,SAAS,MAAM,aAAa,GAAG;AACrC,cAAM,gBAAgB,MAAM,oBAAoB,GAAG;AAEnD,YAAI,CAAC,aAAa,CAAC,UAAU,CAAC,cAAe,QAAO;AAEpD,eAAO;AAAA,UACL,GAAI,aAAa,EAAE,UAAU;AAAA,UAC7B,GAAI,UAAU,EAAE,OAAO;AAAA,UACvB,GAAI,iBAAiB,EAAE,cAAc;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC1TA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,kBAAqB;AAoCd,SAAS,kBAAkB,SAAmC;AACnE,QAAM,EAAE,SAAS,SAAS,aAAa,aAAa,IAAI;AACxD,QAAM,MAAM,IAAI,iBAAK;AAGrB,MAAI,IAAI,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,MAAM,SAAS,OAAO,CAAC,CAAC;AAGnE,QAAM,SAAS,QAAQ,OAAO,YAAY;AAE1C,MAAI,MAAM,EAAE,QAAQ,MAAM,OAAO,MAAe;AAE9C,QAAI;AACJ,QAAI,QAAQ,WAAW,OAAO;AAC5B,cAAQ,OAAO,YAAY,IAAI,IAAI,EAAE,IAAI,GAAG,EAAE,YAAY;AAAA,IAC5D,OAAO;AACL,UAAI;AACF,gBAAQ,MAAM,EAAE,IAAI,KAAK;AAAA,MAC3B,QAAQ;AACN,eAAO,EAAE;AAAA,UACP,EAAE,OAAO,qBAAqB,MAAM,uBAAuB;AAAA,UAC3D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,aAAa;AACf,YAAM,SAAS,YAAY,UAAU,KAAK;AAC1C,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO,EAAE;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,MAAM;AAAA,YACN,SAAS,OAAO,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,cAAQ,OAAO;AAAA,IACjB;AAGA,UAAM,UAA6B;AAAA,MACjC,SAAS,EAAE,IAAI,OAAO,YAAY,KAAK,EAAE,IAAI,OAAO,cAAc,KAAK,OAAO,WAAW;AAAA,MACzF,QAAQ,aAAa;AAAA,IACvB;AAGA,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,OAAO,OAAO;AAG3C,UAAI,cAAc;AAChB,cAAM,eAAe,aAAa,UAAU,MAAM;AAClD,YAAI,CAAC,aAAa,SAAS;AACzB,iBAAO,EAAE;AAAA,YACP,EAAE,OAAO,4BAA4B,MAAM,0BAA0B;AAAA,YACrE;AAAA,UACF;AAAA,QACF;AACA,eAAO,EAAE,KAAK,aAAa,IAAI;AAAA,MACjC;AAEA,aAAO,EAAE,KAAK,MAAM;AAAA,IACtB,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,aAAO,EAAE,KAAmB,EAAE,OAAO,SAAS,MAAM,uBAAuB,GAAG,GAAG;AAAA,IACnF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,SAAS,eAAe;AACtB,SAAO;AAAA,IACL,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAChE,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EAClE;AACF;;;AC/FO,IAAM,sBAAN,MAAoD;AAAA,EAChD,OAAO;AAAA,EACP;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAER,YAAY,SAA8B;AACxC,SAAK,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,SAAS,EAAE;AACvD,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ;AACvB,SAAK,cAAc,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,eAAe,MAAM,KAAK,WAAW;AAAA,MAAU,KAAK;AAAA,MAAO,CAAC,YAC/D,KAAK,cAAc,OAAO;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,KAAK,cAAc;AACrB,YAAM,KAAK,aAAa,OAAO;AAC/B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,SAAoC;AAC9D,QAAI,UAAmB,QAAQ;AAG/B,QAAI,KAAK,aAAa;AACpB,YAAM,SAAS,KAAK,YAAY,UAAU,OAAO;AACjD,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAASC,cAAa;AAC5B,eAAO,KAAK,mCAAmC;AAAA,UAC7C,OAAO,KAAK;AAAA,UACZ,QAAQ,OAAO,MAAM;AAAA,QACvB,CAAC;AACD;AAAA,MACF;AACA,gBAAU,OAAO;AAAA,IACnB;AAGA,UAAM,UAAU,QAAQ,eAAe,SAAS,KAAK,OAAO,WAAW;AACvE,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA,QAAQA,cAAa;AAAA,IACvB;AAEA,QAAI;AACF,YAAM,KAAK,QAAQ,SAAS,OAAO;AAAA,IACrC,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,cAAQ,OAAO,MAAM,wBAAwB;AAAA,QAC3C,OAAO,KAAK;AAAA,QACZ,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAASA,gBAAe;AACtB,SAAO;AAAA,IACL,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAChE,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EAClE;AACF;;;AC/EA,IAAM,sBAAsB;AAYrB,IAAM,yBAAN,MAAuD;AAAA,EACnD,OAAO;AAAA,EACP;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAER,YAAY,SAAiC;AAC3C,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,UAAU,QAAQ;AACvB,SAAK,cAAc,QAAQ;AAC3B,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,eAAe,qBAAqB;AAC3C,YAAM,SAASC,cAAa;AAC5B,aAAO,KAAK,uEAAuE;AAAA,QACjF,MAAM,KAAK;AAAA,QACX,YAAY,KAAK;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,SAAK,QAAQ,YAAY,MAAM;AAC7B,WAAK,KAAK,KAAK;AAAA,IACjB,GAAG,KAAK,UAAU;AAAA,EACpB;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,KAAK,UAAU,QAAW;AAC5B,oBAAc,KAAK,KAAK;AACxB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAc,OAAsB;AAClC,UAAM,UAAU,OAAO,WAAW;AAClC,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA,QAAQA,cAAa;AAAA,IACvB;AAEA,QAAI;AACF,YAAM,KAAK,QAAQ,CAAC,GAAG,OAAO;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,cAAQ,OAAO,MAAM,2BAA2B;AAAA,QAC9C,MAAM,KAAK;AAAA,QACX,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAASA,gBAAe;AACtB,SAAO;AAAA,IACL,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAChE,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EAClE;AACF;;;ACvEO,IAAM,sBAAN,MAAoD;AAAA,EAChD,OAAO;AAAA,EACP;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAER,YAAY,SAA8B;AACxC,SAAK,YAAY,QAAQ,QAAQ;AACjC,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ;AACvB,SAAK,cAAc,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,eAAe,MAAM,KAAK,WAAW;AAAA,MAAU,KAAK;AAAA,MAAW,CAAC,YACnE,KAAK,cAAc,OAAO;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,KAAK,cAAc;AACrB,YAAM,KAAK,aAAa,OAAO;AAC/B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,SAAoC;AAC9D,QAAI,UAAmB,QAAQ;AAG/B,QAAI,KAAK,aAAa;AACpB,YAAM,SAAS,KAAK,YAAY,UAAU,OAAO;AACjD,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAASC,cAAa;AAC5B,eAAO,KAAK,mCAAmC;AAAA,UAC7C,WAAW,KAAK;AAAA,UAChB,QAAQ,OAAO,MAAM;AAAA,QACvB,CAAC;AACD;AAAA,MACF;AACA,gBAAU,OAAO;AAAA,IACnB;AAGA,UAAM,UAAU,QAAQ,eAAe,SAAS,KAAK,OAAO,WAAW;AACvE,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA,QAAQA,cAAa;AAAA,IACvB;AAEA,QAAI;AACF,YAAM,KAAK,QAAQ,SAAS,OAAO;AAAA,IACrC,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,cAAQ,OAAO,MAAM,wBAAwB;AAAA,QAC3C,WAAW,KAAK;AAAA,QAChB,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAASA,gBAAe;AACtB,SAAO;AAAA,IACL,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAChE,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,MAAM,CAAC,KAAa,SAClB,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC9D,OAAO,CAAC,KAAa,SACnB,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EAClE;AACF;;;AC3GA,IAAM,YAAwB;AAAA,EAC5B,cAAc,MAAM;AAAA,EAAC;AAAA,EACrB,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,KAAK,MAAM;AAAA,EAAC;AACd;AAOO,IAAM,4BAAN,MAAiE;AAAA;AAAA,EAEtE,UAAU,MAAc,YAAoE;AAC1F,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,MAAc,OAAe,MAAqC;AAAA,EAE/E;AACF;AAGO,IAAM,eAAe,IAAI,0BAA0B;;;AChBnD,IAAM,4BAAN,MAAiE;AAAA,EACrD;AAAA,EAEjB,YAAY,cAAsB,uBAAuB;AACvD,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,UAAU,MAAc,YAAoE;AAC1F,UAAM,SAAS,OAAO,WAAW,EAAE,MAAM,GAAG,EAAE;AAC9C,UAAM,YAAY,KAAK,IAAI;AAE3B,YAAQ;AAAA,MACN,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,CAAC;AAAA,IACH;AAEA,UAAM,iBAA4D,EAAE,GAAG,WAAW;AAElF,WAAO;AAAA,MACL,aAAa,KAAa,OAAwC;AAChE,uBAAe,GAAG,IAAI;AAAA,MACxB;AAAA,MACA,SAAS,OAAoB;AAC3B,uBAAe,OAAO,IAAI;AAC1B,uBAAe,eAAe,IAAI,MAAM;AACxC,gBAAQ;AAAA,UACN,KAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,OAAO,MAAM;AAAA,YACb,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,MAAY;AACV,cAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,gBAAQ;AAAA,UACN,KAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,MAAc,OAAe,MAAqC;AAC7E,YAAQ;AAAA,MACN,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,KAAK;AAAA,QACd,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AClEO,SAAS,4BAA4B,SAElB;AACxB,QAAM,cAAc,QAAQ,IAAI,cAAc;AAE9C,MAAI,gBAAgB,UAAU,gBAAgB,KAAK;AACjD,WAAO,IAAI,0BAA0B,SAAS,WAAW;AAAA,EAC3D;AAEA,SAAO;AACT;;;ACpBO,IAAM,oBAAN,MAAiD;AAAA;AAAA,EAEtD,OAAO,QAA0B;AAAA,EAEjC;AAAA,EAEA,MAAM,QAAuB;AAAA,EAE7B;AACF;AAGO,IAAM,oBAAoB,IAAI,kBAAkB;;;ACLhD,IAAM,uBAAN,MAAoD;AAAA,EACzD,OAAO,OAAyB;AAC9B,YAAQ,OAAO,MAAM,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EACnD;AAAA,EAEA,MAAM,QAAuB;AAAA,EAE7B;AACF;;;ACNO,SAAS,sBAAqC;AACnD,QAAM,eAAe,QAAQ,IAAI,mBAAmB;AACpD,MAAI,iBAAiB,UAAU,iBAAiB,KAAK;AACnD,WAAO,IAAI,qBAAqB;AAAA,EAClC;AACA,SAAO;AACT;;;AClBA,yBAA2B;AAWpB,SAAS,UAAU,OAAwB;AAChD,QAAM,aAAa,KAAK,UAAU,OAAO,CAAC,MAAM,QAAQ;AAEtD,QAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,SAAS;AACjD,QAAI,eAAe,MAAO,QAAO,EAAE,SAAS,IAAI,SAAS,MAAM,IAAI,KAAK;AACxE,QAAI,OAAO,QAAQ,WAAY,QAAO;AACtC,QAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,SAAS;AACjD,QAAI,QAAQ,OAAW,QAAO;AAC9B,WAAO;AAAA,EACT,CAAC;AACD,aAAO,+BAAW,QAAQ,EACvB,OAAO,cAAc,WAAW,EAChC,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAChB;;;ACNO,IAAM,6BAAN,MAA+D;AAAA,EAC5D,gBAAgB,oBAAI,IAAyC;AAAA,EAC7D,SAAS;AAAA,EAEjB,MAAM,QAAQ,OAAe,SAA6C;AACxE,UAAM,YAAY,QAAQ,UAAU,aAAa,OAAO,EAAE,KAAK,MAAM;AACrE,UAAM,gBAAgB,KAAK,cAAc,IAAI,KAAK;AAElD,QAAI,eAAe;AACjB,YAAM,kBAA8B;AAAA,QAClC,GAAG;AAAA,QACH,UAAU;AAAA,UACR,GAAG,QAAQ;AAAA,UACX;AAAA,UACA,WAAW,QAAQ,UAAU,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnE;AAAA,MACF;AAGA,YAAM,WAAW,MAAM,KAAK,cAAc,OAAO,CAAC;AAClD,YAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,YAAY,QAAQ,eAAe,CAAC,CAAC;AAAA,IACvE;AAEA,WAAO,EAAE,WAAW,OAAO,SAAS,KAAK;AAAA,EAC3C;AAAA,EAEA,MAAM,UAAU,OAAe,SAAgD;AAC7E,UAAM,KAAK,OAAO,EAAE,KAAK,MAAM;AAE/B,QAAI,gBAAgB,KAAK,cAAc,IAAI,KAAK;AAChD,QAAI,CAAC,eAAe;AAClB,sBAAgB,oBAAI,IAAI;AACxB,WAAK,cAAc,IAAI,OAAO,aAAa;AAAA,IAC7C;AACA,kBAAc,IAAI,IAAI,OAAO;AAE7B,UAAM,SAAS,YAA2B;AACxC,YAAM,KAAK,YAAY,EAAE,IAAI,OAAO,QAAQ,YAAY;AAAA,MAAC,EAAE,CAAC;AAAA,IAC9D;AAEA,WAAO,EAAE,IAAI,OAAO,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,YAAY,cAA2C;AAC3D,UAAM,gBAAgB,KAAK,cAAc,IAAI,aAAa,KAAK;AAC/D,QAAI,eAAe;AACjB,oBAAc,OAAO,aAAa,EAAE;AACpC,UAAI,cAAc,SAAS,GAAG;AAC5B,aAAK,cAAc,OAAO,aAAa,KAAK;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,qBAAqB,OAAuB;AAC1C,WAAO,KAAK,cAAc,IAAI,KAAK,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,cAAc,MAAM;AAAA,EAC3B;AACF;AAGO,IAAM,sBAAsB,IAAI,2BAA2B;;;AC3ElE;;;ACEO,SAAS,yBAAyB,SAKlB;AACrB,QAAM,eAAe,SAAS,YAAY,QAAQ,IAAI,sBAAsB,KAAK;AAEjF,UAAQ,cAAc;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,IACT,KAAK,OAAO;AAGV,YAAM,EAAE,0BAAAC,0BAAyB,IAAI;AACrC,aAAO,IAAIA,0BAAyB,SAAS,MAAM;AAAA,IACrD;AAAA,IACA;AACE,cAAQ;AAAA,QACN,gEAAgE,YAAY;AAAA,MAC9E;AACA,aAAO;AAAA,EACX;AACF;;;ACtBO,IAAM,+BAAN,MAAmE;AAAA,EAChE,gBAAyE,CAAC;AAAA,EAC1E,SAAS;AAAA,EAEjB,MAAM,KAAK,cAAwD;AACjE,UAAM,iBAAiB,SAAS,EAAE,KAAK,MAAM;AAE7C,SAAK,cAAc,KAAK;AAAA,MACtB,GAAG;AAAA,MACH;AAAA,MACA,UAAU;AAAA,QACR,GAAG,aAAa;AAAA,QAChB,WAAW,aAAa,UAAU,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACxE;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA,SAAS,aAAa;AAAA,MACtB,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAGA,uBAAwF;AACtF,WAAO,CAAC,GAAG,KAAK,aAAa;AAAA,EAC/B;AAAA;AAAA,EAGA,aAAa,SAAkF;AAC7F,WAAO,KAAK,cAAc,OAAO,CAAC,MAAM,EAAE,YAAY,OAAO;AAAA,EAC/D;AAAA;AAAA,EAGA,eACE,WACiE;AACjE,WAAO,KAAK,cAAc,OAAO,CAAC,MAAM,EAAE,cAAc,SAAS;AAAA,EACnE;AAAA;AAAA,EAGA,IAAI,YAAoB;AACtB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,gBAAgB,CAAC;AACtB,SAAK,SAAS;AAAA,EAChB;AACF;AAGO,IAAM,+BAA+B,IAAI,6BAA6B;;;ACrDtE,SAAS,2BAA2B,SAGlB;AACvB,QAAM,eAAe,SAAS,YAAY,QAAQ,IAAI,uBAAuB,KAAK;AAElF,UAAQ,cAAc;AAAA,IACpB,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA,IAIT;AACE,cAAQ;AAAA,QACN,qEAAqE,YAAY;AAAA,MACnF;AACA,aAAO;AAAA,EACX;AACF;;;ACjBO,IAAM,mBAAN,MAA+C;AAAA,EAC3C,OAAO;AAAA;AAAA,EAGhB,MAAM,cAAc,OAA+C;AACjE,WAAO,EAAE,OAAO,OAAO,OAAO,8BAA8B;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAM,cAAc,OAAoC;AACtD,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAAA;AAAA,EAGA,UAAU,QAAoB,MAAuB;AACnD,WAAO;AAAA,EACT;AACF;AAGO,IAAM,mBAAmB,IAAI,iBAAiB;;;ACnB9C,SAAS,mBAAmB,MAAuC;AACxE,UAAQ,MAAM;AAAA,IACZ,KAAK;AAEH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF,KAAK;AAEH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;;;ACpBO,IAAM,yBAAN,MAA2D;AAAA,EACvD,OAAO;AAAA,EAEhB,cAAsC;AACpC,WAAO,CAAC;AAAA,EACV;AAAA;AAAA,EAGA,QAAQ,SAAiB,YAAoB,SAA6C;AACxF,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF;AAAA,MAGF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,yBAAyB,IAAI,uBAAuB;;;AC3BjE,IAAMC,cAAa;AAmDZ,IAAM,4BAAN,MAA8D;AAAA,EAKnE,YAA6B,QAA8B;AAA9B;AAC3B,SAAK,aAAa,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,EAChE;AAAA,EANS,OAAO;AAAA,EAEC;AAAA,EAMjB,cAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,MACtD,IAAI,EAAE;AAAA,MACN,WAAW;AAAA,MACX,YAAY,OAAO,KAAK,EAAE,UAAU;AAAA,MACpC,GAAI,EAAE,gBAAgB,UAAa,EAAE,aAAa,EAAE,YAAY;AAAA,IAClE,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,QAAgB,WAAmB,QAA4C;AAC3F,UAAM,eAAe,KAAK,WAAW,IAAI,MAAM;AAC/C,QAAI,CAAC,cAAc;AACjB,YAAM,eAAe,MAAM,KAAK,KAAK,WAAW,KAAK,CAAC;AACtD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,oBAAoB,MAAM,SACpC,aAAa,SAAS,IACnB,kBAAkB,aAAa,KAAK,IAAI,CAAC,MACzC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,aAAa,WAAW,SAAS;AACjD,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,OAAO,KAAK,aAAa,UAAU;AACpD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,uBAAuB,SAAS,gBAAgB,MAAM,SAChE,SAAS,SAAS,IACf,qBAAqB,SAAS,KAAK,IAAI,CAAC,MACxC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,WAAO,EAAE,KAAK;AAAA,EAChB;AACF;AAOO,SAAS,gCAAgC,QAAkD;AAChG,SAAO,IAAI,0BAA0B,MAAM;AAC7C;AAUO,SAAS,kBAA0C;AACxD,SAAO,CAAC;AACV;;;ACxHA,IAAMC,cAAa;AA8DZ,IAAM,0BAAN,MAA4D;AAAA,EAKjE,YAA6B,QAA4B;AAA5B;AAC3B,SAAK,aAAa,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,EAChE;AAAA,EANS,OAAO;AAAA,EAEC;AAAA,EAMjB,cAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,MACtD,IAAI,EAAE;AAAA,MACN,WAAW;AAAA,MACX,YAAY,OAAO,KAAK,EAAE,UAAU;AAAA,MACpC,GAAI,EAAE,gBAAgB,UAAa,EAAE,aAAa,EAAE,YAAY;AAAA,IAClE,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,QAAgB,WAAmB,QAA4C;AAC3F,UAAM,eAAe,KAAK,WAAW,IAAI,MAAM;AAC/C,QAAI,CAAC,cAAc;AACjB,YAAM,eAAe,MAAM,KAAK,KAAK,WAAW,KAAK,CAAC;AACtD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,oBAAoB,MAAM,SACpC,aAAa,SAAS,IACnB,kBAAkB,aAAa,KAAK,IAAI,CAAC,MACzC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,aAAa,WAAW,SAAS;AACjD,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,OAAO,KAAK,aAAa,UAAU;AACpD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,uBAAuB,SAAS,gBAAgB,MAAM,SAChE,SAAS,SAAS,IACf,qBAAqB,SAAS,KAAK,IAAI,CAAC,MACxC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,WAAO,EAAE,KAAK;AAAA,EAChB;AACF;AAOO,SAAS,8BAA8B,QAAgD;AAC5F,SAAO,IAAI,wBAAwB,MAAM;AAC3C;AAUO,SAASC,mBAA0C;AACxD,SAAO,CAAC;AACV;;;ACnIA,IAAMC,cAAa;AA0EZ,IAAM,8BAAN,MAAgE;AAAA,EAKrE,YAA6B,QAAgC;AAAhC;AAC3B,SAAK,aAAa,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,EAChE;AAAA,EANS,OAAO;AAAA,EAEC;AAAA,EAMjB,cAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,MACtD,IAAI,EAAE;AAAA,MACN,WAAW,EAAE;AAAA,MACb,YAAY,OAAO,KAAK,EAAE,UAAU;AAAA,MACpC,GAAI,EAAE,gBAAgB,UAAa,EAAE,aAAa,EAAE,YAAY;AAAA,IAClE,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,QAAgB,WAAmB,QAA4C;AAC3F,UAAM,eAAe,KAAK,WAAW,IAAI,MAAM;AAC/C,QAAI,CAAC,cAAc;AACjB,YAAM,eAAe,MAAM,KAAK,KAAK,WAAW,KAAK,CAAC;AACtD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,oBAAoB,MAAM,SACpC,aAAa,SAAS,IACnB,kBAAkB,aAAa,KAAK,IAAI,CAAC,MACzC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,aAAa,WAAW,SAAS;AACjD,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,OAAO,KAAK,aAAa,UAAU;AACpD,aAAO,QAAQ;AAAA,QACb,IAAI;AAAA,UACF,GAAGA,WAAU,uBAAuB,SAAS,gBAAgB,MAAM,SAChE,SAAS,SAAS,IACf,qBAAqB,SAAS,KAAK,IAAI,CAAC,MACxC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,WAAO,EAAE,KAAK;AAAA,EAChB;AACF;AAOO,SAAS,kCACd,QACoB;AACpB,SAAO,IAAI,4BAA4B,MAAM;AAC/C;;;ACnEO,SAAS,yBAAyB,SAKlB;AACrB,QAAM,eAAe,SAAS,YAAY,QAAQ,IAAI,sBAAsB,KAAK,cAAc;AAE/F,UAAQ,cAAc;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,IAET,KAAK,WAAW;AAGd,aAAO;AAAA,QACJ,SAAS,UAA+C,EAAE,SAAS,CAAC,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AAGZ,aAAO;AAAA,QACJ,SAAS,UAA6C,EAAE,SAAS,CAAC,EAAE;AAAA,MACvE;AAAA,IACF;AAAA,IAEA,KAAK;AAAA,IACL,KAAK,OAAO;AAIV,aAAO;AAAA,QACJ,SAAS,UAAiD,EAAE,SAAS,CAAC,EAAE;AAAA,MAC3E;AAAA,IACF;AAAA,IAEA;AACE,UAAI,iBAAiB,QAAQ;AAC3B,gBAAQ;AAAA,UACN,iEAAiE,YAAY;AAAA,QAC/E;AAAA,MACF;AACA,aAAO;AAAA,EACX;AACF;AAiBA,SAAS,gBAAwB;AAC/B,QAAM,aAA2D;AAAA;AAAA;AAAA;AAAA;AAAA,IAK/D,EAAE,KAAK,+CAA+C,cAAc,UAAU;AAAA;AAAA,IAE9E,EAAE,KAAK,6CAA6C,cAAc,QAAQ;AAAA;AAAA;AAAA,IAG1E,EAAE,KAAK,uDAAuD,cAAc,YAAY;AAAA,EAC1F;AAEA,aAAW,EAAE,KAAK,aAAa,KAAK,YAAY;AAC9C,QAAI;AACF,cAAQ,QAAQ,GAAG;AACnB,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAAA,EACF;AAKA,SAAO;AACT;;;ACrIO,SAAS,kBAAwC;AACtD,QAAM,UAAkC,CAAC;AACzC,QAAM,oBAA8B,CAAC;AAGrC,MAAI;AACF,oBAAgB,6CAA6C;AAC7D,sBAAkB,KAAK,0BAA0B;AAEjD,QAAI;AAEF,YAAM,MAAM,QAAQ,6CAA6C;AAGjE,UAAI,OAAO,IAAI,oBAAoB,YAAY;AAC7C,gBAAQ,KAAK,GAAG,IAAI,gBAAgB,CAAC;AAAA,MACvC;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,oBAAgB,2CAA2C;AAC3D,sBAAkB,KAAK,wBAAwB;AAE/C,QAAI;AAEF,YAAM,MAAM,QAAQ,2CAA2C;AAG/D,UAAI,OAAO,IAAI,oBAAoB,YAAY;AAC7C,gBAAQ,KAAK,GAAG,IAAI,gBAAgB,CAAC;AAAA,MACvC;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO,EAAE,SAAS,kBAAkB;AACtC;;;ACxEA,0BAA4D;AAU5D,IAAM,kBAAkB;AAMxB,SAAS,oBAA6C;AACpD,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ,EAAE,MAAM,UAAU,MAAM,CAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,EAAE;AAAA,UAC1E,MAAM,EAAE,MAAM,UAAU,SAAS,KAAK;AAAA,UACtC,cAAc,EAAE,MAAM,SAAS;AAAA,QACjC;AAAA,QACA,UAAU,CAAC,UAAU,MAAM;AAAA,MAC7B;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ,EAAE,MAAM,UAAU,SAAS,QAAQ;AAAA,UAC3C,cAAc,EAAE,MAAM,SAAS;AAAA,QACjC;AAAA,QACA,UAAU,CAAC,QAAQ;AAAA,MACrB;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM,EAAE,MAAM,SAAS;AAAA,UACvB,cAAc,EAAE,MAAM,SAAS;AAAA,QACjC;AAAA,QACA,UAAU,CAAC,MAAM;AAAA,MACnB;AAAA,MACA,SAAS,EAAE,MAAM,YAAY,MAAM,eAAe,cAAc,sBAAsB;AAAA,IACxF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ,EAAE,MAAM,UAAU,SAAS,UAAU;AAAA,UAC7C,YAAY,EAAE,MAAM,UAAU,SAAS,GAAG,SAAS,GAAG;AAAA,UACtD,cAAc,EAAE,MAAM,SAAS;AAAA,QACjC;AAAA,QACA,UAAU,CAAC,QAAQ;AAAA,MACrB;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,wBAAgD;AACvD,QAAM,WAAW,IAAI,uCAAmB;AACxC,mDAAwB,QAAQ;AAEhC,SAAO,SAAS,QAAQ,EAAE,IAAI,CAAC,QAAQ;AACrC,UAAM,aAAmC;AAAA,MACvC,MAAM,IAAI,WAAW;AAAA,MACrB,MAAM,IAAI,WAAW;AAAA,MACrB,aAAa,IAAI,WAAW;AAAA,MAC5B,aAAa,IAAI,WAAW;AAAA,MAC5B,cAAc,IAAI,WAAW;AAAA,IAC/B;AAEA,QAAI,IAAI,WAAW,SAAS,UAAU;AACpC,iBAAW,sBAAsB,IAAI,WAAW;AAAA,IAClD;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAOA,SAAS,uBAAoD;AAC3D,QAAM,aAAa,gBAAgB;AACnC,SAAO,WAAW,QAAQ,IAAI,CAAC,YAAY;AAAA,IACzC,IAAI,OAAO;AAAA,IACX,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,EACrB,EAAE;AACJ;AASO,SAAS,mBAAyC;AACvD,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS;AAAA,IACT,UAAU,kBAAkB;AAAA,IAC5B,cAAc,sBAAsB;AAAA,IACpC,aAAa,qBAAqB;AAAA,IAClC,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,EACvC;AACF;","names":["listDataSources","createLogger","createLogger","createLogger","SqsSnsMessageBusProvider","LOG_PREFIX","LOG_PREFIX","listDataSources","LOG_PREFIX"]}
|
|
1
|
+
{"version":3,"sources":["../src/messaging/sqs-sns.ts","../src/index.ts","../src/triggers/http.ts","../src/triggers/event.ts","../src/triggers/schedule.ts","../src/triggers/queue.ts","../src/observability/noop.ts","../src/observability/otel.ts","../src/observability/factory.ts","../src/observability/audit-noop.ts","../src/observability/audit-console.ts","../src/observability/audit-factory.ts","../src/observability/audit-hash.ts","../src/messaging/noop.ts","../src/messaging/index.ts","../src/messaging/factory.ts","../src/notifications/noop.ts","../src/notifications/factory.ts","../src/auth/noop.ts","../src/auth/factory.ts","../src/datasource/noop.ts","../src/datasource/openapi-adapter.ts","../src/datasource/pulse-adapter.ts","../src/datasource/streaming-adapter.ts","../src/datasource/factory.ts","../src/datasource/scan.ts","../src/prebuild/register.ts"],"sourcesContent":["/**\n * SQS/SNS MessageBusProvider — the first concrete adapter.\n *\n * Architecture:\n * - PUBLISH: Uses SNS Publish to deliver messages to a topic ARN.\n * - SUBSCRIBE: Uses SQS long-polling (ReceiveMessage) to consume from a queue URL.\n *\n * Topic/queue resolution:\n * - Logical topic name → SNS Topic ARN via config map or env var:\n * BUS_TOPIC_{UPPER_SNAKE_NAME}_ARN (e.g. BUS_TOPIC_EQUIPMENT_STATUS_ARN)\n * - Logical queue name → SQS Queue URL via config map or env var:\n * BUS_QUEUE_{UPPER_SNAKE_NAME}_URL (e.g. BUS_QUEUE_EQUIPMENT_STATUS_URL)\n *\n * Trace propagation:\n * - traceContext serialized as SNS/SQS MessageAttributes (StringValue)\n * - metadata fields (timestamp, source, correlationId) also as MessageAttributes\n *\n * Graceful shutdown:\n * - Each subscription has a polling loop with an `active` flag\n * - stop()/unsubscribe() sets active=false, polling loop exits after current\n * ReceiveMessage returns\n *\n * AWS credentials:\n * - Uses standard AWS SDK v3 credential chain (env vars, instance profile, etc.)\n * - NO credential handling in this adapter\n *\n * Design note: This is a thin wrapper. No retry logic beyond SDK defaults,\n * no DLQ support, no batch processing. Production hardening is a separate bead.\n */\n\nimport {\n SNSClient,\n PublishCommand,\n type PublishCommandInput,\n type MessageAttributeValue as SNSMessageAttributeValue,\n} from '@aws-sdk/client-sns';\nimport {\n SQSClient,\n ReceiveMessageCommand,\n DeleteMessageCommand,\n type Message,\n type MessageAttributeValue as SQSMessageAttributeValue,\n} from '@aws-sdk/client-sqs';\nimport type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:messaging';\n\nexport interface SqsSnsConfig {\n /** AWS region (defaults to AWS_REGION env var or 'us-east-1') */\n region?: string;\n /** SNS Topic ARN mapping: logical name → ARN. Overrides env vars. */\n topicArns?: Record<string, string>;\n /** SQS Queue URL mapping: logical name → URL. Overrides env vars. */\n queueUrls?: Record<string, string>;\n /** SQS long-poll wait time in seconds (default: 20, max for long-polling) */\n waitTimeSeconds?: number;\n /** Max messages per ReceiveMessage call (default: 10) */\n maxMessages?: number;\n /**\n * Minimum delay between poll cycles in ms (default: 100).\n * Prevents tight-spinning when waitTimeSeconds is low or the queue is\n * empty and the SDK resolves instantly. In production with\n * waitTimeSeconds=20 the 100ms gap is negligible.\n */\n pollIntervalMs?: number;\n /** Optional SNS client (for testing/DI) */\n snsClient?: SNSClient;\n /** Optional SQS client (for testing/DI) */\n sqsClient?: SQSClient;\n}\n\n/** Convert a logical topic name to UPPER_SNAKE_CASE for env var lookup. */\nexport function toUpperSnake(name: string): string {\n return name.replace(/[-.]/g, '_').toUpperCase();\n}\n\ninterface PollingState {\n active: boolean;\n}\n\nexport class SqsSnsMessageBusProvider implements MessageBusProvider {\n private readonly snsClient: SNSClient;\n private readonly sqsClient: SQSClient;\n private readonly topicArns: Record<string, string>;\n private readonly queueUrls: Record<string, string>;\n private readonly waitTimeSeconds: number;\n private readonly maxMessages: number;\n private readonly pollIntervalMs: number;\n private readonly pollingStates = new Map<string, PollingState>();\n\n constructor(config: SqsSnsConfig = {}) {\n const region = config.region ?? process.env['AWS_REGION'] ?? 'us-east-1';\n this.snsClient = config.snsClient ?? new SNSClient({ region });\n this.sqsClient = config.sqsClient ?? new SQSClient({ region });\n this.topicArns = config.topicArns ?? {};\n this.queueUrls = config.queueUrls ?? {};\n this.waitTimeSeconds = config.waitTimeSeconds ?? 20;\n this.maxMessages = config.maxMessages ?? 10;\n this.pollIntervalMs = config.pollIntervalMs ?? 100;\n }\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const topicArn = this.resolveTopicArn(topic);\n const attributes = this.buildSnsAttributes(message);\n\n const input: PublishCommandInput = {\n TopicArn: topicArn,\n Message: JSON.stringify(message.payload),\n MessageAttributes: attributes,\n };\n\n const response = await this.snsClient.send(new PublishCommand(input));\n const messageId = response.MessageId ?? `sns-${Date.now()}`;\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const queueUrl = this.resolveQueueUrl(topic);\n const id = `sqs-sub-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const state: PollingState = { active: true };\n this.pollingStates.set(id, state);\n\n // Fire-and-forget: polling loop runs in background\n this.poll(queueUrl, handler, state);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const state = this.pollingStates.get(subscription.id);\n if (state) {\n state.active = false;\n this.pollingStates.delete(subscription.id);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private resolveTopicArn(topic: string): string {\n const fromConfig = this.topicArns[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_TOPIC_${toUpperSnake(topic)}_ARN`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SNS Topic ARN found for \"${topic}\". ` +\n `Set config.topicArns[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private resolveQueueUrl(topic: string): string {\n const fromConfig = this.queueUrls[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_QUEUE_${toUpperSnake(topic)}_URL`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SQS Queue URL found for \"${topic}\". ` +\n `Set config.queueUrls[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private buildSnsAttributes(message: BusMessage): Record<string, SNSMessageAttributeValue> {\n const attrs: Record<string, SNSMessageAttributeValue> = {};\n\n // Serialize traceContext fields\n if (message.traceContext) {\n for (const [key, value] of Object.entries(message.traceContext)) {\n attrs[`trace.${key}`] = { DataType: 'String', StringValue: value };\n }\n }\n\n // Serialize metadata fields\n if (message.metadata) {\n const { timestamp, source, correlationId } = message.metadata;\n if (timestamp) {\n attrs['meta.timestamp'] = { DataType: 'String', StringValue: timestamp };\n }\n if (source) {\n attrs['meta.source'] = { DataType: 'String', StringValue: source };\n }\n if (correlationId) {\n attrs['meta.correlationId'] = { DataType: 'String', StringValue: correlationId };\n }\n }\n\n return attrs;\n }\n\n private async poll(\n queueUrl: string,\n handler: MessageHandler,\n state: PollingState,\n ): Promise<void> {\n while (state.active) {\n // Delay between poll cycles to prevent tight-spinning when\n // waitTimeSeconds is low or the mock/SDK resolves instantly.\n await new Promise<void>((resolve) => setTimeout(resolve, this.pollIntervalMs));\n if (!state.active) break;\n\n try {\n const response = await this.sqsClient.send(\n new ReceiveMessageCommand({\n QueueUrl: queueUrl,\n WaitTimeSeconds: this.waitTimeSeconds,\n MaxNumberOfMessages: this.maxMessages,\n MessageAttributeNames: ['All'],\n }),\n );\n\n for (const sqsMessage of response.Messages ?? []) {\n if (!state.active) break;\n\n const busMessage = this.parseSqsMessage(sqsMessage);\n try {\n await handler(busMessage);\n } catch (handlerError) {\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'handler_error',\n error: handlerError instanceof Error ? handlerError.message : String(handlerError),\n queueUrl,\n }),\n );\n // Continue processing — don't crash the polling loop\n continue;\n }\n\n // Delete only after successful handler invocation\n if (sqsMessage.ReceiptHandle) {\n await this.sqsClient.send(\n new DeleteMessageCommand({\n QueueUrl: queueUrl,\n ReceiptHandle: sqsMessage.ReceiptHandle,\n }),\n );\n }\n }\n } catch (pollError) {\n // Log polling errors but keep the loop alive\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'poll_error',\n error: pollError instanceof Error ? pollError.message : String(pollError),\n queueUrl,\n }),\n );\n }\n }\n }\n\n private parseSqsMessage(sqsMessage: Message): BusMessage {\n const payload = sqsMessage.Body ? JSON.parse(sqsMessage.Body) : null;\n const traceContext = this.extractTraceContext(sqsMessage.MessageAttributes);\n const metadata = this.extractMetadata(sqsMessage.MessageAttributes);\n\n return {\n payload,\n ...(traceContext !== undefined && { traceContext }),\n ...(metadata !== undefined && { metadata }),\n };\n }\n\n private extractTraceContext(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): Record<string, string> | undefined {\n if (!attrs) return undefined;\n\n const trace: Record<string, string> = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith('trace.') && value.StringValue) {\n trace[key.slice('trace.'.length)] = value.StringValue;\n }\n }\n\n return Object.keys(trace).length > 0 ? trace : undefined;\n }\n\n private extractMetadata(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): BusMessage['metadata'] {\n if (!attrs) return undefined;\n\n const timestamp = attrs['meta.timestamp']?.StringValue;\n const source = attrs['meta.source']?.StringValue;\n const correlationId = attrs['meta.correlationId']?.StringValue;\n\n if (!timestamp && !source && !correlationId) return undefined;\n\n return {\n ...(timestamp && { timestamp }),\n ...(source && { source }),\n ...(correlationId && { correlationId }),\n };\n }\n}\n","// @stackwright-services/runtime\n// Runtime layer for Stackwright Services -- Hono HTTP server, trigger adapters, observability.\n\nexport {\n createHttpTrigger,\n type HttpTriggerOptions,\n type ServiceError,\n type TriggerAdapter,\n EventTriggerAdapter,\n type EventTriggerOptions,\n ScheduleTriggerAdapter,\n type ScheduleTriggerOptions,\n QueueTriggerAdapter,\n type QueueTriggerOptions,\n} from './triggers';\n\nexport {\n type ObservabilityProvider,\n type SpanHandle,\n NoopObservabilityProvider,\n noopProvider,\n OtelObservabilityProvider,\n createObservabilityProvider,\n type AuditEvent,\n type AuditProvider,\n NoopAuditProvider,\n noopAuditProvider,\n ConsoleAuditProvider,\n createAuditProvider,\n auditHash,\n} from './observability';\n\nexport {\n type MessageBusProvider,\n type BusMessage,\n type MessageMetadata,\n type PublishResult,\n type MessageHandler,\n type Subscription,\n InMemoryMessageBusProvider,\n inMemoryBusProvider,\n SqsSnsMessageBusProvider,\n type SqsSnsConfig,\n createMessageBusProvider,\n} from './messaging';\n\nexport {\n type NotificationProvider,\n type NotificationMessage,\n type NotificationMetadata,\n type NotificationChannel,\n type SendResult,\n InMemoryNotificationProvider,\n inMemoryNotificationProvider,\n createNotificationProvider,\n} from './notifications';\n\nexport {\n type AuthProvider,\n type AuthClaims,\n type TokenValidationResult,\n NoopAuthProvider,\n noopAuthProvider,\n createAuthProvider,\n type AuthProviderType,\n} from './auth';\n\nexport {\n type DataSourceProvider,\n type DataSourceDescriptor,\n type DataSourceResult,\n type DataSourceScanResult,\n NoopDataSourceProvider,\n noopDataSourceProvider,\n createDataSourceProvider,\n scanDataSources,\n OpenApiDataSourceProvider,\n createOpenApiDataSourceProvider,\n listOpenApiDataSources,\n type OpenApiAdapterConfig,\n type OpenApiSourceRegistration,\n type OpenApiOperationHandler,\n PulseDataSourceProvider,\n createPulseDataSourceProvider,\n listPulseDataSources,\n type PulseAdapterConfig,\n type PulseSourceRegistration,\n type PulseOperationHandler,\n} from './datasource';\n\nexport {\n registerServices,\n type PrebuildRegistration,\n type TriggerTypeDescriptor,\n type CapabilityDescriptor,\n type DataSourceDescriptorEntry,\n} from './prebuild';\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { HttpTrigger } from '@stackwright-services/types';\nimport { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport type { z } from 'zod';\n\n/**\n * Options for creating an HTTP trigger runtime.\n */\nexport interface HttpTriggerOptions {\n /** The HTTP trigger configuration from the flow */\n trigger: HttpTrigger;\n /** Flow handler function */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional input validation schema */\n inputSchema?: z.ZodType;\n /** Optional output validation schema */\n outputSchema?: z.ZodType;\n}\n\n/**\n * Typed error response for consistent error handling.\n */\nexport interface ServiceError {\n error: string;\n code: string;\n details?: unknown;\n}\n\n/**\n * Create a Hono app for an HTTP trigger.\n *\n * This is the runtime entry point for HTTP-triggered flows.\n * The same code works on:\n * - Node.js (via @hono/node-server)\n * - AWS Lambda (via Lambda Web Adapter)\n * - Edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport function createHttpTrigger(options: HttpTriggerOptions): Hono {\n const { trigger, handler, inputSchema, outputSchema } = options;\n const app = new Hono();\n\n // Health check\n app.get('/health', (c) => c.json({ status: 'ok', trigger: 'http' }));\n\n // Register the flow route\n const method = trigger.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n\n app[method](trigger.path, async (c: Context) => {\n // Extract input based on method\n let input: unknown;\n if (trigger.method === 'GET') {\n input = Object.fromEntries(new URL(c.req.url).searchParams);\n } else {\n try {\n input = await c.req.json();\n } catch {\n return c.json<ServiceError>(\n { error: 'Invalid JSON body', code: 'INVALID_REQUEST_BODY' },\n 400,\n );\n }\n }\n\n // Validate input if schema provided\n if (inputSchema) {\n const result = inputSchema.safeParse(input);\n if (!result.success) {\n return c.json<ServiceError>(\n {\n error: 'Input validation failed',\n code: 'VALIDATION_ERROR',\n details: result.error.issues,\n },\n 400,\n );\n }\n input = result.data;\n }\n\n // Create context\n const context: CapabilityContext = {\n traceId: c.req.header('x-trace-id') ?? c.req.header('x-request-id') ?? crypto.randomUUID(),\n logger: createLogger(),\n };\n\n // Execute flow\n try {\n const result = await handler(input, context);\n\n // Validate output if schema provided\n if (outputSchema) {\n const outputResult = outputSchema.safeParse(result);\n if (!outputResult.success) {\n return c.json<ServiceError>(\n { error: 'Output validation failed', code: 'OUTPUT_VALIDATION_ERROR' },\n 500,\n );\n }\n return c.json(outputResult.data);\n }\n\n return c.json(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return c.json<ServiceError>({ error: message, code: 'FLOW_EXECUTION_ERROR' }, 500);\n }\n });\n\n return app;\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { EventTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating an event trigger adapter.\n */\nexport interface EventTriggerOptions {\n /** The event trigger configuration from the flow */\n trigger: EventTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * EventTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class EventTriggerAdapter implements TriggerAdapter {\n readonly type = 'event';\n readonly topic: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: EventTriggerOptions) {\n this.topic = options.trigger.source.replace(/^bus:/, '');\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.topic, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Event payload validation failed', {\n topic: this.topic,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Event handler failed', {\n topic: this.topic,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { ScheduleTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a schedule trigger adapter.\n */\nexport interface ScheduleTriggerOptions {\n /** The schedule trigger configuration from the flow */\n trigger: ScheduleTrigger;\n /** Flow handler function invoked on each tick */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation */\n inputSchema?: z.ZodType;\n /**\n * Override interval in milliseconds for local dev / testing.\n * When not provided, defaults to 60_000ms and logs a warning that\n * cron parsing is not built-in. In production, scheduling is handled\n * by infrastructure (EventBridge, CronJob on K8s, etc.).\n */\n intervalMs?: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 60_000;\n\n/**\n * ScheduleTriggerAdapter — local-dev / test scheduler that fires the flow\n * handler on a fixed interval.\n *\n * NOT a production cron implementation. In production the cron expression\n * is consumed by infrastructure (EventBridge rules, K8s CronJobs, etc.)\n * and this adapter is not used.\n *\n * Handler errors are caught and logged — the scheduler never crashes.\n */\nexport class ScheduleTriggerAdapter implements TriggerAdapter {\n readonly type = 'schedule';\n readonly cron: string;\n\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private readonly intervalMs: number;\n private timer: ReturnType<typeof setInterval> | undefined;\n\n constructor(options: ScheduleTriggerOptions) {\n this.cron = options.trigger.cron;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n }\n\n async start(): Promise<void> {\n if (this.intervalMs === DEFAULT_INTERVAL_MS) {\n const logger = createLogger();\n logger.warn('Cron parsing not built-in; using default 60s interval for local dev', {\n cron: this.cron,\n intervalMs: this.intervalMs,\n });\n }\n\n this.timer = setInterval(() => {\n void this.tick();\n }, this.intervalMs);\n }\n\n async stop(): Promise<void> {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }\n\n private async tick(): Promise<void> {\n const traceId = crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler({}, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Schedule handler failed', {\n cron: this.cron,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { QueueTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a queue trigger adapter.\n */\nexport interface QueueTriggerOptions {\n /** The queue trigger configuration from the flow */\n trigger: QueueTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * QueueTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Semantically represents point-to-point delivery (single consumer), unlike\n * the fan-out semantics of EventTriggerAdapter. At the runtime adapter level\n * both use messageBus.subscribe() — the distinction lives in the concrete\n * bus implementation (SQS vs SNS+SQS, competing consumers vs broadcast).\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class QueueTriggerAdapter implements TriggerAdapter {\n readonly type = 'queue';\n readonly queueName: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: QueueTriggerOptions) {\n this.queueName = options.trigger.name;\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.queueName, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Queue payload validation failed', {\n queueName: this.queueName,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Queue handler failed', {\n queueName: this.queueName,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\nconst NOOP_SPAN: SpanHandle = {\n setAttribute: () => {},\n setError: () => {},\n end: () => {},\n};\n\n/**\n * No-op observability provider -- zero runtime cost.\n * Used when OTel is not configured (the default).\n * All methods are no-ops that return immediately.\n */\nexport class NoopObservabilityProvider implements ObservabilityProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n return NOOP_SPAN;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n // Intentionally empty -- zero cost when disabled\n }\n}\n\n/** Singleton no-op provider */\nexport const noopProvider = new NoopObservabilityProvider();\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\n/**\n * OpenTelemetry-compatible observability provider.\n *\n * In Phase 1, this uses structured console logging with span semantics.\n * In Phase 2+, this wraps @opentelemetry/api (trace + metrics).\n *\n * The interface is stable -- upgrading to real OTel is a drop-in replacement.\n */\nexport class OtelObservabilityProvider implements ObservabilityProvider {\n private readonly serviceName: string;\n\n constructor(serviceName: string = 'stackwright-service') {\n this.serviceName = serviceName;\n }\n\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n const spanId = crypto.randomUUID().slice(0, 16);\n const startTime = Date.now();\n\n console.info(\n JSON.stringify({\n type: 'span_start',\n spanId,\n name,\n service: this.serviceName,\n attributes,\n timestamp: new Date().toISOString(),\n }),\n );\n\n const spanAttributes: Record<string, string | number | boolean> = { ...attributes };\n\n return {\n setAttribute(key: string, value: string | number | boolean): void {\n spanAttributes[key] = value;\n },\n setError(error: Error): void {\n spanAttributes['error'] = true;\n spanAttributes['error.message'] = error.message;\n console.error(\n JSON.stringify({\n type: 'span_error',\n spanId,\n name,\n error: error.message,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n end(): void {\n const duration = Date.now() - startTime;\n console.info(\n JSON.stringify({\n type: 'span_end',\n spanId,\n name,\n duration,\n attributes: spanAttributes,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n };\n }\n\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n console.info(\n JSON.stringify({\n type: 'metric',\n name,\n value,\n tags,\n service: this.serviceName,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n}\n","import type { ObservabilityProvider } from './provider';\nimport { noopProvider } from './noop';\nimport { OtelObservabilityProvider } from './otel';\n\n/**\n * Create an observability provider based on environment configuration.\n *\n * - OTEL_ENABLED=true (or \"1\") -> OtelObservabilityProvider\n * - Otherwise -> NoopObservabilityProvider (zero cost)\n *\n * The provider is injected into compiled flow code, not imported.\n * This means zero runtime overhead when observability is disabled.\n */\nexport function createObservabilityProvider(options?: {\n serviceName?: string;\n}): ObservabilityProvider {\n const otelEnabled = process.env['OTEL_ENABLED'];\n\n if (otelEnabled === 'true' || otelEnabled === '1') {\n return new OtelObservabilityProvider(options?.serviceName);\n }\n\n return noopProvider;\n}\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/** No-op audit provider -- zero runtime cost when auditing is disabled */\nexport class NoopAuditProvider implements AuditProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n record(_event: AuditEvent): void {\n // Intentionally empty\n }\n\n async flush(): Promise<void> {\n // Nothing to flush\n }\n}\n\n/** Singleton no-op audit provider */\nexport const noopAuditProvider = new NoopAuditProvider();\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/**\n * Console audit provider -- writes events to stderr as JSON Lines.\n *\n * Works in Lambda (stderr -> CloudWatch), containers (stderr -> log collector),\n * and local dev (stderr -> terminal).\n *\n * Uses stderr to avoid mixing with application stdout.\n */\nexport class ConsoleAuditProvider implements AuditProvider {\n record(event: AuditEvent): void {\n process.stderr.write(JSON.stringify(event) + '\\n');\n }\n\n async flush(): Promise<void> {\n // Console writes are synchronous -- nothing to flush\n }\n}\n","import type { AuditProvider } from './audit';\nimport { noopAuditProvider } from './audit-noop';\nimport { ConsoleAuditProvider } from './audit-console';\n\n/**\n * Create an audit provider based on environment configuration.\n *\n * - STACKWRIGHT_AUDIT=true (or \"1\") -> ConsoleAuditProvider (stderr JSON Lines)\n * - Otherwise -> NoopAuditProvider (zero cost)\n *\n * Defaults to OFF in production, can be enabled with env var.\n */\nexport function createAuditProvider(): AuditProvider {\n const auditEnabled = process.env['STACKWRIGHT_AUDIT'];\n if (auditEnabled === 'true' || auditEnabled === '1') {\n return new ConsoleAuditProvider();\n }\n return noopAuditProvider;\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Compute a truncated SHA-256 hash of a value.\n *\n * Used for audit events -- captures enough to detect \"did the input/output change?\"\n * without storing full payloads (which may be large or contain PII).\n *\n * Returns first 16 hex characters of SHA-256.\n * Deterministic: same input always produces same hash.\n */\nexport function auditHash(value: unknown): string {\n const serialized = JSON.stringify(value, (_key, val) => {\n // Handle non-serializable types gracefully\n if (typeof val === 'bigint') return val.toString();\n if (val instanceof Error) return { message: val.message, name: val.name };\n if (typeof val === 'function') return '[function]';\n if (typeof val === 'symbol') return val.toString();\n if (val === undefined) return null;\n return val;\n });\n return createHash('sha256')\n .update(serialized ?? 'undefined')\n .digest('hex')\n .slice(0, 16);\n}\n","import type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\n/**\n * In-memory MessageBusProvider — delivers messages locally within the process.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external bus is configured\n *\n * Messages published to a topic are delivered synchronously to all\n * subscribed handlers for that topic.\n */\nexport class InMemoryMessageBusProvider implements MessageBusProvider {\n private subscriptions = new Map<string, Map<string, MessageHandler>>();\n private nextId = 0;\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const messageId = message.metadata?.messageId ?? `mem-${++this.nextId}`;\n const topicHandlers = this.subscriptions.get(topic);\n\n if (topicHandlers) {\n const enrichedMessage: BusMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n messageId,\n timestamp: message.metadata?.timestamp ?? new Date().toISOString(),\n },\n };\n\n // Deliver to all subscribers\n const handlers = Array.from(topicHandlers.values());\n await Promise.all(handlers.map((handler) => handler(enrichedMessage)));\n }\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const id = `sub-${++this.nextId}`;\n\n let topicHandlers = this.subscriptions.get(topic);\n if (!topicHandlers) {\n topicHandlers = new Map();\n this.subscriptions.set(topic, topicHandlers);\n }\n topicHandlers.set(id, handler);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const topicHandlers = this.subscriptions.get(subscription.topic);\n if (topicHandlers) {\n topicHandlers.delete(subscription.id);\n if (topicHandlers.size === 0) {\n this.subscriptions.delete(subscription.topic);\n }\n }\n }\n\n /** Helper for testing: get count of active subscriptions for a topic */\n getSubscriptionCount(topic: string): number {\n return this.subscriptions.get(topic)?.size ?? 0;\n }\n\n /** Helper for testing: clear all subscriptions */\n clear(): void {\n this.subscriptions.clear();\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryBusProvider = new InMemoryMessageBusProvider();\n","export type {\n MessageBusProvider,\n BusMessage,\n MessageMetadata,\n PublishResult,\n MessageHandler,\n Subscription,\n} from './provider';\nexport { InMemoryMessageBusProvider, inMemoryBusProvider } from './noop';\nexport { SqsSnsMessageBusProvider, type SqsSnsConfig } from './sqs-sns';\nexport { createMessageBusProvider } from './factory';\n","import type { MessageBusProvider } from './provider';\nimport { inMemoryBusProvider } from './noop';\n\n/**\n * Create a MessageBusProvider based on environment configuration.\n *\n * - MESSAGE_BUS_PROVIDER=memory (or unset) -> InMemoryMessageBusProvider\n * - MESSAGE_BUS_PROVIDER=sqs -> SQS/SNS adapter\n *\n * Same pattern as createObservabilityProvider().\n */\nexport function createMessageBusProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n /** Provider-specific config (e.g. SqsSnsConfig for 'sqs') */\n config?: Record<string, unknown>;\n}): MessageBusProvider {\n const providerType = options?.provider ?? process.env['MESSAGE_BUS_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryBusProvider;\n case 'sqs': {\n // Dynamic require to avoid bundling AWS SDK when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SqsSnsMessageBusProvider } = require('./sqs-sns') as typeof import('./sqs-sns');\n return new SqsSnsMessageBusProvider(options?.config);\n }\n default:\n console.warn(\n `stackwright-services:messaging Unknown MESSAGE_BUS_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryBusProvider;\n }\n}\n","import type { NotificationMessage, NotificationProvider, SendResult } from './provider';\n\n/**\n * In-memory NotificationProvider — records notifications locally for inspection.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external notification service is configured\n *\n * Notifications are stored in-memory and can be inspected via helper methods.\n */\nexport class InMemoryNotificationProvider implements NotificationProvider {\n private notifications: Array<NotificationMessage & { notificationId: string }> = [];\n private nextId = 0;\n\n async send(notification: NotificationMessage): Promise<SendResult> {\n const notificationId = `notif-${++this.nextId}`;\n\n this.notifications.push({\n ...notification,\n notificationId,\n metadata: {\n ...notification.metadata,\n timestamp: notification.metadata?.timestamp ?? new Date().toISOString(),\n },\n });\n\n return {\n notificationId,\n channel: notification.channel,\n success: true,\n };\n }\n\n /** Helper for testing: get all sent notifications */\n getSentNotifications(): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return [...this.notifications];\n }\n\n /** Helper for testing: get notifications filtered by channel */\n getByChannel(channel: string): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.channel === channel);\n }\n\n /** Helper for testing: get notifications filtered by recipient */\n getByRecipient(\n recipient: string,\n ): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.recipient === recipient);\n }\n\n /** Helper for testing: get count of sent notifications */\n get sentCount(): number {\n return this.notifications.length;\n }\n\n /** Helper for testing: clear all recorded notifications */\n clear(): void {\n this.notifications = [];\n this.nextId = 0;\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryNotificationProvider = new InMemoryNotificationProvider();\n","import type { NotificationProvider } from './provider';\nimport { inMemoryNotificationProvider } from './noop';\n\n/**\n * Create a NotificationProvider based on environment configuration.\n *\n * - NOTIFICATION_PROVIDER=memory (or unset) -> InMemoryNotificationProvider\n * - NOTIFICATION_PROVIDER=sendgrid -> (future: SendGrid adapter)\n * - NOTIFICATION_PROVIDER=twilio -> (future: Twilio adapter)\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createNotificationProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n}): NotificationProvider {\n const providerType = options?.provider ?? process.env['NOTIFICATION_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryNotificationProvider;\n // Future: case 'sendgrid' -> SendGrid adapter\n // Future: case 'twilio' -> Twilio/SNS adapter\n // Future: case 'fcm' -> Firebase Cloud Messaging adapter\n default:\n console.warn(\n `stackwright-services:notifications Unknown NOTIFICATION_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryNotificationProvider;\n }\n}\n","import type { AuthClaims, AuthProvider, TokenValidationResult } from './provider';\n\n/**\n * No-op AuthProvider — fail-closed default.\n *\n * Used when no auth provider is configured:\n * - validateToken() always returns { valid: false } (reject all tokens)\n * - extractClaims() throws (no claims without a real provider)\n * - checkRole() always returns false (deny all role checks)\n *\n * This is intentionally fail-closed: if you forget to install a real\n * auth provider, every auth check fails rather than silently passing.\n */\nexport class NoopAuthProvider implements AuthProvider {\n readonly name = 'noop';\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async validateToken(token: string): Promise<TokenValidationResult> {\n return { valid: false, error: 'No auth provider configured' };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async extractClaims(token: string): Promise<AuthClaims> {\n throw new Error('No auth provider configured');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n checkRole(claims: AuthClaims, role: string): boolean {\n return false;\n }\n}\n\n/** Singleton no-op provider */\nexport const noopAuthProvider = new NoopAuthProvider();\n","import type { AuthProvider } from './provider';\nimport { noopAuthProvider } from './noop';\n\nexport type AuthProviderType = 'noop' | 'oidc' | 'cac';\n\n/**\n * Create an AuthProvider based on the requested type.\n *\n * - 'noop' (or unset) -> NoopAuthProvider (fail-closed default)\n * - 'oidc' -> Future: lazy require('@stackwright-pro/auth-oidc')\n * - 'cac' -> Future: lazy require('@stackwright-pro/auth-cac')\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createAuthProvider(type?: AuthProviderType): AuthProvider {\n switch (type) {\n case 'oidc':\n // Future: lazy require('@stackwright-pro/auth-oidc')\n throw new Error(\n 'OIDC auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'cac':\n // Future: lazy require('@stackwright-pro/auth-cac')\n throw new Error(\n 'CAC/PKI auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'noop':\n default:\n return noopAuthProvider;\n }\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\n/**\n * NoopDataSourceProvider — used when no data source provider is installed.\n *\n * listSources() returns an empty array (no sources available to the schema expander).\n * execute() throws a descriptive error pointing to the correct package to install.\n *\n * This is the fail-closed default, consistent with NoopAuthProvider.\n */\nexport class NoopDataSourceProvider implements DataSourceProvider {\n readonly name = 'noop';\n\n listSources(): DataSourceDescriptor[] {\n return [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(_source: string, _operation: string, _params: unknown): Promise<DataSourceResult> {\n return Promise.reject(\n new Error(\n 'No DataSourceProvider is configured. ' +\n 'Install @stackwright-pro/openapi or @stackwright-pro/pulse and register an adapter, ' +\n 'or set DATA_SOURCE_PROVIDER in your environment.',\n ),\n );\n }\n}\n\nexport const noopDataSourceProvider = new NoopDataSourceProvider();\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:openapi';\n\n/**\n * A typed operation handler for a single OpenAPI operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type OpenApiOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single OpenAPI-backed data source.\n */\nexport interface OpenApiSourceRegistration {\n /** Source ID — matches the id in `source: openapi:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, OpenApiOperationHandler>;\n}\n\n/**\n * Configuration for OpenApiDataSourceProvider.\n */\nexport interface OpenApiAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: OpenApiSourceRegistration[];\n}\n\n/**\n * OpenApiDataSourceProvider — wraps registered OpenAPI operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed OpenAPI client methods (from @stackwright-pro/openapi),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/openapi` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class OpenApiDataSourceProvider implements DataSourceProvider {\n readonly name = 'openapi';\n\n private readonly sourcesMap: Map<string, OpenApiSourceRegistration>;\n\n constructor(private readonly config: OpenApiAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'openapi' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in OpenApiAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates an OpenApiDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/openapi's datasource-adapter when installed.\n */\nexport function createOpenApiDataSourceProvider(config: OpenApiAdapterConfig): DataSourceProvider {\n return new OpenApiDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/openapi's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: openapi:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:pulse';\n\n/**\n * A typed operation handler for a single Pulse operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type PulseOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single Pulse-backed data source.\n */\nexport interface PulseSourceRegistration {\n /** Source ID — matches the id in `source: pulse:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, PulseOperationHandler>;\n}\n\n/**\n * Configuration for PulseDataSourceProvider.\n */\nexport interface PulseAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: PulseSourceRegistration[];\n}\n\n/**\n * PulseDataSourceProvider — wraps registered Pulse operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed Pulse client methods (from @stackwright-pro/pulse),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/pulse` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Usage example:\n * ```typescript\n * const provider = createPulseDataSourceProvider({\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryMetrics: pulseClient.queryMetrics },\n * }],\n * });\n * // Matches `source: pulse:fleet-db` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class PulseDataSourceProvider implements DataSourceProvider {\n readonly name = 'pulse';\n\n private readonly sourcesMap: Map<string, PulseSourceRegistration>;\n\n constructor(private readonly config: PulseAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'pulse' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in PulseAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a PulseDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/pulse's datasource-adapter when installed.\n */\nexport function createPulseDataSourceProvider(config: PulseAdapterConfig): DataSourceProvider {\n return new PulseDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/pulse's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: pulse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:streaming';\n\n/**\n * A typed operation handler for a single streaming (WebSocket / SSE) operation.\n * Receives caller-supplied params and returns the operation result.\n *\n * For WebSocket/SSE sources the typical patterns are:\n * - Request-response over WebSocket (send + await reply)\n * - Snapshot of last-known state from an in-process subscription cache\n * - Publish a message to the stream\n *\n * Implementations are responsible for managing the underlying transport connection.\n */\nexport type StreamingOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single streaming data source.\n */\nexport interface StreamingSourceRegistration {\n /** Source ID — matches the id in `source: websocket:<id>` or `source: sse:<id>` YAML references */\n id: string;\n /**\n * Transport protocol for this source.\n * - `websocket`: bidirectional, binary-capable, suitable for most real-time feeds\n * - `sse`: unidirectional server→client, HTTP-compatible, firewall-friendly\n */\n transport: 'websocket' | 'sse';\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, StreamingOperationHandler>;\n}\n\n/**\n * Configuration for StreamingDataSourceProvider.\n */\nexport interface StreamingAdapterConfig {\n /** Data sources to register. Each source declares its transport + named operation handlers. */\n sources: StreamingSourceRegistration[];\n}\n\n/**\n * StreamingDataSourceProvider — wraps registered WebSocket/SSE operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a transport type and operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically typed client methods wrapping `useStreaming` subscriptions\n * (from `@stackwright-pro/pulse`), but any async function with the right signature works.\n *\n * Design rationale:\n * - Same registry pattern as `PulseDataSourceProvider` — swapping 'pulse' for 'websocket'/'sse'.\n * - Transport-agnostic at this layer: the handler decides how to communicate over the socket.\n * - `@stackwright-pro/pulse` registers streaming clients here when installed; the adapter\n * does NOT hard-import that package (IoC at factory time).\n *\n * Usage example:\n * ```typescript\n * const provider = createStreamingDataSourceProvider({\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * });\n * // Matches `source: websocket:ais-vessels` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error.\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is.\n */\nexport class StreamingDataSourceProvider implements DataSourceProvider {\n readonly name = 'streaming';\n\n private readonly sourcesMap: Map<string, StreamingSourceRegistration>;\n\n constructor(private readonly config: StreamingAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: s.transport,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in StreamingAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a StreamingDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by `@stackwright-pro/pulse`'s streaming datasource adapter when installed.\n */\nexport function createStreamingDataSourceProvider(\n config: StreamingAdapterConfig,\n): DataSourceProvider {\n return new StreamingDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * `@stackwright-pro/pulse`'s streaming-datasource-adapter overrides this with a\n * static manifest of all generated streaming clients, enabling the compiler to\n * validate `source: websocket:*` and `source: sse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceProvider } from './provider';\nimport { noopDataSourceProvider } from './noop';\nimport type { OpenApiAdapterConfig } from './openapi-adapter';\nimport { createOpenApiDataSourceProvider } from './openapi-adapter';\nimport type { PulseAdapterConfig } from './pulse-adapter';\nimport { createPulseDataSourceProvider } from './pulse-adapter';\nimport type { StreamingAdapterConfig } from './streaming-adapter';\nimport { createStreamingDataSourceProvider } from './streaming-adapter';\n\n/**\n * Create a DataSourceProvider based on installed packages and environment configuration.\n *\n * Resolution order (first match wins):\n * 1. `options.provider` — explicit code-level override\n * 2. `DATA_SOURCE_PROVIDER` env var — environment-level override\n * 3. IoC auto-discovery — scans for installed adapter packages via require.resolve()\n * a. `@stackwright-pro/openapi/datasource-adapter` (checked first)\n * b. `@stackwright-pro/pulse/datasource-adapter`\n * 4. NoopDataSourceProvider — fail-closed default, throws on execute()\n *\n * Same pattern as createMessageBusProvider() and createAuthProvider().\n *\n * @example Default (IoC — install the package, nothing else needed)\n * ```typescript\n * // With @stackwright-pro/pulse in node_modules:\n * const provider = createDataSourceProvider();\n * // → PulseDataSourceProvider (auto-discovered)\n *\n * // With nothing installed:\n * const provider = createDataSourceProvider();\n * // → NoopDataSourceProvider (execute() will throw)\n * ```\n *\n * @example Explicit override with config (useful in tests and custom setups)\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'pulse',\n * config: {\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryGeneratorStatus: mockHandler },\n * }],\n * },\n * });\n * ```\n *\n * @example Streaming WebSocket/SSE provider\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'websocket',\n * config: {\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * },\n * });\n * ```\n *\n * @example Environment-level override (force noop in isolated tests)\n * ```bash\n * DATA_SOURCE_PROVIDER=noop node my-service.js\n * DATA_SOURCE_PROVIDER=pulse node my-service.js # force pulse even if openapi is installed\n * DATA_SOURCE_PROVIDER=websocket node my-service.js # force streaming (WebSocket)\n * DATA_SOURCE_PROVIDER=sse node my-service.js # force streaming (SSE)\n * ```\n */\nexport function createDataSourceProvider(options?: {\n /** Override the provider type ('openapi' | 'pulse' | 'websocket' | 'sse' | 'noop') */\n provider?: string;\n /** Provider-specific config passed through to the adapter */\n config?: Record<string, unknown>;\n}): DataSourceProvider {\n const providerType = options?.provider ?? process.env['DATA_SOURCE_PROVIDER'] ?? _autoDiscover();\n\n switch (providerType) {\n case 'noop':\n return noopDataSourceProvider;\n\n case 'openapi': {\n // Local OpenAPI adapter — always present, no dynamic require needed.\n // @stackwright-pro/openapi can supplement this via auto-discovery when installed.\n return createOpenApiDataSourceProvider(\n (options?.config as OpenApiAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'pulse': {\n // Local Pulse adapter — always present, no dynamic require needed.\n // @stackwright-pro/pulse can supplement this via auto-discovery when installed.\n return createPulseDataSourceProvider(\n (options?.config as PulseAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'websocket':\n case 'sse': {\n // Streaming adapter — handles both WebSocket and SSE sources.\n // @stackwright-pro/pulse ships a streaming-datasource-adapter entry point that\n // auto-registers generated streaming clients when installed.\n return createStreamingDataSourceProvider(\n (options?.config as StreamingAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n default:\n if (providerType !== 'noop') {\n console.warn(\n `stackwright-services:datasource Unknown DATA_SOURCE_PROVIDER \"${providerType}\", falling back to noop`,\n );\n }\n return noopDataSourceProvider;\n }\n}\n\n/**\n * Auto-discover installed providers via require.resolve().\n * Returns the first provider type found, or 'noop' if none are installed.\n *\n * This is a pure filesystem probe — no module is loaded here, no side effects.\n * Actual provider construction happens in createDataSourceProvider() after this returns.\n *\n * Discovery convention: each adapter package ships a `datasource-adapter` subpath export\n * (`<package>/datasource-adapter`) that this probe checks for. The local OpenApiDataSourceProvider\n * and PulseDataSourceProvider do NOT trigger auto-discovery — they require explicit source\n * registration via factory config. Only the Pro adapter packages auto-register.\n *\n * Check order matters when both are installed: openapi wins. Override with\n * DATA_SOURCE_PROVIDER env var or explicit options.provider to change this.\n */\nfunction _autoDiscover(): string {\n const candidates: Array<{ pkg: string; providerType: string }> = [\n // @stackwright-pro/openapi ships its own datasource-adapter entry point that\n // auto-registers all generated clients — when that package is installed, 'openapi'\n // is returned here. The local OpenApiDataSourceProvider requires explicit source\n // registration and does NOT trigger auto-discovery.\n { pkg: '@stackwright-pro/openapi/datasource-adapter', providerType: 'openapi' },\n // @stackwright-pro/pulse follows the same pattern for Pulse-backed data sources.\n { pkg: '@stackwright-pro/pulse/datasource-adapter', providerType: 'pulse' },\n // @stackwright-pro/pulse also ships a streaming-datasource-adapter for WebSocket/SSE sources.\n // websocket wins if both pulse and streaming are installed (use DATA_SOURCE_PROVIDER to override).\n { pkg: '@stackwright-pro/pulse/streaming-datasource-adapter', providerType: 'websocket' },\n ];\n\n for (const { pkg, providerType } of candidates) {\n try {\n require.resolve(pkg);\n return providerType;\n } catch {\n // not installed — try next\n }\n }\n\n // Nothing found — createDataSourceProvider() will use NoopDataSourceProvider.\n // Any flow step that calls provider.execute() will receive a descriptive error\n // pointing to the correct package to install.\n return 'noop';\n}\n","import type { DataSourceDescriptor } from './provider';\n\n/**\n * Result of a prebuild-time data source scan.\n */\nexport interface DataSourceScanResult {\n /** All sources discovered across all installed providers */\n sources: DataSourceDescriptor[];\n /** Which provider packages were found (for logging/diagnostics) */\n detectedProviders: string[];\n}\n\n/**\n * Scan installed packages at prebuild time to discover available data sources.\n *\n * This is called by the compiler and prebuild hook (yo8) to expand the valid\n * `source:` schema surface. If @stackwright-pro/openapi or @stackwright-pro/pulse\n * are installed and expose an adapter registry, their sources are enumerated here.\n *\n * This is a pure filesystem/module-resolution operation — no network, no side effects.\n * It is safe to call at build time (no running server required).\n *\n * Returns an empty sources array if no providers are installed, which causes the\n * compiler to emit a warning (not an error) when a `source:` reference is encountered.\n */\nexport function scanDataSources(): DataSourceScanResult {\n const sources: DataSourceDescriptor[] = [];\n const detectedProviders: string[] = [];\n\n // Try @stackwright-pro/openapi\n try {\n require.resolve('@stackwright-pro/openapi/datasource-adapter');\n detectedProviders.push('@stackwright-pro/openapi');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/openapi/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/openapi sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/openapi not installed\n }\n\n // Try @stackwright-pro/pulse\n try {\n require.resolve('@stackwright-pro/pulse/datasource-adapter');\n detectedProviders.push('@stackwright-pro/pulse');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/pulse/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/pulse sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/pulse not installed\n }\n\n return { sources, detectedProviders };\n}\n","/**\n * Core prebuild registration function.\n * Discovers and enumerates the complete services schema surface.\n */\nimport { CapabilityRegistry, registerAllCapabilities } from '@stackwright-services/capabilities';\nimport { scanDataSources } from '../datasource/scan';\nimport type {\n CapabilityDescriptor,\n DataSourceDescriptorEntry,\n PrebuildRegistration,\n TriggerTypeDescriptor,\n} from './types';\n\n// Read version from package.json at build time\nconst PACKAGE_VERSION = '0.0.1'; // Synced with package.json via sync-versions.mjs\n\n/**\n * Enumerate all known trigger types.\n * The trigger type set is closed and small per VISION.md.\n */\nfunction enumerateTriggers(): TriggerTypeDescriptor[] {\n return [\n {\n type: 'http',\n description:\n 'HTTP request/response trigger — becomes API Gateway route (Lambda) or Ingress (k8s)',\n inputSchema: {\n type: 'object',\n properties: {\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] },\n path: { type: 'string', pattern: '^/' },\n input_schema: { type: 'string' },\n },\n required: ['method', 'path'],\n },\n example: {\n type: 'http',\n method: 'POST',\n path: '/api/patients/at-risk',\n input_schema: 'AtRiskRequest',\n },\n },\n {\n type: 'event',\n description: 'Pub/sub event trigger — subscribes to a message bus topic',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^bus:' },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'event',\n source: 'bus:equipment-status',\n input_schema: 'EquipmentStatusEvent',\n },\n },\n {\n type: 'schedule',\n description: 'Cron-style scheduled trigger — periodic invocation',\n inputSchema: {\n type: 'object',\n properties: {\n cron: { type: 'string' },\n input_schema: { type: 'string' },\n },\n required: ['cron'],\n },\n example: { type: 'schedule', cron: '0 */6 * * *', input_schema: 'ScheduledCheckInput' },\n },\n {\n type: 'queue',\n description: 'Durable point-to-point queue trigger — processes messages sequentially',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^queue:' },\n batch_size: { type: 'number', minimum: 1, maximum: 10 },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'queue',\n source: 'queue:approvals',\n batch_size: 1,\n input_schema: 'ApprovalMessage',\n },\n },\n ];\n}\n\n/**\n * Walk the capability registry and extract descriptors.\n */\nfunction enumerateCapabilities(): CapabilityDescriptor[] {\n const registry = new CapabilityRegistry();\n registerAllCapabilities(registry);\n\n return registry.listAll().map((cap) => {\n const descriptor: CapabilityDescriptor = {\n name: cap.definition.name,\n kind: cap.definition.kind,\n description: cap.definition.description,\n inputSchema: cap.definition.inputSchema,\n outputSchema: cap.definition.outputSchema,\n };\n\n if (cap.definition.kind === 'effect') {\n descriptor.requiredPermissions = cap.definition.requiredPermissions;\n }\n\n return descriptor;\n });\n}\n\n/**\n * Discover installed data sources.\n * Maps from runtime's DataSourceDescriptor (transport field) to prebuild's\n * DataSourceDescriptorEntry (provider field).\n */\nfunction enumerateDataSources(): DataSourceDescriptorEntry[] {\n const scanResult = scanDataSources();\n return scanResult.sources.map((source) => ({\n id: source.id,\n provider: source.transport,\n operations: source.operations,\n }));\n}\n\n/**\n * Main prebuild registration function.\n * Called by @stackwright/scaffold-core at prebuild time.\n *\n * This is safe to call at build time — no running server required,\n * no network calls, no side effects beyond module resolution for data source scanning.\n */\nexport function registerServices(): PrebuildRegistration {\n return {\n pluginId: '@stackwright-services/runtime',\n version: PACKAGE_VERSION,\n triggers: enumerateTriggers(),\n capabilities: enumerateCapabilities(),\n dataSources: enumerateDataSources(),\n registeredAt: new Date().toISOString(),\n };\n}\n"],"mappings":"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","names":["listDataSources","createLogger","createLogger","createLogger","SqsSnsMessageBusProvider","LOG_PREFIX","LOG_PREFIX","listDataSources","LOG_PREFIX"]}
|
package/dist/index.mjs
CHANGED
|
@@ -818,6 +818,7 @@ var OpenApiDataSourceProvider = class {
|
|
|
818
818
|
this.config = config;
|
|
819
819
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
820
820
|
}
|
|
821
|
+
config;
|
|
821
822
|
name = "openapi";
|
|
822
823
|
sourcesMap;
|
|
823
824
|
listSources() {
|
|
@@ -865,6 +866,7 @@ var PulseDataSourceProvider = class {
|
|
|
865
866
|
this.config = config;
|
|
866
867
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
867
868
|
}
|
|
869
|
+
config;
|
|
868
870
|
name = "pulse";
|
|
869
871
|
sourcesMap;
|
|
870
872
|
listSources() {
|
|
@@ -912,6 +914,7 @@ var StreamingDataSourceProvider = class {
|
|
|
912
914
|
this.config = config;
|
|
913
915
|
this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));
|
|
914
916
|
}
|
|
917
|
+
config;
|
|
915
918
|
name = "streaming";
|
|
916
919
|
sourcesMap;
|
|
917
920
|
listSources() {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/messaging/sqs-sns.ts","../src/triggers/http.ts","../src/triggers/event.ts","../src/triggers/schedule.ts","../src/triggers/queue.ts","../src/observability/noop.ts","../src/observability/otel.ts","../src/observability/factory.ts","../src/observability/audit-noop.ts","../src/observability/audit-console.ts","../src/observability/audit-factory.ts","../src/observability/audit-hash.ts","../src/messaging/noop.ts","../src/messaging/index.ts","../src/messaging/factory.ts","../src/notifications/noop.ts","../src/notifications/factory.ts","../src/auth/noop.ts","../src/auth/factory.ts","../src/datasource/noop.ts","../src/datasource/openapi-adapter.ts","../src/datasource/pulse-adapter.ts","../src/datasource/streaming-adapter.ts","../src/datasource/factory.ts","../src/datasource/scan.ts","../src/prebuild/register.ts"],"sourcesContent":["/**\n * SQS/SNS MessageBusProvider — the first concrete adapter.\n *\n * Architecture:\n * - PUBLISH: Uses SNS Publish to deliver messages to a topic ARN.\n * - SUBSCRIBE: Uses SQS long-polling (ReceiveMessage) to consume from a queue URL.\n *\n * Topic/queue resolution:\n * - Logical topic name → SNS Topic ARN via config map or env var:\n * BUS_TOPIC_{UPPER_SNAKE_NAME}_ARN (e.g. BUS_TOPIC_EQUIPMENT_STATUS_ARN)\n * - Logical queue name → SQS Queue URL via config map or env var:\n * BUS_QUEUE_{UPPER_SNAKE_NAME}_URL (e.g. BUS_QUEUE_EQUIPMENT_STATUS_URL)\n *\n * Trace propagation:\n * - traceContext serialized as SNS/SQS MessageAttributes (StringValue)\n * - metadata fields (timestamp, source, correlationId) also as MessageAttributes\n *\n * Graceful shutdown:\n * - Each subscription has a polling loop with an `active` flag\n * - stop()/unsubscribe() sets active=false, polling loop exits after current\n * ReceiveMessage returns\n *\n * AWS credentials:\n * - Uses standard AWS SDK v3 credential chain (env vars, instance profile, etc.)\n * - NO credential handling in this adapter\n *\n * Design note: This is a thin wrapper. No retry logic beyond SDK defaults,\n * no DLQ support, no batch processing. Production hardening is a separate bead.\n */\n\nimport {\n SNSClient,\n PublishCommand,\n type PublishCommandInput,\n type MessageAttributeValue as SNSMessageAttributeValue,\n} from '@aws-sdk/client-sns';\nimport {\n SQSClient,\n ReceiveMessageCommand,\n DeleteMessageCommand,\n type Message,\n type MessageAttributeValue as SQSMessageAttributeValue,\n} from '@aws-sdk/client-sqs';\nimport type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:messaging';\n\nexport interface SqsSnsConfig {\n /** AWS region (defaults to AWS_REGION env var or 'us-east-1') */\n region?: string;\n /** SNS Topic ARN mapping: logical name → ARN. Overrides env vars. */\n topicArns?: Record<string, string>;\n /** SQS Queue URL mapping: logical name → URL. Overrides env vars. */\n queueUrls?: Record<string, string>;\n /** SQS long-poll wait time in seconds (default: 20, max for long-polling) */\n waitTimeSeconds?: number;\n /** Max messages per ReceiveMessage call (default: 10) */\n maxMessages?: number;\n /**\n * Minimum delay between poll cycles in ms (default: 100).\n * Prevents tight-spinning when waitTimeSeconds is low or the queue is\n * empty and the SDK resolves instantly. In production with\n * waitTimeSeconds=20 the 100ms gap is negligible.\n */\n pollIntervalMs?: number;\n /** Optional SNS client (for testing/DI) */\n snsClient?: SNSClient;\n /** Optional SQS client (for testing/DI) */\n sqsClient?: SQSClient;\n}\n\n/** Convert a logical topic name to UPPER_SNAKE_CASE for env var lookup. */\nexport function toUpperSnake(name: string): string {\n return name.replace(/[-.]/g, '_').toUpperCase();\n}\n\ninterface PollingState {\n active: boolean;\n}\n\nexport class SqsSnsMessageBusProvider implements MessageBusProvider {\n private readonly snsClient: SNSClient;\n private readonly sqsClient: SQSClient;\n private readonly topicArns: Record<string, string>;\n private readonly queueUrls: Record<string, string>;\n private readonly waitTimeSeconds: number;\n private readonly maxMessages: number;\n private readonly pollIntervalMs: number;\n private readonly pollingStates = new Map<string, PollingState>();\n\n constructor(config: SqsSnsConfig = {}) {\n const region = config.region ?? process.env['AWS_REGION'] ?? 'us-east-1';\n this.snsClient = config.snsClient ?? new SNSClient({ region });\n this.sqsClient = config.sqsClient ?? new SQSClient({ region });\n this.topicArns = config.topicArns ?? {};\n this.queueUrls = config.queueUrls ?? {};\n this.waitTimeSeconds = config.waitTimeSeconds ?? 20;\n this.maxMessages = config.maxMessages ?? 10;\n this.pollIntervalMs = config.pollIntervalMs ?? 100;\n }\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const topicArn = this.resolveTopicArn(topic);\n const attributes = this.buildSnsAttributes(message);\n\n const input: PublishCommandInput = {\n TopicArn: topicArn,\n Message: JSON.stringify(message.payload),\n MessageAttributes: attributes,\n };\n\n const response = await this.snsClient.send(new PublishCommand(input));\n const messageId = response.MessageId ?? `sns-${Date.now()}`;\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const queueUrl = this.resolveQueueUrl(topic);\n const id = `sqs-sub-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const state: PollingState = { active: true };\n this.pollingStates.set(id, state);\n\n // Fire-and-forget: polling loop runs in background\n this.poll(queueUrl, handler, state);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const state = this.pollingStates.get(subscription.id);\n if (state) {\n state.active = false;\n this.pollingStates.delete(subscription.id);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private resolveTopicArn(topic: string): string {\n const fromConfig = this.topicArns[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_TOPIC_${toUpperSnake(topic)}_ARN`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SNS Topic ARN found for \"${topic}\". ` +\n `Set config.topicArns[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private resolveQueueUrl(topic: string): string {\n const fromConfig = this.queueUrls[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_QUEUE_${toUpperSnake(topic)}_URL`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SQS Queue URL found for \"${topic}\". ` +\n `Set config.queueUrls[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private buildSnsAttributes(message: BusMessage): Record<string, SNSMessageAttributeValue> {\n const attrs: Record<string, SNSMessageAttributeValue> = {};\n\n // Serialize traceContext fields\n if (message.traceContext) {\n for (const [key, value] of Object.entries(message.traceContext)) {\n attrs[`trace.${key}`] = { DataType: 'String', StringValue: value };\n }\n }\n\n // Serialize metadata fields\n if (message.metadata) {\n const { timestamp, source, correlationId } = message.metadata;\n if (timestamp) {\n attrs['meta.timestamp'] = { DataType: 'String', StringValue: timestamp };\n }\n if (source) {\n attrs['meta.source'] = { DataType: 'String', StringValue: source };\n }\n if (correlationId) {\n attrs['meta.correlationId'] = { DataType: 'String', StringValue: correlationId };\n }\n }\n\n return attrs;\n }\n\n private async poll(\n queueUrl: string,\n handler: MessageHandler,\n state: PollingState,\n ): Promise<void> {\n while (state.active) {\n // Delay between poll cycles to prevent tight-spinning when\n // waitTimeSeconds is low or the mock/SDK resolves instantly.\n await new Promise<void>((resolve) => setTimeout(resolve, this.pollIntervalMs));\n if (!state.active) break;\n\n try {\n const response = await this.sqsClient.send(\n new ReceiveMessageCommand({\n QueueUrl: queueUrl,\n WaitTimeSeconds: this.waitTimeSeconds,\n MaxNumberOfMessages: this.maxMessages,\n MessageAttributeNames: ['All'],\n }),\n );\n\n for (const sqsMessage of response.Messages ?? []) {\n if (!state.active) break;\n\n const busMessage = this.parseSqsMessage(sqsMessage);\n try {\n await handler(busMessage);\n } catch (handlerError) {\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'handler_error',\n error: handlerError instanceof Error ? handlerError.message : String(handlerError),\n queueUrl,\n }),\n );\n // Continue processing — don't crash the polling loop\n continue;\n }\n\n // Delete only after successful handler invocation\n if (sqsMessage.ReceiptHandle) {\n await this.sqsClient.send(\n new DeleteMessageCommand({\n QueueUrl: queueUrl,\n ReceiptHandle: sqsMessage.ReceiptHandle,\n }),\n );\n }\n }\n } catch (pollError) {\n // Log polling errors but keep the loop alive\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'poll_error',\n error: pollError instanceof Error ? pollError.message : String(pollError),\n queueUrl,\n }),\n );\n }\n }\n }\n\n private parseSqsMessage(sqsMessage: Message): BusMessage {\n const payload = sqsMessage.Body ? JSON.parse(sqsMessage.Body) : null;\n const traceContext = this.extractTraceContext(sqsMessage.MessageAttributes);\n const metadata = this.extractMetadata(sqsMessage.MessageAttributes);\n\n return {\n payload,\n ...(traceContext !== undefined && { traceContext }),\n ...(metadata !== undefined && { metadata }),\n };\n }\n\n private extractTraceContext(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): Record<string, string> | undefined {\n if (!attrs) return undefined;\n\n const trace: Record<string, string> = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith('trace.') && value.StringValue) {\n trace[key.slice('trace.'.length)] = value.StringValue;\n }\n }\n\n return Object.keys(trace).length > 0 ? trace : undefined;\n }\n\n private extractMetadata(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): BusMessage['metadata'] {\n if (!attrs) return undefined;\n\n const timestamp = attrs['meta.timestamp']?.StringValue;\n const source = attrs['meta.source']?.StringValue;\n const correlationId = attrs['meta.correlationId']?.StringValue;\n\n if (!timestamp && !source && !correlationId) return undefined;\n\n return {\n ...(timestamp && { timestamp }),\n ...(source && { source }),\n ...(correlationId && { correlationId }),\n };\n }\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { HttpTrigger } from '@stackwright-services/types';\nimport { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport type { z } from 'zod';\n\n/**\n * Options for creating an HTTP trigger runtime.\n */\nexport interface HttpTriggerOptions {\n /** The HTTP trigger configuration from the flow */\n trigger: HttpTrigger;\n /** Flow handler function */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional input validation schema */\n inputSchema?: z.ZodType;\n /** Optional output validation schema */\n outputSchema?: z.ZodType;\n}\n\n/**\n * Typed error response for consistent error handling.\n */\nexport interface ServiceError {\n error: string;\n code: string;\n details?: unknown;\n}\n\n/**\n * Create a Hono app for an HTTP trigger.\n *\n * This is the runtime entry point for HTTP-triggered flows.\n * The same code works on:\n * - Node.js (via @hono/node-server)\n * - AWS Lambda (via Lambda Web Adapter)\n * - Edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport function createHttpTrigger(options: HttpTriggerOptions): Hono {\n const { trigger, handler, inputSchema, outputSchema } = options;\n const app = new Hono();\n\n // Health check\n app.get('/health', (c) => c.json({ status: 'ok', trigger: 'http' }));\n\n // Register the flow route\n const method = trigger.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n\n app[method](trigger.path, async (c: Context) => {\n // Extract input based on method\n let input: unknown;\n if (trigger.method === 'GET') {\n input = Object.fromEntries(new URL(c.req.url).searchParams);\n } else {\n try {\n input = await c.req.json();\n } catch {\n return c.json<ServiceError>(\n { error: 'Invalid JSON body', code: 'INVALID_REQUEST_BODY' },\n 400,\n );\n }\n }\n\n // Validate input if schema provided\n if (inputSchema) {\n const result = inputSchema.safeParse(input);\n if (!result.success) {\n return c.json<ServiceError>(\n {\n error: 'Input validation failed',\n code: 'VALIDATION_ERROR',\n details: result.error.issues,\n },\n 400,\n );\n }\n input = result.data;\n }\n\n // Create context\n const context: CapabilityContext = {\n traceId: c.req.header('x-trace-id') ?? c.req.header('x-request-id') ?? crypto.randomUUID(),\n logger: createLogger(),\n };\n\n // Execute flow\n try {\n const result = await handler(input, context);\n\n // Validate output if schema provided\n if (outputSchema) {\n const outputResult = outputSchema.safeParse(result);\n if (!outputResult.success) {\n return c.json<ServiceError>(\n { error: 'Output validation failed', code: 'OUTPUT_VALIDATION_ERROR' },\n 500,\n );\n }\n return c.json(outputResult.data);\n }\n\n return c.json(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return c.json<ServiceError>({ error: message, code: 'FLOW_EXECUTION_ERROR' }, 500);\n }\n });\n\n return app;\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { EventTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating an event trigger adapter.\n */\nexport interface EventTriggerOptions {\n /** The event trigger configuration from the flow */\n trigger: EventTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * EventTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class EventTriggerAdapter implements TriggerAdapter {\n readonly type = 'event';\n readonly topic: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: EventTriggerOptions) {\n this.topic = options.trigger.source.replace(/^bus:/, '');\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.topic, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Event payload validation failed', {\n topic: this.topic,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Event handler failed', {\n topic: this.topic,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { ScheduleTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a schedule trigger adapter.\n */\nexport interface ScheduleTriggerOptions {\n /** The schedule trigger configuration from the flow */\n trigger: ScheduleTrigger;\n /** Flow handler function invoked on each tick */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation */\n inputSchema?: z.ZodType;\n /**\n * Override interval in milliseconds for local dev / testing.\n * When not provided, defaults to 60_000ms and logs a warning that\n * cron parsing is not built-in. In production, scheduling is handled\n * by infrastructure (EventBridge, CronJob on K8s, etc.).\n */\n intervalMs?: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 60_000;\n\n/**\n * ScheduleTriggerAdapter — local-dev / test scheduler that fires the flow\n * handler on a fixed interval.\n *\n * NOT a production cron implementation. In production the cron expression\n * is consumed by infrastructure (EventBridge rules, K8s CronJobs, etc.)\n * and this adapter is not used.\n *\n * Handler errors are caught and logged — the scheduler never crashes.\n */\nexport class ScheduleTriggerAdapter implements TriggerAdapter {\n readonly type = 'schedule';\n readonly cron: string;\n\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private readonly intervalMs: number;\n private timer: ReturnType<typeof setInterval> | undefined;\n\n constructor(options: ScheduleTriggerOptions) {\n this.cron = options.trigger.cron;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n }\n\n async start(): Promise<void> {\n if (this.intervalMs === DEFAULT_INTERVAL_MS) {\n const logger = createLogger();\n logger.warn('Cron parsing not built-in; using default 60s interval for local dev', {\n cron: this.cron,\n intervalMs: this.intervalMs,\n });\n }\n\n this.timer = setInterval(() => {\n void this.tick();\n }, this.intervalMs);\n }\n\n async stop(): Promise<void> {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }\n\n private async tick(): Promise<void> {\n const traceId = crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler({}, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Schedule handler failed', {\n cron: this.cron,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { QueueTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a queue trigger adapter.\n */\nexport interface QueueTriggerOptions {\n /** The queue trigger configuration from the flow */\n trigger: QueueTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * QueueTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Semantically represents point-to-point delivery (single consumer), unlike\n * the fan-out semantics of EventTriggerAdapter. At the runtime adapter level\n * both use messageBus.subscribe() — the distinction lives in the concrete\n * bus implementation (SQS vs SNS+SQS, competing consumers vs broadcast).\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class QueueTriggerAdapter implements TriggerAdapter {\n readonly type = 'queue';\n readonly queueName: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: QueueTriggerOptions) {\n this.queueName = options.trigger.name;\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.queueName, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Queue payload validation failed', {\n queueName: this.queueName,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Queue handler failed', {\n queueName: this.queueName,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\nconst NOOP_SPAN: SpanHandle = {\n setAttribute: () => {},\n setError: () => {},\n end: () => {},\n};\n\n/**\n * No-op observability provider -- zero runtime cost.\n * Used when OTel is not configured (the default).\n * All methods are no-ops that return immediately.\n */\nexport class NoopObservabilityProvider implements ObservabilityProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n return NOOP_SPAN;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n // Intentionally empty -- zero cost when disabled\n }\n}\n\n/** Singleton no-op provider */\nexport const noopProvider = new NoopObservabilityProvider();\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\n/**\n * OpenTelemetry-compatible observability provider.\n *\n * In Phase 1, this uses structured console logging with span semantics.\n * In Phase 2+, this wraps @opentelemetry/api (trace + metrics).\n *\n * The interface is stable -- upgrading to real OTel is a drop-in replacement.\n */\nexport class OtelObservabilityProvider implements ObservabilityProvider {\n private readonly serviceName: string;\n\n constructor(serviceName: string = 'stackwright-service') {\n this.serviceName = serviceName;\n }\n\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n const spanId = crypto.randomUUID().slice(0, 16);\n const startTime = Date.now();\n\n console.info(\n JSON.stringify({\n type: 'span_start',\n spanId,\n name,\n service: this.serviceName,\n attributes,\n timestamp: new Date().toISOString(),\n }),\n );\n\n const spanAttributes: Record<string, string | number | boolean> = { ...attributes };\n\n return {\n setAttribute(key: string, value: string | number | boolean): void {\n spanAttributes[key] = value;\n },\n setError(error: Error): void {\n spanAttributes['error'] = true;\n spanAttributes['error.message'] = error.message;\n console.error(\n JSON.stringify({\n type: 'span_error',\n spanId,\n name,\n error: error.message,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n end(): void {\n const duration = Date.now() - startTime;\n console.info(\n JSON.stringify({\n type: 'span_end',\n spanId,\n name,\n duration,\n attributes: spanAttributes,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n };\n }\n\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n console.info(\n JSON.stringify({\n type: 'metric',\n name,\n value,\n tags,\n service: this.serviceName,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n}\n","import type { ObservabilityProvider } from './provider';\nimport { noopProvider } from './noop';\nimport { OtelObservabilityProvider } from './otel';\n\n/**\n * Create an observability provider based on environment configuration.\n *\n * - OTEL_ENABLED=true (or \"1\") -> OtelObservabilityProvider\n * - Otherwise -> NoopObservabilityProvider (zero cost)\n *\n * The provider is injected into compiled flow code, not imported.\n * This means zero runtime overhead when observability is disabled.\n */\nexport function createObservabilityProvider(options?: {\n serviceName?: string;\n}): ObservabilityProvider {\n const otelEnabled = process.env['OTEL_ENABLED'];\n\n if (otelEnabled === 'true' || otelEnabled === '1') {\n return new OtelObservabilityProvider(options?.serviceName);\n }\n\n return noopProvider;\n}\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/** No-op audit provider -- zero runtime cost when auditing is disabled */\nexport class NoopAuditProvider implements AuditProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n record(_event: AuditEvent): void {\n // Intentionally empty\n }\n\n async flush(): Promise<void> {\n // Nothing to flush\n }\n}\n\n/** Singleton no-op audit provider */\nexport const noopAuditProvider = new NoopAuditProvider();\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/**\n * Console audit provider -- writes events to stderr as JSON Lines.\n *\n * Works in Lambda (stderr -> CloudWatch), containers (stderr -> log collector),\n * and local dev (stderr -> terminal).\n *\n * Uses stderr to avoid mixing with application stdout.\n */\nexport class ConsoleAuditProvider implements AuditProvider {\n record(event: AuditEvent): void {\n process.stderr.write(JSON.stringify(event) + '\\n');\n }\n\n async flush(): Promise<void> {\n // Console writes are synchronous -- nothing to flush\n }\n}\n","import type { AuditProvider } from './audit';\nimport { noopAuditProvider } from './audit-noop';\nimport { ConsoleAuditProvider } from './audit-console';\n\n/**\n * Create an audit provider based on environment configuration.\n *\n * - STACKWRIGHT_AUDIT=true (or \"1\") -> ConsoleAuditProvider (stderr JSON Lines)\n * - Otherwise -> NoopAuditProvider (zero cost)\n *\n * Defaults to OFF in production, can be enabled with env var.\n */\nexport function createAuditProvider(): AuditProvider {\n const auditEnabled = process.env['STACKWRIGHT_AUDIT'];\n if (auditEnabled === 'true' || auditEnabled === '1') {\n return new ConsoleAuditProvider();\n }\n return noopAuditProvider;\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Compute a truncated SHA-256 hash of a value.\n *\n * Used for audit events -- captures enough to detect \"did the input/output change?\"\n * without storing full payloads (which may be large or contain PII).\n *\n * Returns first 16 hex characters of SHA-256.\n * Deterministic: same input always produces same hash.\n */\nexport function auditHash(value: unknown): string {\n const serialized = JSON.stringify(value, (_key, val) => {\n // Handle non-serializable types gracefully\n if (typeof val === 'bigint') return val.toString();\n if (val instanceof Error) return { message: val.message, name: val.name };\n if (typeof val === 'function') return '[function]';\n if (typeof val === 'symbol') return val.toString();\n if (val === undefined) return null;\n return val;\n });\n return createHash('sha256')\n .update(serialized ?? 'undefined')\n .digest('hex')\n .slice(0, 16);\n}\n","import type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\n/**\n * In-memory MessageBusProvider — delivers messages locally within the process.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external bus is configured\n *\n * Messages published to a topic are delivered synchronously to all\n * subscribed handlers for that topic.\n */\nexport class InMemoryMessageBusProvider implements MessageBusProvider {\n private subscriptions = new Map<string, Map<string, MessageHandler>>();\n private nextId = 0;\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const messageId = message.metadata?.messageId ?? `mem-${++this.nextId}`;\n const topicHandlers = this.subscriptions.get(topic);\n\n if (topicHandlers) {\n const enrichedMessage: BusMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n messageId,\n timestamp: message.metadata?.timestamp ?? new Date().toISOString(),\n },\n };\n\n // Deliver to all subscribers\n const handlers = Array.from(topicHandlers.values());\n await Promise.all(handlers.map((handler) => handler(enrichedMessage)));\n }\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const id = `sub-${++this.nextId}`;\n\n let topicHandlers = this.subscriptions.get(topic);\n if (!topicHandlers) {\n topicHandlers = new Map();\n this.subscriptions.set(topic, topicHandlers);\n }\n topicHandlers.set(id, handler);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const topicHandlers = this.subscriptions.get(subscription.topic);\n if (topicHandlers) {\n topicHandlers.delete(subscription.id);\n if (topicHandlers.size === 0) {\n this.subscriptions.delete(subscription.topic);\n }\n }\n }\n\n /** Helper for testing: get count of active subscriptions for a topic */\n getSubscriptionCount(topic: string): number {\n return this.subscriptions.get(topic)?.size ?? 0;\n }\n\n /** Helper for testing: clear all subscriptions */\n clear(): void {\n this.subscriptions.clear();\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryBusProvider = new InMemoryMessageBusProvider();\n","export type {\n MessageBusProvider,\n BusMessage,\n MessageMetadata,\n PublishResult,\n MessageHandler,\n Subscription,\n} from './provider';\nexport { InMemoryMessageBusProvider, inMemoryBusProvider } from './noop';\nexport { SqsSnsMessageBusProvider, type SqsSnsConfig } from './sqs-sns';\nexport { createMessageBusProvider } from './factory';\n","import type { MessageBusProvider } from './provider';\nimport { inMemoryBusProvider } from './noop';\n\n/**\n * Create a MessageBusProvider based on environment configuration.\n *\n * - MESSAGE_BUS_PROVIDER=memory (or unset) -> InMemoryMessageBusProvider\n * - MESSAGE_BUS_PROVIDER=sqs -> SQS/SNS adapter\n *\n * Same pattern as createObservabilityProvider().\n */\nexport function createMessageBusProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n /** Provider-specific config (e.g. SqsSnsConfig for 'sqs') */\n config?: Record<string, unknown>;\n}): MessageBusProvider {\n const providerType = options?.provider ?? process.env['MESSAGE_BUS_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryBusProvider;\n case 'sqs': {\n // Dynamic require to avoid bundling AWS SDK when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SqsSnsMessageBusProvider } = require('./sqs-sns') as typeof import('./sqs-sns');\n return new SqsSnsMessageBusProvider(options?.config);\n }\n default:\n console.warn(\n `stackwright-services:messaging Unknown MESSAGE_BUS_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryBusProvider;\n }\n}\n","import type { NotificationMessage, NotificationProvider, SendResult } from './provider';\n\n/**\n * In-memory NotificationProvider — records notifications locally for inspection.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external notification service is configured\n *\n * Notifications are stored in-memory and can be inspected via helper methods.\n */\nexport class InMemoryNotificationProvider implements NotificationProvider {\n private notifications: Array<NotificationMessage & { notificationId: string }> = [];\n private nextId = 0;\n\n async send(notification: NotificationMessage): Promise<SendResult> {\n const notificationId = `notif-${++this.nextId}`;\n\n this.notifications.push({\n ...notification,\n notificationId,\n metadata: {\n ...notification.metadata,\n timestamp: notification.metadata?.timestamp ?? new Date().toISOString(),\n },\n });\n\n return {\n notificationId,\n channel: notification.channel,\n success: true,\n };\n }\n\n /** Helper for testing: get all sent notifications */\n getSentNotifications(): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return [...this.notifications];\n }\n\n /** Helper for testing: get notifications filtered by channel */\n getByChannel(channel: string): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.channel === channel);\n }\n\n /** Helper for testing: get notifications filtered by recipient */\n getByRecipient(\n recipient: string,\n ): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.recipient === recipient);\n }\n\n /** Helper for testing: get count of sent notifications */\n get sentCount(): number {\n return this.notifications.length;\n }\n\n /** Helper for testing: clear all recorded notifications */\n clear(): void {\n this.notifications = [];\n this.nextId = 0;\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryNotificationProvider = new InMemoryNotificationProvider();\n","import type { NotificationProvider } from './provider';\nimport { inMemoryNotificationProvider } from './noop';\n\n/**\n * Create a NotificationProvider based on environment configuration.\n *\n * - NOTIFICATION_PROVIDER=memory (or unset) -> InMemoryNotificationProvider\n * - NOTIFICATION_PROVIDER=sendgrid -> (future: SendGrid adapter)\n * - NOTIFICATION_PROVIDER=twilio -> (future: Twilio adapter)\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createNotificationProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n}): NotificationProvider {\n const providerType = options?.provider ?? process.env['NOTIFICATION_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryNotificationProvider;\n // Future: case 'sendgrid' -> SendGrid adapter\n // Future: case 'twilio' -> Twilio/SNS adapter\n // Future: case 'fcm' -> Firebase Cloud Messaging adapter\n default:\n console.warn(\n `stackwright-services:notifications Unknown NOTIFICATION_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryNotificationProvider;\n }\n}\n","import type { AuthClaims, AuthProvider, TokenValidationResult } from './provider';\n\n/**\n * No-op AuthProvider — fail-closed default.\n *\n * Used when no auth provider is configured:\n * - validateToken() always returns { valid: false } (reject all tokens)\n * - extractClaims() throws (no claims without a real provider)\n * - checkRole() always returns false (deny all role checks)\n *\n * This is intentionally fail-closed: if you forget to install a real\n * auth provider, every auth check fails rather than silently passing.\n */\nexport class NoopAuthProvider implements AuthProvider {\n readonly name = 'noop';\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async validateToken(token: string): Promise<TokenValidationResult> {\n return { valid: false, error: 'No auth provider configured' };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async extractClaims(token: string): Promise<AuthClaims> {\n throw new Error('No auth provider configured');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n checkRole(claims: AuthClaims, role: string): boolean {\n return false;\n }\n}\n\n/** Singleton no-op provider */\nexport const noopAuthProvider = new NoopAuthProvider();\n","import type { AuthProvider } from './provider';\nimport { noopAuthProvider } from './noop';\n\nexport type AuthProviderType = 'noop' | 'oidc' | 'cac';\n\n/**\n * Create an AuthProvider based on the requested type.\n *\n * - 'noop' (or unset) -> NoopAuthProvider (fail-closed default)\n * - 'oidc' -> Future: lazy require('@stackwright-pro/auth-oidc')\n * - 'cac' -> Future: lazy require('@stackwright-pro/auth-cac')\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createAuthProvider(type?: AuthProviderType): AuthProvider {\n switch (type) {\n case 'oidc':\n // Future: lazy require('@stackwright-pro/auth-oidc')\n throw new Error(\n 'OIDC auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'cac':\n // Future: lazy require('@stackwright-pro/auth-cac')\n throw new Error(\n 'CAC/PKI auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'noop':\n default:\n return noopAuthProvider;\n }\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\n/**\n * NoopDataSourceProvider — used when no data source provider is installed.\n *\n * listSources() returns an empty array (no sources available to the schema expander).\n * execute() throws a descriptive error pointing to the correct package to install.\n *\n * This is the fail-closed default, consistent with NoopAuthProvider.\n */\nexport class NoopDataSourceProvider implements DataSourceProvider {\n readonly name = 'noop';\n\n listSources(): DataSourceDescriptor[] {\n return [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(_source: string, _operation: string, _params: unknown): Promise<DataSourceResult> {\n return Promise.reject(\n new Error(\n 'No DataSourceProvider is configured. ' +\n 'Install @stackwright-pro/openapi or @stackwright-pro/pulse and register an adapter, ' +\n 'or set DATA_SOURCE_PROVIDER in your environment.',\n ),\n );\n }\n}\n\nexport const noopDataSourceProvider = new NoopDataSourceProvider();\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:openapi';\n\n/**\n * A typed operation handler for a single OpenAPI operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type OpenApiOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single OpenAPI-backed data source.\n */\nexport interface OpenApiSourceRegistration {\n /** Source ID — matches the id in `source: openapi:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, OpenApiOperationHandler>;\n}\n\n/**\n * Configuration for OpenApiDataSourceProvider.\n */\nexport interface OpenApiAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: OpenApiSourceRegistration[];\n}\n\n/**\n * OpenApiDataSourceProvider — wraps registered OpenAPI operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed OpenAPI client methods (from @stackwright-pro/openapi),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/openapi` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class OpenApiDataSourceProvider implements DataSourceProvider {\n readonly name = 'openapi';\n\n private readonly sourcesMap: Map<string, OpenApiSourceRegistration>;\n\n constructor(private readonly config: OpenApiAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'openapi' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in OpenApiAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates an OpenApiDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/openapi's datasource-adapter when installed.\n */\nexport function createOpenApiDataSourceProvider(config: OpenApiAdapterConfig): DataSourceProvider {\n return new OpenApiDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/openapi's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: openapi:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:pulse';\n\n/**\n * A typed operation handler for a single Pulse operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type PulseOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single Pulse-backed data source.\n */\nexport interface PulseSourceRegistration {\n /** Source ID — matches the id in `source: pulse:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, PulseOperationHandler>;\n}\n\n/**\n * Configuration for PulseDataSourceProvider.\n */\nexport interface PulseAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: PulseSourceRegistration[];\n}\n\n/**\n * PulseDataSourceProvider — wraps registered Pulse operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed Pulse client methods (from @stackwright-pro/pulse),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/pulse` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Usage example:\n * ```typescript\n * const provider = createPulseDataSourceProvider({\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryMetrics: pulseClient.queryMetrics },\n * }],\n * });\n * // Matches `source: pulse:fleet-db` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class PulseDataSourceProvider implements DataSourceProvider {\n readonly name = 'pulse';\n\n private readonly sourcesMap: Map<string, PulseSourceRegistration>;\n\n constructor(private readonly config: PulseAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'pulse' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in PulseAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a PulseDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/pulse's datasource-adapter when installed.\n */\nexport function createPulseDataSourceProvider(config: PulseAdapterConfig): DataSourceProvider {\n return new PulseDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/pulse's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: pulse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:streaming';\n\n/**\n * A typed operation handler for a single streaming (WebSocket / SSE) operation.\n * Receives caller-supplied params and returns the operation result.\n *\n * For WebSocket/SSE sources the typical patterns are:\n * - Request-response over WebSocket (send + await reply)\n * - Snapshot of last-known state from an in-process subscription cache\n * - Publish a message to the stream\n *\n * Implementations are responsible for managing the underlying transport connection.\n */\nexport type StreamingOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single streaming data source.\n */\nexport interface StreamingSourceRegistration {\n /** Source ID — matches the id in `source: websocket:<id>` or `source: sse:<id>` YAML references */\n id: string;\n /**\n * Transport protocol for this source.\n * - `websocket`: bidirectional, binary-capable, suitable for most real-time feeds\n * - `sse`: unidirectional server→client, HTTP-compatible, firewall-friendly\n */\n transport: 'websocket' | 'sse';\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, StreamingOperationHandler>;\n}\n\n/**\n * Configuration for StreamingDataSourceProvider.\n */\nexport interface StreamingAdapterConfig {\n /** Data sources to register. Each source declares its transport + named operation handlers. */\n sources: StreamingSourceRegistration[];\n}\n\n/**\n * StreamingDataSourceProvider — wraps registered WebSocket/SSE operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a transport type and operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically typed client methods wrapping `useStreaming` subscriptions\n * (from `@stackwright-pro/pulse`), but any async function with the right signature works.\n *\n * Design rationale:\n * - Same registry pattern as `PulseDataSourceProvider` — swapping 'pulse' for 'websocket'/'sse'.\n * - Transport-agnostic at this layer: the handler decides how to communicate over the socket.\n * - `@stackwright-pro/pulse` registers streaming clients here when installed; the adapter\n * does NOT hard-import that package (IoC at factory time).\n *\n * Usage example:\n * ```typescript\n * const provider = createStreamingDataSourceProvider({\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * });\n * // Matches `source: websocket:ais-vessels` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error.\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is.\n */\nexport class StreamingDataSourceProvider implements DataSourceProvider {\n readonly name = 'streaming';\n\n private readonly sourcesMap: Map<string, StreamingSourceRegistration>;\n\n constructor(private readonly config: StreamingAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: s.transport,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in StreamingAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a StreamingDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by `@stackwright-pro/pulse`'s streaming datasource adapter when installed.\n */\nexport function createStreamingDataSourceProvider(\n config: StreamingAdapterConfig,\n): DataSourceProvider {\n return new StreamingDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * `@stackwright-pro/pulse`'s streaming-datasource-adapter overrides this with a\n * static manifest of all generated streaming clients, enabling the compiler to\n * validate `source: websocket:*` and `source: sse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceProvider } from './provider';\nimport { noopDataSourceProvider } from './noop';\nimport type { OpenApiAdapterConfig } from './openapi-adapter';\nimport { createOpenApiDataSourceProvider } from './openapi-adapter';\nimport type { PulseAdapterConfig } from './pulse-adapter';\nimport { createPulseDataSourceProvider } from './pulse-adapter';\nimport type { StreamingAdapterConfig } from './streaming-adapter';\nimport { createStreamingDataSourceProvider } from './streaming-adapter';\n\n/**\n * Create a DataSourceProvider based on installed packages and environment configuration.\n *\n * Resolution order (first match wins):\n * 1. `options.provider` — explicit code-level override\n * 2. `DATA_SOURCE_PROVIDER` env var — environment-level override\n * 3. IoC auto-discovery — scans for installed adapter packages via require.resolve()\n * a. `@stackwright-pro/openapi/datasource-adapter` (checked first)\n * b. `@stackwright-pro/pulse/datasource-adapter`\n * 4. NoopDataSourceProvider — fail-closed default, throws on execute()\n *\n * Same pattern as createMessageBusProvider() and createAuthProvider().\n *\n * @example Default (IoC — install the package, nothing else needed)\n * ```typescript\n * // With @stackwright-pro/pulse in node_modules:\n * const provider = createDataSourceProvider();\n * // → PulseDataSourceProvider (auto-discovered)\n *\n * // With nothing installed:\n * const provider = createDataSourceProvider();\n * // → NoopDataSourceProvider (execute() will throw)\n * ```\n *\n * @example Explicit override with config (useful in tests and custom setups)\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'pulse',\n * config: {\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryGeneratorStatus: mockHandler },\n * }],\n * },\n * });\n * ```\n *\n * @example Streaming WebSocket/SSE provider\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'websocket',\n * config: {\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * },\n * });\n * ```\n *\n * @example Environment-level override (force noop in isolated tests)\n * ```bash\n * DATA_SOURCE_PROVIDER=noop node my-service.js\n * DATA_SOURCE_PROVIDER=pulse node my-service.js # force pulse even if openapi is installed\n * DATA_SOURCE_PROVIDER=websocket node my-service.js # force streaming (WebSocket)\n * DATA_SOURCE_PROVIDER=sse node my-service.js # force streaming (SSE)\n * ```\n */\nexport function createDataSourceProvider(options?: {\n /** Override the provider type ('openapi' | 'pulse' | 'websocket' | 'sse' | 'noop') */\n provider?: string;\n /** Provider-specific config passed through to the adapter */\n config?: Record<string, unknown>;\n}): DataSourceProvider {\n const providerType = options?.provider ?? process.env['DATA_SOURCE_PROVIDER'] ?? _autoDiscover();\n\n switch (providerType) {\n case 'noop':\n return noopDataSourceProvider;\n\n case 'openapi': {\n // Local OpenAPI adapter — always present, no dynamic require needed.\n // @stackwright-pro/openapi can supplement this via auto-discovery when installed.\n return createOpenApiDataSourceProvider(\n (options?.config as OpenApiAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'pulse': {\n // Local Pulse adapter — always present, no dynamic require needed.\n // @stackwright-pro/pulse can supplement this via auto-discovery when installed.\n return createPulseDataSourceProvider(\n (options?.config as PulseAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'websocket':\n case 'sse': {\n // Streaming adapter — handles both WebSocket and SSE sources.\n // @stackwright-pro/pulse ships a streaming-datasource-adapter entry point that\n // auto-registers generated streaming clients when installed.\n return createStreamingDataSourceProvider(\n (options?.config as StreamingAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n default:\n if (providerType !== 'noop') {\n console.warn(\n `stackwright-services:datasource Unknown DATA_SOURCE_PROVIDER \"${providerType}\", falling back to noop`,\n );\n }\n return noopDataSourceProvider;\n }\n}\n\n/**\n * Auto-discover installed providers via require.resolve().\n * Returns the first provider type found, or 'noop' if none are installed.\n *\n * This is a pure filesystem probe — no module is loaded here, no side effects.\n * Actual provider construction happens in createDataSourceProvider() after this returns.\n *\n * Discovery convention: each adapter package ships a `datasource-adapter` subpath export\n * (`<package>/datasource-adapter`) that this probe checks for. The local OpenApiDataSourceProvider\n * and PulseDataSourceProvider do NOT trigger auto-discovery — they require explicit source\n * registration via factory config. Only the Pro adapter packages auto-register.\n *\n * Check order matters when both are installed: openapi wins. Override with\n * DATA_SOURCE_PROVIDER env var or explicit options.provider to change this.\n */\nfunction _autoDiscover(): string {\n const candidates: Array<{ pkg: string; providerType: string }> = [\n // @stackwright-pro/openapi ships its own datasource-adapter entry point that\n // auto-registers all generated clients — when that package is installed, 'openapi'\n // is returned here. The local OpenApiDataSourceProvider requires explicit source\n // registration and does NOT trigger auto-discovery.\n { pkg: '@stackwright-pro/openapi/datasource-adapter', providerType: 'openapi' },\n // @stackwright-pro/pulse follows the same pattern for Pulse-backed data sources.\n { pkg: '@stackwright-pro/pulse/datasource-adapter', providerType: 'pulse' },\n // @stackwright-pro/pulse also ships a streaming-datasource-adapter for WebSocket/SSE sources.\n // websocket wins if both pulse and streaming are installed (use DATA_SOURCE_PROVIDER to override).\n { pkg: '@stackwright-pro/pulse/streaming-datasource-adapter', providerType: 'websocket' },\n ];\n\n for (const { pkg, providerType } of candidates) {\n try {\n require.resolve(pkg);\n return providerType;\n } catch {\n // not installed — try next\n }\n }\n\n // Nothing found — createDataSourceProvider() will use NoopDataSourceProvider.\n // Any flow step that calls provider.execute() will receive a descriptive error\n // pointing to the correct package to install.\n return 'noop';\n}\n","import type { DataSourceDescriptor } from './provider';\n\n/**\n * Result of a prebuild-time data source scan.\n */\nexport interface DataSourceScanResult {\n /** All sources discovered across all installed providers */\n sources: DataSourceDescriptor[];\n /** Which provider packages were found (for logging/diagnostics) */\n detectedProviders: string[];\n}\n\n/**\n * Scan installed packages at prebuild time to discover available data sources.\n *\n * This is called by the compiler and prebuild hook (yo8) to expand the valid\n * `source:` schema surface. If @stackwright-pro/openapi or @stackwright-pro/pulse\n * are installed and expose an adapter registry, their sources are enumerated here.\n *\n * This is a pure filesystem/module-resolution operation — no network, no side effects.\n * It is safe to call at build time (no running server required).\n *\n * Returns an empty sources array if no providers are installed, which causes the\n * compiler to emit a warning (not an error) when a `source:` reference is encountered.\n */\nexport function scanDataSources(): DataSourceScanResult {\n const sources: DataSourceDescriptor[] = [];\n const detectedProviders: string[] = [];\n\n // Try @stackwright-pro/openapi\n try {\n require.resolve('@stackwright-pro/openapi/datasource-adapter');\n detectedProviders.push('@stackwright-pro/openapi');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/openapi/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/openapi sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/openapi not installed\n }\n\n // Try @stackwright-pro/pulse\n try {\n require.resolve('@stackwright-pro/pulse/datasource-adapter');\n detectedProviders.push('@stackwright-pro/pulse');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/pulse/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/pulse sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/pulse not installed\n }\n\n return { sources, detectedProviders };\n}\n","/**\n * Core prebuild registration function.\n * Discovers and enumerates the complete services schema surface.\n */\nimport { CapabilityRegistry, registerAllCapabilities } from '@stackwright-services/capabilities';\nimport { scanDataSources } from '../datasource/scan';\nimport type {\n CapabilityDescriptor,\n DataSourceDescriptorEntry,\n PrebuildRegistration,\n TriggerTypeDescriptor,\n} from './types';\n\n// Read version from package.json at build time\nconst PACKAGE_VERSION = '0.0.1'; // Synced with package.json via sync-versions.mjs\n\n/**\n * Enumerate all known trigger types.\n * The trigger type set is closed and small per VISION.md.\n */\nfunction enumerateTriggers(): TriggerTypeDescriptor[] {\n return [\n {\n type: 'http',\n description:\n 'HTTP request/response trigger — becomes API Gateway route (Lambda) or Ingress (k8s)',\n inputSchema: {\n type: 'object',\n properties: {\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] },\n path: { type: 'string', pattern: '^/' },\n input_schema: { type: 'string' },\n },\n required: ['method', 'path'],\n },\n example: {\n type: 'http',\n method: 'POST',\n path: '/api/patients/at-risk',\n input_schema: 'AtRiskRequest',\n },\n },\n {\n type: 'event',\n description: 'Pub/sub event trigger — subscribes to a message bus topic',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^bus:' },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'event',\n source: 'bus:equipment-status',\n input_schema: 'EquipmentStatusEvent',\n },\n },\n {\n type: 'schedule',\n description: 'Cron-style scheduled trigger — periodic invocation',\n inputSchema: {\n type: 'object',\n properties: {\n cron: { type: 'string' },\n input_schema: { type: 'string' },\n },\n required: ['cron'],\n },\n example: { type: 'schedule', cron: '0 */6 * * *', input_schema: 'ScheduledCheckInput' },\n },\n {\n type: 'queue',\n description: 'Durable point-to-point queue trigger — processes messages sequentially',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^queue:' },\n batch_size: { type: 'number', minimum: 1, maximum: 10 },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'queue',\n source: 'queue:approvals',\n batch_size: 1,\n input_schema: 'ApprovalMessage',\n },\n },\n ];\n}\n\n/**\n * Walk the capability registry and extract descriptors.\n */\nfunction enumerateCapabilities(): CapabilityDescriptor[] {\n const registry = new CapabilityRegistry();\n registerAllCapabilities(registry);\n\n return registry.listAll().map((cap) => {\n const descriptor: CapabilityDescriptor = {\n name: cap.definition.name,\n kind: cap.definition.kind,\n description: cap.definition.description,\n inputSchema: cap.definition.inputSchema,\n outputSchema: cap.definition.outputSchema,\n };\n\n if (cap.definition.kind === 'effect') {\n descriptor.requiredPermissions = cap.definition.requiredPermissions;\n }\n\n return descriptor;\n });\n}\n\n/**\n * Discover installed data sources.\n * Maps from runtime's DataSourceDescriptor (transport field) to prebuild's\n * DataSourceDescriptorEntry (provider field).\n */\nfunction enumerateDataSources(): DataSourceDescriptorEntry[] {\n const scanResult = scanDataSources();\n return scanResult.sources.map((source) => ({\n id: source.id,\n provider: source.transport,\n operations: source.operations,\n }));\n}\n\n/**\n * Main prebuild registration function.\n * Called by @stackwright/scaffold-core at prebuild time.\n *\n * This is safe to call at build time — no running server required,\n * no network calls, no side effects beyond module resolution for data source scanning.\n */\nexport function registerServices(): PrebuildRegistration {\n return {\n pluginId: '@stackwright-services/runtime',\n version: PACKAGE_VERSION,\n triggers: enumerateTriggers(),\n capabilities: enumerateCapabilities(),\n dataSources: enumerateDataSources(),\n registeredAt: new Date().toISOString(),\n };\n}\n"],"mappings":"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","names":["createLogger","createLogger","createLogger","SqsSnsMessageBusProvider","LOG_PREFIX","LOG_PREFIX","listDataSources","LOG_PREFIX"]}
|
|
1
|
+
{"version":3,"sources":["../src/messaging/sqs-sns.ts","../src/triggers/http.ts","../src/triggers/event.ts","../src/triggers/schedule.ts","../src/triggers/queue.ts","../src/observability/noop.ts","../src/observability/otel.ts","../src/observability/factory.ts","../src/observability/audit-noop.ts","../src/observability/audit-console.ts","../src/observability/audit-factory.ts","../src/observability/audit-hash.ts","../src/messaging/noop.ts","../src/messaging/index.ts","../src/messaging/factory.ts","../src/notifications/noop.ts","../src/notifications/factory.ts","../src/auth/noop.ts","../src/auth/factory.ts","../src/datasource/noop.ts","../src/datasource/openapi-adapter.ts","../src/datasource/pulse-adapter.ts","../src/datasource/streaming-adapter.ts","../src/datasource/factory.ts","../src/datasource/scan.ts","../src/prebuild/register.ts"],"sourcesContent":["/**\n * SQS/SNS MessageBusProvider — the first concrete adapter.\n *\n * Architecture:\n * - PUBLISH: Uses SNS Publish to deliver messages to a topic ARN.\n * - SUBSCRIBE: Uses SQS long-polling (ReceiveMessage) to consume from a queue URL.\n *\n * Topic/queue resolution:\n * - Logical topic name → SNS Topic ARN via config map or env var:\n * BUS_TOPIC_{UPPER_SNAKE_NAME}_ARN (e.g. BUS_TOPIC_EQUIPMENT_STATUS_ARN)\n * - Logical queue name → SQS Queue URL via config map or env var:\n * BUS_QUEUE_{UPPER_SNAKE_NAME}_URL (e.g. BUS_QUEUE_EQUIPMENT_STATUS_URL)\n *\n * Trace propagation:\n * - traceContext serialized as SNS/SQS MessageAttributes (StringValue)\n * - metadata fields (timestamp, source, correlationId) also as MessageAttributes\n *\n * Graceful shutdown:\n * - Each subscription has a polling loop with an `active` flag\n * - stop()/unsubscribe() sets active=false, polling loop exits after current\n * ReceiveMessage returns\n *\n * AWS credentials:\n * - Uses standard AWS SDK v3 credential chain (env vars, instance profile, etc.)\n * - NO credential handling in this adapter\n *\n * Design note: This is a thin wrapper. No retry logic beyond SDK defaults,\n * no DLQ support, no batch processing. Production hardening is a separate bead.\n */\n\nimport {\n SNSClient,\n PublishCommand,\n type PublishCommandInput,\n type MessageAttributeValue as SNSMessageAttributeValue,\n} from '@aws-sdk/client-sns';\nimport {\n SQSClient,\n ReceiveMessageCommand,\n DeleteMessageCommand,\n type Message,\n type MessageAttributeValue as SQSMessageAttributeValue,\n} from '@aws-sdk/client-sqs';\nimport type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:messaging';\n\nexport interface SqsSnsConfig {\n /** AWS region (defaults to AWS_REGION env var or 'us-east-1') */\n region?: string;\n /** SNS Topic ARN mapping: logical name → ARN. Overrides env vars. */\n topicArns?: Record<string, string>;\n /** SQS Queue URL mapping: logical name → URL. Overrides env vars. */\n queueUrls?: Record<string, string>;\n /** SQS long-poll wait time in seconds (default: 20, max for long-polling) */\n waitTimeSeconds?: number;\n /** Max messages per ReceiveMessage call (default: 10) */\n maxMessages?: number;\n /**\n * Minimum delay between poll cycles in ms (default: 100).\n * Prevents tight-spinning when waitTimeSeconds is low or the queue is\n * empty and the SDK resolves instantly. In production with\n * waitTimeSeconds=20 the 100ms gap is negligible.\n */\n pollIntervalMs?: number;\n /** Optional SNS client (for testing/DI) */\n snsClient?: SNSClient;\n /** Optional SQS client (for testing/DI) */\n sqsClient?: SQSClient;\n}\n\n/** Convert a logical topic name to UPPER_SNAKE_CASE for env var lookup. */\nexport function toUpperSnake(name: string): string {\n return name.replace(/[-.]/g, '_').toUpperCase();\n}\n\ninterface PollingState {\n active: boolean;\n}\n\nexport class SqsSnsMessageBusProvider implements MessageBusProvider {\n private readonly snsClient: SNSClient;\n private readonly sqsClient: SQSClient;\n private readonly topicArns: Record<string, string>;\n private readonly queueUrls: Record<string, string>;\n private readonly waitTimeSeconds: number;\n private readonly maxMessages: number;\n private readonly pollIntervalMs: number;\n private readonly pollingStates = new Map<string, PollingState>();\n\n constructor(config: SqsSnsConfig = {}) {\n const region = config.region ?? process.env['AWS_REGION'] ?? 'us-east-1';\n this.snsClient = config.snsClient ?? new SNSClient({ region });\n this.sqsClient = config.sqsClient ?? new SQSClient({ region });\n this.topicArns = config.topicArns ?? {};\n this.queueUrls = config.queueUrls ?? {};\n this.waitTimeSeconds = config.waitTimeSeconds ?? 20;\n this.maxMessages = config.maxMessages ?? 10;\n this.pollIntervalMs = config.pollIntervalMs ?? 100;\n }\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const topicArn = this.resolveTopicArn(topic);\n const attributes = this.buildSnsAttributes(message);\n\n const input: PublishCommandInput = {\n TopicArn: topicArn,\n Message: JSON.stringify(message.payload),\n MessageAttributes: attributes,\n };\n\n const response = await this.snsClient.send(new PublishCommand(input));\n const messageId = response.MessageId ?? `sns-${Date.now()}`;\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const queueUrl = this.resolveQueueUrl(topic);\n const id = `sqs-sub-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const state: PollingState = { active: true };\n this.pollingStates.set(id, state);\n\n // Fire-and-forget: polling loop runs in background\n this.poll(queueUrl, handler, state);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const state = this.pollingStates.get(subscription.id);\n if (state) {\n state.active = false;\n this.pollingStates.delete(subscription.id);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private resolveTopicArn(topic: string): string {\n const fromConfig = this.topicArns[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_TOPIC_${toUpperSnake(topic)}_ARN`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SNS Topic ARN found for \"${topic}\". ` +\n `Set config.topicArns[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private resolveQueueUrl(topic: string): string {\n const fromConfig = this.queueUrls[topic];\n if (fromConfig) return fromConfig;\n\n const envKey = `BUS_QUEUE_${toUpperSnake(topic)}_URL`;\n const fromEnv = process.env[envKey];\n if (fromEnv) return fromEnv;\n\n throw new Error(\n `${LOG_PREFIX} No SQS Queue URL found for \"${topic}\". ` +\n `Set config.queueUrls[\"${topic}\"] or env var ${envKey}.`,\n );\n }\n\n private buildSnsAttributes(message: BusMessage): Record<string, SNSMessageAttributeValue> {\n const attrs: Record<string, SNSMessageAttributeValue> = {};\n\n // Serialize traceContext fields\n if (message.traceContext) {\n for (const [key, value] of Object.entries(message.traceContext)) {\n attrs[`trace.${key}`] = { DataType: 'String', StringValue: value };\n }\n }\n\n // Serialize metadata fields\n if (message.metadata) {\n const { timestamp, source, correlationId } = message.metadata;\n if (timestamp) {\n attrs['meta.timestamp'] = { DataType: 'String', StringValue: timestamp };\n }\n if (source) {\n attrs['meta.source'] = { DataType: 'String', StringValue: source };\n }\n if (correlationId) {\n attrs['meta.correlationId'] = { DataType: 'String', StringValue: correlationId };\n }\n }\n\n return attrs;\n }\n\n private async poll(\n queueUrl: string,\n handler: MessageHandler,\n state: PollingState,\n ): Promise<void> {\n while (state.active) {\n // Delay between poll cycles to prevent tight-spinning when\n // waitTimeSeconds is low or the mock/SDK resolves instantly.\n await new Promise<void>((resolve) => setTimeout(resolve, this.pollIntervalMs));\n if (!state.active) break;\n\n try {\n const response = await this.sqsClient.send(\n new ReceiveMessageCommand({\n QueueUrl: queueUrl,\n WaitTimeSeconds: this.waitTimeSeconds,\n MaxNumberOfMessages: this.maxMessages,\n MessageAttributeNames: ['All'],\n }),\n );\n\n for (const sqsMessage of response.Messages ?? []) {\n if (!state.active) break;\n\n const busMessage = this.parseSqsMessage(sqsMessage);\n try {\n await handler(busMessage);\n } catch (handlerError) {\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'handler_error',\n error: handlerError instanceof Error ? handlerError.message : String(handlerError),\n queueUrl,\n }),\n );\n // Continue processing — don't crash the polling loop\n continue;\n }\n\n // Delete only after successful handler invocation\n if (sqsMessage.ReceiptHandle) {\n await this.sqsClient.send(\n new DeleteMessageCommand({\n QueueUrl: queueUrl,\n ReceiptHandle: sqsMessage.ReceiptHandle,\n }),\n );\n }\n }\n } catch (pollError) {\n // Log polling errors but keep the loop alive\n console.error(\n JSON.stringify({\n prefix: LOG_PREFIX,\n event: 'poll_error',\n error: pollError instanceof Error ? pollError.message : String(pollError),\n queueUrl,\n }),\n );\n }\n }\n }\n\n private parseSqsMessage(sqsMessage: Message): BusMessage {\n const payload = sqsMessage.Body ? JSON.parse(sqsMessage.Body) : null;\n const traceContext = this.extractTraceContext(sqsMessage.MessageAttributes);\n const metadata = this.extractMetadata(sqsMessage.MessageAttributes);\n\n return {\n payload,\n ...(traceContext !== undefined && { traceContext }),\n ...(metadata !== undefined && { metadata }),\n };\n }\n\n private extractTraceContext(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): Record<string, string> | undefined {\n if (!attrs) return undefined;\n\n const trace: Record<string, string> = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith('trace.') && value.StringValue) {\n trace[key.slice('trace.'.length)] = value.StringValue;\n }\n }\n\n return Object.keys(trace).length > 0 ? trace : undefined;\n }\n\n private extractMetadata(\n attrs?: Record<string, SQSMessageAttributeValue>,\n ): BusMessage['metadata'] {\n if (!attrs) return undefined;\n\n const timestamp = attrs['meta.timestamp']?.StringValue;\n const source = attrs['meta.source']?.StringValue;\n const correlationId = attrs['meta.correlationId']?.StringValue;\n\n if (!timestamp && !source && !correlationId) return undefined;\n\n return {\n ...(timestamp && { timestamp }),\n ...(source && { source }),\n ...(correlationId && { correlationId }),\n };\n }\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { HttpTrigger } from '@stackwright-services/types';\nimport { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport type { z } from 'zod';\n\n/**\n * Options for creating an HTTP trigger runtime.\n */\nexport interface HttpTriggerOptions {\n /** The HTTP trigger configuration from the flow */\n trigger: HttpTrigger;\n /** Flow handler function */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional input validation schema */\n inputSchema?: z.ZodType;\n /** Optional output validation schema */\n outputSchema?: z.ZodType;\n}\n\n/**\n * Typed error response for consistent error handling.\n */\nexport interface ServiceError {\n error: string;\n code: string;\n details?: unknown;\n}\n\n/**\n * Create a Hono app for an HTTP trigger.\n *\n * This is the runtime entry point for HTTP-triggered flows.\n * The same code works on:\n * - Node.js (via @hono/node-server)\n * - AWS Lambda (via Lambda Web Adapter)\n * - Edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport function createHttpTrigger(options: HttpTriggerOptions): Hono {\n const { trigger, handler, inputSchema, outputSchema } = options;\n const app = new Hono();\n\n // Health check\n app.get('/health', (c) => c.json({ status: 'ok', trigger: 'http' }));\n\n // Register the flow route\n const method = trigger.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n\n app[method](trigger.path, async (c: Context) => {\n // Extract input based on method\n let input: unknown;\n if (trigger.method === 'GET') {\n input = Object.fromEntries(new URL(c.req.url).searchParams);\n } else {\n try {\n input = await c.req.json();\n } catch {\n return c.json<ServiceError>(\n { error: 'Invalid JSON body', code: 'INVALID_REQUEST_BODY' },\n 400,\n );\n }\n }\n\n // Validate input if schema provided\n if (inputSchema) {\n const result = inputSchema.safeParse(input);\n if (!result.success) {\n return c.json<ServiceError>(\n {\n error: 'Input validation failed',\n code: 'VALIDATION_ERROR',\n details: result.error.issues,\n },\n 400,\n );\n }\n input = result.data;\n }\n\n // Create context\n const context: CapabilityContext = {\n traceId: c.req.header('x-trace-id') ?? c.req.header('x-request-id') ?? crypto.randomUUID(),\n logger: createLogger(),\n };\n\n // Execute flow\n try {\n const result = await handler(input, context);\n\n // Validate output if schema provided\n if (outputSchema) {\n const outputResult = outputSchema.safeParse(result);\n if (!outputResult.success) {\n return c.json<ServiceError>(\n { error: 'Output validation failed', code: 'OUTPUT_VALIDATION_ERROR' },\n 500,\n );\n }\n return c.json(outputResult.data);\n }\n\n return c.json(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return c.json<ServiceError>({ error: message, code: 'FLOW_EXECUTION_ERROR' }, 500);\n }\n });\n\n return app;\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { EventTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating an event trigger adapter.\n */\nexport interface EventTriggerOptions {\n /** The event trigger configuration from the flow */\n trigger: EventTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * EventTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class EventTriggerAdapter implements TriggerAdapter {\n readonly type = 'event';\n readonly topic: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: EventTriggerOptions) {\n this.topic = options.trigger.source.replace(/^bus:/, '');\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.topic, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Event payload validation failed', {\n topic: this.topic,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Event handler failed', {\n topic: this.topic,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { ScheduleTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a schedule trigger adapter.\n */\nexport interface ScheduleTriggerOptions {\n /** The schedule trigger configuration from the flow */\n trigger: ScheduleTrigger;\n /** Flow handler function invoked on each tick */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation */\n inputSchema?: z.ZodType;\n /**\n * Override interval in milliseconds for local dev / testing.\n * When not provided, defaults to 60_000ms and logs a warning that\n * cron parsing is not built-in. In production, scheduling is handled\n * by infrastructure (EventBridge, CronJob on K8s, etc.).\n */\n intervalMs?: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 60_000;\n\n/**\n * ScheduleTriggerAdapter — local-dev / test scheduler that fires the flow\n * handler on a fixed interval.\n *\n * NOT a production cron implementation. In production the cron expression\n * is consumed by infrastructure (EventBridge rules, K8s CronJobs, etc.)\n * and this adapter is not used.\n *\n * Handler errors are caught and logged — the scheduler never crashes.\n */\nexport class ScheduleTriggerAdapter implements TriggerAdapter {\n readonly type = 'schedule';\n readonly cron: string;\n\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private readonly intervalMs: number;\n private timer: ReturnType<typeof setInterval> | undefined;\n\n constructor(options: ScheduleTriggerOptions) {\n this.cron = options.trigger.cron;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n }\n\n async start(): Promise<void> {\n if (this.intervalMs === DEFAULT_INTERVAL_MS) {\n const logger = createLogger();\n logger.warn('Cron parsing not built-in; using default 60s interval for local dev', {\n cron: this.cron,\n intervalMs: this.intervalMs,\n });\n }\n\n this.timer = setInterval(() => {\n void this.tick();\n }, this.intervalMs);\n }\n\n async stop(): Promise<void> {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }\n\n private async tick(): Promise<void> {\n const traceId = crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler({}, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Schedule handler failed', {\n cron: this.cron,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { CapabilityContext } from '@stackwright-services/capabilities';\nimport type { QueueTrigger } from '@stackwright-services/types';\nimport type { z } from 'zod';\n\nimport type { BusMessage, MessageBusProvider, Subscription } from '../messaging/provider';\nimport type { TriggerAdapter } from './adapter';\n\n/**\n * Options for creating a queue trigger adapter.\n */\nexport interface QueueTriggerOptions {\n /** The queue trigger configuration from the flow */\n trigger: QueueTrigger;\n /** Message bus provider to subscribe through */\n messageBus: MessageBusProvider;\n /** Flow handler function invoked for each valid message */\n handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n /** Optional Zod schema for input validation — invalid messages are logged and skipped */\n inputSchema?: z.ZodType;\n}\n\n/**\n * QueueTriggerAdapter — subscribes to a MessageBusProvider topic and routes\n * incoming messages through the compiled flow handler.\n *\n * Semantically represents point-to-point delivery (single consumer), unlike\n * the fan-out semantics of EventTriggerAdapter. At the runtime adapter level\n * both use messageBus.subscribe() — the distinction lives in the concrete\n * bus implementation (SQS vs SNS+SQS, competing consumers vs broadcast).\n *\n * Bus consumers must never crash: handler errors are logged, not rethrown.\n * Validation failures are logged as warnings and the message is skipped.\n */\nexport class QueueTriggerAdapter implements TriggerAdapter {\n readonly type = 'queue';\n readonly queueName: string;\n\n private readonly messageBus: MessageBusProvider;\n private readonly handler: (input: unknown, context: CapabilityContext) => Promise<unknown>;\n private readonly inputSchema: z.ZodType | undefined;\n private subscription: Subscription | undefined;\n\n constructor(options: QueueTriggerOptions) {\n this.queueName = options.trigger.name;\n this.messageBus = options.messageBus;\n this.handler = options.handler;\n this.inputSchema = options.inputSchema;\n }\n\n async start(): Promise<void> {\n this.subscription = await this.messageBus.subscribe(this.queueName, (message) =>\n this.handleMessage(message),\n );\n }\n\n async stop(): Promise<void> {\n if (this.subscription) {\n await this.subscription.cancel();\n this.subscription = undefined;\n }\n }\n\n private async handleMessage(message: BusMessage): Promise<void> {\n let payload: unknown = message.payload;\n\n // Validate input against schema if provided\n if (this.inputSchema) {\n const result = this.inputSchema.safeParse(payload);\n if (!result.success) {\n const logger = createLogger();\n logger.warn('Queue payload validation failed', {\n queueName: this.queueName,\n errors: result.error.issues,\n });\n return;\n }\n payload = result.data;\n }\n\n // Build capability context with trace propagation\n const traceId = message.traceContext?.['traceId'] ?? crypto.randomUUID();\n const context: CapabilityContext = {\n traceId,\n logger: createLogger(),\n };\n\n try {\n await this.handler(payload, context);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n context.logger.error('Queue handler failed', {\n queueName: this.queueName,\n error: errorMessage,\n });\n }\n }\n}\n\nfunction createLogger() {\n return {\n debug: (msg: string, data?: Record<string, unknown>) =>\n console.debug(JSON.stringify({ level: 'debug', msg, ...data })),\n info: (msg: string, data?: Record<string, unknown>) =>\n console.info(JSON.stringify({ level: 'info', msg, ...data })),\n warn: (msg: string, data?: Record<string, unknown>) =>\n console.warn(JSON.stringify({ level: 'warn', msg, ...data })),\n error: (msg: string, data?: Record<string, unknown>) =>\n console.error(JSON.stringify({ level: 'error', msg, ...data })),\n };\n}\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\nconst NOOP_SPAN: SpanHandle = {\n setAttribute: () => {},\n setError: () => {},\n end: () => {},\n};\n\n/**\n * No-op observability provider -- zero runtime cost.\n * Used when OTel is not configured (the default).\n * All methods are no-ops that return immediately.\n */\nexport class NoopObservabilityProvider implements ObservabilityProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n return NOOP_SPAN;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n // Intentionally empty -- zero cost when disabled\n }\n}\n\n/** Singleton no-op provider */\nexport const noopProvider = new NoopObservabilityProvider();\n","import type { ObservabilityProvider, SpanHandle } from './provider';\n\n/**\n * OpenTelemetry-compatible observability provider.\n *\n * In Phase 1, this uses structured console logging with span semantics.\n * In Phase 2+, this wraps @opentelemetry/api (trace + metrics).\n *\n * The interface is stable -- upgrading to real OTel is a drop-in replacement.\n */\nexport class OtelObservabilityProvider implements ObservabilityProvider {\n private readonly serviceName: string;\n\n constructor(serviceName: string = 'stackwright-service') {\n this.serviceName = serviceName;\n }\n\n startSpan(name: string, attributes?: Record<string, string | number | boolean>): SpanHandle {\n const spanId = crypto.randomUUID().slice(0, 16);\n const startTime = Date.now();\n\n console.info(\n JSON.stringify({\n type: 'span_start',\n spanId,\n name,\n service: this.serviceName,\n attributes,\n timestamp: new Date().toISOString(),\n }),\n );\n\n const spanAttributes: Record<string, string | number | boolean> = { ...attributes };\n\n return {\n setAttribute(key: string, value: string | number | boolean): void {\n spanAttributes[key] = value;\n },\n setError(error: Error): void {\n spanAttributes['error'] = true;\n spanAttributes['error.message'] = error.message;\n console.error(\n JSON.stringify({\n type: 'span_error',\n spanId,\n name,\n error: error.message,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n end(): void {\n const duration = Date.now() - startTime;\n console.info(\n JSON.stringify({\n type: 'span_end',\n spanId,\n name,\n duration,\n attributes: spanAttributes,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n };\n }\n\n recordMetric(name: string, value: number, tags?: Record<string, string>): void {\n console.info(\n JSON.stringify({\n type: 'metric',\n name,\n value,\n tags,\n service: this.serviceName,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n}\n","import type { ObservabilityProvider } from './provider';\nimport { noopProvider } from './noop';\nimport { OtelObservabilityProvider } from './otel';\n\n/**\n * Create an observability provider based on environment configuration.\n *\n * - OTEL_ENABLED=true (or \"1\") -> OtelObservabilityProvider\n * - Otherwise -> NoopObservabilityProvider (zero cost)\n *\n * The provider is injected into compiled flow code, not imported.\n * This means zero runtime overhead when observability is disabled.\n */\nexport function createObservabilityProvider(options?: {\n serviceName?: string;\n}): ObservabilityProvider {\n const otelEnabled = process.env['OTEL_ENABLED'];\n\n if (otelEnabled === 'true' || otelEnabled === '1') {\n return new OtelObservabilityProvider(options?.serviceName);\n }\n\n return noopProvider;\n}\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/** No-op audit provider -- zero runtime cost when auditing is disabled */\nexport class NoopAuditProvider implements AuditProvider {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n record(_event: AuditEvent): void {\n // Intentionally empty\n }\n\n async flush(): Promise<void> {\n // Nothing to flush\n }\n}\n\n/** Singleton no-op audit provider */\nexport const noopAuditProvider = new NoopAuditProvider();\n","import type { AuditProvider, AuditEvent } from './audit';\n\n/**\n * Console audit provider -- writes events to stderr as JSON Lines.\n *\n * Works in Lambda (stderr -> CloudWatch), containers (stderr -> log collector),\n * and local dev (stderr -> terminal).\n *\n * Uses stderr to avoid mixing with application stdout.\n */\nexport class ConsoleAuditProvider implements AuditProvider {\n record(event: AuditEvent): void {\n process.stderr.write(JSON.stringify(event) + '\\n');\n }\n\n async flush(): Promise<void> {\n // Console writes are synchronous -- nothing to flush\n }\n}\n","import type { AuditProvider } from './audit';\nimport { noopAuditProvider } from './audit-noop';\nimport { ConsoleAuditProvider } from './audit-console';\n\n/**\n * Create an audit provider based on environment configuration.\n *\n * - STACKWRIGHT_AUDIT=true (or \"1\") -> ConsoleAuditProvider (stderr JSON Lines)\n * - Otherwise -> NoopAuditProvider (zero cost)\n *\n * Defaults to OFF in production, can be enabled with env var.\n */\nexport function createAuditProvider(): AuditProvider {\n const auditEnabled = process.env['STACKWRIGHT_AUDIT'];\n if (auditEnabled === 'true' || auditEnabled === '1') {\n return new ConsoleAuditProvider();\n }\n return noopAuditProvider;\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Compute a truncated SHA-256 hash of a value.\n *\n * Used for audit events -- captures enough to detect \"did the input/output change?\"\n * without storing full payloads (which may be large or contain PII).\n *\n * Returns first 16 hex characters of SHA-256.\n * Deterministic: same input always produces same hash.\n */\nexport function auditHash(value: unknown): string {\n const serialized = JSON.stringify(value, (_key, val) => {\n // Handle non-serializable types gracefully\n if (typeof val === 'bigint') return val.toString();\n if (val instanceof Error) return { message: val.message, name: val.name };\n if (typeof val === 'function') return '[function]';\n if (typeof val === 'symbol') return val.toString();\n if (val === undefined) return null;\n return val;\n });\n return createHash('sha256')\n .update(serialized ?? 'undefined')\n .digest('hex')\n .slice(0, 16);\n}\n","import type {\n BusMessage,\n MessageBusProvider,\n MessageHandler,\n PublishResult,\n Subscription,\n} from './provider';\n\n/**\n * In-memory MessageBusProvider — delivers messages locally within the process.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external bus is configured\n *\n * Messages published to a topic are delivered synchronously to all\n * subscribed handlers for that topic.\n */\nexport class InMemoryMessageBusProvider implements MessageBusProvider {\n private subscriptions = new Map<string, Map<string, MessageHandler>>();\n private nextId = 0;\n\n async publish(topic: string, message: BusMessage): Promise<PublishResult> {\n const messageId = message.metadata?.messageId ?? `mem-${++this.nextId}`;\n const topicHandlers = this.subscriptions.get(topic);\n\n if (topicHandlers) {\n const enrichedMessage: BusMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n messageId,\n timestamp: message.metadata?.timestamp ?? new Date().toISOString(),\n },\n };\n\n // Deliver to all subscribers\n const handlers = Array.from(topicHandlers.values());\n await Promise.all(handlers.map((handler) => handler(enrichedMessage)));\n }\n\n return { messageId, topic, success: true };\n }\n\n async subscribe(topic: string, handler: MessageHandler): Promise<Subscription> {\n const id = `sub-${++this.nextId}`;\n\n let topicHandlers = this.subscriptions.get(topic);\n if (!topicHandlers) {\n topicHandlers = new Map();\n this.subscriptions.set(topic, topicHandlers);\n }\n topicHandlers.set(id, handler);\n\n const cancel = async (): Promise<void> => {\n await this.unsubscribe({ id, topic, cancel: async () => {} });\n };\n\n return { id, topic, cancel };\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n const topicHandlers = this.subscriptions.get(subscription.topic);\n if (topicHandlers) {\n topicHandlers.delete(subscription.id);\n if (topicHandlers.size === 0) {\n this.subscriptions.delete(subscription.topic);\n }\n }\n }\n\n /** Helper for testing: get count of active subscriptions for a topic */\n getSubscriptionCount(topic: string): number {\n return this.subscriptions.get(topic)?.size ?? 0;\n }\n\n /** Helper for testing: clear all subscriptions */\n clear(): void {\n this.subscriptions.clear();\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryBusProvider = new InMemoryMessageBusProvider();\n","export type {\n MessageBusProvider,\n BusMessage,\n MessageMetadata,\n PublishResult,\n MessageHandler,\n Subscription,\n} from './provider';\nexport { InMemoryMessageBusProvider, inMemoryBusProvider } from './noop';\nexport { SqsSnsMessageBusProvider, type SqsSnsConfig } from './sqs-sns';\nexport { createMessageBusProvider } from './factory';\n","import type { MessageBusProvider } from './provider';\nimport { inMemoryBusProvider } from './noop';\n\n/**\n * Create a MessageBusProvider based on environment configuration.\n *\n * - MESSAGE_BUS_PROVIDER=memory (or unset) -> InMemoryMessageBusProvider\n * - MESSAGE_BUS_PROVIDER=sqs -> SQS/SNS adapter\n *\n * Same pattern as createObservabilityProvider().\n */\nexport function createMessageBusProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n /** Provider-specific config (e.g. SqsSnsConfig for 'sqs') */\n config?: Record<string, unknown>;\n}): MessageBusProvider {\n const providerType = options?.provider ?? process.env['MESSAGE_BUS_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryBusProvider;\n case 'sqs': {\n // Dynamic require to avoid bundling AWS SDK when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SqsSnsMessageBusProvider } = require('./sqs-sns') as typeof import('./sqs-sns');\n return new SqsSnsMessageBusProvider(options?.config);\n }\n default:\n console.warn(\n `stackwright-services:messaging Unknown MESSAGE_BUS_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryBusProvider;\n }\n}\n","import type { NotificationMessage, NotificationProvider, SendResult } from './provider';\n\n/**\n * In-memory NotificationProvider — records notifications locally for inspection.\n *\n * Used for:\n * - Unit and integration testing (no infrastructure required)\n * - Local development (stackwright-services dev mode)\n * - Default when no external notification service is configured\n *\n * Notifications are stored in-memory and can be inspected via helper methods.\n */\nexport class InMemoryNotificationProvider implements NotificationProvider {\n private notifications: Array<NotificationMessage & { notificationId: string }> = [];\n private nextId = 0;\n\n async send(notification: NotificationMessage): Promise<SendResult> {\n const notificationId = `notif-${++this.nextId}`;\n\n this.notifications.push({\n ...notification,\n notificationId,\n metadata: {\n ...notification.metadata,\n timestamp: notification.metadata?.timestamp ?? new Date().toISOString(),\n },\n });\n\n return {\n notificationId,\n channel: notification.channel,\n success: true,\n };\n }\n\n /** Helper for testing: get all sent notifications */\n getSentNotifications(): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return [...this.notifications];\n }\n\n /** Helper for testing: get notifications filtered by channel */\n getByChannel(channel: string): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.channel === channel);\n }\n\n /** Helper for testing: get notifications filtered by recipient */\n getByRecipient(\n recipient: string,\n ): ReadonlyArray<NotificationMessage & { notificationId: string }> {\n return this.notifications.filter((n) => n.recipient === recipient);\n }\n\n /** Helper for testing: get count of sent notifications */\n get sentCount(): number {\n return this.notifications.length;\n }\n\n /** Helper for testing: clear all recorded notifications */\n clear(): void {\n this.notifications = [];\n this.nextId = 0;\n }\n}\n\n/** Singleton in-memory provider for convenience */\nexport const inMemoryNotificationProvider = new InMemoryNotificationProvider();\n","import type { NotificationProvider } from './provider';\nimport { inMemoryNotificationProvider } from './noop';\n\n/**\n * Create a NotificationProvider based on environment configuration.\n *\n * - NOTIFICATION_PROVIDER=memory (or unset) -> InMemoryNotificationProvider\n * - NOTIFICATION_PROVIDER=sendgrid -> (future: SendGrid adapter)\n * - NOTIFICATION_PROVIDER=twilio -> (future: Twilio adapter)\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createNotificationProvider(options?: {\n /** Override the provider type (defaults to env var) */\n provider?: string;\n}): NotificationProvider {\n const providerType = options?.provider ?? process.env['NOTIFICATION_PROVIDER'] ?? 'memory';\n\n switch (providerType) {\n case 'memory':\n return inMemoryNotificationProvider;\n // Future: case 'sendgrid' -> SendGrid adapter\n // Future: case 'twilio' -> Twilio/SNS adapter\n // Future: case 'fcm' -> Firebase Cloud Messaging adapter\n default:\n console.warn(\n `stackwright-services:notifications Unknown NOTIFICATION_PROVIDER \"${providerType}\", falling back to in-memory`,\n );\n return inMemoryNotificationProvider;\n }\n}\n","import type { AuthClaims, AuthProvider, TokenValidationResult } from './provider';\n\n/**\n * No-op AuthProvider — fail-closed default.\n *\n * Used when no auth provider is configured:\n * - validateToken() always returns { valid: false } (reject all tokens)\n * - extractClaims() throws (no claims without a real provider)\n * - checkRole() always returns false (deny all role checks)\n *\n * This is intentionally fail-closed: if you forget to install a real\n * auth provider, every auth check fails rather than silently passing.\n */\nexport class NoopAuthProvider implements AuthProvider {\n readonly name = 'noop';\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async validateToken(token: string): Promise<TokenValidationResult> {\n return { valid: false, error: 'No auth provider configured' };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async extractClaims(token: string): Promise<AuthClaims> {\n throw new Error('No auth provider configured');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n checkRole(claims: AuthClaims, role: string): boolean {\n return false;\n }\n}\n\n/** Singleton no-op provider */\nexport const noopAuthProvider = new NoopAuthProvider();\n","import type { AuthProvider } from './provider';\nimport { noopAuthProvider } from './noop';\n\nexport type AuthProviderType = 'noop' | 'oidc' | 'cac';\n\n/**\n * Create an AuthProvider based on the requested type.\n *\n * - 'noop' (or unset) -> NoopAuthProvider (fail-closed default)\n * - 'oidc' -> Future: lazy require('@stackwright-pro/auth-oidc')\n * - 'cac' -> Future: lazy require('@stackwright-pro/auth-cac')\n *\n * Same pattern as createMessageBusProvider() and createObservabilityProvider().\n */\nexport function createAuthProvider(type?: AuthProviderType): AuthProvider {\n switch (type) {\n case 'oidc':\n // Future: lazy require('@stackwright-pro/auth-oidc')\n throw new Error(\n 'OIDC auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'cac':\n // Future: lazy require('@stackwright-pro/auth-cac')\n throw new Error(\n 'CAC/PKI auth provider not yet implemented. Install @stackwright-pro/auth when available.',\n );\n case 'noop':\n default:\n return noopAuthProvider;\n }\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\n/**\n * NoopDataSourceProvider — used when no data source provider is installed.\n *\n * listSources() returns an empty array (no sources available to the schema expander).\n * execute() throws a descriptive error pointing to the correct package to install.\n *\n * This is the fail-closed default, consistent with NoopAuthProvider.\n */\nexport class NoopDataSourceProvider implements DataSourceProvider {\n readonly name = 'noop';\n\n listSources(): DataSourceDescriptor[] {\n return [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(_source: string, _operation: string, _params: unknown): Promise<DataSourceResult> {\n return Promise.reject(\n new Error(\n 'No DataSourceProvider is configured. ' +\n 'Install @stackwright-pro/openapi or @stackwright-pro/pulse and register an adapter, ' +\n 'or set DATA_SOURCE_PROVIDER in your environment.',\n ),\n );\n }\n}\n\nexport const noopDataSourceProvider = new NoopDataSourceProvider();\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:openapi';\n\n/**\n * A typed operation handler for a single OpenAPI operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type OpenApiOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single OpenAPI-backed data source.\n */\nexport interface OpenApiSourceRegistration {\n /** Source ID — matches the id in `source: openapi:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, OpenApiOperationHandler>;\n}\n\n/**\n * Configuration for OpenApiDataSourceProvider.\n */\nexport interface OpenApiAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: OpenApiSourceRegistration[];\n}\n\n/**\n * OpenApiDataSourceProvider — wraps registered OpenAPI operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed OpenAPI client methods (from @stackwright-pro/openapi),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/openapi` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class OpenApiDataSourceProvider implements DataSourceProvider {\n readonly name = 'openapi';\n\n private readonly sourcesMap: Map<string, OpenApiSourceRegistration>;\n\n constructor(private readonly config: OpenApiAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'openapi' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in OpenApiAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates an OpenApiDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/openapi's datasource-adapter when installed.\n */\nexport function createOpenApiDataSourceProvider(config: OpenApiAdapterConfig): DataSourceProvider {\n return new OpenApiDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/openapi's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: openapi:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:pulse';\n\n/**\n * A typed operation handler for a single Pulse operation.\n * Receives the caller-supplied params and returns the operation result.\n * Implementations are typically generated typed client methods.\n */\nexport type PulseOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single Pulse-backed data source.\n */\nexport interface PulseSourceRegistration {\n /** Source ID — matches the id in `source: pulse:<id>` YAML references */\n id: string;\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, PulseOperationHandler>;\n}\n\n/**\n * Configuration for PulseDataSourceProvider.\n */\nexport interface PulseAdapterConfig {\n /** Data sources to register. Each source has a set of named operation handlers. */\n sources: PulseSourceRegistration[];\n}\n\n/**\n * PulseDataSourceProvider — wraps registered Pulse operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a map of operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically generated typed Pulse client methods (from @stackwright-pro/pulse),\n * but any function with the right signature works — useful for testing with mocks.\n *\n * Design rationale:\n * - Same registry pattern as SqsSnsMessageBusProvider (wraps external clients, injectable for testing).\n * - `@stackwright-pro/pulse` uses this adapter when registering its generated clients; the adapter\n * is transport-agnostic and does not hard-import that package.\n * - The `DataSourceResult.metadata` field carries the raw handler response shape for callers\n * that need the full structure beyond `data`.\n *\n * Usage example:\n * ```typescript\n * const provider = createPulseDataSourceProvider({\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryMetrics: pulseClient.queryMetrics },\n * }],\n * });\n * // Matches `source: pulse:fleet-db` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error (not throws sync).\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is (the handler is responsible for shaping them).\n */\nexport class PulseDataSourceProvider implements DataSourceProvider {\n readonly name = 'pulse';\n\n private readonly sourcesMap: Map<string, PulseSourceRegistration>;\n\n constructor(private readonly config: PulseAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: 'pulse' as const,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in PulseAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a PulseDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by @stackwright-pro/pulse's datasource-adapter when installed.\n */\nexport function createPulseDataSourceProvider(config: PulseAdapterConfig): DataSourceProvider {\n return new PulseDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * @stackwright-pro/pulse's datasource-adapter overrides this with a static\n * manifest of all generated clients, enabling the compiler to validate\n * `source: pulse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceDescriptor, DataSourceProvider, DataSourceResult } from './provider';\n\nconst LOG_PREFIX = 'stackwright-services:datasource:streaming';\n\n/**\n * A typed operation handler for a single streaming (WebSocket / SSE) operation.\n * Receives caller-supplied params and returns the operation result.\n *\n * For WebSocket/SSE sources the typical patterns are:\n * - Request-response over WebSocket (send + await reply)\n * - Snapshot of last-known state from an in-process subscription cache\n * - Publish a message to the stream\n *\n * Implementations are responsible for managing the underlying transport connection.\n */\nexport type StreamingOperationHandler = (params: unknown) => Promise<unknown>;\n\n/**\n * Registration entry for a single streaming data source.\n */\nexport interface StreamingSourceRegistration {\n /** Source ID — matches the id in `source: websocket:<id>` or `source: sse:<id>` YAML references */\n id: string;\n /**\n * Transport protocol for this source.\n * - `websocket`: bidirectional, binary-capable, suitable for most real-time feeds\n * - `sse`: unidirectional server→client, HTTP-compatible, firewall-friendly\n */\n transport: 'websocket' | 'sse';\n /** Human-readable description (forwarded to DataSourceDescriptor) */\n description?: string;\n /** Map of operation name → typed handler function */\n operations: Record<string, StreamingOperationHandler>;\n}\n\n/**\n * Configuration for StreamingDataSourceProvider.\n */\nexport interface StreamingAdapterConfig {\n /** Data sources to register. Each source declares its transport + named operation handlers. */\n sources: StreamingSourceRegistration[];\n}\n\n/**\n * StreamingDataSourceProvider — wraps registered WebSocket/SSE operation handlers as a DataSourceProvider.\n *\n * Architecture:\n * - Callers register named sources at construction time, each with a transport type and operation handlers.\n * - `listSources()` returns the full descriptor table for all registered sources.\n * - `execute(source, operation, params)` dispatches to the registered handler.\n * - Handlers are typically typed client methods wrapping `useStreaming` subscriptions\n * (from `@stackwright-pro/pulse`), but any async function with the right signature works.\n *\n * Design rationale:\n * - Same registry pattern as `PulseDataSourceProvider` — swapping 'pulse' for 'websocket'/'sse'.\n * - Transport-agnostic at this layer: the handler decides how to communicate over the socket.\n * - `@stackwright-pro/pulse` registers streaming clients here when installed; the adapter\n * does NOT hard-import that package (IoC at factory time).\n *\n * Usage example:\n * ```typescript\n * const provider = createStreamingDataSourceProvider({\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * });\n * // Matches `source: websocket:ais-vessels` YAML references\n * ```\n *\n * Error semantics:\n * - Unknown source → rejects with a descriptive Error.\n * - Unknown operation → rejects with a descriptive Error.\n * - Handler errors propagate as-is.\n */\nexport class StreamingDataSourceProvider implements DataSourceProvider {\n readonly name = 'streaming';\n\n private readonly sourcesMap: Map<string, StreamingSourceRegistration>;\n\n constructor(private readonly config: StreamingAdapterConfig) {\n this.sourcesMap = new Map(config.sources.map((s) => [s.id, s]));\n }\n\n listSources(): DataSourceDescriptor[] {\n return Array.from(this.sourcesMap.values()).map((s) => ({\n id: s.id,\n transport: s.transport,\n operations: Object.keys(s.operations),\n ...(s.description !== undefined && { description: s.description }),\n }));\n }\n\n async execute(source: string, operation: string, params: unknown): Promise<DataSourceResult> {\n const registration = this.sourcesMap.get(source);\n if (!registration) {\n const knownSources = Array.from(this.sourcesMap.keys());\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown source \"${source}\". ` +\n (knownSources.length > 0\n ? `Known sources: ${knownSources.join(', ')}.`\n : 'No sources are registered. Pass sources in StreamingAdapterConfig.'),\n ),\n );\n }\n\n const handler = registration.operations[operation];\n if (!handler) {\n const knownOps = Object.keys(registration.operations);\n return Promise.reject(\n new Error(\n `${LOG_PREFIX} Unknown operation \"${operation}\" on source \"${source}\". ` +\n (knownOps.length > 0\n ? `Known operations: ${knownOps.join(', ')}.`\n : 'No operations are registered for this source.'),\n ),\n );\n }\n\n const data = await handler(params);\n return { data };\n }\n}\n\n/**\n * Factory function — creates a StreamingDataSourceProvider from config.\n * This is the entry point called by createDataSourceProvider() and\n * by `@stackwright-pro/pulse`'s streaming datasource adapter when installed.\n */\nexport function createStreamingDataSourceProvider(\n config: StreamingAdapterConfig,\n): DataSourceProvider {\n return new StreamingDataSourceProvider(config);\n}\n\n/**\n * Prebuild-time source listing — returns an empty array because registered\n * sources are known only at runtime when handlers are wired.\n *\n * `@stackwright-pro/pulse`'s streaming-datasource-adapter overrides this with a\n * static manifest of all generated streaming clients, enabling the compiler to\n * validate `source: websocket:*` and `source: sse:*` references at build time.\n */\nexport function listDataSources(): DataSourceDescriptor[] {\n return [];\n}\n","import type { DataSourceProvider } from './provider';\nimport { noopDataSourceProvider } from './noop';\nimport type { OpenApiAdapterConfig } from './openapi-adapter';\nimport { createOpenApiDataSourceProvider } from './openapi-adapter';\nimport type { PulseAdapterConfig } from './pulse-adapter';\nimport { createPulseDataSourceProvider } from './pulse-adapter';\nimport type { StreamingAdapterConfig } from './streaming-adapter';\nimport { createStreamingDataSourceProvider } from './streaming-adapter';\n\n/**\n * Create a DataSourceProvider based on installed packages and environment configuration.\n *\n * Resolution order (first match wins):\n * 1. `options.provider` — explicit code-level override\n * 2. `DATA_SOURCE_PROVIDER` env var — environment-level override\n * 3. IoC auto-discovery — scans for installed adapter packages via require.resolve()\n * a. `@stackwright-pro/openapi/datasource-adapter` (checked first)\n * b. `@stackwright-pro/pulse/datasource-adapter`\n * 4. NoopDataSourceProvider — fail-closed default, throws on execute()\n *\n * Same pattern as createMessageBusProvider() and createAuthProvider().\n *\n * @example Default (IoC — install the package, nothing else needed)\n * ```typescript\n * // With @stackwright-pro/pulse in node_modules:\n * const provider = createDataSourceProvider();\n * // → PulseDataSourceProvider (auto-discovered)\n *\n * // With nothing installed:\n * const provider = createDataSourceProvider();\n * // → NoopDataSourceProvider (execute() will throw)\n * ```\n *\n * @example Explicit override with config (useful in tests and custom setups)\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'pulse',\n * config: {\n * sources: [{\n * id: 'fleet-db',\n * operations: { queryGeneratorStatus: mockHandler },\n * }],\n * },\n * });\n * ```\n *\n * @example Streaming WebSocket/SSE provider\n * ```typescript\n * const provider = createDataSourceProvider({\n * provider: 'websocket',\n * config: {\n * sources: [{\n * id: 'ais-vessels',\n * transport: 'websocket',\n * operations: { getLatestPositions: () => vesselCache.snapshot() },\n * }],\n * },\n * });\n * ```\n *\n * @example Environment-level override (force noop in isolated tests)\n * ```bash\n * DATA_SOURCE_PROVIDER=noop node my-service.js\n * DATA_SOURCE_PROVIDER=pulse node my-service.js # force pulse even if openapi is installed\n * DATA_SOURCE_PROVIDER=websocket node my-service.js # force streaming (WebSocket)\n * DATA_SOURCE_PROVIDER=sse node my-service.js # force streaming (SSE)\n * ```\n */\nexport function createDataSourceProvider(options?: {\n /** Override the provider type ('openapi' | 'pulse' | 'websocket' | 'sse' | 'noop') */\n provider?: string;\n /** Provider-specific config passed through to the adapter */\n config?: Record<string, unknown>;\n}): DataSourceProvider {\n const providerType = options?.provider ?? process.env['DATA_SOURCE_PROVIDER'] ?? _autoDiscover();\n\n switch (providerType) {\n case 'noop':\n return noopDataSourceProvider;\n\n case 'openapi': {\n // Local OpenAPI adapter — always present, no dynamic require needed.\n // @stackwright-pro/openapi can supplement this via auto-discovery when installed.\n return createOpenApiDataSourceProvider(\n (options?.config as OpenApiAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'pulse': {\n // Local Pulse adapter — always present, no dynamic require needed.\n // @stackwright-pro/pulse can supplement this via auto-discovery when installed.\n return createPulseDataSourceProvider(\n (options?.config as PulseAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n case 'websocket':\n case 'sse': {\n // Streaming adapter — handles both WebSocket and SSE sources.\n // @stackwright-pro/pulse ships a streaming-datasource-adapter entry point that\n // auto-registers generated streaming clients when installed.\n return createStreamingDataSourceProvider(\n (options?.config as StreamingAdapterConfig | undefined) ?? { sources: [] },\n );\n }\n\n default:\n if (providerType !== 'noop') {\n console.warn(\n `stackwright-services:datasource Unknown DATA_SOURCE_PROVIDER \"${providerType}\", falling back to noop`,\n );\n }\n return noopDataSourceProvider;\n }\n}\n\n/**\n * Auto-discover installed providers via require.resolve().\n * Returns the first provider type found, or 'noop' if none are installed.\n *\n * This is a pure filesystem probe — no module is loaded here, no side effects.\n * Actual provider construction happens in createDataSourceProvider() after this returns.\n *\n * Discovery convention: each adapter package ships a `datasource-adapter` subpath export\n * (`<package>/datasource-adapter`) that this probe checks for. The local OpenApiDataSourceProvider\n * and PulseDataSourceProvider do NOT trigger auto-discovery — they require explicit source\n * registration via factory config. Only the Pro adapter packages auto-register.\n *\n * Check order matters when both are installed: openapi wins. Override with\n * DATA_SOURCE_PROVIDER env var or explicit options.provider to change this.\n */\nfunction _autoDiscover(): string {\n const candidates: Array<{ pkg: string; providerType: string }> = [\n // @stackwright-pro/openapi ships its own datasource-adapter entry point that\n // auto-registers all generated clients — when that package is installed, 'openapi'\n // is returned here. The local OpenApiDataSourceProvider requires explicit source\n // registration and does NOT trigger auto-discovery.\n { pkg: '@stackwright-pro/openapi/datasource-adapter', providerType: 'openapi' },\n // @stackwright-pro/pulse follows the same pattern for Pulse-backed data sources.\n { pkg: '@stackwright-pro/pulse/datasource-adapter', providerType: 'pulse' },\n // @stackwright-pro/pulse also ships a streaming-datasource-adapter for WebSocket/SSE sources.\n // websocket wins if both pulse and streaming are installed (use DATA_SOURCE_PROVIDER to override).\n { pkg: '@stackwright-pro/pulse/streaming-datasource-adapter', providerType: 'websocket' },\n ];\n\n for (const { pkg, providerType } of candidates) {\n try {\n require.resolve(pkg);\n return providerType;\n } catch {\n // not installed — try next\n }\n }\n\n // Nothing found — createDataSourceProvider() will use NoopDataSourceProvider.\n // Any flow step that calls provider.execute() will receive a descriptive error\n // pointing to the correct package to install.\n return 'noop';\n}\n","import type { DataSourceDescriptor } from './provider';\n\n/**\n * Result of a prebuild-time data source scan.\n */\nexport interface DataSourceScanResult {\n /** All sources discovered across all installed providers */\n sources: DataSourceDescriptor[];\n /** Which provider packages were found (for logging/diagnostics) */\n detectedProviders: string[];\n}\n\n/**\n * Scan installed packages at prebuild time to discover available data sources.\n *\n * This is called by the compiler and prebuild hook (yo8) to expand the valid\n * `source:` schema surface. If @stackwright-pro/openapi or @stackwright-pro/pulse\n * are installed and expose an adapter registry, their sources are enumerated here.\n *\n * This is a pure filesystem/module-resolution operation — no network, no side effects.\n * It is safe to call at build time (no running server required).\n *\n * Returns an empty sources array if no providers are installed, which causes the\n * compiler to emit a warning (not an error) when a `source:` reference is encountered.\n */\nexport function scanDataSources(): DataSourceScanResult {\n const sources: DataSourceDescriptor[] = [];\n const detectedProviders: string[] = [];\n\n // Try @stackwright-pro/openapi\n try {\n require.resolve('@stackwright-pro/openapi/datasource-adapter');\n detectedProviders.push('@stackwright-pro/openapi');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/openapi/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/openapi sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/openapi not installed\n }\n\n // Try @stackwright-pro/pulse\n try {\n require.resolve('@stackwright-pro/pulse/datasource-adapter');\n detectedProviders.push('@stackwright-pro/pulse');\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@stackwright-pro/pulse/datasource-adapter') as {\n listDataSources?: () => DataSourceDescriptor[];\n };\n if (typeof mod.listDataSources === 'function') {\n sources.push(...mod.listDataSources());\n }\n } catch (err) {\n console.warn(\n 'stackwright-services:datasource Failed to enumerate @stackwright-pro/pulse sources:',\n err,\n );\n }\n } catch {\n // @stackwright-pro/pulse not installed\n }\n\n return { sources, detectedProviders };\n}\n","/**\n * Core prebuild registration function.\n * Discovers and enumerates the complete services schema surface.\n */\nimport { CapabilityRegistry, registerAllCapabilities } from '@stackwright-services/capabilities';\nimport { scanDataSources } from '../datasource/scan';\nimport type {\n CapabilityDescriptor,\n DataSourceDescriptorEntry,\n PrebuildRegistration,\n TriggerTypeDescriptor,\n} from './types';\n\n// Read version from package.json at build time\nconst PACKAGE_VERSION = '0.0.1'; // Synced with package.json via sync-versions.mjs\n\n/**\n * Enumerate all known trigger types.\n * The trigger type set is closed and small per VISION.md.\n */\nfunction enumerateTriggers(): TriggerTypeDescriptor[] {\n return [\n {\n type: 'http',\n description:\n 'HTTP request/response trigger — becomes API Gateway route (Lambda) or Ingress (k8s)',\n inputSchema: {\n type: 'object',\n properties: {\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] },\n path: { type: 'string', pattern: '^/' },\n input_schema: { type: 'string' },\n },\n required: ['method', 'path'],\n },\n example: {\n type: 'http',\n method: 'POST',\n path: '/api/patients/at-risk',\n input_schema: 'AtRiskRequest',\n },\n },\n {\n type: 'event',\n description: 'Pub/sub event trigger — subscribes to a message bus topic',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^bus:' },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'event',\n source: 'bus:equipment-status',\n input_schema: 'EquipmentStatusEvent',\n },\n },\n {\n type: 'schedule',\n description: 'Cron-style scheduled trigger — periodic invocation',\n inputSchema: {\n type: 'object',\n properties: {\n cron: { type: 'string' },\n input_schema: { type: 'string' },\n },\n required: ['cron'],\n },\n example: { type: 'schedule', cron: '0 */6 * * *', input_schema: 'ScheduledCheckInput' },\n },\n {\n type: 'queue',\n description: 'Durable point-to-point queue trigger — processes messages sequentially',\n inputSchema: {\n type: 'object',\n properties: {\n source: { type: 'string', pattern: '^queue:' },\n batch_size: { type: 'number', minimum: 1, maximum: 10 },\n input_schema: { type: 'string' },\n },\n required: ['source'],\n },\n example: {\n type: 'queue',\n source: 'queue:approvals',\n batch_size: 1,\n input_schema: 'ApprovalMessage',\n },\n },\n ];\n}\n\n/**\n * Walk the capability registry and extract descriptors.\n */\nfunction enumerateCapabilities(): CapabilityDescriptor[] {\n const registry = new CapabilityRegistry();\n registerAllCapabilities(registry);\n\n return registry.listAll().map((cap) => {\n const descriptor: CapabilityDescriptor = {\n name: cap.definition.name,\n kind: cap.definition.kind,\n description: cap.definition.description,\n inputSchema: cap.definition.inputSchema,\n outputSchema: cap.definition.outputSchema,\n };\n\n if (cap.definition.kind === 'effect') {\n descriptor.requiredPermissions = cap.definition.requiredPermissions;\n }\n\n return descriptor;\n });\n}\n\n/**\n * Discover installed data sources.\n * Maps from runtime's DataSourceDescriptor (transport field) to prebuild's\n * DataSourceDescriptorEntry (provider field).\n */\nfunction enumerateDataSources(): DataSourceDescriptorEntry[] {\n const scanResult = scanDataSources();\n return scanResult.sources.map((source) => ({\n id: source.id,\n provider: source.transport,\n operations: source.operations,\n }));\n}\n\n/**\n * Main prebuild registration function.\n * Called by @stackwright/scaffold-core at prebuild time.\n *\n * This is safe to call at build time — no running server required,\n * no network calls, no side effects beyond module resolution for data source scanning.\n */\nexport function registerServices(): PrebuildRegistration {\n return {\n pluginId: '@stackwright-services/runtime',\n version: PACKAGE_VERSION,\n triggers: enumerateTriggers(),\n capabilities: enumerateCapabilities(),\n dataSources: enumerateDataSources(),\n registeredAt: new Date().toISOString(),\n };\n}\n"],"mappings":"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","names":["createLogger","createLogger","createLogger","SqsSnsMessageBusProvider","LOG_PREFIX","LOG_PREFIX","listDataSources","LOG_PREFIX"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackwright-services/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "restricted"
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"hono": "^4",
|
|
29
29
|
"zod": "^3.24",
|
|
30
|
-
"@stackwright-services/capabilities": "0.
|
|
31
|
-
"@stackwright-services/types": "0.
|
|
30
|
+
"@stackwright-services/capabilities": "0.4.0",
|
|
31
|
+
"@stackwright-services/types": "0.4.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@aws-sdk/client-sns": "^3.0.0",
|