@wiscale/velesdb-sdk 1.6.0 → 1.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/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB) -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
4
4
 
5
- **v1.6.0** | Node.js >= 18 | Browser (WASM) | MIT License
5
+ **v1.7.0** | Node.js >= 18 | Browser (WASM) | MIT License
6
6
 
7
- ## What's New in v1.6.0
7
+ ## What's New in v1.7.0
8
8
 
9
9
  - **Agent Memory API** -- semantic, episodic, and procedural memory for AI agents (REST only)
10
10
  - **Graph collections** -- dedicated `createGraphCollection()` for knowledge graphs (REST only)
package/dist/index.d.mts CHANGED
@@ -98,13 +98,13 @@ interface PqTrainOptions {
98
98
  opq?: boolean;
99
99
  }
100
100
  /** Fusion strategy for multi-query search */
101
- type FusionStrategy$1 = 'rrf' | 'average' | 'maximum' | 'weighted';
101
+ type FusionStrategy = 'rrf' | 'average' | 'maximum' | 'weighted';
102
102
  /** Multi-query search options */
103
103
  interface MultiQuerySearchOptions {
104
104
  /** Number of results to return (default: 10) */
105
105
  k?: number;
106
106
  /** Fusion strategy (default: 'rrf') */
107
- fusion?: FusionStrategy$1;
107
+ fusion?: FusionStrategy;
108
108
  /** Fusion parameters */
109
109
  fusionParams?: {
110
110
  /** RRF k parameter (default: 60) */
@@ -143,19 +143,12 @@ interface GraphEdge {
143
143
  /** Edge properties */
144
144
  properties?: Record<string, unknown>;
145
145
  }
146
- /** Request to add an edge to the graph */
147
- interface AddEdgeRequest {
148
- /** Unique edge ID */
149
- id: number;
150
- /** Source node ID */
151
- source: number;
152
- /** Target node ID */
153
- target: number;
154
- /** Edge label (relationship type) */
155
- label: string;
156
- /** Edge properties (optional) */
157
- properties?: Record<string, unknown>;
158
- }
146
+ /**
147
+ * Request to add an edge to the graph.
148
+ * Structurally identical to GraphEdge — kept as a named alias for
149
+ * semantic clarity (input vs stored model).
150
+ */
151
+ type AddEdgeRequest = GraphEdge;
159
152
  /** Response containing edges */
160
153
  interface EdgesResponse {
161
154
  /** List of edges */
@@ -740,6 +733,15 @@ declare class VelesDB {
740
733
  * ```
741
734
  */
742
735
  query(collection: string, queryString: string, params?: Record<string, unknown>, options?: QueryOptions): Promise<QueryApiResponse>;
736
+ /**
737
+ * Explain the execution plan for a VelesQL query without running it
738
+ *
739
+ * @param queryString - VelesQL query string to explain
740
+ * @param params - Optional query parameters (vectors, scalars)
741
+ * @returns Explain response with the query execution plan
742
+ */
743
+ queryExplain(queryString: string, params?: Record<string, unknown>): Promise<ExplainResponse>;
744
+ collectionSanity(collection: string): Promise<CollectionSanityResponse>;
743
745
  /**
744
746
  * Multi-query fusion search combining results from multiple query vectors
745
747
  *
@@ -767,8 +769,6 @@ declare class VelesDB {
767
769
  * });
768
770
  * ```
769
771
  */
770
- queryExplain(queryString: string, params?: Record<string, unknown>): Promise<ExplainResponse>;
771
- collectionSanity(collection: string): Promise<CollectionSanityResponse>;
772
772
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
773
773
  /**
774
774
  * Train Product Quantization on a collection
@@ -1154,10 +1154,9 @@ declare class RestBackend implements IVelesDBBackend {
1154
1154
  *
1155
1155
  * @packageDocumentation
1156
1156
  */
1157
+
1157
1158
  /** Direction for relationship traversal */
1158
1159
  type RelDirection = 'outgoing' | 'incoming' | 'both';
1159
- /** Fusion strategy for hybrid queries */
1160
- type FusionStrategy = 'rrf' | 'average' | 'maximum' | 'weighted';
1161
1160
  /** Options for relationship patterns */
1162
1161
  interface RelOptions {
1163
1162
  direction?: RelDirection;
@@ -1325,4 +1324,4 @@ declare class VelesQLBuilder {
1325
1324
  */
1326
1325
  declare function velesql(): VelesQLBuilder;
1327
1326
 
1328
- export { type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregationQueryResponse, type BackendType, BackpressureError, type Collection, type CollectionConfig, type CollectionConfigResponse, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, ConnectionError, type CreateIndexOptions, type DegreeResponse, type DistanceMetric, type EdgesResponse, type EpisodicEvent, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type FusionOptions, type FusionStrategy$1 as FusionStrategy, type GetEdgesOptions, type GraphCollectionConfig, type GraphEdge, type GraphSchemaMode, type HnswParams, type IVelesDBBackend, type IndexInfo, type IndexType, type MultiQuerySearchOptions, type NearVectorOptions, NotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, type RelDirection, type RelOptions, RestBackend, type RestPointId, type SearchOptions, type SearchResult, type SemanticEntry, type SparseVector, type StorageMode, type TraversalResultItem, type TraversalStats, type TraverseRequest, type TraverseResponse, ValidationError, type VectorDocument, VelesDB, type VelesDBConfig, VelesDBError, VelesQLBuilder, WasmBackend, velesql };
1327
+ export { type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregationQueryResponse, type BackendType, BackpressureError, type Collection, type CollectionConfig, type CollectionConfigResponse, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, ConnectionError, type CreateIndexOptions, type DegreeResponse, type DistanceMetric, type EdgesResponse, type EpisodicEvent, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GraphCollectionConfig, type GraphEdge, type GraphSchemaMode, type HnswParams, type IVelesDBBackend, type IndexInfo, type IndexType, type MultiQuerySearchOptions, type NearVectorOptions, NotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, type RelDirection, type RelOptions, RestBackend, type RestPointId, type SearchOptions, type SearchResult, type SemanticEntry, type SparseVector, type StorageMode, type TraversalResultItem, type TraversalStats, type TraverseRequest, type TraverseResponse, ValidationError, type VectorDocument, VelesDB, type VelesDBConfig, VelesDBError, VelesQLBuilder, WasmBackend, velesql };
package/dist/index.d.ts CHANGED
@@ -98,13 +98,13 @@ interface PqTrainOptions {
98
98
  opq?: boolean;
99
99
  }
100
100
  /** Fusion strategy for multi-query search */
101
- type FusionStrategy$1 = 'rrf' | 'average' | 'maximum' | 'weighted';
101
+ type FusionStrategy = 'rrf' | 'average' | 'maximum' | 'weighted';
102
102
  /** Multi-query search options */
103
103
  interface MultiQuerySearchOptions {
104
104
  /** Number of results to return (default: 10) */
105
105
  k?: number;
106
106
  /** Fusion strategy (default: 'rrf') */
107
- fusion?: FusionStrategy$1;
107
+ fusion?: FusionStrategy;
108
108
  /** Fusion parameters */
109
109
  fusionParams?: {
110
110
  /** RRF k parameter (default: 60) */
@@ -143,19 +143,12 @@ interface GraphEdge {
143
143
  /** Edge properties */
144
144
  properties?: Record<string, unknown>;
145
145
  }
146
- /** Request to add an edge to the graph */
147
- interface AddEdgeRequest {
148
- /** Unique edge ID */
149
- id: number;
150
- /** Source node ID */
151
- source: number;
152
- /** Target node ID */
153
- target: number;
154
- /** Edge label (relationship type) */
155
- label: string;
156
- /** Edge properties (optional) */
157
- properties?: Record<string, unknown>;
158
- }
146
+ /**
147
+ * Request to add an edge to the graph.
148
+ * Structurally identical to GraphEdge — kept as a named alias for
149
+ * semantic clarity (input vs stored model).
150
+ */
151
+ type AddEdgeRequest = GraphEdge;
159
152
  /** Response containing edges */
160
153
  interface EdgesResponse {
161
154
  /** List of edges */
@@ -740,6 +733,15 @@ declare class VelesDB {
740
733
  * ```
741
734
  */
742
735
  query(collection: string, queryString: string, params?: Record<string, unknown>, options?: QueryOptions): Promise<QueryApiResponse>;
736
+ /**
737
+ * Explain the execution plan for a VelesQL query without running it
738
+ *
739
+ * @param queryString - VelesQL query string to explain
740
+ * @param params - Optional query parameters (vectors, scalars)
741
+ * @returns Explain response with the query execution plan
742
+ */
743
+ queryExplain(queryString: string, params?: Record<string, unknown>): Promise<ExplainResponse>;
744
+ collectionSanity(collection: string): Promise<CollectionSanityResponse>;
743
745
  /**
744
746
  * Multi-query fusion search combining results from multiple query vectors
745
747
  *
@@ -767,8 +769,6 @@ declare class VelesDB {
767
769
  * });
768
770
  * ```
769
771
  */
770
- queryExplain(queryString: string, params?: Record<string, unknown>): Promise<ExplainResponse>;
771
- collectionSanity(collection: string): Promise<CollectionSanityResponse>;
772
772
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
773
773
  /**
774
774
  * Train Product Quantization on a collection
@@ -1154,10 +1154,9 @@ declare class RestBackend implements IVelesDBBackend {
1154
1154
  *
1155
1155
  * @packageDocumentation
1156
1156
  */
1157
+
1157
1158
  /** Direction for relationship traversal */
1158
1159
  type RelDirection = 'outgoing' | 'incoming' | 'both';
1159
- /** Fusion strategy for hybrid queries */
1160
- type FusionStrategy = 'rrf' | 'average' | 'maximum' | 'weighted';
1161
1160
  /** Options for relationship patterns */
1162
1161
  interface RelOptions {
1163
1162
  direction?: RelDirection;
@@ -1325,4 +1324,4 @@ declare class VelesQLBuilder {
1325
1324
  */
1326
1325
  declare function velesql(): VelesQLBuilder;
1327
1326
 
1328
- export { type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregationQueryResponse, type BackendType, BackpressureError, type Collection, type CollectionConfig, type CollectionConfigResponse, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, ConnectionError, type CreateIndexOptions, type DegreeResponse, type DistanceMetric, type EdgesResponse, type EpisodicEvent, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type FusionOptions, type FusionStrategy$1 as FusionStrategy, type GetEdgesOptions, type GraphCollectionConfig, type GraphEdge, type GraphSchemaMode, type HnswParams, type IVelesDBBackend, type IndexInfo, type IndexType, type MultiQuerySearchOptions, type NearVectorOptions, NotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, type RelDirection, type RelOptions, RestBackend, type RestPointId, type SearchOptions, type SearchResult, type SemanticEntry, type SparseVector, type StorageMode, type TraversalResultItem, type TraversalStats, type TraverseRequest, type TraverseResponse, ValidationError, type VectorDocument, VelesDB, type VelesDBConfig, VelesDBError, VelesQLBuilder, WasmBackend, velesql };
1327
+ export { type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregationQueryResponse, type BackendType, BackpressureError, type Collection, type CollectionConfig, type CollectionConfigResponse, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, ConnectionError, type CreateIndexOptions, type DegreeResponse, type DistanceMetric, type EdgesResponse, type EpisodicEvent, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GraphCollectionConfig, type GraphEdge, type GraphSchemaMode, type HnswParams, type IVelesDBBackend, type IndexInfo, type IndexType, type MultiQuerySearchOptions, type NearVectorOptions, NotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, type RelDirection, type RelOptions, RestBackend, type RestPointId, type SearchOptions, type SearchResult, type SemanticEntry, type SparseVector, type StorageMode, type TraversalResultItem, type TraversalStats, type TraverseRequest, type TraverseResponse, ValidationError, type VectorDocument, VelesDB, type VelesDBConfig, VelesDBError, VelesQLBuilder, WasmBackend, velesql };
package/dist/index.js CHANGED
@@ -1659,6 +1659,24 @@ var AgentMemoryClient = class {
1659
1659
  };
1660
1660
 
1661
1661
  // src/client.ts
1662
+ function requireNonEmptyString(value, label) {
1663
+ if (!value || typeof value !== "string") {
1664
+ throw new ValidationError(`${label} must be a non-empty string`);
1665
+ }
1666
+ }
1667
+ function requireVector(value, label) {
1668
+ if (!value || !Array.isArray(value) && !(value instanceof Float32Array)) {
1669
+ throw new ValidationError(`${label} must be an array or Float32Array`);
1670
+ }
1671
+ }
1672
+ function validateDocsBatch(docs, validateDoc) {
1673
+ if (!Array.isArray(docs)) {
1674
+ throw new ValidationError("Documents must be an array");
1675
+ }
1676
+ for (const doc of docs) {
1677
+ validateDoc(doc);
1678
+ }
1679
+ }
1662
1680
  var VelesDB = class {
1663
1681
  /**
1664
1682
  * Create a new VelesDB client
@@ -1723,9 +1741,7 @@ var VelesDB = class {
1723
1741
  */
1724
1742
  async createCollection(name, config) {
1725
1743
  this.ensureInitialized();
1726
- if (!name || typeof name !== "string") {
1727
- throw new ValidationError("Collection name must be a non-empty string");
1728
- }
1744
+ requireNonEmptyString(name, "Collection name");
1729
1745
  const isMetadataOnly = config.collectionType === "metadata_only";
1730
1746
  if (!isMetadataOnly && (!config.dimension || config.dimension <= 0)) {
1731
1747
  throw new ValidationError("Dimension must be a positive integer for vector collections");
@@ -1747,9 +1763,7 @@ var VelesDB = class {
1747
1763
  */
1748
1764
  async createMetadataCollection(name) {
1749
1765
  this.ensureInitialized();
1750
- if (!name || typeof name !== "string") {
1751
- throw new ValidationError("Collection name must be a non-empty string");
1752
- }
1766
+ requireNonEmptyString(name, "Collection name");
1753
1767
  await this.backend.createCollection(name, { collectionType: "metadata_only" });
1754
1768
  }
1755
1769
  /**
@@ -1799,29 +1813,15 @@ var VelesDB = class {
1799
1813
  */
1800
1814
  async insertBatch(collection, docs) {
1801
1815
  this.ensureInitialized();
1802
- if (!Array.isArray(docs)) {
1803
- throw new ValidationError("Documents must be an array");
1804
- }
1805
- for (const doc of docs) {
1806
- this.validateDocument(doc);
1807
- }
1816
+ validateDocsBatch(docs, (doc) => this.validateDocument(doc));
1808
1817
  await this.backend.insertBatch(collection, docs);
1809
1818
  }
1810
1819
  validateDocument(doc) {
1811
1820
  if (doc.id === void 0 || doc.id === null) {
1812
1821
  throw new ValidationError("Document ID is required");
1813
1822
  }
1814
- if (!doc.vector) {
1815
- throw new ValidationError("Document vector is required");
1816
- }
1817
- if (!Array.isArray(doc.vector) && !(doc.vector instanceof Float32Array)) {
1818
- throw new ValidationError("Vector must be an array or Float32Array");
1819
- }
1820
- if (this.config.backend === "rest" && (typeof doc.id !== "number" || !Number.isInteger(doc.id) || doc.id < 0 || doc.id > Number.MAX_SAFE_INTEGER)) {
1821
- throw new ValidationError(
1822
- `REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
1823
- );
1824
- }
1823
+ requireVector(doc.vector, "Vector");
1824
+ this.validateRestPointId(doc.id);
1825
1825
  }
1826
1826
  validateRestPointId(id) {
1827
1827
  if (this.config.backend === "rest" && (typeof id !== "number" || !Number.isInteger(id) || id < 0 || id > Number.MAX_SAFE_INTEGER)) {
@@ -1840,9 +1840,7 @@ var VelesDB = class {
1840
1840
  */
1841
1841
  async search(collection, query2, options) {
1842
1842
  this.ensureInitialized();
1843
- if (!query2 || !Array.isArray(query2) && !(query2 instanceof Float32Array)) {
1844
- throw new ValidationError("Query must be an array or Float32Array");
1845
- }
1843
+ requireVector(query2, "Query");
1846
1844
  return this.backend.search(collection, query2, options);
1847
1845
  }
1848
1846
  /**
@@ -1858,9 +1856,7 @@ var VelesDB = class {
1858
1856
  throw new ValidationError("Searches must be an array");
1859
1857
  }
1860
1858
  for (const s of searches) {
1861
- if (!s.vector || !Array.isArray(s.vector) && !(s.vector instanceof Float32Array)) {
1862
- throw new ValidationError("Each search must have a vector (array or Float32Array)");
1863
- }
1859
+ requireVector(s.vector, "Each search vector");
1864
1860
  }
1865
1861
  return this.backend.searchBatch(collection, searches);
1866
1862
  }
@@ -1898,9 +1894,7 @@ var VelesDB = class {
1898
1894
  */
1899
1895
  async textSearch(collection, query2, options) {
1900
1896
  this.ensureInitialized();
1901
- if (!query2 || typeof query2 !== "string") {
1902
- throw new ValidationError("Query must be a non-empty string");
1903
- }
1897
+ requireNonEmptyString(query2, "Query");
1904
1898
  return this.backend.textSearch(collection, query2, options);
1905
1899
  }
1906
1900
  /**
@@ -1914,12 +1908,8 @@ var VelesDB = class {
1914
1908
  */
1915
1909
  async hybridSearch(collection, vector, textQuery, options) {
1916
1910
  this.ensureInitialized();
1917
- if (!vector || !Array.isArray(vector) && !(vector instanceof Float32Array)) {
1918
- throw new ValidationError("Vector must be an array or Float32Array");
1919
- }
1920
- if (!textQuery || typeof textQuery !== "string") {
1921
- throw new ValidationError("Text query must be a non-empty string");
1922
- }
1911
+ requireVector(vector, "Vector");
1912
+ requireNonEmptyString(textQuery, "Text query");
1923
1913
  return this.backend.hybridSearch(collection, vector, textQuery, options);
1924
1914
  }
1925
1915
  /**
@@ -1946,24 +1936,37 @@ var VelesDB = class {
1946
1936
  */
1947
1937
  async query(collection, queryString, params, options) {
1948
1938
  this.ensureInitialized();
1949
- if (!collection || typeof collection !== "string") {
1950
- throw new ValidationError("Collection name must be a non-empty string");
1951
- }
1952
- if (!queryString || typeof queryString !== "string") {
1953
- throw new ValidationError("Query string must be a non-empty string");
1954
- }
1939
+ requireNonEmptyString(collection, "Collection name");
1940
+ requireNonEmptyString(queryString, "Query string");
1955
1941
  return this.backend.query(collection, queryString, params, options);
1956
1942
  }
1943
+ /**
1944
+ * Explain the execution plan for a VelesQL query without running it
1945
+ *
1946
+ * @param queryString - VelesQL query string to explain
1947
+ * @param params - Optional query parameters (vectors, scalars)
1948
+ * @returns Explain response with the query execution plan
1949
+ */
1950
+ async queryExplain(queryString, params) {
1951
+ this.ensureInitialized();
1952
+ requireNonEmptyString(queryString, "Query string");
1953
+ return this.backend.queryExplain(queryString, params);
1954
+ }
1955
+ async collectionSanity(collection) {
1956
+ this.ensureInitialized();
1957
+ requireNonEmptyString(collection, "Collection name");
1958
+ return this.backend.collectionSanity(collection);
1959
+ }
1957
1960
  /**
1958
1961
  * Multi-query fusion search combining results from multiple query vectors
1959
- *
1962
+ *
1960
1963
  * Ideal for RAG pipelines using Multiple Query Generation (MQG).
1961
- *
1964
+ *
1962
1965
  * @param collection - Collection name
1963
1966
  * @param vectors - Array of query vectors
1964
1967
  * @param options - Search options (k, fusion strategy, fusionParams, filter)
1965
1968
  * @returns Fused search results
1966
- *
1969
+ *
1967
1970
  * @example
1968
1971
  * ```typescript
1969
1972
  * // RRF fusion (default)
@@ -1972,7 +1975,7 @@ var VelesDB = class {
1972
1975
  * fusion: 'rrf',
1973
1976
  * fusionParams: { k: 60 }
1974
1977
  * });
1975
- *
1978
+ *
1976
1979
  * // Weighted fusion
1977
1980
  * const results = await db.multiQuerySearch('docs', [emb1, emb2], {
1978
1981
  * k: 10,
@@ -1981,29 +1984,13 @@ var VelesDB = class {
1981
1984
  * });
1982
1985
  * ```
1983
1986
  */
1984
- async queryExplain(queryString, params) {
1985
- this.ensureInitialized();
1986
- if (!queryString || typeof queryString !== "string") {
1987
- throw new ValidationError("Query string must be a non-empty string");
1988
- }
1989
- return this.backend.queryExplain(queryString, params);
1990
- }
1991
- async collectionSanity(collection) {
1992
- this.ensureInitialized();
1993
- if (!collection || typeof collection !== "string") {
1994
- throw new ValidationError("Collection name must be a non-empty string");
1995
- }
1996
- return this.backend.collectionSanity(collection);
1997
- }
1998
1987
  async multiQuerySearch(collection, vectors, options) {
1999
1988
  this.ensureInitialized();
2000
1989
  if (!Array.isArray(vectors) || vectors.length === 0) {
2001
1990
  throw new ValidationError("Vectors must be a non-empty array");
2002
1991
  }
2003
1992
  for (const v of vectors) {
2004
- if (!Array.isArray(v) && !(v instanceof Float32Array)) {
2005
- throw new ValidationError("Each vector must be an array or Float32Array");
2006
- }
1993
+ requireVector(v, "Each vector");
2007
1994
  }
2008
1995
  return this.backend.multiQuerySearch(collection, vectors, options);
2009
1996
  }
@@ -2029,12 +2016,7 @@ var VelesDB = class {
2029
2016
  */
2030
2017
  async streamInsert(collection, docs) {
2031
2018
  this.ensureInitialized();
2032
- if (!Array.isArray(docs)) {
2033
- throw new ValidationError("Documents must be an array");
2034
- }
2035
- for (const doc of docs) {
2036
- this.validateDocument(doc);
2037
- }
2019
+ validateDocsBatch(docs, (doc) => this.validateDocument(doc));
2038
2020
  await this.backend.streamInsert(collection, docs);
2039
2021
  }
2040
2022
  /**
@@ -2244,9 +2226,7 @@ var VelesDB = class {
2244
2226
  */
2245
2227
  async createGraphCollection(name, config) {
2246
2228
  this.ensureInitialized();
2247
- if (!name || typeof name !== "string") {
2248
- throw new ValidationError("Collection name must be a non-empty string");
2249
- }
2229
+ requireNonEmptyString(name, "Collection name");
2250
2230
  await this.backend.createGraphCollection(name, config);
2251
2231
  }
2252
2232
  /**
package/dist/index.mjs CHANGED
@@ -1613,6 +1613,24 @@ var AgentMemoryClient = class {
1613
1613
  };
1614
1614
 
1615
1615
  // src/client.ts
1616
+ function requireNonEmptyString(value, label) {
1617
+ if (!value || typeof value !== "string") {
1618
+ throw new ValidationError(`${label} must be a non-empty string`);
1619
+ }
1620
+ }
1621
+ function requireVector(value, label) {
1622
+ if (!value || !Array.isArray(value) && !(value instanceof Float32Array)) {
1623
+ throw new ValidationError(`${label} must be an array or Float32Array`);
1624
+ }
1625
+ }
1626
+ function validateDocsBatch(docs, validateDoc) {
1627
+ if (!Array.isArray(docs)) {
1628
+ throw new ValidationError("Documents must be an array");
1629
+ }
1630
+ for (const doc of docs) {
1631
+ validateDoc(doc);
1632
+ }
1633
+ }
1616
1634
  var VelesDB = class {
1617
1635
  /**
1618
1636
  * Create a new VelesDB client
@@ -1677,9 +1695,7 @@ var VelesDB = class {
1677
1695
  */
1678
1696
  async createCollection(name, config) {
1679
1697
  this.ensureInitialized();
1680
- if (!name || typeof name !== "string") {
1681
- throw new ValidationError("Collection name must be a non-empty string");
1682
- }
1698
+ requireNonEmptyString(name, "Collection name");
1683
1699
  const isMetadataOnly = config.collectionType === "metadata_only";
1684
1700
  if (!isMetadataOnly && (!config.dimension || config.dimension <= 0)) {
1685
1701
  throw new ValidationError("Dimension must be a positive integer for vector collections");
@@ -1701,9 +1717,7 @@ var VelesDB = class {
1701
1717
  */
1702
1718
  async createMetadataCollection(name) {
1703
1719
  this.ensureInitialized();
1704
- if (!name || typeof name !== "string") {
1705
- throw new ValidationError("Collection name must be a non-empty string");
1706
- }
1720
+ requireNonEmptyString(name, "Collection name");
1707
1721
  await this.backend.createCollection(name, { collectionType: "metadata_only" });
1708
1722
  }
1709
1723
  /**
@@ -1753,29 +1767,15 @@ var VelesDB = class {
1753
1767
  */
1754
1768
  async insertBatch(collection, docs) {
1755
1769
  this.ensureInitialized();
1756
- if (!Array.isArray(docs)) {
1757
- throw new ValidationError("Documents must be an array");
1758
- }
1759
- for (const doc of docs) {
1760
- this.validateDocument(doc);
1761
- }
1770
+ validateDocsBatch(docs, (doc) => this.validateDocument(doc));
1762
1771
  await this.backend.insertBatch(collection, docs);
1763
1772
  }
1764
1773
  validateDocument(doc) {
1765
1774
  if (doc.id === void 0 || doc.id === null) {
1766
1775
  throw new ValidationError("Document ID is required");
1767
1776
  }
1768
- if (!doc.vector) {
1769
- throw new ValidationError("Document vector is required");
1770
- }
1771
- if (!Array.isArray(doc.vector) && !(doc.vector instanceof Float32Array)) {
1772
- throw new ValidationError("Vector must be an array or Float32Array");
1773
- }
1774
- if (this.config.backend === "rest" && (typeof doc.id !== "number" || !Number.isInteger(doc.id) || doc.id < 0 || doc.id > Number.MAX_SAFE_INTEGER)) {
1775
- throw new ValidationError(
1776
- `REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
1777
- );
1778
- }
1777
+ requireVector(doc.vector, "Vector");
1778
+ this.validateRestPointId(doc.id);
1779
1779
  }
1780
1780
  validateRestPointId(id) {
1781
1781
  if (this.config.backend === "rest" && (typeof id !== "number" || !Number.isInteger(id) || id < 0 || id > Number.MAX_SAFE_INTEGER)) {
@@ -1794,9 +1794,7 @@ var VelesDB = class {
1794
1794
  */
1795
1795
  async search(collection, query2, options) {
1796
1796
  this.ensureInitialized();
1797
- if (!query2 || !Array.isArray(query2) && !(query2 instanceof Float32Array)) {
1798
- throw new ValidationError("Query must be an array or Float32Array");
1799
- }
1797
+ requireVector(query2, "Query");
1800
1798
  return this.backend.search(collection, query2, options);
1801
1799
  }
1802
1800
  /**
@@ -1812,9 +1810,7 @@ var VelesDB = class {
1812
1810
  throw new ValidationError("Searches must be an array");
1813
1811
  }
1814
1812
  for (const s of searches) {
1815
- if (!s.vector || !Array.isArray(s.vector) && !(s.vector instanceof Float32Array)) {
1816
- throw new ValidationError("Each search must have a vector (array or Float32Array)");
1817
- }
1813
+ requireVector(s.vector, "Each search vector");
1818
1814
  }
1819
1815
  return this.backend.searchBatch(collection, searches);
1820
1816
  }
@@ -1852,9 +1848,7 @@ var VelesDB = class {
1852
1848
  */
1853
1849
  async textSearch(collection, query2, options) {
1854
1850
  this.ensureInitialized();
1855
- if (!query2 || typeof query2 !== "string") {
1856
- throw new ValidationError("Query must be a non-empty string");
1857
- }
1851
+ requireNonEmptyString(query2, "Query");
1858
1852
  return this.backend.textSearch(collection, query2, options);
1859
1853
  }
1860
1854
  /**
@@ -1868,12 +1862,8 @@ var VelesDB = class {
1868
1862
  */
1869
1863
  async hybridSearch(collection, vector, textQuery, options) {
1870
1864
  this.ensureInitialized();
1871
- if (!vector || !Array.isArray(vector) && !(vector instanceof Float32Array)) {
1872
- throw new ValidationError("Vector must be an array or Float32Array");
1873
- }
1874
- if (!textQuery || typeof textQuery !== "string") {
1875
- throw new ValidationError("Text query must be a non-empty string");
1876
- }
1865
+ requireVector(vector, "Vector");
1866
+ requireNonEmptyString(textQuery, "Text query");
1877
1867
  return this.backend.hybridSearch(collection, vector, textQuery, options);
1878
1868
  }
1879
1869
  /**
@@ -1900,24 +1890,37 @@ var VelesDB = class {
1900
1890
  */
1901
1891
  async query(collection, queryString, params, options) {
1902
1892
  this.ensureInitialized();
1903
- if (!collection || typeof collection !== "string") {
1904
- throw new ValidationError("Collection name must be a non-empty string");
1905
- }
1906
- if (!queryString || typeof queryString !== "string") {
1907
- throw new ValidationError("Query string must be a non-empty string");
1908
- }
1893
+ requireNonEmptyString(collection, "Collection name");
1894
+ requireNonEmptyString(queryString, "Query string");
1909
1895
  return this.backend.query(collection, queryString, params, options);
1910
1896
  }
1897
+ /**
1898
+ * Explain the execution plan for a VelesQL query without running it
1899
+ *
1900
+ * @param queryString - VelesQL query string to explain
1901
+ * @param params - Optional query parameters (vectors, scalars)
1902
+ * @returns Explain response with the query execution plan
1903
+ */
1904
+ async queryExplain(queryString, params) {
1905
+ this.ensureInitialized();
1906
+ requireNonEmptyString(queryString, "Query string");
1907
+ return this.backend.queryExplain(queryString, params);
1908
+ }
1909
+ async collectionSanity(collection) {
1910
+ this.ensureInitialized();
1911
+ requireNonEmptyString(collection, "Collection name");
1912
+ return this.backend.collectionSanity(collection);
1913
+ }
1911
1914
  /**
1912
1915
  * Multi-query fusion search combining results from multiple query vectors
1913
- *
1916
+ *
1914
1917
  * Ideal for RAG pipelines using Multiple Query Generation (MQG).
1915
- *
1918
+ *
1916
1919
  * @param collection - Collection name
1917
1920
  * @param vectors - Array of query vectors
1918
1921
  * @param options - Search options (k, fusion strategy, fusionParams, filter)
1919
1922
  * @returns Fused search results
1920
- *
1923
+ *
1921
1924
  * @example
1922
1925
  * ```typescript
1923
1926
  * // RRF fusion (default)
@@ -1926,7 +1929,7 @@ var VelesDB = class {
1926
1929
  * fusion: 'rrf',
1927
1930
  * fusionParams: { k: 60 }
1928
1931
  * });
1929
- *
1932
+ *
1930
1933
  * // Weighted fusion
1931
1934
  * const results = await db.multiQuerySearch('docs', [emb1, emb2], {
1932
1935
  * k: 10,
@@ -1935,29 +1938,13 @@ var VelesDB = class {
1935
1938
  * });
1936
1939
  * ```
1937
1940
  */
1938
- async queryExplain(queryString, params) {
1939
- this.ensureInitialized();
1940
- if (!queryString || typeof queryString !== "string") {
1941
- throw new ValidationError("Query string must be a non-empty string");
1942
- }
1943
- return this.backend.queryExplain(queryString, params);
1944
- }
1945
- async collectionSanity(collection) {
1946
- this.ensureInitialized();
1947
- if (!collection || typeof collection !== "string") {
1948
- throw new ValidationError("Collection name must be a non-empty string");
1949
- }
1950
- return this.backend.collectionSanity(collection);
1951
- }
1952
1941
  async multiQuerySearch(collection, vectors, options) {
1953
1942
  this.ensureInitialized();
1954
1943
  if (!Array.isArray(vectors) || vectors.length === 0) {
1955
1944
  throw new ValidationError("Vectors must be a non-empty array");
1956
1945
  }
1957
1946
  for (const v of vectors) {
1958
- if (!Array.isArray(v) && !(v instanceof Float32Array)) {
1959
- throw new ValidationError("Each vector must be an array or Float32Array");
1960
- }
1947
+ requireVector(v, "Each vector");
1961
1948
  }
1962
1949
  return this.backend.multiQuerySearch(collection, vectors, options);
1963
1950
  }
@@ -1983,12 +1970,7 @@ var VelesDB = class {
1983
1970
  */
1984
1971
  async streamInsert(collection, docs) {
1985
1972
  this.ensureInitialized();
1986
- if (!Array.isArray(docs)) {
1987
- throw new ValidationError("Documents must be an array");
1988
- }
1989
- for (const doc of docs) {
1990
- this.validateDocument(doc);
1991
- }
1973
+ validateDocsBatch(docs, (doc) => this.validateDocument(doc));
1992
1974
  await this.backend.streamInsert(collection, docs);
1993
1975
  }
1994
1976
  /**
@@ -2198,9 +2180,7 @@ var VelesDB = class {
2198
2180
  */
2199
2181
  async createGraphCollection(name, config) {
2200
2182
  this.ensureInitialized();
2201
- if (!name || typeof name !== "string") {
2202
- throw new ValidationError("Collection name must be a non-empty string");
2203
- }
2183
+ requireNonEmptyString(name, "Collection name");
2204
2184
  await this.backend.createGraphCollection(name, config);
2205
2185
  }
2206
2186
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wiscale/velesdb-sdk",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "VelesDB TypeScript SDK: The Local Vector Database for AI & RAG. Microsecond semantic search in Browser & Node.js.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",