TypeScript SDK for FerresDB vector database
npm install @ferresdb/typescript-sdkSDK TypeScript oficial para o FerresDB - banco de dados vetorial de alta performance.
``bash`
pnpm add @ferresdb/typescript-sdkou
npm install @ferresdb/typescript-sdkou
yarn add @ferresdb/typescript-sdk
Para usar o SDK contra uma instância real do FerresDB, você pode subir o backend e o frontend com as imagens oficiais.
`bash`
docker pull ferresdb/ferres-db-core
docker pull ferresdb/ferres-db-frontend
`bash`
docker run -d \
--name ferres-db-core \
-p 8080:8080 \
-e PORT=8080 \
-e STORAGE_PATH=/data \
-e FERRESDB_API_KEYS=ferres_sk_sua_chave_aqui \
-v ferres-data:/data \
ferresdb/ferres-db-core
- API: http://localhost:8080
- FERRESDB_API_KEYS: chave(s) de API aceitas pelo servidor (opcional; se omitir, use uma chave criada depois via dashboard ou API de keys, se disponível).ferres-data
- O volume persiste coleções e dados entre reinícios.
Com o backend já em execução:
`bash`
docker run -d \
--name ferres-db-frontend \
-p 3000:80 \
-e VITE_API_BASE_URL=http://localhost:8080 \
-e VITE_API_KEY=ferres_sk_sua_chave_aqui \
ferresdb/ferres-db-frontend
- Dashboard: http://localhost:3000
- VITE_API_BASE_URL: URL do backend (ajuste se o backend estiver em outro host/porta).VITE_API_KEY
- : mesma chave configurada no backend, para o dashboard autenticar.
Se o navegador acessar o frontend em uma máquina diferente do host onde o backend roda, use a URL acessível do backend em VITE_API_BASE_URL (ex.: http://ip-do-servidor:8080).
Com o backend no ar em http://localhost:8080 e a mesma API key:
`typescript
import { VectorDBClient } from "@ferres-db/typescript-sdk";
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_sua_chave_aqui",
});
// criar coleções, upsert, search, etc.
`
Todas as rotas de dados (coleções, pontos, busca, API keys) exigem autenticação. Passe a API key nas opções do cliente; o SDK envia automaticamente o header Authorization: Bearer em todas as requisições.
`typescript`
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_...", // obrigatório para rotas protegidas
});
Sem apiKey, o servidor responderá 401 em rotas protegidas.
`typescript
import { VectorDBClient, DistanceMetric } from "@ferres-db/typescript-sdk";
// Cria uma instância do cliente (apiKey necessário para criar/listar coleções, etc.)
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_...",
timeout: 30000,
});
// Cria uma coleção
const collection = await client.createCollection({
name: "documents",
dimension: 384, // Dimensão dos vetores (ex: all-MiniLM-L6-v2)
distance: DistanceMetric.Cosine,
});
console.log("Coleção criada:", collection.name);
// Insere pontos
const points = [
{
id: "doc-1",
vector: [0.1, 0.2, 0.3 / ... 384 dimensões /],
metadata: { text: "Primeiro documento", category: "tech" },
},
{
id: "doc-2",
vector: [0.4, 0.5, 0.6 / ... 384 dimensões /],
metadata: { text: "Segundo documento", category: "science" },
},
];
const result = await client.upsertPoints("documents", points);
console.log(Inseridos: ${result.upserted}, Falhos: ${result.failed.length});
// Busca os 5 pontos mais similares
const queryVector = [0.15, 0.25, 0.35 / ... 384 dimensões /];
const results = await client.search("documents", {
vector: queryVector,
limit: 5,
});
for (const result of results) {
console.log(ID: ${result.id}, Score: ${result.score.toFixed(4)});Metadata:
console.log(, result.metadata);`
}
`typescript
import { VectorDBClient, DistanceMetric } from "@ferres-db/typescript-sdk";
// Assumindo que você tem uma função que gera embeddings
async function generateEmbedding(text: string): Promise
// Use sua biblioteca de embeddings (OpenAI, Cohere, etc)
// Retorna um vetor de 384 dimensões
return []; // Placeholder
}
async function main() {
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_...",
});
// Cria a coleção
await client.createCollection({
name: "documents",
dimension: 384,
distance: DistanceMetric.Cosine,
});
// Indexa documentos
const documents = [
"Rust é uma linguagem de programação",
"Python é popular para machine learning",
"Vector databases são úteis para RAG",
];
const points = [];
for (let i = 0; i < documents.length; i++) {
const embedding = await generateEmbedding(documents[i]);
points.push({
id: doc-${i},
vector: embedding,
metadata: { text: documents[i] },
});
}
await client.upsertPoints("documents", points);
// Busca semântica
const queryEmbedding = await generateEmbedding("linguagem de programação");
const results = await client.search("documents", {
vector: queryEmbedding,
limit: 3,
});
console.log("Documentos mais similares:");
for (const result of results) {
console.log(
- ${result.metadata.text} (similaridade: ${result.score.toFixed(4)}),
);
}
}
main().catch(console.error);
`
`typescript
import { VectorDBClient } from "@ferres-db/typescript-sdk";
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_...",
});
// Busca com filtro de metadata
const results = await client.search("documents", {
vector: queryVector,
limit: 10,
filter: {
category: "tech", // Apenas documentos com category='tech'
},
});
`
`typescript
import {
VectorDBClient,
CollectionNotFoundError,
CollectionAlreadyExistsError,
InvalidDimensionError,
} from "@ferres-db/typescript-sdk";
const client = new VectorDBClient({
baseUrl: "http://localhost:8080",
apiKey: "ferres_sk_...",
maxRetries: 5, // Número máximo de tentativas
retryDelay: 1000, // Delay inicial em ms (exponential backoff)
});
try {
await client.createCollection({
name: "my-collection",
dimension: 384,
distance: DistanceMetric.Cosine,
});
} catch (error) {
if (error instanceof CollectionAlreadyExistsError) {
console.log("Coleção já existe");
} else if (error instanceof InvalidDimensionError) {
console.error("Dimensão inválida:", error.message);
} else {
console.error("Erro desconhecido:", error);
}
}
`
#### Constructor
`typescript`
new VectorDBClient(options: VectorDBClientOptions)
Opções:
- baseUrl (string, obrigatório): URL base do servidor FerresDB (ex: 'http://localhost:8080')apiKey
- (string, opcional): Chave de API para autenticação. Recomendado para todas as rotas de dados; o SDK envia Authorization: Bearer .timeout
- (number, opcional): Timeout das requisições em ms (padrão: 30000)maxRetries
- (number, opcional): Número máximo de tentativas em caso de erro (padrão: 3)retryDelay
- (number, opcional): Delay inicial para retry em ms (padrão: 1000)
#### Métodos
##### createCollection(config: CollectionConfig): Promise
Cria uma nova coleção.
Parâmetros:
- config.name (string): Nome da coleção (apenas letras, números, hífens e underscores)config.dimension
- (number): Dimensão dos vetores (1-4096)config.distance
- (DistanceMetric): Métrica de distânciaconfig.enable_bm25
- (boolean, opcional): Habilita índice BM25 para busca híbrida (padrão: false)config.bm25_text_field
- (string, opcional): Chave em metadata usada como texto para BM25 (padrão: "text")
Retorna: Coleção criada
Erros:
- CollectionAlreadyExistsError: Se a coleção já existeInvalidDimensionError
- : Se a dimensão é inválidaInvalidPayloadError
- : Se o payload é inválido
##### listCollections(): Promise
Lista todas as coleções.
Retorna: Array de coleções
##### deleteCollection(name: string): Promise
Remove uma coleção.
Parâmetros:
- name (string): Nome da coleção
Erros:
- CollectionNotFoundError: Se a coleção não existe
##### upsertPoints(collection: string, points: Point[]): Promise
Insere ou atualiza pontos em uma coleção. Automaticamente faz batching se houver mais de 1000 pontos.
Parâmetros:
- collection (string): Nome da coleçãopoints
- (Point[]): Array de pontos para inserir/atualizar
Retorna: Resultado com número de pontos inseridos e lista de falhas
Erros:
- CollectionNotFoundError: Se a coleção não existeInvalidDimensionError
- : Se as dimensões dos vetores não correspondem
##### deletePoints(collection: string, ids: string[]): Promise
Remove pontos de uma coleção pelos IDs.
Parâmetros:
- collection (string): Nome da coleçãoids
- (string[]): Array de IDs dos pontos a remover
Erros:
- CollectionNotFoundError: Se a coleção não existeInvalidPayloadError
- : Se o array de IDs está vazio
##### search(collection: string, query: SearchQuery): Promise
Busca pontos similares a um vetor de consulta.
Parâmetros:
- collection (string): Nome da coleçãoquery.vector
- (number[]): Vetor de consultaquery.limit
- (number): Número máximo de resultadosquery.filter
- (object, opcional): Filtro de metadata (equality matching)
Retorna: Array de resultados ordenados por similaridade
Erros:
- CollectionNotFoundError: Se a coleção não existeInvalidDimensionError
- : Se a dimensão do vetor não corresponde
##### listKeys(): Promise
Lista as API keys (metadados, sem o valor bruto). Requer API key com perfil Editor/Admin.
Retorna: Array de ApiKeyInfo (id, name, key_prefix, created_at)
##### createKey(name: string): Promise
Cria uma nova API key. O valor bruto (key) é retornado apenas uma vez; armazene-o com segurança.
Parâmetros: name (string): Nome de exibição da chave
Retorna: CreateKeyResponse (id, name, key, key_prefix, created_at)
Erros: InvalidPayloadError se o nome estiver vazio
##### deleteKey(id: number): Promise
Remove uma API key pelo id (retornado por listKeys ou createKey).
#### DistanceMetric
`typescript`
enum DistanceMetric {
Cosine = "Cosine",
DotProduct = "DotProduct",
Euclidean = "Euclidean",
}
#### Point
`typescript`
interface Point {
id: string;
vector: number[];
metadata: Record
}
#### Collection
`typescript`
interface Collection {
name: string;
dimension: number;
distance: DistanceMetric;
created_at?: number;
}
#### SearchResult
`typescript`
interface SearchResult {
id: string;
score: number;
metadata: Record
}
#### UpsertResult
`typescript`
interface UpsertResult {
upserted: number;
failed: Array<{
id: string;
reason: string;
}>;
}
#### ApiKeyInfo
`typescript`
interface ApiKeyInfo {
id: number;
name: string;
key_prefix: string;
created_at: number;
}
#### CreateKeyResponse
`typescript`
interface CreateKeyResponse {
id: number;
name: string;
key: string; // valor bruto — retornado apenas na criação
key_prefix: string;
created_at: number;
}
Todos os erros herdam de VectorDBError:
- CollectionNotFoundError: Coleção não encontrada (404)CollectionAlreadyExistsError
- : Coleção já existe (409)InvalidDimensionError
- : Dimensão inválida (400)InvalidPayloadError
- : Payload inválido (400)InternalError
- : Erro interno do servidor (500)ConnectionError
- : Erro de conexão
`bash`
pnpm install
pnpm build
`bash`
pnpm test
pnpm test:watch
pnpm test:coverage
`bash`
pnpm typecheck
- Autenticação: use apiKey nas opções para rotas de dados; o SDK envia Authorization: Bearer em todas as requisições.
- O SDK usa Axios para requisições HTTP com interceptors para tratamento de erros
- Validação runtime com Zod para garantir tipos corretos
- Retry automático com exponential backoff para erros de servidor (5xx) e conexão
- Suporte para ESM e CJS exports
- Batching automático para operações de upsert com mais de 1000 pontos
O FerresDB também oferece uma API gRPC nativa (porta 50051 por padrão) como alternativa à API REST. Este SDK usa a API REST; para usar gRPC diretamente, gere stubs de cliente a partir do arquivo proto/ferresdb.proto no repositório do servidor (requer --features grpc no build do server).
Para gerar stubs gRPC em TypeScript, use o pacote @grpc/proto-loader ou protoc com o plugin grpc_tools_node_protoc_ts`.
MIT