"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SimpleSteps = exports.SimpleStepsBuilder = exports.SimpleStepsCompileError = exports.compileVirtualWorkflow = exports.analyzeFreeVariables = exports.createSimpleStepsTransformer = exports.isTop = exports.isBottom = exports.isConstant = exports.meet = exports.bottom = exports.constant = exports.top = exports.analyzeHelperFunctions = exports.isEligibleForInlining = exports.ModuleEnvironment = exports.ExpressionEvaluator = exports.WholeProgramAnalyzer = exports.VariableResolutionBuilder = exports.extractResourceArn = exports.resolveExpression = exports.resolveVariables = exports.StepVariableType = exports.JsonataDialect = exports.JsonPathDialect = exports.JSONATA_DIALECT = exports.JSON_PATH_DIALECT = exports.buildChoiceRule = exports.buildParameters = exports.buildStateMachine = exports.deriveStateMachineName = exports.generateStateMachine = exports.buildCFG = exports.CallNodeType = exports.CallGraphNode = exports.AslValidator = exports.AslSerializer = exports.AslParser = void 0;
exports.compile = compile;
exports.compileFromProgram = compileFromProgram;
const typescript_1 = __importDefault(require("typescript"));
const compilerContext_js_1 = require("./compiler/compilerContext.js");
const diagnosticCodes_js_1 = require("./compiler/diagnosticCodes.js");
const intrinsics_js_1 = require("./compiler/discovery/intrinsics.js");
const callSiteLocator_js_1 = require("./compiler/discovery/callSiteLocator.js");
const callGraph_js_1 = require("./compiler/discovery/callGraph.js");
const serviceDiscovery_js_1 = require("./compiler/discovery/serviceDiscovery.js");
const index_js_1 = require("./compiler/cfg/index.js");
const index_js_2 = require("./compiler/analysis/index.js");
const index_js_3 = require("./compiler/generation/index.js");
const wholeProgramAnalyzer_js_1 = require("./compiler/analysis/wholeProgramAnalyzer.js");
var index_js_4 = require("./asl/index.js");
Object.defineProperty(exports, "AslParser", { enumerable: true, get: function () { return index_js_4.AslParser; } });
Object.defineProperty(exports, "AslSerializer", { enumerable: true, get: function () { return index_js_4.AslSerializer; } });
Object.defineProperty(exports, "AslValidator", { enumerable: true, get: function () { return index_js_4.AslValidator; } });
var index_js_5 = require("./compiler/discovery/index.js");
Object.defineProperty(exports, "CallGraphNode", { enumerable: true, get: function () { return index_js_5.CallGraphNode; } });
Object.defineProperty(exports, "CallNodeType", { enumerable: true, get: function () { return index_js_5.CallNodeType; } });
var index_js_6 = require("./compiler/cfg/index.js");
Object.defineProperty(exports, "buildCFG", { enumerable: true, get: function () { return index_js_6.buildCFG; } });
// Re-export generation types
var index_js_7 = require("./compiler/generation/index.js");
Object.defineProperty(exports, "generateStateMachine", { enumerable: true, get: function () { return index_js_7.generateStateMachine; } });
Object.defineProperty(exports, "deriveStateMachineName", { enumerable: true, get: function () { return index_js_7.deriveStateMachineName; } });
Object.defineProperty(exports, "buildStateMachine", { enumerable: true, get: function () { return index_js_7.buildStateMachine; } });
Object.defineProperty(exports, "buildParameters", { enumerable: true, get: function () { return index_js_7.buildParameters; } });
Object.defineProperty(exports, "buildChoiceRule", { enumerable: true, get: function () { return index_js_7.buildChoiceRule; } });
Object.defineProperty(exports, "JSON_PATH_DIALECT", { enumerable: true, get: function () { return index_js_7.JSON_PATH_DIALECT; } });
Object.defineProperty(exports, "JSONATA_DIALECT", { enumerable: true, get: function () { return index_js_7.JSONATA_DIALECT; } });
Object.defineProperty(exports, "JsonPathDialect", { enumerable: true, get: function () { return index_js_7.JsonPathDialect; } });
Object.defineProperty(exports, "JsonataDialect", { enumerable: true, get: function () { return index_js_7.JsonataDialect; } });
// Re-export analysis types
var index_js_8 = require("./compiler/analysis/index.js");
Object.defineProperty(exports, "StepVariableType", { enumerable: true, get: function () { return index_js_8.StepVariableType; } });
Object.defineProperty(exports, "resolveVariables", { enumerable: true, get: function () { return index_js_8.resolveVariables; } });
Object.defineProperty(exports, "resolveExpression", { enumerable: true, get: function () { return index_js_8.resolveExpression; } });
Object.defineProperty(exports, "extractResourceArn", { enumerable: true, get: function () { return index_js_8.extractResourceArn; } });
Object.defineProperty(exports, "VariableResolutionBuilder", { enumerable: true, get: function () { return index_js_8.VariableResolutionBuilder; } });
// Re-export whole-program analysis types
var index_js_9 = require("./compiler/analysis/index.js");
Object.defineProperty(exports, "WholeProgramAnalyzer", { enumerable: true, get: function () { return index_js_9.WholeProgramAnalyzer; } });
Object.defineProperty(exports, "ExpressionEvaluator", { enumerable: true, get: function () { return index_js_9.ExpressionEvaluator; } });
Object.defineProperty(exports, "ModuleEnvironment", { enumerable: true, get: function () { return index_js_9.ModuleEnvironment; } });
Object.defineProperty(exports, "isEligibleForInlining", { enumerable: true, get: function () { return index_js_9.isEligibleForInlining; } });
Object.defineProperty(exports, "analyzeHelperFunctions", { enumerable: true, get: function () { return index_js_9.analyzeHelperFunctions; } });
Object.defineProperty(exports, "top", { enumerable: true, get: function () { return index_js_9.top; } });
Object.defineProperty(exports, "constant", { enumerable: true, get: function () { return index_js_9.constant; } });
Object.defineProperty(exports, "bottom", { enumerable: true, get: function () { return index_js_9.bottom; } });
Object.defineProperty(exports, "meet", { enumerable: true, get: function () { return index_js_9.meet; } });
Object.defineProperty(exports, "isConstant", { enumerable: true, get: function () { return index_js_9.isConstant; } });
Object.defineProperty(exports, "isBottom", { enumerable: true, get: function () { return index_js_9.isBottom; } });
Object.defineProperty(exports, "isTop", { enumerable: true, get: function () { return index_js_9.isTop; } });
// Re-export transformer
var index_js_10 = require("./transformer/index.js");
Object.defineProperty(exports, "createSimpleStepsTransformer", { enumerable: true, get: function () { return index_js_10.createSimpleStepsTransformer; } });
var dataFlow_js_1 = require("./transformer/dataFlow.js");
Object.defineProperty(exports, "analyzeFreeVariables", { enumerable: true, get: function () { return dataFlow_js_1.analyzeFreeVariables; } });
var virtualCompiler_js_1 = require("./transformer/virtualCompiler.js");
Object.defineProperty(exports, "compileVirtualWorkflow", { enumerable: true, get: function () { return virtualCompiler_js_1.compileVirtualWorkflow; } });
// ── Compile function ───────────────────────────────────────────────────
/**
 * Compile TypeScript source files to ASL state machine definitions.
 */
function compile(options) {
    const cwd = options.cwd ?? process.cwd();
    // Create ts.Program
    let program;
    if (options.sourceFiles && options.sourceFiles.length > 0) {
        const compilerOptions = {
            target: typescript_1.default.ScriptTarget.ES2022,
            module: typescript_1.default.ModuleKind.Node16,
            moduleResolution: typescript_1.default.ModuleResolutionKind.Node16,
            strict: true,
            esModuleInterop: true,
            experimentalDecorators: true,
            skipLibCheck: true,
        };
        program = typescript_1.default.createProgram([...options.sourceFiles], compilerOptions);
    }
    else if (options.tsconfigPath) {
        const configFile = typescript_1.default.readConfigFile(options.tsconfigPath, typescript_1.default.sys.readFile);
        if (configFile.error) {
            return {
                stateMachines: [],
                errors: [{
                        file: options.tsconfigPath,
                        line: 1,
                        column: 1,
                        message: typescript_1.default.flattenDiagnosticMessageText(configFile.error.messageText, '\n'),
                        severity: 'error',
                        code: diagnosticCodes_js_1.ErrorCodes.Config.InvalidConfig.code,
                    }],
            };
        }
        const parsed = typescript_1.default.parseJsonConfigFileContent(configFile.config, typescript_1.default.sys, cwd);
        const configErrors = parsed.errors.filter(e => e.category === typescript_1.default.DiagnosticCategory.Error);
        if (configErrors.length > 0) {
            return {
                stateMachines: [],
                errors: configErrors.map(err => ({
                    file: err.file?.fileName ?? options.tsconfigPath,
                    line: 1,
                    column: 1,
                    message: typescript_1.default.flattenDiagnosticMessageText(err.messageText, '\n'),
                    severity: 'error',
                    code: diagnosticCodes_js_1.ErrorCodes.Config.InvalidConfig.code,
                })),
            };
        }
        program = typescript_1.default.createProgram(parsed.fileNames, parsed.options);
    }
    else {
        return {
            stateMachines: [],
            errors: [{
                    file: '',
                    line: 0,
                    column: 0,
                    message: 'Either tsconfigPath or sourceFiles must be provided',
                    severity: 'error',
                    code: diagnosticCodes_js_1.ErrorCodes.Config.InvalidConfig.code,
                }],
        };
    }
    const context = new compilerContext_js_1.CompilerContext(program);
    // ── Stage 1: Load intrinsics + service registry ─────────────────────
    const intrinsics = (0, intrinsics_js_1.loadIntrinsics)(context);
    if (!intrinsics) {
        return {
            stateMachines: [],
            errors: [...context.diagnostics],
        };
    }
    const serviceRegistry = (0, serviceDiscovery_js_1.discoverServices)(context);
    // ── Stage 1b: Create whole-program analyzer ───────────────────────
    const analyzer = new wholeProgramAnalyzer_js_1.WholeProgramAnalyzer(context, serviceRegistry);
    // ── Stage 2: Find call sites (Steps.createFunction, @stepFunction) ──
    const allCallSites = [];
    for (const sourceFile of program.getSourceFiles()) {
        if (sourceFile.isDeclarationFile)
            continue;
        // Skip internal files (runtime, compiler infrastructure)
        if (sourceFile.fileName.includes('/runtime/'))
            continue;
        if (sourceFile.fileName.includes('/compiler/'))
            continue;
        const sites = (0, callSiteLocator_js_1.findCallSites)(context, intrinsics, sourceFile);
        allCallSites.push(...sites);
    }
    // ── Stage 3: Build call graphs ──────────────────────────────────────
    const callGraphs = [];
    for (const callSite of allCallSites) {
        const graph = (0, callGraph_js_1.createCallGraph)(context, callSite);
        callGraphs.push({ callSite, graph });
    }
    // Early return if there are errors from discovery stages
    if (context.hasErrors()) {
        return {
            stateMachines: [],
            errors: [...context.diagnostics],
        };
    }
    // ── Stage 3b: Analyze helper functions for inlining ────────────────────
    const helperRegistries = new Map();
    for (const { callSite, graph } of callGraphs) {
        const helpers = (0, index_js_2.analyzeHelperFunctions)(context, graph, callSite.file);
        if (helpers.size > 0) {
            helperRegistries.set(callSite, helpers);
        }
    }
    // ── Stage 4: Build control flow graphs ────────────────────────────────
    const compilationUnits = [];
    for (const { callSite, graph } of callGraphs) {
        const body = callSite.factoryFunction.factory.body;
        if (body && typescript_1.default.isBlock(body)) {
            const helpers = helperRegistries.get(callSite);
            const result = (0, index_js_1.buildCFG)(context, body, helpers);
            compilationUnits.push({ callSite, graph, cfg: result.cfg, inlineBindings: result.inlineBindings });
        }
    }
    // Early return if there are errors from CFG construction
    if (context.hasErrors()) {
        return {
            stateMachines: [],
            errors: [...context.diagnostics],
        };
    }
    // ── Stage 5: ASL generation ──────────────────────────────────────────
    const dialect = options.queryLanguage === 'JSONPath' ? index_js_3.JSON_PATH_DIALECT : index_js_3.JSONATA_DIALECT;
    const stateMachines = [];
    for (const { callSite, cfg, inlineBindings } of compilationUnits) {
        const definition = (0, index_js_3.generateStateMachine)(context, callSite, cfg, serviceRegistry, options.substitutions, analyzer, inlineBindings, dialect, options.timeoutSeconds, options.version, options.sourceMap);
        const name = (0, index_js_3.deriveStateMachineName)(callSite);
        // Collect service names used by this state machine
        const services = [];
        for (const state of Object.values(definition.States)) {
            if (state.Type === 'Task' && 'Resource' in state && state.Resource) {
                const resourceKey = typeof state.Resource === 'string'
                    ? state.Resource
                    : JSON.stringify(state.Resource);
                if (!services.includes(resourceKey)) {
                    services.push(resourceKey);
                }
            }
        }
        stateMachines.push({ name, source: callSite.file.fileName, definition, services });
    }
    return {
        stateMachines,
        errors: [...context.diagnostics],
    };
}
/**
 * Compile a pre-built ts.Program to ASL state machine definitions.
 *
 * This is the browser-friendly entry point. Unlike compile(), it does not
 * use Node-specific APIs (fs, path, __dirname, process.cwd).
 */
function compileFromProgram(options) {
    const { program, runtimePath, servicesDir } = options;
    const skipPatterns = options.skipPatterns ?? ['/runtime/', '/compiler/'];
    const context = new compilerContext_js_1.CompilerContext(program);
    // Stage 1: Load intrinsics + service registry
    const intrinsics = (0, intrinsics_js_1.loadIntrinsics)(context, runtimePath);
    if (!intrinsics) {
        return { stateMachines: [], errors: [...context.diagnostics] };
    }
    const serviceRegistry = (0, serviceDiscovery_js_1.discoverServices)(context, servicesDir);
    // Stage 1b: Create whole-program analyzer
    const analyzer2 = new wholeProgramAnalyzer_js_1.WholeProgramAnalyzer(context, serviceRegistry);
    // Stage 2: Find call sites
    const allCallSites = [];
    for (const sourceFile of program.getSourceFiles()) {
        if (sourceFile.isDeclarationFile)
            continue;
        if (skipPatterns.some(p => sourceFile.fileName.includes(p)))
            continue;
        const sites = (0, callSiteLocator_js_1.findCallSites)(context, intrinsics, sourceFile);
        allCallSites.push(...sites);
    }
    // Stage 3: Build call graphs
    const callGraphs = [];
    for (const callSite of allCallSites) {
        const graph = (0, callGraph_js_1.createCallGraph)(context, callSite);
        callGraphs.push({ callSite, graph });
    }
    if (context.hasErrors()) {
        return { stateMachines: [], errors: [...context.diagnostics] };
    }
    // Stage 3b: Analyze helper functions for inlining
    const helperRegistries2 = new Map();
    for (const { callSite, graph } of callGraphs) {
        const helpers = (0, index_js_2.analyzeHelperFunctions)(context, graph, callSite.file);
        if (helpers.size > 0) {
            helperRegistries2.set(callSite, helpers);
        }
    }
    // Stage 4: Build control flow graphs
    const compilationUnits = [];
    for (const { callSite, graph } of callGraphs) {
        const body = callSite.factoryFunction.factory.body;
        if (body && typescript_1.default.isBlock(body)) {
            const helpers = helperRegistries2.get(callSite);
            const result = (0, index_js_1.buildCFG)(context, body, helpers);
            compilationUnits.push({ callSite, graph, cfg: result.cfg, inlineBindings: result.inlineBindings });
        }
    }
    if (context.hasErrors()) {
        return { stateMachines: [], errors: [...context.diagnostics] };
    }
    // Stage 5: ASL generation
    const dialect2 = options.queryLanguage === 'JSONPath' ? index_js_3.JSON_PATH_DIALECT : index_js_3.JSONATA_DIALECT;
    const stateMachines = [];
    for (const { callSite, cfg, inlineBindings } of compilationUnits) {
        const definition = (0, index_js_3.generateStateMachine)(context, callSite, cfg, serviceRegistry, options.substitutions, analyzer2, inlineBindings, dialect2, options.timeoutSeconds, options.version, options.sourceMap);
        const name = (0, index_js_3.deriveStateMachineName)(callSite);
        const services = [];
        for (const state of Object.values(definition.States)) {
            if (state.Type === 'Task' && 'Resource' in state && state.Resource) {
                const resourceKey = typeof state.Resource === 'string'
                    ? state.Resource
                    : JSON.stringify(state.Resource);
                if (!services.includes(resourceKey)) {
                    services.push(resourceKey);
                }
            }
        }
        stateMachines.push({ name, source: callSite.file.fileName, definition, services });
    }
    return { stateMachines, errors: [...context.diagnostics] };
}
// ── Fluent API ─────────────────────────────────────────────────────────
/**
 * Thrown by SimpleStepsBuilder methods when compilation produces errors.
 */
class SimpleStepsCompileError extends Error {
    diagnostics;
    constructor(diagnostics) {
        const messages = diagnostics.map(d => `${d.file}:${d.line} - ${d.message}`);
        super(`SimpleSteps compilation failed:\n${messages.join('\n')}`);
        this.name = 'SimpleStepsCompileError';
        this.diagnostics = diagnostics;
    }
}
exports.SimpleStepsCompileError = SimpleStepsCompileError;
/**
 * Builder for extracting compiled state machines.
 */
class SimpleStepsBuilder {
    options;
    result = null;
    constructor(options) {
        this.options = options;
    }
    /**
     * Return a new builder with deploy-time substitutions merged in.
     * Keys are variable names from source; values are resource identifiers
     * (strings, CF intrinsic objects, CDK tokens, etc.).
     */
    withSubstitutions(substitutions) {
        return new SimpleStepsBuilder({
            ...this.options,
            substitutions: { ...this.options.substitutions, ...substitutions },
        });
    }
    getResult() {
        if (!this.result) {
            this.result = compile(this.options);
        }
        return this.result;
    }
    toStateMachine() {
        const result = this.getResult();
        if (result.errors.length > 0) {
            throw new SimpleStepsCompileError(result.errors);
        }
        if (result.stateMachines.length === 0) {
            throw new Error('No state machines found in the provided source files');
        }
        return result.stateMachines[0].definition;
    }
    toStateMachines() {
        const result = this.getResult();
        if (result.errors.length > 0) {
            throw new SimpleStepsCompileError(result.errors);
        }
        return result.stateMachines;
    }
    toResult() {
        return this.getResult();
    }
}
exports.SimpleStepsBuilder = SimpleStepsBuilder;
/**
 * Fluent API for compiling SimpleSteps definitions.
 */
class SimpleSteps {
    static fromFile(filePath) {
        return new SimpleStepsBuilder({ sourceFiles: [filePath] });
    }
    static fromProject(tsconfigPath) {
        return new SimpleStepsBuilder({ tsconfigPath });
    }
}
exports.SimpleSteps = SimpleSteps;
//# sourceMappingURL=index.js.map