"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommonVersionsConfiguration = void 0;
const node_crypto_1 = __importDefault(require("node:crypto"));
const path = __importStar(require("node:path"));
const node_core_library_1 = require("@rushstack/node-core-library");
const PackageNameParsers_1 = require("./PackageNameParsers");
const JsonSchemaUrls_1 = require("../logic/JsonSchemaUrls");
const RushConstants_1 = require("../logic/RushConstants");
const common_versions_schema_json_1 = __importDefault(require("../schemas/common-versions.schema.json"));
/**
 * Use this class to load and save the "common/config/rush/common-versions.json" config file.
 * This config file stores dependency version information that affects all projects in the repo.
 * @public
 */
class CommonVersionsConfiguration {
    constructor(commonVersionsJson, filePath, rushConfiguration) {
        var _a;
        this._modified = false;
        this._preferredVersions = new node_core_library_1.ProtectableMap({
            onSet: this._onSetPreferredVersions.bind(this)
        });
        this.preferredVersions = this._preferredVersions.protectedView;
        if (commonVersionsJson && commonVersionsJson.implicitlyPreferredVersions !== undefined) {
            this.implicitlyPreferredVersions = commonVersionsJson.implicitlyPreferredVersions;
        }
        else {
            this.implicitlyPreferredVersions = undefined;
        }
        this._allowedAlternativeVersions = new node_core_library_1.ProtectableMap({
            onSet: this._onSetAllowedAlternativeVersions.bind(this)
        });
        this.allowedAlternativeVersions = this._allowedAlternativeVersions.protectedView;
        const subspacesFeatureEnabled = rushConfiguration === null || rushConfiguration === void 0 ? void 0 : rushConfiguration.subspacesFeatureEnabled;
        const rushJsonEnsureConsistentVersions = rushConfiguration === null || rushConfiguration === void 0 ? void 0 : rushConfiguration._ensureConsistentVersionsJsonValue;
        const commonVersionsEnsureConsistentVersions = commonVersionsJson === null || commonVersionsJson === void 0 ? void 0 : commonVersionsJson.ensureConsistentVersions;
        if (subspacesFeatureEnabled && rushJsonEnsureConsistentVersions !== undefined) {
            throw new Error(`When using subspaces, the ensureConsistentVersions config is now defined in the ${RushConstants_1.RushConstants.commonVersionsFilename} file, ` +
                `you must remove the old setting "ensureConsistentVersions" from ${RushConstants_1.RushConstants.rushJsonFilename}`);
        }
        else if (!subspacesFeatureEnabled &&
            rushJsonEnsureConsistentVersions !== undefined &&
            commonVersionsEnsureConsistentVersions !== undefined) {
            throw new Error(`When the ensureConsistentVersions config is defined in the ${RushConstants_1.RushConstants.rushJsonFilename} file, ` +
                `it cannot also be defined in the ${RushConstants_1.RushConstants.commonVersionsFilename} file`);
        }
        this.ensureConsistentVersions =
            (_a = commonVersionsEnsureConsistentVersions !== null && commonVersionsEnsureConsistentVersions !== void 0 ? commonVersionsEnsureConsistentVersions : rushJsonEnsureConsistentVersions) !== null && _a !== void 0 ? _a : false;
        this._commonVersionsJsonHasEnsureConsistentVersionsProperty =
            commonVersionsEnsureConsistentVersions !== undefined;
        if (commonVersionsJson) {
            try {
                CommonVersionsConfiguration._deserializeTable(this.preferredVersions, commonVersionsJson.preferredVersions);
                CommonVersionsConfiguration._deserializeTable(this.allowedAlternativeVersions, commonVersionsJson.allowedAlternativeVersions);
            }
            catch (e) {
                throw new Error(`Error loading "${path.basename(filePath)}": ${e.message}`);
            }
        }
        this.filePath = filePath;
    }
    /**
     * Loads the common-versions.json data from the specified file path.
     * If the file has not been created yet, then an empty object is returned.
     */
    static loadFromFile(jsonFilePath, rushConfiguration) {
        let commonVersionsJson = undefined;
        if (node_core_library_1.FileSystem.exists(jsonFilePath)) {
            commonVersionsJson = node_core_library_1.JsonFile.loadAndValidate(jsonFilePath, CommonVersionsConfiguration._jsonSchema);
        }
        return new CommonVersionsConfiguration(commonVersionsJson, jsonFilePath, rushConfiguration);
    }
    static _deserializeTable(map, object) {
        if (object) {
            for (const [key, value] of Object.entries(object)) {
                map.set(key, value);
            }
        }
    }
    static _serializeTable(map) {
        const table = {};
        const keys = [...map.keys()];
        keys.sort();
        for (const key of keys) {
            table[key] = map.get(key);
        }
        return table;
    }
    /**
     * Get a sha1 hash of the preferred versions.
     */
    getPreferredVersionsHash() {
        // Sort so that the hash is stable
        const orderedPreferredVersions = new Map(this._preferredVersions.protectedView);
        node_core_library_1.Sort.sortMapKeys(orderedPreferredVersions);
        // JSON.stringify does not support maps, so we need to convert to an object first
        const preferredVersionsObj = node_core_library_1.MapExtensions.toObject(orderedPreferredVersions);
        return node_crypto_1.default.createHash('sha1').update(JSON.stringify(preferredVersionsObj)).digest('hex');
    }
    /**
     * Writes the "common-versions.json" file to disk, using the filename that was passed to loadFromFile().
     */
    save() {
        if (this._modified) {
            node_core_library_1.JsonFile.save(this._serialize(), this.filePath, {
                updateExistingFile: true,
                ignoreUndefinedValues: true
            });
            this._modified = false;
            return true;
        }
        return false;
    }
    /**
     * Returns preferredVersions.
     */
    getAllPreferredVersions() {
        const allPreferredVersions = new Map();
        node_core_library_1.MapExtensions.mergeFromMap(allPreferredVersions, this.preferredVersions);
        return allPreferredVersions;
    }
    _onSetPreferredVersions(source, key, value) {
        PackageNameParsers_1.PackageNameParsers.permissive.validate(key);
        this._modified = true;
        return value;
    }
    _onSetAllowedAlternativeVersions(source, key, value) {
        PackageNameParsers_1.PackageNameParsers.permissive.validate(key);
        this._modified = true;
        return value;
    }
    _serialize() {
        let preferredVersions;
        if (this._preferredVersions.size) {
            preferredVersions = CommonVersionsConfiguration._serializeTable(this.preferredVersions);
        }
        let allowedAlternativeVersions;
        if (this._allowedAlternativeVersions.size) {
            allowedAlternativeVersions = CommonVersionsConfiguration._serializeTable(this.allowedAlternativeVersions);
        }
        const result = {
            $schema: JsonSchemaUrls_1.JsonSchemaUrls.commonVersions,
            preferredVersions,
            implicitlyPreferredVersions: this.implicitlyPreferredVersions,
            allowedAlternativeVersions,
            ensureConsistentVersions: this._commonVersionsJsonHasEnsureConsistentVersionsProperty
                ? this.ensureConsistentVersions
                : undefined
        };
        return result;
    }
}
exports.CommonVersionsConfiguration = CommonVersionsConfiguration;
CommonVersionsConfiguration._jsonSchema = node_core_library_1.JsonSchema.fromLoadedObject(common_versions_schema_json_1.default);
//# sourceMappingURL=CommonVersionsConfiguration.js.map