@mastra/pg 0.2.9 → 0.2.10-alpha.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.2.9-alpha.0 build /home/runner/work/mastra/mastra/stores/pg
2
+ > @mastra/pg@0.2.10-alpha.0 build /home/runner/work/mastra/mastra/stores/pg
3
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
7
  CLI tsup v8.4.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 10415ms
9
+ TSC ⚡️ Build success in 10514ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.2
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.8.2
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 10461ms
16
+ DTS ⚡️ Build success in 10890ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 40.43 KB
21
- ESM ⚡️ Build success in 1214ms
22
- CJS dist/index.cjs 40.85 KB
23
- CJS ⚡️ Build success in 1213ms
20
+ ESM dist/index.js 41.41 KB
21
+ ESM ⚡️ Build success in 1149ms
22
+ CJS dist/index.cjs 41.83 KB
23
+ CJS ⚡️ Build success in 1150ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 0.2.10-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 4ac6f31: Updated permissions check for creating vector extension
8
+ - Updated dependencies [359b089]
9
+ - @mastra/core@0.8.3-alpha.0
10
+
3
11
  ## 0.2.9
4
12
 
5
13
  ### Patch Changes
@@ -203,6 +203,8 @@ declare class PgVector extends MastraVector {
203
203
  private describeIndexCache;
204
204
  private createdIndexes;
205
205
  private mutexesByName;
206
+ private installVectorExtensionPromise;
207
+ private vectorExtensionInstalled;
206
208
  constructor(connectionString: string);
207
209
  private getMutexByName;
208
210
  transformFilter(filter?: VectorFilter): VectorFilter;
@@ -219,6 +221,7 @@ declare class PgVector extends MastraVector {
219
221
  defineIndex(indexName: string, metric: "cosine" | "euclidean" | "dotproduct" | undefined, indexConfig: IndexConfig): Promise<void>;
220
222
  buildIndex(...args: ParamsToArgs<PgDefineIndexParams> | PgDefineIndexArgs): Promise<void>;
221
223
  private setupIndex;
224
+ private installVectorExtension;
222
225
  listIndexes(): Promise<string[]>;
223
226
  describeIndex(indexName: string): Promise<PGIndexStats>;
224
227
  deleteIndex(indexName: string): Promise<void>;
@@ -203,6 +203,8 @@ declare class PgVector extends MastraVector {
203
203
  private describeIndexCache;
204
204
  private createdIndexes;
205
205
  private mutexesByName;
206
+ private installVectorExtensionPromise;
207
+ private vectorExtensionInstalled;
206
208
  constructor(connectionString: string);
207
209
  private getMutexByName;
208
210
  transformFilter(filter?: VectorFilter): VectorFilter;
@@ -219,6 +221,7 @@ declare class PgVector extends MastraVector {
219
221
  defineIndex(indexName: string, metric: "cosine" | "euclidean" | "dotproduct" | undefined, indexConfig: IndexConfig): Promise<void>;
220
222
  buildIndex(...args: ParamsToArgs<PgDefineIndexParams> | PgDefineIndexArgs): Promise<void>;
221
223
  private setupIndex;
224
+ private installVectorExtension;
222
225
  listIndexes(): Promise<string[]>;
223
226
  describeIndex(indexName: string): Promise<PGIndexStats>;
224
227
  deleteIndex(indexName: string): Promise<void>;
package/dist/index.cjs CHANGED
@@ -299,6 +299,8 @@ var PgVector = class extends vector.MastraVector {
299
299
  describeIndexCache = /* @__PURE__ */ new Map();
300
300
  createdIndexes = /* @__PURE__ */ new Map();
301
301
  mutexesByName = /* @__PURE__ */ new Map();
302
+ installVectorExtensionPromise = null;
303
+ vectorExtensionInstalled = void 0;
302
304
  constructor(connectionString) {
303
305
  super();
304
306
  const basePool = new pg__default.default.Pool({
@@ -461,34 +463,16 @@ var PgVector = class extends vector.MastraVector {
461
463
  }
462
464
  const client = await this.pool.connect();
463
465
  try {
464
- const extensionCheck = await client.query(`
465
- SELECT EXISTS (
466
- SELECT 1 FROM pg_available_extensions WHERE name = 'vector'
467
- );
466
+ await this.installVectorExtension(client);
467
+ await client.query(`
468
+ CREATE TABLE IF NOT EXISTS ${indexName} (
469
+ id SERIAL PRIMARY KEY,
470
+ vector_id TEXT UNIQUE NOT NULL,
471
+ embedding vector(${dimension}),
472
+ metadata JSONB DEFAULT '{}'::jsonb
473
+ );
468
474
  `);
469
- if (!extensionCheck.rows[0].exists) {
470
- this.createdIndexes.delete(indexName);
471
- throw new Error("PostgreSQL vector extension is not available. Please install it first.");
472
- }
473
- try {
474
- await client.query(`
475
- DO $$
476
- BEGIN
477
- CREATE EXTENSION IF NOT EXISTS vector;
478
-
479
- CREATE TABLE IF NOT EXISTS ${indexName} (
480
- id SERIAL PRIMARY KEY,
481
- vector_id TEXT UNIQUE NOT NULL,
482
- embedding vector(${dimension}),
483
- metadata JSONB DEFAULT '{}'::jsonb
484
- );
485
- END $$;
486
- `);
487
- this.createdIndexes.set(indexName, indexCacheKey);
488
- } catch (e) {
489
- this.createdIndexes.delete(indexName);
490
- throw e;
491
- }
475
+ this.createdIndexes.set(indexName, indexCacheKey);
492
476
  if (buildIndex) {
493
477
  await this.setupIndex({ indexName, metric, indexConfig }, client);
494
478
  }
@@ -562,6 +546,44 @@ var PgVector = class extends vector.MastraVector {
562
546
  await client.query(indexSQL);
563
547
  });
564
548
  }
549
+ async installVectorExtension(client) {
550
+ if (this.vectorExtensionInstalled) {
551
+ return;
552
+ }
553
+ if (!this.installVectorExtensionPromise) {
554
+ this.installVectorExtensionPromise = (async () => {
555
+ try {
556
+ const extensionCheck = await client.query(`
557
+ SELECT EXISTS (
558
+ SELECT 1 FROM pg_extension WHERE extname = 'vector'
559
+ );
560
+ `);
561
+ this.vectorExtensionInstalled = extensionCheck.rows[0].exists;
562
+ if (!this.vectorExtensionInstalled) {
563
+ try {
564
+ await client.query("CREATE EXTENSION IF NOT EXISTS vector");
565
+ this.vectorExtensionInstalled = true;
566
+ this.logger.info("Vector extension installed successfully");
567
+ } catch {
568
+ this.logger.warn(
569
+ "Could not install vector extension. This requires superuser privileges. If the extension is already installed globally, you can ignore this warning."
570
+ );
571
+ }
572
+ } else {
573
+ this.logger.debug("Vector extension already installed, skipping installation");
574
+ }
575
+ } catch (error) {
576
+ this.logger.error("Error checking vector extension status", { error });
577
+ this.vectorExtensionInstalled = void 0;
578
+ this.installVectorExtensionPromise = null;
579
+ throw error;
580
+ } finally {
581
+ this.installVectorExtensionPromise = null;
582
+ }
583
+ })();
584
+ }
585
+ await this.installVectorExtensionPromise;
586
+ }
565
587
  async listIndexes() {
566
588
  const client = await this.pool.connect();
567
589
  try {
package/dist/index.js CHANGED
@@ -291,6 +291,8 @@ var PgVector = class extends MastraVector {
291
291
  describeIndexCache = /* @__PURE__ */ new Map();
292
292
  createdIndexes = /* @__PURE__ */ new Map();
293
293
  mutexesByName = /* @__PURE__ */ new Map();
294
+ installVectorExtensionPromise = null;
295
+ vectorExtensionInstalled = void 0;
294
296
  constructor(connectionString) {
295
297
  super();
296
298
  const basePool = new pg.Pool({
@@ -453,34 +455,16 @@ var PgVector = class extends MastraVector {
453
455
  }
454
456
  const client = await this.pool.connect();
455
457
  try {
456
- const extensionCheck = await client.query(`
457
- SELECT EXISTS (
458
- SELECT 1 FROM pg_available_extensions WHERE name = 'vector'
459
- );
458
+ await this.installVectorExtension(client);
459
+ await client.query(`
460
+ CREATE TABLE IF NOT EXISTS ${indexName} (
461
+ id SERIAL PRIMARY KEY,
462
+ vector_id TEXT UNIQUE NOT NULL,
463
+ embedding vector(${dimension}),
464
+ metadata JSONB DEFAULT '{}'::jsonb
465
+ );
460
466
  `);
461
- if (!extensionCheck.rows[0].exists) {
462
- this.createdIndexes.delete(indexName);
463
- throw new Error("PostgreSQL vector extension is not available. Please install it first.");
464
- }
465
- try {
466
- await client.query(`
467
- DO $$
468
- BEGIN
469
- CREATE EXTENSION IF NOT EXISTS vector;
470
-
471
- CREATE TABLE IF NOT EXISTS ${indexName} (
472
- id SERIAL PRIMARY KEY,
473
- vector_id TEXT UNIQUE NOT NULL,
474
- embedding vector(${dimension}),
475
- metadata JSONB DEFAULT '{}'::jsonb
476
- );
477
- END $$;
478
- `);
479
- this.createdIndexes.set(indexName, indexCacheKey);
480
- } catch (e) {
481
- this.createdIndexes.delete(indexName);
482
- throw e;
483
- }
467
+ this.createdIndexes.set(indexName, indexCacheKey);
484
468
  if (buildIndex) {
485
469
  await this.setupIndex({ indexName, metric, indexConfig }, client);
486
470
  }
@@ -554,6 +538,44 @@ var PgVector = class extends MastraVector {
554
538
  await client.query(indexSQL);
555
539
  });
556
540
  }
541
+ async installVectorExtension(client) {
542
+ if (this.vectorExtensionInstalled) {
543
+ return;
544
+ }
545
+ if (!this.installVectorExtensionPromise) {
546
+ this.installVectorExtensionPromise = (async () => {
547
+ try {
548
+ const extensionCheck = await client.query(`
549
+ SELECT EXISTS (
550
+ SELECT 1 FROM pg_extension WHERE extname = 'vector'
551
+ );
552
+ `);
553
+ this.vectorExtensionInstalled = extensionCheck.rows[0].exists;
554
+ if (!this.vectorExtensionInstalled) {
555
+ try {
556
+ await client.query("CREATE EXTENSION IF NOT EXISTS vector");
557
+ this.vectorExtensionInstalled = true;
558
+ this.logger.info("Vector extension installed successfully");
559
+ } catch {
560
+ this.logger.warn(
561
+ "Could not install vector extension. This requires superuser privileges. If the extension is already installed globally, you can ignore this warning."
562
+ );
563
+ }
564
+ } else {
565
+ this.logger.debug("Vector extension already installed, skipping installation");
566
+ }
567
+ } catch (error) {
568
+ this.logger.error("Error checking vector extension status", { error });
569
+ this.vectorExtensionInstalled = void 0;
570
+ this.installVectorExtensionPromise = null;
571
+ throw error;
572
+ } finally {
573
+ this.installVectorExtensionPromise = null;
574
+ }
575
+ })();
576
+ }
577
+ await this.installVectorExtensionPromise;
578
+ }
557
579
  async listIndexes() {
558
580
  const client = await this.pool.connect();
559
581
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/pg",
3
- "version": "0.2.9",
3
+ "version": "0.2.10-alpha.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",
@@ -23,7 +23,7 @@
23
23
  "pg": "^8.13.3",
24
24
  "pg-promise": "^11.11.0",
25
25
  "xxhash-wasm": "^1.1.0",
26
- "@mastra/core": "^0.8.2"
26
+ "@mastra/core": "^0.8.3-alpha.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@microsoft/api-extractor": "^7.52.1",
@@ -64,6 +64,8 @@ export class PgVector extends MastraVector {
64
64
  private describeIndexCache: Map<string, PGIndexStats> = new Map();
65
65
  private createdIndexes = new Map<string, number>();
66
66
  private mutexesByName = new Map<string, Mutex>();
67
+ private installVectorExtensionPromise: Promise<void> | null = null;
68
+ private vectorExtensionInstalled: boolean | undefined = undefined;
67
69
 
68
70
  constructor(connectionString: string) {
69
71
  super();
@@ -261,38 +263,17 @@ export class PgVector extends MastraVector {
261
263
 
262
264
  const client = await this.pool.connect();
263
265
  try {
264
- // First check if vector extension is available
265
- const extensionCheck = await client.query(`
266
- SELECT EXISTS (
267
- SELECT 1 FROM pg_available_extensions WHERE name = 'vector'
268
- );
266
+ // install vector extension
267
+ await this.installVectorExtension(client);
268
+ await client.query(`
269
+ CREATE TABLE IF NOT EXISTS ${indexName} (
270
+ id SERIAL PRIMARY KEY,
271
+ vector_id TEXT UNIQUE NOT NULL,
272
+ embedding vector(${dimension}),
273
+ metadata JSONB DEFAULT '{}'::jsonb
274
+ );
269
275
  `);
270
-
271
- if (!extensionCheck.rows[0].exists) {
272
- this.createdIndexes.delete(indexName);
273
- throw new Error('PostgreSQL vector extension is not available. Please install it first.');
274
- }
275
-
276
- // Try to create extension
277
- try {
278
- await client.query(`
279
- DO $$
280
- BEGIN
281
- CREATE EXTENSION IF NOT EXISTS vector;
282
-
283
- CREATE TABLE IF NOT EXISTS ${indexName} (
284
- id SERIAL PRIMARY KEY,
285
- vector_id TEXT UNIQUE NOT NULL,
286
- embedding vector(${dimension}),
287
- metadata JSONB DEFAULT '{}'::jsonb
288
- );
289
- END $$;
290
- `);
291
- this.createdIndexes.set(indexName, indexCacheKey);
292
- } catch (e) {
293
- this.createdIndexes.delete(indexName);
294
- throw e;
295
- }
276
+ this.createdIndexes.set(indexName, indexCacheKey);
296
277
 
297
278
  if (buildIndex) {
298
279
  await this.setupIndex({ indexName, metric, indexConfig }, client);
@@ -384,6 +365,57 @@ export class PgVector extends MastraVector {
384
365
  });
385
366
  }
386
367
 
368
+ private async installVectorExtension(client: pg.PoolClient) {
369
+ // If we've already successfully installed, no need to do anything
370
+ if (this.vectorExtensionInstalled) {
371
+ return;
372
+ }
373
+
374
+ // If there's no existing installation attempt or the previous one failed
375
+ if (!this.installVectorExtensionPromise) {
376
+ this.installVectorExtensionPromise = (async () => {
377
+ try {
378
+ // First check if extension is already installed
379
+ const extensionCheck = await client.query(`
380
+ SELECT EXISTS (
381
+ SELECT 1 FROM pg_extension WHERE extname = 'vector'
382
+ );
383
+ `);
384
+
385
+ this.vectorExtensionInstalled = extensionCheck.rows[0].exists;
386
+
387
+ if (!this.vectorExtensionInstalled) {
388
+ try {
389
+ await client.query('CREATE EXTENSION IF NOT EXISTS vector');
390
+ this.vectorExtensionInstalled = true;
391
+ this.logger.info('Vector extension installed successfully');
392
+ } catch {
393
+ this.logger.warn(
394
+ 'Could not install vector extension. This requires superuser privileges. ' +
395
+ 'If the extension is already installed globally, you can ignore this warning.',
396
+ );
397
+ // Don't set vectorExtensionInstalled to false here since we're not sure if it failed
398
+ // due to permissions or if it's already installed globally
399
+ }
400
+ } else {
401
+ this.logger.debug('Vector extension already installed, skipping installation');
402
+ }
403
+ } catch (error) {
404
+ this.logger.error('Error checking vector extension status', { error });
405
+ // Reset both the promise and the flag so we can retry
406
+ this.vectorExtensionInstalled = undefined;
407
+ this.installVectorExtensionPromise = null;
408
+ throw error; // Re-throw so caller knows it failed
409
+ } finally {
410
+ // Clear the promise after completion (success or failure)
411
+ this.installVectorExtensionPromise = null;
412
+ }
413
+ })();
414
+ }
415
+
416
+ // Wait for the installation process to complete
417
+ await this.installVectorExtensionPromise;
418
+ }
387
419
  async listIndexes(): Promise<string[]> {
388
420
  const client = await this.pool.connect();
389
421
  try {