emergentdb
v0.0.13
Published
Official TypeScript/JavaScript SDK for EmergentDB vector database
Maintainers
Readme
EmergentDB TypeScript SDK
Official TypeScript/JavaScript SDK for EmergentDB — a managed vector database for embeddings.
Install
npm install emergentdbQuick Start
import { EmergentDB } from "emergentdb";
const db = new EmergentDB("emdb_your_api_key");
// Insert a vector
await db.insert(1, [0.1, 0.2, ...], { title: "My document" });
// Search
const results = await db.search([0.1, 0.2, ...], {
k: 5,
includeMetadata: true,
});
// Delete
await db.delete(1);API
new EmergentDB(apiKey, options?)
Create a client. API key must start with emdb_.
| Option | Type | Default |
|-----------|--------|--------------------------------|
| baseUrl | string | https://api.emergentdb.com |
db.insert(id, vector, metadata?, namespace?)
Insert a single vector. Re-inserting the same ID in the same namespace upserts it.
const result = await db.insert(1, embedding, { title: "Doc" }, "production");
// { success: true, id: 1, namespace: "production", upserted: false }db.batchInsert(vectors, namespace?)
Insert up to 1,000 vectors in one call.
const result = await db.batchInsert([
{ id: 1, vector: [...], metadata: { title: "Doc 1" } },
{ id: 2, vector: [...], metadata: { title: "Doc 2" } },
], "production");
// { success: true, ids: [1, 2], count: 2, new_count: 2, upserted_count: 0 }db.batchInsertAll(vectors, namespace?)
Insert any number of vectors — auto-chunks into batches of 1,000.
const result = await db.batchInsertAll(largeVectorArray, "production");db.search(vector, options?)
Search for similar vectors.
| Option | Type | Default |
|-------------------|---------|-------------|
| k | number | 10 |
| includeMetadata | boolean | false |
| namespace | string | "default" |
const { results, count, namespace } = await db.search(queryVector, {
k: 10,
includeMetadata: true,
namespace: "production",
});
for (const r of results) {
console.log(`${r.id}: ${r.score} — ${r.metadata?.title}`);
}Scores are distances — lower = more similar.
db.delete(id, namespace?)
Delete a vector by ID.
const result = await db.delete(1, "production");
// { deleted: true, id: 1, namespace: "production" }db.listNamespaces()
List all namespaces that have vectors.
const namespaces = await db.listNamespaces();
// ["default", "production", "staging"]Namespaces
Namespaces partition your vectors into isolated groups. They're created automatically on first insert — no setup needed.
// Insert into different namespaces
await db.insert(1, vec, { title: "Prod doc" }, "production");
await db.insert(1, vec, { title: "Dev doc" }, "development");
// Search is scoped to one namespace
const prod = await db.search(q, { namespace: "production" });
const dev = await db.search(q, { namespace: "development" });Vector IDs are unique per namespace — ID 1 in "production" and ID 1 in "development" are completely separate vectors.
With OpenAI Embeddings
import OpenAI from "openai";
import { EmergentDB } from "emergentdb";
const openai = new OpenAI();
const db = new EmergentDB("emdb_your_key");
// Generate embedding
const resp = await openai.embeddings.create({
model: "text-embedding-3-small",
input: "How do neural networks learn?",
});
// Store it
await db.insert(1, resp.data[0].embedding, {
title: "Neural Networks 101",
tags: ["ml", "neural-networks"],
});
// Search later
const queryResp = await openai.embeddings.create({
model: "text-embedding-3-small",
input: "What is backpropagation?",
});
const results = await db.search(queryResp.data[0].embedding, {
k: 5,
includeMetadata: true,
});Error Handling
import { EmergentDB, EmergentDBError } from "emergentdb";
try {
await db.insert(1, vector);
} catch (err) {
if (err instanceof EmergentDBError) {
console.log(err.status); // 401, 402, 400, etc.
console.log(err.body); // Full error response
}
}| Status | Meaning | |--------|--------------------------| | 400 | Invalid request | | 401 | Bad or missing API key | | 402 | Vector capacity exceeded | | 404 | Vector not found | | 500 | Server error |
Type Exports
All response types and schemas are exported:
import {
InsertResult, InsertResultSchema,
BatchInsertResult, BatchInsertResultSchema,
SearchResult, SearchResultSchema,
SearchResponse, SearchResponseSchema,
DeleteResult, DeleteResultSchema,
SearchOptions, SearchOptionsSchema,
VectorEntry, VectorEntrySchema,
} from "emergentdb";Schemas use dhi (Zod-compatible), so you can compose them into your own validation pipelines.
QDKV — Metadata Cache
Every EmergentDB account includes 10K QDKV keys free — same emdb_ API key, no new signup.
QDKV is a SIMD-accelerated key-value cache (Redis alternative) for session state, feature flags, rate counters, and anything that needs sub-millisecond reads at the edge.
HTTP API
# SET
curl -X POST https://api.emergentdb.com/qdkv/set \
-H "Authorization: Bearer emdb_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "key": "session:abc", "value": "{\"userId\":42}", "ttlMs": 3600000 }'
# GET
curl https://api.emergentdb.com/qdkv/get/session:abc \
-H "Authorization: Bearer emdb_YOUR_API_KEY"
# → { "value": "{\"userId\":42}", "found": true }
# DEL
curl -X DELETE https://api.emergentdb.com/qdkv/del/session:abc \
-H "Authorization: Bearer emdb_YOUR_API_KEY"
# MGET (batch)
curl -X POST https://api.emergentdb.com/qdkv/mget \
-H "Authorization: Bearer emdb_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "keys": ["session:abc", "session:xyz"] }'
# → { "values": { "session:abc": "{...}", "session:xyz": null } }
# Stats
curl https://api.emergentdb.com/qdkv/stats \
-H "Authorization: Bearer emdb_YOUR_API_KEY"
# → { "keyCount": 42, "maxKeys": 10000, "plan": "free", "percentUsed": 0 }In Workers (TypeScript)
const KEY = "emdb_YOUR_API_KEY";
const BASE = "https://api.emergentdb.com";
// set
await fetch(`${BASE}/qdkv/set`, {
method: "POST",
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ key: "user:42:prefs", value: JSON.stringify(prefs), ttlMs: 86400_000 }),
});
// get
const r = await fetch(`${BASE}/qdkv/get/user:42:prefs`, {
headers: { Authorization: `Bearer ${KEY}` },
}).then(r => r.json()) as { value: string | null; found: boolean };
if (r.found) {
const prefs = JSON.parse(r.value!);
}Pricing
| Plan | Max Keys | Price | |------|----------|-------| | Free (all accounts) | 10,000 | $0/mo | | Launch | 1,000,000 | $29/mo | | Scale | 10,000,000 | $99/mo |
License
MIT
