@kernl-sdk/pg 0.1.11 → 0.1.12

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 (153) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-check-types.log +36 -0
  3. package/CHANGELOG.md +32 -0
  4. package/README.md +124 -0
  5. package/dist/__tests__/integration.test.js +2 -2
  6. package/dist/__tests__/memory-integration.test.d.ts +2 -0
  7. package/dist/__tests__/memory-integration.test.d.ts.map +1 -0
  8. package/dist/__tests__/memory-integration.test.js +287 -0
  9. package/dist/__tests__/memory.test.d.ts +2 -0
  10. package/dist/__tests__/memory.test.d.ts.map +1 -0
  11. package/dist/__tests__/memory.test.js +357 -0
  12. package/dist/index.d.ts +5 -3
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +5 -3
  15. package/dist/memory/sql.d.ts +30 -0
  16. package/dist/memory/sql.d.ts.map +1 -0
  17. package/dist/memory/sql.js +100 -0
  18. package/dist/memory/store.d.ts +41 -0
  19. package/dist/memory/store.d.ts.map +1 -0
  20. package/dist/memory/store.js +114 -0
  21. package/dist/migrations.d.ts +1 -1
  22. package/dist/migrations.d.ts.map +1 -1
  23. package/dist/migrations.js +9 -3
  24. package/dist/pgvector/__tests__/handle.test.d.ts +2 -0
  25. package/dist/pgvector/__tests__/handle.test.d.ts.map +1 -0
  26. package/dist/pgvector/__tests__/handle.test.js +277 -0
  27. package/dist/pgvector/__tests__/hit.test.d.ts +2 -0
  28. package/dist/pgvector/__tests__/hit.test.d.ts.map +1 -0
  29. package/dist/pgvector/__tests__/hit.test.js +134 -0
  30. package/dist/pgvector/__tests__/integration/document.integration.test.d.ts +7 -0
  31. package/dist/pgvector/__tests__/integration/document.integration.test.d.ts.map +1 -0
  32. package/dist/pgvector/__tests__/integration/document.integration.test.js +587 -0
  33. package/dist/pgvector/__tests__/integration/edge.integration.test.d.ts +8 -0
  34. package/dist/pgvector/__tests__/integration/edge.integration.test.d.ts.map +1 -0
  35. package/dist/pgvector/__tests__/integration/edge.integration.test.js +663 -0
  36. package/dist/pgvector/__tests__/integration/filters.integration.test.d.ts +8 -0
  37. package/dist/pgvector/__tests__/integration/filters.integration.test.d.ts.map +1 -0
  38. package/dist/pgvector/__tests__/integration/filters.integration.test.js +609 -0
  39. package/dist/pgvector/__tests__/integration/lifecycle.integration.test.d.ts +8 -0
  40. package/dist/pgvector/__tests__/integration/lifecycle.integration.test.d.ts.map +1 -0
  41. package/dist/pgvector/__tests__/integration/lifecycle.integration.test.js +449 -0
  42. package/dist/pgvector/__tests__/integration/query.integration.test.d.ts +8 -0
  43. package/dist/pgvector/__tests__/integration/query.integration.test.d.ts.map +1 -0
  44. package/dist/pgvector/__tests__/integration/query.integration.test.js +544 -0
  45. package/dist/pgvector/__tests__/search.test.d.ts +2 -0
  46. package/dist/pgvector/__tests__/search.test.d.ts.map +1 -0
  47. package/dist/pgvector/__tests__/search.test.js +279 -0
  48. package/dist/pgvector/handle.d.ts +60 -0
  49. package/dist/pgvector/handle.d.ts.map +1 -0
  50. package/dist/pgvector/handle.js +213 -0
  51. package/dist/pgvector/hit.d.ts +10 -0
  52. package/dist/pgvector/hit.d.ts.map +1 -0
  53. package/dist/pgvector/hit.js +44 -0
  54. package/dist/pgvector/index.d.ts +7 -0
  55. package/dist/pgvector/index.d.ts.map +1 -0
  56. package/dist/pgvector/index.js +5 -0
  57. package/dist/pgvector/search.d.ts +60 -0
  58. package/dist/pgvector/search.d.ts.map +1 -0
  59. package/dist/pgvector/search.js +227 -0
  60. package/dist/pgvector/sql/__tests__/limit.test.d.ts +2 -0
  61. package/dist/pgvector/sql/__tests__/limit.test.d.ts.map +1 -0
  62. package/dist/pgvector/sql/__tests__/limit.test.js +161 -0
  63. package/dist/pgvector/sql/__tests__/order.test.d.ts +2 -0
  64. package/dist/pgvector/sql/__tests__/order.test.d.ts.map +1 -0
  65. package/dist/pgvector/sql/__tests__/order.test.js +218 -0
  66. package/dist/pgvector/sql/__tests__/query.test.d.ts +2 -0
  67. package/dist/pgvector/sql/__tests__/query.test.d.ts.map +1 -0
  68. package/dist/pgvector/sql/__tests__/query.test.js +392 -0
  69. package/dist/pgvector/sql/__tests__/select.test.d.ts +2 -0
  70. package/dist/pgvector/sql/__tests__/select.test.d.ts.map +1 -0
  71. package/dist/pgvector/sql/__tests__/select.test.js +293 -0
  72. package/dist/pgvector/sql/__tests__/where.test.d.ts +2 -0
  73. package/dist/pgvector/sql/__tests__/where.test.d.ts.map +1 -0
  74. package/dist/pgvector/sql/__tests__/where.test.js +488 -0
  75. package/dist/pgvector/sql/index.d.ts +7 -0
  76. package/dist/pgvector/sql/index.d.ts.map +1 -0
  77. package/dist/pgvector/sql/index.js +6 -0
  78. package/dist/pgvector/sql/limit.d.ts +8 -0
  79. package/dist/pgvector/sql/limit.d.ts.map +1 -0
  80. package/dist/pgvector/sql/limit.js +20 -0
  81. package/dist/pgvector/sql/order.d.ts +9 -0
  82. package/dist/pgvector/sql/order.d.ts.map +1 -0
  83. package/dist/pgvector/sql/order.js +47 -0
  84. package/dist/pgvector/sql/query.d.ts +46 -0
  85. package/dist/pgvector/sql/query.d.ts.map +1 -0
  86. package/dist/pgvector/sql/query.js +54 -0
  87. package/dist/pgvector/sql/schema.d.ts +16 -0
  88. package/dist/pgvector/sql/schema.d.ts.map +1 -0
  89. package/dist/pgvector/sql/schema.js +47 -0
  90. package/dist/pgvector/sql/select.d.ts +11 -0
  91. package/dist/pgvector/sql/select.d.ts.map +1 -0
  92. package/dist/pgvector/sql/select.js +87 -0
  93. package/dist/pgvector/sql/where.d.ts +8 -0
  94. package/dist/pgvector/sql/where.d.ts.map +1 -0
  95. package/dist/pgvector/sql/where.js +137 -0
  96. package/dist/pgvector/types.d.ts +20 -0
  97. package/dist/pgvector/types.d.ts.map +1 -0
  98. package/dist/pgvector/types.js +1 -0
  99. package/dist/pgvector/utils.d.ts +18 -0
  100. package/dist/pgvector/utils.d.ts.map +1 -0
  101. package/dist/pgvector/utils.js +22 -0
  102. package/dist/postgres.d.ts +19 -26
  103. package/dist/postgres.d.ts.map +1 -1
  104. package/dist/postgres.js +15 -27
  105. package/dist/storage.d.ts +48 -0
  106. package/dist/storage.d.ts.map +1 -1
  107. package/dist/storage.js +32 -9
  108. package/dist/thread/sql.d.ts +38 -0
  109. package/dist/thread/sql.d.ts.map +1 -0
  110. package/dist/thread/sql.js +112 -0
  111. package/dist/thread/store.d.ts +2 -2
  112. package/dist/thread/store.d.ts.map +1 -1
  113. package/dist/thread/store.js +32 -102
  114. package/package.json +7 -4
  115. package/src/__tests__/integration.test.ts +15 -17
  116. package/src/__tests__/memory-integration.test.ts +355 -0
  117. package/src/__tests__/memory.test.ts +428 -0
  118. package/src/index.ts +19 -3
  119. package/src/memory/sql.ts +141 -0
  120. package/src/memory/store.ts +166 -0
  121. package/src/migrations.ts +13 -3
  122. package/src/pgvector/README.md +50 -0
  123. package/src/pgvector/__tests__/handle.test.ts +335 -0
  124. package/src/pgvector/__tests__/hit.test.ts +165 -0
  125. package/src/pgvector/__tests__/integration/document.integration.test.ts +717 -0
  126. package/src/pgvector/__tests__/integration/edge.integration.test.ts +835 -0
  127. package/src/pgvector/__tests__/integration/filters.integration.test.ts +721 -0
  128. package/src/pgvector/__tests__/integration/lifecycle.integration.test.ts +570 -0
  129. package/src/pgvector/__tests__/integration/query.integration.test.ts +667 -0
  130. package/src/pgvector/__tests__/search.test.ts +366 -0
  131. package/src/pgvector/handle.ts +285 -0
  132. package/src/pgvector/hit.ts +56 -0
  133. package/src/pgvector/index.ts +7 -0
  134. package/src/pgvector/search.ts +330 -0
  135. package/src/pgvector/sql/__tests__/limit.test.ts +180 -0
  136. package/src/pgvector/sql/__tests__/order.test.ts +248 -0
  137. package/src/pgvector/sql/__tests__/query.test.ts +548 -0
  138. package/src/pgvector/sql/__tests__/select.test.ts +367 -0
  139. package/src/pgvector/sql/__tests__/where.test.ts +554 -0
  140. package/src/pgvector/sql/index.ts +14 -0
  141. package/src/pgvector/sql/limit.ts +29 -0
  142. package/src/pgvector/sql/order.ts +55 -0
  143. package/src/pgvector/sql/query.ts +112 -0
  144. package/src/pgvector/sql/schema.ts +61 -0
  145. package/src/pgvector/sql/select.ts +100 -0
  146. package/src/pgvector/sql/where.ts +152 -0
  147. package/src/pgvector/types.ts +21 -0
  148. package/src/pgvector/utils.ts +24 -0
  149. package/src/postgres.ts +31 -33
  150. package/src/storage.ts +77 -9
  151. package/src/thread/sql.ts +159 -0
  152. package/src/thread/store.ts +40 -127
  153. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,367 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { SQL_SELECT } from "../select";
3
+
4
+ describe("SQL_SELECT", () => {
5
+ describe("encode", () => {
6
+ it("returns id and constant score when no signals", () => {
7
+ const result = SQL_SELECT.encode({
8
+ pkey: "id",
9
+ signals: [],
10
+ });
11
+
12
+ expect(result.sql).toBe('"id" as id, 1 as score');
13
+ expect(result.params).toEqual([]);
14
+ });
15
+
16
+ it("uses custom pkey column", () => {
17
+ const result = SQL_SELECT.encode({
18
+ pkey: "doc_id",
19
+ signals: [],
20
+ });
21
+
22
+ expect(result.sql).toBe('"doc_id" as id, 1 as score');
23
+ });
24
+
25
+ it("builds cosine similarity score for vector signal", () => {
26
+ const vector = [0.1, 0.2, 0.3];
27
+ const result = SQL_SELECT.encode({
28
+ pkey: "id",
29
+ signals: [{ embedding: vector }],
30
+ });
31
+
32
+ expect(result.sql).toBe(
33
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score',
34
+ );
35
+ expect(result.params).toEqual([JSON.stringify(vector)]);
36
+ });
37
+
38
+ it("uses binding to map field to column", () => {
39
+ const vector = [0.1, 0.2, 0.3];
40
+ const result = SQL_SELECT.encode({
41
+ pkey: "id",
42
+ signals: [{ embedding: vector }],
43
+ binding: {
44
+ schema: "public",
45
+ table: "docs",
46
+ pkey: "id",
47
+ fields: {
48
+ embedding: {
49
+ column: "vec_col",
50
+ type: "vector",
51
+ dimensions: 3,
52
+ similarity: "cosine",
53
+ },
54
+ },
55
+ },
56
+ });
57
+
58
+ expect(result.sql).toBe(
59
+ '"id" as id, 1 - ("vec_col" <=> $1::vector) as score, "vec_col"',
60
+ );
61
+ });
62
+
63
+ it("builds euclidean distance score", () => {
64
+ const vector = [0.1, 0.2, 0.3];
65
+ const result = SQL_SELECT.encode({
66
+ pkey: "id",
67
+ signals: [{ embedding: vector }],
68
+ binding: {
69
+ schema: "public",
70
+ table: "docs",
71
+ pkey: "id",
72
+ fields: {
73
+ embedding: {
74
+ column: "embedding",
75
+ type: "vector",
76
+ dimensions: 3,
77
+ similarity: "euclidean",
78
+ },
79
+ },
80
+ },
81
+ });
82
+
83
+ expect(result.sql).toBe(
84
+ '"id" as id, 1 / (1 + ("embedding" <-> $1::vector)) as score, "embedding"',
85
+ );
86
+ });
87
+
88
+ it("builds dot product score", () => {
89
+ const vector = [0.1, 0.2, 0.3];
90
+ const result = SQL_SELECT.encode({
91
+ pkey: "id",
92
+ signals: [{ embedding: vector }],
93
+ binding: {
94
+ schema: "public",
95
+ table: "docs",
96
+ pkey: "id",
97
+ fields: {
98
+ embedding: {
99
+ column: "embedding",
100
+ type: "vector",
101
+ dimensions: 3,
102
+ similarity: "dot_product",
103
+ },
104
+ },
105
+ },
106
+ });
107
+
108
+ expect(result.sql).toBe(
109
+ '"id" as id, -("embedding" <#> $1::vector) as score, "embedding"',
110
+ );
111
+ });
112
+
113
+ it("ignores non-vector signals", () => {
114
+ const result = SQL_SELECT.encode({
115
+ pkey: "id",
116
+ signals: [{ content: "search text" }],
117
+ });
118
+
119
+ // String signals are not vectors, so no vector scoring
120
+ expect(result.sql).toBe('"id" as id, 1 as score');
121
+ expect(result.params).toEqual([]);
122
+ });
123
+
124
+ it("finds vector signal among mixed signals", () => {
125
+ const vector = [0.1, 0.2, 0.3];
126
+ const result = SQL_SELECT.encode({
127
+ pkey: "id",
128
+ signals: [
129
+ { content: "search text", weight: 0.3 },
130
+ { embedding: vector, weight: 0.7 },
131
+ ],
132
+ });
133
+
134
+ expect(result.sql).toBe(
135
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score',
136
+ );
137
+ expect(result.params).toEqual([JSON.stringify(vector)]);
138
+ });
139
+
140
+ it("ignores weight field when detecting vector", () => {
141
+ const vector = [0.1, 0.2, 0.3];
142
+ const result = SQL_SELECT.encode({
143
+ pkey: "id",
144
+ signals: [{ embedding: vector, weight: 0.5 }],
145
+ });
146
+
147
+ expect(result.sql).toBe(
148
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score',
149
+ );
150
+ });
151
+
152
+ describe("binding edge cases", () => {
153
+ it("falls back to field name when binding exists but field not in fields", () => {
154
+ const vector = [0.1, 0.2, 0.3];
155
+ const result = SQL_SELECT.encode({
156
+ pkey: "id",
157
+ signals: [{ embedding: vector }],
158
+ binding: {
159
+ schema: "public",
160
+ table: "docs",
161
+ pkey: "id",
162
+ fields: {
163
+ other_field: {
164
+ column: "other_col",
165
+ type: "vector",
166
+ dimensions: 3,
167
+ similarity: "cosine",
168
+ },
169
+ },
170
+ },
171
+ });
172
+
173
+ // embedding not in binding.fields, so uses "embedding" as column name
174
+ // but other_field column is still selected
175
+ expect(result.sql).toBe(
176
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score, "other_col"',
177
+ );
178
+ });
179
+
180
+ it("defaults to cosine when binding field has no similarity", () => {
181
+ const vector = [0.1, 0.2, 0.3];
182
+ const result = SQL_SELECT.encode({
183
+ pkey: "id",
184
+ signals: [{ embedding: vector }],
185
+ binding: {
186
+ schema: "public",
187
+ table: "docs",
188
+ fields: {
189
+ embedding: {
190
+ column: "vec_col",
191
+ type: "vector",
192
+ dimensions: 3,
193
+ // similarity intentionally omitted
194
+ },
195
+ },
196
+ } as any, // cast to bypass type check for test
197
+ });
198
+
199
+ expect(result.sql).toBe(
200
+ '"id" as id, 1 - ("vec_col" <=> $1::vector) as score, "vec_col"',
201
+ );
202
+ });
203
+ });
204
+
205
+ describe("multiple vector signals", () => {
206
+ it("uses only the first vector signal", () => {
207
+ const vec1 = [0.1, 0.2, 0.3];
208
+ const vec2 = [0.4, 0.5, 0.6];
209
+ const result = SQL_SELECT.encode({
210
+ pkey: "id",
211
+ signals: [{ embedding1: vec1 }, { embedding2: vec2 }],
212
+ });
213
+
214
+ // Should use embedding1, not embedding2
215
+ expect(result.sql).toBe(
216
+ '"id" as id, 1 - ("embedding1" <=> $1::vector) as score',
217
+ );
218
+ expect(result.params).toEqual([JSON.stringify(vec1)]);
219
+ });
220
+
221
+ it("uses first vector field within a single signal object", () => {
222
+ const vec1 = [0.1, 0.2, 0.3];
223
+ const vec2 = [0.4, 0.5, 0.6];
224
+ const result = SQL_SELECT.encode({
225
+ pkey: "id",
226
+ signals: [{ embedding1: vec1, embedding2: vec2 }],
227
+ });
228
+
229
+ // Object iteration order - first encountered wins
230
+ expect(result.params).toHaveLength(1);
231
+ });
232
+ });
233
+
234
+ describe("malformed signals", () => {
235
+ it("treats empty signal object as no vector signal", () => {
236
+ const result = SQL_SELECT.encode({
237
+ pkey: "id",
238
+ signals: [{}],
239
+ });
240
+
241
+ expect(result.sql).toBe('"id" as id, 1 as score');
242
+ expect(result.params).toEqual([]);
243
+ });
244
+
245
+ it("treats signal with only weight as no vector signal", () => {
246
+ const result = SQL_SELECT.encode({
247
+ pkey: "id",
248
+ signals: [{ weight: 0.5 }],
249
+ });
250
+
251
+ expect(result.sql).toBe('"id" as id, 1 as score');
252
+ expect(result.params).toEqual([]);
253
+ });
254
+
255
+ it("handles empty vector array", () => {
256
+ const result = SQL_SELECT.encode({
257
+ pkey: "id",
258
+ signals: [{ embedding: [] }],
259
+ });
260
+
261
+ // Empty array is still detected as vector, generates SQL with empty array
262
+ expect(result.sql).toBe(
263
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score',
264
+ );
265
+ expect(result.params).toEqual(["[]"]);
266
+ });
267
+
268
+ it("handles vector with extra non-vector props", () => {
269
+ const vector = [0.1, 0.2, 0.3];
270
+ const result = SQL_SELECT.encode({
271
+ pkey: "id",
272
+ signals: [{ embedding: vector, metadata: "ignored", count: 42 }],
273
+ });
274
+
275
+ // Only the array field is used for vector scoring
276
+ expect(result.sql).toBe(
277
+ '"id" as id, 1 - ("embedding" <=> $1::vector) as score',
278
+ );
279
+ expect(result.params).toEqual([JSON.stringify(vector)]);
280
+ });
281
+ });
282
+ });
283
+
284
+ describe("include", () => {
285
+ const binding = {
286
+ schema: "public",
287
+ table: "docs",
288
+ pkey: "id",
289
+ fields: {
290
+ title: { column: "title", type: "string" as const },
291
+ content: { column: "content", type: "string" as const },
292
+ embedding: {
293
+ column: "vec",
294
+ type: "vector" as const,
295
+ dimensions: 3,
296
+ similarity: "cosine" as const,
297
+ },
298
+ },
299
+ };
300
+
301
+ it("selects all columns when include is undefined", () => {
302
+ const result = SQL_SELECT.encode({
303
+ pkey: "id",
304
+ signals: [],
305
+ binding,
306
+ });
307
+
308
+ expect(result.sql).toBe(
309
+ '"id" as id, 1 as score, "title", "content", "vec"',
310
+ );
311
+ });
312
+
313
+ it("selects all columns when include is true", () => {
314
+ const result = SQL_SELECT.encode({
315
+ pkey: "id",
316
+ signals: [],
317
+ binding,
318
+ include: true,
319
+ });
320
+
321
+ expect(result.sql).toBe(
322
+ '"id" as id, 1 as score, "title", "content", "vec"',
323
+ );
324
+ });
325
+
326
+ it("selects no columns when include is false", () => {
327
+ const result = SQL_SELECT.encode({
328
+ pkey: "id",
329
+ signals: [],
330
+ binding,
331
+ include: false,
332
+ });
333
+
334
+ expect(result.sql).toBe('"id" as id, 1 as score');
335
+ });
336
+
337
+ it("selects only specified columns when include is array", () => {
338
+ const result = SQL_SELECT.encode({
339
+ pkey: "id",
340
+ signals: [],
341
+ binding,
342
+ include: ["title"],
343
+ });
344
+
345
+ expect(result.sql).toBe('"id" as id, 1 as score, "title"');
346
+ });
347
+
348
+ it("ignores fields not in binding", () => {
349
+ const result = SQL_SELECT.encode({
350
+ pkey: "id",
351
+ signals: [],
352
+ binding,
353
+ include: ["title", "nonexistent"],
354
+ });
355
+
356
+ expect(result.sql).toBe('"id" as id, 1 as score, "title"');
357
+ });
358
+ });
359
+
360
+ describe("decode", () => {
361
+ it("throws not implemented", () => {
362
+ expect(() => SQL_SELECT.decode({} as any)).toThrow(
363
+ "SQL_SELECT.decode not implemented",
364
+ );
365
+ });
366
+ });
367
+ });