diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 5d4788ece..c9ef45568 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -4,7 +4,7 @@ # You can read more on https://github.com/meilisearch/documentation/tree/master/.vuepress/code-samples --- synonyms_guide_1: |- - client.index('movies').updateSynonyms({ + client.index('movies').setting.updateSynonyms({ 'great': ['fantastic'], 'fantastic': ['great'] }) @@ -12,13 +12,13 @@ date_guide_index_1: |- const games = require('./games.json') client.index('games').addDocuments(games).then((res) => console.log(res)) date_guide_filterable_attributes_1: |- - client.index('games').updateFilterableAttributes(['release_timestamp']) + client.index('games').setting.updateFilterableAttributes(['release_timestamp']) date_guide_filter_1: |- client.index('games').search('', { filter: 'release_timestamp >= 1514761200 AND release_timestamp < 1672527600' }) date_guide_sortable_attributes_1: |- - client.index('games').updateSortableAttributes(['release_timestamp']) + client.index('games').setting.updateSortableAttributes(['release_timestamp']) date_guide_sort_1: |- client.index('games').search('', { sort: ['release_timestamp:desc'], @@ -205,25 +205,25 @@ update_settings_1: |- reset_settings_1: |- client.index('movies').resetSettings() get_synonyms_1: |- - client.index('movies').getSynonyms() + client.index('movies').setting.getSynonyms() update_synonyms_1: |- - client.index('movies').updateSynonyms({ + client.index('movies').setting.updateSynonyms({ wolverine: ['xmen', 'logan'], logan: ['wolverine', 'xmen'], wow: ['world of warcraft'] }) reset_synonyms_1: |- - client.index('movies').resetSynonyms() + client.index('movies').setting.resetSynonyms() get_stop_words_1: |- - client.index('movies').getStopWords() + client.index('movies').setting.getStopWords() update_stop_words_1: |- - client.index('movies').updateStopWords(['of', 'the', 'to']) + client.index('movies').setting.updateStopWords(['of', 'the', 'to']) reset_stop_words_1: |- - client.index('movies').resetStopWords() + client.index('movies').setting.resetStopWords() get_ranking_rules_1: |- - client.index('movies').getRankingRules() + client.index('movies').setting.getRankingRules() update_ranking_rules_1: |- - client.index('movies').updateRankingRules([ + client.index('movies').setting.updateRankingRules([ 'words', 'typo', 'proximity', @@ -234,38 +234,38 @@ update_ranking_rules_1: |- 'rank:desc' ]) reset_ranking_rules_1: |- - client.index('movies').resetRankingRules() + client.index('movies').setting.resetRankingRules() get_distinct_attribute_1: |- - client.index('shoes').getDistinctAttribute() + client.index('shoes').setting.getDistinctAttribute() update_distinct_attribute_1: |- - client.index('shoes').updateDistinctAttribute('skuid') + client.index('shoes').setting.updateDistinctAttribute('skuid') reset_distinct_attribute_1: |- - client.index('shoes').resetDistinctAttribute() + client.index('shoes').setting.resetDistinctAttribute() get_searchable_attributes_1: |- - client.index('movies').getSearchableAttributes() + client.index('movies').setting.getSearchableAttributes() update_searchable_attributes_1: |- - client.index('movies').updateSearchableAttributes([ + client.index('movies').setting.updateSearchableAttributes([ 'title', 'overview', 'genres' ]) reset_searchable_attributes_1: |- - client.index('movies').resetSearchableAttributes() + client.index('movies').setting.resetSearchableAttributes() get_displayed_attributes_1: |- - client.index('movies').getDisplayedAttributes() + client.index('movies').setting.getDisplayedAttributes() update_displayed_attributes_1: |- - client.index('movies').updateDisplayedAttributes([ + client.index('movies').setting.updateDisplayedAttributes([ 'title', 'overview', 'genres', 'release_date' ]) reset_displayed_attributes_1: |- - client.index('movies').resetDisplayedAttributes() + client.index('movies').setting.resetDisplayedAttributes() get_typo_tolerance_1: |- - client.index('books').getTypoTolerance() + client.index('books').setting.getTypoTolerance() update_typo_tolerance_1: |- - client.index('books').updateTypoTolerance({ + client.index('books').setting.updateTypoTolerance({ minWordSizeForTypos: { oneTypo: 4, twoTypos: 10 @@ -275,7 +275,7 @@ update_typo_tolerance_1: |- ] }) reset_typo_tolerance_1: |- - client.index('books').resetTypoTolerance() + client.index('books').setting.resetTypoTolerance() get_index_stats_1: |- client.index('movies').getStats() get_indexes_stats_1: |- @@ -285,16 +285,16 @@ get_health_1: |- get_version_1: |- client.getVersion() distinct_attribute_guide_1: |- - client.index('jackets').updateDistinctAttribute('product_id') + client.index('jackets').setting.updateDistinctAttribute('product_id') field_properties_guide_searchable_1: |- - client.index('movies').updateSearchableAttributes([ + client.index('movies').setting.updateSearchableAttributes([ 'title', 'overview', 'genres', ] ) field_properties_guide_displayed_1: |- - client.index('movies').updateDisplayedAttributes([ + client.index('movies').setting.updateDisplayedAttributes([ 'title', 'overview', 'genres', @@ -380,19 +380,19 @@ search_parameter_guide_attributes_to_search_on_1: |- attributesToSearchOn: ['overview'] }) typo_tolerance_guide_1: |- - client.index('movies').updateTypoTolerance({ + client.index('movies').setting.updateTypoTolerance({ enabled: false }) typo_tolerance_guide_2: |- - client.index('movies').updateTypoTolerance({ + client.index('movies').setting.updateTypoTolerance({ disableOnAttributes: ['title'] }) typo_tolerance_guide_3: |- - client.index('movies').updateTypoTolerance({ + client.index('movies').setting.updateTypoTolerance({ disableOnWords: ['shrek'] }) typo_tolerance_guide_4: |- - client.index('movies').updateTypoTolerance({ + client.index('movies').setting.updateTypoTolerance({ minWordSizeForTypos: { oneTypo: 4, twoTypos: 10 @@ -441,7 +441,7 @@ getting_started_add_documents: |- getting_started_search: |- client.index('movies').search('botman').then((res) => console.log(res)) getting_started_update_ranking_rules: |- - client.index('movies').updateRankingRules([ + client.index('movies').setting.updateRankingRules([ 'exactness', 'words', 'typo', @@ -452,20 +452,20 @@ getting_started_update_ranking_rules: |- 'rank:desc' ]) getting_started_update_searchable_attributes: |- - client.index('movies').updateSearchableAttributes([ + client.index('movies').setting.updateSearchableAttributes([ 'title' ]) getting_started_update_stop_words: |- - client.index('movies').updateStopWords(['the']) + client.index('movies').setting.updateStopWords(['the']) getting_started_check_task_status: |- client.getTask(0) getting_started_synonyms: |- - client.index('movies').updateSynonyms({ + client.index('movies').setting.updateSynonyms({ winnie: ['piglet'], piglet: ['winnie'] }) getting_started_update_displayed_attributes: |- - client.index('movies').updateDisplayedAttributes([ + client.index('movies').setting.updateDisplayedAttributes([ 'title', 'overview', 'poster' @@ -489,14 +489,14 @@ getting_started_sorting: |- filter: 'mass < 200' }) getting_started_faceting: |- - client.index('movies').updateFaceting({ + client.index('movies').setting.updateFaceting({ maxValuesPerFacet: 2, sortFacetValuesBy: { '*': 'count' } }) getting_started_typo_tolerance: |- - client.index('movies').updateTypoTolerance({ + client.index('movies').setting.updateTypoTolerance({ minWordSizeForTypos: { oneTypo: 4 } @@ -504,12 +504,12 @@ getting_started_typo_tolerance: |- getting_started_filtering: |- client.index('meteorites').search('', { filter: 'mass < 200' }) getting_started_pagination: |- - client.index('movies').updatePagination({ maxTotalHits: 500 }) + client.index('movies').setting.updatePagination({ maxTotalHits: 500 }) get_filterable_attributes_1: |- - client.index('movies').getFilterableAttributes() + client.index('movies').setting.getFilterableAttributes() update_filterable_attributes_1: |- client.index('movies') - .updateFilterableAttributes([ + .setting.updateFilterableAttributes([ "genres", { attributePatterns: ["genre"], @@ -520,10 +520,10 @@ update_filterable_attributes_1: |- } ]) reset_filterable_attributes_1: |- - client.index('movies').resetFilterableAttributes() + client.index('movies').setting.resetFilterableAttributes() filtering_update_settings_1: |- client.index('movies') - .updateFilterableAttributes([ + .setting.updateFilterableAttributes([ 'director', 'genres' ]) @@ -533,7 +533,7 @@ faceted_search_walkthrough_filter_1: |- filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"'] }) faceted_search_update_settings_1: |- - client.index('movie_ratings').updateFilterableAttributes(['genres', 'rating', 'language']) + client.index('movie_ratings').setting.updateFilterableAttributes(['genres', 'rating', 'language']) faceted_search_1: |- client.index('books').search('classic', { facets: ['genres', 'rating', 'language'] }) post_dump_1: |- @@ -544,12 +544,12 @@ phrase_search_1: |- client.index('movies') .search('"african american" horror') sorting_guide_update_sortable_attributes_1: |- - client.index('books').updateSortableAttributes([ + client.index('books').setting.updateSortableAttributes([ 'author', 'price' ]) sorting_guide_update_ranking_rules_1: |- - client.index('books').updateRankingRules([ + client.index('books').setting.updateRankingRules([ 'words', 'sort', 'typo', @@ -570,25 +570,25 @@ sorting_guide_sort_nested_1: |- 'sort': ['rating.users:asc'], }) get_sortable_attributes_1: |- - client.index('books').getSortableAttributes() + client.index('books').setting.getSortableAttributes() update_sortable_attributes_1: |- client.index('books') - .updateSortableAttributes([ + .setting.updateSortableAttributes([ 'price', 'author' ]) reset_sortable_attributes_1: |- - client.index('books').resetSortableAttributes() + client.index('books').setting.resetSortableAttributes() get_pagination_settings_1: |- - client.index('books').getPagination() + client.index('books').setting.getPagination() update_pagination_settings_1: |- client.index('books').updateSettings({ pagination: { maxTotalHits: 100 }}) reset_pagination_settings_1: |- - client.index('books').resetPagination() + client.index('books').setting.resetPagination() get_faceting_settings_1: |- - client.index('books').getFaceting() + client.index('books').setting.getFaceting() update_faceting_settings_1: |- - client.index('books').updateFaceting({ + client.index('books').setting.updateFaceting({ maxValuesPerFacet: 2 sortFacetValuesBy: { '*': 'alpha', @@ -596,46 +596,46 @@ update_faceting_settings_1: |- } }) reset_faceting_settings_1: |- - client.index('books').resetFaceting() + client.index('books').setting.resetFaceting() get_dictionary_1: |- - client.index('books').getDictionary() + client.index('books').setting.getDictionary() update_dictionary_1: |- - client.index('books').updateDictionary(['J. R. R.', 'W. E. B.']) + client.index('books').setting.updateDictionary(['J. R. R.', 'W. E. B.']) reset_dictionary_1: |- - client.index('books').resetDictionary() + client.index('books').setting.resetDictionary() search_parameter_guide_sort_1: |- client.index('books').search('science fiction', { sort: ['price:asc'], }) get_separator_tokens_1: |- - client.index('books').getSeparatorTokens() + client.index('books').setting.getSeparatorTokens() update_separator_tokens_1: |- - client.index('books').updateSeparatorTokens(['|', '…']) + client.index('books').setting.updateSeparatorTokens(['|', '…']) reset_separator_tokens_1: |- - client.index('books').resetSeparatorTokens() + client.index('books').setting.resetSeparatorTokens() get_non_separator_tokens_1: |- - client.index('books').getNonSeparatorTokens() + client.index('books').setting.getNonSeparatorTokens() update_non_separator_tokens_1: |- - client.index('books').updateNonSeparatorTokens(['@', '#']) + client.index('books').setting.updateNonSeparatorTokens(['@', '#']) reset_non_separator_tokens_1: |- - client.index('books').resetNonSeparatorTokens() + client.index('books').setting.resetNonSeparatorTokens() get_proximity_precision_settings_1: |- - client.index('books').getProximityPrecision() + client.index('books').setting.getProximityPrecision() update_proximity_precision_settings_1: |- - client.index('books').updateProximityPrecision('byAttribute') + client.index('books').setting.updateProximityPrecision('byAttribute') reset_proximity_precision_settings_1: |- - client.index('books').resetProximityPrecision() + client.index('books').setting.resetProximityPrecision() get_search_cutoff_1: |- - client.index('movies').getSearchCutoffMs() + client.index('movies').setting.getSearchCutoffMs() update_search_cutoff_1: |- - client.index('movies').updateSearchCutoffMs(150) + client.index('movies').setting.updateSearchCutoffMs(150) reset_search_cutoff_1: |- - client.index('movies').resetSearchCutoffMs() + client.index('movies').setting.resetSearchCutoffMs() search_parameter_guide_facet_stats_1: |- client.index('movie_ratings').search('Batman', { facets: ['genres', 'rating'] }) geosearch_guide_filter_settings_1: |- client.index('restaurants') - .updateFilterableAttributes([ + .setting.updateFilterableAttributes([ '_geo' ]) geosearch_guide_filter_usage_1: |- @@ -651,7 +651,7 @@ geosearch_guide_filter_usage_3: |- filter: ['_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])'], }) geosearch_guide_sort_settings_1: |- - client.index('restaurants').updateSortableAttributes([ + client.index('restaurants').setting.updateSortableAttributes([ '_geo' ]) geosearch_guide_sort_usage_1: |- @@ -725,7 +725,7 @@ facet_search_1: |- filter: 'rating > 3' }) facet_search_2: |- - client.index('books').updateFaceting({ + client.index('books').setting.updateFaceting({ sortFacetValuesBy: { genres: 'count' } @@ -766,7 +766,7 @@ search_parameter_guide_matching_strategy_3: |- search_parameter_reference_distinct_1: |- client.index('INDEX_NAME').search('QUERY TERMS', { distinct: 'ATTRIBUTE_A' }) distinct_attribute_guide_filterable_1: |- - client.index('products').updateFilterableAttributes(['product_id', 'sku', 'url']) + client.index('products').setting.updateFilterableAttributes(['product_id', 'sku', 'url']) distinct_attribute_guide_distinct_parameter_1: |- client.index('products').search('white shirt', { distinct: 'sku' }) multi_search_federated_1: |- @@ -786,32 +786,32 @@ multi_search_federated_1: |- search_parameter_reference_locales_1: |- client.index('INDEX_NAME').search('QUERY TEXT IN JAPANESE', { locales: ['jpn'] }) get_localized_attribute_settings_1: |- - client.index('INDEX_NAME').getLocalizedAttributes() + client.index('INDEX_NAME').setting.getLocalizedAttributes() update_localized_attribute_settings_1: |- - client.index('INDEX_NAME').updateLocalizedAttributes([ + client.index('INDEX_NAME').setting.updateLocalizedAttributes([ { attributePatterns: ['*_ja'], locales: ['jpn'] }, ]) reset_localized_attribute_settings_1: |- - client.index('INDEX_NAME').resetLocalizedAttributes() + client.index('INDEX_NAME').setting.resetLocalizedAttributes() get_facet_search_settings_1: |- - client.index('INDEX_NAME').getFacetSearch(); + client.index('INDEX_NAME').setting.getFacetSearch(); update_facet_search_settings_1: |- - client.index('INDEX_NAME').updateFacetSearch(false); + client.index('INDEX_NAME').setting.updateFacetSearch(false); reset_facet_search_settings_1: |- - client.index('INDEX_NAME').resetFacetSearch(); + client.index('INDEX_NAME').setting.resetFacetSearch(); get_prefix_search_settings_1: |- - client.index('INDEX_NAME').getPrefixSearch(); + client.index('INDEX_NAME').setting.getPrefixSearch(); update_prefix_search_settings_1: |- - client.index('INDEX_NAME').updatePrefixSearch('disabled'); + client.index('INDEX_NAME').setting.updatePrefixSearch('disabled'); reset_prefix_search_settings_1: |- - client.index('INDEX_NAME').resetPrefixSearch(); + client.index('INDEX_NAME').setting.resetPrefixSearch(); get_all_batches_1: |- client.getBatches(); get_batch_1: |- client.getBatch(BATCH_UID); # Vector search update_embedders_1: |- - client.index('INDEX_NAME').updateEmbedders({ + client.index('INDEX_NAME').setting.updateEmbedders({ default: { source: 'openAi', apiKey: 'OPEN_AI_API_KEY', diff --git a/README.md b/README.md index 3d5e3441f..6e0fbe4f3 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ await index.search( To enable filtering, you must first add your attributes to the [`filterableAttributes` index setting](https://www.meilisearch.com/docs/reference/api/settings#filterable-attributes). ```js -await index.updateFilterableAttributes([ +await index.setting.updateFilterableAttributes([ 'id', 'genres' ]) @@ -710,19 +710,19 @@ client.index('myIndex').resetSettings(): Promise #### [Get pagination](https://www.meilisearch.com/docs/reference/api/settings#get-pagination-settings) ```ts -client.index('myIndex').getPagination(): Promise +client.index('myIndex').setting.getPagination(): Promise ``` #### [Update pagination](https://www.meilisearch.com/docs/reference/api/settings#update-pagination-settings) ```ts -client.index('myIndex').updatePagination(pagination: PaginationSettings): Promise +client.index('myIndex').setting.updatePagination(pagination: PaginationSettings): Promise ``` #### [Reset pagination](https://www.meilisearch.com/docs/reference/api/settings#reset-pagination-settings) ```ts -client.index('myIndex').resetPagination(): Promise +client.index('myIndex').setting.resetPagination(): Promise ``` ### Synonyms @@ -730,19 +730,19 @@ client.index('myIndex').resetPagination(): Promise #### [Get synonyms](https://www.meilisearch.com/docs/reference/api/settings#get-synonyms) ```ts -client.index('myIndex').getSynonyms(): Promise +client.index('myIndex').setting.getSynonyms(): Promise ``` #### [Update synonyms](https://www.meilisearch.com/docs/reference/api/settings#update-synonyms) ```ts -client.index('myIndex').updateSynonyms(synonyms: Synonyms): Promise +client.index('myIndex').setting.updateSynonyms(synonyms: Synonyms): Promise ``` #### [Reset synonyms](https://www.meilisearch.com/docs/reference/api/settings#reset-synonyms) ```ts -client.index('myIndex').resetSynonyms(): Promise +client.index('myIndex').setting.resetSynonyms(): Promise ``` ### Stop words @@ -750,19 +750,19 @@ client.index('myIndex').resetSynonyms(): Promise #### [Get stop words](https://www.meilisearch.com/docs/reference/api/settings#get-stop-words) ```ts -client.index('myIndex').getStopWords(): Promise +client.index('myIndex').setting.getStopWords(): Promise ``` #### [Update stop words](https://www.meilisearch.com/docs/reference/api/settings#update-stop-words) ```ts -client.index('myIndex').updateStopWords(stopWords: string[] | null ): Promise +client.index('myIndex').setting.updateStopWords(stopWords: string[] | null ): Promise ``` #### [Reset stop words](https://www.meilisearch.com/docs/reference/api/settings#reset-stop-words) ```ts -client.index('myIndex').resetStopWords(): Promise +client.index('myIndex').setting.resetStopWords(): Promise ``` ### Ranking rules @@ -770,19 +770,19 @@ client.index('myIndex').resetStopWords(): Promise #### [Get ranking rules](https://www.meilisearch.com/docs/reference/api/settings#get-ranking-rules) ```ts -client.index('myIndex').getRankingRules(): Promise +client.index('myIndex').setting.getRankingRules(): Promise ``` #### [Update ranking rules](https://www.meilisearch.com/docs/reference/api/settings#update-ranking-rules) ```ts -client.index('myIndex').updateRankingRules(rankingRules: string[] | null): Promise +client.index('myIndex').setting.updateRankingRules(rankingRules: string[] | null): Promise ``` #### [Reset ranking rules](https://www.meilisearch.com/docs/reference/api/settings#reset-ranking-rules) ```ts -client.index('myIndex').resetRankingRules(): Promise +client.index('myIndex').setting.resetRankingRules(): Promise ``` ### Distinct Attribute @@ -790,19 +790,19 @@ client.index('myIndex').resetRankingRules(): Promise #### [Get distinct attribute](https://www.meilisearch.com/docs/reference/api/settings#get-distinct-attribute) ```ts -client.index('myIndex').getDistinctAttribute(): Promise +client.index('myIndex').setting.getDistinctAttribute(): Promise ``` #### [Update distinct attribute](https://www.meilisearch.com/docs/reference/api/settings#update-distinct-attribute) ```ts -client.index('myIndex').updateDistinctAttribute(distinctAttribute: string | null): Promise +client.index('myIndex').setting.updateDistinctAttribute(distinctAttribute: string | null): Promise ``` #### [Reset distinct attribute](https://www.meilisearch.com/docs/reference/api/settings#reset-distinct-attribute) ```ts -client.index('myIndex').resetDistinctAttribute(): Promise +client.index('myIndex').setting.resetDistinctAttribute(): Promise ``` ### Searchable attributes @@ -810,19 +810,19 @@ client.index('myIndex').resetDistinctAttribute(): Promise #### [Get searchable attributes](https://www.meilisearch.com/docs/reference/api/settings#get-searchable-attributes) ```ts -client.index('myIndex').getSearchableAttributes(): Promise +client.index('myIndex').setting.getSearchableAttributes(): Promise ``` #### [Update searchable attributes](https://www.meilisearch.com/docs/reference/api/settings#update-searchable-attributes) ```ts -client.index('myIndex').updateSearchableAttributes(searchableAttributes: string[] | null): Promise +client.index('myIndex').setting.updateSearchableAttributes(searchableAttributes: string[] | null): Promise ``` #### [Reset searchable attributes](https://www.meilisearch.com/docs/reference/api/settings#reset-searchable-attributes) ```ts -client.index('myIndex').resetSearchableAttributes(): Promise +client.index('myIndex').setting.resetSearchableAttributes(): Promise ``` ### Displayed attributes @@ -830,19 +830,19 @@ client.index('myIndex').resetSearchableAttributes(): Promise #### [Get displayed attributes](https://www.meilisearch.com/docs/reference/api/settings#get-displayed-attributes) ```ts -client.index('myIndex').getDisplayedAttributes(): Promise +client.index('myIndex').setting.getDisplayedAttributes(): Promise ``` #### [Update displayed attributes](https://www.meilisearch.com/docs/reference/api/settings#update-displayed-attributes) ```ts -client.index('myIndex').updateDisplayedAttributes(displayedAttributes: string[] | null): Promise +client.index('myIndex').setting.updateDisplayedAttributes(displayedAttributes: string[] | null): Promise ``` #### [Reset displayed attributes](https://www.meilisearch.com/docs/reference/api/settings#reset-displayed-attributes) ```ts -client.index('myIndex').resetDisplayedAttributes(): Promise +client.index('myIndex').setting.resetDisplayedAttributes(): Promise ``` ### Filterable attributes @@ -850,19 +850,19 @@ client.index('myIndex').resetDisplayedAttributes(): Promise #### [Get filterable attributes](https://www.meilisearch.com/docs/reference/api/settings#get-filterable-attributes) ```ts -client.index('myIndex').getFilterableAttributes(): Promise +client.index('myIndex').setting.getFilterableAttributes(): Promise ``` #### [Update filterable attributes](https://www.meilisearch.com/docs/reference/api/settings#update-filterable-attributes) ```ts -client.index('myIndex').updateFilterableAttributes(filterableAttributes: string[] | null): Promise +client.index('myIndex').setting.updateFilterableAttributes(filterableAttributes: string[] | null): Promise ``` #### [Reset filterable attributes](https://www.meilisearch.com/docs/reference/api/settings#reset-filterable-attributes) ```ts -client.index('myIndex').resetFilterableAttributes(): Promise +client.index('myIndex').setting.resetFilterableAttributes(): Promise ``` ### Sortable attributes @@ -870,19 +870,19 @@ client.index('myIndex').resetFilterableAttributes(): Promise #### [Get sortable attributes](https://www.meilisearch.com/docs/reference/api/settings#get-sortable-attributes) ```ts -client.index('myIndex').getSortableAttributes(): Promise +client.index('myIndex').setting.getSortableAttributes(): Promise ``` #### [Update sortable attributes](https://www.meilisearch.com/docs/reference/api/settings#update-sortable-attributes) ```ts -client.index('myIndex').updateSortableAttributes(sortableAttributes: string[] | null): Promise +client.index('myIndex').setting.updateSortableAttributes(sortableAttributes: string[] | null): Promise ``` #### [Reset sortable attributes](https://www.meilisearch.com/docs/reference/api/settings#reset-sortable-attributes) ```ts -client.index('myIndex').resetSortableAttributes(): Promise +client.index('myIndex').setting.resetSortableAttributes(): Promise ``` ### Faceting @@ -890,19 +890,19 @@ client.index('myIndex').resetSortableAttributes(): Promise #### [Get faceting](https://www.meilisearch.com/docs/reference/api/settings#get-faceting-settings) ```ts -client.index('myIndex').getFaceting(): Promise +client.index('myIndex').setting.getFaceting(): Promise ``` #### [Update faceting](https://www.meilisearch.com/docs/reference/api/settings#update-faceting-settings) ```ts -client.index('myIndex').updateFaceting(faceting: Faceting): Promise +client.index('myIndex').setting.updateFaceting(faceting: Faceting): Promise ``` #### [Reset faceting](https://www.meilisearch.com/docs/reference/api/settings#reset-faceting-settings) ```ts -client.index('myIndex').resetFaceting(): Promise +client.index('myIndex').setting.resetFaceting(): Promise ``` ### Typo tolerance @@ -910,19 +910,19 @@ client.index('myIndex').resetFaceting(): Promise #### [Get typo tolerance](https://www.meilisearch.com/docs/reference/api/settings#get-typo-tolerance-settings) ```ts -client.index('myIndex').getTypoTolerance(): Promise +client.index('myIndex').setting.getTypoTolerance(): Promise ``` #### [Update typo tolerance](https://www.meilisearch.com/docs/reference/api/settings#update-typo-tolerance-settings) ```ts -client.index('myIndex').updateTypoTolerance(typoTolerance: TypoTolerance | null): Promise +client.index('myIndex').setting.updateTypoTolerance(typoTolerance: TypoTolerance | null): Promise ``` #### [Reset typo tolerance](https://www.meilisearch.com/docs/reference/api/settings#reset-typo-tolerance-settings) ```ts -client.index('myIndex').resetTypoTolerance(): Promise +client.index('myIndex').setting.resetTypoTolerance(): Promise ``` @@ -931,19 +931,19 @@ client.index('myIndex').resetTypoTolerance(): Promise #### [Get separator tokens](https://www.meilisearch.com/docs/reference/api/settings#get-separator-tokens) ```ts -client.index('myIndex').getSeparatorTokens(): Promise +client.index('myIndex').setting.getSeparatorTokens(): Promise ``` #### [Update separator tokens](https://www.meilisearch.com/docs/reference/api/settings#update-separator-tokens) ```ts -client.index('myIndex').updateSeparatorTokens(separatorTokens: SeparatorTokens | null): Promise +client.index('myIndex').setting.updateSeparatorTokens(separatorTokens: SeparatorTokens | null): Promise ``` #### [Reset separator tokens](https://www.meilisearch.com/docs/reference/api/settings#reset-separator-tokens) ```ts -client.index('myIndex').resetSeparatorTokens(): Promise +client.index('myIndex').setting.resetSeparatorTokens(): Promise ``` ### Non Separator tokens @@ -951,19 +951,19 @@ client.index('myIndex').resetSeparatorTokens(): Promise #### [Get non separator tokens](https://www.meilisearch.com/docs/reference/api/settings#get-non-separator-tokens) ```ts -client.index('myIndex').getNonSeparatorTokens(): Promise +client.index('myIndex').setting.getNonSeparatorTokens(): Promise ``` #### [Update non separator tokens](https://www.meilisearch.com/docs/reference/api/settings#update-non-separator-tokens) ```ts -client.index('myIndex').updateNonSeparatorTokens(nonSeparatorTokens: NonSeparatorTokens | null): Promise +client.index('myIndex').setting.updateNonSeparatorTokens(nonSeparatorTokens: NonSeparatorTokens | null): Promise ``` #### [Reset non separator tokens](https://www.meilisearch.com/docs/reference/api/settings#reset-non-separator-tokens) ```ts -client.index('myIndex').resetNonSeparatorTokens(): Promise +client.index('myIndex').setting.resetNonSeparatorTokens(): Promise ``` ### Dictionary @@ -971,19 +971,19 @@ client.index('myIndex').resetNonSeparatorTokens(): Promise #### [Get dictionary](https://www.meilisearch.com/docs/reference/api/settings#get-dictionary) ```ts -client.index('myIndex').getDictionary(): Promise +client.index('myIndex').setting.getDictionary(): Promise ``` #### [Update dictionary](https://www.meilisearch.com/docs/reference/api/settings#update-dictionary) ```ts -client.index('myIndex').updateDictionary(dictionary: Dictionary | null): Promise +client.index('myIndex').setting.updateDictionary(dictionary: Dictionary | null): Promise ``` #### [Reset dictionary](https://www.meilisearch.com/docs/reference/api/settings#reset-dictionary) ```ts -client.index('myIndex').resetDictionary(): Promise +client.index('myIndex').setting.resetDictionary(): Promise ``` ### Proximity Precision @@ -991,19 +991,19 @@ client.index('myIndex').resetDictionary(): Promise #### [Get proximity precision](https://www.meilisearch.com/docs/reference/api/settings#get-proximity-precision-settings) ```ts -client.index('myIndex').getProximityPrecision(): Promise +client.index('myIndex').setting.getProximityPrecision(): Promise ``` #### [Update proximity precision](https://www.meilisearch.com/docs/reference/api/settings#update-proximity-precision-settings) ```ts -client.index('myIndex').updateProximityPrecision(proximityPrecision: ProximityPrecision): Promise +client.index('myIndex').setting.updateProximityPrecision(proximityPrecision: ProximityPrecision): Promise ``` #### [Reset proximity precision](https://www.meilisearch.com/docs/reference/api/settings#reset-proximity-precision-settings) ```ts -client.index('myIndex').resetProximityPrecision(): Promise +client.index('myIndex').setting.resetProximityPrecision(): Promise ``` ### Facet search settings @@ -1011,19 +1011,19 @@ client.index('myIndex').resetProximityPrecision(): Promise #### [Get facet search settings](https://www.meilisearch.com/docs/reference/api/settings#get-facet-search-settings) ```ts -client.index('myIndex').getFacetSearch(): Promise +client.index('myIndex').setting.getFacetSearch(): Promise ``` #### [Update facet search settings](https://www.meilisearch.com/docs/reference/api/settings#update-facet-search-settings) ```ts -client.index('myIndex').updateFacetSearch(enabled: boolean): Promise +client.index('myIndex').setting.updateFacetSearch(enabled: boolean): Promise ``` #### [Reset facet search settings](https://www.meilisearch.com/docs/reference/api/settings#reset-facet-search-settings) ```ts -client.index('myIndex').resetFacetSearch(): Promise +client.index('myIndex').setting.resetFacetSearch(): Promise ``` ### Prefix search settings @@ -1031,19 +1031,19 @@ client.index('myIndex').resetFacetSearch(): Promise #### [Get prefix search settings](https://www.meilisearch.com/docs/reference/api/settings#get-prefix-search-settings) ```ts -client.index('myIndex').getPrefixSearch(): Promise +client.index('myIndex').setting.getPrefixSearch(): Promise ``` #### [Update prefix search settings](https://www.meilisearch.com/docs/reference/api/settings#update-prefix-search-settings) ```ts -client.index('myIndex').updatePrefixSearch(prefixSearch: PrefixSearch): Promise +client.index('myIndex').setting.updatePrefixSearch(prefixSearch: PrefixSearch): Promise ``` #### [Reset prefix search settings](https://www.meilisearch.com/docs/reference/api/settings#reset-prefix-search-settings) ```ts -client.index('myIndex').resetPrefixSearch(): Promise +client.index('myIndex').setting.resetPrefixSearch(): Promise ``` ### Embedders @@ -1051,19 +1051,19 @@ client.index('myIndex').resetPrefixSearch(): Promise #### Get embedders ```ts -client.index('myIndex').getEmbedders(): Promise +client.index('myIndex').setting.getEmbedders(): Promise ``` #### Update embedders ```ts -client.index('myIndex').updateEmbedders(embedders: Embedders): Promise +client.index('myIndex').setting.updateEmbedders(embedders: Embedders): Promise ``` #### Reset embedders ```ts -client.index('myIndex').resetEmbedders(): Promise +client.index('myIndex').setting.resetEmbedders(): Promise ``` ### SearchCutoffMs @@ -1071,19 +1071,19 @@ client.index('myIndex').resetEmbedders(): Promise #### [Get SearchCutoffMs](https://www.meilisearch.com/docs/reference/api/settings#get-search-cutoff) ```ts -client.index('myIndex').getSearchCutoffMs(): Promise +client.index('myIndex').setting.getSearchCutoffMs(): Promise ``` #### [Update SearchCutoffMs](https://www.meilisearch.com/docs/reference/api/settings#update-search-cutoff) ```ts -client.index('myIndex').updateSearchCutoffMs(searchCutoffMs: SearchCutoffMs): Promise +client.index('myIndex').setting.updateSearchCutoffMs(searchCutoffMs: SearchCutoffMs): Promise ``` #### [Reset SearchCutoffMs](https://www.meilisearch.com/docs/reference/api/settings#reset-search-cutoff) ```ts -client.index('myIndex').resetSearchCutoffMs(): Promise +client.index('myIndex').setting.resetSearchCutoffMs(): Promise ``` ### Keys diff --git a/src/indexes.ts b/src/indexes.ts index a3cc3f020..130ea70d6 100644 --- a/src/indexes.ts +++ b/src/indexes.ts @@ -8,48 +8,30 @@ import { MeiliSearchError } from "./errors/index.js"; import type { Config, - SearchResponse, - SearchParams, + ContentType, + DocumentOptions, + DocumentQuery, + DocumentsDeletionQuery, + DocumentsIds, + DocumentsQuery, + EnqueuedTaskPromise, + ExtraRequestInit, Filter, - SearchRequestGET, IndexObject, IndexOptions, IndexStats, - DocumentsQuery, - DocumentQuery, - DocumentOptions, - Settings, - Synonyms, - StopWords, - RankingRules, - DistinctAttribute, - FilterableAttributes, - SortableAttributes, - SearchableAttributes, - DisplayedAttributes, - TypoTolerance, - PaginationSettings, - Faceting, - ResourceResults, RawDocumentAdditionOptions, - ContentType, - DocumentsIds, - DocumentsDeletionQuery, + RecordAny, + ResourceResults, SearchForFacetValuesParams, SearchForFacetValuesResponse, - SeparatorTokens, - NonSeparatorTokens, - Dictionary, - ProximityPrecision, - Embedders, - SearchCutoffMs, + SearchParams, + SearchRequestGET, + SearchResponse, SearchSimilarDocumentsParams, - LocalizedAttributes, + Settings, + UpdatableSettings, UpdateDocumentsByFunctionOptions, - ExtraRequestInit, - PrefixSearch, - RecordAny, - EnqueuedTaskPromise, } from "./types/index.js"; import { HttpRequests } from "./http-requests.js"; import { @@ -57,6 +39,7 @@ import { TaskClient, type HttpRequestsWithEnqueuedTaskPromise, } from "./task.js"; +import { makeSettingFns, type SettingFns } from "./settings.js"; export class Index { uid: string; @@ -81,6 +64,34 @@ export class Index { this.httpRequest, this.tasks, ); + + this.#setting = makeSettingFns( + this.httpRequest, + this.#httpRequestsWithTask, + `indexes/${uid}/settings`, + { + filterableAttributes: "put", + sortableAttributes: "put", + displayedAttributes: "put", + typoTolerance: "patch", + searchableAttributes: "put", + stopWords: "put", + nonSeparatorTokens: "put", + separatorTokens: "put", + dictionary: "put", + synonyms: "put", + distinctAttribute: "put", + proximityPrecision: "put", + localizedAttributes: "put", + rankingRules: "put", + faceting: "patch", + pagination: "patch", + embedders: "patch", + searchCutoffMs: "put", + facetSearch: "put", + prefixSearch: "put", + }, + ); } /// @@ -126,11 +137,11 @@ export class Index { // TODO: Make this a type thing instead of a runtime thing const parseFilter = (filter?: Filter): string | undefined => { if (typeof filter === "string") return filter; - else if (Array.isArray(filter)) + else if (Array.isArray(filter)) { throw new MeiliSearchError( "The filter query parameter should be in string format when using searchGet", ); - else return undefined; + } else return undefined; }; const getParams: SearchRequestGET = { @@ -540,841 +551,34 @@ export class Index { /// SETTINGS /// - /** - * Retrieve all settings - * - * @returns Promise containing Settings object - */ + /** {@link https://www.meilisearch.com/docs/reference/api/settings#get-settings} */ async getSettings(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings`, - }); + return await this.httpRequest.get({ path: `indexes/${this.uid}/settings` }); } - /** - * 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 - */ - updateSettings(settings: Settings): EnqueuedTaskPromise { + /** {@link https://www.meilisearch.com/docs/reference/api/settings#update-settings} */ + updateSettings(settings: UpdatableSettings): EnqueuedTaskPromise { return this.#httpRequestsWithTask.patch({ path: `indexes/${this.uid}/settings`, body: settings, }); } - /** - * Reset settings. - * - * @returns Promise containing an EnqueuedTask - */ + /** {@link https://www.meilisearch.com/docs/reference/api/settings#reset-settings} */ resetSettings(): EnqueuedTaskPromise { return this.#httpRequestsWithTask.delete({ path: `indexes/${this.uid}/settings`, }); } - /// - /// PAGINATION SETTINGS - /// - - /** - * Get the pagination settings. - * - * @returns Promise containing object of pagination settings - */ - async getPagination(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/pagination`, - }); - } - - /** - * Update the pagination settings. - * - * @param pagination - Pagination object - * @returns Promise containing an EnqueuedTask - */ - updatePagination(pagination: PaginationSettings): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.patch({ - path: `indexes/${this.uid}/settings/pagination`, - body: pagination, - }); - } - - /** - * Reset the pagination settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetPagination(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/pagination`, - }); - } - - /// - /// SYNONYMS - /// - - /** - * Get the list of all synonyms - * - * @returns Promise containing record of synonym mappings - */ - async getSynonyms(): Promise> { - return await this.httpRequest.get>({ - path: `indexes/${this.uid}/settings/synonyms`, - }); - } - - /** - * Update the list of synonyms. Overwrite the old list. - * - * @param synonyms - Mapping of synonyms with their associated words - * @returns Promise containing an EnqueuedTask - */ - updateSynonyms(synonyms: Synonyms): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/synonyms`, - body: synonyms, - }); - } - - /** - * Reset the synonym list to be empty again - * - * @returns Promise containing an EnqueuedTask - */ - resetSynonyms(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/synonyms`, - }); - } - - /// - /// STOP WORDS - /// - - /** - * Get the list of all stop-words - * - * @returns Promise containing array of stop-words - */ - async getStopWords(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/stop-words`, - }); - } - - /** - * 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 - */ - updateStopWords(stopWords: StopWords): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/stop-words`, - body: stopWords, - }); - } - - /** - * Reset the stop-words list to be empty again - * - * @returns Promise containing an EnqueuedTask - */ - resetStopWords(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/stop-words`, - }); - } - - /// - /// RANKING RULES - /// - - /** - * Get the list of all ranking-rules - * - * @returns Promise containing array of ranking-rules - */ - async getRankingRules(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/ranking-rules`, - }); - } - - /** - * 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 - */ - updateRankingRules(rankingRules: RankingRules): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/ranking-rules`, - body: rankingRules, - }); - } - - /** - * Reset the ranking rules list to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetRankingRules(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/ranking-rules`, - }); - } - - /// - /// DISTINCT ATTRIBUTE - /// - - /** - * Get the distinct-attribute - * - * @returns Promise containing the distinct-attribute of the index - */ - async getDistinctAttribute(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/distinct-attribute`, - }); - } - - /** - * Update the distinct-attribute. - * - * @param distinctAttribute - Field name of the distinct-attribute - * @returns Promise containing an EnqueuedTask - */ - updateDistinctAttribute( - distinctAttribute: DistinctAttribute, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/distinct-attribute`, - body: distinctAttribute, - }); - } - - /** - * Reset the distinct-attribute. - * - * @returns Promise containing an EnqueuedTask - */ - resetDistinctAttribute(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/distinct-attribute`, - }); - } - - /// - /// FILTERABLE ATTRIBUTES - /// - - /** - * Get the filterable-attributes - * - * @returns Promise containing an array of filterable-attributes - */ - async getFilterableAttributes(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/filterable-attributes`, - }); - } - - /** - * 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 - */ - updateFilterableAttributes( - filterableAttributes: FilterableAttributes, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/filterable-attributes`, - body: filterableAttributes, - }); - } - - /** - * Reset the filterable-attributes. - * - * @returns Promise containing an EnqueuedTask - */ - resetFilterableAttributes(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/filterable-attributes`, - }); - } - - /// - /// SORTABLE ATTRIBUTES - /// - - /** - * Get the sortable-attributes - * - * @returns Promise containing array of sortable-attributes - */ - async getSortableAttributes(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/sortable-attributes`, - }); - } - - /** - * 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 - */ - updateSortableAttributes( - sortableAttributes: SortableAttributes, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/sortable-attributes`, - body: sortableAttributes, - }); - } - - /** - * Reset the sortable-attributes. - * - * @returns Promise containing an EnqueuedTask - */ - resetSortableAttributes(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/sortable-attributes`, - }); - } - - /// - /// SEARCHABLE ATTRIBUTE - /// + readonly #setting: SettingFns; /** - * Get the searchable-attributes + * Contains the get, update and reset functions for every individual setting. * - * @returns Promise containing array of searchable-attributes + * @see {@link https://www.meilisearch.com/docs/reference/api/settings} */ - async getSearchableAttributes(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/searchable-attributes`, - }); - } - - /** - * 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 - */ - updateSearchableAttributes( - searchableAttributes: SearchableAttributes, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/searchable-attributes`, - body: searchableAttributes, - }); - } - - /** - * Reset the searchable-attributes. - * - * @returns Promise containing an EnqueuedTask - */ - resetSearchableAttributes(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/searchable-attributes`, - }); - } - - /// - /// DISPLAYED ATTRIBUTE - /// - - /** - * Get the displayed-attributes - * - * @returns Promise containing array of displayed-attributes - */ - async getDisplayedAttributes(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/displayed-attributes`, - }); - } - - /** - * Update the displayed-attributes. - * - * @param displayedAttributes - Array of strings that contains attributes of - * an index to display - * @returns Promise containing an EnqueuedTask - */ - updateDisplayedAttributes( - displayedAttributes: DisplayedAttributes, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/displayed-attributes`, - body: displayedAttributes, - }); - } - - /** - * Reset the displayed-attributes. - * - * @returns Promise containing an EnqueuedTask - */ - resetDisplayedAttributes(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/displayed-attributes`, - }); - } - - /// - /// TYPO TOLERANCE - /// - - /** - * Get the typo tolerance settings. - * - * @returns Promise containing the typo tolerance settings. - */ - async getTypoTolerance(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/typo-tolerance`, - }); - } - - /** - * Update the typo tolerance settings. - * - * @param typoTolerance - Object containing the custom typo tolerance - * settings. - * @returns Promise containing object of the enqueued update - */ - updateTypoTolerance(typoTolerance: TypoTolerance): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.patch({ - path: `indexes/${this.uid}/settings/typo-tolerance`, - body: typoTolerance, - }); - } - - /** - * Reset the typo tolerance settings. - * - * @returns Promise containing object of the enqueued update - */ - resetTypoTolerance(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/typo-tolerance`, - }); - } - - /// - /// FACETING - /// - - /** - * Get the faceting settings. - * - * @returns Promise containing object of faceting index settings - */ - async getFaceting(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/faceting`, - }); - } - - /** - * Update the faceting settings. - * - * @param faceting - Faceting index settings object - * @returns Promise containing an EnqueuedTask - */ - updateFaceting(faceting: Faceting): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.patch({ - path: `indexes/${this.uid}/settings/faceting`, - body: faceting, - }); - } - - /** - * Reset the faceting settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetFaceting(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/faceting`, - }); - } - - /// - /// SEPARATOR TOKENS - /// - - /** - * Get the list of all separator tokens. - * - * @returns Promise containing array of separator tokens - */ - async getSeparatorTokens(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/separator-tokens`, - }); - } - - /** - * Update the list of separator tokens. Overwrite the old list. - * - * @param separatorTokens - Array that contains separator tokens. - * @returns Promise containing an EnqueuedTask or null - */ - updateSeparatorTokens(separatorTokens: SeparatorTokens): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/separator-tokens`, - body: separatorTokens, - }); - } - - /** - * Reset the separator tokens list to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetSeparatorTokens(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/separator-tokens`, - }); - } - - /// - /// NON-SEPARATOR TOKENS - /// - - /** - * Get the list of all non-separator tokens. - * - * @returns Promise containing array of non-separator tokens - */ - async getNonSeparatorTokens(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/non-separator-tokens`, - }); - } - - /** - * 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 - */ - updateNonSeparatorTokens( - nonSeparatorTokens: NonSeparatorTokens, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/non-separator-tokens`, - body: nonSeparatorTokens, - }); - } - - /** - * Reset the non-separator tokens list to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetNonSeparatorTokens(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/non-separator-tokens`, - }); - } - - /// - /// DICTIONARY - /// - - /** - * Get the dictionary settings of a Meilisearch index. - * - * @returns Promise containing the dictionary settings - */ - async getDictionary(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/dictionary`, - }); - } - - /** - * Update the dictionary settings. Overwrite the old settings. - * - * @param dictionary - Array that contains the new dictionary settings. - * @returns Promise containing an EnqueuedTask or null - */ - updateDictionary(dictionary: Dictionary): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/dictionary`, - body: dictionary, - }); - } - - /** - * Reset the dictionary settings to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetDictionary(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/dictionary`, - }); - } - - /// - /// PROXIMITY PRECISION - /// - - /** - * Get the proximity precision settings of a Meilisearch index. - * - * @returns Promise containing the proximity precision settings - */ - async getProximityPrecision(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/proximity-precision`, - }); - } - - /** - * 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 - */ - updateProximityPrecision( - proximityPrecision: ProximityPrecision, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/proximity-precision`, - body: proximityPrecision, - }); - } - - /** - * Reset the proximity precision settings to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetProximityPrecision(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/proximity-precision`, - }); - } - - /// - /// EMBEDDERS - /// - - /** - * Get the embedders settings of a Meilisearch index. - * - * @returns Promise containing the embedders settings - */ - async getEmbedders(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/embedders`, - }); - } - - /** - * Update the embedders settings. Overwrite the old settings. - * - * @param embedders - Object that contains the new embedders settings. - * @returns Promise containing an EnqueuedTask or null - */ - updateEmbedders(embedders: Embedders): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.patch({ - path: `indexes/${this.uid}/settings/embedders`, - body: embedders, - }); - } - - /** - * Reset the embedders settings to its default value - * - * @returns Promise containing an EnqueuedTask - */ - resetEmbedders(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/embedders`, - }); - } - - /// - /// SEARCHCUTOFFMS SETTINGS - /// - - /** - * Get the SearchCutoffMs settings. - * - * @returns Promise containing object of SearchCutoffMs settings - */ - async getSearchCutoffMs(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/search-cutoff-ms`, - }); - } - - /** - * Update the SearchCutoffMs settings. - * - * @param searchCutoffMs - Object containing SearchCutoffMsSettings - * @returns Promise containing an EnqueuedTask - */ - updateSearchCutoffMs(searchCutoffMs: SearchCutoffMs): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/search-cutoff-ms`, - body: searchCutoffMs, - }); - } - - /** - * Reset the SearchCutoffMs settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetSearchCutoffMs(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/search-cutoff-ms`, - }); - } - - /// - /// LOCALIZED ATTRIBUTES SETTINGS - /// - - /** - * Get the localized attributes settings. - * - * @returns Promise containing object of localized attributes settings - */ - async getLocalizedAttributes(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/localized-attributes`, - }); - } - - /** - * Update the localized attributes settings. - * - * @param localizedAttributes - Localized attributes object - * @returns Promise containing an EnqueuedTask - */ - updateLocalizedAttributes( - localizedAttributes: LocalizedAttributes, - ): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/localized-attributes`, - body: localizedAttributes, - }); - } - - /** - * Reset the localized attributes settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetLocalizedAttributes(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/localized-attributes`, - }); - } - - /// - /// FACET SEARCH SETTINGS - /// - - /** - * Get the facet search settings. - * - * @returns Promise containing object of facet search settings - */ - async getFacetSearch(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/facet-search`, - }); - } - - /** - * Update the facet search settings. - * - * @param facetSearch - Boolean value - * @returns Promise containing an EnqueuedTask - */ - updateFacetSearch(facetSearch: boolean): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/facet-search`, - body: facetSearch, - }); - } - - /** - * Reset the facet search settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetFacetSearch(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/facet-search`, - }); - } - - /// - /// PREFIX SEARCH SETTINGS - /// - - /** - * Get the prefix search settings. - * - * @returns Promise containing object of prefix search settings - */ - async getPrefixSearch(): Promise { - return await this.httpRequest.get({ - path: `indexes/${this.uid}/settings/prefix-search`, - }); - } - - /** - * Update the prefix search settings. - * - * @param prefixSearch - PrefixSearch value - * @returns Promise containing an EnqueuedTask - */ - updatePrefixSearch(prefixSearch: PrefixSearch): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.put({ - path: `indexes/${this.uid}/settings/prefix-search`, - body: prefixSearch, - }); - } - - /** - * Reset the prefix search settings. - * - * @returns Promise containing an EnqueuedTask - */ - resetPrefixSearch(): EnqueuedTaskPromise { - return this.#httpRequestsWithTask.delete({ - path: `indexes/${this.uid}/settings/prefix-search`, - }); + get setting() { + return this.#setting; } } diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 000000000..841c119ec --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,66 @@ +import type { HttpRequests } from "./http-requests.js"; +import type { HttpRequestsWithEnqueuedTaskPromise } from "./task.js"; +import type { + EnqueuedTaskPromise, + SingleUpdatableSettings, + RecordAny, +} from "./types/index.js"; + +/** Each setting property mapped to their REST method required for updates. */ +type MakeSettingsRecord = { + [TKey in keyof SingleUpdatableSettings]: "put" | "patch"; +}; + +/** Each setting property mapped to its get, update and reset functions. */ +export type SettingFns = { + [TKey in keyof SingleUpdatableSettings as `get${Capitalize}`]: () => Promise< + SingleUpdatableSettings[TKey] + >; +} & { + [TKey in keyof SingleUpdatableSettings as `update${Capitalize}`]: ( + body: SingleUpdatableSettings[TKey], + ) => EnqueuedTaskPromise; +} & { + [TKey in keyof SingleUpdatableSettings as `reset${Capitalize}`]: () => EnqueuedTaskPromise; +}; + +function capitalize(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +function camelToKebabCase(str: string): string { + return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); +} + +/** Returns an object containing all the setting functions. */ +export function makeSettingFns( + httpRequest: HttpRequests, + httpRequestsWithTask: HttpRequestsWithEnqueuedTaskPromise, + basePath: string, + opts: MakeSettingsRecord, +): SettingFns { + const settingFns = {} as RecordAny; + + for (const [name, method] of Object.entries(opts)) { + const uppercaseName = capitalize(name); + const path = `${basePath}/${camelToKebabCase(name)}`; + + settingFns[`get${uppercaseName}`] = async function (): Promise< + SingleUpdatableSettings[keyof typeof opts] + > { + return await httpRequest.get({ path }); + }; + + settingFns[`update${uppercaseName}`] = function ( + body: SingleUpdatableSettings[keyof typeof opts], + ): EnqueuedTaskPromise { + return httpRequestsWithTask[method]({ path, body }); + }; + + settingFns[`reset${uppercaseName}`] = function (): EnqueuedTaskPromise { + return httpRequestsWithTask.delete({ path }); + }; + } + + return settingFns as SettingFns; +} diff --git a/src/types/index.ts b/src/types/index.ts index 8aaa23dba..8b0d1a3e7 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,4 +1,5 @@ export * from "./experimental-features.js"; +export * from "./settings.js"; export * from "./task_and_batch.js"; export * from "./token.js"; export * from "./types.js"; diff --git a/src/types/settings.ts b/src/types/settings.ts new file mode 100644 index 000000000..7959dfcda --- /dev/null +++ b/src/types/settings.ts @@ -0,0 +1,224 @@ +import type { PascalToCamelCase } from "./shared.js"; + +/** @see `milli::filterable_attributes_rules::FilterFeatures` */ +export type FilterFeatures = { + equality?: boolean; + comparison?: boolean; +}; + +/** @see `milli::filterable_attributes_rules::FilterableAttributesFeatures` */ +export type FilterableAttributesFeatures = { + facetSearch?: boolean; + filter?: FilterFeatures; +}; + +/** @see `milli::filterable_attributes_rules::FilterableAttributesPatterns` */ +export type FilterableAttributesPatterns = { + attributePatterns: string[]; + features?: FilterableAttributesFeatures; +}; + +/** @see `milli::filterable_attributes_rules::FilterableAttributesRule` */ +export type FilterableAttributesRule = string | FilterableAttributesPatterns; + +/** Deeply map every property of a record to itself excluding null. */ +type NonNullableDeepRecordValues = { + [TKey in keyof T]: Exclude, null>; +}; + +/** Map properties of a record to be optional and nullable. */ +type PartialAndNullable = { [P in keyof T]?: T[P] | null }; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#proximity-precision} + * + * @see `meilisearch_types::settings::ProximityPrecisionView` + */ +export type ProximityPrecisionView = PascalToCamelCase< + "ByWord" | "ByAttribute" +>; + +/** + * @see `minWordSizeForTypos` at {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance} + * + * @see `meilisearch_types::settings::MinWordSizeTyposSetting` + */ +export type MinWordSizeTyposSetting = PartialAndNullable<{ + oneTypo: number; + twoTypos: number; +}>; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance} + * + * @see `meilisearch_types::settings::TypoSettings` + */ +export type TypoSettings = PartialAndNullable<{ + enabled: boolean; + minWordSizeForTypos: MinWordSizeTyposSetting; + disableOnWords: string[]; + disableOnAttributes: string[]; +}>; + +/** + * @see `sortFacetValuesBy` at {@link https://www.meilisearch.com/docs/reference/api/settings#faceting} + * @see `meilisearch_types::facet_values_sort::FacetValuesSort` + */ +export type FacetValuesSort = PascalToCamelCase<"Alpha" | "Count">; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#faceting} + * + * @see `meilisearch_types::settings::FacetingSettings` + */ +export type FacetingSettings = PartialAndNullable<{ + maxValuesPerFacet: number; + sortFacetValuesBy: Record; +}>; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#pagination} + * + * @see `meilisearch_types::settings::PaginationSettings` + */ +export type PaginationSettings = PartialAndNullable<{ maxTotalHits: number }>; + +/** + * `distribution` at + * {@link https://www.meilisearch.com/docs/reference/api/settings#embedders} + * + * @see `milli::vector::DistributionShift` + */ +export type DistributionShift = { + mean: number; + sigma: number; +}; + +/** + * `source` at + * {@link https://www.meilisearch.com/docs/reference/api/settings#embedders} + * + * @see `milli::vector::settings::EmbedderSource` + */ +export type EmbedderSource = PascalToCamelCase< + "OpenAi" | "HuggingFace" | "Ollama" | "UserProvided" | "Rest" | "Composite" +>; + +/** @see `milli::vector::hf::OverridePooling` */ +export type OverridePooling = PascalToCamelCase< + "UseModel" | "ForceCls" | "ForceMean" +>; + +/** @see `milli::vector::settings::SubEmbeddingSettings` */ +export type SubEmbeddingSettings = PartialAndNullable<{ + source: EmbedderSource; + model: string; + revision: string; + pooling: OverridePooling; + apiKey: string; + dimensions: number; + documentTemplate: string; + documentTemplateMaxBytes: number; + url: string; + request: unknown; + response: unknown; + headers: Record; +}>; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#embedders} + * + * @see `milli::vector::settings::EmbeddingSettings` + */ +export type EmbeddingSettings = PartialAndNullable<{ + distribution: DistributionShift; + binaryQuantized: boolean; + searchEmbedder: SubEmbeddingSettings; + indexingEmbedder: SubEmbeddingSettings; +}> & + SubEmbeddingSettings; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#localized-attributes} + * + * @see `meilisearch_types::locales::LocalizedAttributesRuleView` + */ +export type LocalizedAttributesRuleView = { + /** @see `milli::attribute_patterns::AttributePatterns` */ + attributePatterns: string[]; + /** @see `meilisearch_types::locales::Locale` */ + locales: string[]; +}; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#prefix-search} + * + * @see `meilisearch_types::settings::PrefixSearchSettings` + */ +export type PrefixSearchSettings = PascalToCamelCase< + "IndexingTime" | "Disabled" +>; + +/** @see `meilisearch_types::settings::RankingRuleView` */ +export type RankingRuleView = + | PascalToCamelCase< + "Words" | "Typo" | "Proximity" | "Attribute" | "Sort" | "Exactness" + > + | `${string}:${"asc" | "desc"}`; + +/** A version of {@link Settings} that can be used to update the settings. */ +export type UpdatableSettings = PartialAndNullable<{ + /** {@link https://www.meilisearch.com/docs/reference/api/settings#displayed-attributes} */ + displayedAttributes: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#searchable-attributes} */ + searchableAttributes: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#filterable-attributes} */ + filterableAttributes: FilterableAttributesRule[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#sortable-attributes} */ + sortableAttributes: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#ranking-rules} */ + rankingRules: RankingRuleView[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#stop-words} */ + stopWords: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#non-separator-tokens} */ + nonSeparatorTokens: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#separator-tokens} */ + separatorTokens: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#dictionary} */ + dictionary: string[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#synonyms} */ + synonyms: Record; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#distinct-attribute} */ + distinctAttribute: string; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#proximity-precision} */ + proximityPrecision: ProximityPrecisionView; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance} */ + typoTolerance: TypoSettings; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#faceting} */ + faceting: FacetingSettings; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#pagination} */ + pagination: PaginationSettings; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#embedders} */ + embedders: PartialAndNullable>; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#search-cutoff} */ + searchCutoffMs: number; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#localized-attributes} */ + localizedAttributes: LocalizedAttributesRuleView[]; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#facet-search} */ + facetSearch: boolean; + /** {@link https://www.meilisearch.com/docs/reference/api/settings#prefix-search} */ + prefixSearch: PrefixSearchSettings; +}>; + +/** + * A version of {@link UpdatableSettings}, the first layer of properties of which + * is used to update or get individual settings. + */ +export type SingleUpdatableSettings = Required; + +/** + * {@link https://www.meilisearch.com/docs/reference/api/settings#body} + * + * @see `meilisearch_types::settings::Settings` + */ +export type Settings = NonNullableDeepRecordValues; diff --git a/src/types/shared.ts b/src/types/shared.ts index d475d6948..4678a0988 100644 --- a/src/types/shared.ts +++ b/src/types/shared.ts @@ -1,5 +1,3 @@ -import type { RecordAny } from "./types.js"; - export type CursorResults = { results: T[]; limit: number; @@ -8,11 +6,5 @@ export type CursorResults = { total: number; }; -export type NonNullableDeepRecordValues = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [P in keyof T]: T[P] extends any[] - ? Array> - : T[P] extends RecordAny - ? NonNullableDeepRecordValues - : NonNullable; -}; +// taken from https://stackoverflow.com/a/65642944 +export type PascalToCamelCase = Uncapitalize; diff --git a/src/types/task_and_batch.ts b/src/types/task_and_batch.ts index ea61fbea9..8efed6b7f 100644 --- a/src/types/task_and_batch.ts +++ b/src/types/task_and_batch.ts @@ -1,4 +1,4 @@ -import type { Settings } from "./types.js"; +import type { UpdatableSettings } from "./settings.js"; import type { CursorResults } from "./shared.js"; import type { MeiliSearchErrorResponse } from "./types.js"; @@ -97,7 +97,7 @@ export type TaskUidOrEnqueuedTask = EnqueuedTask["taskUid"] | EnqueuedTask; export type IndexSwap = { indexes: [string, string] }; /** {@link https://www.meilisearch.com/docs/reference/api/tasks#details} */ -export type TaskDetails = Settings & { +export type TaskDetails = UpdatableSettings & { receivedDocuments?: number; indexedDocuments?: number; editedDocuments?: number; diff --git a/src/types/types.ts b/src/types/types.ts index 91d29f4b5..818f3578f 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -498,174 +498,6 @@ export type UpdateDocumentsByFunctionOptions = { context?: RecordAny; }; -/* - ** Settings - */ - -type GranularFilterableAttribute = { - attributePatterns: string[]; - features: { - facetSearch: boolean; - filter: { equality: boolean; comparison: boolean }; - }; -}; - -export type FilterableAttributes = - | (string | GranularFilterableAttribute)[] - | null; -export type DistinctAttribute = string | null; -export type SearchableAttributes = string[] | null; -export type SortableAttributes = string[] | null; -export type DisplayedAttributes = string[] | null; -export type RankingRules = string[] | null; -export type StopWords = string[] | null; -export type Synonyms = Record | null; -export type TypoTolerance = { - enabled?: boolean | null; - disableOnAttributes?: string[] | null; - disableOnWords?: string[] | null; - minWordSizeForTypos?: { - oneTypo?: number | null; - twoTypos?: number | null; - }; -} | null; -export type SeparatorTokens = string[] | null; -export type NonSeparatorTokens = string[] | null; -export type Dictionary = string[] | null; -export type ProximityPrecision = "byWord" | "byAttribute"; - -export type Distribution = { - mean: number; - sigma: number; -}; - -export type OpenAiEmbedder = { - source: "openAi"; - model?: string; - apiKey?: string; - documentTemplate?: string; - dimensions?: number; - distribution?: Distribution; - url?: string; - documentTemplateMaxBytes?: number; - binaryQuantized?: boolean; -}; - -export type HuggingFaceEmbedder = { - source: "huggingFace"; - model?: string; - revision?: string; - documentTemplate?: string; - distribution?: Distribution; - pooling?: "useModel" | "forceMean" | "forceCls"; - documentTemplateMaxBytes?: number; - binaryQuantized?: boolean; -}; - -export type UserProvidedEmbedder = { - source: "userProvided"; - dimensions: number; - distribution?: Distribution; - binaryQuantized?: boolean; -}; - -export type RestEmbedder = { - source: "rest"; - url: string; - apiKey?: string; - dimensions?: number; - documentTemplate?: string; - distribution?: Distribution; - request: RecordAny; - response: RecordAny; - headers?: Record; - documentTemplateMaxBytes?: number; - binaryQuantized?: boolean; -}; - -export type OllamaEmbedder = { - source: "ollama"; - url?: string; - apiKey?: string; - model?: string; - documentTemplate?: string; - distribution?: Distribution; - dimensions?: number; - documentTemplateMaxBytes?: number; - binaryQuantized?: boolean; -}; - -export type CompositeEmbedder = { - source: "composite"; - searchEmbedder: Embedder; - indexingEmbedder: Embedder; -}; - -export type Embedder = - | OpenAiEmbedder - | HuggingFaceEmbedder - | UserProvidedEmbedder - | RestEmbedder - | OllamaEmbedder - | CompositeEmbedder - | null; - -export type Embedders = Record | null; - -export type FacetOrder = "alpha" | "count"; - -export type Faceting = { - maxValuesPerFacet?: number | null; - sortFacetValuesBy?: Record | null; -}; - -export type PaginationSettings = { - maxTotalHits?: number | null; -}; - -export type SearchCutoffMs = number | null; - -export type LocalizedAttribute = { - attributePatterns: string[]; - locales: Locale[]; -}; - -export type LocalizedAttributes = LocalizedAttribute[] | null; - -export type PrefixSearch = "indexingTime" | "disabled"; - -export type Settings = { - filterableAttributes?: FilterableAttributes; - distinctAttribute?: DistinctAttribute; - sortableAttributes?: SortableAttributes; - searchableAttributes?: SearchableAttributes; - displayedAttributes?: DisplayedAttributes; - rankingRules?: RankingRules; - stopWords?: StopWords; - synonyms?: Synonyms; - typoTolerance?: TypoTolerance; - faceting?: Faceting; - pagination?: PaginationSettings; - separatorTokens?: SeparatorTokens; - nonSeparatorTokens?: NonSeparatorTokens; - dictionary?: Dictionary; - proximityPrecision?: ProximityPrecision; - embedders?: Embedders; - searchCutoffMs?: SearchCutoffMs; - localizedAttributes?: LocalizedAttributes; - - /** - * Enable facet searching on all the filters of an index (requires Meilisearch - * 1.12.0 or later) - */ - facetSearch?: boolean; - /** - * Enable the ability to search a word by prefix on an index (requires - * Meilisearch 1.12.0 or later) - */ - prefixSearch?: "indexingTime" | "disabled"; -}; - /* *** HEALTH */ diff --git a/tests/__snapshots__/settings.test.ts.snap b/tests/__snapshots__/settings.test.ts.snap deleted file mode 100644 index f755b2549..000000000 --- a/tests/__snapshots__/settings.test.ts.snap +++ /dev/null @@ -1,1383 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`Test on settings > Admin key: Get default settings of an index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Get default settings of empty index with primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Reset embedders settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Reset settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Reset settings of empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update embedders settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": { - "default": { - "documentTemplate": "{% for field in fields %}{% if field.is_searchable and field.value != nil %}{{ field.name }}: {{ field.value }} -{% endif %}{% endfor %}", - "documentTemplateMaxBytes": 400, - "model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - "pooling": "useModel", - "source": "huggingFace", - }, - }, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update facetSearch settings on empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": false, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update prefixSearch settings on an empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "disabled", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update searchableAttributes settings on empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update searchableAttributes settings on empty index with a primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update settings 1`] = ` -{ - "dictionary": [ - "J. K.", - "J. R. R.", - ], - "displayedAttributes": [ - "title", - ], - "distinctAttribute": "title", - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 50, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [ - "title", - ], - "localizedAttributes": null, - "nonSeparatorTokens": [ - "&sep", - "/", - "|", - ], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byAttribute", - "rankingRules": [ - "id:asc", - "typo", - ], - "searchCutoffMs": 1000, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [ - "&sep", - "/", - "|", - ], - "sortableAttributes": [ - "title", - ], - "stopWords": [ - "the", - ], - "synonyms": { - "harry": [ - "potter", - ], - }, - "typoTolerance": { - "disableOnAttributes": [ - "comment", - ], - "disableOnWords": [ - "prince", - ], - "enabled": false, - "minWordSizeForTypos": { - "oneTypo": 1, - "twoTypos": 100, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update settings on empty index with primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": "title", - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "title:asc", - "typo", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [ - "the", - ], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Admin key: Update settings with all null values 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Get default settings of an index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Get default settings of empty index with primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Reset embedders settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Reset settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Reset settings of empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update embedders settings 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": { - "default": { - "documentTemplate": "{% for field in fields %}{% if field.is_searchable and field.value != nil %}{{ field.name }}: {{ field.value }} -{% endif %}{% endfor %}", - "documentTemplateMaxBytes": 400, - "model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - "pooling": "useModel", - "source": "huggingFace", - }, - }, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update facetSearch settings on empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": false, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update prefixSearch settings on an empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "disabled", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update searchableAttributes settings on empty index 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update searchableAttributes settings on empty index with a primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update settings 1`] = ` -{ - "dictionary": [ - "J. K.", - "J. R. R.", - ], - "displayedAttributes": [ - "title", - ], - "distinctAttribute": "title", - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 50, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [ - "title", - ], - "localizedAttributes": null, - "nonSeparatorTokens": [ - "&sep", - "/", - "|", - ], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byAttribute", - "rankingRules": [ - "id:asc", - "typo", - ], - "searchCutoffMs": 1000, - "searchableAttributes": [ - "title", - ], - "separatorTokens": [ - "&sep", - "/", - "|", - ], - "sortableAttributes": [ - "title", - ], - "stopWords": [ - "the", - ], - "synonyms": { - "harry": [ - "potter", - ], - }, - "typoTolerance": { - "disableOnAttributes": [ - "comment", - ], - "disableOnWords": [ - "prince", - ], - "enabled": false, - "minWordSizeForTypos": { - "oneTypo": 1, - "twoTypos": 100, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update settings on empty index with primary key 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": "title", - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "title:asc", - "typo", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [ - "the", - ], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; - -exports[`Test on settings > Master key: Update settings with all null values 1`] = ` -{ - "dictionary": [], - "displayedAttributes": [ - "*", - ], - "distinctAttribute": null, - "embedders": {}, - "facetSearch": true, - "faceting": { - "maxValuesPerFacet": 100, - "sortFacetValuesBy": { - "*": "alpha", - }, - }, - "filterableAttributes": [], - "localizedAttributes": null, - "nonSeparatorTokens": [], - "pagination": { - "maxTotalHits": 1000, - }, - "prefixSearch": "indexingTime", - "proximityPrecision": "byWord", - "rankingRules": [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", - ], - "searchCutoffMs": null, - "searchableAttributes": [ - "*", - ], - "separatorTokens": [], - "sortableAttributes": [], - "stopWords": [], - "synonyms": {}, - "typoTolerance": { - "disableOnAttributes": [], - "disableOnWords": [], - "enabled": true, - "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 9, - }, - }, -} -`; diff --git a/tests/dictionary.test.ts b/tests/dictionary.test.ts deleted file mode 100644 index c4ca74a78..000000000 --- a/tests/dictionary.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on dictionary", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default dictionary`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getDictionary(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Update dictionary`, async () => { - const client = await getClient(permission); - const newDictionary = ["J. K.", "J. R. R."]; - await client.index(index.uid).updateDictionary(newDictionary).waitTask(); - - const response = await client.index(index.uid).getDictionary(); - - expect(response).toEqual(newDictionary); - }); - - test(`${permission} key: Update dictionary with null value`, async () => { - const client = await getClient(permission); - const newDictionary = null; - await client.index(index.uid).updateDictionary(newDictionary).waitTask(); - - const response = await client.index(index.uid).getDictionary(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Reset dictionary`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetDictionary().waitTask(); - - const response = await client.index(index.uid).getDictionary(); - - expect(response).toEqual([]); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getDictionary route`, async () => { - const route = `indexes/${index.uid}/settings/dictionary`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getDictionary(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateDictionary route`, async () => { - const route = `indexes/${index.uid}/settings/dictionary`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateDictionary([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetDictionary route`, async () => { - const route = `indexes/${index.uid}/settings/dictionary`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetDictionary(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/displayed_attributes.test.ts b/tests/displayed_attributes.test.ts deleted file mode 100644 index b2779437d..000000000 --- a/tests/displayed_attributes.test.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on displayed attributes", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default displayed attributes`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getDisplayedAttributes(); - expect(response).toEqual(["*"]); - }); - - test(`${permission} key: Update displayed attributes`, async () => { - const client = await getClient(permission); - const newDisplayedAttribute = ["title"]; - await client - .index(index.uid) - .updateDisplayedAttributes(newDisplayedAttribute) - .waitTask(); - - const response = await client.index(index.uid).getDisplayedAttributes(); - - expect(response).toEqual(newDisplayedAttribute); - }); - - test(`${permission} key: Update displayed attributes at null`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).updateDisplayedAttributes(null).waitTask(); - - const response = await client.index(index.uid).getDisplayedAttributes(); - - expect(response).toEqual(["*"]); - }); - - test(`${permission} key: Reset displayed attributes`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).resetDisplayedAttributes().waitTask(); - - const response = await client.index(index.uid).getDisplayedAttributes(); - - expect(response).toEqual(["*"]); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on displayed attributes", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getDisplayedAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateDisplayedAttributes([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetDisplayedAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on displayed attributes", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getDisplayedAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateDisplayedAttributes([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset displayed attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetDisplayedAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getDisplayedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/displayed-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getDisplayedAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateDisplayedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/displayed-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateDisplayedAttributes([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetDisplayedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/displayed-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetDisplayedAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/distinct_attribute.test.ts b/tests/distinct_attribute.test.ts deleted file mode 100644 index ae9907ac7..000000000 --- a/tests/distinct_attribute.test.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on distinct attribute", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("master"); - - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default distinct attribute`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getDistinctAttribute(); - expect(response).toEqual(null); - }); - - test(`${permission} key: Update distinct attribute`, async () => { - const client = await getClient(permission); - const newDistinctAttribute = "title"; - await client - .index(index.uid) - .updateDistinctAttribute(newDistinctAttribute) - .waitTask(); - - const response = await client.index(index.uid).getDistinctAttribute(); - - expect(response).toEqual(newDistinctAttribute); - }); - - test(`${permission} key: Update distinct attribute at undefined`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateDistinctAttribute(null).waitTask(); - - const response = await client.index(index.uid).getDistinctAttribute(); - - expect(response).toEqual(null); - }); - - test(`${permission} key: Reset distinct attribute`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetDistinctAttribute().waitTask(); - - const response = await client.index(index.uid).getDistinctAttribute(); - - expect(response).toEqual(null); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on distinct attribute", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getDistinctAttribute(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateDistinctAttribute("title"), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetDistinctAttribute(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on distinct attribute", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getDistinctAttribute(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateDistinctAttribute("title"), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset distinct attribute and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetDistinctAttribute(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getDistinctAttribute route`, async () => { - const route = `indexes/${index.uid}/settings/distinct-attribute`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getDistinctAttribute(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateDistinctAttribute route`, async () => { - const route = `indexes/${index.uid}/settings/distinct-attribute`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateDistinctAttribute("a"), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetDistinctAttribute route`, async () => { - const route = `indexes/${index.uid}/settings/distinct-attribute`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetDistinctAttribute(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/documents.test.ts b/tests/documents.test.ts index e9c958761..860ad3000 100644 --- a/tests/documents.test.ts +++ b/tests/documents.test.ts @@ -142,7 +142,7 @@ describe("Documents tests", () => { await client .index(indexPk.uid) - .updateFilterableAttributes(["id"]) + .setting.updateFilterableAttributes(["id"]) .waitTask(); await client.index(indexPk.uid).addDocuments(dataset).waitTask(); @@ -491,7 +491,9 @@ describe("Documents tests", () => { test(`${permission} key: Delete some documents with string filters`, async () => { const client = await getClient(permission); - await client.index(indexPk.uid).updateFilterableAttributes(["id"]); + await client + .index(indexPk.uid) + .setting.updateFilterableAttributes(["id"]); await client.index(indexPk.uid).addDocuments(dataset).waitTask(); const resolvedTask = await client @@ -507,7 +509,9 @@ describe("Documents tests", () => { test(`${permission} key: Delete some documents with array filters`, async () => { const client = await getClient(permission); - await client.index(indexPk.uid).updateFilterableAttributes(["id"]); + await client + .index(indexPk.uid) + .setting.updateFilterableAttributes(["id"]); await client.index(indexPk.uid).addDocuments(dataset).waitTask(); const resolvedTask = await client @@ -681,7 +685,7 @@ describe("Documents tests", () => { const client = await getClient(permission); const index = client.index<(typeof dataset)[number]>(indexPk.uid); - await index.updateFilterableAttributes(["id"]).waitTask(); + await index.setting.updateFilterableAttributes(["id"]).waitTask(); await ( await getClient("Master") diff --git a/tests/dump.test.ts b/tests/dump.test.ts index 75c971533..9c399084b 100644 --- a/tests/dump.test.ts +++ b/tests/dump.test.ts @@ -1,5 +1,5 @@ import { expect, test, describe, beforeEach, assert } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { clearAllIndexes, config, diff --git a/tests/embedders.test.ts b/tests/embedders.test.ts deleted file mode 100644 index 63d6f09ad..000000000 --- a/tests/embedders.test.ts +++ /dev/null @@ -1,411 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import type { Embedders } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - masterClient, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -const datasetSimilarSearch = [ - { - title: "Shazam!", - release_year: 2019, - id: "287947", - _vectors: { manual: [0.8, 0.4, -0.5] }, - }, - { - title: "Captain Marvel", - release_year: 2019, - id: "299537", - _vectors: { manual: [0.6, 0.8, -0.2] }, - }, - { - title: "Escape Room", - release_year: 2019, - id: "522681", - _vectors: { manual: [0.1, 0.6, 0.8] }, - }, - { - title: "How to Train Your Dragon: The Hidden World", - release_year: 2019, - id: "166428", - _vectors: { manual: [0.7, 0.7, -0.4] }, - }, - { - title: "All Quiet on the Western Front", - release_year: 1930, - id: "143", - _vectors: { manual: [-0.5, 0.3, 0.85] }, - }, -]; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on embedders", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient(permission); - - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: Get default embedders`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual({}); - }); - - test(`${permission} key: Update embedders with 'userProvided' source`, async () => { - const client = await getClient(permission); - const newEmbedder: Embedders = { - default: { - source: "userProvided", - dimensions: 1, - distribution: { - mean: 0.7, - sigma: 0.3, - }, - binaryQuantized: false, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual(newEmbedder); - expect(response).not.toHaveProperty("documentTemplateMaxBytes"); - }); - - test(`${permission} key: Update embedders with 'openAi' source`, async () => { - const client = await getClient(permission); - const newEmbedder: Embedders = { - default: { - source: "openAi", - apiKey: "", - model: "text-embedding-3-small", - documentTemplate: - "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", - dimensions: 1536, - distribution: { - mean: 0.7, - sigma: 0.3, - }, - url: "https://api.openai.com/v1/embeddings", - documentTemplateMaxBytes: 500, - binaryQuantized: false, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual({ - default: { - ...newEmbedder.default, - apiKey: " { - const client = await getClient(permission); - const newEmbedder: Embedders = { - default: { - source: "huggingFace", - model: "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - documentTemplate: - "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", - distribution: { - mean: 0.7, - sigma: 0.3, - }, - pooling: "useModel", - documentTemplateMaxBytes: 500, - binaryQuantized: false, - }, - }; - await client - .index(index.uid) - .updateEmbedders(newEmbedder) - .waitTask({ timeout: 60_000 }); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual(newEmbedder); - }); - - test(`${permission} key: Update embedders with 'rest' source`, async () => { - const client = await getClient(permission); - const newEmbedder: Embedders = { - default: { - source: "rest", - url: "https://api.openai.com/v1/embeddings", - apiKey: "", - dimensions: 1536, - documentTemplate: - "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", - distribution: { - mean: 0.7, - sigma: 0.3, - }, - request: { - model: "text-embedding-3-small", - input: ["{{text}}", "{{..}}"], - }, - response: { - data: [ - { - embedding: "{{embedding}}", - }, - "{{..}}", - ], - }, - headers: { - "Custom-Header": "CustomValue", - }, - documentTemplateMaxBytes: 500, - binaryQuantized: false, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual({ - default: { - ...newEmbedder.default, - apiKey: " { - const client = await getClient(permission); - const newEmbedder: Embedders = { - default: { - source: "ollama", - url: "http://localhost:11434/api/embeddings", - apiKey: "", - model: "nomic-embed-text", - documentTemplate: "blabla", - distribution: { - mean: 0.7, - sigma: 0.3, - }, - dimensions: 512, - documentTemplateMaxBytes: 500, - binaryQuantized: false, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual({ - default: { - ...newEmbedder.default, - apiKey: " { - const client = await getClient(permission); - - const newEmbedder: Embedders = { - image: { - source: "userProvided", - dimensions: 512, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual(newEmbedder); - }); - - test(`${permission} key: Update embedders with composite embedder`, async () => { - // first enable the network endpoint. - await masterClient.updateExperimentalFeatures({ - compositeEmbedders: true, - }); - - const client = await getClient(permission); - const embedders = { - default: { - source: "composite", - searchEmbedder: { - source: "huggingFace", - model: - "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - pooling: "useModel", - }, - indexingEmbedder: { - source: "huggingFace", - model: - "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - documentTemplate: "{{doc.title}}", - pooling: "useModel", - documentTemplateMaxBytes: 500, - }, - }, - } satisfies Embedders; - - const task = await client - .index(index.uid) - .updateEmbedders(embedders) - .waitTask(); - const response: Embedders = await client.index(index.uid).getEmbedders(); - - const processedTask = await client.tasks.getTask(task.uid); - expect(processedTask.status).toEqual("succeeded"); - expect(response).toEqual(embedders); - }); - - test(`${permission} key: Reset embedders`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetEmbedders().waitTask(); - - const response = await client.index(index.uid).getEmbedders(); - - expect(response).toEqual({}); - }); - - test(`${permission} key: search (POST) with vectors`, async () => { - const client = await getClient(permission); - - await client - .index(index.uid) - .updateEmbedders({ - default: { - source: "userProvided", - dimensions: 1, - }, - }) - .waitTask(); - - const response = await client.index(index.uid).search("", { - vector: [1], - hybrid: { - embedder: "default", - semanticRatio: 1.0, - }, - }); - - expect(response).toHaveProperty("hits"); - expect(response).toHaveProperty("semanticHitCount"); - // Those fields are no longer returned by the search response - // We want to ensure that they don't appear in it anymore - expect(response).not.toHaveProperty("vector"); - expect(response).not.toHaveProperty("_semanticScore"); - }); - - test(`${permission} key: search (GET) with vectors`, async () => { - const client = await getClient(permission); - - await client - .index(index.uid) - .updateEmbedders({ - default: { - source: "userProvided", - dimensions: 1, - }, - }) - .waitTask(); - - const response = await client.index(index.uid).searchGet("", { - vector: [1], - hybridEmbedder: "default", - hybridSemanticRatio: 1.0, - }); - - expect(response).toHaveProperty("hits"); - expect(response).toHaveProperty("semanticHitCount"); - // Those fields are no longer returned by the search response - // We want to ensure that they don't appear in it anymore - expect(response).not.toHaveProperty("vector"); - expect(response).not.toHaveProperty("_semanticScore"); - }); - - test(`${permission} key: search for similar documents`, async () => { - const client = await getClient(permission); - - const newEmbedder: Embedders = { - manual: { - source: "userProvided", - dimensions: 3, - }, - }; - await client.index(index.uid).updateEmbedders(newEmbedder).waitTask(); - - await client - .index(index.uid) - .addDocuments(datasetSimilarSearch) - .waitTask(); - - const response = await client.index(index.uid).searchSimilarDocuments({ - embedder: "manual", - id: "143", - }); - - expect(response).toHaveProperty("hits"); - expect(response.hits.length).toEqual(4); - expect(response).toHaveProperty("offset", 0); - expect(response).toHaveProperty("limit", 20); - expect(response).toHaveProperty("estimatedTotalHits", 4); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getEmbedders route`, async () => { - const route = `indexes/${index.uid}/settings/embedders`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect(client.index(index.uid).getEmbedders()).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateEmbedders route`, async () => { - const route = `indexes/${index.uid}/settings/embedders`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateEmbedders({}), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetEmbedders route`, async () => { - const route = `indexes/${index.uid}/settings/embedders`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetEmbedders(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/env/node/getting_started.cjs b/tests/env/node/getting_started.cjs index f16d357c6..43fbf90ce 100644 --- a/tests/env/node/getting_started.cjs +++ b/tests/env/node/getting_started.cjs @@ -19,7 +19,7 @@ const { MeiliSearch } = require('../../../dist/cjs/index.cjs') ] // If the index 'movies' does not exist, MeiliSearch creates it when you first add the documents. - await index.updateFilterableAttributes([ + await index.setting.updateFilterableAttributes([ 'director', 'genres', 'id' diff --git a/tests/facet_search_settings.test.ts b/tests/facet_search_settings.test.ts deleted file mode 100644 index d1bb67dbe..000000000 --- a/tests/facet_search_settings.test.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on facet search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get facetSearch settings on empty index`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getFacetSearch(); - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Set facetSearch settings with dedicated endpoint on empty index`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).updateFacetSearch(false).waitTask(); - - const updatedSettings = await client.index(index.uid).getFacetSearch(); - expect(updatedSettings).toBe(false); - }); - - test(`${permission} key: Reset facetSearch settings on an empty index`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).resetFacetSearch().waitTask(); - - const response = await client.index(index.uid).getFacetSearch(); - expect(response).toMatchSnapshot(); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on facet search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getFacetSearch(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFacetSearch(false), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFacetSearch(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on facet search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getFacetSearch(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFacetSearch(false), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset facet search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFacetSearch(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getFacetSearch route`, async () => { - const route = `indexes/${index.uid}/settings/facet-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getFacetSearch(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateFacetSearch route`, async () => { - const route = `indexes/${index.uid}/settings/facet-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateFacetSearch(false), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetFacetSearch route`, async () => { - const route = `indexes/${index.uid}/settings/facet-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetFacetSearch(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/faceting.test.ts b/tests/faceting.test.ts deleted file mode 100644 index dc942b810..000000000 --- a/tests/faceting.test.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { - expect, - test, - describe, - beforeEach, - afterAll, - beforeAll, -} from "vitest"; -import { ErrorStatusCode, type Faceting } from "../src/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on faceting", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default faceting object`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getFaceting(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update faceting settings`, async () => { - const client = await getClient(permission); - const newFaceting: Faceting = { - maxValuesPerFacet: 12, - sortFacetValuesBy: { test: "count" }, - }; - await client.index(index.uid).updateFaceting(newFaceting).waitTask(); - - const response = await client.index(index.uid).getFaceting(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update faceting at null`, async () => { - const client = await getClient(permission); - await client - .index(index.uid) - .updateFaceting({ maxValuesPerFacet: null }) - .waitTask(); - - const response = await client.index(index.uid).getFaceting(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Reset faceting`, async () => { - const client = await getClient(permission); - await client - .index(index.uid) - .updateFaceting({ maxValuesPerFacet: 12 }) - .waitTask(); - - await client.index(index.uid).resetFaceting().waitTask(); - - const response = await client.index(index.uid).getFaceting(); - - expect(response).toMatchSnapshot(); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on faceting", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get faceting and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getFaceting(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update faceting and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFaceting({ maxValuesPerFacet: 13 }), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset faceting and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFaceting(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])("Test on faceting", ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get faceting and be denied`, async () => { - const client = await getClient(permission); - await expect(client.index(index.uid).getFaceting()).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update faceting and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFaceting({ maxValuesPerFacet: 13 }), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset faceting and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFaceting(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); -}); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getFaceting route`, async () => { - const route = `indexes/${index.uid}/settings/faceting`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect(client.index(index.uid).getFaceting()).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateFaceting route`, async () => { - const route = `indexes/${index.uid}/settings/faceting`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateFaceting({ maxValuesPerFacet: undefined }), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetFaceting route`, async () => { - const route = `indexes/${index.uid}/settings/faceting`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetFaceting(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/filterable_attributes.test.ts b/tests/filterable_attributes.test.ts deleted file mode 100644 index c59c87942..000000000 --- a/tests/filterable_attributes.test.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { expect, test, describe, beforeEach, afterAll } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on searchable attributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default attributes for filtering`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getFilterableAttributes(); - - expect(response?.sort()).toEqual([]); - }); - - test(`${permission} key: Update attributes for filtering`, async () => { - const client = await getClient(permission); - const newFilterableAttributes = ["genre"]; - await client - .index(index.uid) - .updateFilterableAttributes(newFilterableAttributes) - .waitTask(); - - const response = await client.index(index.uid).getFilterableAttributes(); - expect(response).toEqual(newFilterableAttributes); - }); - - test(`${permission} key: Update attributes for filtering at null`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateFilterableAttributes(null).waitTask(); - - const response = await client.index(index.uid).getFilterableAttributes(); - - expect(response?.sort()).toEqual([]); - }); - - test(`${permission} key: Update attributes with granular attribute syntax`, async () => { - const client = await getClient(permission); - const newFilterableAttributes = [ - "author", - { - attributePatterns: ["genre"], - features: { - facetSearch: true, - filter: { equality: true, comparison: false }, - }, - }, - ]; - await client - .index(index.uid) - .updateFilterableAttributes(newFilterableAttributes) - .waitTask(); - - const response = await client.index(index.uid).getFilterableAttributes(); - expect(response).toEqual(newFilterableAttributes); - }); - - test(`${permission} key: Reset attributes for filtering`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetFilterableAttributes().waitTask(); - - const response = await client.index(index.uid).getFilterableAttributes(); - - expect(response?.sort()).toEqual([]); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on attributes for filtering", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getFilterableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFilterableAttributes([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFilterableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on attributes for filtering", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getFilterableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateFilterableAttributes([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset attributes for filtering and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetFilterableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getFilterableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/filterable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getFilterableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateFilterableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/filterable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateFilterableAttributes([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetFilterableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/filterable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetFilterableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/get_search.test.ts b/tests/get_search.test.ts index 3a6771b1d..1bb4b2d2d 100644 --- a/tests/get_search.test.ts +++ b/tests/get_search.test.ts @@ -1,5 +1,5 @@ import { expect, test, describe, afterAll, beforeAll } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { clearAllIndexes, config, diff --git a/tests/index.test.ts b/tests/index.test.ts index faea55881..b63d4eeff 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,5 +1,5 @@ import { expect, test, describe, beforeEach, afterAll } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { clearAllIndexes, config, diff --git a/tests/keys.test.ts b/tests/keys.test.ts index a1e305d07..9a5329962 100644 --- a/tests/keys.test.ts +++ b/tests/keys.test.ts @@ -1,6 +1,6 @@ import { expect, test, describe, beforeEach, afterAll } from "vitest"; import { MeiliSearch } from "../src/index.js"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { clearAllIndexes, config, diff --git a/tests/localized_attributes.test.ts b/tests/localized_attributes.test.ts deleted file mode 100644 index 963f406be..000000000 --- a/tests/localized_attributes.test.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { - afterAll, - beforeAll, - beforeEach, - describe, - expect, - test, -} from "vitest"; -import { - ErrorStatusCode, - type LocalizedAttributes, -} from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -const DEFAULT_LOCALIZED_ATTRIBUTES = null; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on localizedAttributes", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default localizedAttributes settings`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getLocalizedAttributes(); - - expect(response).toEqual(DEFAULT_LOCALIZED_ATTRIBUTES); - }); - - test(`${permission} key: Update localizedAttributes to valid value`, async () => { - const client = await getClient(permission); - const newLocalizedAttributes: LocalizedAttributes = [ - { attributePatterns: ["title"], locales: ["eng"] }, - ]; - await client - .index(index.uid) - .updateLocalizedAttributes(newLocalizedAttributes) - .waitTask(); - - const response = await client.index(index.uid).getLocalizedAttributes(); - - expect(response).toEqual(newLocalizedAttributes); - }); - - test(`${permission} key: Update localizedAttributes to null`, async () => { - const client = await getClient(permission); - const newLocalizedAttributes = null; - await client - .index(index.uid) - .updateLocalizedAttributes(newLocalizedAttributes) - .waitTask(); - - const response = await client.index(index.uid).getLocalizedAttributes(); - - expect(response).toEqual(DEFAULT_LOCALIZED_ATTRIBUTES); - }); - - test(`${permission} key: Update localizedAttributes with invalid value`, async () => { - const client = await getClient(permission); - const newLocalizedAttributes = "hello" as unknown as LocalizedAttributes; // bad localizedAttributes value - - await expect( - client - .index(index.uid) - .updateLocalizedAttributes(newLocalizedAttributes), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.INVALID_SETTINGS_LOCALIZED_ATTRIBUTES, - ); - }); - - test(`${permission} key: Reset localizedAttributes`, async () => { - const client = await getClient(permission); - const newLocalizedAttributes: LocalizedAttributes = []; - await client - .index(index.uid) - .updateLocalizedAttributes(newLocalizedAttributes) - .waitTask(); - await client.index(index.uid).resetLocalizedAttributes().waitTask(); - - const response = await client.index(index.uid).getLocalizedAttributes(); - - expect(response).toEqual(DEFAULT_LOCALIZED_ATTRIBUTES); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on localizedAttributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getLocalizedAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateLocalizedAttributes([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetLocalizedAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on localizedAttributes", - ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getLocalizedAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateLocalizedAttributes([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset localizedAttributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetLocalizedAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getLocalizedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/localized-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getLocalizedAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateLocalizedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/localized-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateLocalizedAttributes(null), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetLocalizedAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/localized-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetLocalizedAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/non_separator_tokens.test.ts b/tests/non_separator_tokens.test.ts deleted file mode 100644 index 28c9dae82..000000000 --- a/tests/non_separator_tokens.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { expect, test, describe, beforeEach, afterAll } from "vitest"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on non separator tokens", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default non separator tokens`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getNonSeparatorTokens(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Update non separator tokens`, async () => { - const client = await getClient(permission); - const newNonSeparatorTokens = ["&sep", "/", "|"]; - await client - .index(index.uid) - .updateNonSeparatorTokens(newNonSeparatorTokens) - .waitTask(); - - const response = await client.index(index.uid).getNonSeparatorTokens(); - - expect(response).toEqual(newNonSeparatorTokens); - }); - - test(`${permission} key: Update non separator tokens with null value`, async () => { - const client = await getClient(permission); - const newNonSeparatorTokens = null; - await client - .index(index.uid) - .updateNonSeparatorTokens(newNonSeparatorTokens) - .waitTask(); - - const response = await client.index(index.uid).getNonSeparatorTokens(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Reset NonSeparator tokens`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetNonSeparatorTokens().waitTask(); - - const response = await client.index(index.uid).getNonSeparatorTokens(); - - expect(response).toEqual([]); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getNonSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/non-separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getNonSeparatorTokens(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateNonSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/non-separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateNonSeparatorTokens([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetNonSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/non-separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetNonSeparatorTokens(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/pagination.test.ts b/tests/pagination.test.ts deleted file mode 100644 index f8736bf53..000000000 --- a/tests/pagination.test.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { - expect, - test, - describe, - beforeEach, - afterAll, - beforeAll, -} from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on pagination", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default pagination settings`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getPagination(); - - expect(response).toEqual({ maxTotalHits: 1000 }); - }); - - test(`${permission} key: Update pagination`, async () => { - const client = await getClient(permission); - const newPagination = { - maxTotalHits: 100, - }; - await client.index(index.uid).updatePagination(newPagination).waitTask(); - - const response = await client.index(index.uid).getPagination(); - - expect(response).toEqual(newPagination); - }); - - test(`${permission} key: Update pagination at null`, async () => { - const client = await getClient(permission); - const newPagination = { - maxTotalHits: null, - }; - await client.index(index.uid).updatePagination(newPagination).waitTask(); - - const response = await client.index(index.uid).getPagination(); - - expect(response).toEqual({ maxTotalHits: 1000 }); - }); - - test(`${permission} key: Reset pagination`, async () => { - const client = await getClient(permission); - const newPagination = { - maxTotalHits: 100, - }; - await client.index(index.uid).updatePagination(newPagination).waitTask(); - await client.index(index.uid).resetPagination().waitTask(); - - const response = await client.index(index.uid).getPagination(); - - expect(response).toEqual({ maxTotalHits: 1000 }); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on pagination", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getPagination(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updatePagination({ maxTotalHits: 10 }), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetPagination(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on pagination", - ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getPagination(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updatePagination({ maxTotalHits: 10 }), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset pagination and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetPagination(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getPagination route`, async () => { - const route = `indexes/${index.uid}/settings/pagination`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getPagination(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updatePagination route`, async () => { - const route = `indexes/${index.uid}/settings/pagination`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updatePagination({ maxTotalHits: null }), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetPagination route`, async () => { - const route = `indexes/${index.uid}/settings/pagination`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetPagination(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/prefix_search_settings.test.ts b/tests/prefix_search_settings.test.ts deleted file mode 100644 index 77685c5fc..000000000 --- a/tests/prefix_search_settings.test.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { afterAll, expect, test, describe, beforeEach } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on prefix search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get prefixSearch settings on empty index`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getPrefixSearch(); - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Set prefixSearch settings with dedicated endpoint on empty index`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).updatePrefixSearch("disabled").waitTask(); - - const updatedSettings = await client.index(index.uid).getPrefixSearch(); - expect(updatedSettings).toBe("disabled"); - }); - - test(`${permission} key: Reset prefixSearch settings on an empty index`, async () => { - const client = await getClient(permission); - - await client.index(index.uid).resetPrefixSearch().waitTask(); - - const response = await client.index(index.uid).getPrefixSearch(); - expect(response).toMatchSnapshot(); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on prefix search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getPrefixSearch(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updatePrefixSearch("disabled"), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetPrefixSearch(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on prefix search settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getPrefixSearch(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updatePrefixSearch("disabled"), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset prefix search settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetPrefixSearch(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getPrefixSearch route`, async () => { - const route = `indexes/${index.uid}/settings/prefix-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getPrefixSearch(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updatePrefixSearch route`, async () => { - const route = `indexes/${index.uid}/settings/prefix-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updatePrefixSearch("disabled"), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetPrefixSearch route`, async () => { - const route = `indexes/${index.uid}/settings/prefix-search`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetPrefixSearch(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/proximity_precision.test.ts b/tests/proximity_precision.test.ts deleted file mode 100644 index 8500ca3fd..000000000 --- a/tests/proximity_precision.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { afterAll, describe, test, beforeEach, expect } from "vitest"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on proximity precision", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default proximity precision`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getProximityPrecision(); - - expect(response).toEqual("byWord"); - }); - - test(`${permission} key: Update proximity precision with 'byAttribute' value`, async () => { - const client = await getClient(permission); - const newProximityPrecision = "byAttribute"; - await client - .index(index.uid) - .updateProximityPrecision(newProximityPrecision) - .waitTask(); - - const response = await client.index(index.uid).getProximityPrecision(); - - expect(response).toEqual(newProximityPrecision); - }); - - test(`${permission} key: Update proximity precision with 'byWord' value`, async () => { - const client = await getClient(permission); - const newProximityPrecision = "byWord"; - await client - .index(index.uid) - .updateProximityPrecision(newProximityPrecision) - .waitTask(); - - const response = await client.index(index.uid).getProximityPrecision(); - - expect(response).toEqual(newProximityPrecision); - }); - - test(`${permission} key: Reset proximity precision`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetProximityPrecision().waitTask(); - - const response = await client.index(index.uid).getProximityPrecision(); - - expect(response).toEqual("byWord"); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getProximityPrecision route`, async () => { - const route = `indexes/${index.uid}/settings/proximity-precision`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getProximityPrecision(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateProximityPrecision route`, async () => { - const route = `indexes/${index.uid}/settings/proximity-precision`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateProximityPrecision("byAttribute"), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetProximityPrecision route`, async () => { - const route = `indexes/${index.uid}/settings/proximity-precision`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetProximityPrecision(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/ranking_rules.test.ts b/tests/ranking_rules.test.ts deleted file mode 100644 index 5025ea2c0..000000000 --- a/tests/ranking_rules.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { expect, test, describe, beforeEach, afterAll } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -const defaultRankingRules = [ - "words", - "typo", - "proximity", - "attribute", - "sort", - "exactness", -]; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on ranking rules", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default ranking rules`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getRankingRules(); - expect(response).toEqual(defaultRankingRules); - }); - - test(`${permission} key: Update ranking rules`, async () => { - const client = await getClient(permission); - const newRankingRules = ["title:asc", "typo", "description:desc"]; - await client - .index(index.uid) - .updateRankingRules(newRankingRules) - .waitTask(); - - const response = await client.index(index.uid).getRankingRules(); - - expect(response).toEqual(newRankingRules); - }); - - test(`${permission} key: Update ranking rules at null`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateRankingRules(null).waitTask(); - - const response = await client.index(index.uid).getRankingRules(); - - expect(response).toEqual(defaultRankingRules); - }); - - test(`${permission} key: Reset ranking rules`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetRankingRules().waitTask(); - - const response = await client.index(index.uid).getRankingRules(); - - expect(response).toEqual(defaultRankingRules); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on ranking rules", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getRankingRules(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateRankingRules([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetRankingRules(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on ranking rules", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getRankingRules(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateRankingRules([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset ranking rules and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetRankingRules(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getRankingRules route`, async () => { - const route = `indexes/${index.uid}/settings/ranking-rules`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getRankingRules(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateRankingRules route`, async () => { - const route = `indexes/${index.uid}/settings/ranking-rules`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateRankingRules([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetRankingRules route`, async () => { - const route = `indexes/${index.uid}/settings/ranking-rules`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetRankingRules(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/raw_document.test.ts b/tests/raw_document.test.ts index be1b8aaf5..a0ac03ca3 100644 --- a/tests/raw_document.test.ts +++ b/tests/raw_document.test.ts @@ -4,7 +4,7 @@ import { config, getClient, } from "./utils/meilisearch-test-utils.js"; -import { ContentTypeEnum } from "../src/types/index.js"; +import { ContentTypeEnum } from "../src/index.js"; beforeEach(() => clearAllIndexes(config)); diff --git a/tests/search.test.ts b/tests/search.test.ts index 8cacb0e6b..6052aadff 100644 --- a/tests/search.test.ts +++ b/tests/search.test.ts @@ -7,11 +7,11 @@ import { beforeAll, vi, } from "vitest"; -import { ErrorStatusCode, MatchingStrategies } from "../src/types/index.js"; +import { ErrorStatusCode, MatchingStrategies } from "../src/index.js"; import type { FederatedMultiSearchParams, MultiSearchParams, -} from "../src/types/index.js"; +} from "../src/index.js"; import { clearAllIndexes, config, @@ -1214,7 +1214,7 @@ describe.each([ await masterClient .index(index.uid) - .updateLocalizedAttributes([ + .setting.updateLocalizedAttributes([ { attributePatterns: ["title", "comment"], locales: ["fra", "eng"] }, ]) .waitTask(); @@ -1422,6 +1422,7 @@ describe.each([ }); test(`${permission} key: search should be aborted when reaching timeout`, async () => { + // TODO: AssertionError: expected value to not resolve const key = await getKey(permission); const client = new MeiliSearch({ ...config, diff --git a/tests/search_cutoff_ms.test.ts b/tests/search_cutoff_ms.test.ts deleted file mode 100644 index 7c96faa04..000000000 --- a/tests/search_cutoff_ms.test.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { - afterAll, - beforeAll, - beforeEach, - describe, - expect, - test, -} from "vitest"; -import { ErrorStatusCode, type SearchCutoffMs } from "../src/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -const DEFAULT_SEARCHCUTOFF_MS = null; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on searchCutoffMs", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default searchCutoffMs settings`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getSearchCutoffMs(); - - expect(response).toEqual(DEFAULT_SEARCHCUTOFF_MS); - }); - - test(`${permission} key: Update searchCutoffMs to valid value`, async () => { - const client = await getClient(permission); - const newSearchCutoffMs = 100; - await client - .index(index.uid) - .updateSearchCutoffMs(newSearchCutoffMs) - .waitTask(); - - const response = await client.index(index.uid).getSearchCutoffMs(); - - expect(response).toEqual(newSearchCutoffMs); - }); - - test(`${permission} key: Update searchCutoffMs to null`, async () => { - const client = await getClient(permission); - const newSearchCutoffMs = null; - await client - .index(index.uid) - .updateSearchCutoffMs(newSearchCutoffMs) - .waitTask(); - - const response = await client.index(index.uid).getSearchCutoffMs(); - - expect(response).toEqual(DEFAULT_SEARCHCUTOFF_MS); - }); - - test(`${permission} key: Update searchCutoffMs with invalid value`, async () => { - const client = await getClient(permission); - const newSearchCutoffMs = "hello" as unknown as SearchCutoffMs; // bad searchCutoffMs value - - await expect( - client.index(index.uid).updateSearchCutoffMs(newSearchCutoffMs), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.INVALID_SETTINGS_SEARCH_CUTOFF_MS, - ); - }); - - test(`${permission} key: Reset searchCutoffMs`, async () => { - const client = await getClient(permission); - const newSearchCutoffMs = 100; - await client - .index(index.uid) - .updateSearchCutoffMs(newSearchCutoffMs) - .waitTask(); - await client.index(index.uid).resetSearchCutoffMs().waitTask(); - - const response = await client.index(index.uid).getSearchCutoffMs(); - - expect(response).toEqual(DEFAULT_SEARCHCUTOFF_MS); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on searchCutoffMs", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSearchCutoffMs(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSearchCutoffMs(100), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSearchCutoffMs(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on searchCutoffMs", - ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSearchCutoffMs(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSearchCutoffMs(100), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset searchCutoffMs and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSearchCutoffMs(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSearchCutoffMs route`, async () => { - const route = `indexes/${index.uid}/settings/search-cutoff-ms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getSearchCutoffMs(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateSearchCutoffMs route`, async () => { - const route = `indexes/${index.uid}/settings/search-cutoff-ms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSearchCutoffMs(null), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetSearchCutoffMs route`, async () => { - const route = `indexes/${index.uid}/settings/search-cutoff-ms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSearchCutoffMs(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/searchable_attributes.test.ts b/tests/searchable_attributes.test.ts deleted file mode 100644 index 8a1b1030f..000000000 --- a/tests/searchable_attributes.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { - afterAll, - beforeAll, - beforeEach, - describe, - expect, - test, -} from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on searchable attributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default searchable attributes`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getSearchableAttributes(); - - expect(response).toEqual(["*"]); - }); - - test(`${permission} key: Update searchable attributes`, async () => { - const client = await getClient(permission); - const newSearchableAttributes = ["title"]; - await client - .index(index.uid) - .updateSearchableAttributes(newSearchableAttributes) - .waitTask(); - - const response = await client.index(index.uid).getSearchableAttributes(); - - expect(response).toEqual(newSearchableAttributes); - }); - - test(`${permission} key: Update searchable attributes at null`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateSearchableAttributes(null).waitTask(); - - const response = await client.index(index.uid).getSearchableAttributes(); - - expect(response).toEqual(["*"]); - }); - - test(`${permission} key: Reset searchable attributes`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetSearchableAttributes().waitTask(); - - const response = await client.index(index.uid).getSearchableAttributes(); - - expect(response).toEqual(["*"]); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on searchable attributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSearchableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSearchableAttributes([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSearchableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on searchable attributes", - ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSearchableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSearchableAttributes([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset searchable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSearchableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSearchableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/searchable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getSearchableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateSearchableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/searchable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSearchableAttributes([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetSearchableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/searchable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSearchableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/separator_tokens.test.ts b/tests/separator_tokens.test.ts deleted file mode 100644 index d780eacde..000000000 --- a/tests/separator_tokens.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { afterAll, beforeEach, describe, expect, test } from "vitest"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on separator tokens", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default separator tokens`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getSeparatorTokens(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Update separator tokens`, async () => { - const client = await getClient(permission); - const newSeparatorTokens = ["&sep", "/", "|"]; - await client - .index(index.uid) - .updateSeparatorTokens(newSeparatorTokens) - .waitTask(); - - const response = await client.index(index.uid).getSeparatorTokens(); - - expect(response).toEqual(newSeparatorTokens); - }); - - test(`${permission} key: Update separator tokens with null value`, async () => { - const client = await getClient(permission); - const newSeparatorTokens = null; - await client - .index(index.uid) - .updateSeparatorTokens(newSeparatorTokens) - .waitTask(); - - const response = await client.index(index.uid).getSeparatorTokens(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Reset separator tokens`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetSeparatorTokens().waitTask(); - - const response = await client.index(index.uid).getSeparatorTokens(); - - expect(response).toEqual([]); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getSeparatorTokens(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSeparatorTokens([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetSeparatorTokens route`, async () => { - const route = `indexes/${index.uid}/settings/separator-tokens`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSeparatorTokens(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/settings.test.ts b/tests/settings.test.ts index c6c71dd75..d76a0092c 100644 --- a/tests/settings.test.ts +++ b/tests/settings.test.ts @@ -1,359 +1,585 @@ -import { afterAll, beforeEach, describe, expect, test } from "vitest"; -import { ErrorStatusCode, type Settings } from "../src/types/index.js"; +import { test, describe, afterAll, beforeAll } from "vitest"; +import type { + EnqueuedTaskPromise, + FacetValuesSort, + SingleUpdatableSettings, + PrefixSearchSettings, + ProximityPrecisionView, + RankingRuleView, + EmbedderSource, + UpdatableSettings, +} from "../src/index.js"; import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, + assert, getClient, - dataset, + ObjectKeys, } from "./utils/meilisearch-test-utils.js"; -const index = { - uid: "movies_test", -}; -const indexAndPK = { - uid: "movies_test_with_pk", - primaryKey: "id", +const INDEX_UID = "e16993ea-0cd2-4a29-9365-b99778a92c74"; +const ms = await getClient("Master"); +const index = ms.index(INDEX_UID); + +type InputAndAssertion = { + input: SingleUpdatableSettings[T]; + assertion: ( + input: SingleUpdatableSettings[T], + output: SingleUpdatableSettings[T], + ) => void; }; -afterAll(() => { - return clearAllIndexes(config); -}); +type MappedSettings = { + [TKey in keyof SingleUpdatableSettings]: [ + text: string | undefined, + inputAndAssertion: InputAndAssertion, + ][]; +}; -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("Master"); - await client - .index(indexAndPK.uid) - .addDocuments(dataset, { - primaryKey: indexAndPK.primaryKey, - }) - .waitTask(); - - await client.index(index.uid).addDocuments(dataset, {}).waitTask(); - }); - - test(`${permission} key: Get default settings of an index`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Get default settings of empty index with primary key`, async () => { - const client = await getClient(permission); - - const response = await client.index(indexAndPK.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update settings`, async () => { - const client = await getClient(permission); - const newSettings: Settings = { - filterableAttributes: ["title"], - sortableAttributes: ["title"], - distinctAttribute: "title", - proximityPrecision: "byAttribute", - searchableAttributes: ["title"], - displayedAttributes: ["title"], - rankingRules: ["id:asc", "typo"], - stopWords: ["the"], - synonyms: { harry: ["potter"] }, - typoTolerance: { - enabled: false, - minWordSizeForTypos: { - oneTypo: 1, - twoTypos: 100, - }, - disableOnWords: ["prince"], - disableOnAttributes: ["comment"], +const mappedSettings = { + displayedAttributes: [ + [ + undefined, + { + input: ["augustus", "nero"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); }, - pagination: { - maxTotalHits: 1000, + }, + ], + ], + + searchableAttributes: [ + [ + undefined, + { + input: ["charlemagne", "ferdinand"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); }, - faceting: { - maxValuesPerFacet: 50, - sortFacetValuesBy: { - "*": "alpha", + }, + ], + ], + + filterableAttributes: [ + [ + undefined, + { + input: [ + "modèleZéro", + { + attributePatterns: ["modèleUn", "modèleDeux"], + features: { + facetSearch: true, + filter: { equality: true, comparison: true }, + }, }, + ], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameDeepMembers(input, output); }, - separatorTokens: ["&sep", "/", "|"], - nonSeparatorTokens: ["&sep", "/", "|"], - dictionary: ["J. K.", "J. R. R."], - searchCutoffMs: 1000, - facetSearch: true, - prefixSearch: "indexingTime", - }; - // Add the settings - await client.index(index.uid).updateSettings(newSettings).waitTask(); - - // Fetch the settings - const response = await client.index(index.uid).getSettings(); - - // tests - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update settings with all null values`, async () => { - const client = await getClient(permission); - const newSettings: Settings = { - filterableAttributes: null, - sortableAttributes: null, - distinctAttribute: null, - searchableAttributes: null, - displayedAttributes: null, - rankingRules: null, - stopWords: null, - synonyms: null, - typoTolerance: { - enabled: null, - minWordSizeForTypos: { - oneTypo: null, - twoTypos: null, - }, - disableOnWords: null, - disableOnAttributes: null, + }, + ], + ], + + sortableAttributes: [ + [ + undefined, + { + input: ["madsMikkelsen", "nikolajCosterWaldau"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); }, - faceting: { - maxValuesPerFacet: null, - sortFacetValuesBy: null, + }, + ], + ], + + rankingRules: [ + [ + undefined, + { + input: ObjectKeys({ + words: null, + typo: null, + proximity: null, + attribute: null, + sort: null, + exactness: null, + "some_field:asc": null, + "some_other_field:desc": null, + }), + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); }, - pagination: { - maxTotalHits: null, + }, + ], + ], + + stopWords: [ + [ + undefined, + { + input: ["hideakiAnno", "hayaoMiyazaki"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); }, - separatorTokens: null, - nonSeparatorTokens: null, - dictionary: null, - searchCutoffMs: null, - }; - // Add the settings - await client.index(index.uid).updateSettings(newSettings).waitTask(); - - // Fetch the settings - const response = await client.index(index.uid).getSettings(); - - // tests - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update embedders settings `, async () => { - const client = await getClient(permission); - - const newSettings: Settings = { - embedders: { - default: { - source: "huggingFace", - model: - "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", - }, + }, + ], + ], + + nonSeparatorTokens: [ + [ + undefined, + { + input: ["nile", "amazonRiver"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); + }, + }, + ], + ], + + separatorTokens: [ + [ + undefined, + { + input: ["once", "doce"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); + }, + }, + ], + ], + + dictionary: [ + [ + undefined, + { + input: ["mountEverest", "k2"], + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + assert.sameMembers(input, output); + }, + }, + ], + ], + + synonyms: [ + [ + undefined, + { + input: { + language: ["speech", "tongue", "lingo"], + land: ["country", "nation", "state"], + }, + assertion: (input, output) => { + assert.deepEqual(input, output); + }, + }, + ], + ], + + distinctAttribute: [ + [ + undefined, + { + input: "benjaminFranklin", + assertion: (input, output) => { + assert.strictEqual(input, output); + }, + }, + ], + ], + + proximityPrecision: ObjectKeys({ + byWord: null, + byAttribute: null, + }).map((v) => [ + v, + { + input: v, + assertion: (input, output) => { + assert.strictEqual(input, output); + }, + }, + ]), + + typoTolerance: [ + [ + undefined, + { + input: { + enabled: true, + minWordSizeForTypos: { oneTypo: 2, twoTypos: 3 }, + disableOnWords: ["mot-un", "mot-deux"], + disableOnAttributes: ["attributUn", "attributDeux"], + }, + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + + const { + disableOnWords: dow1, + disableOnAttributes: doa1, + ...restInput + } = input; + const { + disableOnWords: dow2, + disableOnAttributes: doa2, + ...restOutput + } = output; + + assert(dow1 != null && dow2 != null && doa1 != null && doa2 != null); + + assert.sameMembers(dow1, dow2); + assert.sameMembers(doa1, doa2); + + assert.deepEqual(restInput, restOutput); }, - }; - await client - .index(index.uid) - .updateSettings(newSettings) - .waitTask({ timeout: 60_000 }); - const response = await client.index(index.uid).getSettings(); + }, + ], + ], + + faceting: ObjectKeys({ + alpha: null, + count: null, + }).map((v) => [ + `${v} facet value sort`, + { + input: { maxValuesPerFacet: 42, sortFacetValuesBy: { random_field: v } }, + assertion: (input, output) => { + assert.isNotNull(input); + assert.isNotNull(output); + + assert(output.sortFacetValuesBy != null); + const star = output.sortFacetValuesBy["*"]; + delete output.sortFacetValuesBy["*"]; + assert.oneOf(star, ["alpha", undefined]); + + assert.deepEqual(input, output); + }, + }, + ]), + + pagination: [ + [ + undefined, + { + input: { maxTotalHits: 42 }, + assertion: (input, output) => { + assert.deepEqual(input, output); + }, + }, + ], + ], + + embedders: ObjectKeys({ + openAi: null, + huggingFace: null, + ollama: null, + userProvided: null, + rest: null, + composite: null, + }).map((source) => { + return [ + source, + { + input: { + [source]: (() => { + switch (source) { + case "openAi": + return { + source, + apiKey: "", + model: "text-embedding-3-small", + documentTemplate: + "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", + dimensions: 1536, + distribution: { mean: 0.7, sigma: 0.3 }, + url: "https://api.openai.com/v1/embeddings", + documentTemplateMaxBytes: 500, + binaryQuantized: false, + }; + case "huggingFace": + return { + source, + model: + "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", + documentTemplate: + "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", + distribution: { mean: 0.7, sigma: 0.3 }, + pooling: "useModel", + documentTemplateMaxBytes: 500, + binaryQuantized: false, + }; + case "ollama": + return { + source, + url: "http://localhost:11434/api/embeddings", + apiKey: "", + model: "nomic-embed-text", + documentTemplate: "blabla", + distribution: { mean: 0.7, sigma: 0.3 }, + dimensions: 512, + documentTemplateMaxBytes: 500, + binaryQuantized: false, + }; + case "userProvided": + return { + source, + dimensions: 1, + distribution: { mean: 0.7, sigma: 0.3 }, + binaryQuantized: false, + }; + case "rest": + return { + source, + url: "https://api.openai.com/v1/embeddings", + apiKey: "", + dimensions: 1536, + documentTemplate: + "A movie titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}", + distribution: { mean: 0.7, sigma: 0.3 }, + request: { + model: "text-embedding-3-small", + input: ["{{text}}", "{{..}}"], + }, + response: { + data: [{ embedding: "{{embedding}}" }, "{{..}}"], + }, + headers: { "Custom-Header": "CustomValue" }, + documentTemplateMaxBytes: 500, + binaryQuantized: false, + }; + case "composite": + return { + source, + searchEmbedder: { + source: "huggingFace", + model: + "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", + pooling: "useModel", + }, + indexingEmbedder: { + source: "huggingFace", + model: + "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", + documentTemplate: "{{doc.title}}", + pooling: "useModel", + documentTemplateMaxBytes: 500, + }, + }; + default: + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + assert.fail(`untested embedder source ${source}`); + } + })(), + }, + assertion: (input, output) => { + const inputEmbeddingSettings = input?.[source]; + const outputEmbeddingSettings = output?.[source]; + assert( + inputEmbeddingSettings != null && outputEmbeddingSettings != null, + ); + + const { apiKey: inputApiKey, ...restOfInputEmbeddingSettings } = + inputEmbeddingSettings; + const { apiKey: outputApiKey, ...restOfOutputEmbeddingSettings } = + outputEmbeddingSettings; + + assert.deepEqual( + restOfInputEmbeddingSettings, + restOfOutputEmbeddingSettings, + ); + assert(typeof inputApiKey === typeof outputApiKey); + }, + }, + ]; + }), + + searchCutoffMs: [ + [ + undefined, + { + input: 100, + assertion: (input, output) => { + assert.strictEqual(input, output); + }, + }, + ], + ], + + localizedAttributes: [ + [ + undefined, + { + input: [{ attributePatterns: ["title"], locales: ["eng"] }], + assertion: (input, output) => { + assert.deepEqual(input, output); + }, + }, + ], + ], + + facetSearch: [ + [ + undefined, + { + input: true, + assertion: (input, output) => { + assert.strictEqual(input, output); + }, + }, + ], + ], + + prefixSearch: ObjectKeys({ + indexingTime: null, + disabled: null, + }).map((v) => [ + v, + { + input: v, + assertion: (input, output) => { + assert.strictEqual(input, output); + }, + }, + ]), +} satisfies MappedSettings as Record< + string, + [ + text: string | undefined, + inputAndAssertion: InputAndAssertion, + ][] +>; + +beforeAll(async () => { + await ms.updateExperimentalFeatures({ compositeEmbedders: true }); + const task = await ms.createIndex(INDEX_UID).waitTask(); + assert.isTaskSuccessful(task); +}); - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update settings on empty index with primary key`, async () => { - const client = await getClient(permission); - const newSettings = { - distinctAttribute: "title", - rankingRules: ["title:asc", "typo"], - stopWords: ["the"], - }; - await client.index(indexAndPK.uid).updateSettings(newSettings).waitTask(); - - const response = await client.index(indexAndPK.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Reset settings`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetSettings().waitTask(); - - const response = await client.index(index.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Reset settings of empty index`, async () => { - const client = await getClient(permission); - await client.index(indexAndPK.uid).resetSettings().waitTask(); - - const response = await client.index(indexAndPK.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Reset embedders settings `, async () => { - const client = await getClient(permission); - - const newSettings: Settings = { - embedders: null, - }; - await client.index(index.uid).updateSettings(newSettings).waitTask(); - const response = await client.index(index.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update searchableAttributes settings on empty index`, async () => { - const client = await getClient(permission); - const newSettings = { - searchableAttributes: ["title"], - }; - await client.index(index.uid).updateSettings(newSettings).waitTask(); - - const response = await client.index(index.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update searchableAttributes settings on empty index with a primary key`, async () => { - const client = await getClient(permission); - const newSettings = { - searchableAttributes: ["title"], - }; - // Update settings - await client.index(indexAndPK.uid).updateSettings(newSettings).waitTask(); - // Wait for setting addition to be done - - // Fetch settings - const response = await client.index(indexAndPK.uid).getSettings(); - - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update facetSearch settings on empty index`, async () => { - const client = await getClient(permission); - - await client - .index(index.uid) - .updateSettings({ facetSearch: false }) - .waitTask(); - - const response = await client.index(index.uid).getSettings(); - expect(response).toMatchSnapshot(); - }); - - test(`${permission} key: Update prefixSearch settings on an empty index`, async () => { - const client = await getClient(permission); - - await client - .index(index.uid) - .updateSettings({ prefixSearch: "disabled" }) - .waitTask(); - - const response = await client.index(index.uid).getSettings(); - expect(response).toMatchSnapshot(); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on settings", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - test(`${permission} key: try to get settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSettings(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - test(`${permission} key: try to update settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSettings({}), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - test(`${permission} key: try to reset settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSettings(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])("Test on settings", ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - test(`${permission} key: try to get settings and be denied`, async () => { - const client = await getClient(permission); - await expect(client.index(index.uid).getSettings()).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - test(`${permission} key: try to update settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSettings({}), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - test(`${permission} key: try to reset settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSettings(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); +afterAll(async () => { + const task = await index.delete().waitTask(); + assert.isTaskSuccessful(task); + await ms.updateExperimentalFeatures({ compositeEmbedders: false }); }); -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSettings route`, async () => { - const route = `indexes/${index.uid}/settings`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect(client.index(index.uid).getSettings()).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); +describe.for(Object.entries(mappedSettings))("%s", ([key, mappedSetting]) => { + const castKey = key as keyof MappedSettings; + const capitalizedKey = (castKey.charAt(0).toUpperCase() + + key.slice(1)) as Capitalize; + + // Union of functions results in intersection of their parameters + // https://github.com/microsoft/TypeScript/issues/30581 + + const getSetting = index.setting[`get${capitalizedKey}`].bind( + index, + ) as () => Promise; + + const updateSetting = index.setting[`update${capitalizedKey}`].bind( + index, + ) as ( + v: SingleUpdatableSettings[keyof SingleUpdatableSettings], + ) => EnqueuedTaskPromise; + + const resetSetting = index.setting[`reset${capitalizedKey}`].bind(index); + + mappedSetting = mappedSetting.map(([a, b]) => [ + a === undefined ? "" : ` with ${a}`, + b, + ]); + + test.for(mappedSetting)( + "single update and get methods%s", + async ([, { input, assertion }]) => { + const task = await updateSetting(input).waitTask({ timeout: 30_000 }); + assert.isTaskSuccessful(task); + assert.strictEqual(task.type, "settingsUpdate"); + + const taskSetting = task.details?.[castKey]; + assert.isDefined(taskSetting); + assertion(input, taskSetting); + + const setting = await getSetting(); + assertion(input, setting); + }, + ); + + test("single reset method", async () => { + const task = await resetSetting().waitTask(); + assert.includeDeepMembers([null, ["*"]], [task.details?.[castKey]]); + assert.isTaskSuccessful(task); + assert.strictEqual(task.type, "settingsUpdate"); }); - test(`updateSettings route`, async () => { - const route = `indexes/${index.uid}/settings`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSettings({}), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); + test.for(mappedSetting)( + `${index.updateSettings.name} and ${index.getSettings.name} methods%s`, + async ([, { input, assertion }]) => { + const task = await index + .updateSettings({ [castKey]: input }) + .waitTask({ timeout: 30_000 }); + assert.isTaskSuccessful(task); + assert.strictEqual(task.type, "settingsUpdate"); + + const taskSetting = task.details?.[castKey]; + assert.isDefined(taskSetting); + assertion(input, taskSetting); + + const settings = await index.getSettings(); + assert.isDefined(settings[castKey]); + assertion(input, settings[castKey]); + }, + ); + + test(`reset with ${index.updateSettings.name} method`, async () => { + const task = await index.updateSettings({ [castKey]: null }).waitTask(); + assert.includeDeepMembers([null, ["*"]], [task.details?.[castKey]]); + assert.isTaskSuccessful(task); + assert.strictEqual(task.type, "settingsUpdate"); }); +}); - test(`resetSettings route`, async () => { - const route = `indexes/${index.uid}/settings`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSettings(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); +test(`${index.resetSettings.name} method`, async () => { + const task = await index.resetSettings().waitTask(); + + assert.isTaskSuccessful(task); + assert.deepEqual(task.details, { + dictionary: null, + displayedAttributes: ["*"], + distinctAttribute: null, + embedders: null, + facetSearch: null, + faceting: null, + filterableAttributes: null, + localizedAttributes: null, + nonSeparatorTokens: null, + pagination: null, + prefixSearch: null, + proximityPrecision: null, + rankingRules: null, + searchCutoffMs: null, + searchableAttributes: ["*"], + separatorTokens: null, + sortableAttributes: null, + stopWords: null, + synonyms: null, + typoTolerance: null, + } satisfies Required); + assert.strictEqual(task.type, "settingsUpdate"); }); diff --git a/tests/snapshots.test.ts b/tests/snapshots.test.ts index 7b07ab897..cf40638f9 100644 --- a/tests/snapshots.test.ts +++ b/tests/snapshots.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test, assert } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { clearAllIndexes, config, diff --git a/tests/sortable_attributes.test.ts b/tests/sortable_attributes.test.ts deleted file mode 100644 index 814c7f7f0..000000000 --- a/tests/sortable_attributes.test.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { - afterAll, - beforeAll, - beforeEach, - describe, - expect, - test, -} from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on sortable attributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default sortable attributes`, async () => { - const client = await getClient(permission); - - const response = await client.index(index.uid).getSortableAttributes(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Update sortable attributes`, async () => { - const client = await getClient(permission); - const newSortableAttributes = ["title"]; - await client - .index(index.uid) - .updateSortableAttributes(newSortableAttributes) - .waitTask(); - - const response = await client.index(index.uid).getSortableAttributes(); - expect(response).toEqual(newSortableAttributes); - }); - - test(`${permission} key: Update sortable attributes at null`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateSortableAttributes(null).waitTask(); - - const response = await client.index(index.uid).getSortableAttributes(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Reset sortable attributes`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetSortableAttributes().waitTask(); - - const response = await client.index(index.uid).getSortableAttributes(); - - expect(response).toEqual([]); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on sortable attributes", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get sortable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSortableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update sortable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSortableAttributes([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset sortable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSortableAttributes(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on sortable attributes", - ({ permission }) => { - beforeAll(async () => { - const client = await getClient("Master"); - await client.createIndex(index.uid).waitTask(); - }); - - test(`${permission} key: try to get sortable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSortableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update sortable attributes and be denied`, async () => { - const client = await getClient(permission); - const resetSortable: string[] = []; - await expect( - client.index(index.uid).updateSortableAttributes(resetSortable), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset sortable attributes and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSortableAttributes(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSortableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/sortable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getSortableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateSortableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/sortable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSortableAttributes([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetSortableAttributes route`, async () => { - const route = `indexes/${index.uid}/settings/sortable-attributes`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSortableAttributes(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/stop_words.test.ts b/tests/stop_words.test.ts deleted file mode 100644 index e56582c2c..000000000 --- a/tests/stop_words.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { afterAll, beforeEach, describe, expect, test } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on stop words", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default stop words`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getStopWords(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Update stop words`, async () => { - const client = await getClient(permission); - const newStopWords = ["the"]; - await client.index(index.uid).updateStopWords(newStopWords).waitTask(); - - const response = await client.index(index.uid).getStopWords(); - - expect(response).toEqual(newStopWords); - }); - - test(`${permission} key: Update stop words with null value`, async () => { - const client = await getClient(permission); - const newStopWords = null; - await client.index(index.uid).updateStopWords(newStopWords).waitTask(); - - const response = await client.index(index.uid).getStopWords(); - - expect(response).toEqual([]); - }); - - test(`${permission} key: Reset stop words`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetStopWords().waitTask(); - - const response = await client.index(index.uid).getStopWords(); - - expect(response).toEqual([]); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on stop words", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getStopWords(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateStopWords([]), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetStopWords(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Test on stop words", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getStopWords(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateStopWords([]), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset stop words and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetStopWords(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getStopWords route`, async () => { - const route = `indexes/${index.uid}/settings/stop-words`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect(client.index(index.uid).getStopWords()).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateStopWords route`, async () => { - const route = `indexes/${index.uid}/settings/stop-words`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateStopWords([]), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetStopWords route`, async () => { - const route = `indexes/${index.uid}/settings/stop-words`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetStopWords(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/synonyms.test.ts b/tests/synonyms.test.ts deleted file mode 100644 index 48a11835b..000000000 --- a/tests/synonyms.test.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { afterAll, beforeEach, describe, expect, test } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Test on synonyms", - ({ permission }) => { - beforeEach(async () => { - const client = await getClient("Master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default synonyms`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getSynonyms(); - - expect(response).toEqual({}); - }); - - test(`${permission} key: Update synonyms`, async () => { - const client = await getClient(permission); - const newSynonyms = { - hp: ["harry potter"], - }; - await client.index(index.uid).updateSynonyms(newSynonyms).waitTask(); - - const response = await client.index(index.uid).getSynonyms(); - - expect(response).toEqual(newSynonyms); - }); - - test(`${permission} key: Update synonyms with null value`, async () => { - const client = await getClient(permission); - const newSynonyms = null; - await client.index(index.uid).updateSynonyms(newSynonyms).waitTask(); - - const response = await client.index(index.uid).getSynonyms(); - - expect(response).toEqual({}); - }); - - test(`${permission} key: Reset synonyms`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetSynonyms().waitTask(); - - const response = await client.index(index.uid).getSynonyms(); - - expect(response).toEqual({}); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Test on synonyms", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getSynonyms(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSynonyms({}), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSynonyms(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])("Test on synonyms", ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect(client.index(index.uid).getSynonyms()).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateSynonyms({}), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset synonyms and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetSynonyms(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); -}); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`getSynonyms route`, async () => { - const route = `indexes/${index.uid}/settings/synonyms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect(client.index(index.uid).getSynonyms()).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`updateSynonyms route`, async () => { - const route = `indexes/${index.uid}/settings/synonyms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateSynonyms({}), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`resetSynonyms route`, async () => { - const route = `indexes/${index.uid}/settings/synonyms`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetSynonyms(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/task.test.ts b/tests/task.test.ts index 2032e9747..e09c00eba 100644 --- a/tests/task.test.ts +++ b/tests/task.test.ts @@ -1,5 +1,5 @@ import { afterAll, assert, beforeEach, describe, expect, test } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; +import { ErrorStatusCode } from "../src/index.js"; import { sleep } from "../src/utils.js"; import { BAD_HOST, diff --git a/tests/token.test.ts b/tests/token.test.ts index 349c95037..e2b25f301 100644 --- a/tests/token.test.ts +++ b/tests/token.test.ts @@ -299,7 +299,7 @@ describe.each([{ permission: "Admin" }])( const masterClient = await getClient("master"); await masterClient .index(UID) - .updateFilterableAttributes(["id"]) + .setting.updateFilterableAttributes(["id"]) .waitTask(); const client = await getClient(permission); const apiKey = await getKey(permission); diff --git a/tests/typed_search.test.ts b/tests/typed_search.test.ts index a34381989..89794c561 100644 --- a/tests/typed_search.test.ts +++ b/tests/typed_search.test.ts @@ -6,7 +6,7 @@ import { expect, test, } from "vitest"; -import { ErrorStatusCode, type SearchResponse } from "../src/types/index.js"; +import { ErrorStatusCode, type SearchResponse } from "../src/index.js"; import { clearAllIndexes, config, @@ -118,8 +118,8 @@ describe.each([ const newFilterableAttributes = ["genre", "title"]; await client - .index(index.uid) - .updateFilterableAttributes(newFilterableAttributes) + .index(index.uid) + .setting.updateFilterableAttributes(newFilterableAttributes) .waitTask(); await client.index(index.uid).addDocuments(dataset).waitTask(); diff --git a/tests/typo_tolerance.test.ts b/tests/typo_tolerance.test.ts deleted file mode 100644 index 7cad1e126..000000000 --- a/tests/typo_tolerance.test.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { afterAll, beforeEach, describe, expect, test } from "vitest"; -import { ErrorStatusCode } from "../src/types/index.js"; -import { - clearAllIndexes, - config, - BAD_HOST, - MeiliSearch, - getClient, - dataset, -} from "./utils/meilisearch-test-utils.js"; - -const index = { - uid: "movies_test", -}; - -const defaultTypoTolerance = { - enabled: true, - minWordSizeForTypos: { - oneTypo: 5, - twoTypos: 9, - }, - disableOnWords: [], - disableOnAttributes: [], -}; - -afterAll(() => { - return clearAllIndexes(config); -}); - -describe.each([{ permission: "Master" }, { permission: "Admin" }])( - "Tests on typo tolerance", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - const client = await getClient("master"); - await client.index(index.uid).addDocuments(dataset).waitTask(); - }); - - test(`${permission} key: Get default typo tolerance settings`, async () => { - const client = await getClient(permission); - const response = await client.index(index.uid).getTypoTolerance(); - expect(response).toEqual(defaultTypoTolerance); - }); - - test(`${permission} key: Update typo tolerance settings`, async () => { - const client = await getClient(permission); - const newTypoTolerance = { - enabled: false, - minWordSizeForTypos: { - oneTypo: 1, - twoTypos: 2, - }, - disableOnWords: ["title"], - disableOnAttributes: ["hello"], - }; - await client - .index(index.uid) - .updateTypoTolerance(newTypoTolerance) - .waitTask(); - - const response = await client.index(index.uid).getTypoTolerance(); - - expect(response).toEqual(newTypoTolerance); - }); - - test(`${permission} key: Update typo tolerance using null as value`, async () => { - const client = await getClient(permission); - await client.index(index.uid).updateTypoTolerance(null).waitTask(); - - const response = await client.index(index.uid).getTypoTolerance(); - - expect(response).toEqual(defaultTypoTolerance); - }); - - test(`${permission} key: Reset typo tolerance settings`, async () => { - const client = await getClient(permission); - await client.index(index.uid).resetTypoTolerance().waitTask(); - - const response = await client.index(index.uid).getTypoTolerance(); - - expect(response).toEqual(defaultTypoTolerance); - }); - }, -); - -describe.each([{ permission: "Search" }])( - "Tests on typo tolerance", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getTypoTolerance(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to update typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateTypoTolerance({}), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - - test(`${permission} key: try to reset typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetTypoTolerance(), - ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INVALID_API_KEY); - }); - }, -); - -describe.each([{ permission: "No" }])( - "Tests on typo tolerance", - ({ permission }) => { - beforeEach(async () => { - await clearAllIndexes(config); - }); - - test(`${permission} key: try to get typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).getTypoTolerance(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to update typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).updateTypoTolerance({}), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - - test(`${permission} key: try to reset typo tolerance settings and be denied`, async () => { - const client = await getClient(permission); - await expect( - client.index(index.uid).resetTypoTolerance(), - ).rejects.toHaveProperty( - "cause.code", - ErrorStatusCode.MISSING_AUTHORIZATION_HEADER, - ); - }); - }, -); - -describe.each([ - { host: BAD_HOST, trailing: false }, - { host: `${BAD_HOST}/api`, trailing: false }, - { host: `${BAD_HOST}/trailing/`, trailing: true }, -])("Tests on url construction", ({ host, trailing }) => { - test(`get typo tolerance route`, async () => { - const route = `indexes/${index.uid}/settings/typo-tolerance`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).getTypoTolerance(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`update typo tolerance route`, async () => { - const route = `indexes/${index.uid}/settings/typo-tolerance`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).updateTypoTolerance({}), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); - - test(`reset typo tolerance route`, async () => { - const route = `indexes/${index.uid}/settings/typo-tolerance`; - const client = new MeiliSearch({ host }); - const strippedHost = trailing ? host.slice(0, -1) : host; - await expect( - client.index(index.uid).resetTypoTolerance(), - ).rejects.toHaveProperty( - "message", - `Request to ${strippedHost}/${route} has failed`, - ); - }); -}); diff --git a/tests/utils/meilisearch-test-utils.ts b/tests/utils/meilisearch-test-utils.ts index e9faf9510..e7f8d7460 100644 --- a/tests/utils/meilisearch-test-utils.ts +++ b/tests/utils/meilisearch-test-utils.ts @@ -1,6 +1,6 @@ import { assert as vitestAssert } from "vitest"; import { MeiliSearch, Index } from "../../src/index.js"; -import type { Config } from "../../src/types/index.js"; +import type { Config, Task } from "../../src/types/index.js"; // testing const MASTER_KEY = "masterKey"; @@ -127,6 +127,10 @@ const source = { "expected value to not resolve", ); }, + isTaskSuccessful(task: Task) { + vitestAssert.isNull(task.error); + vitestAssert.strictEqual(task.status, "succeeded"); + }, }; export const assert: typeof vitestAssert & typeof source = Object.assign( vitestAssert, @@ -244,7 +248,12 @@ export type Book = { author: string; }; +function ObjectKeys(o: { [TKey in T]: null }): T[] { + return Object.keys(o) as T[]; +} + export { + ObjectKeys, clearAllIndexes, config, masterClient,