@axiom-lattice/pg-stores 1.0.1

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/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # @axiom-lattice/pg-stores
2
+
3
+ PostgreSQL stores implementation for the Axiom Lattice framework.
4
+
5
+ ## Overview
6
+
7
+ This package provides PostgreSQL-based store implementations that conform to the store interfaces. It can be used with the `StoreLatticeManager` from `@axiom-lattice/core` to register and manage PostgreSQL-based store services.
8
+
9
+ ## Features
10
+
11
+ - **ThreadStore**: PostgreSQL implementation for thread management
12
+ - **AssistantStore**: PostgreSQL implementation for assistant management
13
+ - **Migration System**: Automatic schema migration with version tracking
14
+ - **Type Safety**: Full TypeScript support with proper type definitions
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add @axiom-lattice/pg-stores
20
+ ```
21
+
22
+ ## Prerequisites
23
+
24
+ - PostgreSQL database (version 12 or higher)
25
+ - Node.js 18 or higher
26
+
27
+ ## Usage
28
+
29
+ ### Basic Usage - Register ThreadStore
30
+
31
+ ```typescript
32
+ import { PostgreSQLThreadStore } from "@axiom-lattice/pg-stores";
33
+ import { registerStoreLattice, getStoreLattice } from "@axiom-lattice/core";
34
+
35
+ // Create and initialize ThreadStore with connection string
36
+ const threadStore = new PostgreSQLThreadStore({
37
+ poolConfig: process.env.DATABASE_URL || "postgresql://localhost:5432/mydb",
38
+ });
39
+
40
+ // Ensure initialization (migrations run automatically)
41
+ await threadStore.initialize();
42
+
43
+ // Register to StoreLatticeManager
44
+ registerStoreLattice("threads", "thread", threadStore);
45
+
46
+ // Or use PoolConfig object
47
+ const threadStore2 = new PostgreSQLThreadStore({
48
+ poolConfig: {
49
+ host: process.env.DB_HOST || "localhost",
50
+ port: parseInt(process.env.DB_PORT || "5432"),
51
+ database: process.env.DB_NAME || "mydb",
52
+ user: process.env.DB_USER,
53
+ password: process.env.DB_PASSWORD,
54
+ },
55
+ });
56
+
57
+ await threadStore2.initialize();
58
+ registerStoreLattice("threads", "thread", threadStore2);
59
+ ```
60
+
61
+ ### Basic Usage - Register AssistantStore
62
+
63
+ ```typescript
64
+ import { PostgreSQLAssistantStore } from "@axiom-lattice/pg-stores";
65
+ import { registerStoreLattice, getStoreLattice } from "@axiom-lattice/core";
66
+
67
+ // Create and initialize AssistantStore with connection string
68
+ const assistantStore = new PostgreSQLAssistantStore({
69
+ poolConfig: process.env.DATABASE_URL || "postgresql://localhost:5432/mydb",
70
+ });
71
+
72
+ // Ensure initialization (migrations run automatically)
73
+ await assistantStore.initialize();
74
+
75
+ // Register to StoreLatticeManager
76
+ registerStoreLattice("assistants", "assistant", assistantStore);
77
+
78
+ // Get and use the store (with type safety)
79
+ const storeLattice = getStoreLattice("assistants", "assistant");
80
+ const assistantStoreInstance = storeLattice.store; // TypeScript knows this is AssistantStore
81
+
82
+ // Create an assistant
83
+ const assistant = await assistantStoreInstance.createAssistant(
84
+ "assistant-123",
85
+ {
86
+ name: "My Assistant",
87
+ description: "A helpful assistant",
88
+ graphDefinition: {
89
+ /* ... */
90
+ },
91
+ }
92
+ );
93
+
94
+ // Get all assistants
95
+ const assistants = await assistantStoreInstance.getAllAssistants();
96
+
97
+ // Get a specific assistant
98
+ const foundAssistant = await assistantStoreInstance.getAssistantById(
99
+ "assistant-123"
100
+ );
101
+
102
+ // Update assistant
103
+ const updatedAssistant = await assistantStoreInstance.updateAssistant(
104
+ "assistant-123",
105
+ {
106
+ name: "Updated Name",
107
+ }
108
+ );
109
+
110
+ // Delete assistant
111
+ await assistantStoreInstance.deleteAssistant("assistant-123");
112
+ ```
113
+
114
+ // Get and use the store (with type safety)
115
+ const storeLattice = getStoreLattice("threads", "thread");
116
+ const threadStore = storeLattice.store; // TypeScript knows this is ThreadStore
117
+
118
+ // Create a thread
119
+ const thread = await threadStore.createThread("assistant-123", "thread-456", {
120
+ metadata: { title: "My Thread" },
121
+ });
122
+
123
+ // Get threads by assistant
124
+ const threads = await threadStore.getThreadsByAssistantId("assistant-123");
125
+
126
+ // Get a specific thread
127
+ const foundThread = await threadStore.getThreadById(
128
+ "assistant-123",
129
+ "thread-456"
130
+ );
131
+
132
+ // Update thread
133
+ const updatedThread = await threadStore.updateThread(
134
+ "assistant-123",
135
+ "thread-456",
136
+ { metadata: { title: "Updated Title" } }
137
+ );
138
+
139
+ // Delete thread
140
+ await threadStore.deleteThread("assistant-123", "thread-456");
141
+
142
+ ````
143
+
144
+ ### Direct Usage (Without Registration)
145
+
146
+ ```typescript
147
+ import { PostgreSQLThreadStore } from "@axiom-lattice/pg-stores";
148
+
149
+ // Create store instance with connection string (migrations run automatically)
150
+ const threadStore = new PostgreSQLThreadStore({
151
+ poolConfig: process.env.DATABASE_URL || "postgresql://localhost:5432/mydb",
152
+ autoMigrate: true, // Default: true
153
+ });
154
+
155
+ // Ensure initialization
156
+ await threadStore.initialize();
157
+
158
+ // When done, dispose the store to close connections
159
+ // await threadStore.dispose();
160
+
161
+ // Use the store
162
+ const threads = await threadStore.getThreadsByAssistantId("assistant-123");
163
+ ````
164
+
165
+ ### Manual Migration Control
166
+
167
+ ```typescript
168
+ import { PostgreSQLThreadStore } from "@axiom-lattice/pg-stores";
169
+
170
+ // Create store without auto-migration
171
+ const threadStore = new PostgreSQLThreadStore({
172
+ poolConfig: process.env.DATABASE_URL || "postgresql://localhost:5432/mydb",
173
+ autoMigrate: false,
174
+ });
175
+
176
+ // Manually run migrations when ready
177
+ await threadStore.initialize();
178
+ ```
179
+
180
+ ## Migration System
181
+
182
+ The package includes a migration system that automatically:
183
+
184
+ 1. Creates the `lattice_schema_migrations` table to track applied migrations
185
+ 2. Applies pending migrations in order
186
+ 3. Tracks migration versions to prevent duplicate applications
187
+
188
+ ### How Migrations Work
189
+
190
+ Migrations run automatically when you create a store instance (unless `autoMigrate: false`):
191
+
192
+ ```typescript
193
+ // Migrations run automatically on initialization
194
+ const threadStore = new PostgreSQLThreadStore({
195
+ poolConfig: process.env.DATABASE_URL,
196
+ autoMigrate: true, // Default: true
197
+ });
198
+
199
+ await threadStore.initialize(); // Migrations are applied here
200
+ ```
201
+
202
+ ### Migration Structure
203
+
204
+ Migrations are defined with:
205
+
206
+ - **version**: Sequential version number (must be unique)
207
+ - **name**: Descriptive migration name
208
+ - **up**: Migration function to apply changes (creates/modifies tables)
209
+ - **down**: Optional rollback function (for undoing migrations)
210
+
211
+ ### Using MigrationManager Directly
212
+
213
+ For more control, you can use `MigrationManager` directly:
214
+
215
+ ```typescript
216
+ import { Pool } from "pg";
217
+ import { MigrationManager } from "@axiom-lattice/pg-stores";
218
+ import { createThreadsTable } from "@axiom-lattice/pg-stores";
219
+
220
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
221
+ const migrationManager = new MigrationManager(pool);
222
+
223
+ // Register migrations
224
+ migrationManager.register(createThreadsTable);
225
+
226
+ // Apply pending migrations
227
+ await migrationManager.migrate();
228
+
229
+ // Check current version
230
+ const version = await migrationManager.getCurrentVersion();
231
+
232
+ // Rollback last migration (if down migration exists)
233
+ await migrationManager.rollback();
234
+ ```
235
+
236
+ ### Current Migrations
237
+
238
+ - **ThreadStore Version 1**: `create_threads_table` - Creates the threads table with indexes
239
+ - **AssistantStore Version 1**: `create_assistants_table` - Creates the assistants table with indexes
240
+
241
+ For detailed migration usage, see [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md).
242
+
243
+ ## Database Schema
244
+
245
+ ### lattice_threads Table
246
+
247
+ ```sql
248
+ CREATE TABLE lattice_threads (
249
+ id VARCHAR(255) NOT NULL,
250
+ assistant_id VARCHAR(255) NOT NULL,
251
+ metadata JSONB DEFAULT '{}',
252
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
253
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
254
+ PRIMARY KEY (id, assistant_id)
255
+ );
256
+
257
+ CREATE INDEX idx_lattice_threads_assistant_id ON lattice_threads(assistant_id);
258
+ CREATE INDEX idx_lattice_threads_created_at ON lattice_threads(created_at DESC);
259
+ ```
260
+
261
+ ### lattice_assistants Table
262
+
263
+ ```sql
264
+ CREATE TABLE lattice_assistants (
265
+ id VARCHAR(255) PRIMARY KEY,
266
+ name VARCHAR(255) NOT NULL,
267
+ description TEXT,
268
+ graph_definition JSONB NOT NULL,
269
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
270
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
271
+ );
272
+
273
+ CREATE INDEX idx_lattice_assistants_name ON lattice_assistants(name);
274
+ CREATE INDEX idx_lattice_assistants_created_at ON lattice_assistants(created_at DESC);
275
+ ```
276
+
277
+ ## Configuration
278
+
279
+ The PostgreSQL store can be configured via:
280
+
281
+ 1. **Constructor options**: Pass `poolConfig` (connection string or PoolConfig object) and `autoMigrate` directly
282
+ 2. **Environment variables**:
283
+ - `DATABASE_URL` - PostgreSQL connection string (recommended)
284
+ - `DB_HOST` - Database host (if using PoolConfig object)
285
+ - `DB_PORT` - Database port (if using PoolConfig object)
286
+ - `DB_USER` - Database user (if using PoolConfig object)
287
+ - `DB_PASSWORD` - Database password (if using PoolConfig object)
288
+ - `DB_NAME` - Database name (if using PoolConfig object)
289
+
290
+ ### PoolConfig Options
291
+
292
+ You can pass either:
293
+
294
+ - **Connection string**: `"postgresql://user:password@host:port/database"`
295
+ - **PoolConfig object**: `{ host, port, database, user, password, ... }` (see [pg PoolConfig](https://node-postgres.com/api/pool) for all options)
296
+
297
+ ## API Reference
298
+
299
+ ### ThreadStore Interface
300
+
301
+ ```typescript
302
+ interface ThreadStore {
303
+ getThreadsByAssistantId(assistantId: string): Promise<Thread[]>;
304
+ getThreadById(
305
+ assistantId: string,
306
+ threadId: string
307
+ ): Promise<Thread | undefined>;
308
+ createThread(
309
+ assistantId: string,
310
+ threadId: string,
311
+ data: CreateThreadRequest
312
+ ): Promise<Thread>;
313
+ updateThread(
314
+ assistantId: string,
315
+ threadId: string,
316
+ updates: Partial<CreateThreadRequest>
317
+ ): Promise<Thread | null>;
318
+ deleteThread(assistantId: string, threadId: string): Promise<boolean>;
319
+ hasThread(assistantId: string, threadId: string): Promise<boolean>;
320
+ }
321
+ ```
322
+
323
+ ### AssistantStore Interface
324
+
325
+ ```typescript
326
+ interface AssistantStore {
327
+ getAllAssistants(): Promise<Assistant[]>;
328
+ getAssistantById(id: string): Promise<Assistant | undefined>;
329
+ createAssistant(id: string, data: CreateAssistantRequest): Promise<Assistant>;
330
+ updateAssistant(
331
+ id: string,
332
+ updates: Partial<CreateAssistantRequest>
333
+ ): Promise<Assistant | null>;
334
+ deleteAssistant(id: string): Promise<boolean>;
335
+ hasAssistant(id: string): Promise<boolean>;
336
+ }
337
+ ```
338
+
339
+ ## License
340
+
341
+ MIT
@@ -0,0 +1,211 @@
1
+ import { PoolConfig, PoolClient, Pool } from 'pg';
2
+ import { ThreadStore, Thread, CreateThreadRequest, AssistantStore, Assistant, CreateAssistantRequest } from '@axiom-lattice/protocols';
3
+ export { Assistant, AssistantStore, CreateAssistantRequest, CreateThreadRequest, Thread, ThreadStore } from '@axiom-lattice/protocols';
4
+
5
+ /**
6
+ * PostgreSQL implementation of ThreadStore
7
+ */
8
+
9
+ /**
10
+ * PostgreSQL ThreadStore options
11
+ */
12
+ interface PostgreSQLThreadStoreOptions {
13
+ /**
14
+ * PostgreSQL connection pool configuration
15
+ * Can be a connection string or PoolConfig object
16
+ */
17
+ poolConfig: string | PoolConfig;
18
+ /**
19
+ * Whether to run migrations automatically on initialization
20
+ * @default true
21
+ */
22
+ autoMigrate?: boolean;
23
+ }
24
+ /**
25
+ * PostgreSQL implementation of ThreadStore
26
+ */
27
+ declare class PostgreSQLThreadStore implements ThreadStore {
28
+ private pool;
29
+ private migrationManager;
30
+ private initialized;
31
+ private ownsPool;
32
+ constructor(options: PostgreSQLThreadStoreOptions);
33
+ /**
34
+ * Dispose resources and close the connection pool
35
+ * Should be called when the store is no longer needed
36
+ */
37
+ dispose(): Promise<void>;
38
+ /**
39
+ * Initialize the store and run migrations
40
+ */
41
+ initialize(): Promise<void>;
42
+ /**
43
+ * Get all threads for a specific assistant
44
+ */
45
+ getThreadsByAssistantId(assistantId: string): Promise<Thread[]>;
46
+ /**
47
+ * Get a thread by ID for a specific assistant
48
+ */
49
+ getThreadById(assistantId: string, threadId: string): Promise<Thread | undefined>;
50
+ /**
51
+ * Create a new thread for an assistant
52
+ */
53
+ createThread(assistantId: string, threadId: string, data: CreateThreadRequest): Promise<Thread>;
54
+ /**
55
+ * Update an existing thread
56
+ */
57
+ updateThread(assistantId: string, threadId: string, updates: Partial<CreateThreadRequest>): Promise<Thread | null>;
58
+ /**
59
+ * Delete a thread by ID
60
+ */
61
+ deleteThread(assistantId: string, threadId: string): Promise<boolean>;
62
+ /**
63
+ * Check if thread exists
64
+ */
65
+ hasThread(assistantId: string, threadId: string): Promise<boolean>;
66
+ /**
67
+ * Ensure store is initialized
68
+ */
69
+ private ensureInitialized;
70
+ /**
71
+ * Map database row to Thread object
72
+ */
73
+ private mapRowToThread;
74
+ }
75
+
76
+ /**
77
+ * PostgreSQL implementation of AssistantStore
78
+ */
79
+
80
+ /**
81
+ * PostgreSQL AssistantStore options
82
+ */
83
+ interface PostgreSQLAssistantStoreOptions {
84
+ /**
85
+ * PostgreSQL connection pool configuration
86
+ * Can be a connection string or PoolConfig object
87
+ */
88
+ poolConfig: string | PoolConfig;
89
+ /**
90
+ * Whether to run migrations automatically on initialization
91
+ * @default true
92
+ */
93
+ autoMigrate?: boolean;
94
+ }
95
+ /**
96
+ * PostgreSQL implementation of AssistantStore
97
+ */
98
+ declare class PostgreSQLAssistantStore implements AssistantStore {
99
+ private pool;
100
+ private migrationManager;
101
+ private initialized;
102
+ private ownsPool;
103
+ constructor(options: PostgreSQLAssistantStoreOptions);
104
+ /**
105
+ * Initialize the store and run migrations
106
+ */
107
+ initialize(): Promise<void>;
108
+ /**
109
+ * Get all assistants
110
+ */
111
+ getAllAssistants(): Promise<Assistant[]>;
112
+ /**
113
+ * Get assistant by ID
114
+ */
115
+ getAssistantById(id: string): Promise<Assistant | null>;
116
+ /**
117
+ * Create a new assistant
118
+ */
119
+ createAssistant(id: string, data: CreateAssistantRequest): Promise<Assistant>;
120
+ /**
121
+ * Update an existing assistant
122
+ */
123
+ updateAssistant(id: string, updates: Partial<CreateAssistantRequest>): Promise<Assistant | null>;
124
+ /**
125
+ * Delete an assistant by ID
126
+ */
127
+ deleteAssistant(id: string): Promise<boolean>;
128
+ /**
129
+ * Check if assistant exists
130
+ */
131
+ hasAssistant(id: string): Promise<boolean>;
132
+ /**
133
+ * Dispose resources and close the connection pool
134
+ * Should be called when the store is no longer needed
135
+ */
136
+ dispose(): Promise<void>;
137
+ /**
138
+ * Ensure store is initialized
139
+ */
140
+ private ensureInitialized;
141
+ /**
142
+ * Map database row to Assistant object
143
+ */
144
+ private mapRowToAssistant;
145
+ }
146
+
147
+ /**
148
+ * Migration system for database schema management
149
+ */
150
+
151
+ /**
152
+ * Migration definition
153
+ */
154
+ interface Migration {
155
+ version: number;
156
+ name: string;
157
+ up: (client: PoolClient) => Promise<void>;
158
+ down?: (client: PoolClient) => Promise<void>;
159
+ }
160
+ /**
161
+ * Migration manager
162
+ */
163
+ declare class MigrationManager {
164
+ private pool;
165
+ private migrations;
166
+ constructor(pool: Pool);
167
+ /**
168
+ * Register a migration
169
+ */
170
+ register(migration: Migration): void;
171
+ /**
172
+ * Initialize migrations table if it doesn't exist
173
+ */
174
+ private ensureMigrationsTable;
175
+ /**
176
+ * Get applied migrations from database
177
+ */
178
+ private getAppliedMigrations;
179
+ /**
180
+ * Apply pending migrations
181
+ */
182
+ migrate(): Promise<void>;
183
+ /**
184
+ * Rollback last migration
185
+ */
186
+ rollback(): Promise<void>;
187
+ /**
188
+ * Get current migration version
189
+ */
190
+ getCurrentVersion(): Promise<number>;
191
+ }
192
+
193
+ /**
194
+ * Thread table migrations
195
+ */
196
+
197
+ /**
198
+ * Initial migration: Create threads table
199
+ */
200
+ declare const createThreadsTable: Migration;
201
+
202
+ /**
203
+ * Assistant table migrations
204
+ */
205
+
206
+ /**
207
+ * Initial migration: Create assistants table
208
+ */
209
+ declare const createAssistantsTable: Migration;
210
+
211
+ export { type Migration, MigrationManager, PostgreSQLAssistantStore, type PostgreSQLAssistantStoreOptions, PostgreSQLThreadStore, type PostgreSQLThreadStoreOptions, createAssistantsTable, createThreadsTable };