// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { needs } from '@aws-crypto/material-management';
export function getClient(KMSClient, defaultConfig) {
    return function getKmsClient(region) {
        /* a KMS alias is supported.  These do not have a region
         * in this case, the Encryption SDK should find the default region
         * or the default region needs to be supplied to this function
         */
        const config = (region ? { ...defaultConfig, region } : { ...defaultConfig });
        const client = new KMSClient(config);
        /* Postcondition: A region must be configured.
         * The AWS SDK has a process for determining the default region.
         * A user can configure a default region by setting it in `defaultConfig`
         * But KMS requires a region to operate.
         */
        // @ts-ignore the V3 client has set the config to protected, reasonable, but I need to know...
        needs(client.config.region, 'A region is required');
        return client;
    };
}
export function limitRegions(regions, getClient) {
    /* Precondition: limitRegions requires that region be a string. */
    needs(regions.every((r) => !!r && typeof r === 'string'), 'Can only limit on region strings');
    return (region) => {
        if (!regions.includes(region))
            return false;
        return getClient(region);
    };
}
export function excludeRegions(regions, getClient) {
    /* Precondition: excludeRegions requires region be a string. */
    needs(regions.every((r) => !!r && typeof r === 'string'), 'Can only exclude on region strings');
    return (region) => {
        if (regions.includes(region))
            return false;
        return getClient(region);
    };
}
export function cacheClients(getClient) {
    const clientsCache = {};
    return (region) => {
        // Do not cache until KMS has been responded in the given region
        if (!Object.prototype.hasOwnProperty.call(clientsCache, region))
            return deferCache(clientsCache, region, getClient(region));
        return clientsCache[region];
    };
}
/* It is possible that a malicious user can attempt a local resource
 * DOS by sending ciphertext with a large number of spurious regions.
 * This will fill the cache with regions and exhaust resources.
 * To avoid this, a call succeeds in contacting KMS.
 * This does *not* mean that this call is successful,
 * only that the region is backed by a functional KMS service.
 */
export function deferCache(clientsCache, region, client) {
    /* Check for early return (Postcondition): No client, then I cache false and move on. */
    if (!client) {
        clientsCache[region] = false;
        return false;
    }
    const { encrypt, decrypt, generateDataKey } = client;
    return ['encrypt', 'decrypt', 'generateDataKey'].reduce(wrapOperation, client);
    /* Wrap each of the operations to cache the client on response */
    function wrapOperation(client, name) {
        const original = client[name];
        client[name] = async function wrappedOperation(args) {
            // @ts-ignore (there should be a TypeScript solution for this)
            const v2vsV3Response = original.call(client, args);
            const v2vsV3Promise = 'promise' in v2vsV3Response ? v2vsV3Response.promise() : v2vsV3Response;
            return v2vsV3Promise
                .then((response) => {
                clientsCache[region] = Object.assign(client, {
                    encrypt,
                    decrypt,
                    generateDataKey,
                });
                return response;
            })
                .catch(async (e) => {
                /* Errors from a KMS contact mean that the region is "live".
                 * As such the client can be cached because the problem is not with the client per se,
                 * but with the request made.
                 */
                if (e.$metadata && e.$metadata.httpStatusCode) {
                    clientsCache[region] = Object.assign(client, {
                        encrypt,
                        decrypt,
                        generateDataKey,
                    });
                }
                // The request was not successful
                return Promise.reject(e);
            });
        };
        return client;
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia21zX2NsaWVudF9zdXBwbGllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9rbXNfY2xpZW50X3N1cHBsaWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9FQUFvRTtBQUNwRSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGlDQUFpQyxDQUFBO0FBdUJ2RCxNQUFNLFVBQVUsU0FBUyxDQUN2QixTQUEyQyxFQUMzQyxhQUFzQjtJQUV0QixPQUFPLFNBQVMsWUFBWSxDQUFDLE1BQWM7UUFDekM7OztXQUdHO1FBQ0gsTUFBTSxNQUFNLEdBQUcsQ0FDYixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxhQUFhLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxhQUFhLEVBQUUsQ0FDbkQsQ0FBQTtRQUNYLE1BQU0sTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXBDOzs7O1dBSUc7UUFDSCw4RkFBOEY7UUFDOUYsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLHNCQUFzQixDQUFDLENBQUE7UUFDbkQsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDLENBQUE7QUFDSCxDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FDMUIsT0FBaUIsRUFDakIsU0FBb0M7SUFFcEMsa0VBQWtFO0lBQ2xFLEtBQUssQ0FDSCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxFQUNsRCxrQ0FBa0MsQ0FDbkMsQ0FBQTtJQUVELE9BQU8sQ0FBQyxNQUFjLEVBQUUsRUFBRTtRQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQTtRQUMzQyxPQUFPLFNBQVMsQ0FB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