@goatlab/typesense
Version:
Modern TypeScript wrapper for Typesense search engine API
274 lines (273 loc) • 10.9 kB
TypeScript
import type { TypesenseRateLimitInfo, WithRequiredId, TypesenseDocument, TypesenseCollectionOptions, TypesenseCollection } from './typesense.model';
import { defineCollection as defineCollectionUtil, type InferFromCollection } from './utils/schema-to-types';
import { createSchemaTypedApi as createSchemaTypedApiUtil } from './utils/schema-typed-api';
import { TypesenseHttpClient, type HttpClientOptions } from './components/http-client';
import { ResiliencePolicy, type ResiliencePolicyOptions } from './components/resilience-policy';
import { CollectionSchemaManager } from './components/schema-manager';
export interface TypesenseApiOptions extends Omit<HttpClientOptions, 'prefixUrl' | 'token'> {
prefixUrl: string;
token: string;
tenantId?: string;
collectionName?: string;
suppressLogs?: boolean;
appName?: string;
appVersion?: string;
autoCreateCollection?: boolean;
enableVersionCheck?: boolean;
schemaCacheSize?: number;
schemaCacheTtl?: number;
resilience?: ResiliencePolicyOptions;
typesenseVersion?: string;
onCircuitBreakerStateChange?: (state: 'open' | 'closed' | 'half-open', metadata?: any) => void;
onRateLimitUpdate?: (info: TypesenseRateLimitInfo) => void;
}
/**
* Modern, modular Typesense API client with grouped functionality
*
* @example
* ```typescript
* const api = new TypesenseApi({
* prefixUrl: 'http://localhost:8108',
* token: 'xyz',
* collectionName: 'products'
* })
*
* // Collections
* await api.collections.create({ name: 'products', fields: [...] })
* await api.collections.getOrCreate({ name: 'products', fields: [...] })
*
* // Documents
* await api.documents.insert({ id: '1', title: 'Product 1' })
* await api.documents.search({ q: 'product', query_by: 'title' })
*
* // Admin
* await api.admin.health()
* await api.admin.getMetrics()
* ```
*/
/**
* Factory helper for creating typed TypesenseApi instances
* @example
* ```typescript
* interface Product { id: string; title: string; price: number; }
* const productApi = createTypedApi<Product>()({
* prefixUrl: 'http://localhost:8108',
* token: 'xyz',
* collectionName: 'products'
* })
*
* // Now all document operations are typed
* await productApi.documents.insert({ id: "1", title: "Foo", price: 42 }) // ✅ typed
* ```
*/
export declare const createTypedApi: <TDoc extends Record<string, any>>() => (options: TypesenseApiOptions) => TypesenseApi<TDoc>;
/**
* Type-safe multitenant API wrapper
*/
export type TenantApi<TDoc, TenantId extends string> = TypesenseApi<TDoc> & {
readonly tenantId: TenantId;
};
export declare class TypesenseApi<TDoc extends Record<string, any> = Record<string, any>> {
private readonly ctx;
private withCtx;
private readonly options;
readonly httpClient: TypesenseHttpClient;
readonly resilience: ResiliencePolicy;
readonly schemaManager: CollectionSchemaManager;
/**
* Define a strongly-typed collection schema
* @example
* ```typescript
* const ProductCollection = TypesenseApi.defineCollection({
* 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)
* ```
*/
static defineCollection: typeof defineCollectionUtil;
/**
* Create a strongly-typed API instance from a collection schema
* @example
* ```typescript
* const ProductCollection = TypesenseApi.defineCollection({...})
*
* const api = TypesenseApi.createSchemaTypedApi(ProductCollection)({
* prefixUrl: 'http://localhost:8108',
* token: 'xyz'
* })
*
* // Now all document operations are fully typed
* await api.documents.insert({
* id: '1',
* title: 'Product',
* price: 99.99,
* inStock: true
* })
* ```
*/
static createSchemaTypedApi: typeof createSchemaTypedApiUtil;
/**
* Create a typed API from an inline collection definition (convenience method)
* @example
* ```typescript
* 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 }
* ] as const
* } as const)({
* prefixUrl: 'http://localhost:8108',
* token: 'xyz'
* })
* ```
*/
static createFromSchema<const C extends TypesenseCollection>(collection: C): (options: Omit<TypesenseApiOptions, "collectionName">) => TypesenseApi<InferFromCollection<C>>;
constructor(options: TypesenseApiOptions);
private checkVersion;
/**
* Collection management operations
*/
get collections(): {
create: (collection: TypesenseCollection) => any;
get: (collectionName?: string) => any;
update: (collection: Partial<TypesenseCollection>, options?: TypesenseCollectionOptions) => any;
delete: (collectionName?: string) => any;
list: () => any;
getOrCreate: (collection: TypesenseCollection) => any;
};
/**
* Document CRUD operations
*/
get documents(): {
insert: (document: WithRequiredId<TDoc>, options?: TypesenseCollectionOptions) => Promise<TypesenseDocument<TDoc>>;
upsert: (document: WithRequiredId<TDoc>, options?: TypesenseCollectionOptions) => Promise<TypesenseDocument<TDoc>>;
update: (document: Partial<TypesenseDocument<TDoc>> & {
id: string | number;
}, options?: TypesenseCollectionOptions) => Promise<TypesenseDocument<TDoc>>;
delete: (id: string | number, options?: TypesenseCollectionOptions) => any;
getById: (id: string | number, options?: TypesenseCollectionOptions) => any;
import: (documents: string | import("stream").Readable | TypesenseDocument<Record<string, any>>[], format?: import("./typesense.model").TypesenseImportFormat, importOptions?: import("./typesense.model").TypesenseImportOptions, collectionOptions?: TypesenseCollectionOptions) => any;
export: (format?: import("./typesense.model").TypesenseExportFormat, options?: import("./typesense.model").TypesenseExportOptions & TypesenseCollectionOptions) => any;
exportStream: (options?: import("./typesense.model").TypesenseExportOptions & TypesenseCollectionOptions) => any;
deleteByFilter: (filter: string, options?: import("./typesense.model").TypesenseDeleteByFilterOptions & TypesenseCollectionOptions) => any;
clear: (options?: TypesenseCollectionOptions) => any;
search: (query: import("./typesense.model").TypesenseQuery, options?: TypesenseCollectionOptions) => any;
searchText: (query: import("./typesense.model").TypesenseTextQuery, options?: TypesenseCollectionOptions) => any;
searchVector: (query: import("./typesense.model").TypesenseVectorQuery, options?: TypesenseCollectionOptions) => any;
};
/**
* Search operations (alias for documents.search*)
*/
get search(): {
query: (query: import("./typesense.model").TypesenseQuery, options?: TypesenseCollectionOptions) => any;
text: (query: import("./typesense.model").TypesenseTextQuery, options?: TypesenseCollectionOptions) => any;
vector: (query: import("./typesense.model").TypesenseVectorQuery, options?: TypesenseCollectionOptions) => any;
multi: (request: import("./typesense.model").TypesenseMultiSearchRequest) => any;
};
/**
* Admin operations
*/
get admin(): {
health: () => any;
waitForHealth: (maxRetries?: number, delayMs?: number) => any;
getMetrics: () => any;
getStats: () => any;
getCollectionStats: (collectionName?: string) => any;
};
/**
* Alias management (v29+)
*/
get aliases(): {
createOrUpdate: (aliasName: string, collectionName: string) => any;
get: (aliasName: string) => any;
list: () => any;
delete: (aliasName: string) => any;
};
/**
* Synonym management (v29+)
*/
get synonyms(): {
upsert: (synonym: import("./typesense.model").TypesenseSynonym, options?: TypesenseCollectionOptions) => any;
get: (synonymId: string, options?: TypesenseCollectionOptions) => any;
list: (options?: TypesenseCollectionOptions) => any;
delete: (synonymId: string, options?: TypesenseCollectionOptions) => any;
};
/**
* Search override management (v29+)
*/
get overrides(): {
upsert: (override: import("./typesense.model").TypesenseOverride, options?: TypesenseCollectionOptions) => any;
get: (overrideId: string, options?: TypesenseCollectionOptions) => any;
list: (options?: TypesenseCollectionOptions) => any;
delete: (overrideId: string, options?: TypesenseCollectionOptions) => any;
};
/**
* Preset management (v29+)
*/
get presets(): {
upsert: (preset: import("./typesense.model").TypesensePreset) => any;
get: (presetName: string) => any;
list: () => any;
delete: (presetName: string) => any;
};
/**
* Get current resilience status
*/
getResilienceStatus(): {
failures: number;
circuitOpen: boolean;
circuitOpenUntil: number;
rateLimited: boolean;
retryAfterUntil: number;
rateLimit: TypesenseRateLimitInfo | null;
};
/**
* Get current rate limit info
*/
getRateLimit(): TypesenseRateLimitInfo;
/**
* Get cache statistics
*/
getCacheStats(): {
size: number;
maxSize: number;
};
/**
* Get client version
*/
getVersion(): string;
/**
* Get Typesense server version
*/
getTypesenseVersion(): string;
/**
* Admin helper: List all collections for the current tenant
* Returns only collections that belong to the configured tenant
*/
listTenantCollections(): Promise<string[]>;
/**
* Admin helper: Get base collection names for the current tenant
* Returns collection names without the tenant prefix
*/
listTenantBaseCollectionNames(): Promise<string[]>;
/**
* Admin helper: Delete all collections for the current tenant
* Use with caution - this will permanently delete all tenant data
*/
deleteAllTenantCollections(): Promise<void>;
/**
* Admin helper: Check if a collection exists for the current tenant
*/
tenantCollectionExists(baseCollectionName?: string): Promise<boolean>;
/**
* Destroy the client and clean up resources
*/
destroy(): void;
}