UNPKG

nestjs-meili

Version:

Seamless and declarative integration of [MeiliSearch](https://www.meilisearch.com/) into [NestJS](https://nestjs.com/). Use decorators to configure indexes and inject `MeiliSearch` with type safety and zero boilerplate.

56 lines (55 loc) 2.68 kB
import { Injectable } from "@nestjs/common"; import { MEILI_PRIMARY_KEY, MEILI_INDEX_RANKING_RULES, MEILI_INDEX_STOP_WORDS, MEILI_INDEX_SYNONYMS, MEILI_INDEX_DISTINCT, MEILI_INDEX_PAGINATION, MEILI_INDEX_FACETING, MEILI_INDEX_DISPLAYED, MEILI_INDEX, MEILI_INDEX_SEARCHABLE, MEILI_INDEX_FILTERABLE, MEILI_INDEX_SORTABLE, } from "./watermarks"; @Injectable() export class MeiliUtils { async setupIndex(index, client) { const indexName = this.getIndexName(index); const primaryKey = Reflect.getMetadata(MEILI_PRIMARY_KEY, index); if (!primaryKey) { throw new Error(`Primary key for model ${index.name} is not set`); } try { const meiliIndex = await client.initIndex(indexName, primaryKey); const settings = { searchableAttributes: this.collectProps(index, MEILI_INDEX_SEARCHABLE), filterableAttributes: this.collectProps(index, MEILI_INDEX_FILTERABLE), sortableAttributes: this.collectProps(index, MEILI_INDEX_SORTABLE), }; this.addOptionalSettings(index, settings); await meiliIndex.updateSettings(settings); } catch (error) { console.error(`Failed to setup Meili index for ${index.name}:`, error); } } getIndexName(index) { const customName = Reflect.getMetadata(MEILI_INDEX, index); return customName || index.name.toLowerCase(); } collectProps(index, watermark) { return Reflect.getMetadata(watermark, index) || []; } addOptionalSettings(index, settings) { const ranking = Reflect.getMetadata(MEILI_INDEX_RANKING_RULES, index); const stopWords = Reflect.getMetadata(MEILI_INDEX_STOP_WORDS, index); const synonyms = Reflect.getMetadata(MEILI_INDEX_SYNONYMS, index); const distinct = Reflect.getMetadata(MEILI_INDEX_DISTINCT, index); const pagination = Reflect.getMetadata(MEILI_INDEX_PAGINATION, index); const faceting = Reflect.getMetadata(MEILI_INDEX_FACETING, index); const displayed = Reflect.getMetadata(MEILI_INDEX_DISPLAYED, index); if (ranking) settings.rankingRules = ranking; if (stopWords) settings.stopWords = stopWords; if (synonyms) settings.synonyms = synonyms; if (displayed?.length) settings.displayedAttributes = displayed; if (distinct) settings.distinctAttribute = distinct; if (pagination) settings.pagination = { maxTotalHits: pagination }; if (faceting) settings.faceting = { maxValuesPerFacet: faceting }; } }