import { ResponseError } from '../lib/errors.js';
import { BaseAPI, JSONApiResponse, } from '../lib/runtime.js';
import { addClientAuthentication, } from './client-authentication.js';
import { TelemetryMiddleware } from '../lib/middleware/telemetry-middleware.js';
export class AuthApiError extends Error {
    constructor(error, error_description, statusCode, body, headers) {
        super(error_description || error);
        this.error = error;
        this.error_description = error_description;
        this.statusCode = statusCode;
        this.body = body;
        this.headers = headers;
        this.name = 'AuthApiError';
    }
}
function parseErrorBody(body) {
    const rawData = JSON.parse(body);
    let data;
    if (rawData.error) {
        data = rawData;
    }
    else {
        data = {
            error: rawData.code,
            error_description: rawData.description,
        };
    }
    return data;
}
async function parseError(response) {
    // Errors typically have a specific format:
    // {
    //    error: 'invalid_body',
    //    error_description: 'Bad Request',
    // }
    const body = await response.text();
    try {
        const data = parseErrorBody(body);
        return new AuthApiError(data.error, data.error_description, response.status, body, response.headers);
    }
    catch (_) {
        return new ResponseError(response.status, body, response.headers, 'Response returned an error code');
    }
}
export class BaseAuthAPI extends BaseAPI {
    constructor(options) {
        super({
            ...options,
            baseUrl: `https://${options.domain}`,
            middleware: options.telemetry !== false ? [new TelemetryMiddleware(options)] : [],
            parseError,
            retry: { enabled: false, ...options.retry },
        });
        this.domain = options.domain;
        this.clientId = options.clientId;
        this.clientSecret = options.clientSecret;
        this.clientAssertionSigningKey = options.clientAssertionSigningKey;
        this.clientAssertionSigningAlg = options.clientAssertionSigningAlg;
    }
    /**
     * @private
     */
    async addClientAuthentication(payload) {
        return addClientAuthentication({
            payload,
            domain: this.domain,
            clientId: this.clientId,
            clientSecret: this.clientSecret,
            clientAssertionSigningKey: this.clientAssertionSigningKey,
            clientAssertionSigningAlg: this.clientAssertionSigningAlg,
        });
    }
}
/**
 * @private
 * Perform an OAuth 2.0 grant.
 */
export async function grant(grantType, bodyParameters, { idTokenValidateOptions, initOverrides } = {}, clientId, idTokenValidator, request) {
    const response = await request({
        path: '/oauth/token',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            client_id: clientId,
            ...bodyParameters,
            grant_type: grantType,
        }),
    }, initOverrides);
    const res = await JSONApiResponse.fromResponse(response);
    if (res.data.id_token) {
        await idTokenValidator.validate(res.data.id_token, idTokenValidateOptions);
    }
    return res;
}
//# sourceMappingURL=base-auth-api.js.map