@mastra/pg 1.31.1-alpha.1 → 1.31.2-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.
package/dist/index.js CHANGED
@@ -14539,6 +14539,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
14539
14539
  };
14540
14540
  //#endregion
14541
14541
  //#region src/storage/domains/notifications/index.ts
14542
+ const COMPOSITE_PRIMARY_KEY$1 = TABLE_CONFIGS[TABLE_NOTIFICATIONS].compositePrimaryKey;
14542
14543
  const statusTimestamp = (status, now) => {
14543
14544
  if (status === "delivered") return { deliveredAt: now };
14544
14545
  if (status === "seen") return { seenAt: now };
@@ -14650,11 +14651,58 @@ var NotificationsPG = class NotificationsPG extends NotificationsStorage {
14650
14651
  async init() {
14651
14652
  await this.#db.createTable({
14652
14653
  tableName: TABLE_NOTIFICATIONS,
14653
- schema: TABLE_SCHEMAS[TABLE_NOTIFICATIONS]
14654
+ schema: TABLE_SCHEMAS[TABLE_NOTIFICATIONS],
14655
+ compositePrimaryKey: COMPOSITE_PRIMARY_KEY$1
14654
14656
  });
14657
+ await this.ensurePrimaryKey();
14655
14658
  await this.createDefaultIndexes();
14656
14659
  await this.createCustomIndexes();
14657
14660
  }
14661
+ async #hasPrimaryKey() {
14662
+ return !!(await this.#db.client.oneOrNone(`SELECT EXISTS (
14663
+ SELECT 1 FROM pg_index i
14664
+ JOIN pg_class c ON c.oid = i.indrelid
14665
+ JOIN pg_namespace n ON n.oid = c.relnamespace
14666
+ WHERE c.relname = $1 AND n.nspname = $2 AND i.indisprimary
14667
+ ) AS exists`, [TABLE_NOTIFICATIONS, this.#schema]))?.exists;
14668
+ }
14669
+ /**
14670
+ * Tables created before the composite primary key was declared have no key at
14671
+ * all, which allows duplicate ids and leaves the table without a replica
14672
+ * identity (UPDATE/DELETE fail under logical replication). `createTable` is a
14673
+ * no-op for existing tables, so add the key here. If duplicate rows already
14674
+ * exist, or the role does not own the table, the key cannot be added; warn with
14675
+ * remediation instead of blocking init.
14676
+ */
14677
+ async ensurePrimaryKey() {
14678
+ if (await this.#hasPrimaryKey()) return;
14679
+ const tableName = getTableName$5({
14680
+ indexName: TABLE_NOTIFICATIONS,
14681
+ schemaName: getSchemaName$5(this.#schema)
14682
+ });
14683
+ const keyColumns = COMPOSITE_PRIMARY_KEY$1.map((column) => `"${parseSqlIdentifier(column, "column name")}"`).join(", ");
14684
+ const remediation = `ALTER TABLE ${tableName} ADD PRIMARY KEY (${keyColumns});`;
14685
+ if (await this.#db.client.oneOrNone(`SELECT 1 FROM ${tableName} GROUP BY ${keyColumns} HAVING count(*) > 1 LIMIT 1`)) {
14686
+ this.logger?.warn?.(`${tableName} contains duplicate (${keyColumns}) rows, so its PRIMARY KEY could not be added. Remove the duplicates, then run: ${remediation}`);
14687
+ return;
14688
+ }
14689
+ try {
14690
+ await this.#db.client.none(`ALTER TABLE ${tableName} ADD PRIMARY KEY (${keyColumns})`);
14691
+ this.logger?.info?.(`Added PRIMARY KEY (${keyColumns}) to ${tableName}`);
14692
+ } catch (error) {
14693
+ if (await this.#hasPrimaryKey()) return;
14694
+ if (error?.code === "42501") {
14695
+ this.logger?.warn?.(`Insufficient privilege to add PRIMARY KEY (${keyColumns}) to ${tableName}. Ask the table owner to run: ${remediation}`);
14696
+ return;
14697
+ }
14698
+ throw new MastraError({
14699
+ id: createStorageErrorId("PG", "ADD_NOTIFICATIONS_PRIMARY_KEY", "FAILED"),
14700
+ domain: ErrorDomain.STORAGE,
14701
+ category: ErrorCategory.THIRD_PARTY,
14702
+ details: { tableName }
14703
+ }, error);
14704
+ }
14705
+ }
14658
14706
  /**
14659
14707
  * Lazily ensures a btree index exists on each configured policy's retention
14660
14708
  * anchor column so age-based `prune()` deletes stay fast on large tables.
@@ -14738,6 +14786,7 @@ var NotificationsPG = class NotificationsPG extends NotificationsStorage {
14738
14786
  tableName: TABLE_NOTIFICATIONS,
14739
14787
  schema: TABLE_SCHEMAS[TABLE_NOTIFICATIONS],
14740
14788
  schemaName,
14789
+ compositePrimaryKey: COMPOSITE_PRIMARY_KEY$1,
14741
14790
  includeAllConstraints: true
14742
14791
  }));
14743
14792
  for (const idx of NotificationsPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));