"use strict";
/**********************************************************************
 * Copyright (c) 2021 Red Hat, Inc.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 ***********************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateTypescriptReferencesFor = exports.updateAssemblyTsConfigFile = exports.updateRootTsConfigFile = void 0;
const fs = require("fs-extra");
const path = require("path");
const EXCLUDED_REFERENCES = ['examples/api-samples', 'examples/browser', 'examples/electron', 'packages/git'];
/**
 * Update root tsconfig.json file
 */
async function updateRootTsConfigFile(rootFolder) {
    const excludedReferences = EXCLUDED_REFERENCES.map(excluded => path.resolve(rootFolder, excluded));
    return updateTsConfigFile(rootFolder, ['examples/assembly'], excludedReferences);
}
exports.updateRootTsConfigFile = updateRootTsConfigFile;
/**
 * Update /theia/examples/assembly tsconfig.json file
 */
async function updateAssemblyTsConfigFile(rootFolder, assemblyFolder) {
    // get theia references
    const theiaReferencesFilePath = path.join(__dirname, '../src', 'templates', 'theia-references.json');
    const theiaReferencesRawData = await fs.readFile(theiaReferencesFilePath);
    const theiaReferencesParsedData = JSON.parse(theiaReferencesRawData.toString());
    const theiaReferences = theiaReferencesParsedData['references'];
    // filter references
    const excludedReferences = EXCLUDED_REFERENCES.map(excluded => path.resolve(rootFolder, excluded));
    const verifiedTheiaReferences = await verifyReferencies(rootFolder, theiaReferences, excludedReferences);
    // get theia references as relative
    const preparedTheiaReferences = verifiedTheiaReferences.map(reference => {
        const absolutePath = path.resolve(rootFolder, reference.path);
        const relativePath = path.posix.relative(assemblyFolder, absolutePath);
        return { path: relativePath };
    });
    // get assembly references
    const assemblyTsConfigPath = path.join(assemblyFolder, 'tsconfig.json');
    const assemblyTsConfigRawData = await fs.readFile(assemblyTsConfigPath);
    const assemblyTsConfigParsedData = JSON.parse(assemblyTsConfigRawData.toString());
    const assemblyReferences = assemblyTsConfigParsedData['references'];
    // get assembly references as relative
    const preparedAssemblyReferences = assemblyReferences.map(reference => {
        const absolutePath = path.resolve(assemblyFolder, reference.path);
        const relativePath = path.posix.relative(fs.realpathSync(assemblyFolder), fs.realpathSync(absolutePath));
        return { path: relativePath };
    });
    // concat references
    const newData = preparedTheiaReferences.concat(preparedAssemblyReferences);
    assemblyTsConfigParsedData['references'] = newData;
    // write the result back to config file
    const newContent = JSON.stringify(assemblyTsConfigParsedData, undefined, 2);
    await fs.writeFile(assemblyTsConfigPath, newContent);
}
exports.updateAssemblyTsConfigFile = updateAssemblyTsConfigFile;
async function updateTypescriptReferencesFor(packagePath, dependencies, yarnWorkspaces) {
    const tsReferencies = await getTypescriptReferences(packagePath, dependencies, yarnWorkspaces);
    await updateTsConfigFile(packagePath, tsReferencies, []);
}
exports.updateTypescriptReferencesFor = updateTypescriptReferencesFor;
async function getTypescriptReferences(packagePath, dependencies, yarnWorkspaces) {
    const references = await Promise.all(dependencies.map(async (dependencyName) => {
        const dependency = yarnWorkspaces.get(dependencyName);
        if (!dependency) {
            return undefined;
        }
        const dependencyTsConfigPath = path.join(fs.realpathSync(dependency.location), 'tsconfig.json');
        // we consider only dependencies with tsconfig to apply incremental build
        if (!(await fs.pathExists(dependencyTsConfigPath))) {
            return undefined;
        }
        return path.posix.relative(fs.realpathSync(packagePath), fs.realpathSync(dependency.location));
    }));
    return references.filter(reference => reference !== undefined);
}
async function updateTsConfigFile(packagePath, expectedReferences, excludedReferences) {
    const tsConfigPath = path.join(packagePath, 'tsconfig.json');
    if (!(await fs.pathExists(tsConfigPath))) {
        return;
    }
    const tsConfigRawData = await fs.readFile(tsConfigPath);
    const tsConfigParsedData = JSON.parse(tsConfigRawData.toString());
    const compilerOptions = tsConfigParsedData.compilerOptions;
    if (!compilerOptions.composite) {
        tsConfigParsedData.compilerOptions = Object.assign({ composite: true }, compilerOptions);
    }
    const tsConfigReferences = tsConfigParsedData.references || [];
    const references = tsConfigReferences.concat(expectedReferences.map(reference => ({
        path: reference,
    })));
    tsConfigParsedData.references =
        excludedReferences.length > 0
            ? await verifyReferencies(packagePath, references, excludedReferences)
            : references;
    const newContent = JSON.stringify(tsConfigParsedData, undefined, 2);
    await fs.writeFile(tsConfigPath, newContent);
}
async function verifyReferencies(tsConfigFolder, referencies, excludedReferences) {
    const result = await Promise.all(referencies.map(async (reference) => {
        const tsConfigPath = path.resolve(tsConfigFolder, reference.path);
        if (excludedReferences.includes(tsConfigPath) || !(await fs.pathExists(tsConfigPath))) {
            return undefined;
        }
        return reference;
    }));
    return result.filter(reference => reference !== undefined);
}
//# sourceMappingURL=resolve-tsconfigs.js.map