@axiom-lattice/pg-stores 1.0.83 → 1.0.84

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 (34) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +9 -0
  3. package/dist/index.d.mts +124 -44
  4. package/dist/index.d.ts +124 -44
  5. package/dist/index.js +472 -162
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +472 -162
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +3 -3
  10. package/scripts/check-migration-versions.mjs +42 -9
  11. package/src/createPgStoreConfig.ts +97 -3
  12. package/src/migrations/migration.ts +91 -60
  13. package/src/stores/ChannelBindingStore.ts +21 -3
  14. package/src/stores/ChannelIdentityMappingStore.ts +21 -3
  15. package/src/stores/MenuStore.ts +21 -3
  16. package/src/stores/PostgreSQLA2AApiKeyStore.ts +21 -3
  17. package/src/stores/PostgreSQLAssistantStore.ts +19 -3
  18. package/src/stores/PostgreSQLChannelInstallationStore.ts +21 -3
  19. package/src/stores/PostgreSQLDatabaseConfigStore.ts +23 -4
  20. package/src/stores/PostgreSQLEvalStore.ts +15 -3
  21. package/src/stores/PostgreSQLMcpServerConfigStore.ts +23 -4
  22. package/src/stores/PostgreSQLMetricsServerConfigStore.ts +23 -4
  23. package/src/stores/PostgreSQLProjectStore.ts +19 -3
  24. package/src/stores/PostgreSQLScheduleStorage.ts +21 -4
  25. package/src/stores/PostgreSQLSkillStore.ts +14 -3
  26. package/src/stores/PostgreSQLTaskStore.ts +14 -3
  27. package/src/stores/PostgreSQLTenantStore.ts +19 -3
  28. package/src/stores/PostgreSQLThreadStore.ts +19 -3
  29. package/src/stores/PostgreSQLUserStore.ts +18 -4
  30. package/src/stores/PostgreSQLUserTenantLinkStore.ts +18 -4
  31. package/src/stores/PostgreSQLWorkflowTrackingStore.ts +18 -4
  32. package/src/stores/PostgreSQLWorkspaceStore.ts +19 -3
  33. package/src/stores/PostgresSharedResourceStore.ts +21 -3
  34. package/src/stores/ThreadMessageQueueStore.ts +14 -3
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  // src/index.ts
2
- import { Pool as Pool23 } from "pg";
2
+ import { Pool as Pool24 } from "pg";
3
3
 
4
- // src/stores/PostgreSQLThreadStore.ts
5
- import { Pool } from "pg";
4
+ // src/createPgStoreConfig.ts
5
+ import { Pool as Pool21 } from "pg";
6
6
 
7
7
  // src/migrations/migration.ts
8
8
  var MigrationManager = class {
@@ -11,39 +11,68 @@ var MigrationManager = class {
11
11
  this.pool = pool;
12
12
  }
13
13
  /**
14
- * Register a migration
14
+ * Register a migration.
15
+ * Duplicate names are rejected immediately (name = identity).
16
+ * Duplicate versions are allowed (version = ordering only).
15
17
  */
16
18
  register(migration) {
19
+ const existing = this.migrations.find((m) => m.name === migration.name);
20
+ if (existing) {
21
+ throw new Error(
22
+ `Migration name conflict: "${migration.name}" v${migration.version} collides with existing registration at v${existing.version}`
23
+ );
24
+ }
17
25
  this.migrations.push(migration);
18
26
  this.migrations.sort((a, b) => a.version - b.version);
19
27
  }
20
28
  /**
21
- * Initialize migrations table if it doesn't exist
29
+ * Ensure the tracking table exists with the correct schema.
30
+ * Handles migration from old schema (PK on version) to new schema (PK on name).
22
31
  */
23
32
  async ensureMigrationsTable(client) {
24
- await client.query(`
25
- CREATE TABLE IF NOT EXISTS lattice_schema_migrations (
26
- version INTEGER PRIMARY KEY,
27
- name VARCHAR(255) NOT NULL,
28
- applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
33
+ const tableExists = await client.query(`
34
+ SELECT EXISTS (
35
+ SELECT FROM information_schema.tables
36
+ WHERE table_name = 'lattice_schema_migrations'
29
37
  )
30
38
  `);
39
+ if (!tableExists.rows[0].exists) {
40
+ await client.query(`
41
+ CREATE TABLE lattice_schema_migrations (
42
+ name VARCHAR(255) PRIMARY KEY,
43
+ version INTEGER NOT NULL,
44
+ applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
45
+ )
46
+ `);
47
+ return;
48
+ }
49
+ const pkCheck = await client.query(`
50
+ SELECT a.attname AS column_name, con.conname AS constraint_name
51
+ FROM pg_index i
52
+ JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
53
+ JOIN pg_constraint con ON con.conindid = i.indexrelid
54
+ WHERE i.indrelid = 'lattice_schema_migrations'::regclass
55
+ AND i.indisprimary
56
+ `);
57
+ const pkColumn = pkCheck.rows[0]?.column_name;
58
+ const constraintName = pkCheck.rows[0]?.constraint_name;
59
+ if (pkColumn === "version" && constraintName) {
60
+ await client.query(
61
+ `ALTER TABLE lattice_schema_migrations DROP CONSTRAINT ${constraintName}`
62
+ );
63
+ await client.query(
64
+ `ALTER TABLE lattice_schema_migrations ADD PRIMARY KEY (name)`
65
+ );
66
+ }
31
67
  }
32
68
  /**
33
- * Get applied migrations from database
69
+ * Get the set of already-applied migration names from the tracking table.
34
70
  */
35
- async getAppliedMigrations(client) {
36
- await client.query(`
37
- CREATE TABLE IF NOT EXISTS lattice_schema_migrations (
38
- version INTEGER PRIMARY KEY,
39
- name VARCHAR(255) NOT NULL,
40
- applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
41
- )
42
- `);
71
+ async getAppliedNames(client) {
43
72
  const result = await client.query(
44
- "SELECT version, name, applied_at FROM lattice_schema_migrations ORDER BY version"
73
+ "SELECT name, version, applied_at FROM lattice_schema_migrations ORDER BY version"
45
74
  );
46
- return result.rows;
75
+ return new Set(result.rows.map((r) => r.name));
47
76
  }
48
77
  /**
49
78
  * Apply pending migrations
@@ -57,10 +86,9 @@ var MigrationManager = class {
57
86
  try {
58
87
  await client.query("BEGIN");
59
88
  await this.ensureMigrationsTable(client);
60
- const appliedMigrations = await this.getAppliedMigrations(client);
61
- const appliedVersions = new Set(appliedMigrations.map((m) => m.version));
89
+ const appliedNames = await this.getAppliedNames(client);
62
90
  const pendingMigrations = this.migrations.filter(
63
- (m) => !appliedVersions.has(m.version)
91
+ (m) => !appliedNames.has(m.name)
64
92
  );
65
93
  if (pendingMigrations.length === 0) {
66
94
  console.log("No pending migrations");
@@ -69,12 +97,12 @@ var MigrationManager = class {
69
97
  }
70
98
  for (const migration of pendingMigrations) {
71
99
  console.log(
72
- `Applying migration ${migration.version}: ${migration.name}`
100
+ `Applying migration v${migration.version}: ${migration.name}`
73
101
  );
74
102
  await migration.up(client);
75
103
  await client.query(
76
- "INSERT INTO lattice_schema_migrations (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING",
77
- [migration.version, migration.name]
104
+ "INSERT INTO lattice_schema_migrations (name, version) VALUES ($1, $2) ON CONFLICT (name) DO NOTHING",
105
+ [migration.name, migration.version]
78
106
  );
79
107
  }
80
108
  await client.query("COMMIT");
@@ -90,34 +118,37 @@ var MigrationManager = class {
90
118
  }
91
119
  }
92
120
  /**
93
- * Rollback last migration
121
+ * Rollback the last-applied migration (highest version).
94
122
  */
95
123
  async rollback() {
96
124
  const client = await this.pool.connect();
97
125
  try {
98
126
  await client.query("BEGIN");
99
- const appliedMigrations = await this.getAppliedMigrations(client);
100
- if (appliedMigrations.length === 0) {
127
+ await this.ensureMigrationsTable(client);
128
+ const result = await client.query(
129
+ "SELECT name, version FROM lattice_schema_migrations ORDER BY version DESC LIMIT 1"
130
+ );
131
+ if (result.rows.length === 0) {
101
132
  console.log("No migrations to rollback");
102
133
  await client.query("COMMIT");
103
134
  return;
104
135
  }
105
- const lastMigration = appliedMigrations[appliedMigrations.length - 1];
136
+ const lastApplied = result.rows[0];
106
137
  const migration = this.migrations.find(
107
- (m) => m.version === lastMigration.version
138
+ (m) => m.name === lastApplied.name
108
139
  );
109
140
  if (!migration || !migration.down) {
110
141
  throw new Error(
111
- `Migration ${lastMigration.version} does not have a down migration`
142
+ `Migration "${lastApplied.name}" (v${lastApplied.version}) does not have a down migration`
112
143
  );
113
144
  }
114
145
  console.log(
115
- `Rolling back migration ${lastMigration.version}: ${lastMigration.name}`
146
+ `Rolling back migration v${lastApplied.version}: ${lastApplied.name}`
116
147
  );
117
148
  await migration.down(client);
118
149
  await client.query(
119
- "DELETE FROM lattice_schema_migrations WHERE version = $1",
120
- [lastMigration.version]
150
+ "DELETE FROM lattice_schema_migrations WHERE name = $1",
151
+ [lastApplied.name]
121
152
  );
122
153
  await client.query("COMMIT");
123
154
  console.log("Rollback completed");
@@ -129,22 +160,25 @@ var MigrationManager = class {
129
160
  }
130
161
  }
131
162
  /**
132
- * Get current migration version
163
+ * Get the highest applied migration version.
133
164
  */
134
165
  async getCurrentVersion() {
135
166
  const client = await this.pool.connect();
136
167
  try {
137
- const appliedMigrations = await this.getAppliedMigrations(client);
138
- if (appliedMigrations.length === 0) {
139
- return 0;
140
- }
141
- return Math.max(...appliedMigrations.map((m) => m.version));
168
+ await this.ensureMigrationsTable(client);
169
+ const result = await client.query(
170
+ "SELECT COALESCE(MAX(version), 0) AS max FROM lattice_schema_migrations"
171
+ );
172
+ return result.rows[0]?.max ?? 0;
142
173
  } finally {
143
174
  client.release();
144
175
  }
145
176
  }
146
177
  };
147
178
 
179
+ // src/stores/PostgreSQLThreadStore.ts
180
+ import { Pool } from "pg";
181
+
148
182
  // src/migrations/thread_migrations.ts
149
183
  var createThreadsTable = {
150
184
  version: 1,
@@ -285,10 +319,18 @@ var PostgreSQLThreadStore = class {
285
319
  this.initialized = false;
286
320
  this.ownsPool = true;
287
321
  this.initPromise = null;
322
+ if (options.pool) {
323
+ this.pool = options.pool;
324
+ this.ownsPool = false;
325
+ this.initialized = true;
326
+ return;
327
+ }
288
328
  if (typeof options.poolConfig === "string") {
289
329
  this.pool = new Pool({ connectionString: options.poolConfig });
290
- } else {
330
+ } else if (options.poolConfig) {
291
331
  this.pool = new Pool(options.poolConfig);
332
+ } else {
333
+ throw new Error("Either pool or poolConfig must be provided");
292
334
  }
293
335
  this.migrationManager = new MigrationManager(this.pool);
294
336
  this.migrationManager.register(createThreadsTable);
@@ -631,10 +673,18 @@ var PostgreSQLAssistantStore = class {
631
673
  this.initialized = false;
632
674
  this.ownsPool = true;
633
675
  this.initPromise = null;
676
+ if (options.pool) {
677
+ this.pool = options.pool;
678
+ this.ownsPool = false;
679
+ this.initialized = true;
680
+ return;
681
+ }
634
682
  if (typeof options.poolConfig === "string") {
635
683
  this.pool = new Pool2({ connectionString: options.poolConfig });
636
- } else {
684
+ } else if (options.poolConfig) {
637
685
  this.pool = new Pool2(options.poolConfig);
686
+ } else {
687
+ throw new Error("Either pool or poolConfig must be provided");
638
688
  }
639
689
  this.migrationManager = new MigrationManager(this.pool);
640
690
  this.migrationManager.register(createAssistantsTable);
@@ -911,11 +961,20 @@ import { encrypt, decrypt } from "@axiom-lattice/core";
911
961
  var PostgreSQLDatabaseConfigStore = class {
912
962
  constructor(options) {
913
963
  this.initialized = false;
964
+ this.ownsPool = true;
914
965
  this.initPromise = null;
966
+ if (options.pool) {
967
+ this.pool = options.pool;
968
+ this.ownsPool = false;
969
+ this.initialized = true;
970
+ return;
971
+ }
915
972
  if (typeof options.poolConfig === "string") {
916
973
  this.pool = new Pool3({ connectionString: options.poolConfig });
917
- } else {
974
+ } else if (options.poolConfig) {
918
975
  this.pool = new Pool3(options.poolConfig);
976
+ } else {
977
+ throw new Error("Either pool or poolConfig must be provided");
919
978
  }
920
979
  this.migrationManager = new MigrationManager(this.pool);
921
980
  this.migrationManager.register(createDatabaseConfigsTable);
@@ -1134,7 +1193,9 @@ var PostgreSQLDatabaseConfigStore = class {
1134
1193
  * Dispose resources and close the connection pool
1135
1194
  */
1136
1195
  async dispose() {
1137
- await this.pool.end();
1196
+ if (this.ownsPool && this.pool) {
1197
+ await this.pool.end();
1198
+ }
1138
1199
  }
1139
1200
  /**
1140
1201
  * Ensure store is initialized
@@ -1225,11 +1286,20 @@ import { encrypt as encrypt2, decrypt as decrypt2 } from "@axiom-lattice/core";
1225
1286
  var PostgreSQLMetricsServerConfigStore = class {
1226
1287
  constructor(options) {
1227
1288
  this.initialized = false;
1289
+ this.ownsPool = true;
1228
1290
  this.initPromise = null;
1291
+ if (options.pool) {
1292
+ this.pool = options.pool;
1293
+ this.ownsPool = false;
1294
+ this.initialized = true;
1295
+ return;
1296
+ }
1229
1297
  if (typeof options.poolConfig === "string") {
1230
1298
  this.pool = new Pool4({ connectionString: options.poolConfig });
1231
- } else {
1299
+ } else if (options.poolConfig) {
1232
1300
  this.pool = new Pool4(options.poolConfig);
1301
+ } else {
1302
+ throw new Error("Either pool or poolConfig must be provided");
1233
1303
  }
1234
1304
  this.migrationManager = new MigrationManager(this.pool);
1235
1305
  this.migrationManager.register(createMetricsConfigsTable);
@@ -1448,7 +1518,9 @@ var PostgreSQLMetricsServerConfigStore = class {
1448
1518
  * Dispose resources and close the connection pool
1449
1519
  */
1450
1520
  async dispose() {
1451
- await this.pool.end();
1521
+ if (this.ownsPool && this.pool) {
1522
+ await this.pool.end();
1523
+ }
1452
1524
  }
1453
1525
  /**
1454
1526
  * Ensure store is initialized
@@ -1558,11 +1630,20 @@ import { encrypt as encrypt3, decrypt as decrypt3 } from "@axiom-lattice/core";
1558
1630
  var PostgreSQLMcpServerConfigStore = class {
1559
1631
  constructor(options) {
1560
1632
  this.initialized = false;
1633
+ this.ownsPool = true;
1561
1634
  this.initPromise = null;
1635
+ if (options.pool) {
1636
+ this.pool = options.pool;
1637
+ this.ownsPool = false;
1638
+ this.initialized = true;
1639
+ return;
1640
+ }
1562
1641
  if (typeof options.poolConfig === "string") {
1563
1642
  this.pool = new Pool5({ connectionString: options.poolConfig });
1564
- } else {
1643
+ } else if (options.poolConfig) {
1565
1644
  this.pool = new Pool5(options.poolConfig);
1645
+ } else {
1646
+ throw new Error("Either pool or poolConfig must be provided");
1566
1647
  }
1567
1648
  this.migrationManager = new MigrationManager(this.pool);
1568
1649
  this.migrationManager.register(createMcpServerConfigsTable);
@@ -1797,7 +1878,9 @@ var PostgreSQLMcpServerConfigStore = class {
1797
1878
  * Dispose resources and close the connection pool
1798
1879
  */
1799
1880
  async dispose() {
1800
- await this.pool.end();
1881
+ if (this.ownsPool && this.pool) {
1882
+ await this.pool.end();
1883
+ }
1801
1884
  }
1802
1885
  /**
1803
1886
  * Ensure store is initialized
@@ -1898,10 +1981,18 @@ var PostgreSQLWorkspaceStore = class {
1898
1981
  constructor(options) {
1899
1982
  this.initialized = false;
1900
1983
  this.ownsPool = true;
1984
+ if (options.pool) {
1985
+ this.pool = options.pool;
1986
+ this.ownsPool = false;
1987
+ this.initialized = true;
1988
+ return;
1989
+ }
1901
1990
  if (typeof options.poolConfig === "string") {
1902
1991
  this.pool = new Pool6({ connectionString: options.poolConfig });
1903
- } else {
1992
+ } else if (options.poolConfig) {
1904
1993
  this.pool = new Pool6(options.poolConfig);
1994
+ } else {
1995
+ throw new Error("Either pool or poolConfig must be provided");
1905
1996
  }
1906
1997
  this.migrationManager = new MigrationManager(this.pool);
1907
1998
  this.migrationManager.register(createWorkspacesTable);
@@ -2141,10 +2232,18 @@ var PostgreSQLProjectStore = class {
2141
2232
  constructor(options) {
2142
2233
  this.initialized = false;
2143
2234
  this.ownsPool = true;
2235
+ if (options.pool) {
2236
+ this.pool = options.pool;
2237
+ this.ownsPool = false;
2238
+ this.initialized = true;
2239
+ return;
2240
+ }
2144
2241
  if (typeof options.poolConfig === "string") {
2145
2242
  this.pool = new Pool7({ connectionString: options.poolConfig });
2146
- } else {
2243
+ } else if (options.poolConfig) {
2147
2244
  this.pool = new Pool7(options.poolConfig);
2245
+ } else {
2246
+ throw new Error("Either pool or poolConfig must be provided");
2148
2247
  }
2149
2248
  this.migrationManager = new MigrationManager(this.pool);
2150
2249
  this.migrationManager.register(createProjectsTable);
@@ -2391,10 +2490,19 @@ var addUserStatusColumn = {
2391
2490
  var PostgreSQLUserStore = class {
2392
2491
  constructor(options) {
2393
2492
  this.initialized = false;
2493
+ this.ownsPool = true;
2494
+ if (options.pool) {
2495
+ this.pool = options.pool;
2496
+ this.ownsPool = false;
2497
+ this.initialized = true;
2498
+ return;
2499
+ }
2394
2500
  if (typeof options.poolConfig === "string") {
2395
2501
  this.pool = new Pool8({ connectionString: options.poolConfig });
2396
- } else {
2502
+ } else if (options.poolConfig) {
2397
2503
  this.pool = new Pool8(options.poolConfig);
2504
+ } else {
2505
+ throw new Error("Either pool or poolConfig must be provided");
2398
2506
  }
2399
2507
  this.migrationManager = new MigrationManager(this.pool);
2400
2508
  this.migrationManager.register(createUsersTable);
@@ -2407,7 +2515,9 @@ var PostgreSQLUserStore = class {
2407
2515
  }
2408
2516
  }
2409
2517
  async dispose() {
2410
- await this.pool.end();
2518
+ if (this.ownsPool && this.pool) {
2519
+ await this.pool.end();
2520
+ }
2411
2521
  }
2412
2522
  async initialize() {
2413
2523
  if (this.initialized) return;
@@ -2580,10 +2690,18 @@ var PostgreSQLTenantStore = class {
2580
2690
  constructor(options) {
2581
2691
  this.initialized = false;
2582
2692
  this.ownsPool = true;
2693
+ if (options.pool) {
2694
+ this.pool = options.pool;
2695
+ this.ownsPool = false;
2696
+ this.initialized = true;
2697
+ return;
2698
+ }
2583
2699
  if (typeof options.poolConfig === "string") {
2584
2700
  this.pool = new Pool9({ connectionString: options.poolConfig });
2585
- } else {
2701
+ } else if (options.poolConfig) {
2586
2702
  this.pool = new Pool9(options.poolConfig);
2703
+ } else {
2704
+ throw new Error("Either pool or poolConfig must be provided");
2587
2705
  }
2588
2706
  this.migrationManager = new MigrationManager(this.pool);
2589
2707
  this.migrationManager.register(createTenantsTable);
@@ -2833,10 +2951,19 @@ var migrateRemoveTenantIdFromUsers = {
2833
2951
  var PostgreSQLUserTenantLinkStore = class {
2834
2952
  constructor(options) {
2835
2953
  this.initialized = false;
2954
+ this.ownsPool = true;
2955
+ if (options.pool) {
2956
+ this.pool = options.pool;
2957
+ this.ownsPool = false;
2958
+ this.initialized = true;
2959
+ return;
2960
+ }
2836
2961
  if (typeof options.poolConfig === "string") {
2837
2962
  this.pool = new Pool10({ connectionString: options.poolConfig });
2838
- } else {
2963
+ } else if (options.poolConfig) {
2839
2964
  this.pool = new Pool10(options.poolConfig);
2965
+ } else {
2966
+ throw new Error("Either pool or poolConfig must be provided");
2840
2967
  }
2841
2968
  this.migrationManager = new MigrationManager(this.pool);
2842
2969
  this.migrationManager.register(createUserTenantLinkTable);
@@ -2849,7 +2976,9 @@ var PostgreSQLUserTenantLinkStore = class {
2849
2976
  }
2850
2977
  }
2851
2978
  async dispose() {
2852
- await this.pool.end();
2979
+ if (this.ownsPool && this.pool) {
2980
+ await this.pool.end();
2981
+ }
2853
2982
  }
2854
2983
  async initialize() {
2855
2984
  if (this.initialized) return;
@@ -3078,11 +3207,20 @@ var addStepThreadId = {
3078
3207
  var PostgreSQLWorkflowTrackingStore = class {
3079
3208
  constructor(options) {
3080
3209
  this.initialized = false;
3210
+ this.ownsPool = true;
3081
3211
  this.initPromise = null;
3212
+ if (options.pool) {
3213
+ this.pool = options.pool;
3214
+ this.ownsPool = false;
3215
+ this.initialized = true;
3216
+ return;
3217
+ }
3082
3218
  if (typeof options.poolConfig === "string") {
3083
3219
  this.pool = new Pool11({ connectionString: options.poolConfig });
3084
- } else {
3220
+ } else if (options.poolConfig) {
3085
3221
  this.pool = new Pool11(options.poolConfig);
3222
+ } else {
3223
+ throw new Error("Either pool or poolConfig must be provided");
3086
3224
  }
3087
3225
  this.migrationManager = new MigrationManager(this.pool);
3088
3226
  this.migrationManager.register(createWorkflowTrackingTables);
@@ -3095,7 +3233,9 @@ var PostgreSQLWorkflowTrackingStore = class {
3095
3233
  }
3096
3234
  }
3097
3235
  async dispose() {
3098
- await this.pool.end();
3236
+ if (this.ownsPool && this.pool) {
3237
+ await this.pool.end();
3238
+ }
3099
3239
  }
3100
3240
  async initialize() {
3101
3241
  if (this.initialized) return;
@@ -3584,10 +3724,18 @@ var PostgreSQLEvalStore = class {
3584
3724
  this.initialized = false;
3585
3725
  this.ownsPool = true;
3586
3726
  this.initPromise = null;
3727
+ if (options.pool) {
3728
+ this.pool = options.pool;
3729
+ this.ownsPool = false;
3730
+ this.initialized = true;
3731
+ return;
3732
+ }
3587
3733
  if (typeof options.poolConfig === "string") {
3588
3734
  this.pool = new Pool12({ connectionString: options.poolConfig });
3589
- } else {
3735
+ } else if (options.poolConfig) {
3590
3736
  this.pool = new Pool12(options.poolConfig);
3737
+ } else {
3738
+ throw new Error("Either pool or poolConfig must be provided");
3591
3739
  }
3592
3740
  this.migrationManager = new MigrationManager(this.pool);
3593
3741
  for (const m of evalMigrations) {
@@ -4450,10 +4598,18 @@ var ThreadMessageQueueStore = class {
4450
4598
  this.ownsPool = true;
4451
4599
  this.initialized = false;
4452
4600
  this.initPromise = null;
4601
+ if (options.pool) {
4602
+ this.pool = options.pool;
4603
+ this.ownsPool = false;
4604
+ this.initialized = true;
4605
+ return;
4606
+ }
4453
4607
  if (typeof options.poolConfig === "string") {
4454
4608
  this.pool = new Pool13({ connectionString: options.poolConfig });
4455
- } else {
4609
+ } else if (options.poolConfig) {
4456
4610
  this.pool = new Pool13(options.poolConfig);
4611
+ } else {
4612
+ throw new Error("Either pool or poolConfig must be provided");
4457
4613
  }
4458
4614
  this.migrationManager = new MigrationManager(this.pool);
4459
4615
  this.migrationManager.register(createThreadMessageQueueTable);
@@ -4692,8 +4848,17 @@ var createChannelBindingsTable = {
4692
4848
  var ChannelBindingStore = class {
4693
4849
  constructor(options) {
4694
4850
  this.initialized = false;
4851
+ this.ownsPool = true;
4695
4852
  this.initPromise = null;
4696
- this.pool = typeof options.poolConfig === "string" ? new Pool14({ connectionString: options.poolConfig }) : new Pool14(options.poolConfig);
4853
+ if (options.pool) {
4854
+ this.pool = options.pool;
4855
+ this.ownsPool = false;
4856
+ this.initialized = true;
4857
+ return;
4858
+ }
4859
+ this.pool = typeof options.poolConfig === "string" ? new Pool14({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool14(options.poolConfig) : (() => {
4860
+ throw new Error("Either pool or poolConfig must be provided");
4861
+ })();
4697
4862
  this.migrationManager = new MigrationManager(this.pool);
4698
4863
  this.migrationManager.register(createChannelBindingsTable);
4699
4864
  if (options.autoMigrate !== false) {
@@ -4716,6 +4881,11 @@ var ChannelBindingStore = class {
4716
4881
  })();
4717
4882
  return this.initPromise;
4718
4883
  }
4884
+ async dispose() {
4885
+ if (this.ownsPool && this.pool) {
4886
+ await this.pool.end();
4887
+ }
4888
+ }
4719
4889
  async resolve(params) {
4720
4890
  await this.ensureInitialized();
4721
4891
  const result = await this.pool.query(
@@ -4939,8 +5109,17 @@ import { decrypt as decrypt4, encrypt as encrypt4 } from "@axiom-lattice/core";
4939
5109
  var PostgreSQLChannelInstallationStore = class {
4940
5110
  constructor(options) {
4941
5111
  this.initialized = false;
5112
+ this.ownsPool = true;
4942
5113
  this.initPromise = null;
4943
- this.pool = typeof options.poolConfig === "string" ? new Pool15({ connectionString: options.poolConfig }) : new Pool15(options.poolConfig);
5114
+ if (options.pool) {
5115
+ this.pool = options.pool;
5116
+ this.ownsPool = false;
5117
+ this.initialized = true;
5118
+ return;
5119
+ }
5120
+ this.pool = typeof options.poolConfig === "string" ? new Pool15({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool15(options.poolConfig) : (() => {
5121
+ throw new Error("Either pool or poolConfig must be provided");
5122
+ })();
4944
5123
  this.migrationManager = new MigrationManager(this.pool);
4945
5124
  this.migrationManager.register(createChannelInstallationsTable);
4946
5125
  this.migrationManager.register(alterChannelInstallationsTable);
@@ -4971,6 +5150,11 @@ var PostgreSQLChannelInstallationStore = class {
4971
5150
  })();
4972
5151
  return this.initPromise;
4973
5152
  }
5153
+ async dispose() {
5154
+ if (this.ownsPool && this.pool) {
5155
+ await this.pool.end();
5156
+ }
5157
+ }
4974
5158
  async getInstallationById(installationId) {
4975
5159
  await this.ensureInitialized();
4976
5160
  const result = await this.pool.query(
@@ -5215,8 +5399,17 @@ function mapRowToRecord(row) {
5215
5399
  var PostgreSQLA2AApiKeyStore = class {
5216
5400
  constructor(options) {
5217
5401
  this.initialized = false;
5402
+ this.ownsPool = true;
5218
5403
  this.initPromise = null;
5219
- this.pool = typeof options.poolConfig === "string" ? new Pool16({ connectionString: options.poolConfig }) : new Pool16(options.poolConfig);
5404
+ if (options.pool) {
5405
+ this.pool = options.pool;
5406
+ this.ownsPool = false;
5407
+ this.initialized = true;
5408
+ return;
5409
+ }
5410
+ this.pool = typeof options.poolConfig === "string" ? new Pool16({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool16(options.poolConfig) : (() => {
5411
+ throw new Error("Either pool or poolConfig must be provided");
5412
+ })();
5220
5413
  this.migrationManager = new MigrationManager(this.pool);
5221
5414
  this.migrationManager.register(createA2AApiKeysTable);
5222
5415
  if (options.autoMigrate !== false) {
@@ -5239,6 +5432,11 @@ var PostgreSQLA2AApiKeyStore = class {
5239
5432
  })();
5240
5433
  return this.initPromise;
5241
5434
  }
5435
+ async dispose() {
5436
+ if (this.ownsPool && this.pool) {
5437
+ await this.pool.end();
5438
+ }
5439
+ }
5242
5440
  async ensureInitialized() {
5243
5441
  if (!this.initialized) await this.initialize();
5244
5442
  }
@@ -5504,10 +5702,19 @@ var addScheduleTenantId = {
5504
5702
  var PostgreSQLScheduleStorage = class {
5505
5703
  constructor(options) {
5506
5704
  this.initialized = false;
5705
+ this.ownsPool = true;
5706
+ if (options.pool) {
5707
+ this.pool = options.pool;
5708
+ this.ownsPool = false;
5709
+ this.initialized = true;
5710
+ return;
5711
+ }
5507
5712
  if (typeof options.poolConfig === "string") {
5508
5713
  this.pool = new Pool17({ connectionString: options.poolConfig });
5509
- } else {
5714
+ } else if (options.poolConfig) {
5510
5715
  this.pool = new Pool17(options.poolConfig);
5716
+ } else {
5717
+ throw new Error("Either pool or poolConfig must be provided");
5511
5718
  }
5512
5719
  this.migrationManager = new MigrationManager(this.pool);
5513
5720
  this.migrationManager.register(createScheduledTasksTable);
@@ -5523,7 +5730,7 @@ var PostgreSQLScheduleStorage = class {
5523
5730
  * Dispose resources and close the connection pool
5524
5731
  */
5525
5732
  async dispose() {
5526
- if (this.pool) {
5733
+ if (this.ownsPool && this.pool) {
5527
5734
  await this.pool.end();
5528
5735
  }
5529
5736
  }
@@ -6017,10 +6224,18 @@ var PostgreSQLTaskStore = class {
6017
6224
  this.initialized = false;
6018
6225
  this.ownsPool = true;
6019
6226
  this.initPromise = null;
6227
+ if (options.pool) {
6228
+ this.pool = options.pool;
6229
+ this.ownsPool = false;
6230
+ this.initialized = true;
6231
+ return;
6232
+ }
6020
6233
  if (typeof options.poolConfig === "string") {
6021
6234
  this.pool = new Pool18({ connectionString: options.poolConfig });
6022
- } else {
6235
+ } else if (options.poolConfig) {
6023
6236
  this.pool = new Pool18(options.poolConfig);
6237
+ } else {
6238
+ throw new Error("Either pool or poolConfig must be provided");
6024
6239
  }
6025
6240
  this.migrationManager = new MigrationManager(this.pool);
6026
6241
  this.migrationManager.register(createTasksTable);
@@ -6284,8 +6499,17 @@ var addFileContentType = {
6284
6499
  var MenuStore = class {
6285
6500
  constructor(options) {
6286
6501
  this.initialized = false;
6502
+ this.ownsPool = true;
6287
6503
  this.initPromise = null;
6288
- this.pool = typeof options.poolConfig === "string" ? new Pool19({ connectionString: options.poolConfig }) : new Pool19(options.poolConfig);
6504
+ if (options.pool) {
6505
+ this.pool = options.pool;
6506
+ this.ownsPool = false;
6507
+ this.initialized = true;
6508
+ return;
6509
+ }
6510
+ this.pool = typeof options.poolConfig === "string" ? new Pool19({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool19(options.poolConfig) : (() => {
6511
+ throw new Error("Either pool or poolConfig must be provided");
6512
+ })();
6289
6513
  this.migrationManager = new MigrationManager(this.pool);
6290
6514
  this.migrationManager.register(createMenuItemsTable);
6291
6515
  this.migrationManager.register(addFileContentType);
@@ -6309,6 +6533,11 @@ var MenuStore = class {
6309
6533
  })();
6310
6534
  return this.initPromise;
6311
6535
  }
6536
+ async dispose() {
6537
+ if (this.ownsPool && this.pool) {
6538
+ await this.pool.end();
6539
+ }
6540
+ }
6312
6541
  async list(params) {
6313
6542
  await this.ensureInitialized();
6314
6543
  const conditions = ["tenant_id = $1"];
@@ -6479,8 +6708,17 @@ var createSharedResourcesTable = {
6479
6708
  var PostgresSharedResourceStore = class {
6480
6709
  constructor(options) {
6481
6710
  this.initialized = false;
6711
+ this.ownsPool = true;
6482
6712
  this.initPromise = null;
6483
- this.pool = typeof options.poolConfig === "string" ? new Pool20({ connectionString: options.poolConfig }) : new Pool20(options.poolConfig);
6713
+ if (options.pool) {
6714
+ this.pool = options.pool;
6715
+ this.ownsPool = false;
6716
+ this.initialized = true;
6717
+ return;
6718
+ }
6719
+ this.pool = typeof options.poolConfig === "string" ? new Pool20({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool20(options.poolConfig) : (() => {
6720
+ throw new Error("Either pool or poolConfig must be provided");
6721
+ })();
6484
6722
  this.migrationManager = new MigrationManager(this.pool);
6485
6723
  this.migrationManager.register(createSharedResourcesTable);
6486
6724
  if (options.autoMigrate !== false) {
@@ -6506,6 +6744,11 @@ var PostgresSharedResourceStore = class {
6506
6744
  })();
6507
6745
  return this.initPromise;
6508
6746
  }
6747
+ async dispose() {
6748
+ if (this.ownsPool && this.pool) {
6749
+ await this.pool.end();
6750
+ }
6751
+ }
6509
6752
  async findByToken(token) {
6510
6753
  await this.ensureInitialized();
6511
6754
  const { rows } = await this.pool.query(
@@ -6643,39 +6886,6 @@ var PostgresSharedResourceStore = class {
6643
6886
 
6644
6887
  // src/createPgStoreConfig.ts
6645
6888
  import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
6646
- function createPgStoreConfig(connectionString) {
6647
- const opts = { poolConfig: connectionString, autoMigrate: true };
6648
- const checkpoint = PostgresSaver.fromConnString(connectionString);
6649
- checkpoint.setup().catch((err) => {
6650
- console.error("[pg-stores] Failed to setup checkpoint table:", err.message || err);
6651
- });
6652
- return {
6653
- workspace: new PostgreSQLWorkspaceStore(opts),
6654
- project: new PostgreSQLProjectStore(opts),
6655
- eval: new PostgreSQLEvalStore(opts),
6656
- user: new PostgreSQLUserStore(opts),
6657
- tenant: new PostgreSQLTenantStore(opts),
6658
- userTenantLink: new PostgreSQLUserTenantLinkStore(opts),
6659
- channelBinding: new ChannelBindingStore(opts),
6660
- channelInstallation: new PostgreSQLChannelInstallationStore(opts),
6661
- thread: new PostgreSQLThreadStore(opts),
6662
- database: new PostgreSQLDatabaseConfigStore(opts),
6663
- metrics: new PostgreSQLMetricsServerConfigStore(opts),
6664
- mcp: new PostgreSQLMcpServerConfigStore(opts),
6665
- assistant: new PostgreSQLAssistantStore(opts),
6666
- workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
6667
- threadMessageQueue: new ThreadMessageQueueStore(opts),
6668
- task: new PostgreSQLTaskStore(opts),
6669
- a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
6670
- schedule: new PostgreSQLScheduleStorage(opts),
6671
- menu: new MenuStore(opts),
6672
- sharedResource: new PostgresSharedResourceStore(opts),
6673
- checkpoint
6674
- };
6675
- }
6676
-
6677
- // src/stores/PostgreSQLSkillStore.ts
6678
- import { Pool as Pool21 } from "pg";
6679
6889
 
6680
6890
  // src/migrations/skill_migrations.ts
6681
6891
  var createSkillsTable = {
@@ -6830,16 +7040,157 @@ var changeSkillPrimaryKey = {
6830
7040
  }
6831
7041
  };
6832
7042
 
7043
+ // src/migrations/channel_identity_mapping_migration.ts
7044
+ var createChannelIdentityMappingTables = {
7045
+ version: 20,
7046
+ name: "create_channel_identity_mapping_tables",
7047
+ up: async (client) => {
7048
+ await client.query(`
7049
+ CREATE TABLE IF NOT EXISTS channel_identity_mappings (
7050
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7051
+ channel VARCHAR(50) NOT NULL,
7052
+ channel_app_id VARCHAR(255) NOT NULL,
7053
+ tenant_id VARCHAR(255) NOT NULL,
7054
+ assistant_id VARCHAR(255) NOT NULL,
7055
+ mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
7056
+ external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
7057
+ external_subject_key VARCHAR(512) NOT NULL,
7058
+ lark_open_id VARCHAR(255),
7059
+ lark_chat_id VARCHAR(255) NOT NULL,
7060
+ lark_message_id VARCHAR(255),
7061
+ thread_id VARCHAR(255) NOT NULL,
7062
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7063
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7064
+ last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7065
+ UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7066
+ )
7067
+ `);
7068
+ await client.query(`
7069
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
7070
+ ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7071
+ `);
7072
+ await client.query(`
7073
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
7074
+ ON channel_identity_mappings(thread_id, tenant_id)
7075
+ `);
7076
+ await client.query(`
7077
+ CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
7078
+ channel VARCHAR(50) NOT NULL,
7079
+ channel_app_id VARCHAR(255) NOT NULL,
7080
+ external_message_id VARCHAR(255) NOT NULL,
7081
+ tenant_id VARCHAR(255) NOT NULL,
7082
+ status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
7083
+ thread_id VARCHAR(255),
7084
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7085
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7086
+ PRIMARY KEY (channel, channel_app_id, external_message_id)
7087
+ )
7088
+ `);
7089
+ },
7090
+ down: async (client) => {
7091
+ await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
7092
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
7093
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
7094
+ await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
7095
+ }
7096
+ };
7097
+
7098
+ // src/createPgStoreConfig.ts
7099
+ async function createPgStoreConfig(connectionString) {
7100
+ const pool = new Pool21({ connectionString });
7101
+ const mm = new MigrationManager(pool);
7102
+ mm.register(createThreadsTable);
7103
+ mm.register(createScheduledTasksTable);
7104
+ mm.register(createAssistantsTable);
7105
+ mm.register(createSkillsTable);
7106
+ mm.register(createWorkspacesTable);
7107
+ mm.register(createProjectsTable);
7108
+ mm.register(createUsersTable);
7109
+ mm.register(createTenantsTable);
7110
+ mm.register(addUserStatusColumn);
7111
+ mm.register(createUserTenantLinkTable);
7112
+ mm.register(migrateRemoveTenantIdFromUsers);
7113
+ mm.register(createMetricsConfigsTable);
7114
+ mm.register(createMcpServerConfigsTable);
7115
+ mm.register(addAssistantTenantId);
7116
+ mm.register(addSkillTenantId);
7117
+ mm.register(changeSkillPrimaryKey);
7118
+ mm.register(addScheduleTenantId);
7119
+ mm.register(changeThreadPrimaryKey);
7120
+ mm.register(createChannelIdentityMappingTables);
7121
+ mm.register(createChannelInstallationsTable);
7122
+ mm.register(addThreadTenantId);
7123
+ mm.register(addProjectConfigColumn);
7124
+ mm.register(createThreadMessageQueueTable);
7125
+ mm.register(addPriorityAndCommandColumns);
7126
+ mm.register(alterMessageQueueIdColumn);
7127
+ mm.register(createWorkflowTrackingTables);
7128
+ for (const m of evalMigrations) {
7129
+ mm.register(m);
7130
+ }
7131
+ mm.register(alterChannelInstallationsTable);
7132
+ mm.register(createChannelBindingsTable);
7133
+ mm.register(createDatabaseConfigsTable);
7134
+ mm.register(changeAssistantPrimaryKey);
7135
+ mm.register(addStepThreadId);
7136
+ mm.register(addCustomRunConfigColumn);
7137
+ mm.register(createA2AApiKeysTable);
7138
+ mm.register(addWorkspaceProjectToQueue);
7139
+ mm.register(addAssistantOwnerUserId);
7140
+ mm.register(createTasksTable);
7141
+ mm.register(createMenuItemsTable);
7142
+ mm.register(createSharedResourcesTable);
7143
+ mm.register(addFileContentType);
7144
+ await mm.migrate();
7145
+ const checkpoint = PostgresSaver.fromConnString(connectionString);
7146
+ checkpoint.setup().catch((err) => {
7147
+ console.error("[pg-stores] Failed to setup checkpoint table:", err.message || err);
7148
+ });
7149
+ const opts = { pool };
7150
+ return {
7151
+ workspace: new PostgreSQLWorkspaceStore(opts),
7152
+ project: new PostgreSQLProjectStore(opts),
7153
+ eval: new PostgreSQLEvalStore(opts),
7154
+ user: new PostgreSQLUserStore(opts),
7155
+ tenant: new PostgreSQLTenantStore(opts),
7156
+ userTenantLink: new PostgreSQLUserTenantLinkStore(opts),
7157
+ channelBinding: new ChannelBindingStore(opts),
7158
+ channelInstallation: new PostgreSQLChannelInstallationStore(opts),
7159
+ thread: new PostgreSQLThreadStore(opts),
7160
+ database: new PostgreSQLDatabaseConfigStore(opts),
7161
+ metrics: new PostgreSQLMetricsServerConfigStore(opts),
7162
+ mcp: new PostgreSQLMcpServerConfigStore(opts),
7163
+ assistant: new PostgreSQLAssistantStore(opts),
7164
+ workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
7165
+ threadMessageQueue: new ThreadMessageQueueStore(opts),
7166
+ task: new PostgreSQLTaskStore(opts),
7167
+ a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
7168
+ schedule: new PostgreSQLScheduleStorage(opts),
7169
+ menu: new MenuStore(opts),
7170
+ sharedResource: new PostgresSharedResourceStore(opts),
7171
+ checkpoint
7172
+ };
7173
+ }
7174
+
6833
7175
  // src/stores/PostgreSQLSkillStore.ts
7176
+ import { Pool as Pool22 } from "pg";
6834
7177
  var PostgreSQLSkillStore = class {
6835
7178
  constructor(options) {
6836
7179
  this.initialized = false;
6837
7180
  this.ownsPool = true;
6838
7181
  this.initPromise = null;
7182
+ if (options.pool) {
7183
+ this.pool = options.pool;
7184
+ this.ownsPool = false;
7185
+ this.initialized = true;
7186
+ return;
7187
+ }
6839
7188
  if (typeof options.poolConfig === "string") {
6840
- this.pool = new Pool21({ connectionString: options.poolConfig });
7189
+ this.pool = new Pool22({ connectionString: options.poolConfig });
7190
+ } else if (options.poolConfig) {
7191
+ this.pool = new Pool22(options.poolConfig);
6841
7192
  } else {
6842
- this.pool = new Pool21(options.poolConfig);
7193
+ throw new Error("Either pool or poolConfig must be provided");
6843
7194
  }
6844
7195
  this.migrationManager = new MigrationManager(this.pool);
6845
7196
  this.migrationManager.register(createSkillsTable);
@@ -7137,68 +7488,22 @@ var PostgreSQLSkillStore = class {
7137
7488
  }
7138
7489
  };
7139
7490
 
7140
- // src/migrations/channel_identity_mapping_migration.ts
7141
- var createChannelIdentityMappingTables = {
7142
- version: 20,
7143
- name: "create_channel_identity_mapping_tables",
7144
- up: async (client) => {
7145
- await client.query(`
7146
- CREATE TABLE IF NOT EXISTS channel_identity_mappings (
7147
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7148
- channel VARCHAR(50) NOT NULL,
7149
- channel_app_id VARCHAR(255) NOT NULL,
7150
- tenant_id VARCHAR(255) NOT NULL,
7151
- assistant_id VARCHAR(255) NOT NULL,
7152
- mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
7153
- external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
7154
- external_subject_key VARCHAR(512) NOT NULL,
7155
- lark_open_id VARCHAR(255),
7156
- lark_chat_id VARCHAR(255) NOT NULL,
7157
- lark_message_id VARCHAR(255),
7158
- thread_id VARCHAR(255) NOT NULL,
7159
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7160
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7161
- last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7162
- UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7163
- )
7164
- `);
7165
- await client.query(`
7166
- CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
7167
- ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7168
- `);
7169
- await client.query(`
7170
- CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
7171
- ON channel_identity_mappings(thread_id, tenant_id)
7172
- `);
7173
- await client.query(`
7174
- CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
7175
- channel VARCHAR(50) NOT NULL,
7176
- channel_app_id VARCHAR(255) NOT NULL,
7177
- external_message_id VARCHAR(255) NOT NULL,
7178
- tenant_id VARCHAR(255) NOT NULL,
7179
- status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
7180
- thread_id VARCHAR(255),
7181
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7182
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7183
- PRIMARY KEY (channel, channel_app_id, external_message_id)
7184
- )
7185
- `);
7186
- },
7187
- down: async (client) => {
7188
- await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
7189
- await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
7190
- await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
7191
- await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
7192
- }
7193
- };
7194
-
7195
7491
  // src/stores/ChannelIdentityMappingStore.ts
7196
- import { Pool as Pool22 } from "pg";
7492
+ import { Pool as Pool23 } from "pg";
7197
7493
  var ChannelIdentityMappingStore = class {
7198
7494
  constructor(options) {
7199
7495
  this.initialized = false;
7496
+ this.ownsPool = true;
7200
7497
  this.initPromise = null;
7201
- this.pool = typeof options.poolConfig === "string" ? new Pool22({ connectionString: options.poolConfig }) : new Pool22(options.poolConfig);
7498
+ if (options.pool) {
7499
+ this.pool = options.pool;
7500
+ this.ownsPool = false;
7501
+ this.initialized = true;
7502
+ return;
7503
+ }
7504
+ this.pool = typeof options.poolConfig === "string" ? new Pool23({ connectionString: options.poolConfig }) : options.poolConfig ? new Pool23(options.poolConfig) : (() => {
7505
+ throw new Error("Either pool or poolConfig must be provided");
7506
+ })();
7202
7507
  this.migrationManager = new MigrationManager(this.pool);
7203
7508
  this.migrationManager.register(createChannelIdentityMappingTables);
7204
7509
  if (options.autoMigrate !== false) {
@@ -7225,6 +7530,11 @@ var ChannelIdentityMappingStore = class {
7225
7530
  })();
7226
7531
  return this.initPromise;
7227
7532
  }
7533
+ async dispose() {
7534
+ if (this.ownsPool && this.pool) {
7535
+ await this.pool.end();
7536
+ }
7537
+ }
7228
7538
  async createMapping(input) {
7229
7539
  await this.ensureInitialized();
7230
7540
  const result = await this.pool.query(
@@ -7414,7 +7724,7 @@ export {
7414
7724
  ChannelIdentityMappingStore,
7415
7725
  MenuStore,
7416
7726
  MigrationManager,
7417
- Pool23 as Pool,
7727
+ Pool24 as Pool,
7418
7728
  PostgreSQLA2AApiKeyStore,
7419
7729
  PostgreSQLAssistantStore,
7420
7730
  PostgreSQLChannelInstallationStore,