Skip to content

Repository files navigation

TSense

Opinionated, fully-typed Typesense client powered by Arktype

Installation

bun add tsense arktype

Example

import { type } from "arktype";
import { TSense } from "tsense";

const UsersCollection = new TSense({
  name: "users",
  schema: type({
    "id?": "string",
    email: "string",
    age: type("number.integer").configure({ type: "int32", sort: true }),
    "company?": type.enumerated("netflix", "google").configure({ facet: true }),
    "phone?": "string",
    name: type("string").configure({ sort: true }),
    "work_history?": type({
      company: "string",
      date: "string",
    })
      .array()
      .configure({ type: "object[]", index: false }),
  }),
  connection: {
    host: "127.0.0.1",
    port: 8108,
    protocol: "http",
    apiKey: "123",
  },
  defaultSearchField: "name",
  validateOnUpsert: true,
});

type User = typeof UsersCollection.infer;

await UsersCollection.create();

await UsersCollection.upsert([
  { id: "1", email: "john@example.com", age: 30, name: "John Doe", company: "netflix" },
  { id: "2", email: "jane@example.com", age: 25, name: "Jane Smith", company: "google" },
]);

const results = await UsersCollection.search({
  query: "john",
  queryBy: ["name", "email"],
  sortBy: ["age:desc", "name:asc"],
  filter: {
    age: { min: 20 },
    OR: [{ company: "google" }, { company: "netflix" }],
  },
});

const faceted = await UsersCollection.search({
  query: "john",
  facetBy: ["company"],
});

const highlighted = await UsersCollection.search({
  query: "john",
  highlight: true,
});

await UsersCollection.drop();

API Reference

Schema Configuration

Use .configure() to set Typesense field options:

type("string").configure({
  type: "string",
  facet: true,
  sort: true,
  index: true,
});

Collection Methods

Method/Property Description
create() Creates the collection in Typesense
drop() Deletes the collection
get(id) Retrieves a document by ID
delete(id) Deletes a document by ID
deleteMany(filter) Deletes documents matching filter
update(id, data) Updates a document by ID
updateMany(filter, data) Updates documents matching filter
upsert(docs) Inserts or updates documents
search(options) Searches the collection
syncSchema() Syncs schema (creates/patches collection)
syncData(options) Syncs data from external source
fields Array of generated field schemas

Schema Sync

Automatically sync schema before the first operation:

const Collection = new TSense({
  // ...
  autoSyncSchema: true,
});

Or manually:

await Collection.syncSchema();

Data Sync

Sync documents from an external source (database, API, etc.):

const Collection = new TSense({
  // ...
  dataSync: {
    getAllIds: async () => {
      return db
        .selectFrom("users")
        .select("id")
        .execute()
        .then((rows) => rows.map((r) => r.id));
    },
    getItems: async (ids) => {
      return db.selectFrom("users").where("id", "in", ids).execute();
    },
    chunkSize: 100, // optional, default 500
  },
});

// Full sync
await Collection.syncData();

// Partial sync (specific IDs)
await Collection.syncData({ ids: ["id1", "id2"] });

// Full sync + remove orphan documents
await Collection.syncData({ purge: true });

// Override chunk size
await Collection.syncData({ chunkSize: 50 });

Filter Syntax

filter: { name: "John" }                    // Exact match
filter: { age: 30 }                         // Numeric match
filter: { age: [25, 30, 35] }               // IN
filter: { age: { min: 20, max: 40 } }       // Range
filter: { name: { not: "John" } }           // Not equal
filter: { OR: [{ age: 25 }, { age: 30 }] }  // OR conditions

About

Opinionated, fully typed typesense client

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages