// Type definitions for meilisearch
// Project: https://github.com/meilisearch/meilisearch-js
// Definitions by: qdequele <quentin@meilisearch.com> <https://github.com/meilisearch>
// Definitions: https://github.com/meilisearch/meilisearch-js
// TypeScript Version: ^3.8.3
/*
 * SEARCH PARAMETERS
 */
const MatchingStrategies = {
    ALL: 'all',
    LAST: 'last',
    FREQUENCY: 'frequency',
};
const ContentTypeEnum = {
    JSON: 'application/json',
    CSV: 'text/csv',
    NDJSON: 'application/x-ndjson',
};
/*
 ** TASKS
 */
const TaskStatus = {
    TASK_SUCCEEDED: 'succeeded',
    TASK_PROCESSING: 'processing',
    TASK_FAILED: 'failed',
    TASK_ENQUEUED: 'enqueued',
    TASK_CANCELED: 'canceled',
};
const TaskTypes = {
    DOCUMENTS_ADDITION_OR_UPDATE: 'documentAdditionOrUpdate',
    DOCUMENT_DELETION: 'documentDeletion',
    DUMP_CREATION: 'dumpCreation',
    INDEX_CREATION: 'indexCreation',
    INDEX_DELETION: 'indexDeletion',
    INDEXES_SWAP: 'indexSwap',
    INDEX_UPDATE: 'indexUpdate',
    SETTINGS_UPDATE: 'settingsUpdate',
    SNAPSHOT_CREATION: 'snapshotCreation',
    TASK_CANCELATION: 'taskCancelation',
    TASK_DELETION: 'taskDeletion',
};
const ErrorStatusCode = {
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_creation_failed */
    INDEX_CREATION_FAILED: 'index_creation_failed',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_index_uid */
    MISSING_INDEX_UID: 'missing_index_uid',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_already_exists */
    INDEX_ALREADY_EXISTS: 'index_already_exists',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_not_found */
    INDEX_NOT_FOUND: 'index_not_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_uid */
    INVALID_INDEX_UID: 'invalid_index_uid',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_not_accessible */
    INDEX_NOT_ACCESSIBLE: 'index_not_accessible',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_offset */
    INVALID_INDEX_OFFSET: 'invalid_index_offset',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_limit */
    INVALID_INDEX_LIMIT: 'invalid_index_limit',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_state */
    INVALID_STATE: 'invalid_state',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#primary_key_inference_failed */
    PRIMARY_KEY_INFERENCE_FAILED: 'primary_key_inference_failed',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_primary_key_already_exists */
    INDEX_PRIMARY_KEY_ALREADY_EXISTS: 'index_primary_key_already_exists',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_primary_key */
    INVALID_INDEX_PRIMARY_KEY: 'invalid_index_primary_key',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#max_fields_limit_exceeded */
    DOCUMENTS_FIELDS_LIMIT_REACHED: 'document_fields_limit_reached',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_id */
    MISSING_DOCUMENT_ID: 'missing_document_id',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_id */
    INVALID_DOCUMENT_ID: 'invalid_document_id',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_content_type */
    INVALID_CONTENT_TYPE: 'invalid_content_type',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_content_type */
    MISSING_CONTENT_TYPE: 'missing_content_type',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_fields */
    INVALID_DOCUMENT_FIELDS: 'invalid_document_fields',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_limit */
    INVALID_DOCUMENT_LIMIT: 'invalid_document_limit',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_offset */
    INVALID_DOCUMENT_OFFSET: 'invalid_document_offset',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_filter */
    INVALID_DOCUMENT_FILTER: 'invalid_document_filter',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_filter */
    MISSING_DOCUMENT_FILTER: 'missing_document_filter',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_vectors_field */
    INVALID_DOCUMENT_VECTORS_FIELD: 'invalid_document_vectors_field',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#payload_too_large */
    PAYLOAD_TOO_LARGE: 'payload_too_large',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_payload */
    MISSING_PAYLOAD: 'missing_payload',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#malformed_payload */
    MALFORMED_PAYLOAD: 'malformed_payload',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#no_space_left_on_device */
    NO_SPACE_LEFT_ON_DEVICE: 'no_space_left_on_device',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_store_file */
    INVALID_STORE_FILE: 'invalid_store_file',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_ranking_rules */
    INVALID_RANKING_RULES: 'missing_document_id',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_request */
    INVALID_REQUEST: 'invalid_request',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_geo_field */
    INVALID_DOCUMENT_GEO_FIELD: 'invalid_document_geo_field',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_q */
    INVALID_SEARCH_Q: 'invalid_search_q',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_offset */
    INVALID_SEARCH_OFFSET: 'invalid_search_offset',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_limit */
    INVALID_SEARCH_LIMIT: 'invalid_search_limit',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_page */
    INVALID_SEARCH_PAGE: 'invalid_search_page',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_hits_per_page */
    INVALID_SEARCH_HITS_PER_PAGE: 'invalid_search_hits_per_page',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_retrieve */
    INVALID_SEARCH_ATTRIBUTES_TO_RETRIEVE: 'invalid_search_attributes_to_retrieve',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_crop */
    INVALID_SEARCH_ATTRIBUTES_TO_CROP: 'invalid_search_attributes_to_crop',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_crop_length */
    INVALID_SEARCH_CROP_LENGTH: 'invalid_search_crop_length',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_highlight */
    INVALID_SEARCH_ATTRIBUTES_TO_HIGHLIGHT: 'invalid_search_attributes_to_highlight',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_show_matches_position */
    INVALID_SEARCH_SHOW_MATCHES_POSITION: 'invalid_search_show_matches_position',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_filter */
    INVALID_SEARCH_FILTER: 'invalid_search_filter',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_sort */
    INVALID_SEARCH_SORT: 'invalid_search_sort',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_facets */
    INVALID_SEARCH_FACETS: 'invalid_search_facets',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_highlight_pre_tag */
    INVALID_SEARCH_HIGHLIGHT_PRE_TAG: 'invalid_search_highlight_pre_tag',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_highlight_post_tag */
    INVALID_SEARCH_HIGHLIGHT_POST_TAG: 'invalid_search_highlight_post_tag',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_crop_marker */
    INVALID_SEARCH_CROP_MARKER: 'invalid_search_crop_marker',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_matching_strategy */
    INVALID_SEARCH_MATCHING_STRATEGY: 'invalid_search_matching_strategy',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_vector */
    INVALID_SEARCH_VECTOR: 'invalid_search_vector',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_search_on */
    INVALID_SEARCH_ATTRIBUTES_TO_SEARCH_ON: 'invalid_search_attributes_to_search_on',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#bad_request */
    BAD_REQUEST: 'bad_request',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#document_not_found */
    DOCUMENT_NOT_FOUND: 'document_not_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#internal */
    INTERNAL: 'internal',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key */
    INVALID_API_KEY: 'invalid_api_key',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_description */
    INVALID_API_KEY_DESCRIPTION: 'invalid_api_key_description',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_actions */
    INVALID_API_KEY_ACTIONS: 'invalid_api_key_actions',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_indexes */
    INVALID_API_KEY_INDEXES: 'invalid_api_key_indexes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_expires_at */
    INVALID_API_KEY_EXPIRES_AT: 'invalid_api_key_expires_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#api_key_not_found */
    API_KEY_NOT_FOUND: 'api_key_not_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_uid */
    IMMUTABLE_API_KEY_UID: 'immutable_api_key_uid',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_actions */
    IMMUTABLE_API_KEY_ACTIONS: 'immutable_api_key_actions',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_indexes */
    IMMUTABLE_API_KEY_INDEXES: 'immutable_api_key_indexes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_expires_at */
    IMMUTABLE_API_KEY_EXPIRES_AT: 'immutable_api_key_expires_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_created_at */
    IMMUTABLE_API_KEY_CREATED_AT: 'immutable_api_key_created_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_updated_at */
    IMMUTABLE_API_KEY_UPDATED_AT: 'immutable_api_key_updated_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_authorization_header */
    MISSING_AUTHORIZATION_HEADER: 'missing_authorization_header',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#unretrievable_document */
    UNRETRIEVABLE_DOCUMENT: 'unretrievable_document',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#database_size_limit_reached */
    MAX_DATABASE_SIZE_LIMIT_REACHED: 'database_size_limit_reached',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#task_not_found */
    TASK_NOT_FOUND: 'task_not_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#dump_process_failed */
    DUMP_PROCESS_FAILED: 'dump_process_failed',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#dump_not_found */
    DUMP_NOT_FOUND: 'dump_not_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_swap_duplicate_index_found */
    INVALID_SWAP_DUPLICATE_INDEX_FOUND: 'invalid_swap_duplicate_index_found',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_swap_indexes */
    INVALID_SWAP_INDEXES: 'invalid_swap_indexes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_swap_indexes */
    MISSING_SWAP_INDEXES: 'missing_swap_indexes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_master_key */
    MISSING_MASTER_KEY: 'missing_master_key',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_types */
    INVALID_TASK_TYPES: 'invalid_task_types',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_uids */
    INVALID_TASK_UIDS: 'invalid_task_uids',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_statuses */
    INVALID_TASK_STATUSES: 'invalid_task_statuses',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_limit */
    INVALID_TASK_LIMIT: 'invalid_task_limit',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_from */
    INVALID_TASK_FROM: 'invalid_task_from',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_canceled_by */
    INVALID_TASK_CANCELED_BY: 'invalid_task_canceled_by',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_task_filters */
    MISSING_TASK_FILTERS: 'missing_task_filters',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#too_many_open_files */
    TOO_MANY_OPEN_FILES: 'too_many_open_files',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#io_error */
    IO_ERROR: 'io_error',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_index_uids */
    INVALID_TASK_INDEX_UIDS: 'invalid_task_index_uids',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_uid */
    IMMUTABLE_INDEX_UID: 'immutable_index_uid',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_created_at */
    IMMUTABLE_INDEX_CREATED_AT: 'immutable_index_created_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_updated_at */
    IMMUTABLE_INDEX_UPDATED_AT: 'immutable_index_updated_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_displayed_attributes */
    INVALID_SETTINGS_DISPLAYED_ATTRIBUTES: 'invalid_settings_displayed_attributes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_searchable_attributes */
    INVALID_SETTINGS_SEARCHABLE_ATTRIBUTES: 'invalid_settings_searchable_attributes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_filterable_attributes */
    INVALID_SETTINGS_FILTERABLE_ATTRIBUTES: 'invalid_settings_filterable_attributes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_sortable_attributes */
    INVALID_SETTINGS_SORTABLE_ATTRIBUTES: 'invalid_settings_sortable_attributes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_ranking_rules */
    INVALID_SETTINGS_RANKING_RULES: 'invalid_settings_ranking_rules',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_stop_words */
    INVALID_SETTINGS_STOP_WORDS: 'invalid_settings_stop_words',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_synonyms */
    INVALID_SETTINGS_SYNONYMS: 'invalid_settings_synonyms',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_distinct_attribute */
    INVALID_SETTINGS_DISTINCT_ATTRIBUTE: 'invalid_settings_distinct_attribute',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_typo_tolerance */
    INVALID_SETTINGS_TYPO_TOLERANCE: 'invalid_settings_typo_tolerance',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_faceting */
    INVALID_SETTINGS_FACETING: 'invalid_settings_faceting',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_pagination */
    INVALID_SETTINGS_PAGINATION: 'invalid_settings_pagination',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_search_cutoff_ms */
    INVALID_SETTINGS_SEARCH_CUTOFF_MS: 'invalid_settings_search_cutoff_ms',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_enqueued_at */
    INVALID_TASK_BEFORE_ENQUEUED_AT: 'invalid_task_before_enqueued_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_enqueued_at */
    INVALID_TASK_AFTER_ENQUEUED_AT: 'invalid_task_after_enqueued_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_started_at */
    INVALID_TASK_BEFORE_STARTED_AT: 'invalid_task_before_started_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_started_at */
    INVALID_TASK_AFTER_STARTED_AT: 'invalid_task_after_started_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_finished_at */
    INVALID_TASK_BEFORE_FINISHED_AT: 'invalid_task_before_finished_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_finished_at */
    INVALID_TASK_AFTER_FINISHED_AT: 'invalid_task_after_finished_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_actions */
    MISSING_API_KEY_ACTIONS: 'missing_api_key_actions',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_indexes */
    MISSING_API_KEY_INDEXES: 'missing_api_key_indexes',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_expires_at */
    MISSING_API_KEY_EXPIRES_AT: 'missing_api_key_expires_at',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_limit */
    INVALID_API_KEY_LIMIT: 'invalid_api_key_limit',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_offset */
    INVALID_API_KEY_OFFSET: 'invalid_api_key_offset',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_name */
    INVALID_FACET_SEARCH_FACET_NAME: 'invalid_facet_search_facet_name',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_facet_search_facet_name */
    MISSING_FACET_SEARCH_FACET_NAME: 'missing_facet_search_facet_name',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_query */
    INVALID_FACET_SEARCH_FACET_QUERY: 'invalid_facet_search_facet_query',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_ranking_score_threshold */
    INVALID_SEARCH_RANKING_SCORE_THRESHOLD: 'invalid_search_ranking_score_threshold',
    /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_similar_ranking_score_threshold */
    INVALID_SIMILAR_RANKING_SCORE_THRESHOLD: 'invalid_similar_ranking_score_threshold',
};

class MeiliSearchError extends Error {
    constructor(message) {
        super(message);
        // Make errors comparison possible. ex: error instanceof MeiliSearchError.
        Object.setPrototypeOf(this, MeiliSearchError.prototype);
        this.name = 'MeiliSearchError';
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, MeiliSearchError);
        }
    }
}

class MeiliSearchCommunicationError extends MeiliSearchError {
    statusCode;
    errno;
    code;
    stack;
    constructor(message, body, url, stack) {
        super(message);
        // Make errors comparison possible. ex: error instanceof MeiliSearchCommunicationError.
        Object.setPrototypeOf(this, MeiliSearchCommunicationError.prototype);
        this.name = 'MeiliSearchCommunicationError';
        if (body instanceof Response) {
            this.message = body.statusText;
            this.statusCode = body.status;
        }
        if (body instanceof Error) {
            this.errno = body.errno;
            this.code = body.code;
        }
        if (stack) {
            this.stack = stack;
            this.stack = this.stack?.replace(/(TypeError|FetchError)/, this.name);
            this.stack = this.stack?.replace('Failed to fetch', `request to ${url} failed, reason: connect ECONNREFUSED`);
            this.stack = this.stack?.replace('Not Found', `Not Found: ${url}`);
        }
        else {
            if (Error.captureStackTrace) {
                Error.captureStackTrace(this, MeiliSearchCommunicationError);
            }
        }
    }
}

const MeiliSearchApiError = class extends MeiliSearchError {
    httpStatus;
    code;
    link;
    type;
    stack;
    constructor(error, status) {
        super(error.message);
        // Make errors comparison possible. ex: error instanceof MeiliSearchApiError.
        Object.setPrototypeOf(this, MeiliSearchApiError.prototype);
        this.name = 'MeiliSearchApiError';
        this.code = error.code;
        this.type = error.type;
        this.link = error.link;
        this.message = error.message;
        this.httpStatus = status;
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, MeiliSearchApiError);
        }
    }
};

async function httpResponseErrorHandler(response) {
    if (!response.ok) {
        let responseBody;
        try {
            // If it is not possible to parse the return body it means there is none
            // In which case it is a communication error with the Meilisearch instance
            responseBody = await response.json();
        }
        catch (e) {
            // Not sure on how to test this part of the code.
            throw new MeiliSearchCommunicationError(response.statusText, response, response.url);
        }
        // If the body is parsable, then it means Meilisearch returned a body with
        // information on the error.
        throw new MeiliSearchApiError(responseBody, response.status);
    }
    return response;
}
function httpErrorHandler(response, stack, url) {
    if (response.name !== 'MeiliSearchApiError') {
        throw new MeiliSearchCommunicationError(response.message, response, url, stack);
    }
    throw response;
}

class MeiliSearchTimeOutError extends MeiliSearchError {
    constructor(message) {
        super(message);
        // Make errors comparison possible. ex: error instanceof MeiliSearchTimeOutError.
        Object.setPrototypeOf(this, MeiliSearchTimeOutError.prototype);
        this.name = 'MeiliSearchTimeOutError';
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, MeiliSearchTimeOutError);
        }
    }
}

function versionErrorHintMessage(message, method) {
    return `${message}\nHint: It might not be working because maybe you're not up to date with the Meilisearch version that ${method} call requires.`;
}

/** Removes undefined entries from object */
function removeUndefinedFromObject(obj) {
    return Object.entries(obj).reduce((acc, curEntry) => {
        const [key, val] = curEntry;
        if (val !== undefined)
            acc[key] = val;
        return acc;
    }, {});
}
async function sleep(ms) {
    return await new Promise((resolve) => setTimeout(resolve, ms));
}
function addProtocolIfNotPresent(host) {
    if (!(host.startsWith('https://') || host.startsWith('http://'))) {
        return `http://${host}`;
    }
    return host;
}
function addTrailingSlash(url) {
    if (!url.endsWith('/')) {
        url += '/';
    }
    return url;
}
function validateUuid4(uuid) {
    const regexExp = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi;
    return regexExp.test(uuid);
}

const PACKAGE_VERSION = '0.41.0';

function toQueryParams(parameters) {
    const params = Object.keys(parameters);
    const queryParams = params.reduce((acc, key) => {
        const value = parameters[key];
        if (value === undefined) {
            return acc;
        }
        else if (Array.isArray(value)) {
            return { ...acc, [key]: value.join(',') };
        }
        else if (value instanceof Date) {
            return { ...acc, [key]: value.toISOString() };
        }
        return { ...acc, [key]: value };
    }, {});
    return queryParams;
}
function constructHostURL(host) {
    try {
        host = addProtocolIfNotPresent(host);
        host = addTrailingSlash(host);
        return host;
    }
    catch (e) {
        throw new MeiliSearchError('The provided host is not valid.');
    }
}
function cloneAndParseHeaders(headers) {
    if (Array.isArray(headers)) {
        return headers.reduce((acc, headerPair) => {
            acc[headerPair[0]] = headerPair[1];
            return acc;
        }, {});
    }
    else if ('has' in headers) {
        const clonedHeaders = {};
        headers.forEach((value, key) => (clonedHeaders[key] = value));
        return clonedHeaders;
    }
    else {
        return Object.assign({}, headers);
    }
}
function createHeaders(config) {
    const agentHeader = 'X-Meilisearch-Client';
    const packageAgent = `Meilisearch JavaScript (v${PACKAGE_VERSION})`;
    const contentType = 'Content-Type';
    const authorization = 'Authorization';
    const headers = cloneAndParseHeaders(config.requestConfig?.headers ?? {});
    // do not override if user provided the header
    if (config.apiKey && !headers[authorization]) {
        headers[authorization] = `Bearer ${config.apiKey}`;
    }
    if (!headers[contentType]) {
        headers['Content-Type'] = 'application/json';
    }
    // Creates the custom user agent with information on the package used.
    if (config.clientAgents && Array.isArray(config.clientAgents)) {
        const clients = config.clientAgents.concat(packageAgent);
        headers[agentHeader] = clients.join(' ; ');
    }
    else if (config.clientAgents && !Array.isArray(config.clientAgents)) {
        // If the header is defined but not an array
        throw new MeiliSearchError(`Meilisearch: The header "${agentHeader}" should be an array of string(s).\n`);
    }
    else {
        headers[agentHeader] = packageAgent;
    }
    return headers;
}
class HttpRequests {
    headers;
    url;
    requestConfig;
    httpClient;
    requestTimeout;
    constructor(config) {
        this.headers = createHeaders(config);
        this.requestConfig = config.requestConfig;
        this.httpClient = config.httpClient;
        this.requestTimeout = config.timeout;
        try {
            const host = constructHostURL(config.host);
            this.url = new URL(host);
        }
        catch (e) {
            throw new MeiliSearchError('The provided host is not valid.');
        }
    }
    async request({ method, url, params, body, config = {}, }) {
        if (typeof fetch === 'undefined') {
            require('cross-fetch/polyfill');
        }
        const constructURL = new URL(url, this.url);
        if (params) {
            const queryParams = new URLSearchParams();
            Object.keys(params)
                .filter((x) => params[x] !== null)
                .map((x) => queryParams.set(x, params[x]));
            constructURL.search = queryParams.toString();
        }
        // in case a custom content-type is provided
        // do not stringify body
        if (!config.headers?.['Content-Type']) {
            body = JSON.stringify(body);
        }
        const headers = { ...this.headers, ...config.headers };
        try {
            const result = this.fetchWithTimeout(constructURL.toString(), {
                ...config,
                ...this.requestConfig,
                method,
                body,
                headers,
            }, this.requestTimeout);
            // When using a custom HTTP client, the response is returned to allow the user to parse/handle it as they see fit
            if (this.httpClient) {
                return await result;
            }
            const response = await result.then((res) => httpResponseErrorHandler(res));
            const parsedBody = await response.json().catch(() => undefined);
            return parsedBody;
        }
        catch (e) {
            const stack = e.stack;
            httpErrorHandler(e, stack, constructURL.toString());
        }
    }
    async fetchWithTimeout(url, options, timeout) {
        return new Promise((resolve, reject) => {
            const fetchFn = this.httpClient ? this.httpClient : fetch;
            const fetchPromise = fetchFn(url, options);
            const promises = [fetchPromise];
            // TimeoutPromise will not run if undefined or zero
            let timeoutId;
            if (timeout) {
                const timeoutPromise = new Promise((_, reject) => {
                    timeoutId = setTimeout(() => {
                        reject(new Error('Error: Request Timed Out'));
                    }, timeout);
                });
                promises.push(timeoutPromise);
            }
            Promise.race(promises)
                .then(resolve)
                .catch(reject)
                .finally(() => {
                clearTimeout(timeoutId);
            });
        });
    }
    async get(url, params, config) {
        return await this.request({
            method: 'GET',
            url,
            params,
            config,
        });
    }
    async post(url, data, params, config) {
        return await this.request({
            method: 'POST',
            url,
            body: data,
            params,
            config,
        });
    }
    async put(url, data, params, config) {
        return await this.request({
            method: 'PUT',
            url,
            body: data,
            params,
            config,
        });
    }
    async patch(url, data, params, config) {
        return await this.request({
            method: 'PATCH',
            url,
            body: data,
            params,
            config,
        });
    }
    async delete(url, data, params, config) {
        return await this.request({
            method: 'DELETE',
            url,
            body: data,
            params,
            config,
        });
    }
}

class EnqueuedTask {
    taskUid;
    indexUid;
    status;
    type;
    enqueuedAt;
    constructor(task) {
        this.taskUid = task.taskUid;
        this.indexUid = task.indexUid;
        this.status = task.status;
        this.type = task.type;
        this.enqueuedAt = new Date(task.enqueuedAt);
    }
}

class Task {
    indexUid;
    status;
    type;
    uid;
    canceledBy;
    details;
    error;
    duration;
    startedAt;
    enqueuedAt;
    finishedAt;
    constructor(task) {
        this.indexUid = task.indexUid;
        this.status = task.status;
        this.type = task.type;
        this.uid = task.uid;
        this.details = task.details;
        this.canceledBy = task.canceledBy;
        this.error = task.error;
        this.duration = task.duration;
        this.startedAt = new Date(task.startedAt);
        this.enqueuedAt = new Date(task.enqueuedAt);
        this.finishedAt = new Date(task.finishedAt);
    }
}
class TaskClient {
    httpRequest;
    constructor(config) {
        this.httpRequest = new HttpRequests(config);
    }
    /**
     * Get one task
     *
     * @param uid - Unique identifier of the task
     * @returns
     */
    async getTask(uid) {
        const url = `tasks/${uid}`;
        const taskItem = await this.httpRequest.get(url);
        return new Task(taskItem);
    }
    /**
     * Get tasks
     *
     * @param parameters - Parameters to browse the tasks
     * @returns Promise containing all tasks
     */
    async getTasks(parameters = {}) {
        const url = `tasks`;
        const tasks = await this.httpRequest.get(url, toQueryParams(parameters));
        return {
            ...tasks,
            results: tasks.results.map((task) => new Task(task)),
        };
    }
    /**
     * Wait for a task to be processed.
     *
     * @param taskUid - Task identifier
     * @param options - Additional configuration options
     * @returns Promise returning a task after it has been processed
     */
    async waitForTask(taskUid, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        const startingTime = Date.now();
        while (Date.now() - startingTime < timeOutMs) {
            const response = await this.getTask(taskUid);
            if (![
                TaskStatus.TASK_ENQUEUED,
                TaskStatus.TASK_PROCESSING,
            ].includes(response.status))
                return response;
            await sleep(intervalMs);
        }
        throw new MeiliSearchTimeOutError(`timeout of ${timeOutMs}ms has exceeded on process ${taskUid} when waiting a task to be resolved.`);
    }
    /**
     * Waits for multiple tasks to be processed
     *
     * @param taskUids - Tasks identifier list
     * @param options - Wait options
     * @returns Promise returning a list of tasks after they have been processed
     */
    async waitForTasks(taskUids, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        const tasks = [];
        for (const taskUid of taskUids) {
            const task = await this.waitForTask(taskUid, {
                timeOutMs,
                intervalMs,
            });
            tasks.push(task);
        }
        return tasks;
    }
    /**
     * Cancel a list of enqueued or processing tasks.
     *
     * @param parameters - Parameters to filter the tasks.
     * @returns Promise containing an EnqueuedTask
     */
    async cancelTasks(parameters = {}) {
        const url = `tasks/cancel`;
        const task = await this.httpRequest.post(url, {}, toQueryParams(parameters));
        return new EnqueuedTask(task);
    }
    /**
     * Delete a list tasks.
     *
     * @param parameters - Parameters to filter the tasks.
     * @returns Promise containing an EnqueuedTask
     */
    async deleteTasks(parameters = {}) {
        const url = `tasks`;
        const task = await this.httpRequest.delete(url, {}, toQueryParams(parameters));
        return new EnqueuedTask(task);
    }
}

/*
 * Bundle: MeiliSearch / Indexes
 * Project: MeiliSearch - Javascript API
 * Author: Quentin de Quelen <quentin@meilisearch.com>
 * Copyright: 2019, MeiliSearch
 */
class Index {
    uid;
    primaryKey;
    createdAt;
    updatedAt;
    httpRequest;
    tasks;
    /**
     * @param config - Request configuration options
     * @param uid - UID of the index
     * @param primaryKey - Primary Key of the index
     */
    constructor(config, uid, primaryKey) {
        this.uid = uid;
        this.primaryKey = primaryKey;
        this.httpRequest = new HttpRequests(config);
        this.tasks = new TaskClient(config);
    }
    ///
    /// SEARCH
    ///
    /**
     * Search for documents into an index
     *
     * @param query - Query string
     * @param options - Search options
     * @param config - Additional request configuration options
     * @returns Promise containing the search response
     */
    async search(query, options, config) {
        const url = `indexes/${this.uid}/search`;
        return await this.httpRequest.post(url, removeUndefinedFromObject({ q: query, ...options }), undefined, config);
    }
    /**
     * Search for documents into an index using the GET method
     *
     * @param query - Query string
     * @param options - Search options
     * @param config - Additional request configuration options
     * @returns Promise containing the search response
     */
    async searchGet(query, options, config) {
        const url = `indexes/${this.uid}/search`;
        const parseFilter = (filter) => {
            if (typeof filter === 'string')
                return filter;
            else if (Array.isArray(filter))
                throw new MeiliSearchError('The filter query parameter should be in string format when using searchGet');
            else
                return undefined;
        };
        const getParams = {
            q: query,
            ...options,
            filter: parseFilter(options?.filter),
            sort: options?.sort?.join(','),
            facets: options?.facets?.join(','),
            attributesToRetrieve: options?.attributesToRetrieve?.join(','),
            attributesToCrop: options?.attributesToCrop?.join(','),
            attributesToHighlight: options?.attributesToHighlight?.join(','),
            vector: options?.vector?.join(','),
            attributesToSearchOn: options?.attributesToSearchOn?.join(','),
        };
        return await this.httpRequest.get(url, removeUndefinedFromObject(getParams), config);
    }
    /**
     * Search for facet values
     *
     * @param params - Parameters used to search on the facets
     * @param config - Additional request configuration options
     * @returns Promise containing the search response
     */
    async searchForFacetValues(params, config) {
        const url = `indexes/${this.uid}/facet-search`;
        return await this.httpRequest.post(url, removeUndefinedFromObject(params), undefined, config);
    }
    /**
     * Search for similar documents
     *
     * @param params - Parameters used to search for similar documents
     * @returns Promise containing the search response
     */
    async searchSimilarDocuments(params) {
        const url = `indexes/${this.uid}/similar`;
        return await this.httpRequest.post(url, removeUndefinedFromObject(params), undefined);
    }
    ///
    /// INDEX
    ///
    /**
     * Get index information.
     *
     * @returns Promise containing index information
     */
    async getRawInfo() {
        const url = `indexes/${this.uid}`;
        const res = await this.httpRequest.get(url);
        this.primaryKey = res.primaryKey;
        this.updatedAt = new Date(res.updatedAt);
        this.createdAt = new Date(res.createdAt);
        return res;
    }
    /**
     * Fetch and update Index information.
     *
     * @returns Promise to the current Index object with updated information
     */
    async fetchInfo() {
        await this.getRawInfo();
        return this;
    }
    /**
     * Get Primary Key.
     *
     * @returns Promise containing the Primary Key of the index
     */
    async fetchPrimaryKey() {
        this.primaryKey = (await this.getRawInfo()).primaryKey;
        return this.primaryKey;
    }
    /**
     * Create an index.
     *
     * @param uid - Unique identifier of the Index
     * @param options - Index options
     * @param config - Request configuration options
     * @returns Newly created Index object
     */
    static async create(uid, options = {}, config) {
        const url = `indexes`;
        const req = new HttpRequests(config);
        const task = await req.post(url, { ...options, uid });
        return new EnqueuedTask(task);
    }
    /**
     * Update an index.
     *
     * @param data - Data to update
     * @returns Promise to the current Index object with updated information
     */
    async update(data) {
        const url = `indexes/${this.uid}`;
        const task = await this.httpRequest.patch(url, data);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    /**
     * Delete an index.
     *
     * @returns Promise which resolves when index is deleted successfully
     */
    async delete() {
        const url = `indexes/${this.uid}`;
        const task = await this.httpRequest.delete(url);
        return new EnqueuedTask(task);
    }
    ///
    /// TASKS
    ///
    /**
     * Get the list of all the tasks of the index.
     *
     * @param parameters - Parameters to browse the tasks
     * @returns Promise containing all tasks
     */
    async getTasks(parameters = {}) {
        return await this.tasks.getTasks({ ...parameters, indexUids: [this.uid] });
    }
    /**
     * Get one task of the index.
     *
     * @param taskUid - Task identifier
     * @returns Promise containing a task
     */
    async getTask(taskUid) {
        return await this.tasks.getTask(taskUid);
    }
    /**
     * Wait for multiple tasks to be processed.
     *
     * @param taskUids - Tasks identifier
     * @param waitOptions - Options on timeout and interval
     * @returns Promise containing an array of tasks
     */
    async waitForTasks(taskUids, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        return await this.tasks.waitForTasks(taskUids, {
            timeOutMs,
            intervalMs,
        });
    }
    /**
     * Wait for a task to be processed.
     *
     * @param taskUid - Task identifier
     * @param waitOptions - Options on timeout and interval
     * @returns Promise containing an array of tasks
     */
    async waitForTask(taskUid, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        return await this.tasks.waitForTask(taskUid, {
            timeOutMs,
            intervalMs,
        });
    }
    ///
    /// STATS
    ///
    /**
     * Get stats of an index
     *
     * @returns Promise containing object with stats of the index
     */
    async getStats() {
        const url = `indexes/${this.uid}/stats`;
        return await this.httpRequest.get(url);
    }
    ///
    /// DOCUMENTS
    ///
    /**
     * Get documents of an index.
     *
     * @param parameters - Parameters to browse the documents. Parameters can
     *   contain the `filter` field only available in Meilisearch v1.2 and newer
     * @returns Promise containing the returned documents
     */
    async getDocuments(parameters = {}) {
        parameters = removeUndefinedFromObject(parameters);
        // In case `filter` is provided, use `POST /documents/fetch`
        if (parameters.filter !== undefined) {
            try {
                const url = `indexes/${this.uid}/documents/fetch`;
                return await this.httpRequest.post(url, parameters);
            }
            catch (e) {
                if (e instanceof MeiliSearchCommunicationError) {
                    e.message = versionErrorHintMessage(e.message, 'getDocuments');
                }
                else if (e instanceof MeiliSearchApiError) {
                    e.message = versionErrorHintMessage(e.message, 'getDocuments');
                }
                throw e;
            }
            // Else use `GET /documents` method
        }
        else {
            const url = `indexes/${this.uid}/documents`;
            // Transform fields to query parameter string format
            const fields = Array.isArray(parameters?.fields)
                ? { fields: parameters?.fields?.join(',') }
                : {};
            return await this.httpRequest.get(url, {
                ...parameters,
                ...fields,
            });
        }
    }
    /**
     * Get one document
     *
     * @param documentId - Document ID
     * @param parameters - Parameters applied on a document
     * @returns Promise containing Document response
     */
    async getDocument(documentId, parameters) {
        const url = `indexes/${this.uid}/documents/${documentId}`;
        const fields = (() => {
            if (Array.isArray(parameters?.fields)) {
                return parameters?.fields?.join(',');
            }
            return undefined;
        })();
        return await this.httpRequest.get(url, removeUndefinedFromObject({
            ...parameters,
            fields,
        }));
    }
    /**
     * Add or replace multiples documents to an index
     *
     * @param documents - Array of Document objects to add/replace
     * @param options - Options on document addition
     * @returns Promise containing an EnqueuedTask
     */
    async addDocuments(documents, options) {
        const url = `indexes/${this.uid}/documents`;
        const task = await this.httpRequest.post(url, documents, options);
        return new EnqueuedTask(task);
    }
    /**
     * Add or replace multiples documents in a string format to an index. It only
     * supports csv, ndjson and json formats.
     *
     * @param documents - Documents provided in a string to add/replace
     * @param contentType - Content type of your document:
     *   'text/csv'|'application/x-ndjson'|'application/json'
     * @param options - Options on document addition
     * @returns Promise containing an EnqueuedTask
     */
    async addDocumentsFromString(documents, contentType, queryParams) {
        const url = `indexes/${this.uid}/documents`;
        const task = await this.httpRequest.post(url, documents, queryParams, {
            headers: {
                'Content-Type': contentType,
            },
        });
        return new EnqueuedTask(task);
    }
    /**
     * Add or replace multiples documents to an index in batches
     *
     * @param documents - Array of Document objects to add/replace
     * @param batchSize - Size of the batch
     * @param options - Options on document addition
     * @returns Promise containing array of enqueued task objects for each batch
     */
    async addDocumentsInBatches(documents, batchSize = 1000, options) {
        const updates = [];
        for (let i = 0; i < documents.length; i += batchSize) {
            updates.push(await this.addDocuments(documents.slice(i, i + batchSize), options));
        }
        return updates;
    }
    /**
     * Add or update multiples documents to an index
     *
     * @param documents - Array of Document objects to add/update
     * @param options - Options on document update
     * @returns Promise containing an EnqueuedTask
     */
    async updateDocuments(documents, options) {
        const url = `indexes/${this.uid}/documents`;
        const task = await this.httpRequest.put(url, documents, options);
        return new EnqueuedTask(task);
    }
    /**
     * Add or update multiples documents to an index in batches
     *
     * @param documents - Array of Document objects to add/update
     * @param batchSize - Size of the batch
     * @param options - Options on document update
     * @returns Promise containing array of enqueued task objects for each batch
     */
    async updateDocumentsInBatches(documents, batchSize = 1000, options) {
        const updates = [];
        for (let i = 0; i < documents.length; i += batchSize) {
            updates.push(await this.updateDocuments(documents.slice(i, i + batchSize), options));
        }
        return updates;
    }
    /**
     * Add or update multiples documents in a string format to an index. It only
     * supports csv, ndjson and json formats.
     *
     * @param documents - Documents provided in a string to add/update
     * @param contentType - Content type of your document:
     *   'text/csv'|'application/x-ndjson'|'application/json'
     * @param queryParams - Options on raw document addition
     * @returns Promise containing an EnqueuedTask
     */
    async updateDocumentsFromString(documents, contentType, queryParams) {
        const url = `indexes/${this.uid}/documents`;
        const task = await this.httpRequest.put(url, documents, queryParams, {
            headers: {
                'Content-Type': contentType,
            },
        });
        return new EnqueuedTask(task);
    }
    /**
     * Delete one document
     *
     * @param documentId - Id of Document to delete
     * @returns Promise containing an EnqueuedTask
     */
    async deleteDocument(documentId) {
        const url = `indexes/${this.uid}/documents/${documentId}`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    /**
     * Delete multiples documents of an index.
     *
     * @param params - Params value can be:
     *
     *   - DocumentsDeletionQuery: An object containing the parameters to customize
     *       your document deletion. Only available in Meilisearch v1.2 and newer
     *   - DocumentsIds: An array of document ids to delete
     *
     * @returns Promise containing an EnqueuedTask
     */
    async deleteDocuments(params) {
        // If params is of type DocumentsDeletionQuery
        const isDocumentsDeletionQuery = !Array.isArray(params) && typeof params === 'object';
        const endpoint = isDocumentsDeletionQuery
            ? 'documents/delete'
            : 'documents/delete-batch';
        const url = `indexes/${this.uid}/${endpoint}`;
        try {
            const task = await this.httpRequest.post(url, params);
            return new EnqueuedTask(task);
        }
        catch (e) {
            if (e instanceof MeiliSearchCommunicationError &&
                isDocumentsDeletionQuery) {
                e.message = versionErrorHintMessage(e.message, 'deleteDocuments');
            }
            else if (e instanceof MeiliSearchApiError) {
                e.message = versionErrorHintMessage(e.message, 'deleteDocuments');
            }
            throw e;
        }
    }
    /**
     * Delete all documents of an index
     *
     * @returns Promise containing an EnqueuedTask
     */
    async deleteAllDocuments() {
        const url = `indexes/${this.uid}/documents`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// SETTINGS
    ///
    /**
     * Retrieve all settings
     *
     * @returns Promise containing Settings object
     */
    async getSettings() {
        const url = `indexes/${this.uid}/settings`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update all settings Any parameters not provided will be left unchanged.
     *
     * @param settings - Object containing parameters with their updated values
     * @returns Promise containing an EnqueuedTask
     */
    async updateSettings(settings) {
        const url = `indexes/${this.uid}/settings`;
        const task = await this.httpRequest.patch(url, settings);
        task.enqueued = new Date(task.enqueuedAt);
        return task;
    }
    /**
     * Reset settings.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSettings() {
        const url = `indexes/${this.uid}/settings`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// PAGINATION SETTINGS
    ///
    /**
     * Get the pagination settings.
     *
     * @returns Promise containing object of pagination settings
     */
    async getPagination() {
        const url = `indexes/${this.uid}/settings/pagination`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the pagination settings.
     *
     * @param pagination - Pagination object
     * @returns Promise containing an EnqueuedTask
     */
    async updatePagination(pagination) {
        const url = `indexes/${this.uid}/settings/pagination`;
        const task = await this.httpRequest.patch(url, pagination);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the pagination settings.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetPagination() {
        const url = `indexes/${this.uid}/settings/pagination`;
        const task = await this.httpRequest.delete(url);
        return new EnqueuedTask(task);
    }
    ///
    /// SYNONYMS
    ///
    /**
     * Get the list of all synonyms
     *
     * @returns Promise containing object of synonym mappings
     */
    async getSynonyms() {
        const url = `indexes/${this.uid}/settings/synonyms`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the list of synonyms. Overwrite the old list.
     *
     * @param synonyms - Mapping of synonyms with their associated words
     * @returns Promise containing an EnqueuedTask
     */
    async updateSynonyms(synonyms) {
        const url = `indexes/${this.uid}/settings/synonyms`;
        const task = await this.httpRequest.put(url, synonyms);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the synonym list to be empty again
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSynonyms() {
        const url = `indexes/${this.uid}/settings/synonyms`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// STOP WORDS
    ///
    /**
     * Get the list of all stop-words
     *
     * @returns Promise containing array of stop-words
     */
    async getStopWords() {
        const url = `indexes/${this.uid}/settings/stop-words`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the list of stop-words. Overwrite the old list.
     *
     * @param stopWords - Array of strings that contains the stop-words.
     * @returns Promise containing an EnqueuedTask
     */
    async updateStopWords(stopWords) {
        const url = `indexes/${this.uid}/settings/stop-words`;
        const task = await this.httpRequest.put(url, stopWords);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the stop-words list to be empty again
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetStopWords() {
        const url = `indexes/${this.uid}/settings/stop-words`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// RANKING RULES
    ///
    /**
     * Get the list of all ranking-rules
     *
     * @returns Promise containing array of ranking-rules
     */
    async getRankingRules() {
        const url = `indexes/${this.uid}/settings/ranking-rules`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the list of ranking-rules. Overwrite the old list.
     *
     * @param rankingRules - Array that contain ranking rules sorted by order of
     *   importance.
     * @returns Promise containing an EnqueuedTask
     */
    async updateRankingRules(rankingRules) {
        const url = `indexes/${this.uid}/settings/ranking-rules`;
        const task = await this.httpRequest.put(url, rankingRules);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the ranking rules list to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetRankingRules() {
        const url = `indexes/${this.uid}/settings/ranking-rules`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// DISTINCT ATTRIBUTE
    ///
    /**
     * Get the distinct-attribute
     *
     * @returns Promise containing the distinct-attribute of the index
     */
    async getDistinctAttribute() {
        const url = `indexes/${this.uid}/settings/distinct-attribute`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the distinct-attribute.
     *
     * @param distinctAttribute - Field name of the distinct-attribute
     * @returns Promise containing an EnqueuedTask
     */
    async updateDistinctAttribute(distinctAttribute) {
        const url = `indexes/${this.uid}/settings/distinct-attribute`;
        const task = await this.httpRequest.put(url, distinctAttribute);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the distinct-attribute.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetDistinctAttribute() {
        const url = `indexes/${this.uid}/settings/distinct-attribute`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// FILTERABLE ATTRIBUTES
    ///
    /**
     * Get the filterable-attributes
     *
     * @returns Promise containing an array of filterable-attributes
     */
    async getFilterableAttributes() {
        const url = `indexes/${this.uid}/settings/filterable-attributes`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the filterable-attributes.
     *
     * @param filterableAttributes - Array of strings containing the attributes
     *   that can be used as filters at query time
     * @returns Promise containing an EnqueuedTask
     */
    async updateFilterableAttributes(filterableAttributes) {
        const url = `indexes/${this.uid}/settings/filterable-attributes`;
        const task = await this.httpRequest.put(url, filterableAttributes);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the filterable-attributes.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetFilterableAttributes() {
        const url = `indexes/${this.uid}/settings/filterable-attributes`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// SORTABLE ATTRIBUTES
    ///
    /**
     * Get the sortable-attributes
     *
     * @returns Promise containing array of sortable-attributes
     */
    async getSortableAttributes() {
        const url = `indexes/${this.uid}/settings/sortable-attributes`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the sortable-attributes.
     *
     * @param sortableAttributes - Array of strings containing the attributes that
     *   can be used to sort search results at query time
     * @returns Promise containing an EnqueuedTask
     */
    async updateSortableAttributes(sortableAttributes) {
        const url = `indexes/${this.uid}/settings/sortable-attributes`;
        const task = await this.httpRequest.put(url, sortableAttributes);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the sortable-attributes.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSortableAttributes() {
        const url = `indexes/${this.uid}/settings/sortable-attributes`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// SEARCHABLE ATTRIBUTE
    ///
    /**
     * Get the searchable-attributes
     *
     * @returns Promise containing array of searchable-attributes
     */
    async getSearchableAttributes() {
        const url = `indexes/${this.uid}/settings/searchable-attributes`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the searchable-attributes.
     *
     * @param searchableAttributes - Array of strings that contains searchable
     *   attributes sorted by order of importance(most to least important)
     * @returns Promise containing an EnqueuedTask
     */
    async updateSearchableAttributes(searchableAttributes) {
        const url = `indexes/${this.uid}/settings/searchable-attributes`;
        const task = await this.httpRequest.put(url, searchableAttributes);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the searchable-attributes.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSearchableAttributes() {
        const url = `indexes/${this.uid}/settings/searchable-attributes`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// DISPLAYED ATTRIBUTE
    ///
    /**
     * Get the displayed-attributes
     *
     * @returns Promise containing array of displayed-attributes
     */
    async getDisplayedAttributes() {
        const url = `indexes/${this.uid}/settings/displayed-attributes`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the displayed-attributes.
     *
     * @param displayedAttributes - Array of strings that contains attributes of
     *   an index to display
     * @returns Promise containing an EnqueuedTask
     */
    async updateDisplayedAttributes(displayedAttributes) {
        const url = `indexes/${this.uid}/settings/displayed-attributes`;
        const task = await this.httpRequest.put(url, displayedAttributes);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the displayed-attributes.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetDisplayedAttributes() {
        const url = `indexes/${this.uid}/settings/displayed-attributes`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// TYPO TOLERANCE
    ///
    /**
     * Get the typo tolerance settings.
     *
     * @returns Promise containing the typo tolerance settings.
     */
    async getTypoTolerance() {
        const url = `indexes/${this.uid}/settings/typo-tolerance`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the typo tolerance settings.
     *
     * @param typoTolerance - Object containing the custom typo tolerance
     *   settings.
     * @returns Promise containing object of the enqueued update
     */
    async updateTypoTolerance(typoTolerance) {
        const url = `indexes/${this.uid}/settings/typo-tolerance`;
        const task = await this.httpRequest.patch(url, typoTolerance);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    /**
     * Reset the typo tolerance settings.
     *
     * @returns Promise containing object of the enqueued update
     */
    async resetTypoTolerance() {
        const url = `indexes/${this.uid}/settings/typo-tolerance`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// FACETING
    ///
    /**
     * Get the faceting settings.
     *
     * @returns Promise containing object of faceting index settings
     */
    async getFaceting() {
        const url = `indexes/${this.uid}/settings/faceting`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the faceting settings.
     *
     * @param faceting - Faceting index settings object
     * @returns Promise containing an EnqueuedTask
     */
    async updateFaceting(faceting) {
        const url = `indexes/${this.uid}/settings/faceting`;
        const task = await this.httpRequest.patch(url, faceting);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the faceting settings.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetFaceting() {
        const url = `indexes/${this.uid}/settings/faceting`;
        const task = await this.httpRequest.delete(url);
        return new EnqueuedTask(task);
    }
    ///
    /// SEPARATOR TOKENS
    ///
    /**
     * Get the list of all separator tokens.
     *
     * @returns Promise containing array of separator tokens
     */
    async getSeparatorTokens() {
        const url = `indexes/${this.uid}/settings/separator-tokens`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the list of separator tokens. Overwrite the old list.
     *
     * @param separatorTokens - Array that contains separator tokens.
     * @returns Promise containing an EnqueuedTask or null
     */
    async updateSeparatorTokens(separatorTokens) {
        const url = `indexes/${this.uid}/settings/separator-tokens`;
        const task = await this.httpRequest.put(url, separatorTokens);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the separator tokens list to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSeparatorTokens() {
        const url = `indexes/${this.uid}/settings/separator-tokens`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// NON-SEPARATOR TOKENS
    ///
    /**
     * Get the list of all non-separator tokens.
     *
     * @returns Promise containing array of non-separator tokens
     */
    async getNonSeparatorTokens() {
        const url = `indexes/${this.uid}/settings/non-separator-tokens`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the list of non-separator tokens. Overwrite the old list.
     *
     * @param nonSeparatorTokens - Array that contains non-separator tokens.
     * @returns Promise containing an EnqueuedTask or null
     */
    async updateNonSeparatorTokens(nonSeparatorTokens) {
        const url = `indexes/${this.uid}/settings/non-separator-tokens`;
        const task = await this.httpRequest.put(url, nonSeparatorTokens);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the non-separator tokens list to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetNonSeparatorTokens() {
        const url = `indexes/${this.uid}/settings/non-separator-tokens`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// DICTIONARY
    ///
    /**
     * Get the dictionary settings of a Meilisearch index.
     *
     * @returns Promise containing the dictionary settings
     */
    async getDictionary() {
        const url = `indexes/${this.uid}/settings/dictionary`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the dictionary settings. Overwrite the old settings.
     *
     * @param dictionary - Array that contains the new dictionary settings.
     * @returns Promise containing an EnqueuedTask or null
     */
    async updateDictionary(dictionary) {
        const url = `indexes/${this.uid}/settings/dictionary`;
        const task = await this.httpRequest.put(url, dictionary);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the dictionary settings to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetDictionary() {
        const url = `indexes/${this.uid}/settings/dictionary`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// PROXIMITY PRECISION
    ///
    /**
     * Get the proximity precision settings of a Meilisearch index.
     *
     * @returns Promise containing the proximity precision settings
     */
    async getProximityPrecision() {
        const url = `indexes/${this.uid}/settings/proximity-precision`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the proximity precision settings. Overwrite the old settings.
     *
     * @param proximityPrecision - String that contains the new proximity
     *   precision settings.
     * @returns Promise containing an EnqueuedTask or null
     */
    async updateProximityPrecision(proximityPrecision) {
        const url = `indexes/${this.uid}/settings/proximity-precision`;
        const task = await this.httpRequest.put(url, proximityPrecision);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the proximity precision settings to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetProximityPrecision() {
        const url = `indexes/${this.uid}/settings/proximity-precision`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// EMBEDDERS
    ///
    /**
     * Get the embedders settings of a Meilisearch index.
     *
     * @returns Promise containing the embedders settings
     */
    async getEmbedders() {
        const url = `indexes/${this.uid}/settings/embedders`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the embedders settings. Overwrite the old settings.
     *
     * @param embedders - Object that contains the new embedders settings.
     * @returns Promise containing an EnqueuedTask or null
     */
    async updateEmbedders(embedders) {
        const url = `indexes/${this.uid}/settings/embedders`;
        const task = await this.httpRequest.patch(url, embedders);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the embedders settings to its default value
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetEmbedders() {
        const url = `indexes/${this.uid}/settings/embedders`;
        const task = await this.httpRequest.delete(url);
        task.enqueuedAt = new Date(task.enqueuedAt);
        return task;
    }
    ///
    /// SEARCHCUTOFFMS SETTINGS
    ///
    /**
     * Get the SearchCutoffMs settings.
     *
     * @returns Promise containing object of SearchCutoffMs settings
     */
    async getSearchCutoffMs() {
        const url = `indexes/${this.uid}/settings/search-cutoff-ms`;
        return await this.httpRequest.get(url);
    }
    /**
     * Update the SearchCutoffMs settings.
     *
     * @param searchCutoffMs - Object containing SearchCutoffMsSettings
     * @returns Promise containing an EnqueuedTask
     */
    async updateSearchCutoffMs(searchCutoffMs) {
        const url = `indexes/${this.uid}/settings/search-cutoff-ms`;
        const task = await this.httpRequest.put(url, searchCutoffMs);
        return new EnqueuedTask(task);
    }
    /**
     * Reset the SearchCutoffMs settings.
     *
     * @returns Promise containing an EnqueuedTask
     */
    async resetSearchCutoffMs() {
        const url = `indexes/${this.uid}/settings/search-cutoff-ms`;
        const task = await this.httpRequest.delete(url);
        return new EnqueuedTask(task);
    }
}

/*
 * Bundle: MeiliSearch
 * Project: MeiliSearch - Javascript API
 * Author: Quentin de Quelen <quentin@meilisearch.com>
 * Copyright: 2019, MeiliSearch
 */
class Client {
    config;
    httpRequest;
    tasks;
    /**
     * Creates new MeiliSearch instance
     *
     * @param config - Configuration object
     */
    constructor(config) {
        this.config = config;
        this.httpRequest = new HttpRequests(config);
        this.tasks = new TaskClient(config);
    }
    /**
     * Return an Index instance
     *
     * @param indexUid - The index UID
     * @returns Instance of Index
     */
    index(indexUid) {
        return new Index(this.config, indexUid);
    }
    /**
     * Gather information about an index by calling MeiliSearch and return an
     * Index instance with the gathered information
     *
     * @param indexUid - The index UID
     * @returns Promise returning Index instance
     */
    async getIndex(indexUid) {
        return new Index(this.config, indexUid).fetchInfo();
    }
    /**
     * Gather information about an index by calling MeiliSearch and return the raw
     * JSON response
     *
     * @param indexUid - The index UID
     * @returns Promise returning index information
     */
    async getRawIndex(indexUid) {
        return new Index(this.config, indexUid).getRawInfo();
    }
    /**
     * Get all the indexes as Index instances.
     *
     * @param parameters - Parameters to browse the indexes
     * @returns Promise returning array of raw index information
     */
    async getIndexes(parameters = {}) {
        const rawIndexes = await this.getRawIndexes(parameters);
        const indexes = rawIndexes.results.map((index) => new Index(this.config, index.uid, index.primaryKey));
        return { ...rawIndexes, results: indexes };
    }
    /**
     * Get all the indexes in their raw value (no Index instances).
     *
     * @param parameters - Parameters to browse the indexes
     * @returns Promise returning array of raw index information
     */
    async getRawIndexes(parameters = {}) {
        const url = `indexes`;
        return await this.httpRequest.get(url, parameters);
    }
    /**
     * Create a new index
     *
     * @param uid - The index UID
     * @param options - Index options
     * @returns Promise returning Index instance
     */
    async createIndex(uid, options = {}) {
        return await Index.create(uid, options, this.config);
    }
    /**
     * Update an index
     *
     * @param uid - The index UID
     * @param options - Index options to update
     * @returns Promise returning Index instance after updating
     */
    async updateIndex(uid, options = {}) {
        return await new Index(this.config, uid).update(options);
    }
    /**
     * Delete an index
     *
     * @param uid - The index UID
     * @returns Promise which resolves when index is deleted successfully
     */
    async deleteIndex(uid) {
        return await new Index(this.config, uid).delete();
    }
    /**
     * Deletes an index if it already exists.
     *
     * @param uid - The index UID
     * @returns Promise which resolves to true when index exists and is deleted
     *   successfully, otherwise false if it does not exist
     */
    async deleteIndexIfExists(uid) {
        try {
            await this.deleteIndex(uid);
            return true;
        }
        catch (e) {
            if (e.code === ErrorStatusCode.INDEX_NOT_FOUND) {
                return false;
            }
            throw e;
        }
    }
    /**
     * Swaps a list of index tuples.
     *
     * @param params - List of indexes tuples to swap.
     * @returns Promise returning object of the enqueued task
     */
    async swapIndexes(params) {
        const url = '/swap-indexes';
        return await this.httpRequest.post(url, params);
    }
    ///
    /// Multi Search
    ///
    /**
     * Perform multiple search queries.
     *
     * It is possible to make multiple search queries on the same index or on
     * different ones
     *
     * @example
     *
     * ```ts
     * client.multiSearch({
     *   queries: [
     *     { indexUid: 'movies', q: 'wonder' },
     *     { indexUid: 'books', q: 'flower' },
     *   ],
     * });
     * ```
     *
     * @param queries - Search queries
     * @param config - Additional request configuration options
     * @returns Promise containing the search responses
     */
    async multiSearch(queries, config) {
        const url = `multi-search`;
        return await this.httpRequest.post(url, queries, undefined, config);
    }
    ///
    /// TASKS
    ///
    /**
     * Get the list of all client tasks
     *
     * @param parameters - Parameters to browse the tasks
     * @returns Promise returning all tasks
     */
    async getTasks(parameters = {}) {
        return await this.tasks.getTasks(parameters);
    }
    /**
     * Get one task on the client scope
     *
     * @param taskUid - Task identifier
     * @returns Promise returning a task
     */
    async getTask(taskUid) {
        return await this.tasks.getTask(taskUid);
    }
    /**
     * Wait for multiple tasks to be finished.
     *
     * @param taskUids - Tasks identifier
     * @param waitOptions - Options on timeout and interval
     * @returns Promise returning an array of tasks
     */
    async waitForTasks(taskUids, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        return await this.tasks.waitForTasks(taskUids, {
            timeOutMs,
            intervalMs,
        });
    }
    /**
     * Wait for a task to be finished.
     *
     * @param taskUid - Task identifier
     * @param waitOptions - Options on timeout and interval
     * @returns Promise returning an array of tasks
     */
    async waitForTask(taskUid, { timeOutMs = 5000, intervalMs = 50 } = {}) {
        return await this.tasks.waitForTask(taskUid, {
            timeOutMs,
            intervalMs,
        });
    }
    /**
     * Cancel a list of enqueued or processing tasks.
     *
     * @param parameters - Parameters to filter the tasks.
     * @returns Promise containing an EnqueuedTask
     */
    async cancelTasks(parameters) {
        return await this.tasks.cancelTasks(parameters);
    }
    /**
     * Delete a list of tasks.
     *
     * @param parameters - Parameters to filter the tasks.
     * @returns Promise containing an EnqueuedTask
     */
    async deleteTasks(parameters = {}) {
        return await this.tasks.deleteTasks(parameters);
    }
    ///
    /// KEYS
    ///
    /**
     * Get all API keys
     *
     * @param parameters - Parameters to browse the indexes
     * @returns Promise returning an object with keys
     */
    async getKeys(parameters = {}) {
        const url = `keys`;
        const keys = await this.httpRequest.get(url, parameters);
        keys.results = keys.results.map((key) => ({
            ...key,
            createdAt: new Date(key.createdAt),
            updatedAt: new Date(key.updatedAt),
        }));
        return keys;
    }
    /**
     * Get one API key
     *
     * @param keyOrUid - Key or uid of the API key
     * @returns Promise returning a key
     */
    async getKey(keyOrUid) {
        const url = `keys/${keyOrUid}`;
        return await this.httpRequest.get(url);
    }
    /**
     * Create one API key
     *
     * @param options - Key options
     * @returns Promise returning a key
     */
    async createKey(options) {
        const url = `keys`;
        return await this.httpRequest.post(url, options);
    }
    /**
     * Update one API key
     *
     * @param keyOrUid - Key
     * @param options - Key options
     * @returns Promise returning a key
     */
    async updateKey(keyOrUid, options) {
        const url = `keys/${keyOrUid}`;
        return await this.httpRequest.patch(url, options);
    }
    /**
     * Delete one API key
     *
     * @param keyOrUid - Key
     * @returns
     */
    async deleteKey(keyOrUid) {
        const url = `keys/${keyOrUid}`;
        return await this.httpRequest.delete(url);
    }
    ///
    /// HEALTH
    ///
    /**
     * Checks if the server is healthy, otherwise an error will be thrown.
     *
     * @returns Promise returning an object with health details
     */
    async health() {
        const url = `health`;
        return await this.httpRequest.get(url);
    }
    /**
     * Checks if the server is healthy, return true or false.
     *
     * @returns Promise returning a boolean
     */
    async isHealthy() {
        try {
            const url = `health`;
            await this.httpRequest.get(url);
            return true;
        }
        catch (e) {
            return false;
        }
    }
    ///
    /// STATS
    ///
    /**
     * Get the stats of all the database
     *
     * @returns Promise returning object of all the stats
     */
    async getStats() {
        const url = `stats`;
        return await this.httpRequest.get(url);
    }
    ///
    /// VERSION
    ///
    /**
     * Get the version of MeiliSearch
     *
     * @returns Promise returning object with version details
     */
    async getVersion() {
        const url = `version`;
        return await this.httpRequest.get(url);
    }
    ///
    /// DUMPS
    ///
    /**
     * Creates a dump
     *
     * @returns Promise returning object of the enqueued task
     */
    async createDump() {
        const url = `dumps`;
        const task = await this.httpRequest.post(url);
        return new EnqueuedTask(task);
    }
    ///
    /// SNAPSHOTS
    ///
    /**
     * Creates a snapshot
     *
     * @returns Promise returning object of the enqueued task
     */
    async createSnapshot() {
        const url = `snapshots`;
        const task = await this.httpRequest.post(url);
        return new EnqueuedTask(task);
    }
    ///
    /// TOKENS
    ///
    /**
     * Generate a tenant token
     *
     * @param apiKeyUid - The uid of the api key used as issuer of the token.
     * @param searchRules - Search rules that are applied to every search.
     * @param options - Token options to customize some aspect of the token.
     * @returns The token in JWT format.
     */
    generateTenantToken(_apiKeyUid, _searchRules, _options) {
        const error = new Error();
        error.message = `Meilisearch: failed to generate a tenant token. Generation of a token only works in a node environment \n ${error.stack}.`;
        return Promise.reject(error);
    }
}

function encode64(data) {
    return Buffer.from(JSON.stringify(data)).toString('base64');
}
/**
 * Create the header of the token.
 *
 * @param apiKey - API key used to sign the token.
 * @param encodedHeader - Header of the token in base64.
 * @param encodedPayload - Payload of the token in base64.
 * @returns The signature of the token in base64.
 */
async function sign(apiKey, encodedHeader, encodedPayload) {
    const { createHmac } = await import('crypto');
    return createHmac('sha256', apiKey)
        .update(`${encodedHeader}.${encodedPayload}`)
        .digest('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}
/**
 * Create the header of the token.
 *
 * @returns The header encoded in base64.
 */
function createHeader() {
    const header = {
        alg: 'HS256',
        typ: 'JWT',
    };
    return encode64(header).replace(/=/g, '');
}
/**
 * Validate the parameter used for the payload of the token.
 *
 * @param searchRules - Search rules that are applied to every search.
 * @param apiKey - Api key used as issuer of the token.
 * @param uid - The uid of the api key used as issuer of the token.
 * @param expiresAt - Date at which the token expires.
 */
function validateTokenParameters(tokenParams) {
    const { searchRules, uid, apiKey, expiresAt } = tokenParams;
    if (expiresAt) {
        if (!(expiresAt instanceof Date)) {
            throw new MeiliSearchError(`Meilisearch: The expiredAt field must be an instance of Date.`);
        }
        else if (expiresAt.getTime() < Date.now()) {
            throw new MeiliSearchError(`Meilisearch: The expiresAt field must be a date in the future.`);
        }
    }
    if (searchRules) {
        if (!(typeof searchRules === 'object' || Array.isArray(searchRules))) {
            throw new MeiliSearchError(`Meilisearch: The search rules added in the token generation must be of type array or object.`);
        }
    }
    if (!apiKey || typeof apiKey !== 'string') {
        throw new MeiliSearchError(`Meilisearch: The API key used for the token generation must exist and be of type string.`);
    }
    if (!uid || typeof uid !== 'string') {
        throw new MeiliSearchError(`Meilisearch: The uid of the api key used for the token generation must exist, be of type string and comply to the uuid4 format.`);
    }
    if (!validateUuid4(uid)) {
        throw new MeiliSearchError(`Meilisearch: The uid of your key is not a valid uuid4. To find out the uid of your key use getKey().`);
    }
}
/**
 * Create the payload of the token.
 *
 * @param searchRules - Search rules that are applied to every search.
 * @param uid - The uid of the api key used as issuer of the token.
 * @param expiresAt - Date at which the token expires.
 * @returns The payload encoded in base64.
 */
function createPayload(payloadParams) {
    const { searchRules, uid, expiresAt } = payloadParams;
    const payload = {
        searchRules,
        apiKeyUid: uid,
        exp: expiresAt ? Math.floor(expiresAt.getTime() / 1000) : undefined,
    };
    return encode64(payload).replace(/=/g, '');
}
class Token {
    config;
    constructor(config) {
        this.config = config;
    }
    /**
     * Generate a tenant token
     *
     * @param apiKeyUid - The uid of the api key used as issuer of the token.
     * @param searchRules - Search rules that are applied to every search.
     * @param options - Token options to customize some aspect of the token.
     * @returns The token in JWT format.
     */
    async generateTenantToken(apiKeyUid, searchRules, options) {
        const apiKey = options?.apiKey || this.config.apiKey || '';
        const uid = apiKeyUid || '';
        const expiresAt = options?.expiresAt;
        validateTokenParameters({ apiKey, uid, expiresAt, searchRules });
        const encodedHeader = createHeader();
        const encodedPayload = createPayload({ searchRules, uid, expiresAt });
        const signature = await sign(apiKey, encodedHeader, encodedPayload);
        return `${encodedHeader}.${encodedPayload}.${signature}`;
    }
}

class MeiliSearch extends Client {
    tokens;
    constructor(config) {
        super(config);
        this.tokens = new Token(config);
    }
    /**
     * Generate a tenant token
     *
     * @param apiKeyUid - The uid of the api key used as issuer of the token.
     * @param searchRules - Search rules that are applied to every search.
     * @param options - Token options to customize some aspect of the token.
     * @returns The token in JWT format.
     */
    async generateTenantToken(apiKeyUid, searchRules, options) {
        if (typeof window === 'undefined') {
            return await this.tokens.generateTenantToken(apiKeyUid, searchRules, options);
        }
        return await super.generateTenantToken(apiKeyUid, searchRules, options);
    }
}

export { ContentTypeEnum, EnqueuedTask, ErrorStatusCode, Index, MatchingStrategies, MeiliSearch, MeiliSearchApiError, MeiliSearchCommunicationError, MeiliSearchError, MeiliSearchTimeOutError, MeiliSearch as Meilisearch, Task, TaskClient, TaskStatus, TaskTypes, MeiliSearch as default, httpErrorHandler, httpResponseErrorHandler, versionErrorHintMessage };
