@samveys/typesense

Version
1.0.2Nov 5, 2026
Install
pnpm add @samveys/typesense

From packages/typesense/README.md in the framework repository.

A Typesense driver for @samveys/search. It talks to Typesense over its REST API with the global fetch, so it has no runtime dependencies. It passes the @samveys/search conformance suite against a real Typesense container.

Use it

ts
import { typesense } from '@samveys/typesense'
import type { SearchIndexDefinition } from '@samveys/search/contracts'

const driver = typesense({ host: 'http://127.0.0.1:8108', apiKey: process.env['TYPESENSE_API_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
}
OptionMeaning
hostBase URL of Typesense
apiKeyAPI key, sent as X-TYPESENSE-API-KEY. Never put in an error message
requestTimeoutMsPer-request timeout. Default 30 000

Engine failures throw SamveysError SVS_E107.

How it behaves

  • Ranking. Fields are searched with query_by and query_by_weights. Typesense wants positive integer weights, so each weight is rounded and raised to at least 1 (a weight of 0.4 becomes 1).
  • Every word must match. drop_tokens_threshold is 0, so Typesense never drops words to find more results. Punctuation in user text is replaced by spaces, so quotes, -, * and : are plain separators; empty text matches everything.
  • Consistency. Writes are visible as soon as the call returns. There is no refresh step.
  • Totals. found is exact.
  • Filters. Stored as strings with a type prefix, percent-encoded, and queried as backtick-quoted filter_by values, so no user value can end the quote. The type prefix means the number 1 and the string '1' are different filter values.
  • Ids. Percent-encoded when stored and decoded when returned.
  • flush. Drops and recreates the collection. That is the only call that empties a collection of any size.

Run the conformance test

sh
SVS_REQUIRE_DOCKER=1 node --no-warnings --test packages/typesense/test/conformance.test.ts

The test starts typesense/typesense:27.1 as samveys-conformance-typesense-<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.