"use strict";
// Copyright 2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultErrorRedactor = exports.GaxiosError = void 0;
const url_1 = require("url");
/* eslint-disable @typescript-eslint/no-explicit-any */
class GaxiosError extends Error {
    constructor(message, config, response, error) {
        super(message);
        this.config = config;
        this.response = response;
        this.error = error;
        if (this.response) {
            try {
                this.response.data = translateData(config.responseType, response === null || response === void 0 ? void 0 : response.data);
            }
            catch (_a) {
                // best effort - don't throw an error within an error
                // we could set `this.response.config.responseType = 'unknown'`, but
                // that would mutate future calls with this config object.
            }
            this.status = this.response.status;
        }
        if (error && 'code' in error && error.code) {
            this.code = error.code;
        }
        if (config.errorRedactor) {
            const errorRedactor = (config.errorRedactor);
            // shallow-copy config for redaction as we do not want
            // future requests to have redacted information
            this.config = { ...config };
            if (this.response) {
                // copy response's config, as it may be recursively redacted
                this.response = { ...this.response, config: { ...this.response.config } };
            }
            const results = errorRedactor({ config, response });
            this.config = { ...config, ...results.config };
            if (this.response) {
                this.response = { ...this.response, ...results.response, config };
            }
        }
    }
}
exports.GaxiosError = GaxiosError;
function translateData(responseType, data) {
    switch (responseType) {
        case 'stream':
            return data;
        case 'json':
            return JSON.parse(JSON.stringify(data));
        case 'arraybuffer':
            return JSON.parse(Buffer.from(data).toString('utf8'));
        case 'blob':
            return JSON.parse(data.text());
        default:
            return data;
    }
}
/**
 * An experimental error redactor.
 *
 * @param config Config to potentially redact properties of
 * @param response Config to potentially redact properties of
 *
 * @experimental
 */
function defaultErrorRedactor(data) {
    const REDACT = '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.';
    function redactHeaders(headers) {
        if (!headers)
            return;
        for (const key of Object.keys(headers)) {
            // any casing of `Authentication`
            if (/^authentication$/.test(key)) {
                headers[key] = REDACT;
            }
        }
    }
    function redactString(obj, key) {
        if (typeof obj === 'object' &&
            obj !== null &&
            typeof obj[key] === 'string') {
            const text = obj[key];
            if (/grant_type=/.test(text) || /assertion=/.test(text)) {
                obj[key] = REDACT;
            }
        }
    }
    function redactObject(obj) {
        if (typeof obj === 'object' && obj !== null) {
            if ('grant_type' in obj) {
                obj['grant_type'] = REDACT;
            }
            if ('assertion' in obj) {
                obj['assertion'] = REDACT;
            }
        }
    }
    if (data.config) {
        redactHeaders(data.config.headers);
        redactString(data.config, 'data');
        redactObject(data.config.data);
        redactString(data.config, 'body');
        redactObject(data.config.body);
        try {
            const url = new url_1.URL(data.config.url || '');
            if (url.searchParams.has('token')) {
                url.searchParams.set('token', REDACT);
            }
            data.config.url = url.toString();
        }
        catch (_a) {
            // ignore error - no need to parse an invalid URL
        }
    }
    if (data.response) {
        defaultErrorRedactor({ config: data.response.config });
        redactHeaders(data.response.headers);
        redactString(data.response, 'data');
        redactObject(data.response.data);
    }
    return data;
}
exports.defaultErrorRedactor = defaultErrorRedactor;
//# sourceMappingURL=common.js.map