"use strict";
/**
 * Event-Driven Workflow Schema
 * Defines strict types and validation rules for event-driven system architecture
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventDrivenWorkflowSchema = void 0;
const zod_1 = require("zod");
/**
 * Event Definition Schema
 * Events are system-wide communication contracts
 */
const EventDefinitionSchema = zod_1.z.object({
    description: zod_1.z.string().min(1),
    payload: zod_1.z.record(zod_1.z.string(), zod_1.z.enum(['string', 'number', 'boolean', 'array', 'object'])),
});
/**
 * Component Schema
 * Components are logical parts of the system that emit/consume events
 */
const ComponentSchema = zod_1.z.object({
    description: zod_1.z.string().min(1),
    emits: zod_1.z.array(zod_1.z.string()).default([]),
    consumes: zod_1.z.array(zod_1.z.string()).default([]),
});
/**
 * Actor Schema
 * Actors perform workflows (humans or systems)
 */
const ActorSchema = zod_1.z.object({
    type: zod_1.z.enum(['human', 'system']),
    name: zod_1.z.string().min(1),
    description: zod_1.z.string().min(1),
});
/**
 * Workflow Step Schema
 * Individual steps within a workflow
 */
const WorkflowStepSchema = zod_1.z.object({
    id: zod_1.z.string().min(1),
    action: zod_1.z.string().min(1),
    component: zod_1.z.string().min(1), // Must reference a defined component
    emits: zod_1.z.string().optional(), // Must reference a defined event
    consumes: zod_1.z.string().optional(), // Must reference a defined event
    depends_on: zod_1.z.array(zod_1.z.string()).optional(),
    choices: zod_1.z.array(zod_1.z.string()).optional(), // For branching (e.g., payment methods)
    on_success: zod_1.z.string().optional(),
    on_failure: zod_1.z.string().optional(),
});
/**
 * Workflow Schema
 * Step-by-step processes that actors perform
 */
const WorkflowSchema = zod_1.z.object({
    actor: zod_1.z.string().min(1), // Must reference a defined actor
    description: zod_1.z.string().min(1),
    steps: zod_1.z.array(WorkflowStepSchema).min(1),
});
/**
 * Service Configuration Schema
 * Concrete service implementations
 */
const ServiceConfigSchema = zod_1.z.object({
    type: zod_1.z.string().min(1), // e.g., payment_processor, oms, email_provider
    config: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
    // Context-based usage (optional)
    use_for: zod_1.z.array(zod_1.z.string()).optional(), // e.g., ["signup", "admin_login"], or ["*"] for all contexts
    fallback: zod_1.z.boolean().default(false), // Use as fallback if primary fails
});
/**
 * Stack Schema
 * Maps abstract components to concrete services
 */
const StackComponentSchema = zod_1.z.object({
    services: zod_1.z.record(zod_1.z.string(), ServiceConfigSchema).refine((services) => Object.keys(services).length > 0, {
        message: "At least one service must be defined"
    }),
    primary: zod_1.z.string().optional(), // Primary/default service to use (service name)
    routing: zod_1.z.enum(['primary_only', 'context_based', 'load_balanced']).default('primary_only'),
});
/**
 * Action Schema
 * Specific tasks that can be performed
 */
const ActionSchema = zod_1.z.object({
    description: zod_1.z.string().min(1),
    component: zod_1.z.string().min(1), // Must reference a defined component
    emits: zod_1.z.string().optional(), // Must reference a defined event
    consumes: zod_1.z.string().optional(), // Must reference a defined event
    inputs: zod_1.z.array(zod_1.z.record(zod_1.z.string(), zod_1.z.string())).optional(),
});
/**
 * Service Configuration Schema
 * For configuring additional infrastructure services
 */
const ServiceInstanceSchema = zod_1.z.object({
    provider: zod_1.z.string().min(1), // e.g., "redis", "elasticache", "upstash"
    connection: zod_1.z.string().min(1), // Connection string or config
    config: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
});
/**
 * Worker Configuration Schema
 * For background job processing
 */
const WorkerConfigSchema = zod_1.z.object({
    enabled: zod_1.z.boolean().default(true),
    concurrency: zod_1.z.number().default(1),
    queues: zod_1.z.array(zod_1.z.string()).default(['default']),
    config: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
});
/**
 * Stage Infrastructure Schema
 * Multi-domain, multi-database, multi-service infrastructure
 */
const StageInfrastructureSchema = zod_1.z.object({
    // Multiple domains (web app, API, docs, admin panel, etc.)
    domains: zod_1.z.object({
        web: zod_1.z.string().optional(), // Main web application
        api: zod_1.z.string().optional(), // API endpoint
        docs: zod_1.z.string().optional(), // Documentation site
        portal: zod_1.z.string().optional(), // Customer/partner portal
        admin: zod_1.z.string().optional(), // Admin panel
        marketing: zod_1.z.string().optional(), // Marketing site
        custom: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(), // Additional custom domains
    }).optional(),
    // Multiple databases (primary, analytics, cache, etc.)
    databases: zod_1.z.object({
        primary: zod_1.z.string(), // Main application database (REQUIRED)
        analytics: zod_1.z.string().optional(), // Analytics/reporting database
        cache: zod_1.z.string().optional(), // Cache database (Redis, etc.)
        custom: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(), // Additional databases
    }),
    // Additional infrastructure services
    services: zod_1.z.object({
        redis: ServiceInstanceSchema.optional(), // Cache, session store
        queue: ServiceInstanceSchema.optional(), // Job queue (Bull, BullMQ, etc.)
        storage: ServiceInstanceSchema.optional(), // Object storage (S3, R2, etc.)
        search: ServiceInstanceSchema.optional(), // Search engine (Elasticsearch, Algolia, etc.)
        email: ServiceInstanceSchema.optional(), // Email service (SendGrid, SES, etc.)
        cdn: ServiceInstanceSchema.optional(), // CDN (CloudFront, Cloudflare, etc.)
        monitoring: ServiceInstanceSchema.optional(), // Monitoring (DataDog, Sentry, etc.)
        custom: zod_1.z.record(zod_1.z.string(), ServiceInstanceSchema).optional(), // Additional services
    }).optional(),
    // Background workers
    workers: WorkerConfigSchema.optional(),
});
/**
 * Stage Configuration Schema
 * Smart defaults with override capability
 */
const StageConfigSchema = zod_1.z.object({
    log_level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default('info'),
    development_tools: zod_1.z.boolean().optional(), // Override development tools enablement
    error_details: zod_1.z.boolean().default(false), // Show detailed errors (default false for security)
    cors: zod_1.z.object({
        enabled: zod_1.z.boolean().default(true),
        origins: zod_1.z.array(zod_1.z.string()).optional(), // Allowed origins
    }).optional(),
    rate_limiting: zod_1.z.object({
        enabled: zod_1.z.boolean().default(true),
        requests_per_minute: zod_1.z.number().default(100),
    }).optional(),
    custom: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(), // Additional custom config
});
/**
 * Stage Schema
 * Environment configurations with full infrastructure support
 */
const StageSchema = zod_1.z.object({
    description: zod_1.z.string().optional(),
    infrastructure: StageInfrastructureSchema,
    config: StageConfigSchema.optional(),
    env: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(), // Environment variables
});
/**
 * Main Event-Driven Workflow Schema
 */
exports.EventDrivenWorkflowSchema = zod_1.z.object({
    workflow: zod_1.z.object({
        id: zod_1.z.string().min(1),
        version: zod_1.z.string().min(1),
        name: zod_1.z.string().min(1),
        description: zod_1.z.string().min(1),
    }),
    // Events: System-wide event definitions (must be defined before use)
    events: zod_1.z.record(zod_1.z.string(), EventDefinitionSchema),
    // Actors: Who/what performs workflows
    actors: zod_1.z.record(zod_1.z.string(), ActorSchema),
    // Components: Logical parts that emit/consume events
    components: zod_1.z.record(zod_1.z.string(), ComponentSchema),
    // Workflows: Step-by-step processes
    workflows: zod_1.z.record(zod_1.z.string(), WorkflowSchema),
    // Stack: Maps components to services
    stack: zod_1.z.record(zod_1.z.string(), StackComponentSchema),
    // Actions: Reusable tasks (optional)
    actions: zod_1.z.record(zod_1.z.string(), ActionSchema).optional(),
    // Stages: Environment configs (optional)
    stages: zod_1.z.record(zod_1.z.string(), StageSchema).optional(),
}).superRefine((data, ctx) => {
    // Custom validation: Ensure referential integrity
    // Collect all defined event names
    const definedEvents = new Set(Object.keys(data.events));
    // Collect all defined component names
    const definedComponents = new Set(Object.keys(data.components));
    // Collect all defined actor names
    const definedActors = new Set(Object.keys(data.actors));
    // Validate components emit/consume only defined events
    Object.entries(data.components).forEach(([componentName, component]) => {
        component.emits.forEach((event) => {
            if (!definedEvents.has(event)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Component '${componentName}' emits undefined event '${event}'. Event must be defined in 'events' section.`,
                    path: ['components', componentName, 'emits'],
                });
            }
        });
        component.consumes.forEach((event) => {
            if (!definedEvents.has(event)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Component '${componentName}' consumes undefined event '${event}'. Event must be defined in 'events' section.`,
                    path: ['components', componentName, 'consumes'],
                });
            }
        });
    });
    // Validate workflows reference defined actors and components
    Object.entries(data.workflows).forEach(([workflowName, workflow]) => {
        if (!definedActors.has(workflow.actor)) {
            ctx.addIssue({
                code: zod_1.z.ZodIssueCode.custom,
                message: `Workflow '${workflowName}' references undefined actor '${workflow.actor}'. Actor must be defined in 'actors' section.`,
                path: ['workflows', workflowName, 'actor'],
            });
        }
        workflow.steps.forEach((step, index) => {
            if (!definedComponents.has(step.component)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Workflow '${workflowName}' step '${step.id}' references undefined component '${step.component}'. Component must be defined in 'components' section.`,
                    path: ['workflows', workflowName, 'steps', index, 'component'],
                });
            }
            if (step.emits && !definedEvents.has(step.emits)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Workflow '${workflowName}' step '${step.id}' emits undefined event '${step.emits}'. Event must be defined in 'events' section.`,
                    path: ['workflows', workflowName, 'steps', index, 'emits'],
                });
            }
            if (step.consumes && !definedEvents.has(step.consumes)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Workflow '${workflowName}' step '${step.id}' consumes undefined event '${step.consumes}'. Event must be defined in 'events' section.`,
                    path: ['workflows', workflowName, 'steps', index, 'consumes'],
                });
            }
        });
    });
    // Validate stack maps to defined components
    Object.keys(data.stack).forEach((componentName) => {
        if (!definedComponents.has(componentName)) {
            ctx.addIssue({
                code: zod_1.z.ZodIssueCode.custom,
                message: `Stack defines services for undefined component '${componentName}'. Component must be defined in 'components' section.`,
                path: ['stack', componentName],
            });
        }
    });
    // Validate actions reference defined components and events
    if (data.actions) {
        Object.entries(data.actions).forEach(([actionName, action]) => {
            if (!definedComponents.has(action.component)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Action '${actionName}' references undefined component '${action.component}'. Component must be defined in 'components' section.`,
                    path: ['actions', actionName, 'component'],
                });
            }
            if (action.emits && !definedEvents.has(action.emits)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Action '${actionName}' emits undefined event '${action.emits}'. Event must be defined in 'events' section.`,
                    path: ['actions', actionName, 'emits'],
                });
            }
            if (action.consumes && !definedEvents.has(action.consumes)) {
                ctx.addIssue({
                    code: zod_1.z.ZodIssueCode.custom,
                    message: `Action '${actionName}' consumes undefined event '${action.consumes}'. Event must be defined in 'events' section.`,
                    path: ['actions', actionName, 'consumes'],
                });
            }
        });
    }
    // Validate event flow: ensure emitted events are consumed somewhere
    const emittedEvents = new Set();
    const consumedEvents = new Set();
    Object.values(data.components).forEach((component) => {
        component.emits.forEach((event) => emittedEvents.add(event));
        component.consumes.forEach((event) => consumedEvents.add(event));
    });
    // Warn if events are emitted but never consumed
    emittedEvents.forEach((event) => {
        if (!consumedEvents.has(event)) {
            ctx.addIssue({
                code: zod_1.z.ZodIssueCode.custom,
                message: `Event '${event}' is emitted but never consumed by any component. This may indicate a missing consumer.`,
                path: ['events', event],
            });
        }
    });
    // Warn if events are consumed but never emitted
    consumedEvents.forEach((event) => {
        if (!emittedEvents.has(event)) {
            ctx.addIssue({
                code: zod_1.z.ZodIssueCode.custom,
                message: `Event '${event}' is consumed but never emitted by any component. This may indicate a missing emitter.`,
                path: ['events', event],
            });
        }
    });
});
//# sourceMappingURL=event-driven-schema.js.map