"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runConfig = void 0;
const tslib_1 = require("tslib");
const vm_1 = (0, tslib_1.__importDefault)(require("vm"));
const resolve_1 = require("../resolve");
const async_cache_1 = (0, tslib_1.__importDefault)(require("../utils/async-cache"));
const error_1 = require("../utils/error");
const rootModule = '@refloat/boot.js';
async function runConfig(path, configSource, checkout, fetch, configCtx, overrides) {
    const config = {
        source: configSource,
        linux: '{}',
        macos: '{}',
        windows: '{}',
    };
    const dependencies = new Set();
    const paths = new WeakMap();
    const checkouts = new async_cache_1.default(checkout);
    const sources = new async_cache_1.default(async (source) => {
        const dep = (0, resolve_1.parse)(source);
        await checkouts.get(`${dep.scheme}://${dep.host}/${dep.owner}/${dep.repo}${dep.ref ? `#${dep.ref}` : ''}`);
        return fetch(source);
    });
    await Promise.all(Array.from(['linux', 'macos', 'windows']).map(async (platform) => {
        var _a, _b;
        const context = vm_1.default.createContext({}, { codeGeneration: { strings: false, wasm: false } });
        const modules = new async_cache_1.default(async (sourceIdentifier) => {
            const source = getSource(sourceIdentifier, overrides);
            const code = source === path ? configSource : await sources.get(source);
            const module = new vm_1.default.SourceTextModule(code, {
                context,
                identifier: source,
            });
            if (source !== path) {
                dependencies.add(source);
            }
            for (const specifier of module.dependencySpecifiers) {
                if (!specifier.startsWith('@refloat/')) {
                    modules.preload((0, resolve_1.resolve)(source, specifier));
                }
            }
            paths.set(module, source);
            return module;
        });
        const module = new vm_1.default.SourceTextModule(`
						import { jobs } from ${JSON.stringify(path)}

						export const json = JSON.stringify({ jobs })
					`, { context, identifier: rootModule });
        paths.set(module, rootModule);
        try {
            await module.link((specifier, referrer) => {
                var _a;
                const path = (0, resolve_1.resolve)((_a = paths.get(referrer)) !== null && _a !== void 0 ? _a : (0, error_1.error)('Failed to find VM referrer path'), specifier);
                return path === '@refloat/context'
                    ? new vm_1.default.SourceTextModule(createContext(configCtx, platform), {
                        context,
                        identifier: path,
                    })
                    : modules.get(path);
            });
            await module.evaluate();
        }
        catch (error) {
            throw new Error(String((_b = (_a = error === null || error === void 0 ? void 0 : error.stack) !== null && _a !== void 0 ? _a : error) !== null && _b !== void 0 ? _b : 'Unexpected error')
                .replace(/at SourceTextModule\.evaluate(.|\s)*/, '')
                .trimEnd());
        }
        const { json } = module.namespace;
        config[platform] =
            typeof json === 'string'
                ? json
                : (0, error_1.error)(`Unexpected VM script result type: "${typeof json}"`);
    }));
    return {
        config,
        dependencies: Array.from(dependencies),
    };
}
exports.runConfig = runConfig;
const getSource = (path, overrides) => {
    for (const key of Object.keys(overrides)) {
        if (path === key || path.startsWith(key + '/')) {
            return path.replace(key, overrides[key]);
        }
    }
    return path;
};
const createContext = (context, platform) => `
	export const platform = ${JSON.stringify(platform)}
	export const {build, repo, org, commit, user} = ${JSON.stringify(context)}
`;
//# sourceMappingURL=run.js.map