edgevector
Version:
Official TypeScript/JavaScript SDK for EdgeVector - Edge-native multi-paradigm database with AI-first features
381 lines (377 loc) • 12.7 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* EdgeVector SDK
* Official TypeScript/JavaScript client for EdgeVector
*
* @version 1.0.0
* @author EdgeVector Team
*/
/**
* Main EdgeVector client class
*/
class EdgeVector {
constructor(config = {}) {
this.cache = new Map();
this.config = {
endpoint: config.endpoint || 'https://edgevector-db.finhub.workers.dev',
apiKey: config.apiKey || '',
timeout: config.timeout || 30000,
retries: config.retries || 3,
cache: config.cache ?? true,
compression: config.compression ?? true,
headers: config.headers || {},
region: config.region || 'us-east'
};
}
/**
* Make HTTP request with retry logic
*/
async request(path, options = {}) {
const url = `${this.config.endpoint}${path}`;
const cacheKey = `${options.method || 'GET'}:${path}:${JSON.stringify(options.body || {})}`;
// Check cache for GET requests
if (this.config.cache && (!options.method || options.method === 'GET')) {
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < 60000) { // 1 minute cache
return cached.data;
}
}
const headers = {
'Content-Type': 'application/json',
'User-Agent': 'EdgeVector-SDK/1.0.0',
...(this.config.apiKey && { 'Authorization': `Bearer ${this.config.apiKey}` }),
...(this.config.compression && { 'Accept-Encoding': 'gzip' }),
...this.config.headers,
...options.headers
};
let lastError;
for (let attempt = 0; attempt <= this.config.retries; attempt++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
const response = await fetch(url, {
...options,
headers,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
// Cache successful GET requests
if (this.config.cache && (!options.method || options.method === 'GET')) {
this.cache.set(cacheKey, { data, timestamp: Date.now() });
}
return data;
}
catch (error) {
lastError = error;
// Don't retry on client errors (4xx)
if (error.message.includes('HTTP 4')) {
throw error;
}
// Exponential backoff
if (attempt < this.config.retries) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}
throw lastError;
}
/**
* Get database health status
*/
async health() {
return this.request('/api/v1/health');
}
/**
* Get a collection reference
*/
collection(name) {
return new Collection(this, name);
}
/**
* Create a database reference
*/
db(name = 'default') {
return new Database(this, name);
}
/**
* AI operations
*/
get ai() {
return new AIOperations(this);
}
/**
* Time series operations
*/
timeseries(collection) {
return new TimeSeriesOperations(this, collection);
}
/**
* Create real-time stream
*/
async stream(options = {}) {
const params = new URLSearchParams();
if (options.collections)
params.append('collections', options.collections.join(','));
if (options.operations)
params.append('operations', options.operations.join(','));
if (options.filter)
params.append('filter', JSON.stringify(options.filter));
const eventSource = new EventSource(`${this.config.endpoint}/api/v1/stream?${params}`);
return eventSource;
}
/**
* Quick start helper for common use cases
*/
static quickStart(apiKey, appName) {
return new EdgeVector({
apiKey,
headers: appName ? { 'X-App-Name': appName } : {},
cache: true,
compression: true,
retries: 3
});
}
}
/**
* Database operations
*/
class Database {
constructor(client, name) {
this.client = client;
this.name = name;
}
collection(name) {
return new Collection(this.client, name);
}
async createCollection(name, options = {}) {
await this.client.request('/api/v1/collections', {
method: 'POST',
body: JSON.stringify({ name, database: this.name, ...options })
});
}
async dropCollection(name) {
await this.client.request(`/api/v1/collections/${name}`, {
method: 'DELETE'
});
}
async listCollections() {
const result = await this.client.request(`/api/v1/collections?database=${this.name}`);
return result.collections || [];
}
}
/**
* Collection operations
*/
class Collection {
constructor(client, name) {
this.client = client;
this.name = name;
}
// Document operations
async insertOne(document) {
const result = await this.client.request('/api/v1/documents', {
method: 'POST',
body: JSON.stringify({ collection: this.name, document })
});
return { insertedId: result.documentId };
}
async insertMany(documents) {
const result = await this.client.request('/api/v1/documents/bulk', {
method: 'POST',
body: JSON.stringify({ collection: this.name, documents })
});
return { insertedIds: result.documentIds || [] };
}
async findOne(filter = {}) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'POST',
body: JSON.stringify({ filter, limit: 1 })
});
return result.documents?.[0] || null;
}
async find(filter = {}, options = {}) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'POST',
body: JSON.stringify({ filter, ...options })
});
return result.documents || [];
}
async updateOne(filter, update) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'PATCH',
body: JSON.stringify({ filter, update, limit: 1 })
});
return { modifiedCount: result.modifiedCount || 0 };
}
async updateMany(filter, update) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'PATCH',
body: JSON.stringify({ filter, update })
});
return { modifiedCount: result.modifiedCount || 0 };
}
async deleteOne(filter) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'DELETE',
body: JSON.stringify({ filter, limit: 1 })
});
return { deletedCount: result.deletedCount || 0 };
}
async deleteMany(filter) {
const result = await this.client.request(`/api/v1/documents/${this.name}`, {
method: 'DELETE',
body: JSON.stringify({ filter })
});
return { deletedCount: result.deletedCount || 0 };
}
async aggregate(pipeline) {
const result = await this.client.request(`/api/v1/documents/${this.name}/aggregate`, {
method: 'POST',
body: JSON.stringify({ pipeline })
});
return result.results || [];
}
// Vector operations
async vectorSearch(options) {
const result = await this.client.request('/api/v1/vectors/search', {
method: 'POST',
body: JSON.stringify({ collection: this.name, ...options })
});
return result.results || [];
}
async hybridSearch(options) {
const result = await this.client.request('/api/v1/vectors/hybrid', {
method: 'POST',
body: JSON.stringify({ collection: this.name, ...options })
});
return result.results || [];
}
vectors() {
return new VectorOperations(this.client, this.name);
}
timeseries() {
return new TimeSeriesOperations(this.client, this.name);
}
// Real-time operations
async watch(filter = {}, callback) {
const eventSource = new EventSource(`${this.client.config.endpoint}/api/v1/collections/${this.name}/watch?filter=${JSON.stringify(filter)}`);
eventSource.onmessage = (event) => {
callback(JSON.parse(event.data));
};
return () => eventSource.close();
}
}
/**
* Vector-specific operations
*/
class VectorOperations {
constructor(client, collection) {
this.client = client;
this.collection = collection;
}
async insert(vector, metadata) {
const result = await this.client.request('/api/v1/vectors', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, vector, metadata })
});
return { id: result.id };
}
async search(vector, options = {}) {
const result = await this.client.request('/api/v1/vectors/search', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, vector, ...options })
});
return result.results || [];
}
async generateEmbedding(text) {
const result = await this.client.request('/api/v1/vectors/embed', {
method: 'POST',
body: JSON.stringify({ text })
});
return result;
}
async similaritySearch(text, options = {}) {
const result = await this.client.request('/api/v1/vectors/search', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, text, ...options })
});
return result.results || [];
}
}
/**
* Time series operations
*/
class TimeSeriesOperations {
constructor(client, collection) {
this.client = client;
this.collection = collection;
}
async write(points) {
const pointsArray = Array.isArray(points) ? points : [points];
await this.client.request('/api/v1/timeseries', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, points: pointsArray })
});
}
async query(options) {
const result = await this.client.request('/api/v1/timeseries/query', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, ...options })
});
return result.data || [];
}
async detectAnomalies(metric, options = {}) {
const result = await this.client.request('/api/v1/timeseries/anomalies', {
method: 'POST',
body: JSON.stringify({ collection: this.collection, metric, ...options })
});
return result.anomalies || [];
}
}
/**
* AI operations
*/
class AIOperations {
constructor(client) {
this.client = client;
}
async embed(text, model) {
const result = await this.client.request('/api/v1/ai/embed', {
method: 'POST',
body: JSON.stringify({ text, model })
});
return result;
}
async embedBatch(texts, model) {
const result = await this.client.request('/api/v1/ai/embed/batch', {
method: 'POST',
body: JSON.stringify({ texts, model })
});
return result;
}
async chat(messages, options = {}) {
const result = await this.client.request('/api/v1/ai/chat', {
method: 'POST',
body: JSON.stringify({ messages, ...options })
});
return result;
}
}
// Helper function for quick initialization
function quickStart(apiKey, appName) {
return EdgeVector.quickStart(apiKey, appName);
}
exports.AIOperations = AIOperations;
exports.Collection = Collection;
exports.Database = Database;
exports.EdgeVector = EdgeVector;
exports.TimeSeriesOperations = TimeSeriesOperations;
exports.VectorOperations = VectorOperations;
exports.default = EdgeVector;
exports.quickStart = quickStart;
//# sourceMappingURL=index.js.map