SearchFn

Getting Started

Install SearchFn, index documents, and run your first search query in minutes.

Packages

SearchFn is split into focused packages. Install only what you need:

PackagePurpose
@searchfn/coreBuilt-in search engine (text pipeline, BM25 scoring, inverted index, fuzzy matching)
@searchfn/adaptersAdapter implementations — Memory and IndexedDB (built-in engine), Postgres, Meilisearch, Elasticsearch/OpenSearch (external backends)
@searchfn/clientClient API for app code that calls search directly (browser or Node)
@searchfn/serverHTTP server exposing /searchfn/* endpoints with authorization and logging
@searchfn/datafn-providerDataFn integration — maps any adapter into a DataFn SearchProvider

Installation

For client-side or in-process search (uses the built-in search engine):

npm install @searchfn/client @searchfn/adapters

For server-side HTTP search API:

npm install @searchfn/server @searchfn/adapters

Quick Start

The quickstart uses MemoryAdapter, which runs SearchFn's built-in search engine in-process. No external services required — this is the same engine that powers production in-process and offline-first search.

1. Create a Client

import { createSearchClient } from "@searchfn/client";
import { MemoryAdapter } from "@searchfn/adapters";

const client = createSearchClient({
  adapter: new MemoryAdapter(),
  defaults: {
    limit: 20,
    limitPerResource: 10,
    fuzzy: true,
  },
});

2. Initialize Resources

Before indexing, declare which resources exist and which fields are searchable:

await client.initialize?.({
  resources: [
    { name: "tasks", searchFields: ["title", "description"] },
    { name: "notes", searchFields: ["content"] },
  ],
});

3. Index Documents

await client.index({
  resource: "tasks",
  documents: [
    { id: "t-1", fields: { title: "Ship docs", description: "Write getting started guide" } },
    { id: "t-2", fields: { title: "Fix bug", description: "Handle retry logic" } },
    { id: "t-3", fields: { title: "Plan launch", description: "Coordinate docs and release" } },
  ],
});
const ids = await client.search({
  resource: "tasks",
  query: "docs",
  limit: 5,
});

console.log(ids); // ["t-1", "t-3"]

5. Search Across Resources

const results = await client.searchAll({
  query: "docs",
  resources: ["tasks", "notes"],
  limitPerResource: 5,
});

// [{ resource: "tasks", id: "t-1", score: 1.2 }, ...]

Server Quick Start

The server wraps any adapter behind HTTP endpoints with built-in validation, authorization, and structured logging.

import { createSearchFnServer } from "@searchfn/server";
import { MemoryAdapter } from "@searchfn/adapters";

const server = await createSearchFnServer({
  adapter: new MemoryAdapter(),
  basePath: "/searchfn",
});

// Mount server.router with your @superfunctions/http adapter (Express, Fastify, Hono, etc.)

The server exposes these endpoints under the configured basePath:

EndpointMethodDescription
/searchfn/statusGETHealth check and adapter info
/searchfn/indexPOSTIndex documents into a resource
/searchfn/searchPOSTSearch a single resource
/searchfn/search-allPOSTSearch across multiple resources
/searchfn/removePOSTRemove documents by ID
/searchfn/clearPOSTClear all documents in a resource

Convenience Constructors

For common setups, use the built-in shorthand constructors:

import { createMemorySearchClient, createIndexedDbSearchClient } from "@searchfn/client";

const memoryClient = createMemorySearchClient({
  defaults: { limit: 20, fuzzy: true },
});

const browserClient = createIndexedDbSearchClient({
  adapterConfig: { dbName: "my-app-search" },
  defaults: { limit: 20, fuzzy: true },
});

Next Steps

  • Architecture — search engine internals and adapter contract.
  • Adapters — choose the right adapter for your use case.
  • Client API — full method reference.
  • Server API — endpoint details and authorization.
  • Operations — deployment, limits, and production setup.