@mastra/pg 1.0.0-beta.10 → 1.0.0-beta.11

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/dist/index.cjs CHANGED
@@ -8,7 +8,6 @@ var asyncMutex = require('async-mutex');
8
8
  var pg = require('pg');
9
9
  var xxhash = require('xxhash-wasm');
10
10
  var filter = require('@mastra/core/vector/filter');
11
- var pgPromise = require('pg-promise');
12
11
  var base = require('@mastra/core/base');
13
12
  var agent = require('@mastra/core/agent');
14
13
  var evals = require('@mastra/core/evals');
@@ -35,13 +34,15 @@ function _interopNamespace(e) {
35
34
 
36
35
  var pg__namespace = /*#__PURE__*/_interopNamespace(pg);
37
36
  var xxhash__default = /*#__PURE__*/_interopDefault(xxhash);
38
- var pgPromise__default = /*#__PURE__*/_interopDefault(pgPromise);
39
37
 
40
38
  // src/vector/index.ts
41
39
 
42
40
  // src/shared/config.ts
41
+ var isPoolConfig = (cfg) => {
42
+ return "pool" in cfg;
43
+ };
43
44
  var isConnectionStringConfig = (cfg) => {
44
- return "connectionString" in cfg;
45
+ return "connectionString" in cfg && typeof cfg.connectionString === "string";
45
46
  };
46
47
  var isHostConfig = (cfg) => {
47
48
  return "host" in cfg && "database" in cfg && "user" in cfg && "password" in cfg;
@@ -49,16 +50,13 @@ var isHostConfig = (cfg) => {
49
50
  var isCloudSqlConfig = (cfg) => {
50
51
  return "stream" in cfg || "password" in cfg && typeof cfg.password === "function";
51
52
  };
52
- var isClientConfig = (cfg) => {
53
- return "client" in cfg;
54
- };
55
53
  var validateConfig = (name, config) => {
56
54
  if (!config.id || typeof config.id !== "string" || config.id.trim() === "") {
57
55
  throw new Error(`${name}: id must be provided and cannot be empty.`);
58
56
  }
59
- if (isClientConfig(config)) {
60
- if (!config.client) {
61
- throw new Error(`${name}: client must be provided when using client config.`);
57
+ if (isPoolConfig(config)) {
58
+ if (!config.pool) {
59
+ throw new Error(`${name}: pool must be provided when using pool config.`);
62
60
  }
63
61
  return;
64
62
  }
@@ -79,7 +77,7 @@ var validateConfig = (name, config) => {
79
77
  }
80
78
  } else {
81
79
  throw new Error(
82
- `${name}: invalid config. Provide either {client}, {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with \`stream\`).`
80
+ `${name}: invalid config. Provide either {pool}, {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with \`stream\`).`
83
81
  );
84
82
  }
85
83
  };
@@ -544,8 +542,8 @@ var PgVector = class extends vector.MastraVector {
544
542
  } else if (isCloudSqlConfig(config)) {
545
543
  poolConfig = {
546
544
  ...config,
547
- max: config.max ?? 20,
548
- idleTimeoutMillis: config.idleTimeoutMillis ?? 3e4,
545
+ max: config.pgPoolOptions?.max ?? 20,
546
+ idleTimeoutMillis: config.pgPoolOptions?.idleTimeoutMillis ?? 3e4,
549
547
  connectionTimeoutMillis: 2e3,
550
548
  ...config.pgPoolOptions
551
549
  };
@@ -1687,6 +1685,132 @@ var PgVector = class extends vector.MastraVector {
1687
1685
  }
1688
1686
  }
1689
1687
  };
1688
+
1689
+ // src/storage/client.ts
1690
+ function truncateQuery(query, maxLength = 100) {
1691
+ const normalized = query.replace(/\s+/g, " ").trim();
1692
+ if (normalized.length <= maxLength) {
1693
+ return normalized;
1694
+ }
1695
+ return normalized.slice(0, maxLength) + "...";
1696
+ }
1697
+ var PoolAdapter = class {
1698
+ constructor($pool) {
1699
+ this.$pool = $pool;
1700
+ }
1701
+ connect() {
1702
+ return this.$pool.connect();
1703
+ }
1704
+ async none(query, values) {
1705
+ await this.$pool.query(query, values);
1706
+ return null;
1707
+ }
1708
+ async one(query, values) {
1709
+ const result = await this.$pool.query(query, values);
1710
+ if (result.rows.length === 0) {
1711
+ throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1712
+ }
1713
+ if (result.rows.length > 1) {
1714
+ throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
1715
+ }
1716
+ return result.rows[0];
1717
+ }
1718
+ async oneOrNone(query, values) {
1719
+ const result = await this.$pool.query(query, values);
1720
+ if (result.rows.length === 0) {
1721
+ return null;
1722
+ }
1723
+ if (result.rows.length > 1) {
1724
+ throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
1725
+ }
1726
+ return result.rows[0];
1727
+ }
1728
+ async any(query, values) {
1729
+ const result = await this.$pool.query(query, values);
1730
+ return result.rows;
1731
+ }
1732
+ async manyOrNone(query, values) {
1733
+ return this.any(query, values);
1734
+ }
1735
+ async many(query, values) {
1736
+ const result = await this.$pool.query(query, values);
1737
+ if (result.rows.length === 0) {
1738
+ throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1739
+ }
1740
+ return result.rows;
1741
+ }
1742
+ async query(query, values) {
1743
+ return this.$pool.query(query, values);
1744
+ }
1745
+ async tx(callback) {
1746
+ const client = await this.$pool.connect();
1747
+ try {
1748
+ await client.query("BEGIN");
1749
+ const txClient = new TransactionClient(client);
1750
+ const result = await callback(txClient);
1751
+ await client.query("COMMIT");
1752
+ return result;
1753
+ } catch (error) {
1754
+ try {
1755
+ await client.query("ROLLBACK");
1756
+ } catch (rollbackError) {
1757
+ console.error("Transaction rollback failed:", rollbackError);
1758
+ }
1759
+ throw error;
1760
+ } finally {
1761
+ client.release();
1762
+ }
1763
+ }
1764
+ };
1765
+ var TransactionClient = class {
1766
+ constructor(client) {
1767
+ this.client = client;
1768
+ }
1769
+ async none(query, values) {
1770
+ await this.client.query(query, values);
1771
+ return null;
1772
+ }
1773
+ async one(query, values) {
1774
+ const result = await this.client.query(query, values);
1775
+ if (result.rows.length === 0) {
1776
+ throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1777
+ }
1778
+ if (result.rows.length > 1) {
1779
+ throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
1780
+ }
1781
+ return result.rows[0];
1782
+ }
1783
+ async oneOrNone(query, values) {
1784
+ const result = await this.client.query(query, values);
1785
+ if (result.rows.length === 0) {
1786
+ return null;
1787
+ }
1788
+ if (result.rows.length > 1) {
1789
+ throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
1790
+ }
1791
+ return result.rows[0];
1792
+ }
1793
+ async any(query, values) {
1794
+ const result = await this.client.query(query, values);
1795
+ return result.rows;
1796
+ }
1797
+ async manyOrNone(query, values) {
1798
+ return this.any(query, values);
1799
+ }
1800
+ async many(query, values) {
1801
+ const result = await this.client.query(query, values);
1802
+ if (result.rows.length === 0) {
1803
+ throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1804
+ }
1805
+ return result.rows;
1806
+ }
1807
+ async query(query, values) {
1808
+ return this.client.query(query, values);
1809
+ }
1810
+ async batch(promises) {
1811
+ return Promise.all(promises);
1812
+ }
1813
+ };
1690
1814
  function resolvePgConfig(config) {
1691
1815
  if ("client" in config) {
1692
1816
  return {
@@ -1696,10 +1820,32 @@ function resolvePgConfig(config) {
1696
1820
  indexes: config.indexes
1697
1821
  };
1698
1822
  }
1699
- const pgp = pgPromise__default.default();
1700
- const client = pgp(config);
1823
+ if ("pool" in config) {
1824
+ return {
1825
+ client: new PoolAdapter(config.pool),
1826
+ schemaName: config.schemaName,
1827
+ skipDefaultIndexes: config.skipDefaultIndexes,
1828
+ indexes: config.indexes
1829
+ };
1830
+ }
1831
+ let pool;
1832
+ if ("connectionString" in config) {
1833
+ pool = new pg.Pool({
1834
+ connectionString: config.connectionString,
1835
+ ssl: config.ssl
1836
+ });
1837
+ } else {
1838
+ pool = new pg.Pool({
1839
+ host: config.host,
1840
+ port: config.port,
1841
+ database: config.database,
1842
+ user: config.user,
1843
+ password: config.password,
1844
+ ssl: config.ssl
1845
+ });
1846
+ }
1701
1847
  return {
1702
- client,
1848
+ client: new PoolAdapter(pool),
1703
1849
  schemaName: config.schemaName,
1704
1850
  skipDefaultIndexes: config.skipDefaultIndexes,
1705
1851
  indexes: config.indexes
@@ -1714,6 +1860,87 @@ function getTableName({ indexName, schemaName }) {
1714
1860
  const quotedSchemaName = schemaName;
1715
1861
  return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
1716
1862
  }
1863
+ function mapToSqlType(type) {
1864
+ switch (type) {
1865
+ case "uuid":
1866
+ return "UUID";
1867
+ case "boolean":
1868
+ return "BOOLEAN";
1869
+ default:
1870
+ return storage.getSqlType(type);
1871
+ }
1872
+ }
1873
+ function generateTableSQL({
1874
+ tableName,
1875
+ schema,
1876
+ schemaName
1877
+ }) {
1878
+ const timeZColumns = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => {
1879
+ const parsedName = utils.parseSqlIdentifier(name, "column name");
1880
+ return `"${parsedName}Z" TIMESTAMPTZ DEFAULT NOW()`;
1881
+ });
1882
+ const columns = Object.entries(schema).map(([name, def]) => {
1883
+ const parsedName = utils.parseSqlIdentifier(name, "column name");
1884
+ const constraints = [];
1885
+ if (def.primaryKey) constraints.push("PRIMARY KEY");
1886
+ if (!def.nullable) constraints.push("NOT NULL");
1887
+ return `"${parsedName}" ${mapToSqlType(def.type)} ${constraints.join(" ")}`;
1888
+ });
1889
+ const finalColumns = [...columns, ...timeZColumns].join(",\n");
1890
+ const parsedSchemaName = schemaName ? utils.parseSqlIdentifier(schemaName, "schema name") : "";
1891
+ const constraintPrefix = parsedSchemaName ? `${parsedSchemaName}_` : "";
1892
+ const quotedSchemaName = getSchemaName(schemaName);
1893
+ const sql = `
1894
+ CREATE TABLE IF NOT EXISTS ${getTableName({ indexName: tableName, schemaName: quotedSchemaName })} (
1895
+ ${finalColumns}
1896
+ );
1897
+ ${tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? `
1898
+ DO $$ BEGIN
1899
+ IF NOT EXISTS (
1900
+ SELECT 1 FROM pg_constraint WHERE conname = '${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key'
1901
+ ) AND NOT EXISTS (
1902
+ SELECT 1 FROM pg_indexes WHERE indexname = '${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key'
1903
+ ) THEN
1904
+ ALTER TABLE ${getTableName({ indexName: tableName, schemaName: quotedSchemaName })}
1905
+ ADD CONSTRAINT ${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key
1906
+ UNIQUE (workflow_name, run_id);
1907
+ END IF;
1908
+ END $$;
1909
+ ` : ""}
1910
+ ${tableName === storage.TABLE_SPANS ? `
1911
+ DO $$ BEGIN
1912
+ IF NOT EXISTS (
1913
+ SELECT 1 FROM pg_constraint WHERE conname = '${constraintPrefix}mastra_ai_spans_traceid_spanid_pk'
1914
+ ) THEN
1915
+ ALTER TABLE ${getTableName({ indexName: tableName, schemaName: quotedSchemaName })}
1916
+ ADD CONSTRAINT ${constraintPrefix}mastra_ai_spans_traceid_spanid_pk
1917
+ PRIMARY KEY ("traceId", "spanId");
1918
+ END IF;
1919
+ END $$;
1920
+ ` : ""}
1921
+ `;
1922
+ return sql;
1923
+ }
1924
+ function exportSchemas(schemaName) {
1925
+ const statements = [];
1926
+ if (schemaName) {
1927
+ const quotedSchemaName = getSchemaName(schemaName);
1928
+ statements.push(`-- Create schema if it doesn't exist`);
1929
+ statements.push(`CREATE SCHEMA IF NOT EXISTS ${quotedSchemaName};`);
1930
+ statements.push("");
1931
+ }
1932
+ for (const [tableName, schema] of Object.entries(storage.TABLE_SCHEMAS)) {
1933
+ statements.push(`-- Table: ${tableName}`);
1934
+ const sql = generateTableSQL({
1935
+ tableName,
1936
+ schema,
1937
+ schemaName
1938
+ });
1939
+ statements.push(sql.trim());
1940
+ statements.push("");
1941
+ }
1942
+ return statements.join("\n");
1943
+ }
1717
1944
  var schemaSetupRegistry = /* @__PURE__ */ new Map();
1718
1945
  var PgDB = class extends base.MastraBase {
1719
1946
  client;
@@ -1831,16 +2058,6 @@ var PgDB = class extends base.MastraBase {
1831
2058
  }
1832
2059
  await registryEntry.promise;
1833
2060
  }
1834
- getSqlType(type) {
1835
- switch (type) {
1836
- case "uuid":
1837
- return "UUID";
1838
- case "boolean":
1839
- return "BOOLEAN";
1840
- default:
1841
- return storage.getSqlType(type);
1842
- }
1843
- }
1844
2061
  getDefaultValue(type) {
1845
2062
  switch (type) {
1846
2063
  case "timestamp":
@@ -1910,52 +2127,10 @@ var PgDB = class extends base.MastraBase {
1910
2127
  }) {
1911
2128
  try {
1912
2129
  const timeZColumnNames = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => name);
1913
- const timeZColumns = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => {
1914
- const parsedName = utils.parseSqlIdentifier(name, "column name");
1915
- return `"${parsedName}Z" TIMESTAMPTZ DEFAULT NOW()`;
1916
- });
1917
- const columns = Object.entries(schema).map(([name, def]) => {
1918
- const parsedName = utils.parseSqlIdentifier(name, "column name");
1919
- const constraints = [];
1920
- if (def.primaryKey) constraints.push("PRIMARY KEY");
1921
- if (!def.nullable) constraints.push("NOT NULL");
1922
- return `"${parsedName}" ${this.getSqlType(def.type)} ${constraints.join(" ")}`;
1923
- });
1924
2130
  if (this.schemaName) {
1925
2131
  await this.setupSchema();
1926
2132
  }
1927
- const finalColumns = [...columns, ...timeZColumns].join(",\n");
1928
- const constraintPrefix = this.schemaName ? `${this.schemaName}_` : "";
1929
- const schemaName = getSchemaName(this.schemaName);
1930
- const sql = `
1931
- CREATE TABLE IF NOT EXISTS ${getTableName({ indexName: tableName, schemaName })} (
1932
- ${finalColumns}
1933
- );
1934
- ${tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? `
1935
- DO $$ BEGIN
1936
- IF NOT EXISTS (
1937
- SELECT 1 FROM pg_constraint WHERE conname = '${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key'
1938
- ) AND NOT EXISTS (
1939
- SELECT 1 FROM pg_indexes WHERE indexname = '${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key'
1940
- ) THEN
1941
- ALTER TABLE ${getTableName({ indexName: tableName, schemaName })}
1942
- ADD CONSTRAINT ${constraintPrefix}mastra_workflow_snapshot_workflow_name_run_id_key
1943
- UNIQUE (workflow_name, run_id);
1944
- END IF;
1945
- END $$;
1946
- ` : ""}
1947
- ${tableName === storage.TABLE_SPANS ? `
1948
- DO $$ BEGIN
1949
- IF NOT EXISTS (
1950
- SELECT 1 FROM pg_constraint WHERE conname = '${constraintPrefix}mastra_ai_spans_traceid_spanid_pk'
1951
- ) THEN
1952
- ALTER TABLE ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })}
1953
- ADD CONSTRAINT ${constraintPrefix}mastra_ai_spans_traceid_spanid_pk
1954
- PRIMARY KEY ("traceId", "spanId");
1955
- END IF;
1956
- END $$;
1957
- ` : ""}
1958
- `;
2133
+ const sql = generateTableSQL({ tableName, schema, schemaName: this.schemaName });
1959
2134
  await this.client.none(sql);
1960
2135
  await this.alterTable({
1961
2136
  tableName,
@@ -2029,7 +2204,7 @@ var PgDB = class extends base.MastraBase {
2029
2204
  const columnExists = await this.hasColumn(storage.TABLE_SPANS, columnName);
2030
2205
  if (!columnExists) {
2031
2206
  const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
2032
- const sqlType = this.getSqlType(columnDef.type);
2207
+ const sqlType = mapToSqlType(columnDef.type);
2033
2208
  const nullable = columnDef.nullable ? "" : "NOT NULL";
2034
2209
  const defaultValue = !columnDef.nullable ? this.getDefaultValue(columnDef.type) : "";
2035
2210
  const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
@@ -2076,7 +2251,7 @@ var PgDB = class extends base.MastraBase {
2076
2251
  if (schema[columnName]) {
2077
2252
  const columnDef = schema[columnName];
2078
2253
  const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
2079
- const sqlType = this.getSqlType(columnDef.type);
2254
+ const sqlType = mapToSqlType(columnDef.type);
2080
2255
  const nullable = columnDef.nullable ? "" : "NOT NULL";
2081
2256
  const defaultValue = !columnDef.nullable ? this.getDefaultValue(columnDef.type) : "";
2082
2257
  const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
@@ -2396,9 +2571,9 @@ var PgDB = class extends base.MastraBase {
2396
2571
  size: result.size || "0",
2397
2572
  definition: result.definition || "",
2398
2573
  method: result.method || "btree",
2399
- scans: parseInt(result.scans) || 0,
2400
- tuples_read: parseInt(result.tuples_read) || 0,
2401
- tuples_fetched: parseInt(result.tuples_fetched) || 0
2574
+ scans: parseInt(String(result.scans)) || 0,
2575
+ tuples_read: parseInt(String(result.tuples_read)) || 0,
2576
+ tuples_fetched: parseInt(String(result.tuples_fetched)) || 0
2402
2577
  };
2403
2578
  } catch (error$1) {
2404
2579
  throw new error.MastraError(
@@ -2915,6 +3090,9 @@ function getTableName3({ indexName, schemaName }) {
2915
3090
  const quotedIndexName = `"${indexName}"`;
2916
3091
  return schemaName ? `${schemaName}.${quotedIndexName}` : quotedIndexName;
2917
3092
  }
3093
+ function inPlaceholders(count, startIndex = 1) {
3094
+ return Array.from({ length: count }, (_, i) => `$${i + startIndex}`).join(", ");
3095
+ }
2918
3096
  var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
2919
3097
  #db;
2920
3098
  #schema;
@@ -3186,17 +3364,18 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3186
3364
  ...metadata
3187
3365
  };
3188
3366
  try {
3367
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3189
3368
  const thread = await this.#db.client.one(
3190
3369
  `UPDATE ${threadTableName}
3191
3370
  SET
3192
3371
  title = $1,
3193
3372
  metadata = $2,
3194
3373
  "updatedAt" = $3,
3195
- "updatedAtZ" = $3
3196
- WHERE id = $4
3374
+ "updatedAtZ" = $4
3375
+ WHERE id = $5
3197
3376
  RETURNING *
3198
3377
  `,
3199
- [title, mergedMetadata, (/* @__PURE__ */ new Date()).toISOString(), id]
3378
+ [title, mergedMetadata, now, now, id]
3200
3379
  );
3201
3380
  return {
3202
3381
  id: thread.id,
@@ -3339,7 +3518,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3339
3518
  const tableName = getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) });
3340
3519
  const query = `
3341
3520
  ${selectStatement} FROM ${tableName}
3342
- WHERE id IN (${messageIds.map((_, i) => `$${i + 1}`).join(", ")})
3521
+ WHERE id IN (${inPlaceholders(messageIds.length)})
3343
3522
  ORDER BY "createdAt" DESC
3344
3523
  `;
3345
3524
  const resultRows = await this.#db.client.manyOrNone(query, messageIds);
@@ -3400,8 +3579,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3400
3579
  const orderByStatement = `ORDER BY "${field}" ${direction}`;
3401
3580
  const selectStatement = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"`;
3402
3581
  const tableName = getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) });
3403
- const threadPlaceholders = threadIds.map((_, i) => `$${i + 1}`).join(", ");
3404
- const conditions = [`thread_id IN (${threadPlaceholders})`];
3582
+ const conditions = [`thread_id IN (${inPlaceholders(threadIds.length)})`];
3405
3583
  const queryParams = [...threadIds];
3406
3584
  let paramIndex = threadIds.length + 1;
3407
3585
  if (resourceId) {
@@ -3558,14 +3736,15 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3558
3736
  );
3559
3737
  });
3560
3738
  const threadTableName = getTableName3({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName3(this.#schema) });
3739
+ const nowStr = (/* @__PURE__ */ new Date()).toISOString();
3561
3740
  const threadUpdate = t.none(
3562
3741
  `UPDATE ${threadTableName}
3563
3742
  SET
3564
3743
  "updatedAt" = $1,
3565
- "updatedAtZ" = $1
3566
- WHERE id = $2
3744
+ "updatedAtZ" = $2
3745
+ WHERE id = $3
3567
3746
  `,
3568
- [(/* @__PURE__ */ new Date()).toISOString(), threadId]
3747
+ [nowStr, nowStr, threadId]
3569
3748
  );
3570
3749
  await Promise.all([...messageInserts, threadUpdate]);
3571
3750
  });
@@ -3602,8 +3781,8 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3602
3781
  return [];
3603
3782
  }
3604
3783
  const messageIds = messages.map((m) => m.id);
3605
- const selectQuery = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId" FROM ${getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) })} WHERE id IN ($1:list)`;
3606
- const existingMessagesDb = await this.#db.client.manyOrNone(selectQuery, [messageIds]);
3784
+ const selectQuery = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId" FROM ${getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) })} WHERE id IN (${inPlaceholders(messageIds.length)})`;
3785
+ const existingMessagesDb = await this.#db.client.manyOrNone(selectQuery, messageIds);
3607
3786
  if (existingMessagesDb.length === 0) {
3608
3787
  return [];
3609
3788
  }
@@ -3664,10 +3843,11 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3664
3843
  }
3665
3844
  }
3666
3845
  if (threadIdsToUpdate.size > 0) {
3846
+ const threadIds = Array.from(threadIdsToUpdate);
3667
3847
  queries.push(
3668
3848
  t.none(
3669
- `UPDATE ${getTableName3({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName3(this.#schema) })} SET "updatedAt" = NOW(), "updatedAtZ" = NOW() WHERE id IN ($1:list)`,
3670
- [Array.from(threadIdsToUpdate)]
3849
+ `UPDATE ${getTableName3({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName3(this.#schema) })} SET "updatedAt" = NOW(), "updatedAtZ" = NOW() WHERE id IN (${inPlaceholders(threadIds.length)})`,
3850
+ threadIds
3671
3851
  )
3672
3852
  );
3673
3853
  }
@@ -3675,7 +3855,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3675
3855
  await t.batch(queries);
3676
3856
  }
3677
3857
  });
3678
- const updatedMessages = await this.#db.client.manyOrNone(selectQuery, [messageIds]);
3858
+ const updatedMessages = await this.#db.client.manyOrNone(selectQuery, messageIds);
3679
3859
  return (updatedMessages || []).map((row) => {
3680
3860
  const message = this.normalizeMessageRow(row);
3681
3861
  if (typeof message.content === "string") {
@@ -3787,11 +3967,11 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
3787
3967
  values.push(JSON.stringify(updatedResource.metadata));
3788
3968
  paramIndex++;
3789
3969
  }
3790
- updates.push(`"updatedAt" = $${paramIndex}`);
3791
- values.push(updatedResource.updatedAt.toISOString());
3970
+ const updatedAtStr = updatedResource.updatedAt.toISOString();
3971
+ updates.push(`"updatedAt" = $${paramIndex++}`);
3972
+ values.push(updatedAtStr);
3792
3973
  updates.push(`"updatedAtZ" = $${paramIndex++}`);
3793
- values.push(updatedResource.updatedAt.toISOString());
3794
- paramIndex++;
3974
+ values.push(updatedAtStr);
3795
3975
  values.push(resourceId);
3796
3976
  await this.#db.client.none(`UPDATE ${tableName} SET ${updates.join(", ")} WHERE id = $${paramIndex}`, values);
3797
3977
  return updatedResource;
@@ -5070,9 +5250,12 @@ var WorkflowsPG = class _WorkflowsPG extends storage.WorkflowsStorage {
5070
5250
  };
5071
5251
 
5072
5252
  // src/storage/index.ts
5253
+ var DEFAULT_MAX_CONNECTIONS = 20;
5254
+ var DEFAULT_IDLE_TIMEOUT_MS = 3e4;
5073
5255
  var PostgresStore = class extends storage.MastraStorage {
5256
+ #pool;
5074
5257
  #db;
5075
- #pgp;
5258
+ #ownsPool;
5076
5259
  schema;
5077
5260
  isInitialized = false;
5078
5261
  stores;
@@ -5081,59 +5264,26 @@ var PostgresStore = class extends storage.MastraStorage {
5081
5264
  validateConfig("PostgresStore", config);
5082
5265
  super({ id: config.id, name: "PostgresStore", disableInit: config.disableInit });
5083
5266
  this.schema = config.schemaName || "public";
5084
- this.#pgp = pgPromise__default.default();
5085
- if (isClientConfig(config)) {
5086
- this.#db = config.client;
5267
+ if (isPoolConfig(config)) {
5268
+ this.#pool = config.pool;
5269
+ this.#ownsPool = false;
5087
5270
  } else {
5088
- let pgConfig;
5089
- if (isConnectionStringConfig(config)) {
5090
- pgConfig = {
5091
- id: config.id,
5092
- connectionString: config.connectionString,
5093
- max: config.max,
5094
- idleTimeoutMillis: config.idleTimeoutMillis,
5095
- ssl: config.ssl
5096
- };
5097
- } else if (isCloudSqlConfig(config)) {
5098
- pgConfig = {
5099
- ...config,
5100
- id: config.id,
5101
- max: config.max,
5102
- idleTimeoutMillis: config.idleTimeoutMillis
5103
- };
5104
- } else if (isHostConfig(config)) {
5105
- pgConfig = {
5106
- id: config.id,
5107
- host: config.host,
5108
- port: config.port,
5109
- database: config.database,
5110
- user: config.user,
5111
- password: config.password,
5112
- ssl: config.ssl,
5113
- max: config.max,
5114
- idleTimeoutMillis: config.idleTimeoutMillis
5115
- };
5116
- } else {
5117
- throw new Error(
5118
- "PostgresStore: invalid config. Provide either {client}, {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with `stream`)."
5119
- );
5120
- }
5121
- this.#db = this.#pgp(pgConfig);
5122
- }
5123
- const skipDefaultIndexes = config.skipDefaultIndexes;
5124
- const indexes = config.indexes;
5125
- const domainConfig = { client: this.#db, schemaName: this.schema, skipDefaultIndexes, indexes };
5126
- const scores = new ScoresPG(domainConfig);
5127
- const workflows = new WorkflowsPG(domainConfig);
5128
- const memory = new MemoryPG(domainConfig);
5129
- const observability = new ObservabilityPG(domainConfig);
5130
- const agents = new AgentsPG(domainConfig);
5271
+ this.#pool = this.createPool(config);
5272
+ this.#ownsPool = true;
5273
+ }
5274
+ this.#db = new PoolAdapter(this.#pool);
5275
+ const domainConfig = {
5276
+ client: this.#db,
5277
+ schemaName: this.schema,
5278
+ skipDefaultIndexes: config.skipDefaultIndexes,
5279
+ indexes: config.indexes
5280
+ };
5131
5281
  this.stores = {
5132
- scores,
5133
- workflows,
5134
- memory,
5135
- observability,
5136
- agents
5282
+ scores: new ScoresPG(domainConfig),
5283
+ workflows: new WorkflowsPG(domainConfig),
5284
+ memory: new MemoryPG(domainConfig),
5285
+ observability: new ObservabilityPG(domainConfig),
5286
+ agents: new AgentsPG(domainConfig)
5137
5287
  };
5138
5288
  } catch (e) {
5139
5289
  throw new error.MastraError(
@@ -5146,6 +5296,32 @@ var PostgresStore = class extends storage.MastraStorage {
5146
5296
  );
5147
5297
  }
5148
5298
  }
5299
+ createPool(config) {
5300
+ if (isConnectionStringConfig(config)) {
5301
+ return new pg.Pool({
5302
+ connectionString: config.connectionString,
5303
+ ssl: config.ssl,
5304
+ max: config.max ?? DEFAULT_MAX_CONNECTIONS,
5305
+ idleTimeoutMillis: config.idleTimeoutMillis ?? DEFAULT_IDLE_TIMEOUT_MS
5306
+ });
5307
+ }
5308
+ if (isHostConfig(config)) {
5309
+ return new pg.Pool({
5310
+ host: config.host,
5311
+ port: config.port,
5312
+ database: config.database,
5313
+ user: config.user,
5314
+ password: config.password,
5315
+ ssl: config.ssl,
5316
+ max: config.max ?? DEFAULT_MAX_CONNECTIONS,
5317
+ idleTimeoutMillis: config.idleTimeoutMillis ?? DEFAULT_IDLE_TIMEOUT_MS
5318
+ });
5319
+ }
5320
+ if (isCloudSqlConfig(config)) {
5321
+ return new pg.Pool(config);
5322
+ }
5323
+ throw new Error("PostgresStore: invalid config");
5324
+ }
5149
5325
  async init() {
5150
5326
  if (this.isInitialized) {
5151
5327
  return;
@@ -5165,19 +5341,32 @@ var PostgresStore = class extends storage.MastraStorage {
5165
5341
  );
5166
5342
  }
5167
5343
  }
5344
+ /**
5345
+ * Database client for executing queries.
5346
+ *
5347
+ * @example
5348
+ * ```typescript
5349
+ * const rows = await store.db.any('SELECT * FROM users WHERE active = $1', [true]);
5350
+ * const user = await store.db.one('SELECT * FROM users WHERE id = $1', [userId]);
5351
+ * ```
5352
+ */
5168
5353
  get db() {
5169
5354
  return this.#db;
5170
5355
  }
5171
- get pgp() {
5172
- return this.#pgp;
5356
+ /**
5357
+ * The underlying pg.Pool for direct database access or ORM integration.
5358
+ */
5359
+ get pool() {
5360
+ return this.#pool;
5173
5361
  }
5174
5362
  /**
5175
- * Closes the pg-promise connection pool.
5176
- *
5177
- * This will close ALL connections in the pool, including pre-configured clients.
5363
+ * Closes the connection pool if it was created by this store.
5364
+ * If a pool was passed in via config, it will not be closed.
5178
5365
  */
5179
5366
  async close() {
5180
- this.pgp.end();
5367
+ if (this.#ownsPool) {
5368
+ await this.#pool.end();
5369
+ }
5181
5370
  }
5182
5371
  };
5183
5372
 
@@ -5285,8 +5474,10 @@ exports.MemoryPG = MemoryPG;
5285
5474
  exports.ObservabilityPG = ObservabilityPG;
5286
5475
  exports.PGVECTOR_PROMPT = PGVECTOR_PROMPT;
5287
5476
  exports.PgVector = PgVector;
5477
+ exports.PoolAdapter = PoolAdapter;
5288
5478
  exports.PostgresStore = PostgresStore;
5289
5479
  exports.ScoresPG = ScoresPG;
5290
5480
  exports.WorkflowsPG = WorkflowsPG;
5481
+ exports.exportSchemas = exportSchemas;
5291
5482
  //# sourceMappingURL=index.cjs.map
5292
5483
  //# sourceMappingURL=index.cjs.map