/**
 * Base export target interface and abstract class
 *
 * Defines the contract for serverless export targets and provides
 * shared utilities for generating deployment artifacts.
 */
import * as path from 'path';
import { getGeneratedBranding } from '../../generated-branding.js';
/**
 * Base export target with shared utilities
 */
export class BaseExportTarget {
    /**
     * Generate a standard package.json
     */
    generatePackageJson(options) {
        const pkg = {
            name: `fw-${options.name}`,
            version: '1.0.0',
            description: options.description || `Flow Weaver workflow: ${options.name}`,
            type: 'module',
            main: options.main || 'index.js',
            scripts: options.scripts || {},
            dependencies: options.dependencies || {},
            devDependencies: {
                typescript: '^5.0.0',
                ...options.devDependencies,
            },
        };
        return JSON.stringify(pkg, null, 2);
    }
    /**
     * Generate a standard tsconfig.json
     */
    generateTsConfig(options = {}) {
        const config = {
            compilerOptions: {
                target: 'ES2022',
                module: options.module || 'NodeNext',
                moduleResolution: options.moduleResolution || 'NodeNext',
                outDir: options.outDir || './dist',
                strict: true,
                esModuleInterop: true,
                skipLibCheck: true,
                ...(options.types && { types: options.types }),
            },
            include: ['**/*.ts'],
        };
        return JSON.stringify(config, null, 2);
    }
    /**
     * Create a file object
     */
    createFile(outputDir, relativePath, content, type) {
        return {
            relativePath,
            absolutePath: path.join(outputDir, relativePath),
            content,
            type,
        };
    }
    /**
     * Generate content files for workflows and node types in a bundle.
     * Creates files under workflows/ and node-types/ subdirectories.
     */
    generateBundleContentFiles(workflows, nodeTypes, outputDir, workflowDir = 'workflows', nodeTypeDir = 'node-types') {
        const files = [];
        for (const w of workflows) {
            if (w.code) {
                files.push(this.createFile(outputDir, `${workflowDir}/${w.name}.ts`, w.code, 'workflow'));
            }
        }
        for (const nt of nodeTypes) {
            if (nt.code) {
                // Use lowercase functionName for file naming to ensure consistency with import paths
                // and avoid case-sensitivity issues on case-insensitive filesystems (macOS, Windows)
                files.push(this.createFile(outputDir, `${nodeTypeDir}/${nt.functionName.toLowerCase()}.ts`, nt.code, 'nodeType'));
            }
        }
        return files;
    }
    /**
     * Generate content files for compiled workflows.
     * Creates files under the workflows/ subdirectory.
     */
    generateWorkflowContentFiles(workflows, outputDir, workflowDir = 'workflows') {
        const files = [];
        for (const w of workflows) {
            if (w.code) {
                files.push(this.createFile(outputDir, `${workflowDir}/${w.name}.ts`, w.code, 'workflow'));
            }
        }
        return files;
    }
    /**
     * Generate content files for node types.
     * Creates files under the node-types/ subdirectory.
     */
    generateNodeTypeContentFiles(nodeTypes, outputDir, nodeTypeDir = 'node-types') {
        const files = [];
        for (const nt of nodeTypes) {
            if (nt.code) {
                // Use lowercase functionName for file naming to ensure consistency with import paths
                // and avoid case-sensitivity issues on case-insensitive filesystems
                files.push(this.createFile(outputDir, `${nodeTypeDir}/${nt.functionName.toLowerCase()}.ts`, nt.code, 'nodeType'));
            }
        }
        return files;
    }
    /**
     * Get relative import path for the workflow
     */
    getWorkflowImport(workflowFile) {
        const basename = path.basename(workflowFile, path.extname(workflowFile));
        return `./${basename}.js`;
    }
    /**
     * Generate OpenAPI spec for node types as HTTP endpoints
     */
    generateNodeTypeOpenAPI(nodeTypes, options) {
        const paths = {};
        for (const nodeType of nodeTypes) {
            // Build request schema from inputs
            const inputProperties = {};
            const requiredInputs = [];
            for (const [portName, portDef] of Object.entries(nodeType.inputs)) {
                // Skip control flow ports (execute)
                if (portDef.dataType === 'STEP')
                    continue;
                inputProperties[portName] = {
                    type: this.mapDataTypeToJsonSchema(portDef.dataType || 'any'),
                    description: portDef.label || portName,
                    ...(portDef.tsType && { 'x-ts-type': portDef.tsType }),
                };
                if (!portDef.optional) {
                    requiredInputs.push(portName);
                }
            }
            // Build response schema from outputs
            const outputProperties = {};
            for (const [portName, portDef] of Object.entries(nodeType.outputs)) {
                // Skip control flow ports (onSuccess, onFailure)
                if (portDef.dataType === 'STEP')
                    continue;
                outputProperties[portName] = {
                    type: this.mapDataTypeToJsonSchema(portDef.dataType || 'any'),
                    description: portDef.label || portName,
                    ...(portDef.tsType && { 'x-ts-type': portDef.tsType }),
                };
            }
            paths[`/api/${nodeType.name}`] = {
                post: {
                    operationId: `execute_${nodeType.functionName}`,
                    summary: `Execute ${nodeType.name}`,
                    description: nodeType.description || `Execute the ${nodeType.name} node type function`,
                    tags: ['node-types'],
                    requestBody: {
                        description: 'Node type input parameters',
                        required: true,
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'object',
                                    properties: inputProperties,
                                    required: requiredInputs.length > 0 ? requiredInputs : undefined,
                                },
                            },
                        },
                    },
                    responses: {
                        '200': {
                            description: 'Successful execution',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            success: { type: 'boolean' },
                                            result: {
                                                type: 'object',
                                                properties: outputProperties,
                                            },
                                            executionTime: { type: 'number' },
                                            requestId: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                        '404': {
                            description: 'Node type not found',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            error: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                        '500': {
                            description: 'Execution error',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            success: { type: 'boolean' },
                                            error: { type: 'string' },
                                            requestId: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };
        }
        // Add OpenAPI spec endpoint
        paths['/api/openapi.json'] = {
            get: {
                operationId: 'get_openapi',
                summary: 'OpenAPI Specification',
                description: 'Returns this OpenAPI 3.0 specification',
                tags: ['documentation'],
                responses: {
                    '200': {
                        description: 'OpenAPI specification',
                        content: {
                            'application/json': {},
                        },
                    },
                },
            },
        };
        return {
            openapi: '3.0.3',
            info: {
                title: options.title,
                version: options.version,
                description: `Node type service with ${nodeTypes.length} endpoints`,
            },
            servers: [{ url: options.baseUrl || '/', description: 'Current deployment' }],
            paths,
            tags: [
                { name: 'node-types', description: 'Node type execution endpoints' },
                { name: 'documentation', description: 'API documentation' },
            ],
        };
    }
    /**
     * Map Flow Weaver data types to JSON Schema types
     */
    mapDataTypeToJsonSchema(dataType) {
        const typeMap = {
            STRING: 'string',
            NUMBER: 'number',
            BOOLEAN: 'boolean',
            OBJECT: 'object',
            ARRAY: 'array',
            ANY: 'any',
            FUNCTION: 'object',
            STEP: 'boolean',
        };
        return typeMap[dataType] || 'any';
    }
    /**
     * Generate consolidated OpenAPI spec for multiple workflows
     */
    generateConsolidatedOpenAPI(workflows, options) {
        const paths = {};
        for (const workflow of workflows) {
            paths[`/api/${workflow.name}`] = {
                post: {
                    operationId: `execute_${workflow.functionName}`,
                    summary: `Execute ${workflow.name} workflow`,
                    description: workflow.description || `Execute the ${workflow.name} workflow`,
                    tags: ['workflows'],
                    requestBody: {
                        description: 'Workflow input parameters',
                        required: true,
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'object',
                                    description: 'Workflow-specific parameters. Function parameters can be registry IDs.',
                                    additionalProperties: true,
                                },
                            },
                        },
                    },
                    responses: {
                        '200': {
                            description: 'Successful workflow execution',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            success: { type: 'boolean' },
                                            result: { type: 'object' },
                                            executionTime: { type: 'number' },
                                            requestId: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                        '404': {
                            description: 'Workflow not found',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            error: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                        '500': {
                            description: 'Execution error',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: {
                                            success: { type: 'boolean' },
                                            error: { type: 'string' },
                                            requestId: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };
        }
        // Add /api/functions endpoint
        paths['/api/functions'] = {
            get: {
                operationId: 'list_functions',
                summary: 'List available functions',
                description: 'Returns all registered functions that can be used as parameters',
                tags: ['functions'],
                parameters: [
                    {
                        name: 'category',
                        in: 'query',
                        required: false,
                        schema: {
                            type: 'string',
                            enum: ['transform', 'filter', 'validate', 'format', 'custom'],
                        },
                        description: 'Filter by function category',
                    },
                ],
                responses: {
                    '200': {
                        description: 'List of registered functions',
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'array',
                                    items: {
                                        type: 'object',
                                        properties: {
                                            id: { type: 'string', example: 'string:uppercase' },
                                            name: { type: 'string' },
                                            description: { type: 'string' },
                                            category: {
                                                type: 'string',
                                                enum: ['transform', 'filter', 'validate', 'format', 'custom'],
                                            },
                                            inputType: { type: 'string' },
                                            outputType: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            },
        };
        // Add OpenAPI spec endpoint
        paths['/api/openapi.json'] = {
            get: {
                operationId: 'get_openapi',
                summary: 'OpenAPI Specification',
                description: 'Returns this OpenAPI 3.0 specification',
                tags: ['documentation'],
                responses: {
                    '200': {
                        description: 'OpenAPI specification',
                        content: {
                            'application/json': {},
                        },
                    },
                },
            },
        };
        return {
            openapi: '3.0.3',
            info: {
                title: options.title,
                version: options.version,
                description: `Multi-workflow service with ${workflows.length} workflows`,
            },
            servers: [{ url: options.baseUrl || '/', description: 'Current deployment' }],
            paths,
            tags: [
                { name: 'workflows', description: 'Workflow execution endpoints' },
                { name: 'functions', description: 'Function registry endpoints' },
                { name: 'documentation', description: 'API documentation' },
            ],
            components: {
                schemas: {
                    FunctionReference: {
                        oneOf: [
                            {
                                type: 'string',
                                description: 'Registry function ID (e.g., "string:uppercase")',
                            },
                            {
                                type: 'object',
                                properties: {
                                    registryId: {
                                        type: 'string',
                                        description: 'Registry function ID',
                                    },
                                    partialArgs: {
                                        type: 'object',
                                        description: 'Pre-bound arguments',
                                        additionalProperties: true,
                                    },
                                },
                                required: ['registryId'],
                            },
                        ],
                        description: 'Function parameter - can be a registry ID or object with partial arguments',
                    },
                },
            },
        };
    }
    /**
     * Generate OpenAPI spec for a unified bundle of workflows and node types.
     * Only includes exposed items as HTTP endpoints.
     */
    generateBundleOpenAPI(workflows, nodeTypes, options) {
        const paths = {};
        const tags = [];
        // Add exposed workflows
        const exposedWorkflows = workflows.filter((w) => w.expose);
        if (exposedWorkflows.length > 0) {
            tags.push({ name: 'workflows', description: 'Workflow execution endpoints' });
            for (const workflow of exposedWorkflows) {
                paths[`/api/workflows/${workflow.name}`] = {
                    post: {
                        operationId: `execute_workflow_${workflow.functionName}`,
                        summary: `Execute ${workflow.name} workflow`,
                        description: workflow.description || `Execute the ${workflow.name} workflow`,
                        tags: ['workflows'],
                        requestBody: {
                            description: 'Workflow input parameters',
                            required: true,
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        description: 'Workflow-specific parameters',
                                        additionalProperties: true,
                                    },
                                },
                            },
                        },
                        responses: {
                            '200': {
                                description: 'Successful workflow execution',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: {
                                                success: { type: 'boolean' },
                                                result: { type: 'object' },
                                                executionTime: { type: 'number' },
                                                requestId: { type: 'string' },
                                            },
                                        },
                                    },
                                },
                            },
                            '404': {
                                description: 'Workflow not found',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: { error: { type: 'string' } },
                                        },
                                    },
                                },
                            },
                            '500': {
                                description: 'Execution error',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: {
                                                success: { type: 'boolean' },
                                                error: { type: 'string' },
                                                requestId: { type: 'string' },
                                            },
                                        },
                                    },
                                },
                            },
                        },
                    },
                };
            }
        }
        // Add exposed node types
        const exposedNodeTypes = nodeTypes.filter((nt) => nt.expose);
        if (exposedNodeTypes.length > 0) {
            tags.push({ name: 'node-types', description: 'Node type execution endpoints' });
            for (const nodeType of exposedNodeTypes) {
                // Build request schema from inputs
                const inputProperties = {};
                const requiredInputs = [];
                for (const [portName, portDef] of Object.entries(nodeType.inputs)) {
                    // Skip control flow ports (execute)
                    if (portDef.dataType === 'STEP')
                        continue;
                    inputProperties[portName] = {
                        type: this.mapDataTypeToJsonSchema(portDef.dataType || 'any'),
                        description: portDef.label || portName,
                        ...(portDef.tsType && { 'x-ts-type': portDef.tsType }),
                    };
                    if (!portDef.optional) {
                        requiredInputs.push(portName);
                    }
                }
                // Build response schema from outputs
                const outputProperties = {};
                for (const [portName, portDef] of Object.entries(nodeType.outputs)) {
                    // Skip control flow ports
                    if (portDef.dataType === 'STEP')
                        continue;
                    outputProperties[portName] = {
                        type: this.mapDataTypeToJsonSchema(portDef.dataType || 'any'),
                        description: portDef.label || portName,
                        ...(portDef.tsType && { 'x-ts-type': portDef.tsType }),
                    };
                }
                paths[`/api/nodes/${nodeType.name}`] = {
                    post: {
                        operationId: `execute_node_${nodeType.functionName}`,
                        summary: `Execute ${nodeType.name}`,
                        description: nodeType.description || `Execute the ${nodeType.name} node type function`,
                        tags: ['node-types'],
                        requestBody: {
                            description: 'Node type input parameters',
                            required: true,
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: inputProperties,
                                        required: requiredInputs.length > 0 ? requiredInputs : undefined,
                                    },
                                },
                            },
                        },
                        responses: {
                            '200': {
                                description: 'Successful execution',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: {
                                                success: { type: 'boolean' },
                                                result: {
                                                    type: 'object',
                                                    properties: outputProperties,
                                                },
                                                executionTime: { type: 'number' },
                                                requestId: { type: 'string' },
                                            },
                                        },
                                    },
                                },
                            },
                            '404': {
                                description: 'Node type not found',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: { error: { type: 'string' } },
                                        },
                                    },
                                },
                            },
                            '500': {
                                description: 'Execution error',
                                content: {
                                    'application/json': {
                                        schema: {
                                            type: 'object',
                                            properties: {
                                                success: { type: 'boolean' },
                                                error: { type: 'string' },
                                                requestId: { type: 'string' },
                                            },
                                        },
                                    },
                                },
                            },
                        },
                    },
                };
            }
        }
        // Add function registry endpoint
        tags.push({ name: 'functions', description: 'Function registry endpoints' });
        paths['/api/functions'] = {
            get: {
                operationId: 'list_functions',
                summary: 'List available functions',
                description: 'Returns all registered functions that can be used as parameters',
                tags: ['functions'],
                parameters: [
                    {
                        name: 'category',
                        in: 'query',
                        required: false,
                        schema: {
                            type: 'string',
                            enum: ['transform', 'filter', 'validate', 'format', 'custom'],
                        },
                        description: 'Filter by function category',
                    },
                ],
                responses: {
                    '200': {
                        description: 'List of registered functions',
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'array',
                                    items: {
                                        type: 'object',
                                        properties: {
                                            id: { type: 'string' },
                                            name: { type: 'string' },
                                            description: { type: 'string' },
                                            category: { type: 'string' },
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            },
        };
        // Add OpenAPI spec endpoint
        tags.push({ name: 'documentation', description: 'API documentation' });
        paths['/api/openapi.json'] = {
            get: {
                operationId: 'get_openapi',
                summary: 'OpenAPI Specification',
                description: 'Returns this OpenAPI 3.0 specification',
                tags: ['documentation'],
                responses: {
                    '200': {
                        description: 'OpenAPI specification',
                        content: { 'application/json': {} },
                    },
                },
            },
        };
        // Build description
        const exposedCounts = [];
        if (exposedWorkflows.length > 0) {
            exposedCounts.push(`${exposedWorkflows.length} workflow${exposedWorkflows.length !== 1 ? 's' : ''}`);
        }
        if (exposedNodeTypes.length > 0) {
            exposedCounts.push(`${exposedNodeTypes.length} node type${exposedNodeTypes.length !== 1 ? 's' : ''}`);
        }
        return {
            openapi: '3.0.3',
            info: {
                title: options.title,
                version: options.version,
                description: `Bundle service with ${exposedCounts.join(' and ')} exposed`,
            },
            servers: [{ url: options.baseUrl || '/', description: 'Current deployment' }],
            paths,
            tags,
        };
    }
    /**
     * Generate a README.md from deploy instructions
     */
    generateReadme(instructions, workflowName, target) {
        const lines = [];
        lines.push(`# Deploy ${workflowName} to ${target}`);
        lines.push('');
        if (instructions.prerequisites.length > 0) {
            lines.push('## Prerequisites');
            lines.push('');
            instructions.prerequisites.forEach((p) => lines.push(`- ${p}`));
            lines.push('');
        }
        if (instructions.steps.length > 0) {
            lines.push('## Deployment Steps');
            lines.push('');
            instructions.steps.forEach((step, i) => {
                if (step.startsWith('  ')) {
                    // Indented sub-steps rendered as code
                    lines.push(`   \`${step.trim()}\``);
                }
                else {
                    lines.push(`${i + 1}. \`${step}\``);
                }
            });
            lines.push('');
        }
        if (instructions.localTestSteps && instructions.localTestSteps.length > 0) {
            lines.push('## Local Testing');
            lines.push('');
            lines.push('Test your deployment locally before pushing to production:');
            lines.push('');
            lines.push('```bash');
            instructions.localTestSteps.forEach((step) => lines.push(step));
            lines.push('```');
            lines.push('');
        }
        if (instructions.links && instructions.links.length > 0) {
            lines.push('## Useful Links');
            lines.push('');
            instructions.links.forEach((link) => lines.push(`- [${link.label}](${link.url})`));
            lines.push('');
        }
        lines.push('---');
        lines.push(getGeneratedBranding().markdown);
        lines.push('');
        return lines.join('\n');
    }
    /**
     * Generate real runtime files from the Flow Weaver runtime source.
     * Includes the function registry, builtin functions, and parameter resolver.
     * These replace the placeholder files that were previously generated.
     */
    generateRuntimeFiles(outputDir, workflows, nodeTypes) {
        const files = [];
        // Generate function registry with workflow/nodeType metadata
        files.push(this.createFile(outputDir, 'runtime/function-registry.ts', this.generateFunctionRegistryContent(workflows, nodeTypes), 'other'));
        // Generate builtin functions module
        files.push(this.createFile(outputDir, 'runtime/builtin-functions.ts', `// Builtin functions — auto-registers known functions\nimport './function-registry.js';\n`, 'other'));
        // Generate parameter resolver
        files.push(this.createFile(outputDir, 'runtime/parameter-resolver.ts', `// Parameter resolver\nexport function resolveFunction(param: unknown) { return typeof param === 'function' ? param : undefined; }\n`, 'other'));
        return files;
    }
    /**
     * Generate function registry content with workflow/nodeType metadata.
     * Used as fallback when real runtime source files aren't available.
     */
    generateFunctionRegistryContent(workflows, nodeTypes) {
        return `// Generated function registry
type FunctionInfo = {
  name: string;
  type: 'workflow' | 'nodeType';
  exposed: boolean;
};

const functions: FunctionInfo[] = [
${workflows.map((w) => `  { name: '${w.name}', type: 'workflow', exposed: ${w.expose} },`).join('\n')}
${nodeTypes.map((nt) => `  { name: '${nt.name}', type: 'nodeType', exposed: ${nt.expose} },`).join('\n')}
];

export const functionRegistry = {
  list(category?: 'workflow' | 'nodeType'): FunctionInfo[] {
    if (!category) return functions;
    return functions.filter((f) => f.type === category);
  },
  get(name: string): FunctionInfo | undefined {
    return functions.find((f) => f.name === name);
  },
};
`;
    }
}
/**
 * Registry of available export targets
 */
export class ExportTargetRegistry {
    factories = new Map();
    instances = new Map();
    /**
     * Register a target factory. The target is only instantiated on first use.
     * Also accepts a pre-instantiated target.
     */
    register(nameOrTarget, factory) {
        if (typeof nameOrTarget === 'string') {
            // New lazy factory API: register(name, factory)
            this.factories.set(nameOrTarget, factory);
        }
        else {
            // Legacy API: register(target) — wrap in factory
            const target = nameOrTarget;
            this.instances.set(target.name, target);
            this.factories.set(target.name, () => target);
        }
    }
    get(name) {
        if (!this.instances.has(name)) {
            const factory = this.factories.get(name);
            if (factory)
                this.instances.set(name, factory());
        }
        return this.instances.get(name);
    }
    getAll() {
        for (const [name, factory] of this.factories) {
            if (!this.instances.has(name))
                this.instances.set(name, factory());
        }
        return Array.from(this.instances.values());
    }
    getNames() {
        return Array.from(this.factories.keys());
    }
    /** Get deploy schemas from all registered targets (for validation/autocomplete) */
    getDeploySchemas() {
        const schemas = {};
        for (const target of this.getAll()) {
            if (target.deploySchema)
                schemas[target.name] = target.deploySchema;
        }
        return schemas;
    }
}
//# sourceMappingURL=base.js.map