UNPKG

meilisearch

Version:

The Meilisearch JS client for Node.js and the browser.

1 lines 137 kB
{"version":3,"file":"index.cjs","sources":["../../src/types/types.ts","../../src/errors/meilisearch-error.ts","../../src/errors/meilisearch-api-error.ts","../../src/errors/meilisearch-request-error.ts","../../src/errors/meilisearch-request-timeout-error.ts","../../src/errors/meilisearch-task-timeout-error.ts","../../src/package-version.ts","../../src/utils.ts","../../src/http-requests.ts","../../src/task.ts","../../src/indexes.ts","../../src/batch.ts","../../src/meilisearch.ts","../../src/index.ts"],"sourcesContent":["// Type definitions for meilisearch\n// Project: https://github.com/meilisearch/meilisearch-js\n// Definitions by: qdequele <quentin@meilisearch.com> <https://github.com/meilisearch>\n// Definitions: https://github.com/meilisearch/meilisearch-js\n// TypeScript Version: ^5.8.2\n\nimport type { WaitOptions } from \"./task_and_batch.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RecordAny = Record<string, any>;\n\n/**\n * Shape of allowed record object that can be appended to a\n * {@link URLSearchParams}.\n */\nexport type URLSearchParamsRecord = Record<\n string,\n | string\n | string[]\n | (string | string[])[]\n | number\n | number[]\n | boolean\n | Date\n | null\n | undefined\n>;\n\n/**\n * {@link RequestInit} without {@link RequestInit.body} and\n * {@link RequestInit.method} properties.\n */\nexport type ExtraRequestInit = Omit<RequestInit, \"body\" | \"method\">;\n\n/** Same as {@link ExtraRequestInit} but without {@link ExtraRequestInit.signal}. */\nexport type BaseRequestInit = Omit<ExtraRequestInit, \"signal\">;\n\n/**\n * Same as {@link BaseRequestInit} but with its headers property forced as a\n * {@link Headers} object.\n */\nexport type HttpRequestsRequestInit = Omit<BaseRequestInit, \"headers\"> & {\n headers: Headers;\n};\n\n/** Main configuration object for the meilisearch client. */\nexport type Config = {\n /**\n * The base URL for reaching a meilisearch instance.\n *\n * @remarks\n * Protocol and trailing slash can be omitted.\n */\n host: string;\n /**\n * API key for interacting with a meilisearch instance.\n *\n * @see {@link https://www.meilisearch.com/docs/learn/security/basic_security}\n */\n apiKey?: string;\n /**\n * Custom strings that will be concatted to the \"X-Meilisearch-Client\" header\n * on each request.\n */\n clientAgents?: string[];\n /** Base request options that may override the default ones. */\n requestInit?: BaseRequestInit;\n /**\n * Custom function that can be provided in place of {@link fetch}.\n *\n * @remarks\n * API response errors will have to be handled manually with this as well.\n * @deprecated This will be removed in a future version. See\n * {@link https://github.com/meilisearch/meilisearch-js/issues/1824 | issue}.\n */\n httpClient?: (...args: Parameters<typeof fetch>) => Promise<unknown>;\n /** Timeout in milliseconds for each HTTP request. */\n timeout?: number;\n /** Customizable default options for awaiting tasks. */\n defaultWaitOptions?: WaitOptions;\n};\n\n/** Main options of a request. */\nexport type MainRequestOptions = {\n /** The path or subpath of the URL to make a request to. */\n path: string;\n /** The REST method of the request. */\n method?: string;\n /** The search parameters of the URL. */\n params?: URLSearchParamsRecord;\n /**\n * {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type | Content-Type}\n * passed to request {@link Headers}.\n */\n contentType?: string;\n /**\n * The body of the request.\n *\n * @remarks\n * This only really supports string for now (any other type gets stringified)\n * but it could support more in the future.\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#body}\n */\n body?: string | boolean | number | object | null;\n /**\n * An extra, more limited {@link RequestInit}, that may override some of the\n * options.\n */\n extraRequestInit?: ExtraRequestInit;\n};\n\n/**\n * {@link MainRequestOptions} without {@link MainRequestOptions.method}, for\n * method functions.\n */\nexport type RequestOptions = Omit<MainRequestOptions, \"method\">;\n\n///\n/// Resources\n///\n\nexport type Pagination = {\n offset?: number;\n limit?: number;\n};\n\nexport type ResourceQuery = Pagination & {};\n\nexport type ResourceResults<T> = Pagination & {\n results: T;\n total: number;\n};\n\n///\n/// Indexes\n///\n\nexport type IndexOptions = {\n primaryKey?: string;\n};\n\nexport type IndexObject = {\n uid: string;\n primaryKey?: string;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type IndexesQuery = ResourceQuery & {};\n\nexport type IndexesResults<T> = ResourceResults<T> & {};\n\n/*\n * SEARCH PARAMETERS\n */\n\nexport const MatchingStrategies = {\n ALL: \"all\",\n LAST: \"last\",\n FREQUENCY: \"frequency\",\n} as const;\n\nexport type MatchingStrategies =\n (typeof MatchingStrategies)[keyof typeof MatchingStrategies];\n\nexport type Filter = string | (string | string[])[];\n\nexport type Query = {\n q?: string | null;\n};\n\nexport type Highlight = {\n attributesToHighlight?: string[];\n highlightPreTag?: string;\n highlightPostTag?: string;\n};\n\nexport type Crop = {\n attributesToCrop?: string[];\n cropLength?: number;\n cropMarker?: string;\n};\n\n// `facetName` becomes mandatory when using `searchForFacetValues`\nexport type SearchForFacetValuesParams = Omit<SearchParams, \"facetName\"> & {\n facetName: string;\n /**\n * If true, the facet search will return the exhaustive count of the facet\n * values.\n */\n exhaustiveFacetCount?: boolean;\n};\n\nexport type FacetHit = {\n value: string;\n count: number;\n};\n\nexport type SearchForFacetValuesResponse = {\n facetHits: FacetHit[];\n facetQuery: string | null;\n processingTimeMs: number;\n};\n\nexport type HybridSearch = {\n embedder: string;\n semanticRatio?: number;\n};\n\n// https://www.meilisearch.com/docs/reference/api/settings#localized-attributes\nexport type Locale = string;\n\nexport type SearchParams = Query &\n Pagination &\n Highlight &\n Crop & {\n filter?: Filter;\n sort?: string[];\n facets?: string[];\n attributesToRetrieve?: string[];\n showMatchesPosition?: boolean;\n matchingStrategy?: MatchingStrategies;\n hitsPerPage?: number;\n page?: number;\n facetName?: string;\n facetQuery?: string;\n vector?: number[] | null;\n showRankingScore?: boolean;\n showRankingScoreDetails?: boolean;\n rankingScoreThreshold?: number;\n attributesToSearchOn?: string[] | null;\n hybrid?: HybridSearch;\n distinct?: string;\n retrieveVectors?: boolean;\n locales?: Locale[];\n };\n\n// Search parameters for searches made with the GET method\n// Are different than the parameters for the POST method\nexport type SearchRequestGET = Pagination &\n Query &\n Omit<Highlight, \"attributesToHighlight\"> &\n Omit<Crop, \"attributesToCrop\"> & {\n filter?: string;\n sort?: string;\n facets?: string;\n attributesToRetrieve?: string;\n attributesToHighlight?: string;\n attributesToCrop?: string;\n showMatchesPosition?: boolean;\n vector?: string | null;\n attributesToSearchOn?: string | null;\n hybridEmbedder?: string;\n hybridSemanticRatio?: number;\n rankingScoreThreshold?: number;\n distinct?: string;\n retrieveVectors?: boolean;\n locales?: Locale[];\n };\n\nexport type MergeFacets = {\n maxValuesPerFacet?: number | null;\n};\n\nexport type FederationOptions = { weight: number; remote?: string };\nexport type MultiSearchFederation = {\n limit?: number;\n offset?: number;\n facetsByIndex?: Record<string, string[]>;\n mergeFacets?: MergeFacets | null;\n};\n\nexport type MultiSearchQuery = SearchParams & { indexUid: string };\nexport type MultiSearchQueryWithFederation = MultiSearchQuery & {\n federationOptions?: FederationOptions;\n};\n\nexport type MultiSearchParams = {\n queries: MultiSearchQuery[];\n};\nexport type FederatedMultiSearchParams = {\n federation: MultiSearchFederation;\n queries: MultiSearchQueryWithFederation[];\n};\n\n/**\n * {@link https://www.meilisearch.com/docs/reference/api/network#the-remote-object}\n *\n * @see `meilisearch_types::features::Remote` at {@link https://github.com/meilisearch/meilisearch}\n */\nexport type Remote = {\n url: string;\n searchApiKey: string | null;\n};\n\n/**\n * {@link https://www.meilisearch.com/docs/reference/api/network#the-network-object}\n *\n * @see `meilisearch_types::features::Network` at {@link https://github.com/meilisearch/meilisearch}\n */\nexport type Network = {\n self: string | null;\n remotes: Record<string, Remote>;\n};\n\nexport type CategoriesDistribution = {\n [category: string]: number;\n};\n\nexport type Facet = string;\nexport type FacetDistribution = Record<Facet, CategoriesDistribution>;\nexport type MatchesPosition<T> = Partial<\n Record<keyof T, { start: number; length: number; indices?: number[] }[]>\n>;\n\nexport type RankingScoreDetails = {\n words?: {\n order: number;\n matchingWords: number;\n maxMatchingWords: number;\n score: number;\n };\n typo?: {\n order: number;\n typoCount: number;\n maxTypoCount: number;\n score: number;\n };\n proximity?: {\n order: number;\n score: number;\n };\n attribute?: {\n order: number;\n attributes_ranking_order: number;\n attributes_query_word_order: number;\n score: number;\n };\n exactness?: {\n order: number;\n matchType: string;\n score: number;\n };\n [key: string]: RecordAny | undefined;\n};\n\nexport type FederationDetails = {\n indexUid: string;\n queriesPosition: number;\n weightedRankingScore: number;\n};\n\nexport type Hit<T = RecordAny> = T & {\n _formatted?: Partial<T>;\n _matchesPosition?: MatchesPosition<T>;\n _rankingScore?: number;\n _rankingScoreDetails?: RankingScoreDetails;\n _federation?: FederationDetails;\n};\n\nexport type Hits<T = RecordAny> = Hit<T>[];\n\nexport type FacetStat = { min: number; max: number };\nexport type FacetStats = Record<string, FacetStat>;\n\nexport type FacetsByIndex = Record<\n string,\n {\n distribution: FacetDistribution;\n stats: FacetStats;\n }\n>;\n\nexport type SearchResponse<\n T = RecordAny,\n S extends SearchParams | undefined = undefined,\n> = {\n hits: Hits<T>;\n processingTimeMs: number;\n query: string;\n facetDistribution?: FacetDistribution;\n facetStats?: FacetStats;\n facetsByIndex?: FacetsByIndex;\n} & (undefined extends S\n ? Partial<FinitePagination & InfinitePagination>\n : true extends IsFinitePagination<NonNullable<S>>\n ? FinitePagination\n : InfinitePagination);\n\ntype FinitePagination = {\n totalHits: number;\n hitsPerPage: number;\n page: number;\n totalPages: number;\n};\ntype InfinitePagination = {\n offset: number;\n limit: number;\n estimatedTotalHits: number;\n};\n\ntype IsFinitePagination<S extends SearchParams> = Or<\n HasHitsPerPage<S>,\n HasPage<S>\n>;\n\ntype Or<A extends boolean, B extends boolean> = true extends A\n ? true\n : true extends B\n ? true\n : false;\n\ntype HasHitsPerPage<S extends SearchParams> = undefined extends S[\"hitsPerPage\"]\n ? false\n : true;\n\ntype HasPage<S extends SearchParams> = undefined extends S[\"page\"]\n ? false\n : true;\n\nexport type MultiSearchResult<T> = SearchResponse<T> & { indexUid: string };\n\nexport type MultiSearchResponse<T = RecordAny> = {\n results: MultiSearchResult<T>[];\n};\n\nexport type MultiSearchResponseOrSearchResponse<\n T1 extends FederatedMultiSearchParams | MultiSearchParams,\n T2 extends RecordAny = RecordAny,\n> = T1 extends FederatedMultiSearchParams\n ? SearchResponse<T2>\n : MultiSearchResponse<T2>;\n\nexport type FieldDistribution = {\n [field: string]: number;\n};\n\nexport type SearchSimilarDocumentsParams = {\n id: string | number;\n offset?: number;\n limit?: number;\n filter?: Filter;\n embedder?: string;\n attributesToRetrieve?: string[];\n showRankingScore?: boolean;\n showRankingScoreDetails?: boolean;\n rankingScoreThreshold?: number;\n};\n\n/*\n ** Documents\n */\n\ntype Fields<T = RecordAny> =\n | Extract<keyof T, string>[]\n | Extract<keyof T, string>;\n\nexport type DocumentOptions = {\n primaryKey?: string;\n};\n\nexport const ContentTypeEnum: Readonly<Record<string, ContentType>> = {\n JSON: \"application/json\",\n CSV: \"text/csv\",\n NDJSON: \"application/x-ndjson\",\n};\n\nexport type ContentType =\n | \"text/csv\"\n | \"application/x-ndjson\"\n | \"application/json\";\n\nexport type RawDocumentAdditionOptions = DocumentOptions & {\n csvDelimiter?: string;\n};\n\nexport type DocumentsQuery<T = RecordAny> = ResourceQuery & {\n ids?: string[] | number[];\n fields?: Fields<T>;\n filter?: Filter;\n limit?: number;\n offset?: number;\n retrieveVectors?: boolean;\n};\n\nexport type DocumentQuery<T = RecordAny> = {\n fields?: Fields<T>;\n};\n\nexport type DocumentsDeletionQuery = {\n filter: Filter;\n};\n\nexport type DocumentsIds = string[] | number[];\n\nexport type UpdateDocumentsByFunctionOptions = {\n function: string;\n filter?: string | string[];\n context?: RecordAny;\n};\n\n/*\n ** Settings\n */\n\nexport type GranularFilterableAttribute = {\n attributePatterns: string[];\n features: {\n facetSearch: boolean;\n filter: { equality: boolean; comparison: boolean };\n };\n};\n\nexport type FilterableAttributes =\n | (string | GranularFilterableAttribute)[]\n | null;\nexport type DistinctAttribute = string | null;\nexport type SearchableAttributes = string[] | null;\nexport type SortableAttributes = string[] | null;\nexport type DisplayedAttributes = string[] | null;\nexport type RankingRules = string[] | null;\nexport type StopWords = string[] | null;\nexport type Synonyms = Record<string, string[]> | null;\nexport type TypoTolerance = {\n enabled?: boolean | null;\n disableOnAttributes?: string[] | null;\n disableOnNumbers?: boolean | null;\n disableOnWords?: string[] | null;\n minWordSizeForTypos?: {\n oneTypo?: number | null;\n twoTypos?: number | null;\n };\n} | null;\nexport type SeparatorTokens = string[] | null;\nexport type NonSeparatorTokens = string[] | null;\nexport type Dictionary = string[] | null;\nexport type ProximityPrecision = \"byWord\" | \"byAttribute\";\n\nexport type Distribution = {\n mean: number;\n sigma: number;\n};\n\nexport type OpenAiEmbedder = {\n source: \"openAi\";\n model?: string;\n apiKey?: string;\n documentTemplate?: string;\n dimensions?: number;\n distribution?: Distribution;\n url?: string;\n documentTemplateMaxBytes?: number;\n binaryQuantized?: boolean;\n};\n\nexport type HuggingFaceEmbedder = {\n source: \"huggingFace\";\n model?: string;\n revision?: string;\n documentTemplate?: string;\n distribution?: Distribution;\n pooling?: \"useModel\" | \"forceMean\" | \"forceCls\";\n documentTemplateMaxBytes?: number;\n binaryQuantized?: boolean;\n};\n\nexport type UserProvidedEmbedder = {\n source: \"userProvided\";\n dimensions: number;\n distribution?: Distribution;\n binaryQuantized?: boolean;\n};\n\nexport type RestEmbedder = {\n source: \"rest\";\n url: string;\n apiKey?: string;\n dimensions?: number;\n documentTemplate?: string;\n distribution?: Distribution;\n request: RecordAny;\n response: RecordAny;\n headers?: Record<string, string>;\n documentTemplateMaxBytes?: number;\n binaryQuantized?: boolean;\n};\n\nexport type OllamaEmbedder = {\n source: \"ollama\";\n url?: string;\n apiKey?: string;\n model?: string;\n documentTemplate?: string;\n distribution?: Distribution;\n dimensions?: number;\n documentTemplateMaxBytes?: number;\n binaryQuantized?: boolean;\n};\n\nexport type CompositeEmbedder = {\n source: \"composite\";\n searchEmbedder: Embedder;\n indexingEmbedder: Embedder;\n};\n\nexport type Embedder =\n | OpenAiEmbedder\n | HuggingFaceEmbedder\n | UserProvidedEmbedder\n | RestEmbedder\n | OllamaEmbedder\n | CompositeEmbedder\n | null;\n\nexport type Embedders = Record<string, Embedder> | null;\n\nexport type FacetOrder = \"alpha\" | \"count\";\n\nexport type Faceting = {\n maxValuesPerFacet?: number | null;\n sortFacetValuesBy?: Record<string, FacetOrder> | null;\n};\n\nexport type PaginationSettings = {\n maxTotalHits?: number | null;\n};\n\nexport type SearchCutoffMs = number | null;\n\nexport type LocalizedAttribute = {\n attributePatterns: string[];\n locales: Locale[];\n};\n\nexport type LocalizedAttributes = LocalizedAttribute[] | null;\n\nexport type PrefixSearch = \"indexingTime\" | \"disabled\";\n\nexport type Settings = {\n filterableAttributes?: FilterableAttributes;\n distinctAttribute?: DistinctAttribute;\n sortableAttributes?: SortableAttributes;\n searchableAttributes?: SearchableAttributes;\n displayedAttributes?: DisplayedAttributes;\n rankingRules?: RankingRules;\n stopWords?: StopWords;\n synonyms?: Synonyms;\n typoTolerance?: TypoTolerance;\n faceting?: Faceting;\n pagination?: PaginationSettings;\n separatorTokens?: SeparatorTokens;\n nonSeparatorTokens?: NonSeparatorTokens;\n dictionary?: Dictionary;\n proximityPrecision?: ProximityPrecision;\n embedders?: Embedders;\n searchCutoffMs?: SearchCutoffMs;\n localizedAttributes?: LocalizedAttributes;\n\n /**\n * Enable facet searching on all the filters of an index (requires Meilisearch\n * 1.12.0 or later)\n */\n facetSearch?: boolean;\n /**\n * Enable the ability to search a word by prefix on an index (requires\n * Meilisearch 1.12.0 or later)\n */\n prefixSearch?: \"indexingTime\" | \"disabled\";\n};\n\n/*\n *** HEALTH\n */\n\nexport type Health = {\n status: \"available\";\n};\n\n/*\n *** STATS\n */\n\nexport type IndexStats = {\n numberOfDocuments: number;\n isIndexing: boolean;\n fieldDistribution: FieldDistribution;\n numberOfEmbeddedDocuments: number;\n numberOfEmbeddings: number;\n rawDocumentDbSize: number;\n avgDocumentSize: number;\n};\n\nexport type Stats = {\n databaseSize: number;\n usedDatabaseSize: number;\n lastUpdate: string;\n indexes: {\n [index: string]: IndexStats;\n };\n};\n\n/*\n ** Keys\n */\n\nexport type Key = {\n uid: string;\n description: string;\n name: string | null;\n key: string;\n actions: string[];\n indexes: string[];\n expiresAt: Date;\n createdAt: Date;\n updatedAt: Date;\n};\n\nexport type KeyCreation = {\n uid?: string;\n name?: string;\n description?: string;\n actions: string[];\n indexes: string[];\n expiresAt: Date | null;\n};\n\nexport type KeyUpdate = {\n name?: string;\n description?: string;\n};\n\nexport type KeysQuery = ResourceQuery & {};\n\nexport type KeysResults = ResourceResults<Key[]> & {};\n\n/*\n ** version\n */\nexport type Version = {\n commitSha: string;\n commitDate: string;\n pkgVersion: string;\n};\n\n/*\n ** ERROR HANDLER\n */\n\nexport interface FetchError extends Error {\n type: string;\n errno: string;\n code: string;\n}\n\nexport type MeiliSearchErrorResponse = {\n message: string;\n // https://www.meilisearch.com/docs/reference/errors/error_codes\n code: string;\n // https://www.meilisearch.com/docs/reference/errors/overview#errors\n type: string;\n link: string;\n};\n\n// @TODO: This doesn't seem to be up to date, and its usefulness comes into question.\nexport const ErrorStatusCode = {\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_creation_failed */\n INDEX_CREATION_FAILED: \"index_creation_failed\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_index_uid */\n MISSING_INDEX_UID: \"missing_index_uid\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_already_exists */\n INDEX_ALREADY_EXISTS: \"index_already_exists\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_not_found */\n INDEX_NOT_FOUND: \"index_not_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_uid */\n INVALID_INDEX_UID: \"invalid_index_uid\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_not_accessible */\n INDEX_NOT_ACCESSIBLE: \"index_not_accessible\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_offset */\n INVALID_INDEX_OFFSET: \"invalid_index_offset\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_limit */\n INVALID_INDEX_LIMIT: \"invalid_index_limit\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_state */\n INVALID_STATE: \"invalid_state\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#primary_key_inference_failed */\n PRIMARY_KEY_INFERENCE_FAILED: \"primary_key_inference_failed\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#index_primary_key_already_exists */\n INDEX_PRIMARY_KEY_ALREADY_EXISTS: \"index_primary_key_already_exists\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_index_primary_key */\n INVALID_INDEX_PRIMARY_KEY: \"invalid_index_primary_key\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#max_fields_limit_exceeded */\n DOCUMENTS_FIELDS_LIMIT_REACHED: \"document_fields_limit_reached\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_id */\n MISSING_DOCUMENT_ID: \"missing_document_id\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_id */\n INVALID_DOCUMENT_ID: \"invalid_document_id\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_content_type */\n INVALID_CONTENT_TYPE: \"invalid_content_type\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_content_type */\n MISSING_CONTENT_TYPE: \"missing_content_type\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_fields */\n INVALID_DOCUMENT_FIELDS: \"invalid_document_fields\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_limit */\n INVALID_DOCUMENT_LIMIT: \"invalid_document_limit\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_offset */\n INVALID_DOCUMENT_OFFSET: \"invalid_document_offset\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_filter */\n INVALID_DOCUMENT_FILTER: \"invalid_document_filter\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_filter */\n MISSING_DOCUMENT_FILTER: \"missing_document_filter\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_vectors_field */\n INVALID_DOCUMENT_VECTORS_FIELD: \"invalid_document_vectors_field\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#payload_too_large */\n PAYLOAD_TOO_LARGE: \"payload_too_large\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_payload */\n MISSING_PAYLOAD: \"missing_payload\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#malformed_payload */\n MALFORMED_PAYLOAD: \"malformed_payload\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#no_space_left_on_device */\n NO_SPACE_LEFT_ON_DEVICE: \"no_space_left_on_device\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_store_file */\n INVALID_STORE_FILE: \"invalid_store_file\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_ranking_rules */\n INVALID_RANKING_RULES: \"missing_document_id\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_request */\n INVALID_REQUEST: \"invalid_request\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_geo_field */\n INVALID_DOCUMENT_GEO_FIELD: \"invalid_document_geo_field\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_q */\n INVALID_SEARCH_Q: \"invalid_search_q\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_offset */\n INVALID_SEARCH_OFFSET: \"invalid_search_offset\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_limit */\n INVALID_SEARCH_LIMIT: \"invalid_search_limit\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_page */\n INVALID_SEARCH_PAGE: \"invalid_search_page\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_hits_per_page */\n INVALID_SEARCH_HITS_PER_PAGE: \"invalid_search_hits_per_page\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_retrieve */\n INVALID_SEARCH_ATTRIBUTES_TO_RETRIEVE:\n \"invalid_search_attributes_to_retrieve\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_crop */\n INVALID_SEARCH_ATTRIBUTES_TO_CROP: \"invalid_search_attributes_to_crop\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_crop_length */\n INVALID_SEARCH_CROP_LENGTH: \"invalid_search_crop_length\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_highlight */\n INVALID_SEARCH_ATTRIBUTES_TO_HIGHLIGHT:\n \"invalid_search_attributes_to_highlight\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_show_matches_position */\n INVALID_SEARCH_SHOW_MATCHES_POSITION: \"invalid_search_show_matches_position\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_filter */\n INVALID_SEARCH_FILTER: \"invalid_search_filter\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_sort */\n INVALID_SEARCH_SORT: \"invalid_search_sort\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_facets */\n INVALID_SEARCH_FACETS: \"invalid_search_facets\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_highlight_pre_tag */\n INVALID_SEARCH_HIGHLIGHT_PRE_TAG: \"invalid_search_highlight_pre_tag\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_highlight_post_tag */\n INVALID_SEARCH_HIGHLIGHT_POST_TAG: \"invalid_search_highlight_post_tag\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_crop_marker */\n INVALID_SEARCH_CROP_MARKER: \"invalid_search_crop_marker\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_matching_strategy */\n INVALID_SEARCH_MATCHING_STRATEGY: \"invalid_search_matching_strategy\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_vector */\n INVALID_SEARCH_VECTOR: \"invalid_search_vector\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_search_on */\n INVALID_SEARCH_ATTRIBUTES_TO_SEARCH_ON:\n \"invalid_search_attributes_to_search_on\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#bad_request */\n BAD_REQUEST: \"bad_request\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#document_not_found */\n DOCUMENT_NOT_FOUND: \"document_not_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#internal */\n INTERNAL: \"internal\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key */\n INVALID_API_KEY: \"invalid_api_key\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_description */\n INVALID_API_KEY_DESCRIPTION: \"invalid_api_key_description\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_actions */\n INVALID_API_KEY_ACTIONS: \"invalid_api_key_actions\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_indexes */\n INVALID_API_KEY_INDEXES: \"invalid_api_key_indexes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_expires_at */\n INVALID_API_KEY_EXPIRES_AT: \"invalid_api_key_expires_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#api_key_not_found */\n API_KEY_NOT_FOUND: \"api_key_not_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_uid */\n IMMUTABLE_API_KEY_UID: \"immutable_api_key_uid\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_actions */\n IMMUTABLE_API_KEY_ACTIONS: \"immutable_api_key_actions\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_indexes */\n IMMUTABLE_API_KEY_INDEXES: \"immutable_api_key_indexes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_expires_at */\n IMMUTABLE_API_KEY_EXPIRES_AT: \"immutable_api_key_expires_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_created_at */\n IMMUTABLE_API_KEY_CREATED_AT: \"immutable_api_key_created_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_api_key_updated_at */\n IMMUTABLE_API_KEY_UPDATED_AT: \"immutable_api_key_updated_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_authorization_header */\n MISSING_AUTHORIZATION_HEADER: \"missing_authorization_header\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#unretrievable_document */\n UNRETRIEVABLE_DOCUMENT: \"unretrievable_document\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#database_size_limit_reached */\n MAX_DATABASE_SIZE_LIMIT_REACHED: \"database_size_limit_reached\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#task_not_found */\n TASK_NOT_FOUND: \"task_not_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#dump_process_failed */\n DUMP_PROCESS_FAILED: \"dump_process_failed\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#dump_not_found */\n DUMP_NOT_FOUND: \"dump_not_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_swap_duplicate_index_found */\n INVALID_SWAP_DUPLICATE_INDEX_FOUND: \"invalid_swap_duplicate_index_found\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_swap_indexes */\n INVALID_SWAP_INDEXES: \"invalid_swap_indexes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_swap_indexes */\n MISSING_SWAP_INDEXES: \"missing_swap_indexes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_master_key */\n MISSING_MASTER_KEY: \"missing_master_key\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_types */\n INVALID_TASK_TYPES: \"invalid_task_types\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_uids */\n INVALID_TASK_UIDS: \"invalid_task_uids\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_statuses */\n INVALID_TASK_STATUSES: \"invalid_task_statuses\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_limit */\n INVALID_TASK_LIMIT: \"invalid_task_limit\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_from */\n INVALID_TASK_FROM: \"invalid_task_from\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_canceled_by */\n INVALID_TASK_CANCELED_BY: \"invalid_task_canceled_by\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_task_filters */\n MISSING_TASK_FILTERS: \"missing_task_filters\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#too_many_open_files */\n TOO_MANY_OPEN_FILES: \"too_many_open_files\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#io_error */\n IO_ERROR: \"io_error\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_index_uids */\n INVALID_TASK_INDEX_UIDS: \"invalid_task_index_uids\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_uid */\n IMMUTABLE_INDEX_UID: \"immutable_index_uid\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_created_at */\n IMMUTABLE_INDEX_CREATED_AT: \"immutable_index_created_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#immutable_index_updated_at */\n IMMUTABLE_INDEX_UPDATED_AT: \"immutable_index_updated_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_displayed_attributes */\n INVALID_SETTINGS_DISPLAYED_ATTRIBUTES:\n \"invalid_settings_displayed_attributes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_searchable_attributes */\n INVALID_SETTINGS_SEARCHABLE_ATTRIBUTES:\n \"invalid_settings_searchable_attributes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_filterable_attributes */\n INVALID_SETTINGS_FILTERABLE_ATTRIBUTES:\n \"invalid_settings_filterable_attributes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_sortable_attributes */\n INVALID_SETTINGS_SORTABLE_ATTRIBUTES: \"invalid_settings_sortable_attributes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_ranking_rules */\n INVALID_SETTINGS_RANKING_RULES: \"invalid_settings_ranking_rules\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_stop_words */\n INVALID_SETTINGS_STOP_WORDS: \"invalid_settings_stop_words\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_synonyms */\n INVALID_SETTINGS_SYNONYMS: \"invalid_settings_synonyms\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_distinct_attribute */\n INVALID_SETTINGS_DISTINCT_ATTRIBUTE: \"invalid_settings_distinct_attribute\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_typo_tolerance */\n INVALID_SETTINGS_TYPO_TOLERANCE: \"invalid_settings_typo_tolerance\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_faceting */\n INVALID_SETTINGS_FACETING: \"invalid_settings_faceting\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_pagination */\n INVALID_SETTINGS_PAGINATION: \"invalid_settings_pagination\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_search_cutoff_ms */\n INVALID_SETTINGS_SEARCH_CUTOFF_MS: \"invalid_settings_search_cutoff_ms\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_settings_search_cutoff_ms */\n INVALID_SETTINGS_LOCALIZED_ATTRIBUTES:\n \"invalid_settings_localized_attributes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_enqueued_at */\n INVALID_TASK_BEFORE_ENQUEUED_AT: \"invalid_task_before_enqueued_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_enqueued_at */\n INVALID_TASK_AFTER_ENQUEUED_AT: \"invalid_task_after_enqueued_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_started_at */\n INVALID_TASK_BEFORE_STARTED_AT: \"invalid_task_before_started_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_started_at */\n INVALID_TASK_AFTER_STARTED_AT: \"invalid_task_after_started_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_before_finished_at */\n INVALID_TASK_BEFORE_FINISHED_AT: \"invalid_task_before_finished_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_task_after_finished_at */\n INVALID_TASK_AFTER_FINISHED_AT: \"invalid_task_after_finished_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_actions */\n MISSING_API_KEY_ACTIONS: \"missing_api_key_actions\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_indexes */\n MISSING_API_KEY_INDEXES: \"missing_api_key_indexes\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_api_key_expires_at */\n MISSING_API_KEY_EXPIRES_AT: \"missing_api_key_expires_at\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_limit */\n INVALID_API_KEY_LIMIT: \"invalid_api_key_limit\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_offset */\n INVALID_API_KEY_OFFSET: \"invalid_api_key_offset\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_name */\n INVALID_FACET_SEARCH_FACET_NAME: \"invalid_facet_search_facet_name\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_facet_search_facet_name */\n MISSING_FACET_SEARCH_FACET_NAME: \"missing_facet_search_facet_name\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_query */\n INVALID_FACET_SEARCH_FACET_QUERY: \"invalid_facet_search_facet_query\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_ranking_score_threshold */\n INVALID_SEARCH_RANKING_SCORE_THRESHOLD:\n \"invalid_search_ranking_score_threshold\",\n\n /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_similar_ranking_score_threshold */\n INVALID_SIMILAR_RANKING_SCORE_THRESHOLD:\n \"invalid_similar_ranking_score_threshold\",\n};\n\nexport type ErrorStatusCode =\n (typeof ErrorStatusCode)[keyof typeof ErrorStatusCode];\n","export class MeiliSearchError extends Error {\n override name = \"MeiliSearchError\";\n}\n","import type { MeiliSearchErrorResponse } from \"../types/index.js\";\nimport { MeiliSearchError } from \"./meilisearch-error.js\";\n\nexport class MeiliSearchApiError extends MeiliSearchError {\n override name = \"MeiliSearchApiError\";\n override cause?: MeiliSearchErrorResponse;\n readonly response: Response;\n\n constructor(response: Response, responseBody?: MeiliSearchErrorResponse) {\n super(\n responseBody?.message ?? `${response.status}: ${response.statusText}`,\n );\n\n this.response = response;\n\n if (responseBody !== undefined) {\n this.cause = responseBody;\n }\n }\n}\n","import { MeiliSearchError } from \"./meilisearch-error.js\";\n\nexport class MeiliSearchRequestError extends MeiliSearchError {\n override name = \"MeiliSearchRequestError\";\n\n constructor(url: string, cause: unknown) {\n super(`Request to ${url} has failed`, { cause });\n }\n}\n","import { MeiliSearchError } from \"./meilisearch-error.js\";\n\n/** Error thrown when a HTTP request times out. */\nexport class MeiliSearchRequestTimeOutError extends MeiliSearchError {\n override name = \"MeiliSearchRequestTimeOutError\";\n override cause: { timeout: number; requestInit: RequestInit };\n\n constructor(timeout: number, requestInit: RequestInit) {\n super(`request timed out after ${timeout}ms`);\n\n this.cause = { timeout, requestInit };\n }\n}\n","import { MeiliSearchError } from \"./meilisearch-error.js\";\n\n/** Error thrown when a waiting for a task times out. */\nexport class MeiliSearchTaskTimeOutError extends MeiliSearchError {\n override name = \"MeiliSearchTaskTimeOutError\";\n override cause: { taskUid: number; timeout: number };\n\n constructor(taskUid: number, timeout: number) {\n super(\n `timeout of ${timeout}ms has exceeded on task ${taskUid} when waiting for it to be resolved.`,\n );\n\n this.cause = { taskUid, timeout };\n }\n}\n","export const PACKAGE_VERSION = \"0.51.0\";\n","async function sleep(ms: number): Promise<void> {\n return await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction addProtocolIfNotPresent(host: string): string {\n if (!(host.startsWith(\"https://\") || host.startsWith(\"http://\"))) {\n return `http://${host}`;\n }\n return host;\n}\n\nfunction addTrailingSlash(url: string): string {\n if (!url.endsWith(\"/\")) {\n url += \"/\";\n }\n return url;\n}\n\nexport { sleep, addProtocolIfNotPresent, addTrailingSlash };\n","import type {\n Config,\n HttpRequestsRequestInit,\n RequestOptions,\n MainRequestOptions,\n URLSearchParamsRecord,\n MeiliSearchErrorResponse,\n} from \"./types/index.js\";\nimport { PACKAGE_VERSION } from \"./package-version.js\";\nimport {\n MeiliSearchError,\n MeiliSearchApiError,\n MeiliSearchRequestError,\n MeiliSearchRequestTimeOutError,\n} from \"./errors/index.js\";\nimport { addProtocolIfNotPresent, addTrailingSlash } from \"./utils.js\";\n\n/** Append a set of key value pairs to a {@link URLSearchParams} object. */\nfunction appendRecordToURLSearchParams(\n searchParams: URLSearchParams,\n recordToAppend: URLSearchParamsRecord,\n): void {\n for (const [key, val] of Object.entries(recordToAppend)) {\n if (val != null) {\n searchParams.set(\n key,\n Array.isArray(val)\n ? val.join()\n : val instanceof Date\n ? val.toISOString()\n : String(val),\n );\n }\n }\n}\n\n/**\n * Creates a new Headers object from a {@link HeadersInit} and adds various\n * properties to it, some from {@link Config}.\n *\n * @returns A new Headers object\n */\nfunction getHeaders(config: Config, headersInit?: HeadersInit): Headers {\n const agentHeader = \"X-Meilisearch-Client\";\n const packageAgent = `Meilisearch JavaScript (v${PACKAGE_VERSION})`;\n const contentType = \"Content-Type\";\n const authorization = \"Authorization\";\n\n const headers = new Headers(headersInit);\n\n // do not override if user provided the header\n if (config.apiKey && !headers.has(authorization)) {\n headers.set(authorization, `Bearer ${config.apiKey}`);\n }\n\n if (!headers.has(contentType)) {\n headers.set(contentType, \"application/json\");\n }\n\n // Creates the custom user agent with information on the package used.\n if (config.clientAgents !== undefined) {\n const clients = config.clientAgents.concat(packageAgent);\n\n headers.set(agentHeader, clients.join(\" ; \"));\n } else {\n headers.set(agentHeader, packageAgent);\n }\n\n return headers;\n}\n\n/** Used to identify whether an error is a timeout error after fetch request. */\nconst TIMEOUT_ID = Symbol(\"<timeout>\");\n\n/**\n * Attach a timeout signal to a {@link RequestInit}, while preserving original\n * signal functionality, if there is one.\n *\n * @remarks\n * This could be a short few straight forward lines using {@link AbortSignal.any}\n * and {@link AbortSignal.timeout}, but these aren't yet widely supported enough,\n * nor polyfill -able, at the time of writing.\n * @returns A new function which starts the timeout, which then returns another\n * function that clears the timeout\n */\nfunction getTimeoutFn(\n requestInit: RequestInit,\n ms: number,\n): () => (() => void) | void {\n const { signal } = requestInit;\n const ac = new AbortController();\n\n if (signal != null) {\n let acSignalFn: (() => void) | null = null;\n\n if (signal.aborted) {\n ac.abort(signal.reason);\n } else {\n const fn = () => ac.abort(signal.reason);\n\n signal.addEventListener(\"abort\", fn, { once: true });\n\n acSignalFn = () => signal.removeEventListener(\"abort\", fn);\n ac.signal.addEventListener(\"abort\", acSignalFn, { once: true });\n }\n\n return () => {\n if (signal.aborted) {\n return;\n }\n\n const to = setTimeout(() => ac.abort(TIMEOUT_ID), ms);\n const fn = () => {\n clearTimeout(to);\n\n if (acSignalFn !== null) {\n ac.signal.removeEventListener(\"abort\", acSignalFn);\n }\n };\n\n signal.addEventListener(\"abort\", fn, { once: true });\n\n return () => {\n signal.removeEventListener(\"abort\", fn);\n fn();\n };\n };\n }\n\n requestInit.signal = ac.signal;\n\n return () => {\n const to = setTimeout(() => ac.abort(TIMEOUT_ID), ms);\n return () => clearTimeout(to);\n };\n}\n\n/** Class used to perform HTTP requests. */\nexport class HttpRequests {\n #url: URL;\n #requestInit: HttpRequestsRequestInit;\n #customRequestFn?: Config[\"httpClient\"];\n #requestTimeout?: Config[\"timeout\"];\n\n constructor(config: Config) {\n const host = addTrailingSlash(addProtocolIfNotPresent(config.host));\n\n try {\n this.#url = new URL(host);\n } catch (error) {\n throw new MeiliSearchError(\"The provided host is not valid\", {\n cause: error,\n });\n }\n\n this.#requestInit = {\n ...config.requestInit,\n headers: getHeaders(config, config.requestInit?.headers),\n };\n\n this.#customRequestFn = config.httpClient;\n this.#requestTimeout = config.timeout;\n }\n\n /**\n * Combines provided extra {@link RequestInit} headers, provided content type\n * and class instance RequestInit headers, prioritizing them in this order.\n *\n * @returns A new Headers object or the main headers of this class if no\n * headers are provided\n */\n #getHeaders(extraHeaders?: HeadersInit, contentType?: string): Headers {\n if (extraHeaders === undefined && contentType === undefined) {\n return this.#requestInit.headers;\n }\n\n const headers = new Headers(extraHeaders);\n\n if (contentType !== undefined && !headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", contentType);\n }\n\n for (const [key, val] of this.#requestInit.headers) {\n if (!headers.has(key)) {\n headers.set(key, val);\n }\n }\n\n return headers;\n }\n\n /**\n * Sends a request with {@link fetch} or a custom HTTP client, combining\n * parameters and class properties.\n *\n * @returns A promise containing the response\n */\n async #request<T = unknown>({\n path,\n method,\n params,\n contentType,\n body,\n extraRequestInit,\n }: MainRequestOptions): Promise<T> {\n const url = new URL(path, this.#url);\n if (params !== undefined) {\n appendRecordToURLSearchParams(url.searchParams, params);\n }\n\n const init: RequestInit = {\n method,\n body:\n contentType === undefined || typeof body !== \"string\"\n ? JSON.stringify(body)\n : body,\n ...extraRequestInit,\n ...this.#requestInit,\n headers: this.#getHeaders(extraRequestInit?.headers, contentType),\n };\n\n const startTimeout =\n this.#requestTimeout !== undefined\n ? getTimeoutFn(init, this.#requestTimeout)\n : null;\n\n const stopTimeout = startTimeout?.();\n\n let response: Response;\n let responseBody: string;\n try {\n if (this.#customRequestFn !== undefined) {\n // When using a custom HTTP client, the response should already be handled and ready to be returned\n return (await this.#customRequestFn(url, init)) as T;\n }\n\n response = await fetch(url, init);\n responseBody = await response.text();\n } catch (error) {\n throw new MeiliSearchRequestError(\n url.toString(),\n Object.is(error, TIMEOUT_ID)\n ? new MeiliSearchRequestTimeOutError(this.#requestTimeout!, init)\n : error,\n );\n } finally {\n stopTimeout?.();\n }\n\n const parsedResponse =\n responseBody === \"\"\n ? undefined\n : (JSON.parse(responseBody) as T | MeiliSearchErrorResponse);\n\n if (!response.ok) {\n throw new MeiliSearchApiError(\n response,\n parsedResponse as MeiliSearchErrorResponse | undefined,\n );\n }\n\n return parsedResponse as T;\n }\n\n /** Request with GET. */\n get<T = unknown>(options: RequestOptions): Promise<T> {\n return this.#request<T>(options);\n }\n\n /** Request with POST. */\n post<T = unknown>(options: RequestOptions): Promise<T> {\n return this.#request<T>({ ...options, method: \"POST\" });\n }\n\n /** Request with PUT. */\n put<T = unknown>(options: RequestOptions): Promise<T> {\n return this.#request<T>({ ...options, method: \"PUT\" });\n }\n\n /** Request with PATCH. */\n patch<T = unknown>(options: RequestOptions): Promise<T> {\n return this.#request<T>({ ...options, method: \"PATCH\" });\n }\n\n /** Request with DELETE. */\n delete<T = unknown>(options: RequestOptions): Promise<T> {\n return this.#request<T>({ ...options, method: \"DELETE\" });\n }\n}\n","import { MeiliSearchTaskTimeOutError } from \"./errors/index.js\";\nimport type {\n WaitOptions,\n TasksOrBatchesQuery,\n TasksResults,\n Task,\n DeleteOrCancelTasksQuery,\n EnqueuedTask,\n EnqueuedTaskPromise,\n TaskUidOrEnqueuedTask,\n ExtraRequestInit,\n} from \"./types/index.js\";\nimport type { HttpRequests } from \"./http-requests.js\"