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.

200 lines (149 loc) โ€ข 4.62 kB
# ๐Ÿ” nestjs-meili 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. --- ## โœจ Features - ๐Ÿง  **Decorator-driven** index configuration - โšก **Modular** design with `forFeature()` per entity - ๐Ÿงฉ **Typed injection** of indexes using class reference - ๐Ÿ”ง **Sync and async** initialization (e.g. with `ConfigModule`) - ๐Ÿงช Built-in **testing** support - ๐Ÿšซ No global registry โ€” each module owns its own setup --- ## ๐Ÿ“ฆ Installation ```bash yarn add nestjs-meili meilisearch reflect-metadata ``` Update `tsconfig.json`: ```json { "experimentalDecorators": true, "emitDecoratorMetadata": true } ``` --- ## ๐Ÿš€ Quick Start ### 1. Define a model ```ts @MeiliIndex("books") @RankingRules(["words", "typo"]) @StopWords(["the", "a"]) @Synonyms({ hp: ["harry potter"] }) @Pagination(1000) @Faceting(50) export class Book { @PrimaryKey() id: string; @Searchable() title: string; @Filterable() genre: string; @Sortable() publishedAt: string; @Displayed() title: string; @Displayed() genre: string; @Distinct() isbn: string; } ``` ### 2. Register module ```ts @Module({ imports: [ MeiliModule.forRoot({ host: "http://localhost:7700", apiKey: "your_meili_api_key", }), MeiliModule.forFeature([Book]), ], }) export class AppModule {} ``` --- ## ๐Ÿงฐ Inject and use ```ts @Injectable() export class BookService { constructor( @InjectMeiliIndex(Book) private readonly bookIndex: Index<Book> ) {} searchBooks(q: string) { return this.bookIndex.search(q); } } ``` --- ## โš™๏ธ Async Configuration ```ts @Module({ imports: [ ConfigModule.forRoot(), MeiliModule.forRootAsync({ useFactory: (config: ConfigService) => ({ host: config.get("MEILI_HOST"), apiKey: config.get("MEILI_API_KEY"), }), inject: [ConfigService], }), MeiliModule.forFeature([Book]), ], }) export class AppModule {} ``` --- ## ๐Ÿง  Available Decorators | Decorator | Target | Purpose | | ---------------------- | -------- | ----------------------------------- | | `@MeiliIndex(name)` | Class | Define MeiliSearch index name | | `@PrimaryKey()` | Property | Set primary key field | | `@Searchable()` | Property | Field is full-text searchable | | `@Filterable()` | Property | Field is usable in filters | | `@Sortable()` | Property | Field is sortable | | `@Displayed()` | Property | Field is returned in search results | | `@Distinct()` | Property | Used for deduplication | | `@RankingRules([...])` | Class | Custom ranking rules | | `@StopWords([...])` | Class | Stop words for the index | | `@Synonyms({...})` | Class | Synonyms map | | `@Pagination(n)` | Class | Sets `maxTotalHits` | | `@Faceting(n)` | Class | Sets `maxValuesPerFacet` | --- ## ๐Ÿงช Testing Replace `MeiliService` with a mock in unit tests: ```ts { provide: MeiliService, useValue: { getIndex: jest.fn().mockReturnValue(mockIndex), }, } ``` You can also inject and mock the index directly using `@InjectMeiliIndex(YourModel)`. --- ## ๐Ÿงญ Architecture - `MeiliModule.forRoot(...)` initializes the Meili client once - `MeiliModule.forFeature([ModelA, ModelB])`: - Registers each index based on decorators - Applies index settings at startup - Exposes injectable typed index via `@InjectMeiliIndex(Model)` No need for external config, global registries, or reflection hacks. --- ## โ“ Why use `nestjs-meili`? | Feature | Manual Setup | `nestjs-meili` | | --------------------------- | ------------ | -------------- | | Type-safe index injection | โŒ | โœ… | | Centralized index config | โŒ | โœ… | | Decorator-based schema | โŒ | โœ… | | Built-in support for NestJS | โŒ | โœ… | | No global registry required | โŒ | โœ… | --- ## ๐Ÿšง Roadmap - [ ] Auto-sync schema changes (diff vs Meili state) - [ ] CLI to print index status & debug settings - [ ] Hooks: `@OnIndexSynced()`, `@OnIndexError()` - [ ] Optional `@Boost()` decorator - [ ] Automatic deletion/reindex hooks --- ## ๐Ÿ“œ License MIT ยฉ 2025