JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q39087F
  • License MIT

Modern TypeScript wrapper for Typesense search engine API

Package Exports

  • @goatlab/typesense
  • @goatlab/typesense/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@goatlab/typesense) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@goatlab/typesense

A modern, type-safe TypeScript wrapper for the Typesense search engine API. This package provides a comprehensive client with built-in resilience, multi-tenancy support, and a clean, grouped API interface.

Installation

npm install @goatlab/typesense
# or
pnpm add @goatlab/typesense
# or
yarn add @goatlab/typesense

Basic Usage

import { TypesenseApi } from '@goatlab/typesense'

// Initialize the client
const typesense = new TypesenseApi({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key',
  collectionName: 'products' // default collection name
})

// Create a collection
await typesense.collections.create({
  name: 'products',
  fields: [
    { name: 'id', type: 'string' },
    { name: 'title', type: 'string' },
    { name: 'price', type: 'float' },
    { name: 'description', type: 'string' }
  ]
})

// Insert a document
await typesense.documents.insert({
  id: '1',
  title: 'iPhone 15',
  price: 999.99,
  description: 'Latest Apple smartphone'
})

// Search documents
const results = await typesense.search.query({
  q: 'iphone',
  query_by: 'title,description'
})

Key Features

  • Grouped API Interface: Organized methods under logical namespaces (collections, documents, search, admin)
  • Full Type Safety: Generic type support for document operations with compile-time checking
  • Multi-tenancy Support: Built-in tenant isolation with automatic collection name prefixing
  • Resilience Features: Circuit breaker pattern, rate limiting, and automatic retries
  • Schema Management: Automatic schema caching and version compatibility checks
  • Stream Support: Efficient document export with streaming capabilities
  • Advanced Search: Support for text search, vector search, and multi-search operations

Available Methods

Collections

  • collections.create() - Create a new collection
  • collections.get() - Retrieve collection details
  • collections.update() - Update collection schema
  • collections.delete() - Delete a collection
  • collections.list() - List all collections
  • collections.getOrCreate() - Get existing or create new collection

Documents

  • documents.insert() - Insert a single document
  • documents.upsert() - Insert or update a document
  • documents.update() - Update an existing document
  • documents.delete() - Delete a document by ID
  • documents.getById() - Retrieve a document by ID
  • documents.import() - Bulk import documents
  • documents.export() - Export documents (with optional filtering)
  • documents.exportStream() - Export documents as a stream
  • documents.deleteByFilter() - Delete documents matching a filter
  • documents.clear() - Clear all documents in a collection
  • search.query() - Perform a search query
  • search.text() - Text-based search
  • search.vector() - Vector similarity search
  • search.multi() - Execute multiple searches in one request

Admin

  • admin.health() - Check server health
  • admin.waitForHealth() - Wait for server to be healthy
  • admin.getMetrics() - Get server metrics
  • admin.getStats() - Get server statistics
  • admin.getCollectionStats() - Get collection-specific statistics

Additional Features (v29+)

  • Aliases: Create and manage collection aliases
  • Synonyms: Define search synonyms
  • Overrides: Set up search result overrides
  • Presets: Configure search presets

Type Safety

The TypesenseApi supports full type safety for document operations:

Basic Typed API

import { createTypedApi } from '@goatlab/typesense'

// Define your document type
interface Product {
  id: string
  title: string
  price: number
  inStock: boolean
}

// Create a typed API instance
const productApi = createTypedApi<Product>()({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key',
  collectionName: 'products'
})

// All document operations are now type-safe
await productApi.documents.insert({
  id: '1',
  title: 'Widget',
  price: 99.99,
  inStock: true
}) // ✅ Typed

// TypeScript will catch errors at compile time
// await productApi.documents.insert({ id: '2', title: 'Gadget' })
// ❌ Error: missing 'price' and 'inStock'

Direct Generic Usage

const api = new TypesenseApi<Product>({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key',
  collectionName: 'products'
})

Multi-tenancy

The TypesenseApi provides built-in multi-tenancy support through collection-level isolation:

Basic Tenant Setup

// Create API instance with tenant ID
const api = new TypesenseApi({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key',
  tenantId: 'acme',  // Tenant ID
  collectionName: 'products'
})

// All operations use tenant-prefixed collections automatically
// Collection name becomes: 'acme__products'
await api.documents.insert({ id: '1', name: 'Product' })

Type-Safe Tenant APIs

import { forTenant } from '@goatlab/typesense'

interface Customer {
  id: string
  name: string
  email: string
}

// Create tenant-specific APIs with compile-time safety
const tenant1Api = forTenant<Customer, 'tenant1'>('tenant1', {
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key',
  collectionName: 'customers'
})

// Tenant ID is preserved in the type
const tenantId: 'tenant1' = tenant1Api.tenantId // ✅ Type-safe

Tenant Admin Operations

// List all collections for a tenant
const collections = await api.listTenantCollections()
// Returns: ['acme__products', 'acme__users', ...]

// Get base collection names (without prefix)
const baseNames = await api.listTenantBaseCollectionNames()
// Returns: ['products', 'users', ...]

// Check if a collection exists
const exists = await api.tenantCollectionExists('products')

// Delete all tenant collections (use with caution!)
await api.deleteAllTenantCollections()

Collection Naming Convention

Tenant collections follow the pattern: <tenantId>__<baseCollectionName>

  • Tenant IDs are automatically sanitized (lowercase, alphanumeric + hyphens/underscores)
  • Maximum tenant ID length: 128 characters
  • Examples: acme__products, tenant-123__users

Schema-based Type Safety

The TypesenseApi provides compile-time type safety for your collections using TypeScript's advanced type system:

Define Collections with Type Inference

import { TypesenseApi } from '@goatlab/typesense'

// Define your collection schema with proper const assertions
const ProductCollection = TypesenseApi.defineCollection({
  name: 'products',
  fields: [
    { name: 'id', type: 'string' as const },
    { name: 'title', type: 'string' as const },
    { name: 'description', type: 'string' as const, optional: true },
    { name: 'price', type: 'float' as const },
    { name: 'inStock', type: 'bool' as const },
    { name: 'tags', type: 'string[]' as const, optional: true },
    { name: 'rating', type: 'int32' as const, optional: true }
  ] as const
} as const)

// Create a strongly-typed API instance
const api = TypesenseApi.createSchemaTypedApi(ProductCollection)({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key'
})

// All operations are now fully typed with autocomplete
await api.documents.insert({
  id: 'prod-001',
  title: 'Laptop',           // ✅ Required, must be string
  price: 999.99,            // ✅ Required, must be number
  inStock: true,            // ✅ Required, must be boolean
  description: 'Gaming laptop', // ✅ Optional, can be omitted
  tags: ['gaming', 'laptop']   // ✅ Optional, must be string[]
})

// TypeScript will catch these errors at compile time:
// ❌ Missing required field
// await api.documents.insert({
//   id: 'prod-002',
//   price: 99.99,
//   inStock: true
//   // Error: Property 'title' is missing
// })

// ❌ Wrong type
// await api.documents.insert({
//   id: 'prod-003',
//   title: 'Product',
//   price: '99.99',  // Error: Type 'string' is not assignable to type 'number'
//   inStock: true
// })

One-Step API Creation

For simpler cases, you can define and create the API in one step:

const api = TypesenseApi.createFromSchema({
  name: 'products',
  fields: [
    { name: 'id', type: 'string' as const },
    { name: 'title', type: 'string' as const },
    { name: 'price', type: 'float' as const },
    { name: 'inStock', type: 'bool' as const }
  ] as const
} as const)({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key'
})

Complex Field Types

The type inference supports all Typesense field types:

const EventCollection = TypesenseApi.defineCollection({
  name: 'events',
  fields: [
    { name: 'id', type: 'string' as const },
    { name: 'name', type: 'string' as const },
    { name: 'timestamp', type: 'int64' as const },
    { name: 'location', type: 'geopoint' as const },      // [lat, lon] tuple
    { name: 'attendees', type: 'int32[]' as const, optional: true },
    { name: 'metadata', type: 'object' as const, optional: true },
    { name: 'tags', type: 'auto' as const, optional: true }  // string | string[]
  ] as const
} as const)

const api = TypesenseApi.createSchemaTypedApi(EventCollection)({
  prefixUrl: 'http://localhost:8108',
  token: 'your-api-key'
})

// Properly typed document
await api.documents.insert({
  id: 'evt-001',
  name: 'Tech Conference',
  timestamp: Date.now(),
  location: [37.7749, -122.4194],  // Geopoint as [lat, lon]
  attendees: [100, 200, 300],      // Optional int32 array
  metadata: { venue: 'Moscone Center' }  // Optional object
})

Key Features

  • Compile-time type checking - No runtime overhead
  • Full autocomplete support - Your IDE knows all field names and types
  • Optional field handling - Correctly distinguishes between required and optional fields
  • All Typesense types supported - Including arrays, objects, geopoints, and auto fields
  • Zero runtime validation - Pure TypeScript type inference

Alternative Import Methods

The utility functions are also available as direct imports:

import { defineCollection, createSchemaTypedApi } from '@goatlab/typesense'

const collection = defineCollection({...})
const api = createSchemaTypedApi(collection)({...})

Type Mapping Reference

Typesense Type TypeScript Type
string string
string[] string[]
int32, int64 number
int32[], int64[] number[]
float number
float[] number[]
bool boolean
bool[] boolean[]
geopoint [number, number]
geopoint[] [number, number][]
object Record<string, any>
object[] Record<string, any>[]
auto string | string[]

Note: The id field is excluded from the document type for insert() operations, as it's handled separately by the TypesenseApi with WithRequiredId<T> type.

Advanced Configuration

const typesense = new TypesenseApi({
  prefixUrl: 'https://typesense.example.com',
  token: 'your-api-key',
  
  // Multi-tenancy
  tenantId: 'customer-123',
  
  // Timeouts
  searchTimeout: 5000,
  importTimeout: 60000,
  defaultTimeout: 10000,
  
  // Resilience settings
  resilience: {
    maxFailures: 5,
    resetTimeout: 60000,
    halfOpenRequests: 3
  },
  
  // Other options
  autoCreateCollection: true,
  enableVersionCheck: true,
  suppressLogs: false
})

Components

The package includes several utility components that can be used independently:

  • TypesenseHttpClient - HTTP client with built-in authentication
  • ResiliencePolicy - Circuit breaker and rate limiting implementation
  • CollectionSchemaManager - Schema caching and management
  • TypesenseFilterBuilder - Fluent filter query builder
  • ExportFormatter - Document export formatting utilities