@nextlyhq/adapter-postgres 0.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.
@@ -0,0 +1,328 @@
1
+ import { DrizzleAdapter } from '@nextlyhq/adapter-drizzle';
2
+ import { PostgresAdapterConfig, SqlParam, TransactionContext, TransactionOptions, DatabaseCapabilities, PoolStats, InsertOptions, DatabaseError } from '@nextlyhq/adapter-drizzle/types';
3
+ export { AdapterLogger, PoolConfig as AdapterPoolConfig, BaseAdapterConfig, DatabaseCapabilities, DatabaseError, DatabaseErrorKind, DeleteOptions, InsertOptions, JoinSpec, OrderBySpec, PoolStats, PostgresAdapterConfig, SelectOptions, SqlParam, SslConfig, TransactionContext, TransactionOptions, UpdateOptions, UpsertOptions, WhereClause, WhereCondition, WhereOperator } from '@nextlyhq/adapter-drizzle/types';
4
+ import { NodePgDatabase } from 'drizzle-orm/node-postgres';
5
+
6
+ /**
7
+ * @nextlyhq/adapter-postgres
8
+ *
9
+ * PostgreSQL database adapter for Nextly.
10
+ * Extends the base DrizzleAdapter from @nextlyhq/adapter-drizzle to provide
11
+ * PostgreSQL-specific functionality.
12
+ *
13
+ * @remarks
14
+ * This adapter uses the `pg` (node-postgres) driver for database connections
15
+ * and integrates with Drizzle ORM for type-safe queries.
16
+ *
17
+ * Features:
18
+ * - Connection pooling via pg.Pool
19
+ * - Full transaction support with savepoints
20
+ * - RETURNING clause support for all CRUD operations
21
+ * - PostgreSQL-specific error classification
22
+ * - JSONB support
23
+ * - Full-text search capabilities
24
+ * - Automatic retry for serialization failures and deadlocks
25
+ *
26
+ * @example
27
+ * Simple usage with connection string:
28
+ * ```typescript
29
+ * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';
30
+ *
31
+ * const adapter = createPostgresAdapter({
32
+ * url: process.env.DATABASE_URL!,
33
+ * });
34
+ *
35
+ * await adapter.connect();
36
+ * ```
37
+ *
38
+ * @example
39
+ * Full configuration:
40
+ * ```typescript
41
+ * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';
42
+ *
43
+ * const adapter = createPostgresAdapter({
44
+ * url: process.env.DATABASE_URL!,
45
+ * pool: {
46
+ * min: 2,
47
+ * max: 20,
48
+ * idleTimeoutMs: 30000,
49
+ * },
50
+ * ssl: {
51
+ * rejectUnauthorized: true,
52
+ * },
53
+ * applicationName: 'my-nextly-app',
54
+ * });
55
+ * ```
56
+ *
57
+ * @example
58
+ * Using the adapter class directly:
59
+ * ```typescript
60
+ * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';
61
+ * import type { PostgresAdapterConfig } from '@nextlyhq/adapter-postgres';
62
+ *
63
+ * const config: PostgresAdapterConfig = {
64
+ * url: process.env.DATABASE_URL!,
65
+ * };
66
+ *
67
+ * const adapter = new PostgresAdapter(config);
68
+ * await adapter.connect();
69
+ * ```
70
+ *
71
+ * @packageDocumentation
72
+ */
73
+
74
+ /**
75
+ * Package version.
76
+ */
77
+ declare const VERSION = "0.1.0";
78
+ /**
79
+ * PostgreSQL database adapter for Nextly.
80
+ *
81
+ * @remarks
82
+ * This class extends the base DrizzleAdapter to provide PostgreSQL-specific
83
+ * functionality including:
84
+ *
85
+ * - Connection pooling with pg.Pool
86
+ * - Transaction support with savepoints
87
+ * - PostgreSQL-specific error codes
88
+ * - JSONB and array type support
89
+ * - Full-text search
90
+ * - Automatic retry for serialization failures and deadlocks
91
+ *
92
+ * For most use cases, use the `createPostgresAdapter` factory function
93
+ * instead of instantiating this class directly.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';
98
+ *
99
+ * const adapter = new PostgresAdapter({
100
+ * url: 'postgres://user:pass@localhost:5432/mydb',
101
+ * });
102
+ *
103
+ * await adapter.connect();
104
+ *
105
+ * // Use the adapter
106
+ * const users = await adapter.select('users', {
107
+ * where: { and: [{ column: 'status', op: '=', value: 'active' }] },
108
+ * });
109
+ *
110
+ * await adapter.disconnect();
111
+ * ```
112
+ *
113
+ * @public
114
+ */
115
+ declare class PostgresAdapter extends DrizzleAdapter {
116
+ /**
117
+ * The database dialect - always 'postgresql' for this adapter.
118
+ */
119
+ readonly dialect: "postgresql";
120
+ /**
121
+ * Adapter configuration.
122
+ */
123
+ protected readonly config: PostgresAdapterConfig;
124
+ /**
125
+ * Connection pool instance.
126
+ */
127
+ private pool;
128
+ /**
129
+ * Connection state flag.
130
+ */
131
+ private connected;
132
+ /**
133
+ * Auto-detected provider (Neon, Supabase, or standard).
134
+ * Set during connect() from DATABASE_URL pattern or DB_PROVIDER env var.
135
+ */
136
+ private detectedProvider;
137
+ /**
138
+ * Provider-specific connection defaults. Applied as fallbacks when
139
+ * user config doesn't specify a value.
140
+ */
141
+ private providerDefaults;
142
+ /**
143
+ * Creates a new PostgreSQL adapter instance.
144
+ *
145
+ * @param config - Adapter configuration
146
+ */
147
+ constructor(config: PostgresAdapterConfig);
148
+ /**
149
+ * Establishes a connection to the PostgreSQL database.
150
+ *
151
+ * @remarks
152
+ * This method initializes the connection pool and verifies connectivity
153
+ * by executing a simple query. It is idempotent - calling it multiple
154
+ * times will not create multiple pools.
155
+ *
156
+ * @throws {DatabaseError} If connection fails
157
+ */
158
+ connect(): Promise<void>;
159
+ /**
160
+ * Closes the database connection and releases all pool resources.
161
+ *
162
+ * @remarks
163
+ * This method is idempotent - calling it multiple times is safe.
164
+ * It waits for all checked-out clients to be returned before shutting down.
165
+ */
166
+ disconnect(): Promise<void>;
167
+ /**
168
+ * Checks if the adapter is currently connected.
169
+ *
170
+ * @returns True if connected and pool is available
171
+ */
172
+ isConnected(): boolean;
173
+ /**
174
+ * Executes a raw SQL query.
175
+ *
176
+ * @param sql - SQL statement with $1, $2, ... placeholders
177
+ * @param params - Query parameters
178
+ * @returns Array of result rows
179
+ *
180
+ * @throws {DatabaseError} If query execution fails
181
+ */
182
+ executeQuery<T = unknown>(sql: string, params?: SqlParam[]): Promise<T[]>;
183
+ /**
184
+ * Executes a callback within a database transaction.
185
+ *
186
+ * @remarks
187
+ * PostgreSQL supports full ACID transactions with savepoints.
188
+ * If the callback throws, the transaction is rolled back.
189
+ *
190
+ * Supports automatic retry for serialization failures (40001) and
191
+ * deadlocks (40P01) when `retryCount` is specified in options.
192
+ *
193
+ * @param callback - Function to execute within the transaction
194
+ * @param options - Transaction options (isolation level, timeout, retry)
195
+ * @returns The result of the callback
196
+ *
197
+ * @throws {DatabaseError} If transaction fails after all retries
198
+ */
199
+ transaction<T>(callback: (ctx: TransactionContext) => Promise<T>, options?: TransactionOptions): Promise<T>;
200
+ /**
201
+ * Returns the database capabilities for PostgreSQL.
202
+ *
203
+ * @remarks
204
+ * PostgreSQL has the most comprehensive feature set of all supported
205
+ * databases, including JSONB, arrays, full-text search, and more.
206
+ */
207
+ getCapabilities(): DatabaseCapabilities;
208
+ /**
209
+ * Returns connection pool statistics.
210
+ *
211
+ * @returns Pool stats or null if not connected
212
+ */
213
+ getPoolStats(): PoolStats | null;
214
+ /**
215
+ * Override insertMany for bulk insert optimization.
216
+ *
217
+ * @remarks
218
+ * Uses a single multi-row INSERT statement for better performance
219
+ * when inserting multiple records.
220
+ */
221
+ insertMany<T = unknown>(table: string, data: Record<string, unknown>[], options?: InsertOptions): Promise<T[]>;
222
+ /**
223
+ * Ensures pool is connected and returns it.
224
+ *
225
+ * @throws {DatabaseError} If not connected
226
+ */
227
+ private ensurePool;
228
+ /**
229
+ * Return the typed Drizzle instance for PostgreSQL.
230
+ * Guarded for server-only usage and requires an active connection.
231
+ *
232
+ * @param schema - Optional schema for relational queries (db.query.*)
233
+ * @returns Drizzle ORM instance wrapping the pg pool connection
234
+ * @throws {Error} If called in browser or not connected
235
+ */
236
+ getDrizzle<T = NodePgDatabase<any>>(schema?: Record<string, unknown>): T;
237
+ /**
238
+ * Builds pg Pool configuration from adapter config.
239
+ */
240
+ private buildPoolConfig;
241
+ /**
242
+ * Begins a transaction with the specified options.
243
+ */
244
+ private beginTransaction;
245
+ /**
246
+ * Creates a TransactionContext for the given client.
247
+ */
248
+ private createTransactionContext;
249
+ /**
250
+ * Classifies a PostgreSQL error into a DatabaseError.
251
+ *
252
+ * @param error - Original error from pg
253
+ * @param sql - SQL statement that caused the error (optional)
254
+ * @returns DatabaseError with proper classification
255
+ */
256
+ private classifyError;
257
+ /**
258
+ * Override handleQueryError to use PostgreSQL-specific classification.
259
+ */
260
+ protected handleQueryError(error: unknown, operation: string, table: string): DatabaseError;
261
+ }
262
+ /**
263
+ * Creates a PostgreSQL database adapter instance.
264
+ *
265
+ * @remarks
266
+ * This is the recommended way to create a PostgreSQL adapter.
267
+ * The adapter is not connected after creation - call `connect()` to
268
+ * establish the database connection.
269
+ *
270
+ * @param config - Adapter configuration
271
+ * @returns A new PostgresAdapter instance
272
+ *
273
+ * @example
274
+ * Simple usage:
275
+ * ```typescript
276
+ * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';
277
+ *
278
+ * const adapter = createPostgresAdapter({
279
+ * url: process.env.DATABASE_URL!,
280
+ * });
281
+ *
282
+ * await adapter.connect();
283
+ * ```
284
+ *
285
+ * @example
286
+ * With full configuration:
287
+ * ```typescript
288
+ * const adapter = createPostgresAdapter({
289
+ * url: process.env.DATABASE_URL!,
290
+ * pool: {
291
+ * min: 5,
292
+ * max: 20,
293
+ * idleTimeoutMs: 30000,
294
+ * connectionTimeoutMs: 10000,
295
+ * },
296
+ * ssl: {
297
+ * rejectUnauthorized: true,
298
+ * ca: process.env.CA_CERT,
299
+ * },
300
+ * applicationName: 'my-app',
301
+ * statementTimeout: 30000,
302
+ * });
303
+ * ```
304
+ *
305
+ * @public
306
+ */
307
+ declare function createPostgresAdapter(config: PostgresAdapterConfig): PostgresAdapter;
308
+ /**
309
+ * Type guard to check if a value is a PostgresAdapter instance.
310
+ *
311
+ * @param value - Value to check
312
+ * @returns True if value is a PostgresAdapter
313
+ *
314
+ * @example
315
+ * ```typescript
316
+ * import { isPostgresAdapter } from '@nextlyhq/adapter-postgres';
317
+ *
318
+ * if (isPostgresAdapter(adapter)) {
319
+ * // TypeScript knows adapter is PostgresAdapter
320
+ * console.log(adapter.dialect); // 'postgresql'
321
+ * }
322
+ * ```
323
+ *
324
+ * @public
325
+ */
326
+ declare function isPostgresAdapter(value: unknown): value is PostgresAdapter;
327
+
328
+ export { PostgresAdapter, VERSION, createPostgresAdapter, isPostgresAdapter };