@ekodb/ekodb-client 0.6.1 → 0.7.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.d.ts CHANGED
@@ -206,6 +206,9 @@ export declare class EkoDBClient {
206
206
  private makeRequest;
207
207
  /**
208
208
  * Insert a document into a collection
209
+ * @param collection - Collection name
210
+ * @param record - Document to insert
211
+ * @param ttl - Optional TTL: duration string ("1h", "30m"), seconds ("3600"), or ISO8601 timestamp
209
212
  */
210
213
  insert(collection: string, record: Record, ttl?: string): Promise<Record>;
211
214
  /**
@@ -260,9 +263,12 @@ export declare class EkoDBClient {
260
263
  */
261
264
  batchDelete(collection: string, ids: string[], bypassRipple?: boolean): Promise<BatchOperationResult>;
262
265
  /**
263
- * Set a key-value pair
266
+ * Set a key-value pair with optional TTL
267
+ * @param key - The key to set
268
+ * @param value - The value to store
269
+ * @param ttl - Optional TTL in seconds
264
270
  */
265
- kvSet(key: string, value: any): Promise<void>;
271
+ kvSet(key: string, value: any, ttl?: number): Promise<void>;
266
272
  /**
267
273
  * Get a value by key
268
274
  */
@@ -271,6 +277,53 @@ export declare class EkoDBClient {
271
277
  * Delete a key
272
278
  */
273
279
  kvDelete(key: string): Promise<void>;
280
+ /**
281
+ * Check if a key exists
282
+ * @param key - The key to check
283
+ * @returns true if the key exists, false otherwise
284
+ */
285
+ kvExists(key: string): Promise<boolean>;
286
+ /**
287
+ * Query/find KV entries with pattern matching
288
+ * @param options - Query options including pattern and include_expired
289
+ * @returns Array of matching records
290
+ */
291
+ kvFind(options?: {
292
+ pattern?: string;
293
+ include_expired?: boolean;
294
+ }): Promise<any[]>;
295
+ /**
296
+ * Alias for kvFind - query KV store with pattern
297
+ */
298
+ kvQuery(options?: {
299
+ pattern?: string;
300
+ include_expired?: boolean;
301
+ }): Promise<any[]>;
302
+ /**
303
+ * Begin a new transaction
304
+ * @param isolationLevel - Transaction isolation level (default: "ReadCommitted")
305
+ * @returns Transaction ID
306
+ */
307
+ beginTransaction(isolationLevel?: string): Promise<string>;
308
+ /**
309
+ * Get transaction status
310
+ * @param transactionId - The transaction ID
311
+ * @returns Transaction status object
312
+ */
313
+ getTransactionStatus(transactionId: string): Promise<{
314
+ state: string;
315
+ operations_count: number;
316
+ }>;
317
+ /**
318
+ * Commit a transaction
319
+ * @param transactionId - The transaction ID to commit
320
+ */
321
+ commitTransaction(transactionId: string): Promise<void>;
322
+ /**
323
+ * Rollback a transaction
324
+ * @param transactionId - The transaction ID to rollback
325
+ */
326
+ rollbackTransaction(transactionId: string): Promise<void>;
274
327
  /**
275
328
  * List all collections
276
329
  */
package/dist/client.js CHANGED
@@ -263,11 +263,14 @@ class EkoDBClient {
263
263
  }
264
264
  /**
265
265
  * Insert a document into a collection
266
+ * @param collection - Collection name
267
+ * @param record - Document to insert
268
+ * @param ttl - Optional TTL: duration string ("1h", "30m"), seconds ("3600"), or ISO8601 timestamp
266
269
  */
267
270
  async insert(collection, record, ttl) {
268
271
  const data = { ...record };
269
272
  if (ttl) {
270
- data.ttl_duration = ttl;
273
+ data.ttl = ttl;
271
274
  }
272
275
  return this.makeRequest("POST", `/api/insert/${collection}`, data);
273
276
  }
@@ -347,10 +350,17 @@ class EkoDBClient {
347
350
  return this.makeRequest("DELETE", `/api/batch/delete/${collection}`, { deletes });
348
351
  }
349
352
  /**
350
- * Set a key-value pair
353
+ * Set a key-value pair with optional TTL
354
+ * @param key - The key to set
355
+ * @param value - The value to store
356
+ * @param ttl - Optional TTL in seconds
351
357
  */
352
- async kvSet(key, value) {
353
- await this.makeRequest("POST", `/api/kv/set/${encodeURIComponent(key)}`, { value }, 0, true);
358
+ async kvSet(key, value, ttl) {
359
+ const body = { value };
360
+ if (ttl !== undefined) {
361
+ body.ttl = ttl;
362
+ }
363
+ await this.makeRequest("POST", `/api/kv/set/${encodeURIComponent(key)}`, body, 0, true);
354
364
  }
355
365
  /**
356
366
  * Get a value by key
@@ -365,6 +375,69 @@ class EkoDBClient {
365
375
  async kvDelete(key) {
366
376
  await this.makeRequest("DELETE", `/api/kv/delete/${encodeURIComponent(key)}`, undefined, 0, true);
367
377
  }
378
+ /**
379
+ * Check if a key exists
380
+ * @param key - The key to check
381
+ * @returns true if the key exists, false otherwise
382
+ */
383
+ async kvExists(key) {
384
+ try {
385
+ const result = await this.kvGet(key);
386
+ return result !== null && result !== undefined;
387
+ }
388
+ catch {
389
+ return false;
390
+ }
391
+ }
392
+ /**
393
+ * Query/find KV entries with pattern matching
394
+ * @param options - Query options including pattern and include_expired
395
+ * @returns Array of matching records
396
+ */
397
+ async kvFind(options) {
398
+ const result = await this.makeRequest("POST", "/api/kv/find", options || {}, 0, true);
399
+ return result;
400
+ }
401
+ /**
402
+ * Alias for kvFind - query KV store with pattern
403
+ */
404
+ async kvQuery(options) {
405
+ return this.kvFind(options);
406
+ }
407
+ // ============================================================================
408
+ // Transaction Operations
409
+ // ============================================================================
410
+ /**
411
+ * Begin a new transaction
412
+ * @param isolationLevel - Transaction isolation level (default: "ReadCommitted")
413
+ * @returns Transaction ID
414
+ */
415
+ async beginTransaction(isolationLevel = "ReadCommitted") {
416
+ const result = await this.makeRequest("POST", "/api/transactions", { isolation_level: isolationLevel }, 0, true);
417
+ return result.transaction_id;
418
+ }
419
+ /**
420
+ * Get transaction status
421
+ * @param transactionId - The transaction ID
422
+ * @returns Transaction status object
423
+ */
424
+ async getTransactionStatus(transactionId) {
425
+ return this.makeRequest("GET", `/api/transactions/${encodeURIComponent(transactionId)}`, undefined, 0, true);
426
+ }
427
+ /**
428
+ * Commit a transaction
429
+ * @param transactionId - The transaction ID to commit
430
+ */
431
+ async commitTransaction(transactionId) {
432
+ await this.makeRequest("POST", `/api/transactions/${encodeURIComponent(transactionId)}/commit`, undefined, 0, true);
433
+ }
434
+ /**
435
+ * Rollback a transaction
436
+ * @param transactionId - The transaction ID to rollback
437
+ */
438
+ async rollbackTransaction(transactionId) {
439
+ await this.makeRequest("POST", `/api/transactions/${encodeURIComponent(transactionId)}/rollback`, undefined, 0, true);
440
+ }
368
441
  /**
369
442
  * List all collections
370
443
  */
@@ -174,6 +174,26 @@ export type FunctionStageConfig = {
174
174
  } | {
175
175
  type: "ReleaseSavepoint";
176
176
  name: string;
177
+ } | {
178
+ type: "KvGet";
179
+ key: string;
180
+ output_field?: string;
181
+ } | {
182
+ type: "KvSet";
183
+ key: string;
184
+ value: any;
185
+ ttl?: number;
186
+ } | {
187
+ type: "KvDelete";
188
+ key: string;
189
+ } | {
190
+ type: "KvExists";
191
+ key: string;
192
+ output_field?: string;
193
+ } | {
194
+ type: "KvQuery";
195
+ pattern?: string;
196
+ include_expired?: boolean;
177
197
  };
178
198
  export interface ChatMessage {
179
199
  role: string;
@@ -275,4 +295,9 @@ export declare const Stage: {
275
295
  createSavepoint: (name: string) => FunctionStageConfig;
276
296
  rollbackToSavepoint: (name: string) => FunctionStageConfig;
277
297
  releaseSavepoint: (name: string) => FunctionStageConfig;
298
+ kvGet: (key: string, output_field?: string) => FunctionStageConfig;
299
+ kvSet: (key: string, value: any, ttl?: number) => FunctionStageConfig;
300
+ kvDelete: (key: string) => FunctionStageConfig;
301
+ kvExists: (key: string, output_field?: string) => FunctionStageConfig;
302
+ kvQuery: (pattern?: string, include_expired?: boolean) => FunctionStageConfig;
278
303
  };
package/dist/functions.js CHANGED
@@ -206,4 +206,30 @@ exports.Stage = {
206
206
  type: "ReleaseSavepoint",
207
207
  name,
208
208
  }),
209
+ // KV Store operations - faster than collection lookups for simple key-value data
210
+ kvGet: (key, output_field) => ({
211
+ type: "KvGet",
212
+ key,
213
+ output_field,
214
+ }),
215
+ kvSet: (key, value, ttl) => ({
216
+ type: "KvSet",
217
+ key,
218
+ value,
219
+ ttl,
220
+ }),
221
+ kvDelete: (key) => ({
222
+ type: "KvDelete",
223
+ key,
224
+ }),
225
+ kvExists: (key, output_field) => ({
226
+ type: "KvExists",
227
+ key,
228
+ output_field,
229
+ }),
230
+ kvQuery: (pattern, include_expired) => ({
231
+ type: "KvQuery",
232
+ pattern,
233
+ include_expired,
234
+ }),
209
235
  };
package/dist/index.d.ts CHANGED
@@ -4,7 +4,8 @@ export { SearchQueryBuilder } from "./search";
4
4
  export { SchemaBuilder, FieldTypeSchemaBuilder, VectorIndexAlgorithm, DistanceMetric, } from "./schema";
5
5
  export { JoinBuilder } from "./join";
6
6
  export { Stage, ChatMessage } from "./functions";
7
- export { getValue, getValues, extractRecord, getDateTimeValue, getUUIDValue, getDecimalValue, getDurationValue, getBytesValue, getBinaryValue, getArrayValue, getSetValue, getVectorValue, getObjectValue, } from "./utils";
7
+ export { getValue, getValues, extractRecord, getDateTimeValue, getUUIDValue, getDecimalValue, getDurationValue, getBytesValue, getBinaryValue, getArrayValue, getSetValue, getVectorValue, getObjectValue, Field, } from "./utils";
8
+ export type { WrappedFieldValue } from "./utils";
8
9
  export type { SearchQuery, SearchResult, SearchResponse } from "./search";
9
10
  export type { Schema, FieldTypeSchema, IndexConfig, CollectionMetadata, } from "./schema";
10
11
  export type { JoinConfig } from "./join";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getObjectValue = exports.getVectorValue = exports.getSetValue = exports.getArrayValue = exports.getBinaryValue = exports.getBytesValue = exports.getDurationValue = exports.getDecimalValue = exports.getUUIDValue = exports.getDateTimeValue = exports.extractRecord = exports.getValues = exports.getValue = exports.ChatMessage = exports.Stage = exports.JoinBuilder = exports.DistanceMetric = exports.VectorIndexAlgorithm = exports.FieldTypeSchemaBuilder = exports.SchemaBuilder = exports.SearchQueryBuilder = exports.SortOrder = exports.QueryBuilder = exports.RateLimitError = exports.MergeStrategy = exports.SerializationFormat = exports.WebSocketClient = exports.EkoDBClient = void 0;
3
+ exports.Field = exports.getObjectValue = exports.getVectorValue = exports.getSetValue = exports.getArrayValue = exports.getBinaryValue = exports.getBytesValue = exports.getDurationValue = exports.getDecimalValue = exports.getUUIDValue = exports.getDateTimeValue = exports.extractRecord = exports.getValues = exports.getValue = exports.ChatMessage = exports.Stage = exports.JoinBuilder = exports.DistanceMetric = exports.VectorIndexAlgorithm = exports.FieldTypeSchemaBuilder = exports.SchemaBuilder = exports.SearchQueryBuilder = exports.SortOrder = exports.QueryBuilder = exports.RateLimitError = exports.MergeStrategy = exports.SerializationFormat = exports.WebSocketClient = exports.EkoDBClient = void 0;
4
4
  var client_1 = require("./client");
5
5
  Object.defineProperty(exports, "EkoDBClient", { enumerable: true, get: function () { return client_1.EkoDBClient; } });
6
6
  Object.defineProperty(exports, "WebSocketClient", { enumerable: true, get: function () { return client_1.WebSocketClient; } });
@@ -36,3 +36,4 @@ Object.defineProperty(exports, "getArrayValue", { enumerable: true, get: functio
36
36
  Object.defineProperty(exports, "getSetValue", { enumerable: true, get: function () { return utils_1.getSetValue; } });
37
37
  Object.defineProperty(exports, "getVectorValue", { enumerable: true, get: function () { return utils_1.getVectorValue; } });
38
38
  Object.defineProperty(exports, "getObjectValue", { enumerable: true, get: function () { return utils_1.getObjectValue; } });
39
+ Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return utils_1.Field; } });
package/dist/utils.d.ts CHANGED
@@ -87,3 +87,88 @@ export declare function getObjectValue<T = any>(field: any): T | null;
87
87
  * ```
88
88
  */
89
89
  export declare function extractRecord<T extends Record<string, any>>(record: any): T;
90
+ export interface WrappedFieldValue {
91
+ type: string;
92
+ value: unknown;
93
+ }
94
+ /**
95
+ * Field builders for creating wrapped type values to send to ekoDB.
96
+ * These are the inverse of the getValue* extraction functions.
97
+ */
98
+ export declare const Field: {
99
+ /**
100
+ * Create a UUID field value
101
+ * @param value - UUID string (e.g., "550e8400-e29b-41d4-a716-446655440000")
102
+ */
103
+ uuid: (value: string) => WrappedFieldValue;
104
+ /**
105
+ * Create a Decimal field value for precise numeric values
106
+ * @param value - Decimal as string (e.g., "99.99") to preserve precision
107
+ */
108
+ decimal: (value: string) => WrappedFieldValue;
109
+ /**
110
+ * Create a DateTime field value
111
+ * @param value - Date object or RFC3339 string
112
+ */
113
+ dateTime: (value: Date | string) => WrappedFieldValue;
114
+ /**
115
+ * Create a Duration field value
116
+ * @param milliseconds - Duration in milliseconds
117
+ */
118
+ duration: (milliseconds: number) => WrappedFieldValue;
119
+ /**
120
+ * Create a Number field value (flexible numeric type)
121
+ * @param value - Integer or float
122
+ */
123
+ number: (value: number) => WrappedFieldValue;
124
+ /**
125
+ * Create a Set field value (unique elements)
126
+ * @param values - Array of values (duplicates will be removed by server)
127
+ */
128
+ set: <T>(values: T[]) => WrappedFieldValue;
129
+ /**
130
+ * Create a Vector field value (for embeddings/similarity search)
131
+ * @param values - Array of numbers representing the vector
132
+ */
133
+ vector: (values: number[]) => WrappedFieldValue;
134
+ /**
135
+ * Create a Binary field value
136
+ * @param value - Base64 encoded string or Uint8Array
137
+ */
138
+ binary: (value: string | Uint8Array) => WrappedFieldValue;
139
+ /**
140
+ * Create a Bytes field value
141
+ * @param value - Base64 encoded string or Uint8Array
142
+ */
143
+ bytes: (value: string | Uint8Array) => WrappedFieldValue;
144
+ /**
145
+ * Create an Array field value
146
+ * @param values - Array of values
147
+ */
148
+ array: <T>(values: T[]) => WrappedFieldValue;
149
+ /**
150
+ * Create an Object field value
151
+ * @param value - Object/map of key-value pairs
152
+ */
153
+ object: (value: Record<string, unknown>) => WrappedFieldValue;
154
+ /**
155
+ * Create a String field value (explicit wrapping)
156
+ * @param value - String value
157
+ */
158
+ string: (value: string) => WrappedFieldValue;
159
+ /**
160
+ * Create an Integer field value (explicit wrapping)
161
+ * @param value - Integer value
162
+ */
163
+ integer: (value: number) => WrappedFieldValue;
164
+ /**
165
+ * Create a Float field value (explicit wrapping)
166
+ * @param value - Float value
167
+ */
168
+ float: (value: number) => WrappedFieldValue;
169
+ /**
170
+ * Create a Boolean field value (explicit wrapping)
171
+ * @param value - Boolean value
172
+ */
173
+ boolean: (value: boolean) => WrappedFieldValue;
174
+ };
package/dist/utils.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * Utility functions for working with ekoDB records
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Field = void 0;
6
7
  exports.getValue = getValue;
7
8
  exports.getValues = getValues;
8
9
  exports.getDateTimeValue = getDateTimeValue;
@@ -196,3 +197,129 @@ function extractRecord(record) {
196
197
  }
197
198
  return result;
198
199
  }
200
+ /**
201
+ * Field builders for creating wrapped type values to send to ekoDB.
202
+ * These are the inverse of the getValue* extraction functions.
203
+ */
204
+ exports.Field = {
205
+ /**
206
+ * Create a UUID field value
207
+ * @param value - UUID string (e.g., "550e8400-e29b-41d4-a716-446655440000")
208
+ */
209
+ uuid: (value) => ({
210
+ type: "UUID",
211
+ value,
212
+ }),
213
+ /**
214
+ * Create a Decimal field value for precise numeric values
215
+ * @param value - Decimal as string (e.g., "99.99") to preserve precision
216
+ */
217
+ decimal: (value) => ({
218
+ type: "Decimal",
219
+ value,
220
+ }),
221
+ /**
222
+ * Create a DateTime field value
223
+ * @param value - Date object or RFC3339 string
224
+ */
225
+ dateTime: (value) => ({
226
+ type: "DateTime",
227
+ value: value instanceof Date ? value.toISOString() : value,
228
+ }),
229
+ /**
230
+ * Create a Duration field value
231
+ * @param milliseconds - Duration in milliseconds
232
+ */
233
+ duration: (milliseconds) => ({
234
+ type: "Duration",
235
+ value: milliseconds,
236
+ }),
237
+ /**
238
+ * Create a Number field value (flexible numeric type)
239
+ * @param value - Integer or float
240
+ */
241
+ number: (value) => ({
242
+ type: "Number",
243
+ value,
244
+ }),
245
+ /**
246
+ * Create a Set field value (unique elements)
247
+ * @param values - Array of values (duplicates will be removed by server)
248
+ */
249
+ set: (values) => ({
250
+ type: "Set",
251
+ value: values,
252
+ }),
253
+ /**
254
+ * Create a Vector field value (for embeddings/similarity search)
255
+ * @param values - Array of numbers representing the vector
256
+ */
257
+ vector: (values) => ({
258
+ type: "Vector",
259
+ value: values,
260
+ }),
261
+ /**
262
+ * Create a Binary field value
263
+ * @param value - Base64 encoded string or Uint8Array
264
+ */
265
+ binary: (value) => ({
266
+ type: "Binary",
267
+ value: value instanceof Uint8Array ? btoa(String.fromCharCode(...value)) : value,
268
+ }),
269
+ /**
270
+ * Create a Bytes field value
271
+ * @param value - Base64 encoded string or Uint8Array
272
+ */
273
+ bytes: (value) => ({
274
+ type: "Bytes",
275
+ value: value instanceof Uint8Array ? btoa(String.fromCharCode(...value)) : value,
276
+ }),
277
+ /**
278
+ * Create an Array field value
279
+ * @param values - Array of values
280
+ */
281
+ array: (values) => ({
282
+ type: "Array",
283
+ value: values,
284
+ }),
285
+ /**
286
+ * Create an Object field value
287
+ * @param value - Object/map of key-value pairs
288
+ */
289
+ object: (value) => ({
290
+ type: "Object",
291
+ value,
292
+ }),
293
+ /**
294
+ * Create a String field value (explicit wrapping)
295
+ * @param value - String value
296
+ */
297
+ string: (value) => ({
298
+ type: "String",
299
+ value,
300
+ }),
301
+ /**
302
+ * Create an Integer field value (explicit wrapping)
303
+ * @param value - Integer value
304
+ */
305
+ integer: (value) => ({
306
+ type: "Integer",
307
+ value: Math.floor(value),
308
+ }),
309
+ /**
310
+ * Create a Float field value (explicit wrapping)
311
+ * @param value - Float value
312
+ */
313
+ float: (value) => ({
314
+ type: "Float",
315
+ value,
316
+ }),
317
+ /**
318
+ * Create a Boolean field value (explicit wrapping)
319
+ * @param value - Boolean value
320
+ */
321
+ boolean: (value) => ({
322
+ type: "Boolean",
323
+ value,
324
+ }),
325
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekodb/ekodb-client",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Official TypeScript/JavaScript client for ekoDB",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/client.ts CHANGED
@@ -441,6 +441,9 @@ export class EkoDBClient {
441
441
 
442
442
  /**
443
443
  * Insert a document into a collection
444
+ * @param collection - Collection name
445
+ * @param record - Document to insert
446
+ * @param ttl - Optional TTL: duration string ("1h", "30m"), seconds ("3600"), or ISO8601 timestamp
444
447
  */
445
448
  async insert(
446
449
  collection: string,
@@ -449,7 +452,7 @@ export class EkoDBClient {
449
452
  ): Promise<Record> {
450
453
  const data = { ...record };
451
454
  if (ttl) {
452
- data.ttl_duration = ttl;
455
+ data.ttl = ttl;
453
456
  }
454
457
  return this.makeRequest<Record>("POST", `/api/insert/${collection}`, data);
455
458
  }
@@ -575,13 +578,20 @@ export class EkoDBClient {
575
578
  }
576
579
 
577
580
  /**
578
- * Set a key-value pair
581
+ * Set a key-value pair with optional TTL
582
+ * @param key - The key to set
583
+ * @param value - The value to store
584
+ * @param ttl - Optional TTL in seconds
579
585
  */
580
- async kvSet(key: string, value: any): Promise<void> {
586
+ async kvSet(key: string, value: any, ttl?: number): Promise<void> {
587
+ const body: any = { value };
588
+ if (ttl !== undefined) {
589
+ body.ttl = ttl;
590
+ }
581
591
  await this.makeRequest<void>(
582
592
  "POST",
583
593
  `/api/kv/set/${encodeURIComponent(key)}`,
584
- { value },
594
+ body,
585
595
  0,
586
596
  true, // Force JSON for KV operations
587
597
  );
@@ -614,6 +624,116 @@ export class EkoDBClient {
614
624
  );
615
625
  }
616
626
 
627
+ /**
628
+ * Check if a key exists
629
+ * @param key - The key to check
630
+ * @returns true if the key exists, false otherwise
631
+ */
632
+ async kvExists(key: string): Promise<boolean> {
633
+ try {
634
+ const result = await this.kvGet(key);
635
+ return result !== null && result !== undefined;
636
+ } catch {
637
+ return false;
638
+ }
639
+ }
640
+
641
+ /**
642
+ * Query/find KV entries with pattern matching
643
+ * @param options - Query options including pattern and include_expired
644
+ * @returns Array of matching records
645
+ */
646
+ async kvFind(options?: {
647
+ pattern?: string;
648
+ include_expired?: boolean;
649
+ }): Promise<any[]> {
650
+ const result = await this.makeRequest<any[]>(
651
+ "POST",
652
+ "/api/kv/find",
653
+ options || {},
654
+ 0,
655
+ true, // Force JSON for KV operations
656
+ );
657
+ return result;
658
+ }
659
+
660
+ /**
661
+ * Alias for kvFind - query KV store with pattern
662
+ */
663
+ async kvQuery(options?: {
664
+ pattern?: string;
665
+ include_expired?: boolean;
666
+ }): Promise<any[]> {
667
+ return this.kvFind(options);
668
+ }
669
+
670
+ // ============================================================================
671
+ // Transaction Operations
672
+ // ============================================================================
673
+
674
+ /**
675
+ * Begin a new transaction
676
+ * @param isolationLevel - Transaction isolation level (default: "ReadCommitted")
677
+ * @returns Transaction ID
678
+ */
679
+ async beginTransaction(
680
+ isolationLevel: string = "ReadCommitted",
681
+ ): Promise<string> {
682
+ const result = await this.makeRequest<{ transaction_id: string }>(
683
+ "POST",
684
+ "/api/transactions",
685
+ { isolation_level: isolationLevel },
686
+ 0,
687
+ true,
688
+ );
689
+ return result.transaction_id;
690
+ }
691
+
692
+ /**
693
+ * Get transaction status
694
+ * @param transactionId - The transaction ID
695
+ * @returns Transaction status object
696
+ */
697
+ async getTransactionStatus(
698
+ transactionId: string,
699
+ ): Promise<{ state: string; operations_count: number }> {
700
+ return this.makeRequest<{ state: string; operations_count: number }>(
701
+ "GET",
702
+ `/api/transactions/${encodeURIComponent(transactionId)}`,
703
+ undefined,
704
+ 0,
705
+ true,
706
+ );
707
+ }
708
+
709
+ /**
710
+ * Commit a transaction
711
+ * @param transactionId - The transaction ID to commit
712
+ */
713
+ async commitTransaction(transactionId: string): Promise<void> {
714
+ await this.makeRequest<void>(
715
+ "POST",
716
+ `/api/transactions/${encodeURIComponent(transactionId)}/commit`,
717
+ undefined,
718
+ 0,
719
+ true,
720
+ );
721
+ }
722
+
723
+ /**
724
+ * Rollback a transaction
725
+ * @param transactionId - The transaction ID to rollback
726
+ */
727
+ async rollbackTransaction(transactionId: string): Promise<void> {
728
+ await this.makeRequest<void>(
729
+ "POST",
730
+ `/api/transactions/${encodeURIComponent(transactionId)}/rollback`,
731
+ undefined,
732
+ 0,
733
+ true,
734
+ );
735
+ }
736
+
617
737
  /**
618
738
  * List all collections
619
739
  */
package/src/functions.ts CHANGED
@@ -187,6 +187,31 @@ export type FunctionStageConfig =
187
187
  | {
188
188
  type: "ReleaseSavepoint";
189
189
  name: string;
190
+ }
191
+ | {
192
+ type: "KvGet";
193
+ key: string;
194
+ output_field?: string;
195
+ }
196
+ | {
197
+ type: "KvSet";
198
+ key: string;
199
+ value: any;
200
+ ttl?: number;
201
+ }
202
+ | {
203
+ type: "KvDelete";
204
+ key: string;
205
+ }
206
+ | {
207
+ type: "KvExists";
208
+ key: string;
209
+ output_field?: string;
210
+ }
211
+ | {
212
+ type: "KvQuery";
213
+ pattern?: string;
214
+ include_expired?: boolean;
190
215
  };
191
216
 
192
217
  export interface ChatMessage {
@@ -572,4 +597,38 @@ export const Stage = {
572
597
  type: "ReleaseSavepoint",
573
598
  name,
574
599
  }),
600
+
601
+ // KV Store operations - faster than collection lookups for simple key-value data
602
+ kvGet: (key: string, output_field?: string): FunctionStageConfig => ({
603
+ type: "KvGet",
604
+ key,
605
+ output_field,
606
+ }),
607
+
608
+ kvSet: (key: string, value: any, ttl?: number): FunctionStageConfig => ({
609
+ type: "KvSet",
610
+ key,
611
+ value,
612
+ ttl,
613
+ }),
614
+
615
+ kvDelete: (key: string): FunctionStageConfig => ({
616
+ type: "KvDelete",
617
+ key,
618
+ }),
619
+
620
+ kvExists: (key: string, output_field?: string): FunctionStageConfig => ({
621
+ type: "KvExists",
622
+ key,
623
+ output_field,
624
+ }),
625
+
626
+ kvQuery: (
627
+ pattern?: string,
628
+ include_expired?: boolean,
629
+ ): FunctionStageConfig => ({
630
+ type: "KvQuery",
631
+ pattern,
632
+ include_expired,
633
+ }),
575
634
  };
package/src/index.ts CHANGED
@@ -29,7 +29,9 @@ export {
29
29
  getSetValue,
30
30
  getVectorValue,
31
31
  getObjectValue,
32
+ Field,
32
33
  } from "./utils";
34
+ export type { WrappedFieldValue } from "./utils";
33
35
  export type { SearchQuery, SearchResult, SearchResponse } from "./search";
34
36
  export type {
35
37
  Schema,
package/src/utils.ts CHANGED
@@ -191,3 +191,165 @@ export function extractRecord<T extends Record<string, any>>(record: any): T {
191
191
  }
192
192
  return result as T;
193
193
  }
194
+
195
+ // ============================================================================
196
+ // Wrapped Type Builders
197
+ // ============================================================================
198
+ // These functions create wrapped type objects for sending to ekoDB.
199
+ // Use these when inserting/updating records with special field types.
200
+ //
201
+ // Example:
202
+ // await client.insert("orders", {
203
+ // id: Field.uuid("550e8400-e29b-41d4-a716-446655440000"),
204
+ // total: Field.decimal("99.99"),
205
+ // created_at: Field.dateTime(new Date()),
206
+ // tags: Field.set(["sale", "featured"]),
207
+ // });
208
+
209
+ export interface WrappedFieldValue {
210
+ type: string;
211
+ value: unknown;
212
+ }
213
+
214
+ /**
215
+ * Field builders for creating wrapped type values to send to ekoDB.
216
+ * These are the inverse of the getValue* extraction functions.
217
+ */
218
+ export const Field = {
219
+ /**
220
+ * Create a UUID field value
221
+ * @param value - UUID string (e.g., "550e8400-e29b-41d4-a716-446655440000")
222
+ */
223
+ uuid: (value: string): WrappedFieldValue => ({
224
+ type: "UUID",
225
+ value,
226
+ }),
227
+
228
+ /**
229
+ * Create a Decimal field value for precise numeric values
230
+ * @param value - Decimal as string (e.g., "99.99") to preserve precision
231
+ */
232
+ decimal: (value: string): WrappedFieldValue => ({
233
+ type: "Decimal",
234
+ value,
235
+ }),
236
+
237
+ /**
238
+ * Create a DateTime field value
239
+ * @param value - Date object or RFC3339 string
240
+ */
241
+ dateTime: (value: Date | string): WrappedFieldValue => ({
242
+ type: "DateTime",
243
+ value: value instanceof Date ? value.toISOString() : value,
244
+ }),
245
+
246
+ /**
247
+ * Create a Duration field value
248
+ * @param milliseconds - Duration in milliseconds
249
+ */
250
+ duration: (milliseconds: number): WrappedFieldValue => ({
251
+ type: "Duration",
252
+ value: milliseconds,
253
+ }),
254
+
255
+ /**
256
+ * Create a Number field value (flexible numeric type)
257
+ * @param value - Integer or float
258
+ */
259
+ number: (value: number): WrappedFieldValue => ({
260
+ type: "Number",
261
+ value,
262
+ }),
263
+
264
+ /**
265
+ * Create a Set field value (unique elements)
266
+ * @param values - Array of values (duplicates will be removed by server)
267
+ */
268
+ set: <T>(values: T[]): WrappedFieldValue => ({
269
+ type: "Set",
270
+ value: values,
271
+ }),
272
+
273
+ /**
274
+ * Create a Vector field value (for embeddings/similarity search)
275
+ * @param values - Array of numbers representing the vector
276
+ */
277
+ vector: (values: number[]): WrappedFieldValue => ({
278
+ type: "Vector",
279
+ value: values,
280
+ }),
281
+
282
+ /**
283
+ * Create a Binary field value
284
+ * @param value - Base64 encoded string or Uint8Array
285
+ */
286
+ binary: (value: string | Uint8Array): WrappedFieldValue => ({
287
+ type: "Binary",
288
+ value:
289
+ value instanceof Uint8Array ? btoa(String.fromCharCode(...value)) : value,
290
+ }),
291
+
292
+ /**
293
+ * Create a Bytes field value
294
+ * @param value - Base64 encoded string or Uint8Array
295
+ */
296
+ bytes: (value: string | Uint8Array): WrappedFieldValue => ({
297
+ type: "Bytes",
298
+ value:
299
+ value instanceof Uint8Array ? btoa(String.fromCharCode(...value)) : value,
300
+ }),
301
+
302
+ /**
303
+ * Create an Array field value
304
+ * @param values - Array of values
305
+ */
306
+ array: <T>(values: T[]): WrappedFieldValue => ({
307
+ type: "Array",
308
+ value: values,
309
+ }),
310
+
311
+ /**
312
+ * Create an Object field value
313
+ * @param value - Object/map of key-value pairs
314
+ */
315
+ object: (value: Record<string, unknown>): WrappedFieldValue => ({
316
+ type: "Object",
317
+ value,
318
+ }),
319
+
320
+ /**
321
+ * Create a String field value (explicit wrapping)
322
+ * @param value - String value
323
+ */
324
+ string: (value: string): WrappedFieldValue => ({
325
+ type: "String",
326
+ value,
327
+ }),
328
+
329
+ /**
330
+ * Create an Integer field value (explicit wrapping)
331
+ * @param value - Integer value
332
+ */
333
+ integer: (value: number): WrappedFieldValue => ({
334
+ type: "Integer",
335
+ value: Math.floor(value),
336
+ }),
337
+
338
+ /**
339
+ * Create a Float field value (explicit wrapping)
340
+ * @param value - Float value
341
+ */
342
+ float: (value: number): WrappedFieldValue => ({
343
+ type: "Float",
344
+ value,
345
+ }),
346
+
347
+ /**
348
+ * Create a Boolean field value (explicit wrapping)
349
+ * @param value - Boolean value
350
+ */
351
+ boolean: (value: boolean): WrappedFieldValue => ({
352
+ type: "Boolean",
353
+ value,
354
+ }),
355
+ };