@ekodb/ekodb-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js ADDED
@@ -0,0 +1,553 @@
1
+ "use strict";
2
+ /**
3
+ * ekoDB TypeScript Client
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.WebSocketClient = exports.EkoDBClient = exports.MergeStrategy = exports.RateLimitError = void 0;
40
+ const query_builder_1 = require("./query-builder");
41
+ const search_1 = require("./search");
42
+ const schema_1 = require("./schema");
43
+ /**
44
+ * Rate limit error
45
+ */
46
+ class RateLimitError extends Error {
47
+ constructor(retryAfterSecs, message) {
48
+ super(message || `Rate limit exceeded. Retry after ${retryAfterSecs} seconds`);
49
+ this.retryAfterSecs = retryAfterSecs;
50
+ this.name = 'RateLimitError';
51
+ }
52
+ }
53
+ exports.RateLimitError = RateLimitError;
54
+ var MergeStrategy;
55
+ (function (MergeStrategy) {
56
+ MergeStrategy["Chronological"] = "Chronological";
57
+ MergeStrategy["Summarized"] = "Summarized";
58
+ MergeStrategy["LatestOnly"] = "LatestOnly";
59
+ })(MergeStrategy || (exports.MergeStrategy = MergeStrategy = {}));
60
+ class EkoDBClient {
61
+ constructor(config, apiKey) {
62
+ this.token = null;
63
+ this.rateLimitInfo = null;
64
+ // Support both old (baseURL, apiKey) and new (config object) signatures
65
+ if (typeof config === 'string') {
66
+ this.baseURL = config;
67
+ this.apiKey = apiKey;
68
+ this.shouldRetry = true;
69
+ this.maxRetries = 3;
70
+ this.timeout = 30000;
71
+ }
72
+ else {
73
+ this.baseURL = config.baseURL;
74
+ this.apiKey = config.apiKey;
75
+ this.shouldRetry = config.shouldRetry ?? true;
76
+ this.maxRetries = config.maxRetries ?? 3;
77
+ this.timeout = config.timeout ?? 30000;
78
+ }
79
+ }
80
+ /**
81
+ * Initialize the client by getting an auth token
82
+ */
83
+ async init() {
84
+ await this.refreshToken();
85
+ }
86
+ /**
87
+ * Get the current rate limit information
88
+ */
89
+ getRateLimitInfo() {
90
+ return this.rateLimitInfo;
91
+ }
92
+ /**
93
+ * Check if approaching rate limit (less than 10% remaining)
94
+ */
95
+ isNearRateLimit() {
96
+ if (!this.rateLimitInfo)
97
+ return false;
98
+ const threshold = this.rateLimitInfo.limit * 0.1;
99
+ return this.rateLimitInfo.remaining <= threshold;
100
+ }
101
+ /**
102
+ * Refresh the authentication token
103
+ */
104
+ async refreshToken() {
105
+ const response = await fetch(`${this.baseURL}/api/auth/token`, {
106
+ method: 'POST',
107
+ headers: { 'Content-Type': 'application/json' },
108
+ body: JSON.stringify({ api_key: this.apiKey }),
109
+ });
110
+ if (!response.ok) {
111
+ throw new Error(`Auth failed with status: ${response.status}`);
112
+ }
113
+ const result = await response.json();
114
+ this.token = result.token;
115
+ }
116
+ /**
117
+ * Extract rate limit information from response headers
118
+ */
119
+ extractRateLimitInfo(response) {
120
+ const limit = response.headers.get('x-ratelimit-limit');
121
+ const remaining = response.headers.get('x-ratelimit-remaining');
122
+ const reset = response.headers.get('x-ratelimit-reset');
123
+ if (limit && remaining && reset) {
124
+ this.rateLimitInfo = {
125
+ limit: parseInt(limit, 10),
126
+ remaining: parseInt(remaining, 10),
127
+ reset: parseInt(reset, 10),
128
+ };
129
+ // Log warning if approaching rate limit
130
+ if (this.isNearRateLimit()) {
131
+ console.warn(`Approaching rate limit: ${this.rateLimitInfo.remaining}/${this.rateLimitInfo.limit} remaining`);
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Sleep for a specified number of seconds
137
+ */
138
+ sleep(seconds) {
139
+ return new Promise(resolve => setTimeout(resolve, seconds * 1000));
140
+ }
141
+ /**
142
+ * Make an HTTP request to the ekoDB API with retry logic
143
+ */
144
+ async makeRequest(method, path, data, attempt = 0) {
145
+ if (!this.token) {
146
+ await this.refreshToken();
147
+ }
148
+ const options = {
149
+ method,
150
+ headers: {
151
+ 'Authorization': `Bearer ${this.token}`,
152
+ 'Content-Type': 'application/json',
153
+ },
154
+ };
155
+ if (data) {
156
+ options.body = JSON.stringify(data);
157
+ }
158
+ try {
159
+ const response = await fetch(`${this.baseURL}${path}`, options);
160
+ // Extract rate limit info from successful responses
161
+ if (response.ok) {
162
+ this.extractRateLimitInfo(response);
163
+ return response.json();
164
+ }
165
+ // Handle rate limiting (429)
166
+ if (response.status === 429) {
167
+ const retryAfter = parseInt(response.headers.get('retry-after') || '60', 10);
168
+ if (this.shouldRetry && attempt < this.maxRetries) {
169
+ console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);
170
+ await this.sleep(retryAfter);
171
+ return this.makeRequest(method, path, data, attempt + 1);
172
+ }
173
+ throw new RateLimitError(retryAfter);
174
+ }
175
+ // Handle service unavailable (503)
176
+ if (response.status === 503 && this.shouldRetry && attempt < this.maxRetries) {
177
+ const retryDelay = 10;
178
+ console.log(`Service unavailable. Retrying after ${retryDelay} seconds...`);
179
+ await this.sleep(retryDelay);
180
+ return this.makeRequest(method, path, data, attempt + 1);
181
+ }
182
+ // Handle other errors
183
+ const text = await response.text();
184
+ throw new Error(`Request failed with status ${response.status}: ${text}`);
185
+ }
186
+ catch (error) {
187
+ // Handle network errors with retry
188
+ if (error instanceof TypeError && this.shouldRetry && attempt < this.maxRetries) {
189
+ const retryDelay = 3;
190
+ console.log(`Network error. Retrying after ${retryDelay} seconds...`);
191
+ await this.sleep(retryDelay);
192
+ return this.makeRequest(method, path, data, attempt + 1);
193
+ }
194
+ throw error;
195
+ }
196
+ }
197
+ /**
198
+ * Insert a document into a collection
199
+ */
200
+ async insert(collection, record, ttl) {
201
+ const data = { ...record };
202
+ if (ttl) {
203
+ data.ttl_duration = ttl;
204
+ }
205
+ return this.makeRequest('POST', `/api/insert/${collection}`, data);
206
+ }
207
+ /**
208
+ * Find documents in a collection
209
+ *
210
+ * @param collection - Collection name
211
+ * @param query - Query object or QueryBuilder instance
212
+ * @returns Array of matching records
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * // Using QueryBuilder
217
+ * const results = await client.find("users",
218
+ * new QueryBuilder()
219
+ * .eq("status", "active")
220
+ * .gt("age", 18)
221
+ * .sortDesc("created_at")
222
+ * .limit(10)
223
+ * );
224
+ *
225
+ * // Using plain Query object
226
+ * const results = await client.find("users", { limit: 10 });
227
+ * ```
228
+ */
229
+ async find(collection, query = {}) {
230
+ const queryObj = query instanceof query_builder_1.QueryBuilder ? query.build() : query;
231
+ return this.makeRequest('POST', `/api/find/${collection}`, queryObj);
232
+ }
233
+ /**
234
+ * Find a document by ID
235
+ */
236
+ async findByID(collection, id) {
237
+ return this.makeRequest('GET', `/api/find/${collection}/${id}`);
238
+ }
239
+ /**
240
+ * Update a document
241
+ */
242
+ async update(collection, id, record) {
243
+ return this.makeRequest('PUT', `/api/update/${collection}/${id}`, record);
244
+ }
245
+ /**
246
+ * Delete a document
247
+ */
248
+ async delete(collection, id) {
249
+ await this.makeRequest('DELETE', `/api/delete/${collection}/${id}`);
250
+ }
251
+ /**
252
+ * Batch insert multiple documents
253
+ */
254
+ async batchInsert(collection, records) {
255
+ const inserts = records.map(data => ({ data }));
256
+ const result = await this.makeRequest('POST', `/api/batch/insert/${collection}`, { inserts });
257
+ return result.successful.map(id => ({ id }));
258
+ }
259
+ /**
260
+ * Batch update multiple documents
261
+ */
262
+ async batchUpdate(collection, updates) {
263
+ const result = await this.makeRequest('PUT', `/api/batch/update/${collection}`, { updates });
264
+ return result.successful.map(id => ({ id }));
265
+ }
266
+ /**
267
+ * Batch delete multiple documents
268
+ */
269
+ async batchDelete(collection, ids) {
270
+ const deletes = ids.map(id => ({ id }));
271
+ const result = await this.makeRequest('DELETE', `/api/batch/delete/${collection}`, { deletes });
272
+ return result.successful.length;
273
+ }
274
+ /**
275
+ * Set a key-value pair
276
+ */
277
+ async kvSet(key, value) {
278
+ await this.makeRequest('POST', `/api/kv/set/${encodeURIComponent(key)}`, { value });
279
+ }
280
+ /**
281
+ * Get a value by key
282
+ */
283
+ async kvGet(key) {
284
+ const result = await this.makeRequest('GET', `/api/kv/get/${encodeURIComponent(key)}`);
285
+ return result.value;
286
+ }
287
+ /**
288
+ * Delete a key
289
+ */
290
+ async kvDelete(key) {
291
+ await this.makeRequest('DELETE', `/api/kv/delete/${encodeURIComponent(key)}`);
292
+ }
293
+ /**
294
+ * List all collections
295
+ */
296
+ async listCollections() {
297
+ const result = await this.makeRequest('GET', '/api/collections');
298
+ return result.collections;
299
+ }
300
+ /**
301
+ * Delete a collection
302
+ */
303
+ async deleteCollection(collection) {
304
+ await this.makeRequest('DELETE', `/api/collections/${collection}`);
305
+ }
306
+ /**
307
+ * Create a collection with schema
308
+ *
309
+ * @param collection - Collection name
310
+ * @param schema - Schema definition or SchemaBuilder instance
311
+ *
312
+ * @example
313
+ * ```typescript
314
+ * const schema = new SchemaBuilder()
315
+ * .addField("name", new FieldTypeSchemaBuilder("string").required())
316
+ * .addField("email", new FieldTypeSchemaBuilder("string").unique())
317
+ * .addField("age", new FieldTypeSchemaBuilder("number").range(0, 150));
318
+ *
319
+ * await client.createCollection("users", schema);
320
+ * ```
321
+ */
322
+ async createCollection(collection, schema) {
323
+ const schemaObj = schema instanceof schema_1.SchemaBuilder ? schema.build() : schema;
324
+ await this.makeRequest('POST', `/api/collections/${collection}`, schemaObj);
325
+ }
326
+ /**
327
+ * Get collection metadata and schema
328
+ *
329
+ * @param collection - Collection name
330
+ * @returns Collection metadata including schema and analytics
331
+ */
332
+ async getCollection(collection) {
333
+ return this.makeRequest('GET', `/api/collections/${collection}`);
334
+ }
335
+ /**
336
+ * Get collection schema
337
+ *
338
+ * @param collection - Collection name
339
+ * @returns The collection schema
340
+ */
341
+ async getSchema(collection) {
342
+ const metadata = await this.getCollection(collection);
343
+ return metadata.collection;
344
+ }
345
+ /**
346
+ * Search documents in a collection using full-text, vector, or hybrid search
347
+ *
348
+ * @param collection - Collection name
349
+ * @param searchQuery - Search query object or SearchQueryBuilder instance
350
+ * @returns Search response with results and metadata
351
+ *
352
+ * @example
353
+ * ```typescript
354
+ * // Full-text search
355
+ * const results = await client.search("users",
356
+ * new SearchQueryBuilder("john")
357
+ * .fields(["name", "email"])
358
+ * .fuzzy(true)
359
+ * .limit(10)
360
+ * );
361
+ *
362
+ * // Vector search
363
+ * const results = await client.search("documents",
364
+ * new SearchQueryBuilder("")
365
+ * .vector([0.1, 0.2, 0.3, ...])
366
+ * .vectorK(5)
367
+ * );
368
+ *
369
+ * // Hybrid search
370
+ * const results = await client.search("products",
371
+ * new SearchQueryBuilder("laptop")
372
+ * .vector([0.1, 0.2, ...])
373
+ * .textWeight(0.7)
374
+ * .vectorWeight(0.3)
375
+ * );
376
+ * ```
377
+ */
378
+ async search(collection, searchQuery) {
379
+ const queryObj = searchQuery instanceof search_1.SearchQueryBuilder ? searchQuery.build() : searchQuery;
380
+ return this.makeRequest('POST', `/api/search/${collection}`, queryObj);
381
+ }
382
+ // ========== Chat Methods ==========
383
+ /**
384
+ * Create a new chat session
385
+ */
386
+ async createChatSession(request) {
387
+ return this.makeRequest('POST', '/api/chat', request);
388
+ }
389
+ /**
390
+ * Send a message in an existing chat session
391
+ */
392
+ async chatMessage(sessionId, request) {
393
+ return this.makeRequest('POST', `/api/chat/${sessionId}/messages`, request);
394
+ }
395
+ /**
396
+ * Get a chat session by ID
397
+ */
398
+ async getChatSession(sessionId) {
399
+ return this.makeRequest('GET', `/api/chat/${sessionId}`);
400
+ }
401
+ /**
402
+ * List all chat sessions
403
+ */
404
+ async listChatSessions(query) {
405
+ const params = new URLSearchParams();
406
+ if (query?.limit)
407
+ params.append('limit', query.limit.toString());
408
+ if (query?.skip)
409
+ params.append('skip', query.skip.toString());
410
+ if (query?.sort)
411
+ params.append('sort', query.sort);
412
+ const queryString = params.toString();
413
+ const path = queryString ? `/api/chat?${queryString}` : '/api/chat';
414
+ return this.makeRequest('GET', path);
415
+ }
416
+ /**
417
+ * Get messages from a chat session
418
+ */
419
+ async getChatSessionMessages(sessionId, query) {
420
+ const params = new URLSearchParams();
421
+ if (query?.limit)
422
+ params.append('limit', query.limit.toString());
423
+ if (query?.skip)
424
+ params.append('skip', query.skip.toString());
425
+ if (query?.sort)
426
+ params.append('sort', query.sort);
427
+ const queryString = params.toString();
428
+ const path = queryString ? `/api/chat/${sessionId}/messages?${queryString}` : `/api/chat/${sessionId}/messages`;
429
+ return this.makeRequest('GET', path);
430
+ }
431
+ /**
432
+ * Update a chat session
433
+ */
434
+ async updateChatSession(sessionId, request) {
435
+ return this.makeRequest('PUT', `/api/chat/${sessionId}`, request);
436
+ }
437
+ /**
438
+ * Branch a chat session
439
+ */
440
+ async branchChatSession(request) {
441
+ return this.makeRequest('POST', '/api/chat/branch', request);
442
+ }
443
+ /**
444
+ * Delete a chat session
445
+ */
446
+ async deleteChatSession(sessionId) {
447
+ await this.makeRequest('DELETE', `/api/chat/${sessionId}`);
448
+ }
449
+ /**
450
+ * Regenerate an AI response message
451
+ */
452
+ async regenerateMessage(sessionId, messageId) {
453
+ return this.makeRequest('POST', `/api/chat/${sessionId}/messages/${messageId}/regenerate`);
454
+ }
455
+ /**
456
+ * Update a specific message
457
+ */
458
+ async updateChatMessage(sessionId, messageId, content) {
459
+ await this.makeRequest('PUT', `/api/chat/${sessionId}/messages/${messageId}`, { content });
460
+ }
461
+ /**
462
+ * Delete a specific message
463
+ */
464
+ async deleteChatMessage(sessionId, messageId) {
465
+ await this.makeRequest('DELETE', `/api/chat/${sessionId}/messages/${messageId}`);
466
+ }
467
+ /**
468
+ * Toggle the "forgotten" status of a message
469
+ */
470
+ async toggleForgottenMessage(sessionId, messageId, forgotten) {
471
+ await this.makeRequest('PATCH', `/api/chat/${sessionId}/messages/${messageId}/forgotten`, { forgotten });
472
+ }
473
+ /**
474
+ * Merge multiple chat sessions into one
475
+ */
476
+ async mergeChatSessions(request) {
477
+ return this.makeRequest('POST', '/api/chat/merge', request);
478
+ }
479
+ /**
480
+ * Create a WebSocket client
481
+ */
482
+ websocket(wsURL) {
483
+ return new WebSocketClient(wsURL, this.token);
484
+ }
485
+ }
486
+ exports.EkoDBClient = EkoDBClient;
487
+ /**
488
+ * WebSocket client for real-time queries
489
+ */
490
+ class WebSocketClient {
491
+ constructor(wsURL, token) {
492
+ this.ws = null;
493
+ this.wsURL = wsURL;
494
+ this.token = token;
495
+ }
496
+ /**
497
+ * Connect to WebSocket
498
+ */
499
+ async connect() {
500
+ if (this.ws)
501
+ return;
502
+ // Dynamic import for Node.js WebSocket
503
+ const WebSocket = (await Promise.resolve().then(() => __importStar(require('ws')))).default;
504
+ let url = this.wsURL;
505
+ if (!url.endsWith('/api/ws')) {
506
+ url += '/api/ws';
507
+ }
508
+ this.ws = new WebSocket(url, {
509
+ headers: {
510
+ 'Authorization': `Bearer ${this.token}`,
511
+ },
512
+ });
513
+ return new Promise((resolve, reject) => {
514
+ this.ws.on('open', () => resolve());
515
+ this.ws.on('error', (err) => reject(err));
516
+ });
517
+ }
518
+ /**
519
+ * Find all records in a collection via WebSocket
520
+ */
521
+ async findAll(collection) {
522
+ await this.connect();
523
+ const messageId = Date.now().toString();
524
+ const request = {
525
+ type: 'FindAll',
526
+ messageId,
527
+ payload: { collection },
528
+ };
529
+ return new Promise((resolve, reject) => {
530
+ this.ws.send(JSON.stringify(request));
531
+ this.ws.once('message', (data) => {
532
+ const response = JSON.parse(data.toString());
533
+ if (response.type === 'Error') {
534
+ reject(new Error(response.message));
535
+ }
536
+ else {
537
+ resolve(response.payload?.data || []);
538
+ }
539
+ });
540
+ this.ws.once('error', reject);
541
+ });
542
+ }
543
+ /**
544
+ * Close the WebSocket connection
545
+ */
546
+ close() {
547
+ if (this.ws) {
548
+ this.ws.close();
549
+ this.ws = null;
550
+ }
551
+ }
552
+ }
553
+ exports.WebSocketClient = WebSocketClient;
@@ -0,0 +1,9 @@
1
+ export { EkoDBClient, WebSocketClient, MergeStrategy, RateLimitError } from './client';
2
+ export { QueryBuilder, SortOrder } from './query-builder';
3
+ export { SearchQueryBuilder } from './search';
4
+ export { SchemaBuilder, FieldTypeSchemaBuilder, VectorIndexAlgorithm, DistanceMetric } from './schema';
5
+ export { JoinBuilder } from './join';
6
+ export type { SearchQuery, SearchResult, SearchResponse } from './search';
7
+ export type { Schema, FieldTypeSchema, IndexConfig, CollectionMetadata } from './schema';
8
+ export type { JoinConfig } from './join';
9
+ export type { Record, Query, BatchOperationResult, ClientConfig, RateLimitInfo, CollectionConfig, ChatRequest, CreateChatSessionRequest, ChatMessageRequest, TokenUsage, ChatResponse, ChatSession, ChatSessionResponse, ListSessionsQuery, ListSessionsResponse, GetMessagesQuery, GetMessagesResponse, UpdateSessionRequest, MergeSessionsRequest } from './client';
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JoinBuilder = exports.DistanceMetric = exports.VectorIndexAlgorithm = exports.FieldTypeSchemaBuilder = exports.SchemaBuilder = exports.SearchQueryBuilder = exports.SortOrder = exports.QueryBuilder = exports.RateLimitError = exports.MergeStrategy = exports.WebSocketClient = exports.EkoDBClient = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "EkoDBClient", { enumerable: true, get: function () { return client_1.EkoDBClient; } });
6
+ Object.defineProperty(exports, "WebSocketClient", { enumerable: true, get: function () { return client_1.WebSocketClient; } });
7
+ Object.defineProperty(exports, "MergeStrategy", { enumerable: true, get: function () { return client_1.MergeStrategy; } });
8
+ Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return client_1.RateLimitError; } });
9
+ var query_builder_1 = require("./query-builder");
10
+ Object.defineProperty(exports, "QueryBuilder", { enumerable: true, get: function () { return query_builder_1.QueryBuilder; } });
11
+ Object.defineProperty(exports, "SortOrder", { enumerable: true, get: function () { return query_builder_1.SortOrder; } });
12
+ var search_1 = require("./search");
13
+ Object.defineProperty(exports, "SearchQueryBuilder", { enumerable: true, get: function () { return search_1.SearchQueryBuilder; } });
14
+ var schema_1 = require("./schema");
15
+ Object.defineProperty(exports, "SchemaBuilder", { enumerable: true, get: function () { return schema_1.SchemaBuilder; } });
16
+ Object.defineProperty(exports, "FieldTypeSchemaBuilder", { enumerable: true, get: function () { return schema_1.FieldTypeSchemaBuilder; } });
17
+ Object.defineProperty(exports, "VectorIndexAlgorithm", { enumerable: true, get: function () { return schema_1.VectorIndexAlgorithm; } });
18
+ Object.defineProperty(exports, "DistanceMetric", { enumerable: true, get: function () { return schema_1.DistanceMetric; } });
19
+ var join_1 = require("./join");
20
+ Object.defineProperty(exports, "JoinBuilder", { enumerable: true, get: function () { return join_1.JoinBuilder; } });
package/dist/join.d.ts ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Join support for multi-collection queries
3
+ *
4
+ * This module provides support for joining data across multiple collections,
5
+ * similar to SQL joins but with document-oriented semantics.
6
+ */
7
+ /**
8
+ * Configuration for joining collections
9
+ */
10
+ export interface JoinConfig {
11
+ /** Target collections to join with */
12
+ collections: string[];
13
+ /** Field in the current collection */
14
+ local_field: string;
15
+ /** Field in the target collection(s) */
16
+ foreign_field: string;
17
+ /** Name of the field to store joined data */
18
+ as_field: string;
19
+ }
20
+ /**
21
+ * Builder for constructing join configurations
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Single collection join
26
+ * const join = JoinBuilder.single("users", "user_id", "id", "user");
27
+ *
28
+ * // Multi-collection join
29
+ * const join = JoinBuilder.multi(
30
+ * ["users", "profiles", "settings"],
31
+ * "user_id",
32
+ * "id",
33
+ * "user_info"
34
+ * );
35
+ *
36
+ * // Use in query
37
+ * const query = new QueryBuilder()
38
+ * .eq("status", "active")
39
+ * .join(join)
40
+ * .build();
41
+ * ```
42
+ */
43
+ export declare class JoinBuilder {
44
+ private config;
45
+ private constructor();
46
+ /**
47
+ * Create a join with a single collection
48
+ *
49
+ * @param collection - Target collection name
50
+ * @param localField - Field in the current collection
51
+ * @param foreignField - Field in the target collection
52
+ * @param asField - Name of the field to store joined data
53
+ */
54
+ static single(collection: string, localField: string, foreignField: string, asField: string): JoinConfig;
55
+ /**
56
+ * Create a join with multiple collections
57
+ *
58
+ * @param collections - Array of target collection names
59
+ * @param localField - Field in the current collection
60
+ * @param foreignField - Field in the target collections
61
+ * @param asField - Name of the field to store joined data
62
+ */
63
+ static multi(collections: string[], localField: string, foreignField: string, asField: string): JoinConfig;
64
+ /**
65
+ * Build the final JoinConfig
66
+ */
67
+ build(): JoinConfig;
68
+ }