@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.
Files changed (65) hide show
  1. package/README.md +160 -0
  2. package/dist/client.d.ts +319 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +681 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/collection.d.ts +227 -0
  7. package/dist/collection.d.ts.map +1 -0
  8. package/dist/collection.js +436 -0
  9. package/dist/collection.js.map +1 -0
  10. package/dist/esm/client.js +674 -0
  11. package/dist/esm/client.js.map +1 -0
  12. package/dist/esm/collection.js +428 -0
  13. package/dist/esm/collection.js.map +1 -0
  14. package/dist/esm/filter.js +228 -0
  15. package/dist/esm/filter.js.map +1 -0
  16. package/dist/esm/generated/schema.js +6 -0
  17. package/dist/esm/generated/schema.js.map +1 -0
  18. package/dist/esm/graph.js +678 -0
  19. package/dist/esm/graph.js.map +1 -0
  20. package/dist/esm/index.js +86 -0
  21. package/dist/esm/index.js.map +1 -0
  22. package/dist/esm/search.js +317 -0
  23. package/dist/esm/search.js.map +1 -0
  24. package/dist/esm/transport.js +33 -0
  25. package/dist/esm/transport.js.map +1 -0
  26. package/dist/esm/types.js +181 -0
  27. package/dist/esm/types.js.map +1 -0
  28. package/dist/filter.d.ts +51 -0
  29. package/dist/filter.d.ts.map +1 -0
  30. package/dist/filter.js +241 -0
  31. package/dist/filter.js.map +1 -0
  32. package/dist/generated/schema.d.ts +4271 -0
  33. package/dist/generated/schema.d.ts.map +1 -0
  34. package/dist/generated/schema.js +7 -0
  35. package/dist/generated/schema.js.map +1 -0
  36. package/dist/graph.d.ts +350 -0
  37. package/dist/graph.d.ts.map +1 -0
  38. package/dist/graph.js +690 -0
  39. package/dist/graph.js.map +1 -0
  40. package/dist/index.d.ts +58 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +126 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/search.d.ts +160 -0
  45. package/dist/search.d.ts.map +1 -0
  46. package/dist/search.js +322 -0
  47. package/dist/search.js.map +1 -0
  48. package/dist/transport.d.ts +40 -0
  49. package/dist/transport.d.ts.map +1 -0
  50. package/dist/transport.js +39 -0
  51. package/dist/transport.js.map +1 -0
  52. package/dist/types.d.ts +632 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +185 -0
  55. package/dist/types.js.map +1 -0
  56. package/package.json +72 -0
  57. package/src/client.ts +856 -0
  58. package/src/collection.ts +578 -0
  59. package/src/filter.ts +280 -0
  60. package/src/generated/schema.ts +4271 -0
  61. package/src/graph.ts +811 -0
  62. package/src/index.ts +184 -0
  63. package/src/search.ts +401 -0
  64. package/src/transport.ts +52 -0
  65. package/src/types.ts +726 -0
package/src/filter.ts ADDED
@@ -0,0 +1,280 @@
1
+ /**
2
+ * ProximaDB TypeScript SDK - Filter Builder
3
+ *
4
+ * Provides a fluent API for building metadata filters on vector searches.
5
+ *
6
+ * Copyright 2025 ProximaDB Contributors
7
+ * Licensed under the Apache License, Version 2.0
8
+ */
9
+
10
+ import {
11
+ Filter,
12
+ FilterCondition,
13
+ FilterGroup,
14
+ FilterNode,
15
+ FilterOp,
16
+ LogicalOp,
17
+ JsonValue,
18
+ } from "./types";
19
+
20
+ /**
21
+ * Check if a node is a FilterCondition
22
+ */
23
+ function isFilterCondition(node: FilterNode): node is FilterCondition {
24
+ return "field" in node && "operation" in node;
25
+ }
26
+
27
+ /**
28
+ * Check if a node is a FilterGroup
29
+ */
30
+ function isFilterGroup(node: FilterNode): node is FilterGroup {
31
+ return "operator" in node && "conditions" in node;
32
+ }
33
+
34
+ /**
35
+ * Convert a filter condition to expression string
36
+ */
37
+ function conditionToExpression(condition: FilterCondition): string {
38
+ const { field, operation, value } = condition;
39
+
40
+ if (value === undefined) {
41
+ const opStr = operation === "exists" ? "EXISTS" : "IS NULL";
42
+ return field + " " + opStr;
43
+ }
44
+
45
+ let valStr: string;
46
+ if (typeof value === "string") {
47
+ valStr = "'" + value + "'";
48
+ } else if (Array.isArray(value)) {
49
+ const items = value.map((x) =>
50
+ typeof x === "string" ? "'" + x + "'" : String(x)
51
+ );
52
+ valStr = "[" + items.join(", ") + "]";
53
+ } else {
54
+ valStr = String(value);
55
+ }
56
+
57
+ const opMap: Record<string, string> = {
58
+ equals: "=",
59
+ not_equals: "!=",
60
+ gt: ">",
61
+ gte: ">=",
62
+ lt: "<",
63
+ lte: "<=",
64
+ in: "IN",
65
+ not_in: "NOT IN",
66
+ contains: "CONTAINS",
67
+ starts_with: "STARTS WITH",
68
+ ends_with: "ENDS WITH",
69
+ };
70
+
71
+ const opStr = opMap[operation] ?? operation;
72
+ return field + " " + opStr + " " + valStr;
73
+ }
74
+
75
+ /**
76
+ * Convert a filter group to expression string
77
+ */
78
+ function groupToExpression(group: FilterGroup): string {
79
+ const exprs: string[] = group.conditions
80
+ .map((node) => {
81
+ if (isFilterCondition(node)) {
82
+ return conditionToExpression(node);
83
+ } else if (isFilterGroup(node)) {
84
+ return "(" + groupToExpression(node) + ")";
85
+ }
86
+ return "";
87
+ })
88
+ .filter((s) => s.length > 0);
89
+
90
+ const sep = group.operator === "and" ? " AND " : " OR ";
91
+ return exprs.join(sep);
92
+ }
93
+
94
+ /**
95
+ * Builder for constructing complex filter expressions
96
+ */
97
+ export class FilterBuilder {
98
+ private conditions: FilterNode[] = [];
99
+ private currentOperator: LogicalOp = LogicalOp.And;
100
+ private pendingOperator: LogicalOp | null = null;
101
+
102
+ static new(): FilterBuilder {
103
+ return new FilterBuilder();
104
+ }
105
+
106
+ eq(field: string, value: JsonValue): FilterBuilder {
107
+ this.addCondition({ field, operation: FilterOp.Eq, value });
108
+ return this;
109
+ }
110
+
111
+ ne(field: string, value: JsonValue): FilterBuilder {
112
+ this.addCondition({ field, operation: FilterOp.Ne, value });
113
+ return this;
114
+ }
115
+
116
+ gt(field: string, value: JsonValue): FilterBuilder {
117
+ this.addCondition({ field, operation: FilterOp.Gt, value });
118
+ return this;
119
+ }
120
+
121
+ gte(field: string, value: JsonValue): FilterBuilder {
122
+ this.addCondition({ field, operation: FilterOp.Gte, value });
123
+ return this;
124
+ }
125
+
126
+ lt(field: string, value: JsonValue): FilterBuilder {
127
+ this.addCondition({ field, operation: FilterOp.Lt, value });
128
+ return this;
129
+ }
130
+
131
+ lte(field: string, value: JsonValue): FilterBuilder {
132
+ this.addCondition({ field, operation: FilterOp.Lte, value });
133
+ return this;
134
+ }
135
+
136
+ inList(field: string, values: JsonValue[]): FilterBuilder {
137
+ this.addCondition({ field, operation: FilterOp.In, value: values });
138
+ return this;
139
+ }
140
+
141
+ notIn(field: string, values: JsonValue[]): FilterBuilder {
142
+ this.addCondition({ field, operation: FilterOp.NotIn, value: values });
143
+ return this;
144
+ }
145
+
146
+ contains(field: string, value: JsonValue): FilterBuilder {
147
+ this.addCondition({ field, operation: FilterOp.Contains, value });
148
+ return this;
149
+ }
150
+
151
+ startsWith(field: string, prefixVal: string): FilterBuilder {
152
+ this.addCondition({ field, operation: FilterOp.StartsWith, value: prefixVal });
153
+ return this;
154
+ }
155
+
156
+ endsWith(field: string, suffixVal: string): FilterBuilder {
157
+ this.addCondition({ field, operation: FilterOp.EndsWith, value: suffixVal });
158
+ return this;
159
+ }
160
+
161
+ prefix(field: string, prefixVal: string): FilterBuilder {
162
+ return this.startsWith(field, prefixVal);
163
+ }
164
+
165
+ suffix(field: string, suffixVal: string): FilterBuilder {
166
+ return this.endsWith(field, suffixVal);
167
+ }
168
+
169
+ exists(field: string): FilterBuilder {
170
+ this.addCondition({ field, operation: FilterOp.Exists });
171
+ return this;
172
+ }
173
+
174
+ isNull(field: string): FilterBuilder {
175
+ this.addCondition({ field, operation: FilterOp.IsNull });
176
+ return this;
177
+ }
178
+
179
+ range(field: string, min: JsonValue, max: JsonValue): FilterBuilder {
180
+ this.addCondition({ field, operation: FilterOp.Gte, value: min });
181
+ this.addCondition({ field, operation: FilterOp.Lte, value: max });
182
+ return this;
183
+ }
184
+
185
+ and(): FilterBuilder {
186
+ this.pendingOperator = LogicalOp.And;
187
+ return this;
188
+ }
189
+
190
+ or(): FilterBuilder {
191
+ this.pendingOperator = LogicalOp.Or;
192
+ return this;
193
+ }
194
+
195
+ group(builderFn: (fb: FilterBuilder) => FilterBuilder): FilterBuilder {
196
+ const inner = builderFn(new FilterBuilder());
197
+ const filter = inner.build();
198
+ this.conditions.push({
199
+ operator: filter.operator,
200
+ conditions: filter.conditions,
201
+ });
202
+ return this;
203
+ }
204
+
205
+ private addCondition(condition: FilterCondition): void {
206
+ if (this.pendingOperator !== null) {
207
+ if (
208
+ this.pendingOperator === LogicalOp.Or &&
209
+ this.currentOperator === LogicalOp.And
210
+ ) {
211
+ this.currentOperator = LogicalOp.Or;
212
+ }
213
+ this.pendingOperator = null;
214
+ }
215
+ this.conditions.push(condition);
216
+ }
217
+
218
+ build(): Filter {
219
+ return {
220
+ operator: this.currentOperator,
221
+ conditions: [...this.conditions],
222
+ };
223
+ }
224
+
225
+ toExpression(): string {
226
+ const filter = this.build();
227
+ return groupToExpression({
228
+ operator: filter.operator,
229
+ conditions: filter.conditions,
230
+ });
231
+ }
232
+
233
+ toJson(): string {
234
+ return JSON.stringify(this.build());
235
+ }
236
+ }
237
+
238
+ export function eq(field: string, value: JsonValue): Filter {
239
+ return FilterBuilder.new().eq(field, value).build();
240
+ }
241
+
242
+ export function ne(field: string, value: JsonValue): Filter {
243
+ return FilterBuilder.new().ne(field, value).build();
244
+ }
245
+
246
+ export function gt(field: string, value: JsonValue): Filter {
247
+ return FilterBuilder.new().gt(field, value).build();
248
+ }
249
+
250
+ export function lt(field: string, value: JsonValue): Filter {
251
+ return FilterBuilder.new().lt(field, value).build();
252
+ }
253
+
254
+ export function inList(field: string, values: JsonValue[]): Filter {
255
+ return FilterBuilder.new().inList(field, values).build();
256
+ }
257
+
258
+ export function range(field: string, min: JsonValue, max: JsonValue): Filter {
259
+ return FilterBuilder.new().range(field, min, max).build();
260
+ }
261
+
262
+ export function andFilters(filters: Filter[]): Filter {
263
+ const conditions: FilterNode[] = filters.flatMap((f) => f.conditions);
264
+ return { operator: LogicalOp.And, conditions };
265
+ }
266
+
267
+ export function orFilters(filters: Filter[]): Filter {
268
+ const conditions: FilterNode[] = filters.map((f) => ({
269
+ operator: f.operator,
270
+ conditions: f.conditions,
271
+ }));
272
+ return { operator: LogicalOp.Or, conditions };
273
+ }
274
+
275
+ export function filterToExpression(filter: Filter): string {
276
+ return groupToExpression({
277
+ operator: filter.operator,
278
+ conditions: filter.conditions,
279
+ });
280
+ }