@axiom-lattice/pg-stores 3.1.6 → 3.1.8
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +20 -0
- package/dist/index.d.mts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/PostgreSQLMcpServerConfigStore.test.ts +79 -0
- package/src/__tests__/PostgreSQLProjectRoomReadStateStore.test.ts +136 -0
- package/src/createPgStoreConfig.ts +4 -1
- package/src/index.ts +1 -0
- package/src/migrations/project_room_migration.ts +26 -0
- package/src/stores/PostgreSQLMcpServerConfigStore.ts +23 -0
- package/src/stores/PostgreSQLProjectRoomMessageStore.ts +16 -0
- package/src/stores/PostgreSQLProjectRoomReadStateStore.ts +47 -0
package/dist/index.mjs
CHANGED
|
@@ -2016,6 +2016,18 @@ var PostgreSQLMcpServerConfigStore = class {
|
|
|
2016
2016
|
throw new Error("Failed to decrypt MCP server configuration");
|
|
2017
2017
|
}
|
|
2018
2018
|
}
|
|
2019
|
+
if (config.headers && row.is_env_encrypted) {
|
|
2020
|
+
try {
|
|
2021
|
+
const decryptedHeaders = {};
|
|
2022
|
+
for (const [key, value] of Object.entries(config.headers)) {
|
|
2023
|
+
decryptedHeaders[key] = decrypt3(value);
|
|
2024
|
+
}
|
|
2025
|
+
config.headers = decryptedHeaders;
|
|
2026
|
+
} catch (error) {
|
|
2027
|
+
console.error("Failed to decrypt MCP server headers:", error);
|
|
2028
|
+
throw new Error("Failed to decrypt MCP server configuration");
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2019
2031
|
return {
|
|
2020
2032
|
id: row.id,
|
|
2021
2033
|
tenantId: row.tenant_id,
|
|
@@ -2044,6 +2056,14 @@ var PostgreSQLMcpServerConfigStore = class {
|
|
|
2044
2056
|
configCopy.env = encryptedEnv;
|
|
2045
2057
|
isEnvEncrypted = true;
|
|
2046
2058
|
}
|
|
2059
|
+
if (configCopy.headers && Object.keys(configCopy.headers).length > 0) {
|
|
2060
|
+
const encryptedHeaders = {};
|
|
2061
|
+
for (const [key, value] of Object.entries(configCopy.headers)) {
|
|
2062
|
+
encryptedHeaders[key] = encrypt3(value);
|
|
2063
|
+
}
|
|
2064
|
+
configCopy.headers = encryptedHeaders;
|
|
2065
|
+
isEnvEncrypted = true;
|
|
2066
|
+
}
|
|
2047
2067
|
return { config: configCopy, isEnvEncrypted };
|
|
2048
2068
|
}
|
|
2049
2069
|
};
|
|
@@ -9586,6 +9606,30 @@ var createProjectRoomTables = {
|
|
|
9586
9606
|
await client.query("DROP TABLE IF EXISTS lattice_project_rooms");
|
|
9587
9607
|
}
|
|
9588
9608
|
};
|
|
9609
|
+
var createProjectRoomReadStates = {
|
|
9610
|
+
version: 177,
|
|
9611
|
+
name: "create_project_room_read_states",
|
|
9612
|
+
up: async (client) => {
|
|
9613
|
+
await client.query(`
|
|
9614
|
+
CREATE TABLE IF NOT EXISTS lattice_project_room_read_states (
|
|
9615
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
9616
|
+
room_id VARCHAR(255) NOT NULL,
|
|
9617
|
+
user_id VARCHAR(255) NOT NULL,
|
|
9618
|
+
last_read_at TIMESTAMPTZ NOT NULL,
|
|
9619
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
9620
|
+
PRIMARY KEY (tenant_id, room_id, user_id)
|
|
9621
|
+
)
|
|
9622
|
+
`);
|
|
9623
|
+
await client.query(`
|
|
9624
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_project_room_read_states_user
|
|
9625
|
+
ON lattice_project_room_read_states (tenant_id, user_id)
|
|
9626
|
+
`);
|
|
9627
|
+
},
|
|
9628
|
+
down: async (client) => {
|
|
9629
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_project_room_read_states_user");
|
|
9630
|
+
await client.query("DROP TABLE IF EXISTS lattice_project_room_read_states");
|
|
9631
|
+
}
|
|
9632
|
+
};
|
|
9589
9633
|
|
|
9590
9634
|
// src/stores/PostgreSQLCapabilityBundleStore.ts
|
|
9591
9635
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -10373,6 +10417,19 @@ var PostgreSQLProjectRoomMessageStore = class {
|
|
|
10373
10417
|
);
|
|
10374
10418
|
return result.rows[0] ? mapRow5(result.rows[0]) : null;
|
|
10375
10419
|
}
|
|
10420
|
+
/** Counts messages created strictly after a horizon, optionally excluding one human author. */
|
|
10421
|
+
async countAfter(input) {
|
|
10422
|
+
if (!(input.after instanceof Date) || Number.isNaN(input.after.getTime())) {
|
|
10423
|
+
throw new RangeError("Project room message count horizon date is invalid");
|
|
10424
|
+
}
|
|
10425
|
+
const result = await this.pool.query(
|
|
10426
|
+
`SELECT COUNT(*)::int AS count FROM lattice_project_room_messages
|
|
10427
|
+
WHERE tenant_id = $1 AND room_id = $2 AND created_at > $3
|
|
10428
|
+
AND ($4::text IS NULL OR author->>'type' <> 'human' OR author->>'userId' <> $4)`,
|
|
10429
|
+
[input.tenantId, input.roomId, input.after, input.excludeAuthorUserId ?? null]
|
|
10430
|
+
);
|
|
10431
|
+
return result.rows[0]?.count ?? 0;
|
|
10432
|
+
}
|
|
10376
10433
|
parameters(input) {
|
|
10377
10434
|
return [
|
|
10378
10435
|
input.id,
|
|
@@ -10391,6 +10448,45 @@ var PostgreSQLProjectRoomMessageStore = class {
|
|
|
10391
10448
|
}
|
|
10392
10449
|
};
|
|
10393
10450
|
|
|
10451
|
+
// src/stores/PostgreSQLProjectRoomReadStateStore.ts
|
|
10452
|
+
function mapRow6(row) {
|
|
10453
|
+
if (typeof row.tenant_id !== "string" || typeof row.room_id !== "string" || typeof row.user_id !== "string" || !(row.last_read_at instanceof Date) || Number.isNaN(row.last_read_at.getTime()) || !(row.updated_at instanceof Date) || Number.isNaN(row.updated_at.getTime())) {
|
|
10454
|
+
throw new Error("Invalid project room read state row");
|
|
10455
|
+
}
|
|
10456
|
+
return { tenantId: row.tenant_id, roomId: row.room_id, userId: row.user_id, lastReadAt: row.last_read_at, updatedAt: row.updated_at };
|
|
10457
|
+
}
|
|
10458
|
+
var PostgreSQLProjectRoomReadStateStore = class {
|
|
10459
|
+
/** Creates a store using an externally managed shared pool. */
|
|
10460
|
+
constructor(options) {
|
|
10461
|
+
this.pool = options.pool;
|
|
10462
|
+
}
|
|
10463
|
+
/** Returns the user's read marker for a room, or null when never reported. */
|
|
10464
|
+
async get(tenantId, roomId, userId) {
|
|
10465
|
+
const result = await this.pool.query(
|
|
10466
|
+
`SELECT tenant_id, room_id, user_id, last_read_at, updated_at
|
|
10467
|
+
FROM lattice_project_room_read_states WHERE tenant_id = $1 AND room_id = $2 AND user_id = $3`,
|
|
10468
|
+
[tenantId, roomId, userId]
|
|
10469
|
+
);
|
|
10470
|
+
return result.rows[0] ? mapRow6(result.rows[0]) : null;
|
|
10471
|
+
}
|
|
10472
|
+
/** Upserts the marker monotonically using GREATEST so older reports never regress it. */
|
|
10473
|
+
async markRead(input) {
|
|
10474
|
+
if (!(input.lastReadAt instanceof Date) || Number.isNaN(input.lastReadAt.getTime())) {
|
|
10475
|
+
throw new RangeError("Project room read state lastReadAt is invalid");
|
|
10476
|
+
}
|
|
10477
|
+
const result = await this.pool.query(
|
|
10478
|
+
`INSERT INTO lattice_project_room_read_states (tenant_id, room_id, user_id, last_read_at, updated_at)
|
|
10479
|
+
VALUES ($1, $2, $3, $4, NOW())
|
|
10480
|
+
ON CONFLICT (tenant_id, room_id, user_id) DO UPDATE
|
|
10481
|
+
SET last_read_at = GREATEST(lattice_project_room_read_states.last_read_at, EXCLUDED.last_read_at),
|
|
10482
|
+
updated_at = NOW()
|
|
10483
|
+
RETURNING tenant_id, room_id, user_id, last_read_at, updated_at`,
|
|
10484
|
+
[input.tenantId, input.roomId, input.userId, input.lastReadAt]
|
|
10485
|
+
);
|
|
10486
|
+
return mapRow6(result.rows[0]);
|
|
10487
|
+
}
|
|
10488
|
+
};
|
|
10489
|
+
|
|
10394
10490
|
// src/createPgStoreConfig.ts
|
|
10395
10491
|
async function createPgStoreConfig(connectionString) {
|
|
10396
10492
|
const pool = new Pool26({ connectionString });
|
|
@@ -10454,6 +10550,7 @@ async function createPgStoreConfig(connectionString) {
|
|
|
10454
10550
|
mm.register(addTrustedRunContextColumn);
|
|
10455
10551
|
mm.register(addProjectLifecycleEventIndex);
|
|
10456
10552
|
mm.register(addAgentWebAppsIdentity);
|
|
10553
|
+
mm.register(createProjectRoomReadStates);
|
|
10457
10554
|
await mm.migrate();
|
|
10458
10555
|
const checkpoint = PostgresSaver.fromConnString(connectionString);
|
|
10459
10556
|
checkpoint.setup().catch((err) => {
|
|
@@ -10491,6 +10588,7 @@ async function createPgStoreConfig(connectionString) {
|
|
|
10491
10588
|
projectMembership: new PostgreSQLProjectMembershipStore(opts),
|
|
10492
10589
|
projectBotMembership: new PostgreSQLProjectBotMembershipStore(opts),
|
|
10493
10590
|
projectRoomMessage: new PostgreSQLProjectRoomMessageStore(opts),
|
|
10591
|
+
projectRoomReadState: new PostgreSQLProjectRoomReadStateStore(opts),
|
|
10494
10592
|
vectorStoreProvider: new PGVectorStoreProvider(pool, connectionString),
|
|
10495
10593
|
checkpoint
|
|
10496
10594
|
};
|
|
@@ -11066,6 +11164,7 @@ export {
|
|
|
11066
11164
|
PostgreSQLProjectBotMembershipStore,
|
|
11067
11165
|
PostgreSQLProjectMembershipStore,
|
|
11068
11166
|
PostgreSQLProjectRoomMessageStore,
|
|
11167
|
+
PostgreSQLProjectRoomReadStateStore,
|
|
11069
11168
|
PostgreSQLProjectRoomStore,
|
|
11070
11169
|
PostgreSQLProjectStore,
|
|
11071
11170
|
PostgreSQLScheduleStorage,
|
|
@@ -11118,6 +11217,7 @@ export {
|
|
|
11118
11217
|
createMetricsConfigsTable,
|
|
11119
11218
|
createPGVectorStoreProvider,
|
|
11120
11219
|
createPgStoreConfig,
|
|
11220
|
+
createProjectRoomReadStates,
|
|
11121
11221
|
createProjectRoomTables,
|
|
11122
11222
|
createProjectsTable,
|
|
11123
11223
|
createScheduledTasksTable,
|