@samveys/meilisearch
From packages/meilisearch/README.md in the framework repository.
A Meilisearch driver for @samveys/search. It talks to Meilisearch over its REST API with the global fetch, so it has no runtime dependencies. It passes the @samveys/search conformance suite against a real Meilisearch container.
Use it
import { meilisearch } from '@samveys/meilisearch'
import type { SearchIndexDefinition } from '@samveys/search/contracts'
const driver = meilisearch({ host: 'http://127.0.0.1:7700', apiKey: process.env['MEILI_MASTER_KEY'] })
const reports: SearchIndexDefinition = {
name: 'reports',
fields: { title: { weight: 3 }, body: { weight: 1 } },
filters: ['region'],
}
export async function demo(): Promise<readonly string[]> {
await driver.ensureIndex(reports)
await driver.upsert(reports, [{ id: '1', fields: { title: 'October revenue report', body: 'numbers' }, filters: { region: 'bali' } }])
const { ids } = await driver.search(reports, { text: 'october revenue', filters: { region: 'bali' }, limit: 10, offset: 0 })
return ids
}Pass the driver wherever @samveys/search takes one (see that package for searchable()).
| Option | Meaning |
|---|---|
host | Base URL of Meilisearch |
apiKey | Master or admin key, sent as a bearer token. Never put in an error message |
taskTimeoutMs | How long to wait for an indexing task. Default 60 000 |
requestTimeoutMs | Per-request timeout. Default 30 000 |
Engine failures throw SamveysError SVS_E107.
How it behaves
- Ranking. Meilisearch ranks by the order of
searchableAttributes, not by numeric weights. The driver orders fields by descending weight, so a higher-weight field wins over a lower one. Equal weights keep declaration order. - Every word must match. Searches use
matchingStrategy: "all". Quotes and a leading-in user text are removed, so they are plain words, not operators. - Consistency. Meilisearch indexes asynchronously. Every write waits for its task to succeed before it returns, so a document is searchable as soon as
upsert,removeorflushresolves. - Totals. When
offsetis a multiple oflimit, the total is exact (page mode). Otherwise Meilisearch only gives an estimate (estimatedTotalHits). - Filters. Values are quoted and escaped in the filter string. Filter names must be letters, digits and underscores.
- Ids. Meilisearch only allows
[A-Za-z0-9_-]in primary keys, so ids are stored base64url-encoded alongside the original.
Run the conformance test
SVS_REQUIRE_DOCKER=1 node --no-warnings --test packages/meilisearch/test/conformance.test.tsThe test starts getmeili/meilisearch:v1.12 as samveys-conformance-meilisearch-<pid> and removes it afterwards. Without Docker it skips; SVS_DOCKER=0 forces a skip, and SVS_REQUIRE_DOCKER=1 makes a missing Docker a failure.