@anvailabs/proximadb-client 0.3.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 +160 -0
- package/dist/client.d.ts +319 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +681 -0
- package/dist/client.js.map +1 -0
- package/dist/collection.d.ts +227 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +436 -0
- package/dist/collection.js.map +1 -0
- package/dist/esm/client.js +674 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/collection.js +428 -0
- package/dist/esm/collection.js.map +1 -0
- package/dist/esm/filter.js +228 -0
- package/dist/esm/filter.js.map +1 -0
- package/dist/esm/generated/schema.js +6 -0
- package/dist/esm/generated/schema.js.map +1 -0
- package/dist/esm/graph.js +678 -0
- package/dist/esm/graph.js.map +1 -0
- package/dist/esm/index.js +86 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/search.js +317 -0
- package/dist/esm/search.js.map +1 -0
- package/dist/esm/transport.js +33 -0
- package/dist/esm/transport.js.map +1 -0
- package/dist/esm/types.js +181 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/filter.d.ts +51 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +241 -0
- package/dist/filter.js.map +1 -0
- package/dist/generated/schema.d.ts +4271 -0
- package/dist/generated/schema.d.ts.map +1 -0
- package/dist/generated/schema.js +7 -0
- package/dist/generated/schema.js.map +1 -0
- package/dist/graph.d.ts +350 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +690 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/search.d.ts +160 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +322 -0
- package/dist/search.js.map +1 -0
- package/dist/transport.d.ts +40 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +39 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +632 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +185 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
- package/src/client.ts +856 -0
- package/src/collection.ts +578 -0
- package/src/filter.ts +280 -0
- package/src/generated/schema.ts +4271 -0
- package/src/graph.ts +811 -0
- package/src/index.ts +184 -0
- package/src/search.ts +401 -0
- package/src/transport.ts +52 -0
- package/src/types.ts +726 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProximaDB TypeScript SDK
|
|
3
|
+
*
|
|
4
|
+
* A modern, async-first TypeScript client for ProximaDB vector database.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { connect, FilterBuilder } from "@proximadb/client";
|
|
9
|
+
*
|
|
10
|
+
* // Connect to ProximaDB
|
|
11
|
+
* const client = connect("http://localhost:5678");
|
|
12
|
+
*
|
|
13
|
+
* // Create a collection
|
|
14
|
+
* await client.createCollection("embeddings")
|
|
15
|
+
* .dimension(768)
|
|
16
|
+
* .engine(StorageEngine.Sst)
|
|
17
|
+
* .execute();
|
|
18
|
+
*
|
|
19
|
+
* // Insert vectors
|
|
20
|
+
* await client.collection("embeddings")
|
|
21
|
+
* .insert()
|
|
22
|
+
* .id("vec_1")
|
|
23
|
+
* .vector([0.1, 0.2, ...])
|
|
24
|
+
* .meta("category", "tech")
|
|
25
|
+
* .execute();
|
|
26
|
+
*
|
|
27
|
+
* // Search with filters
|
|
28
|
+
* const results = await client.collection("embeddings")
|
|
29
|
+
* .search()
|
|
30
|
+
* .vector(queryVector)
|
|
31
|
+
* .topK(10)
|
|
32
|
+
* .filterEq("category", "tech")
|
|
33
|
+
* .execute();
|
|
34
|
+
*
|
|
35
|
+
* // Graph operations
|
|
36
|
+
* await client.createGraph("knowledge").execute();
|
|
37
|
+
* await client.graph("knowledge")
|
|
38
|
+
* .addNode()
|
|
39
|
+
* .id("person_1")
|
|
40
|
+
* .label("Person")
|
|
41
|
+
* .property("name", "Alice")
|
|
42
|
+
* .execute();
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Copyright 2025 ProximaDB Contributors
|
|
46
|
+
* Licensed under the Apache License, Version 2.0
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// VERSION
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
export const VERSION = "1.0.0";
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// TYPES
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
// Enums (runtime values)
|
|
60
|
+
export {
|
|
61
|
+
DistanceMetric,
|
|
62
|
+
StorageEngine,
|
|
63
|
+
IndexType,
|
|
64
|
+
FilterOp,
|
|
65
|
+
LogicalOp,
|
|
66
|
+
SearchMode,
|
|
67
|
+
TraversalDirection,
|
|
68
|
+
ErrorCode,
|
|
69
|
+
ProximaDBError,
|
|
70
|
+
} from "./types";
|
|
71
|
+
|
|
72
|
+
// Type-only exports (interfaces and types)
|
|
73
|
+
export type {
|
|
74
|
+
ProximaRecord,
|
|
75
|
+
VectorRecord,
|
|
76
|
+
SearchResult,
|
|
77
|
+
CollectionConfig,
|
|
78
|
+
CollectionStats,
|
|
79
|
+
CollectionInfo,
|
|
80
|
+
HealthStatus,
|
|
81
|
+
Metadata,
|
|
82
|
+
MetadataValue,
|
|
83
|
+
JsonValue,
|
|
84
|
+
Filter,
|
|
85
|
+
FilterCondition,
|
|
86
|
+
FilterGroup,
|
|
87
|
+
FilterNode,
|
|
88
|
+
GraphNode,
|
|
89
|
+
GraphEdge,
|
|
90
|
+
TraversalResult,
|
|
91
|
+
GraphInfo,
|
|
92
|
+
ClientConfig,
|
|
93
|
+
SearchOptions,
|
|
94
|
+
InsertOptions,
|
|
95
|
+
UpdateOptions,
|
|
96
|
+
DeleteResult,
|
|
97
|
+
OperationMetrics,
|
|
98
|
+
SearchResultBatch,
|
|
99
|
+
SearchResultIterator,
|
|
100
|
+
ProbeResponse,
|
|
101
|
+
ColumnDefinition,
|
|
102
|
+
SchemaDefinition,
|
|
103
|
+
SchemaResponse,
|
|
104
|
+
UpdateSchemaRequest,
|
|
105
|
+
UpdateSchemaResponse,
|
|
106
|
+
QueryLanguage,
|
|
107
|
+
QueryRequest,
|
|
108
|
+
ExplainQueryRequest,
|
|
109
|
+
QueryResponse,
|
|
110
|
+
} from "./types";
|
|
111
|
+
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// CLIENT
|
|
114
|
+
// ============================================================================
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
ProximaDBClient,
|
|
118
|
+
ClientBuilder,
|
|
119
|
+
connect,
|
|
120
|
+
connectRest,
|
|
121
|
+
} from "./client";
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// COLLECTION
|
|
125
|
+
// ============================================================================
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
CollectionHandle,
|
|
129
|
+
CollectionBuilder,
|
|
130
|
+
InsertBuilder,
|
|
131
|
+
BatchInsertBuilder,
|
|
132
|
+
UpdateBuilder,
|
|
133
|
+
} from "./collection";
|
|
134
|
+
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// SEARCH
|
|
137
|
+
// ============================================================================
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
SearchBuilder,
|
|
141
|
+
createSearchBuilder,
|
|
142
|
+
} from "./search";
|
|
143
|
+
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// FILTER
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
FilterBuilder,
|
|
150
|
+
// Convenience functions
|
|
151
|
+
eq,
|
|
152
|
+
ne,
|
|
153
|
+
gt,
|
|
154
|
+
lt,
|
|
155
|
+
inList,
|
|
156
|
+
range,
|
|
157
|
+
andFilters,
|
|
158
|
+
orFilters,
|
|
159
|
+
filterToExpression,
|
|
160
|
+
} from "./filter";
|
|
161
|
+
|
|
162
|
+
// ============================================================================
|
|
163
|
+
// GRAPH
|
|
164
|
+
// ============================================================================
|
|
165
|
+
|
|
166
|
+
export {
|
|
167
|
+
GraphHandle,
|
|
168
|
+
GraphBuilder,
|
|
169
|
+
NodeBuilder,
|
|
170
|
+
EdgeBuilder,
|
|
171
|
+
TraversalBuilder,
|
|
172
|
+
// Convenience functions
|
|
173
|
+
createNode,
|
|
174
|
+
node,
|
|
175
|
+
createEdge,
|
|
176
|
+
edge,
|
|
177
|
+
} from "./graph";
|
|
178
|
+
|
|
179
|
+
// ============================================================================
|
|
180
|
+
// DEFAULT EXPORT
|
|
181
|
+
// ============================================================================
|
|
182
|
+
|
|
183
|
+
import { ProximaDBClient } from "./client";
|
|
184
|
+
export default ProximaDBClient;
|
package/src/search.ts
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProximaDB TypeScript SDK - Search Builder
|
|
3
|
+
*
|
|
4
|
+
* Provides a fluent API for building and executing vector similarity searches.
|
|
5
|
+
*
|
|
6
|
+
* Copyright 2025 ProximaDB Contributors
|
|
7
|
+
* Licensed under the Apache License, Version 2.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
Filter,
|
|
12
|
+
SearchResult,
|
|
13
|
+
JsonValue,
|
|
14
|
+
SearchResultIterator,
|
|
15
|
+
} from "./types";
|
|
16
|
+
import { SearchMode } from "./types";
|
|
17
|
+
import { FilterBuilder, filterToExpression } from "./filter";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Internal search request structure
|
|
21
|
+
*/
|
|
22
|
+
interface SearchRequest {
|
|
23
|
+
vector: number[];
|
|
24
|
+
top_k: number;
|
|
25
|
+
filter?: string;
|
|
26
|
+
searchMode?: string;
|
|
27
|
+
include_vector: boolean;
|
|
28
|
+
include_text: boolean;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* HTTP client interface for search operations
|
|
34
|
+
*/
|
|
35
|
+
export interface SearchHttpClient {
|
|
36
|
+
post<T>(url: string, body: unknown): Promise<T>;
|
|
37
|
+
url(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Typed transport for vector search (TD-126 Phase 4). Routes through the
|
|
40
|
+
* generated REST client (POST /api/v2/collections/{collection_id}/search).
|
|
41
|
+
*/
|
|
42
|
+
searchRecordsRequest(
|
|
43
|
+
collectionId: string,
|
|
44
|
+
body: Record<string, unknown>,
|
|
45
|
+
): Promise<unknown>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Builder for search queries with fluent API
|
|
50
|
+
*/
|
|
51
|
+
export class SearchBuilder {
|
|
52
|
+
private client: SearchHttpClient;
|
|
53
|
+
private collectionName: string;
|
|
54
|
+
private queryVector: number[] | null = null;
|
|
55
|
+
private k: number = 10;
|
|
56
|
+
private filterExpr: string | null = null;
|
|
57
|
+
private filterBuilder: FilterBuilder | null = null;
|
|
58
|
+
private searchMode: SearchMode = SearchMode.Exact;
|
|
59
|
+
private nprobeValue: number | null = null;
|
|
60
|
+
private adaptiveThreshold: number | null = null;
|
|
61
|
+
private includeVectorsFlag: boolean = false;
|
|
62
|
+
private minScoreValue: number | null = null;
|
|
63
|
+
private timeoutMsValue: number | null = null;
|
|
64
|
+
|
|
65
|
+
constructor(client: SearchHttpClient, collection: string) {
|
|
66
|
+
this.client = client;
|
|
67
|
+
this.collectionName = collection;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Set the query vector
|
|
72
|
+
*/
|
|
73
|
+
vector(vec: number[]): SearchBuilder {
|
|
74
|
+
this.queryVector = vec;
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Set the number of results to return
|
|
80
|
+
*/
|
|
81
|
+
topK(k: number): SearchBuilder {
|
|
82
|
+
this.k = k;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Alias for topK
|
|
88
|
+
*/
|
|
89
|
+
limit(k: number): SearchBuilder {
|
|
90
|
+
return this.topK(k);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Set a filter expression string
|
|
95
|
+
*/
|
|
96
|
+
filter(filterStr: string): SearchBuilder {
|
|
97
|
+
this.filterExpr = filterStr;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Apply a pre-built filter
|
|
103
|
+
*/
|
|
104
|
+
withFilter(filterObj: Filter): SearchBuilder {
|
|
105
|
+
this.filterExpr = filterToExpression(filterObj);
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Set the search mode
|
|
111
|
+
*/
|
|
112
|
+
mode(searchMode: SearchMode): SearchBuilder {
|
|
113
|
+
this.searchMode = searchMode;
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Use exact search (100% recall)
|
|
119
|
+
*/
|
|
120
|
+
exact(): SearchBuilder {
|
|
121
|
+
this.searchMode = SearchMode.Exact;
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Use approximate search for faster results
|
|
127
|
+
*/
|
|
128
|
+
approximate(): SearchBuilder {
|
|
129
|
+
this.searchMode = SearchMode.Approximate;
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Use approximate search with specific nprobe value
|
|
135
|
+
*/
|
|
136
|
+
approximateWithNprobe(nprobe: number): SearchBuilder {
|
|
137
|
+
this.searchMode = SearchMode.Approximate;
|
|
138
|
+
this.nprobeValue = nprobe;
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Use adaptive search mode
|
|
144
|
+
*/
|
|
145
|
+
adaptive(threshold: number): SearchBuilder {
|
|
146
|
+
this.searchMode = SearchMode.Adaptive;
|
|
147
|
+
this.adaptiveThreshold = threshold;
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Include vectors in results
|
|
153
|
+
*/
|
|
154
|
+
includeVectors(include: boolean = true): SearchBuilder {
|
|
155
|
+
this.includeVectorsFlag = include;
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Include metadata in results
|
|
161
|
+
*/
|
|
162
|
+
includeMetadata(_include: boolean = true): SearchBuilder {
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Set minimum score threshold
|
|
168
|
+
*/
|
|
169
|
+
minScore(score: number): SearchBuilder {
|
|
170
|
+
this.minScoreValue = score;
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Set request timeout in milliseconds
|
|
176
|
+
*/
|
|
177
|
+
timeoutMs(timeout: number): SearchBuilder {
|
|
178
|
+
this.timeoutMsValue = timeout;
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Set timeout in seconds (convenience method)
|
|
184
|
+
*/
|
|
185
|
+
timeoutSecs(secs: number): SearchBuilder {
|
|
186
|
+
this.timeoutMsValue = secs * 1000;
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// =========================================================================
|
|
191
|
+
// Inline filter methods for convenience
|
|
192
|
+
// =========================================================================
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Add an equality filter condition
|
|
196
|
+
*/
|
|
197
|
+
filterEq(field: string, value: JsonValue): SearchBuilder {
|
|
198
|
+
this.ensureFilterBuilder();
|
|
199
|
+
this.filterBuilder = this.filterBuilder!.eq(field, value);
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Add a not-equal filter condition
|
|
205
|
+
*/
|
|
206
|
+
filterNe(field: string, value: JsonValue): SearchBuilder {
|
|
207
|
+
this.ensureFilterBuilder();
|
|
208
|
+
this.filterBuilder = this.filterBuilder!.ne(field, value);
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Add a greater-than filter condition
|
|
214
|
+
*/
|
|
215
|
+
filterGt(field: string, value: JsonValue): SearchBuilder {
|
|
216
|
+
this.ensureFilterBuilder();
|
|
217
|
+
this.filterBuilder = this.filterBuilder!.gt(field, value);
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Add a greater-than-or-equal filter condition
|
|
223
|
+
*/
|
|
224
|
+
filterGte(field: string, value: JsonValue): SearchBuilder {
|
|
225
|
+
this.ensureFilterBuilder();
|
|
226
|
+
this.filterBuilder = this.filterBuilder!.gte(field, value);
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Add a less-than filter condition
|
|
232
|
+
*/
|
|
233
|
+
filterLt(field: string, value: JsonValue): SearchBuilder {
|
|
234
|
+
this.ensureFilterBuilder();
|
|
235
|
+
this.filterBuilder = this.filterBuilder!.lt(field, value);
|
|
236
|
+
return this;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Add a less-than-or-equal filter condition
|
|
241
|
+
*/
|
|
242
|
+
filterLte(field: string, value: JsonValue): SearchBuilder {
|
|
243
|
+
this.ensureFilterBuilder();
|
|
244
|
+
this.filterBuilder = this.filterBuilder!.lte(field, value);
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Add a range filter condition (inclusive)
|
|
250
|
+
*/
|
|
251
|
+
filterRange(field: string, min: JsonValue, max: JsonValue): SearchBuilder {
|
|
252
|
+
this.ensureFilterBuilder();
|
|
253
|
+
this.filterBuilder = this.filterBuilder!.range(field, min, max);
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Add an IN filter condition
|
|
259
|
+
*/
|
|
260
|
+
filterIn(field: string, values: JsonValue[]): SearchBuilder {
|
|
261
|
+
this.ensureFilterBuilder();
|
|
262
|
+
this.filterBuilder = this.filterBuilder!.inList(field, values);
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Add a contains filter condition
|
|
268
|
+
*/
|
|
269
|
+
filterContains(field: string, value: JsonValue): SearchBuilder {
|
|
270
|
+
this.ensureFilterBuilder();
|
|
271
|
+
this.filterBuilder = this.filterBuilder!.contains(field, value);
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Add an exists filter condition
|
|
277
|
+
*/
|
|
278
|
+
filterExists(field: string): SearchBuilder {
|
|
279
|
+
this.ensureFilterBuilder();
|
|
280
|
+
this.filterBuilder = this.filterBuilder!.exists(field);
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
private ensureFilterBuilder(): void {
|
|
285
|
+
if (this.filterBuilder === null) {
|
|
286
|
+
this.filterBuilder = FilterBuilder.new();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private buildFilter(): string | undefined {
|
|
291
|
+
if (this.filterBuilder !== null) {
|
|
292
|
+
return this.filterBuilder.toExpression();
|
|
293
|
+
}
|
|
294
|
+
return this.filterExpr ?? undefined;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private buildSearchModeString(): string {
|
|
298
|
+
switch (this.searchMode) {
|
|
299
|
+
case SearchMode.Exact:
|
|
300
|
+
return "exact";
|
|
301
|
+
case SearchMode.Approximate:
|
|
302
|
+
if (this.nprobeValue !== null) {
|
|
303
|
+
return "approximate:" + this.nprobeValue;
|
|
304
|
+
}
|
|
305
|
+
return "approximate";
|
|
306
|
+
case SearchMode.Adaptive:
|
|
307
|
+
if (this.adaptiveThreshold !== null) {
|
|
308
|
+
return "adaptive:" + this.adaptiveThreshold;
|
|
309
|
+
}
|
|
310
|
+
return "adaptive:10000";
|
|
311
|
+
default:
|
|
312
|
+
return "exact";
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Execute the search query
|
|
318
|
+
*/
|
|
319
|
+
async execute(): Promise<SearchResult[]> {
|
|
320
|
+
if (this.queryVector === null) {
|
|
321
|
+
throw new Error("Query vector is required");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (this.k <= 0 || this.k > 10000) {
|
|
325
|
+
throw new Error("topK must be between 1 and 10000");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const request: SearchRequest = {
|
|
329
|
+
vector: this.queryVector,
|
|
330
|
+
top_k: this.k,
|
|
331
|
+
filter: this.buildFilter(),
|
|
332
|
+
searchMode: this.buildSearchModeString(),
|
|
333
|
+
include_vector: this.includeVectorsFlag,
|
|
334
|
+
include_text: false,
|
|
335
|
+
timeoutMs: this.timeoutMsValue ?? undefined,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const response = (await this.client.searchRecordsRequest(
|
|
339
|
+
this.collectionName,
|
|
340
|
+
request as unknown as Record<string, unknown>,
|
|
341
|
+
)) as { results: SearchResult[] };
|
|
342
|
+
|
|
343
|
+
let results = response.results;
|
|
344
|
+
|
|
345
|
+
// Apply min_score filter if set
|
|
346
|
+
if (this.minScoreValue !== null) {
|
|
347
|
+
results = results.filter((r) => r.score >= this.minScoreValue!);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return results;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Execute the search and return a streaming iterator
|
|
355
|
+
*/
|
|
356
|
+
async *stream(): AsyncGenerator<SearchResult, void, unknown> {
|
|
357
|
+
const results = await this.execute();
|
|
358
|
+
for (const result of results) {
|
|
359
|
+
yield result;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Create an async iterator for streaming results
|
|
365
|
+
*/
|
|
366
|
+
async iterate(): Promise<SearchResultIterator> {
|
|
367
|
+
const results = await this.execute();
|
|
368
|
+
let index = 0;
|
|
369
|
+
const total = results.length;
|
|
370
|
+
|
|
371
|
+
const iterator: SearchResultIterator = {
|
|
372
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<SearchResult> {
|
|
373
|
+
return iterator;
|
|
374
|
+
},
|
|
375
|
+
async next(): Promise<IteratorResult<SearchResult>> {
|
|
376
|
+
if (index < results.length) {
|
|
377
|
+
return { value: results[index++]!, done: false };
|
|
378
|
+
}
|
|
379
|
+
return { value: undefined as unknown as SearchResult, done: true };
|
|
380
|
+
},
|
|
381
|
+
getTotal(): number {
|
|
382
|
+
return total;
|
|
383
|
+
},
|
|
384
|
+
isComplete(): boolean {
|
|
385
|
+
return index >= results.length;
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
return iterator;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Create a new search builder
|
|
395
|
+
*/
|
|
396
|
+
export function createSearchBuilder(
|
|
397
|
+
client: SearchHttpClient,
|
|
398
|
+
collection: string
|
|
399
|
+
): SearchBuilder {
|
|
400
|
+
return new SearchBuilder(client, collection);
|
|
401
|
+
}
|
package/src/transport.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProximaDB TypeScript SDK - Generated REST transport seam (TD-126 Phase 4)
|
|
3
|
+
*
|
|
4
|
+
* This is the thin, hand-written ergonomic facade over the GENERATED REST
|
|
5
|
+
* transport. The wire contract — path templates, path/query parameter
|
|
6
|
+
* encoding, request/response JSON shapes — is generated from
|
|
7
|
+
* `docs/openapi/proximadb-openapi.yaml` into `src/generated/schema.ts`
|
|
8
|
+
* (openapi-typescript, pinned in package.json; regenerate with
|
|
9
|
+
* `npm run gen-sdk`). `openapi-fetch` turns those generated `paths` types into
|
|
10
|
+
* a typed runtime client.
|
|
11
|
+
*
|
|
12
|
+
* Generators don't do ergonomics; this layer is the value-add: it injects the
|
|
13
|
+
* facade's own `fetch` (which owns bearer auth, retries, and error mapping —
|
|
14
|
+
* see `client.ts`) into the typed client, so the generated wire plumbing and
|
|
15
|
+
* the hand-written transport policy compose without either reimplementing the
|
|
16
|
+
* other. This mirrors the merged Go pilot (TD-126 Phase 2), where the generated
|
|
17
|
+
* `genrest.Client` is driven through `RequestEditorFn`s + a custom `http.Client`.
|
|
18
|
+
*
|
|
19
|
+
* Copyright 2025 ProximaDB Contributors
|
|
20
|
+
* Licensed under the Apache License, Version 2.0
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import createClient from "openapi-fetch";
|
|
24
|
+
import type { Client } from "openapi-fetch";
|
|
25
|
+
import type { paths } from "./generated/schema";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The typed REST client over the generated OpenAPI `paths`.
|
|
29
|
+
*/
|
|
30
|
+
export type GeneratedClient = Client<paths>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A fetch implementation matching the facade's transport policy. It is given a
|
|
34
|
+
* resolved `Request` (URL + method + body assembled by the generated client)
|
|
35
|
+
* and must return a native `Response`. The facade implements auth/retry/error
|
|
36
|
+
* mapping inside this function (see `ProximaDBClient`).
|
|
37
|
+
*/
|
|
38
|
+
export type TransportFetch = (input: Request) => Promise<Response>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Construct the generated typed REST client, routing every request the
|
|
42
|
+
* generated client issues through the facade's transport `fetch`.
|
|
43
|
+
*/
|
|
44
|
+
export function createTransport(
|
|
45
|
+
baseUrl: string,
|
|
46
|
+
fetchImpl: TransportFetch,
|
|
47
|
+
): GeneratedClient {
|
|
48
|
+
return createClient<paths>({
|
|
49
|
+
baseUrl,
|
|
50
|
+
fetch: fetchImpl,
|
|
51
|
+
});
|
|
52
|
+
}
|