@mastra/pg 0.1.8-alpha.9 → 0.2.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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/pg@0.1.8-alpha.9 build /home/runner/work/mastra/mastra/stores/pg
3
- > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake
2
+ > @mastra/pg@0.2.0-alpha.12 build /home/runner/work/mastra/mastra/stores/pg
3
+ > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.3.6
7
+ CLI tsup v8.4.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 9376ms
9
+ TSC ⚡️ Build success in 9808ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.7.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.7.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 10054ms
16
+ DTS ⚡️ Build success in 10902ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 33.26 KB
21
- ESM ⚡️ Build success in 1131ms
22
- CJS dist/index.cjs 33.66 KB
23
- CJS ⚡️ Build success in 1131ms
20
+ ESM dist/index.js 34.40 KB
21
+ ESM ⚡️ Build success in 1053ms
22
+ CJS dist/index.cjs 34.80 KB
23
+ CJS ⚡️ Build success in 1065ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3de7e06: Added new operations implementations for MastraVector interface methods in pg vector store
8
+
9
+ ### Patch Changes
10
+
11
+ - fd4a1d7: Update cjs bundling to make sure files are split
12
+ - Updated dependencies [a910463]
13
+ - Updated dependencies [59df7b6]
14
+ - Updated dependencies [22643eb]
15
+ - Updated dependencies [6feb23f]
16
+ - Updated dependencies [f2d6727]
17
+ - Updated dependencies [7a7a547]
18
+ - Updated dependencies [29f3a82]
19
+ - Updated dependencies [3d0e290]
20
+ - Updated dependencies [e9fbac5]
21
+ - Updated dependencies [301e4ee]
22
+ - Updated dependencies [ee667a2]
23
+ - Updated dependencies [dfbe4e9]
24
+ - Updated dependencies [dab255b]
25
+ - Updated dependencies [1e8bcbc]
26
+ - Updated dependencies [f6678e4]
27
+ - Updated dependencies [9e81f35]
28
+ - Updated dependencies [c93798b]
29
+ - Updated dependencies [a85ab24]
30
+ - Updated dependencies [dbd9f2d]
31
+ - Updated dependencies [59df7b6]
32
+ - Updated dependencies [caefaa2]
33
+ - Updated dependencies [c151ae6]
34
+ - Updated dependencies [52e0418]
35
+ - Updated dependencies [d79aedf]
36
+ - Updated dependencies [03236ec]
37
+ - Updated dependencies [3764e71]
38
+ - Updated dependencies [df982db]
39
+ - Updated dependencies [a171b37]
40
+ - Updated dependencies [506f1d5]
41
+ - Updated dependencies [02ffb7b]
42
+ - Updated dependencies [0461849]
43
+ - Updated dependencies [2259379]
44
+ - Updated dependencies [aeb5e36]
45
+ - Updated dependencies [f2301de]
46
+ - Updated dependencies [358f069]
47
+ - Updated dependencies [fd4a1d7]
48
+ - Updated dependencies [c139344]
49
+ - @mastra/core@0.5.0
50
+
51
+ ## 0.2.0-alpha.12
52
+
53
+ ### Patch Changes
54
+
55
+ - Updated dependencies [a85ab24]
56
+ - @mastra/core@0.5.0-alpha.12
57
+
58
+ ## 0.2.0-alpha.11
59
+
60
+ ### Patch Changes
61
+
62
+ - fd4a1d7: Update cjs bundling to make sure files are split
63
+ - Updated dependencies [7a7a547]
64
+ - Updated dependencies [c93798b]
65
+ - Updated dependencies [dbd9f2d]
66
+ - Updated dependencies [a171b37]
67
+ - Updated dependencies [fd4a1d7]
68
+ - @mastra/core@0.5.0-alpha.11
69
+
70
+ ## 0.2.0-alpha.10
71
+
72
+ ### Minor Changes
73
+
74
+ - 3de7e06: Added new operations implementations for MastraVector interface methods in pg vector store
75
+
76
+ ### Patch Changes
77
+
78
+ - Updated dependencies [a910463]
79
+ - @mastra/core@0.5.0-alpha.10
80
+
3
81
  ## 0.1.8-alpha.9
4
82
 
5
83
  ### Patch Changes
@@ -216,6 +216,11 @@ declare class PgVector extends MastraVector {
216
216
  deleteIndex(indexName: string): Promise<void>;
217
217
  truncateIndex(indexName: string): Promise<void>;
218
218
  disconnect(): Promise<void>;
219
+ updateIndexById(indexName: string, id: string, update: {
220
+ vector?: number[];
221
+ metadata?: Record<string, any>;
222
+ }): Promise<void>;
223
+ deleteIndexById(indexName: string, id: string): Promise<void>;
219
224
  }
220
225
  export { PgVector }
221
226
  export { PgVector as PgVector_alias_1 }
@@ -216,6 +216,11 @@ declare class PgVector extends MastraVector {
216
216
  deleteIndex(indexName: string): Promise<void>;
217
217
  truncateIndex(indexName: string): Promise<void>;
218
218
  disconnect(): Promise<void>;
219
+ updateIndexById(indexName: string, id: string, update: {
220
+ vector?: number[];
221
+ metadata?: Record<string, any>;
222
+ }): Promise<void>;
223
+ deleteIndexById(indexName: string, id: string): Promise<void>;
219
224
  }
220
225
  export { PgVector }
221
226
  export { PgVector as PgVector_alias_1 }
package/dist/index.cjs CHANGED
@@ -589,6 +589,49 @@ var PgVector = class extends vector.MastraVector {
589
589
  async disconnect() {
590
590
  await this.pool.end();
591
591
  }
592
+ async updateIndexById(indexName, id, update) {
593
+ if (!update.vector && !update.metadata) {
594
+ throw new Error("No updates provided");
595
+ }
596
+ const client = await this.pool.connect();
597
+ try {
598
+ let updateParts = [];
599
+ let values = [id];
600
+ let valueIndex = 2;
601
+ if (update.vector) {
602
+ updateParts.push(`embedding = $${valueIndex}::vector`);
603
+ values.push(`[${update.vector.join(",")}]`);
604
+ valueIndex++;
605
+ }
606
+ if (update.metadata) {
607
+ updateParts.push(`metadata = $${valueIndex}::jsonb`);
608
+ values.push(JSON.stringify(update.metadata));
609
+ }
610
+ if (updateParts.length === 0) {
611
+ return;
612
+ }
613
+ const query = `
614
+ UPDATE ${indexName}
615
+ SET ${updateParts.join(", ")}
616
+ WHERE vector_id = $1
617
+ `;
618
+ await client.query(query, values);
619
+ } finally {
620
+ client.release();
621
+ }
622
+ }
623
+ async deleteIndexById(indexName, id) {
624
+ const client = await this.pool.connect();
625
+ try {
626
+ const query = `
627
+ DELETE FROM ${indexName}
628
+ WHERE vector_id = $1
629
+ `;
630
+ await client.query(query, [id]);
631
+ } finally {
632
+ client.release();
633
+ }
634
+ }
592
635
  };
593
636
  var PostgresStore = class extends storage.MastraStorage {
594
637
  db;
package/dist/index.js CHANGED
@@ -582,6 +582,49 @@ var PgVector = class extends MastraVector {
582
582
  async disconnect() {
583
583
  await this.pool.end();
584
584
  }
585
+ async updateIndexById(indexName, id, update) {
586
+ if (!update.vector && !update.metadata) {
587
+ throw new Error("No updates provided");
588
+ }
589
+ const client = await this.pool.connect();
590
+ try {
591
+ let updateParts = [];
592
+ let values = [id];
593
+ let valueIndex = 2;
594
+ if (update.vector) {
595
+ updateParts.push(`embedding = $${valueIndex}::vector`);
596
+ values.push(`[${update.vector.join(",")}]`);
597
+ valueIndex++;
598
+ }
599
+ if (update.metadata) {
600
+ updateParts.push(`metadata = $${valueIndex}::jsonb`);
601
+ values.push(JSON.stringify(update.metadata));
602
+ }
603
+ if (updateParts.length === 0) {
604
+ return;
605
+ }
606
+ const query = `
607
+ UPDATE ${indexName}
608
+ SET ${updateParts.join(", ")}
609
+ WHERE vector_id = $1
610
+ `;
611
+ await client.query(query, values);
612
+ } finally {
613
+ client.release();
614
+ }
615
+ }
616
+ async deleteIndexById(indexName, id) {
617
+ const client = await this.pool.connect();
618
+ try {
619
+ const query = `
620
+ DELETE FROM ${indexName}
621
+ WHERE vector_id = $1
622
+ `;
623
+ await client.query(query, [id]);
624
+ } finally {
625
+ client.release();
626
+ }
627
+ }
585
628
  };
586
629
  var PostgresStore = class extends MastraStorage {
587
630
  db;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/pg",
3
- "version": "0.1.8-alpha.9",
3
+ "version": "0.2.0",
4
4
  "description": "Postgres provider for Mastra - includes both vector and db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,22 +19,22 @@
19
19
  "./package.json": "./package.json"
20
20
  },
21
21
  "dependencies": {
22
- "pg": "^8.13.1",
23
- "pg-promise": "^11.5.4",
24
- "@mastra/core": "^0.5.0-alpha.9"
22
+ "pg": "^8.13.3",
23
+ "pg-promise": "^11.11.0",
24
+ "@mastra/core": "^0.5.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@microsoft/api-extractor": "^7.49.2",
28
- "@types/node": "^22.13.1",
29
- "@types/pg": "^8.11.10",
30
- "tsup": "^8.0.1",
31
- "typescript": "^5.7.3",
32
- "vitest": "^3.0.4",
33
- "eslint": "^9.20.1",
34
- "@internal/lint": "0.0.0"
27
+ "@microsoft/api-extractor": "^7.52.1",
28
+ "@types/node": "^22.13.10",
29
+ "@types/pg": "^8.11.11",
30
+ "eslint": "^9.22.0",
31
+ "tsup": "^8.4.0",
32
+ "typescript": "^5.8.2",
33
+ "vitest": "^3.0.8",
34
+ "@internal/lint": "0.0.1"
35
35
  },
36
36
  "scripts": {
37
- "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake",
37
+ "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
38
38
  "build:watch": "pnpm build --watch",
39
39
  "pretest": "docker compose up -d && (for i in $(seq 1 30); do docker compose exec -T db pg_isready -U postgres && break || (sleep 1; [ $i -eq 30 ] && exit 1); done)",
40
40
  "test": "vitest run",
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach, vi } from 'vitest';
2
2
 
3
3
  import { PgVector } from '.';
4
+ import { type QueryResult } from '@mastra/core';
4
5
 
5
6
  describe('PgVector', () => {
6
7
  let vectorDB: PgVector;
@@ -232,6 +233,136 @@ describe('PgVector', () => {
232
233
  });
233
234
  });
234
235
 
236
+ describe('updates', () => {
237
+ const testVectors = [
238
+ [1, 2, 3],
239
+ [4, 5, 6],
240
+ [7, 8, 9],
241
+ ];
242
+
243
+ beforeEach(async () => {
244
+ await vectorDB.createIndex({ indexName: testIndexName, dimension: 3 });
245
+ });
246
+
247
+ afterEach(async () => {
248
+ await vectorDB.deleteIndex(testIndexName);
249
+ });
250
+
251
+ it('should update the vector by id', async () => {
252
+ const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
253
+ expect(ids).toHaveLength(3);
254
+
255
+ const idToBeUpdated = ids[0];
256
+ const newVector = [1, 2, 3];
257
+ const newMetaData = {
258
+ test: 'updates',
259
+ };
260
+
261
+ const update = {
262
+ vector: newVector,
263
+ metadata: newMetaData,
264
+ };
265
+
266
+ await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
267
+
268
+ const results: QueryResult[] = await vectorDB.query({
269
+ indexName: testIndexName,
270
+ queryVector: newVector,
271
+ topK: 2,
272
+ includeVector: true,
273
+ });
274
+ expect(results[0]?.id).toBe(idToBeUpdated);
275
+ expect(results[0]?.vector).toEqual(newVector);
276
+ expect(results[0]?.metadata).toEqual(newMetaData);
277
+ });
278
+
279
+ it('should only update the metadata by id', async () => {
280
+ const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
281
+ expect(ids).toHaveLength(3);
282
+
283
+ const idToBeUpdated = ids[0];
284
+ const newMetaData = {
285
+ test: 'updates',
286
+ };
287
+
288
+ const update = {
289
+ metadata: newMetaData,
290
+ };
291
+
292
+ await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
293
+
294
+ const results: QueryResult[] = await vectorDB.query({
295
+ indexName: testIndexName,
296
+ queryVector: testVectors[0],
297
+ topK: 2,
298
+ includeVector: true,
299
+ });
300
+ expect(results[0]?.id).toBe(idToBeUpdated);
301
+ expect(results[0]?.vector).toEqual(testVectors[0]);
302
+ expect(results[0]?.metadata).toEqual(newMetaData);
303
+ });
304
+
305
+ it('should only update vector embeddings by id', async () => {
306
+ const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
307
+ expect(ids).toHaveLength(3);
308
+
309
+ const idToBeUpdated = ids[0];
310
+ const newVector = [1, 2, 3];
311
+
312
+ const update = {
313
+ vector: newVector,
314
+ };
315
+
316
+ await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
317
+
318
+ const results: QueryResult[] = await vectorDB.query({
319
+ indexName: testIndexName,
320
+ queryVector: newVector,
321
+ topK: 2,
322
+ includeVector: true,
323
+ });
324
+ expect(results[0]?.id).toBe(idToBeUpdated);
325
+ expect(results[0]?.vector).toEqual(newVector);
326
+ });
327
+
328
+ it('should throw exception when no updates are given', () => {
329
+ expect(vectorDB.updateIndexById(testIndexName, 'id', {})).rejects.toThrow('No updates provided');
330
+ });
331
+ });
332
+
333
+ describe('deletes', () => {
334
+ const testVectors = [
335
+ [1, 2, 3],
336
+ [4, 5, 6],
337
+ [7, 8, 9],
338
+ ];
339
+
340
+ beforeEach(async () => {
341
+ await vectorDB.createIndex({ indexName: testIndexName, dimension: 3 });
342
+ });
343
+
344
+ afterEach(async () => {
345
+ await vectorDB.deleteIndex(testIndexName);
346
+ });
347
+
348
+ it('should delete the vector by id', async () => {
349
+ const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
350
+ expect(ids).toHaveLength(3);
351
+ const idToBeDeleted = ids[0];
352
+
353
+ await vectorDB.deleteIndexById(testIndexName, idToBeDeleted);
354
+
355
+ const results: QueryResult[] = await vectorDB.query({
356
+ indexName: testIndexName,
357
+ queryVector: [1.0, 0.0, 0.0],
358
+ topK: 2,
359
+ });
360
+
361
+ expect(results).toHaveLength(2);
362
+ expect(results.map(res => res.id)).not.toContain(idToBeDeleted);
363
+ });
364
+ });
365
+
235
366
  describe('Basic Query Operations', () => {
236
367
  ['flat', 'hnsw', 'ivfflat'].forEach(indexType => {
237
368
  const indexName = `test_query_2_${indexType}`;
@@ -426,4 +426,64 @@ export class PgVector extends MastraVector {
426
426
  async disconnect() {
427
427
  await this.pool.end();
428
428
  }
429
+
430
+ async updateIndexById(
431
+ indexName: string,
432
+ id: string,
433
+ update: {
434
+ vector?: number[];
435
+ metadata?: Record<string, any>;
436
+ },
437
+ ): Promise<void> {
438
+ if (!update.vector && !update.metadata) {
439
+ throw new Error('No updates provided');
440
+ }
441
+
442
+ const client = await this.pool.connect();
443
+ try {
444
+ let updateParts = [];
445
+ let values = [id];
446
+ let valueIndex = 2;
447
+
448
+ if (update.vector) {
449
+ updateParts.push(`embedding = $${valueIndex}::vector`);
450
+ values.push(`[${update.vector.join(',')}]`);
451
+ valueIndex++;
452
+ }
453
+
454
+ if (update.metadata) {
455
+ updateParts.push(`metadata = $${valueIndex}::jsonb`);
456
+ values.push(JSON.stringify(update.metadata));
457
+ }
458
+
459
+ if (updateParts.length === 0) {
460
+ return;
461
+ }
462
+
463
+ // query looks like this:
464
+ // UPDATE table SET embedding = $2::vector, metadata = $3::jsonb WHERE id = $1
465
+ const query = `
466
+ UPDATE ${indexName}
467
+ SET ${updateParts.join(', ')}
468
+ WHERE vector_id = $1
469
+ `;
470
+
471
+ await client.query(query, values);
472
+ } finally {
473
+ client.release();
474
+ }
475
+ }
476
+
477
+ async deleteIndexById(indexName: string, id: string): Promise<void> {
478
+ const client = await this.pool.connect();
479
+ try {
480
+ const query = `
481
+ DELETE FROM ${indexName}
482
+ WHERE vector_id = $1
483
+ `;
484
+ await client.query(query, [id]);
485
+ } finally {
486
+ client.release();
487
+ }
488
+ }
429
489
  }