@nextlyhq/adapter-postgres 0.0.2-alpha.7 → 0.0.2-alpha.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/dist/index.cjs +40 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +20 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var net = require('net');
|
|
3
4
|
var adapterDrizzle = require('@nextlyhq/adapter-drizzle');
|
|
4
5
|
var types = require('@nextlyhq/adapter-drizzle/types');
|
|
5
6
|
var versionCheck = require('@nextlyhq/adapter-drizzle/version-check');
|
|
6
7
|
var nodePostgres = require('drizzle-orm/node-postgres');
|
|
7
8
|
var pg = require('pg');
|
|
8
9
|
|
|
10
|
+
function _interopNamespace(e) {
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var net__namespace = /*#__PURE__*/_interopNamespace(net);
|
|
29
|
+
|
|
9
30
|
// src/index.ts
|
|
10
31
|
|
|
11
32
|
// src/provider.ts
|
|
@@ -100,6 +121,21 @@ var PG_ERROR_CODES = {
|
|
|
100
121
|
function delay(ms) {
|
|
101
122
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
102
123
|
}
|
|
124
|
+
var HAPPY_EYEBALLS_MIN_TIMEOUT_MS = 5e3;
|
|
125
|
+
var happyEyeballsTimeoutApplied = false;
|
|
126
|
+
function applyHappyEyeballsTimeoutOnce() {
|
|
127
|
+
if (happyEyeballsTimeoutApplied) return;
|
|
128
|
+
happyEyeballsTimeoutApplied = true;
|
|
129
|
+
try {
|
|
130
|
+
const current = typeof net__namespace.getDefaultAutoSelectFamilyAttemptTimeout === "function" ? net__namespace.getDefaultAutoSelectFamilyAttemptTimeout() : 0;
|
|
131
|
+
if (current < HAPPY_EYEBALLS_MIN_TIMEOUT_MS) {
|
|
132
|
+
net__namespace.setDefaultAutoSelectFamilyAttemptTimeout(
|
|
133
|
+
HAPPY_EYEBALLS_MIN_TIMEOUT_MS
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
}
|
|
103
139
|
var PostgresAdapter = class extends adapterDrizzle.DrizzleAdapter {
|
|
104
140
|
/**
|
|
105
141
|
* The database dialect - always 'postgresql' for this adapter.
|
|
@@ -147,6 +183,7 @@ var PostgresAdapter = class extends adapterDrizzle.DrizzleAdapter {
|
|
|
147
183
|
* @throws {DatabaseError} If connection fails
|
|
148
184
|
*/
|
|
149
185
|
async connect() {
|
|
186
|
+
applyHappyEyeballsTimeoutOnce();
|
|
150
187
|
if (this.connected && this.pool) {
|
|
151
188
|
return;
|
|
152
189
|
}
|
|
@@ -513,8 +550,9 @@ var PostgresAdapter = class extends adapterDrizzle.DrizzleAdapter {
|
|
|
513
550
|
if (this.config.applicationName) {
|
|
514
551
|
config.application_name = this.config.applicationName;
|
|
515
552
|
}
|
|
516
|
-
|
|
517
|
-
|
|
553
|
+
const effectiveStatementTimeout = this.config.statementTimeout ?? this.providerDefaults.statementTimeoutMs;
|
|
554
|
+
if (effectiveStatementTimeout !== void 0) {
|
|
555
|
+
config.statement_timeout = effectiveStatementTimeout;
|
|
518
556
|
}
|
|
519
557
|
if (this.config.queryTimeout) {
|
|
520
558
|
config.query_timeout = this.config.queryTimeout;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts","../src/index.ts"],"names":["DrizzleAdapter","Pool","checkDialectVersion","createDatabaseError","drizzle","isDatabaseError"],"mappings":"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","file":"index.cjs","sourcesContent":["// Auto-detects PostgreSQL provider from DATABASE_URL pattern\n// and returns appropriate connection defaults.\n// Standard pg driver works with all providers - only config changes.\n\nexport type PostgresProvider = \"standard\" | \"neon\" | \"supabase\";\n\nexport interface ProviderDefaults {\n ssl: boolean;\n poolMax: number;\n poolMin: number;\n idleTimeoutMs: number;\n connectionTimeoutMs: number;\n statementTimeoutMs: number;\n retryAttempts: number;\n}\n\n// Detect provider from URL pattern or explicit override\nexport function detectPostgresProvider(\n url: string,\n explicitProvider?: string\n): PostgresProvider {\n // Explicit override takes priority (if valid)\n if (explicitProvider) {\n const normalized = explicitProvider.toLowerCase();\n if (\n normalized === \"neon\" ||\n normalized === \"supabase\" ||\n normalized === \"standard\"\n ) {\n return normalized;\n }\n }\n\n // Auto-detect from URL hostname\n if (url.includes(\".neon.tech\") || url.includes(\"neon.\")) {\n return \"neon\";\n }\n if (url.includes(\".supabase.\") || url.includes(\"supabase.\")) {\n return \"supabase\";\n }\n\n return \"standard\";\n}\n\n// Get connection defaults for a provider\nexport function getProviderDefaults(\n provider: PostgresProvider\n): ProviderDefaults {\n switch (provider) {\n case \"neon\":\n // Neon: serverless PG with auto-suspend, cold starts need more retries\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 10000,\n connectionTimeoutMs: 20000,\n statementTimeoutMs: 30000,\n retryAttempts: 5,\n };\n case \"supabase\":\n // Supabase: managed PG with Supavisor pooler, SSL required\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n case \"standard\":\n default:\n // Standard: Docker, self-hosted, direct PG connections\n return {\n ssl: false,\n poolMax: 10,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n }\n}\n","/**\n * @nextlyhq/adapter-postgres\n *\n * PostgreSQL database adapter for Nextly.\n * Extends the base DrizzleAdapter from @nextlyhq/adapter-drizzle to provide\n * PostgreSQL-specific functionality.\n *\n * @remarks\n * This adapter uses the `pg` (node-postgres) driver for database connections\n * and integrates with Drizzle ORM for type-safe queries.\n *\n * Features:\n * - Connection pooling via pg.Pool\n * - Full transaction support with savepoints\n * - RETURNING clause support for all CRUD operations\n * - PostgreSQL-specific error classification\n * - JSONB support\n * - Full-text search capabilities\n * - Automatic retry for serialization failures and deadlocks\n *\n * @example\n * Simple usage with connection string:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * Full configuration:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 2,\n * max: 20,\n * idleTimeoutMs: 30000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * },\n * applicationName: 'my-nextly-app',\n * });\n * ```\n *\n * @example\n * Using the adapter class directly:\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n * import type { PostgresAdapterConfig } from '@nextlyhq/adapter-postgres';\n *\n * const config: PostgresAdapterConfig = {\n * url: process.env.DATABASE_URL!,\n * };\n *\n * const adapter = new PostgresAdapter(config);\n * await adapter.connect();\n * ```\n *\n * @packageDocumentation\n */\n\nimport { DrizzleAdapter } from \"@nextlyhq/adapter-drizzle\";\n// F17: connect-time DB version check shared across all adapters.\nimport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n WhereClause,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport {\n createDatabaseError,\n isDatabaseError,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport { checkDialectVersion } from \"@nextlyhq/adapter-drizzle/version-check\";\nimport { drizzle, type NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient, PoolConfig } from \"pg\";\nimport { Pool } from \"pg\";\n\nimport {\n detectPostgresProvider,\n getProviderDefaults,\n type PostgresProvider,\n type ProviderDefaults,\n} from \"./provider\";\n\n// Re-export types from @nextlyhq/adapter-drizzle for convenience\nexport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n // Additional types users might need\n BaseAdapterConfig,\n AdapterLogger,\n PoolConfig as AdapterPoolConfig,\n SslConfig,\n WhereClause,\n WhereCondition,\n WhereOperator,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n OrderBySpec,\n JoinSpec,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\n\n/**\n * Package version.\n */\nexport const VERSION = \"0.1.0\";\n\n/**\n * Default pool configuration values.\n *\n * min: 0 – Never eagerly create background connections. This is critical\n * for cold-start recovery (e.g. Neon auto-suspend): after the\n * initial smoke-test connection, the pool won't immediately try\n * to create additional connections that might still fail while\n * the DB is waking up.\n *\n * max: 5 – Conservative default to avoid overwhelming cloud databases\n * (Neon free-tier limit is ~25-30 simultaneous connections).\n * With Next.js spawning up to 7 build workers this keeps the\n * total connection count safely under typical limits.\n */\nconst DEFAULT_POOL_CONFIG = {\n min: 0,\n max: 5,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n};\n\n/**\n * PostgreSQL error codes mapping to DatabaseErrorKind.\n *\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\nconst PG_ERROR_CODES: Record<string, DatabaseErrorKind> = {\n // Class 08 - Connection Exception\n \"08000\": \"connection\",\n \"08003\": \"connection\",\n \"08006\": \"connection\",\n \"08001\": \"connection\",\n \"08004\": \"connection\",\n \"08007\": \"connection\",\n \"08P01\": \"connection\",\n\n // Class 23 - Integrity Constraint Violation\n \"23000\": \"constraint\",\n \"23001\": \"constraint\",\n \"23502\": \"not_null_violation\",\n \"23503\": \"foreign_key_violation\",\n \"23505\": \"unique_violation\",\n \"23514\": \"check_violation\",\n \"23P01\": \"constraint\",\n\n // Class 40 - Transaction Rollback\n \"40000\": \"query\",\n \"40001\": \"serialization_failure\",\n \"40002\": \"constraint\",\n \"40003\": \"query\",\n \"40P01\": \"deadlock\",\n\n // Class 57 - Operator Intervention\n \"57014\": \"timeout\",\n \"57P01\": \"connection\",\n \"57P02\": \"connection\",\n \"57P03\": \"connection\",\n};\n\n/**\n * Delay helper for retry logic.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * PostgreSQL database adapter for Nextly.\n *\n * @remarks\n * This class extends the base DrizzleAdapter to provide PostgreSQL-specific\n * functionality including:\n *\n * - Connection pooling with pg.Pool\n * - Transaction support with savepoints\n * - PostgreSQL-specific error codes\n * - JSONB and array type support\n * - Full-text search\n * - Automatic retry for serialization failures and deadlocks\n *\n * For most use cases, use the `createPostgresAdapter` factory function\n * instead of instantiating this class directly.\n *\n * @example\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = new PostgresAdapter({\n * url: 'postgres://user:pass@localhost:5432/mydb',\n * });\n *\n * await adapter.connect();\n *\n * // Use the adapter\n * const users = await adapter.select('users', {\n * where: { and: [{ column: 'status', op: '=', value: 'active' }] },\n * });\n *\n * await adapter.disconnect();\n * ```\n *\n * @public\n */\nexport class PostgresAdapter extends DrizzleAdapter {\n /**\n * The database dialect - always 'postgresql' for this adapter.\n */\n public readonly dialect = \"postgresql\" as const;\n\n /**\n * Adapter configuration.\n */\n protected readonly config: PostgresAdapterConfig;\n\n /**\n * Connection pool instance.\n */\n private pool: Pool | null = null;\n\n /**\n * Connection state flag.\n */\n private connected = false;\n\n /**\n * Auto-detected provider (Neon, Supabase, or standard).\n * Set during connect() from DATABASE_URL pattern or DB_PROVIDER env var.\n */\n private detectedProvider: PostgresProvider = \"standard\";\n\n /**\n * Provider-specific connection defaults. Applied as fallbacks when\n * user config doesn't specify a value.\n */\n private providerDefaults: ProviderDefaults = getProviderDefaults(\"standard\");\n\n /**\n * Creates a new PostgreSQL adapter instance.\n *\n * @param config - Adapter configuration\n */\n constructor(config: PostgresAdapterConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Establishes a connection to the PostgreSQL database.\n *\n * @remarks\n * This method initializes the connection pool and verifies connectivity\n * by executing a simple query. It is idempotent - calling it multiple\n * times will not create multiple pools.\n *\n * @throws {DatabaseError} If connection fails\n */\n async connect(): Promise<void> {\n if (this.connected && this.pool) {\n return;\n }\n\n // Auto-detect provider from URL and apply defaults\n const url = this.config.url || \"\";\n this.detectedProvider = detectPostgresProvider(\n url,\n process.env.DB_PROVIDER\n );\n this.providerDefaults = getProviderDefaults(this.detectedProvider);\n\n // Log detected provider for developer awareness\n if (this.config.logger?.info) {\n const source = process.env.DB_PROVIDER ? \"(explicit)\" : \"(auto-detected)\";\n this.config.logger.info(\n `PostgreSQL provider: ${this.detectedProvider} ${source}`,\n {}\n );\n }\n\n // Node.js network error codes that are safe to retry (transient failures).\n // These cover cloud databases (e.g. Neon) waking from auto-suspend, brief\n // network hiccups, and DNS resolution races during build parallelism.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ]);\n\n // Use provider-specific retry count (Neon needs more for cold starts)\n const maxAttempts = this.providerDefaults.retryAttempts;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const poolConfig = this.buildPoolConfig();\n this.pool = new Pool(poolConfig);\n\n // Handle pool errors (background errors on idle clients)\n this.pool.on(\"error\", (err: Error) => {\n // Log through adapter logger if configured\n if (this.config.logger?.error) {\n this.config.logger.error(err, {\n context: \"pool_error\",\n message: \"Unexpected error on idle client\",\n });\n }\n // Client is automatically removed from pool, no action needed\n });\n\n // Verify connection with smoke test, then check dialect version.\n // Why: F17 hard-fails at connect on unsupported PG versions (<15.0)\n // so users see a clear upgrade pointer instead of cryptic errors\n // mid-apply later. The version query runs inside the existing retry\n // loop's try block, so transient network failures (Neon cold start,\n // EAI_AGAIN) continue to retry; only confirmed version mismatch\n // surfaces as UnsupportedDialectVersionError and exits the loop.\n const client = await this.pool.connect();\n try {\n await client.query(\"SELECT 1\");\n await checkDialectVersion(client, \"postgresql\", {\n // Why: route any future variant warnings through the adapter's\n // logger. PG has no recognized variants today, but this keeps\n // the integration symmetric with MySQL.\n onWarning: msg => this.config.logger?.warn?.(msg),\n });\n this.connected = true;\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection established\", {\n host: this.config.host ?? \"from URL\",\n database: this.config.database ?? \"from URL\",\n });\n }\n\n return; // Success — exit retry loop\n } finally {\n client.release();\n }\n } catch (error) {\n // Clean up the failed pool before deciding whether to retry\n if (this.pool) {\n await this.pool.end().catch(() => {});\n this.pool = null;\n }\n\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxAttempts) {\n // Exponential back-off with jitter: ~1 s, ~2 s, ~3 s, ~4 s\n const waitMs = 1000 * attempt;\n const msg = `PostgreSQL connection attempt ${attempt}/${maxAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`;\n if (this.config.logger?.warn) {\n this.config.logger.warn(msg);\n } else {\n console.warn(`[PostgresAdapter] ${msg}`);\n }\n await delay(waitMs);\n continue;\n }\n\n // Non-retryable error or exhausted retries — surface to caller\n throw this.classifyError(error);\n }\n }\n }\n\n /**\n * Closes the database connection and releases all pool resources.\n *\n * @remarks\n * This method is idempotent - calling it multiple times is safe.\n * It waits for all checked-out clients to be returned before shutting down.\n */\n async disconnect(): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n try {\n await this.pool.end();\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection closed\");\n }\n } finally {\n this.pool = null;\n this.connected = false;\n }\n }\n\n /**\n * Checks if the adapter is currently connected.\n *\n * @returns True if connected and pool is available\n */\n override isConnected(): boolean {\n return this.connected && this.pool !== null;\n }\n\n /**\n * Executes a raw SQL query.\n *\n * @param sql - SQL statement with $1, $2, ... placeholders\n * @param params - Query parameters\n * @returns Array of result rows\n *\n * @throws {DatabaseError} If query execution fails\n */\n async executeQuery<T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> {\n const pool = this.ensurePool();\n const startTime = Date.now();\n\n // Transient network errors that are safe to retry at the query level.\n // These occur when Neon auto-suspends between the pool smoke-test and the\n // actual query, or when multiple build workers compete for cold-start.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n ]);\n const maxQueryAttempts = 3;\n\n for (let attempt = 1; attempt <= maxQueryAttempts; attempt++) {\n try {\n const result = await pool.query(sql, params as unknown[]);\n\n // Log query if logger configured\n if (this.config.logger?.query) {\n const durationMs = Date.now() - startTime;\n this.config.logger.query(sql, params, durationMs);\n }\n\n return result.rows as T[];\n } catch (error) {\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxQueryAttempts) {\n const waitMs = 500 * attempt;\n console.warn(\n `[PostgresAdapter] Query attempt ${attempt}/${maxQueryAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`\n );\n await delay(waitMs);\n continue;\n }\n\n throw this.classifyError(error, sql);\n }\n }\n\n // Unreachable — loop always returns or throws\n throw this.classifyError(new Error(\"executeQuery: exhausted retries\"));\n }\n\n /**\n * Executes a callback within a database transaction.\n *\n * @remarks\n * PostgreSQL supports full ACID transactions with savepoints.\n * If the callback throws, the transaction is rolled back.\n *\n * Supports automatic retry for serialization failures (40001) and\n * deadlocks (40P01) when `retryCount` is specified in options.\n *\n * @param callback - Function to execute within the transaction\n * @param options - Transaction options (isolation level, timeout, retry)\n * @returns The result of the callback\n *\n * @throws {DatabaseError} If transaction fails after all retries\n */\n async transaction<T>(\n callback: (ctx: TransactionContext) => Promise<T>,\n options?: TransactionOptions\n ): Promise<T> {\n const pool = this.ensurePool();\n const maxAttempts = (options?.retryCount ?? 0) + 1;\n const retryDelayMs = options?.retryDelayMs ?? 100;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const client = await pool.connect();\n const startTime = Date.now();\n\n try {\n // Begin transaction with options\n await this.beginTransaction(client, options);\n\n // Create transaction context\n const ctx = this.createTransactionContext(client);\n\n // Execute callback\n const result = await callback(ctx);\n\n // Commit transaction\n await client.query(\"COMMIT\");\n\n // Log success\n if (this.config.logger?.debug) {\n const durationMs = Date.now() - startTime;\n this.config.logger.debug(\"Transaction committed\", {\n attempt,\n durationMs,\n });\n }\n\n return result;\n } catch (error) {\n // Rollback transaction\n await client.query(\"ROLLBACK\").catch(() => {});\n\n lastError = error;\n\n // Check if error is retryable\n const pgError = error as { code?: string };\n const isRetryable =\n pgError.code === \"40001\" || // serialization_failure\n pgError.code === \"40P01\"; // deadlock\n\n if (isRetryable && attempt < maxAttempts) {\n if (this.config.logger?.warn) {\n this.config.logger.warn(\n `Transaction failed with ${pgError.code}, retrying (${attempt}/${maxAttempts})`,\n { code: pgError.code, attempt }\n );\n }\n await delay(retryDelayMs * attempt); // Exponential backoff\n continue;\n }\n\n throw this.classifyError(error);\n } finally {\n client.release();\n }\n }\n\n // Should not reach here, but handle just in case\n throw this.classifyError(lastError);\n }\n\n /**\n * Returns the database capabilities for PostgreSQL.\n *\n * @remarks\n * PostgreSQL has the most comprehensive feature set of all supported\n * databases, including JSONB, arrays, full-text search, and more.\n */\n getCapabilities(): DatabaseCapabilities {\n return {\n dialect: \"postgresql\",\n supportsJsonb: true,\n supportsJson: true,\n supportsArrays: true,\n supportsGeneratedColumns: true,\n supportsFts: true,\n supportsIlike: true,\n supportsReturning: true,\n supportsSavepoints: true,\n supportsOnConflict: true,\n maxParamsPerQuery: 65535, // PostgreSQL limit\n maxIdentifierLength: 63, // PostgreSQL default\n };\n }\n\n /**\n * Returns connection pool statistics.\n *\n * @returns Pool stats or null if not connected\n */\n override getPoolStats(): PoolStats | null {\n if (!this.pool) {\n return null;\n }\n\n return {\n total: this.pool.totalCount,\n idle: this.pool.idleCount,\n waiting: this.pool.waitingCount,\n active: this.pool.totalCount - this.pool.idleCount,\n };\n }\n\n /**\n * Override insertMany for bulk insert optimization.\n *\n * @remarks\n * Uses a single multi-row INSERT statement for better performance\n * when inserting multiple records.\n */\n override async insertMany<T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n // For single record, use parent implementation\n if (data.length === 1) {\n const result = await this.insert<T>(table, data[0], options);\n return [result];\n }\n\n // Build multi-row INSERT\n const columns = Object.keys(data[0]);\n const params: SqlParam[] = [];\n const valuesClauses: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const record = data[i];\n const placeholders: string[] = [];\n\n for (const col of columns) {\n params.push(record[col] as SqlParam);\n placeholders.push(`$${params.length}`);\n }\n\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n const columnList = columns\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columnList}) VALUES ${valuesClauses.join(\", \")}`;\n\n // Add RETURNING clause\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning.map(col => this.escapeIdentifier(col)).join(\", \");\n sql += ` RETURNING ${returning}`;\n }\n\n try {\n return await this.executeQuery<T>(sql, params);\n } catch (error) {\n throw this.handleQueryError(error, \"insertMany\", table);\n }\n }\n\n // ============================================================\n // Protected Helper Methods\n // ============================================================\n\n /**\n * Ensures pool is connected and returns it.\n *\n * @throws {DatabaseError} If not connected\n */\n private ensurePool(): Pool {\n if (!this.pool) {\n throw createDatabaseError({\n kind: \"connection\",\n message: \"PostgresAdapter is not connected. Call connect() first.\",\n });\n }\n return this.pool;\n }\n\n /**\n * Return the typed Drizzle instance for PostgreSQL.\n * Guarded for server-only usage and requires an active connection.\n *\n * @param schema - Optional schema for relational queries (db.query.*)\n * @returns Drizzle ORM instance wrapping the pg pool connection\n * @throws {Error} If called in browser or not connected\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getDrizzle<T = NodePgDatabase<any>>(schema?: Record<string, unknown>): T {\n if (typeof window !== \"undefined\") {\n throw new Error(\"getDrizzle() is server-only\");\n }\n const pool = this.ensurePool();\n return (schema ? drizzle(pool, { schema }) : drizzle(pool)) as T;\n }\n\n /**\n * Builds pg Pool configuration from adapter config.\n */\n private buildPoolConfig(): PoolConfig {\n const config: PoolConfig = {};\n\n // Connection string or explicit options\n if (this.config.url) {\n config.connectionString = this.config.url;\n } else {\n if (this.config.host) config.host = this.config.host;\n if (this.config.port) config.port = this.config.port;\n if (this.config.database) config.database = this.config.database;\n if (this.config.user) config.user = this.config.user;\n if (this.config.password) config.password = this.config.password;\n }\n\n // Pool settings (user config > provider defaults > hardcoded defaults)\n config.min =\n this.config.pool?.min ??\n this.providerDefaults.poolMin ??\n DEFAULT_POOL_CONFIG.min;\n config.max =\n this.config.pool?.max ??\n this.providerDefaults.poolMax ??\n DEFAULT_POOL_CONFIG.max;\n config.idleTimeoutMillis =\n this.config.pool?.idleTimeoutMs ??\n this.providerDefaults.idleTimeoutMs ??\n DEFAULT_POOL_CONFIG.idleTimeoutMs;\n config.connectionTimeoutMillis =\n this.config.pool?.connectionTimeoutMs ??\n this.providerDefaults.connectionTimeoutMs ??\n DEFAULT_POOL_CONFIG.connectionTimeoutMs;\n\n // TCP keepalive - prevents cloud databases (e.g. Neon) from silently\n // dropping idle connections between the pool smoke-test and the first\n // real query, which manifests as ETIMEDOUT on the query itself.\n config.keepAlive = true;\n config.keepAliveInitialDelayMillis = 10000;\n\n // SSL configuration (user config > provider default)\n if (this.config.ssl) {\n if (typeof this.config.ssl === \"boolean\") {\n config.ssl = this.config.ssl;\n } else {\n if (this.config.ssl.rejectUnauthorized === false) {\n console.warn(\n \"[nextly/adapter-postgres] ssl.rejectUnauthorized is set to false — \" +\n \"TLS certificates will not be validated. This is unsafe on untrusted networks. \" +\n \"Provide a trusted `ca` cert instead, or remove the rejectUnauthorized override.\"\n );\n }\n config.ssl = {\n rejectUnauthorized: this.config.ssl.rejectUnauthorized,\n ca: this.config.ssl.ca,\n cert: this.config.ssl.cert,\n key: this.config.ssl.key,\n };\n }\n } else if (this.providerDefaults.ssl) {\n // Provider requires SSL but user didn't explicitly configure it.\n // Default to validating certs; the user can opt out by setting\n // `ssl: { rejectUnauthorized: false }` explicitly (which logs a warning above).\n config.ssl = { rejectUnauthorized: true };\n }\n\n // PostgreSQL-specific options\n if (this.config.applicationName) {\n config.application_name = this.config.applicationName;\n }\n\n if (this.config.statementTimeout) {\n config.statement_timeout = this.config.statementTimeout;\n }\n\n if (this.config.queryTimeout) {\n config.query_timeout = this.config.queryTimeout;\n }\n\n return config;\n }\n\n /**\n * Begins a transaction with the specified options.\n */\n private async beginTransaction(\n client: PoolClient,\n options?: TransactionOptions\n ): Promise<void> {\n let beginSql = \"BEGIN\";\n\n // Add isolation level if specified\n if (options?.isolationLevel) {\n const isolationMap: Record<string, string> = {\n \"read uncommitted\": \"READ UNCOMMITTED\",\n \"read committed\": \"READ COMMITTED\",\n \"repeatable read\": \"REPEATABLE READ\",\n serializable: \"SERIALIZABLE\",\n };\n const level = isolationMap[options.isolationLevel];\n if (level) {\n beginSql += ` ISOLATION LEVEL ${level}`;\n }\n }\n\n // Add read-only mode if specified\n if (options?.readOnly) {\n beginSql += \" READ ONLY\";\n }\n\n await client.query(beginSql);\n\n // Set statement timeout if specified\n if (options?.timeoutMs) {\n await client.query(`SET LOCAL statement_timeout = ${options.timeoutMs}`);\n }\n }\n\n /**\n * Creates a TransactionContext for the given client.\n */\n private createTransactionContext(client: PoolClient): TransactionContext {\n return {\n execute: async <T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> => {\n const result = await client.query(sql, params as unknown[]);\n return result.rows as T[];\n },\n\n insert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options?: InsertOptions\n ): Promise<T> => {\n const columns = Object.keys(data);\n const values = Object.values(data);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES (${placeholders})`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, values);\n return result.rows[0] as T;\n },\n\n insertMany: async <T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> => {\n if (data.length === 0) return [];\n\n const columns = Object.keys(data[0]);\n const params: unknown[] = [];\n const valuesClauses: string[] = [];\n\n for (const record of data) {\n const placeholders: string[] = [];\n for (const col of columns) {\n params.push(record[col]);\n placeholders.push(`$${params.length}`);\n }\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES ${valuesClauses.join(\", \")}`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, params);\n return result.rows as T[];\n },\n\n // TransactionContext CRUD methods delegate to the adapter's CRUD\n // which uses Drizzle query API via the TableResolver.\n // The Drizzle transaction is handled at a higher level.\n select: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T[]> => {\n return this.select<T>(table, options);\n },\n\n selectOne: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T | null> => {\n return this.selectOne<T>(table, options);\n },\n\n update: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n where: WhereClause,\n options?: UpdateOptions\n ): Promise<T[]> => {\n return this.update<T>(table, data, where, options);\n },\n\n delete: async (\n table: string,\n where: WhereClause,\n _options?: DeleteOptions\n ): Promise<number> => {\n return this.delete(table, where);\n },\n\n upsert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options: UpsertOptions\n ): Promise<T> => {\n return this.upsert<T>(table, data, options);\n },\n\n savepoint: async (name: string): Promise<void> => {\n await client.query(`SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n\n rollbackToSavepoint: async (name: string): Promise<void> => {\n await client.query(\n `ROLLBACK TO SAVEPOINT ${this.escapeIdentifier(name)}`\n );\n },\n\n releaseSavepoint: async (name: string): Promise<void> => {\n await client.query(`RELEASE SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n };\n }\n\n /**\n * Classifies a PostgreSQL error into a DatabaseError.\n *\n * @param error - Original error from pg\n * @param sql - SQL statement that caused the error (optional)\n * @returns DatabaseError with proper classification\n */\n private classifyError(error: unknown, sql?: string): DatabaseError {\n // Why short-circuit on existing DatabaseError: F17's\n // UnsupportedDialectVersionError is already a typed DatabaseError with\n // kind: \"unsupported_version\" plus detectedVersion/requiredVersion\n // fields. Re-wrapping it here would erase those fields and re-tag it\n // as kind: \"unknown\".\n if (isDatabaseError(error)) return error;\n\n const pgError = error as {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n column?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n };\n\n // Determine error kind from PostgreSQL error code\n const kind: DatabaseErrorKind =\n (pgError.code && PG_ERROR_CODES[pgError.code]) || \"unknown\";\n\n // Build error message\n let message = pgError.message ?? String(error);\n if (sql && kind === \"query\") {\n message = `Query failed: ${message}`;\n }\n\n return createDatabaseError({\n kind,\n message,\n code: pgError.code,\n constraint: pgError.constraint,\n table: pgError.table,\n column: pgError.column,\n detail: pgError.detail,\n hint: pgError.hint,\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Override handleQueryError to use PostgreSQL-specific classification.\n */\n protected override handleQueryError(\n error: unknown,\n operation: string,\n table: string\n ): DatabaseError {\n const dbError = this.classifyError(error);\n\n // Add operation context if not already present\n if (!dbError.message.includes(operation)) {\n dbError.message = `${operation} operation failed on table '${table}': ${dbError.message}`;\n }\n\n if (!dbError.table) {\n dbError.table = table;\n }\n\n return dbError;\n }\n}\n\n/**\n * Creates a PostgreSQL database adapter instance.\n *\n * @remarks\n * This is the recommended way to create a PostgreSQL adapter.\n * The adapter is not connected after creation - call `connect()` to\n * establish the database connection.\n *\n * @param config - Adapter configuration\n * @returns A new PostgresAdapter instance\n *\n * @example\n * Simple usage:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * With full configuration:\n * ```typescript\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 5,\n * max: 20,\n * idleTimeoutMs: 30000,\n * connectionTimeoutMs: 10000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * ca: process.env.CA_CERT,\n * },\n * applicationName: 'my-app',\n * statementTimeout: 30000,\n * });\n * ```\n *\n * @public\n */\nexport function createPostgresAdapter(\n config: PostgresAdapterConfig\n): PostgresAdapter {\n return new PostgresAdapter(config);\n}\n\n/**\n * Type guard to check if a value is a PostgresAdapter instance.\n *\n * @param value - Value to check\n * @returns True if value is a PostgresAdapter\n *\n * @example\n * ```typescript\n * import { isPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * if (isPostgresAdapter(adapter)) {\n * // TypeScript knows adapter is PostgresAdapter\n * console.log(adapter.dialect); // 'postgresql'\n * }\n * ```\n *\n * @public\n */\nexport function isPostgresAdapter(value: unknown): value is PostgresAdapter {\n return value instanceof PostgresAdapter;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts","../src/index.ts"],"names":["net","DrizzleAdapter","Pool","checkDialectVersion","createDatabaseError","drizzle","isDatabaseError"],"mappings":"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","file":"index.cjs","sourcesContent":["// Auto-detects PostgreSQL provider from DATABASE_URL pattern\n// and returns appropriate connection defaults.\n// Standard pg driver works with all providers - only config changes.\n\nexport type PostgresProvider = \"standard\" | \"neon\" | \"supabase\";\n\nexport interface ProviderDefaults {\n ssl: boolean;\n poolMax: number;\n poolMin: number;\n idleTimeoutMs: number;\n connectionTimeoutMs: number;\n statementTimeoutMs: number;\n retryAttempts: number;\n}\n\n// Detect provider from URL pattern or explicit override\nexport function detectPostgresProvider(\n url: string,\n explicitProvider?: string\n): PostgresProvider {\n // Explicit override takes priority (if valid)\n if (explicitProvider) {\n const normalized = explicitProvider.toLowerCase();\n if (\n normalized === \"neon\" ||\n normalized === \"supabase\" ||\n normalized === \"standard\"\n ) {\n return normalized;\n }\n }\n\n // Auto-detect from URL hostname\n if (url.includes(\".neon.tech\") || url.includes(\"neon.\")) {\n return \"neon\";\n }\n if (url.includes(\".supabase.\") || url.includes(\"supabase.\")) {\n return \"supabase\";\n }\n\n return \"standard\";\n}\n\n// Get connection defaults for a provider\nexport function getProviderDefaults(\n provider: PostgresProvider\n): ProviderDefaults {\n switch (provider) {\n case \"neon\":\n // Neon: serverless PG with auto-suspend, cold starts need more retries\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 10000,\n connectionTimeoutMs: 20000,\n statementTimeoutMs: 30000,\n retryAttempts: 5,\n };\n case \"supabase\":\n // Supabase: managed PG with Supavisor pooler, SSL required\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n case \"standard\":\n default:\n // Standard: Docker, self-hosted, direct PG connections\n return {\n ssl: false,\n poolMax: 10,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n }\n}\n","/**\n * @nextlyhq/adapter-postgres\n *\n * PostgreSQL database adapter for Nextly.\n * Extends the base DrizzleAdapter from @nextlyhq/adapter-drizzle to provide\n * PostgreSQL-specific functionality.\n *\n * @remarks\n * This adapter uses the `pg` (node-postgres) driver for database connections\n * and integrates with Drizzle ORM for type-safe queries.\n *\n * Features:\n * - Connection pooling via pg.Pool\n * - Full transaction support with savepoints\n * - RETURNING clause support for all CRUD operations\n * - PostgreSQL-specific error classification\n * - JSONB support\n * - Full-text search capabilities\n * - Automatic retry for serialization failures and deadlocks\n *\n * @example\n * Simple usage with connection string:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * Full configuration:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 2,\n * max: 20,\n * idleTimeoutMs: 30000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * },\n * applicationName: 'my-nextly-app',\n * });\n * ```\n *\n * @example\n * Using the adapter class directly:\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n * import type { PostgresAdapterConfig } from '@nextlyhq/adapter-postgres';\n *\n * const config: PostgresAdapterConfig = {\n * url: process.env.DATABASE_URL!,\n * };\n *\n * const adapter = new PostgresAdapter(config);\n * await adapter.connect();\n * ```\n *\n * @packageDocumentation\n */\n\nimport * as net from \"node:net\";\n\nimport { DrizzleAdapter } from \"@nextlyhq/adapter-drizzle\";\n// F17: connect-time DB version check shared across all adapters.\nimport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n WhereClause,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport {\n createDatabaseError,\n isDatabaseError,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport { checkDialectVersion } from \"@nextlyhq/adapter-drizzle/version-check\";\nimport { drizzle, type NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient, PoolConfig } from \"pg\";\nimport { Pool } from \"pg\";\n\nimport {\n detectPostgresProvider,\n getProviderDefaults,\n type PostgresProvider,\n type ProviderDefaults,\n} from \"./provider\";\n\n// Re-export types from @nextlyhq/adapter-drizzle for convenience\nexport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n // Additional types users might need\n BaseAdapterConfig,\n AdapterLogger,\n PoolConfig as AdapterPoolConfig,\n SslConfig,\n WhereClause,\n WhereCondition,\n WhereOperator,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n OrderBySpec,\n JoinSpec,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\n\n/**\n * Package version.\n */\nexport const VERSION = \"0.1.0\";\n\n/**\n * Default pool configuration values.\n *\n * min: 0 – Never eagerly create background connections. This is critical\n * for cold-start recovery (e.g. Neon auto-suspend): after the\n * initial smoke-test connection, the pool won't immediately try\n * to create additional connections that might still fail while\n * the DB is waking up.\n *\n * max: 5 – Conservative default to avoid overwhelming cloud databases\n * (Neon free-tier limit is ~25-30 simultaneous connections).\n * With Next.js spawning up to 7 build workers this keeps the\n * total connection count safely under typical limits.\n */\nconst DEFAULT_POOL_CONFIG = {\n min: 0,\n max: 5,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n};\n\n/**\n * PostgreSQL error codes mapping to DatabaseErrorKind.\n *\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\nconst PG_ERROR_CODES: Record<string, DatabaseErrorKind> = {\n // Class 08 - Connection Exception\n \"08000\": \"connection\",\n \"08003\": \"connection\",\n \"08006\": \"connection\",\n \"08001\": \"connection\",\n \"08004\": \"connection\",\n \"08007\": \"connection\",\n \"08P01\": \"connection\",\n\n // Class 23 - Integrity Constraint Violation\n \"23000\": \"constraint\",\n \"23001\": \"constraint\",\n \"23502\": \"not_null_violation\",\n \"23503\": \"foreign_key_violation\",\n \"23505\": \"unique_violation\",\n \"23514\": \"check_violation\",\n \"23P01\": \"constraint\",\n\n // Class 40 - Transaction Rollback\n \"40000\": \"query\",\n \"40001\": \"serialization_failure\",\n \"40002\": \"constraint\",\n \"40003\": \"query\",\n \"40P01\": \"deadlock\",\n\n // Class 57 - Operator Intervention\n \"57014\": \"timeout\",\n \"57P01\": \"connection\",\n \"57P02\": \"connection\",\n \"57P03\": \"connection\",\n};\n\n/**\n * Delay helper for retry logic.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n// Node 20+ defaults the Happy Eyeballs per-address connection-attempt timeout\n// to 250ms. For consumers connecting from a region with RTT > 250ms to their\n// database (typical transcontinental: Pakistan→Singapore is ~310ms),\n// every TCP attempt is killed mid-handshake and the pg driver reports\n// ETIMEDOUT after exhausting all DNS-resolved addresses — even though the\n// network is fine.\n//\n// We bump the timeout to 5000ms on first adapter connect. This is process-\n// global state but the change is purely permissive (only increases the\n// per-address budget; cannot break anything that worked at 250ms). If the\n// process has already set a higher value, we leave it alone.\n//\n// References:\n// https://nodejs.org/api/net.html#netsetdefaultautoselectfamilyattempttimeoutvalue\n// https://www.rfc-editor.org/rfc/rfc8305\nconst HAPPY_EYEBALLS_MIN_TIMEOUT_MS = 5000;\nlet happyEyeballsTimeoutApplied = false;\nfunction applyHappyEyeballsTimeoutOnce(): void {\n if (happyEyeballsTimeoutApplied) return;\n happyEyeballsTimeoutApplied = true;\n try {\n const current =\n typeof net.getDefaultAutoSelectFamilyAttemptTimeout === \"function\"\n ? net.getDefaultAutoSelectFamilyAttemptTimeout()\n : 0;\n if (current < HAPPY_EYEBALLS_MIN_TIMEOUT_MS) {\n net.setDefaultAutoSelectFamilyAttemptTimeout(\n HAPPY_EYEBALLS_MIN_TIMEOUT_MS\n );\n }\n } catch {\n // Older Node versions (< 20) don't have these APIs. Swallow — the\n // 250ms default they have predates Happy Eyeballs anyway, so they\n // don't suffer this bug.\n }\n}\n\n/**\n * PostgreSQL database adapter for Nextly.\n *\n * @remarks\n * This class extends the base DrizzleAdapter to provide PostgreSQL-specific\n * functionality including:\n *\n * - Connection pooling with pg.Pool\n * - Transaction support with savepoints\n * - PostgreSQL-specific error codes\n * - JSONB and array type support\n * - Full-text search\n * - Automatic retry for serialization failures and deadlocks\n *\n * For most use cases, use the `createPostgresAdapter` factory function\n * instead of instantiating this class directly.\n *\n * @example\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = new PostgresAdapter({\n * url: 'postgres://user:pass@localhost:5432/mydb',\n * });\n *\n * await adapter.connect();\n *\n * // Use the adapter\n * const users = await adapter.select('users', {\n * where: { and: [{ column: 'status', op: '=', value: 'active' }] },\n * });\n *\n * await adapter.disconnect();\n * ```\n *\n * @public\n */\nexport class PostgresAdapter extends DrizzleAdapter {\n /**\n * The database dialect - always 'postgresql' for this adapter.\n */\n public readonly dialect = \"postgresql\" as const;\n\n /**\n * Adapter configuration.\n */\n protected readonly config: PostgresAdapterConfig;\n\n /**\n * Connection pool instance.\n */\n private pool: Pool | null = null;\n\n /**\n * Connection state flag.\n */\n private connected = false;\n\n /**\n * Auto-detected provider (Neon, Supabase, or standard).\n * Set during connect() from DATABASE_URL pattern or DB_PROVIDER env var.\n */\n private detectedProvider: PostgresProvider = \"standard\";\n\n /**\n * Provider-specific connection defaults. Applied as fallbacks when\n * user config doesn't specify a value.\n */\n private providerDefaults: ProviderDefaults = getProviderDefaults(\"standard\");\n\n /**\n * Creates a new PostgreSQL adapter instance.\n *\n * @param config - Adapter configuration\n */\n constructor(config: PostgresAdapterConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Establishes a connection to the PostgreSQL database.\n *\n * @remarks\n * This method initializes the connection pool and verifies connectivity\n * by executing a simple query. It is idempotent - calling it multiple\n * times will not create multiple pools.\n *\n * @throws {DatabaseError} If connection fails\n */\n async connect(): Promise<void> {\n // Fix Node 20+ Happy Eyeballs default before constructing the pool —\n // see applyHappyEyeballsTimeoutOnce above.\n applyHappyEyeballsTimeoutOnce();\n\n if (this.connected && this.pool) {\n return;\n }\n\n // Auto-detect provider from URL and apply defaults\n const url = this.config.url || \"\";\n this.detectedProvider = detectPostgresProvider(\n url,\n process.env.DB_PROVIDER\n );\n this.providerDefaults = getProviderDefaults(this.detectedProvider);\n\n // Log detected provider for developer awareness\n if (this.config.logger?.info) {\n const source = process.env.DB_PROVIDER ? \"(explicit)\" : \"(auto-detected)\";\n this.config.logger.info(\n `PostgreSQL provider: ${this.detectedProvider} ${source}`,\n {}\n );\n }\n\n // Node.js network error codes that are safe to retry (transient failures).\n // These cover cloud databases (e.g. Neon) waking from auto-suspend, brief\n // network hiccups, and DNS resolution races during build parallelism.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ]);\n\n // Use provider-specific retry count (Neon needs more for cold starts)\n const maxAttempts = this.providerDefaults.retryAttempts;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const poolConfig = this.buildPoolConfig();\n this.pool = new Pool(poolConfig);\n\n // Handle pool errors (background errors on idle clients)\n this.pool.on(\"error\", (err: Error) => {\n // Log through adapter logger if configured\n if (this.config.logger?.error) {\n this.config.logger.error(err, {\n context: \"pool_error\",\n message: \"Unexpected error on idle client\",\n });\n }\n // Client is automatically removed from pool, no action needed\n });\n\n // Verify connection with smoke test, then check dialect version.\n // Why: F17 hard-fails at connect on unsupported PG versions (<15.0)\n // so users see a clear upgrade pointer instead of cryptic errors\n // mid-apply later. The version query runs inside the existing retry\n // loop's try block, so transient network failures (Neon cold start,\n // EAI_AGAIN) continue to retry; only confirmed version mismatch\n // surfaces as UnsupportedDialectVersionError and exits the loop.\n const client = await this.pool.connect();\n try {\n await client.query(\"SELECT 1\");\n await checkDialectVersion(client, \"postgresql\", {\n // Why: route any future variant warnings through the adapter's\n // logger. PG has no recognized variants today, but this keeps\n // the integration symmetric with MySQL.\n onWarning: msg => this.config.logger?.warn?.(msg),\n });\n this.connected = true;\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection established\", {\n host: this.config.host ?? \"from URL\",\n database: this.config.database ?? \"from URL\",\n });\n }\n\n return; // Success — exit retry loop\n } finally {\n client.release();\n }\n } catch (error) {\n // Clean up the failed pool before deciding whether to retry\n if (this.pool) {\n await this.pool.end().catch(() => {});\n this.pool = null;\n }\n\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxAttempts) {\n // Exponential back-off with jitter: ~1 s, ~2 s, ~3 s, ~4 s\n const waitMs = 1000 * attempt;\n const msg = `PostgreSQL connection attempt ${attempt}/${maxAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`;\n if (this.config.logger?.warn) {\n this.config.logger.warn(msg);\n } else {\n console.warn(`[PostgresAdapter] ${msg}`);\n }\n await delay(waitMs);\n continue;\n }\n\n // Non-retryable error or exhausted retries — surface to caller\n throw this.classifyError(error);\n }\n }\n }\n\n /**\n * Closes the database connection and releases all pool resources.\n *\n * @remarks\n * This method is idempotent - calling it multiple times is safe.\n * It waits for all checked-out clients to be returned before shutting down.\n */\n async disconnect(): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n try {\n await this.pool.end();\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection closed\");\n }\n } finally {\n this.pool = null;\n this.connected = false;\n }\n }\n\n /**\n * Checks if the adapter is currently connected.\n *\n * @returns True if connected and pool is available\n */\n override isConnected(): boolean {\n return this.connected && this.pool !== null;\n }\n\n /**\n * Executes a raw SQL query.\n *\n * @param sql - SQL statement with $1, $2, ... placeholders\n * @param params - Query parameters\n * @returns Array of result rows\n *\n * @throws {DatabaseError} If query execution fails\n */\n async executeQuery<T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> {\n const pool = this.ensurePool();\n const startTime = Date.now();\n\n // Transient network errors that are safe to retry at the query level.\n // These occur when Neon auto-suspends between the pool smoke-test and the\n // actual query, or when multiple build workers compete for cold-start.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n ]);\n const maxQueryAttempts = 3;\n\n for (let attempt = 1; attempt <= maxQueryAttempts; attempt++) {\n try {\n const result = await pool.query(sql, params as unknown[]);\n\n // Log query if logger configured\n if (this.config.logger?.query) {\n const durationMs = Date.now() - startTime;\n this.config.logger.query(sql, params, durationMs);\n }\n\n return result.rows as T[];\n } catch (error) {\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxQueryAttempts) {\n const waitMs = 500 * attempt;\n console.warn(\n `[PostgresAdapter] Query attempt ${attempt}/${maxQueryAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`\n );\n await delay(waitMs);\n continue;\n }\n\n throw this.classifyError(error, sql);\n }\n }\n\n // Unreachable — loop always returns or throws\n throw this.classifyError(new Error(\"executeQuery: exhausted retries\"));\n }\n\n /**\n * Executes a callback within a database transaction.\n *\n * @remarks\n * PostgreSQL supports full ACID transactions with savepoints.\n * If the callback throws, the transaction is rolled back.\n *\n * Supports automatic retry for serialization failures (40001) and\n * deadlocks (40P01) when `retryCount` is specified in options.\n *\n * @param callback - Function to execute within the transaction\n * @param options - Transaction options (isolation level, timeout, retry)\n * @returns The result of the callback\n *\n * @throws {DatabaseError} If transaction fails after all retries\n */\n async transaction<T>(\n callback: (ctx: TransactionContext) => Promise<T>,\n options?: TransactionOptions\n ): Promise<T> {\n const pool = this.ensurePool();\n const maxAttempts = (options?.retryCount ?? 0) + 1;\n const retryDelayMs = options?.retryDelayMs ?? 100;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const client = await pool.connect();\n const startTime = Date.now();\n\n try {\n // Begin transaction with options\n await this.beginTransaction(client, options);\n\n // Create transaction context\n const ctx = this.createTransactionContext(client);\n\n // Execute callback\n const result = await callback(ctx);\n\n // Commit transaction\n await client.query(\"COMMIT\");\n\n // Log success\n if (this.config.logger?.debug) {\n const durationMs = Date.now() - startTime;\n this.config.logger.debug(\"Transaction committed\", {\n attempt,\n durationMs,\n });\n }\n\n return result;\n } catch (error) {\n // Rollback transaction\n await client.query(\"ROLLBACK\").catch(() => {});\n\n lastError = error;\n\n // Check if error is retryable\n const pgError = error as { code?: string };\n const isRetryable =\n pgError.code === \"40001\" || // serialization_failure\n pgError.code === \"40P01\"; // deadlock\n\n if (isRetryable && attempt < maxAttempts) {\n if (this.config.logger?.warn) {\n this.config.logger.warn(\n `Transaction failed with ${pgError.code}, retrying (${attempt}/${maxAttempts})`,\n { code: pgError.code, attempt }\n );\n }\n await delay(retryDelayMs * attempt); // Exponential backoff\n continue;\n }\n\n throw this.classifyError(error);\n } finally {\n client.release();\n }\n }\n\n // Should not reach here, but handle just in case\n throw this.classifyError(lastError);\n }\n\n /**\n * Returns the database capabilities for PostgreSQL.\n *\n * @remarks\n * PostgreSQL has the most comprehensive feature set of all supported\n * databases, including JSONB, arrays, full-text search, and more.\n */\n getCapabilities(): DatabaseCapabilities {\n return {\n dialect: \"postgresql\",\n supportsJsonb: true,\n supportsJson: true,\n supportsArrays: true,\n supportsGeneratedColumns: true,\n supportsFts: true,\n supportsIlike: true,\n supportsReturning: true,\n supportsSavepoints: true,\n supportsOnConflict: true,\n maxParamsPerQuery: 65535, // PostgreSQL limit\n maxIdentifierLength: 63, // PostgreSQL default\n };\n }\n\n /**\n * Returns connection pool statistics.\n *\n * @returns Pool stats or null if not connected\n */\n override getPoolStats(): PoolStats | null {\n if (!this.pool) {\n return null;\n }\n\n return {\n total: this.pool.totalCount,\n idle: this.pool.idleCount,\n waiting: this.pool.waitingCount,\n active: this.pool.totalCount - this.pool.idleCount,\n };\n }\n\n /**\n * Override insertMany for bulk insert optimization.\n *\n * @remarks\n * Uses a single multi-row INSERT statement for better performance\n * when inserting multiple records.\n */\n override async insertMany<T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n // For single record, use parent implementation\n if (data.length === 1) {\n const result = await this.insert<T>(table, data[0], options);\n return [result];\n }\n\n // Build multi-row INSERT\n const columns = Object.keys(data[0]);\n const params: SqlParam[] = [];\n const valuesClauses: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const record = data[i];\n const placeholders: string[] = [];\n\n for (const col of columns) {\n params.push(record[col] as SqlParam);\n placeholders.push(`$${params.length}`);\n }\n\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n const columnList = columns\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columnList}) VALUES ${valuesClauses.join(\", \")}`;\n\n // Add RETURNING clause\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning.map(col => this.escapeIdentifier(col)).join(\", \");\n sql += ` RETURNING ${returning}`;\n }\n\n try {\n return await this.executeQuery<T>(sql, params);\n } catch (error) {\n throw this.handleQueryError(error, \"insertMany\", table);\n }\n }\n\n // ============================================================\n // Protected Helper Methods\n // ============================================================\n\n /**\n * Ensures pool is connected and returns it.\n *\n * @throws {DatabaseError} If not connected\n */\n private ensurePool(): Pool {\n if (!this.pool) {\n throw createDatabaseError({\n kind: \"connection\",\n message: \"PostgresAdapter is not connected. Call connect() first.\",\n });\n }\n return this.pool;\n }\n\n /**\n * Return the typed Drizzle instance for PostgreSQL.\n * Guarded for server-only usage and requires an active connection.\n *\n * @param schema - Optional schema for relational queries (db.query.*)\n * @returns Drizzle ORM instance wrapping the pg pool connection\n * @throws {Error} If called in browser or not connected\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getDrizzle<T = NodePgDatabase<any>>(schema?: Record<string, unknown>): T {\n if (typeof window !== \"undefined\") {\n throw new Error(\"getDrizzle() is server-only\");\n }\n const pool = this.ensurePool();\n return (schema ? drizzle(pool, { schema }) : drizzle(pool)) as T;\n }\n\n /**\n * Builds pg Pool configuration from adapter config.\n */\n private buildPoolConfig(): PoolConfig {\n const config: PoolConfig = {};\n\n // Connection string or explicit options\n if (this.config.url) {\n config.connectionString = this.config.url;\n } else {\n if (this.config.host) config.host = this.config.host;\n if (this.config.port) config.port = this.config.port;\n if (this.config.database) config.database = this.config.database;\n if (this.config.user) config.user = this.config.user;\n if (this.config.password) config.password = this.config.password;\n }\n\n // Pool settings (user config > provider defaults > hardcoded defaults)\n config.min =\n this.config.pool?.min ??\n this.providerDefaults.poolMin ??\n DEFAULT_POOL_CONFIG.min;\n config.max =\n this.config.pool?.max ??\n this.providerDefaults.poolMax ??\n DEFAULT_POOL_CONFIG.max;\n config.idleTimeoutMillis =\n this.config.pool?.idleTimeoutMs ??\n this.providerDefaults.idleTimeoutMs ??\n DEFAULT_POOL_CONFIG.idleTimeoutMs;\n config.connectionTimeoutMillis =\n this.config.pool?.connectionTimeoutMs ??\n this.providerDefaults.connectionTimeoutMs ??\n DEFAULT_POOL_CONFIG.connectionTimeoutMs;\n\n // TCP keepalive - prevents cloud databases (e.g. Neon) from silently\n // dropping idle connections between the pool smoke-test and the first\n // real query, which manifests as ETIMEDOUT on the query itself.\n config.keepAlive = true;\n config.keepAliveInitialDelayMillis = 10000;\n\n // SSL configuration (user config > provider default)\n if (this.config.ssl) {\n if (typeof this.config.ssl === \"boolean\") {\n config.ssl = this.config.ssl;\n } else {\n if (this.config.ssl.rejectUnauthorized === false) {\n console.warn(\n \"[nextly/adapter-postgres] ssl.rejectUnauthorized is set to false — \" +\n \"TLS certificates will not be validated. This is unsafe on untrusted networks. \" +\n \"Provide a trusted `ca` cert instead, or remove the rejectUnauthorized override.\"\n );\n }\n config.ssl = {\n rejectUnauthorized: this.config.ssl.rejectUnauthorized,\n ca: this.config.ssl.ca,\n cert: this.config.ssl.cert,\n key: this.config.ssl.key,\n };\n }\n } else if (this.providerDefaults.ssl) {\n // Provider requires SSL but user didn't explicitly configure it.\n // Default to validating certs; the user can opt out by setting\n // `ssl: { rejectUnauthorized: false }` explicitly (which logs a warning above).\n config.ssl = { rejectUnauthorized: true };\n }\n\n // PostgreSQL-specific options\n if (this.config.applicationName) {\n config.application_name = this.config.applicationName;\n }\n\n // User config beats provider default; both beat \"unset\".\n // Why: provider.ts:58 declared a Neon statementTimeoutMs default but the\n // adapter previously ignored it, leaving stuck queries to pin pool slots\n // indefinitely. Wire the fallback chain here so the declared defaults\n // actually fire.\n const effectiveStatementTimeout =\n this.config.statementTimeout ?? this.providerDefaults.statementTimeoutMs;\n if (effectiveStatementTimeout !== undefined) {\n config.statement_timeout = effectiveStatementTimeout;\n }\n\n if (this.config.queryTimeout) {\n config.query_timeout = this.config.queryTimeout;\n }\n\n return config;\n }\n\n /**\n * Begins a transaction with the specified options.\n */\n private async beginTransaction(\n client: PoolClient,\n options?: TransactionOptions\n ): Promise<void> {\n let beginSql = \"BEGIN\";\n\n // Add isolation level if specified\n if (options?.isolationLevel) {\n const isolationMap: Record<string, string> = {\n \"read uncommitted\": \"READ UNCOMMITTED\",\n \"read committed\": \"READ COMMITTED\",\n \"repeatable read\": \"REPEATABLE READ\",\n serializable: \"SERIALIZABLE\",\n };\n const level = isolationMap[options.isolationLevel];\n if (level) {\n beginSql += ` ISOLATION LEVEL ${level}`;\n }\n }\n\n // Add read-only mode if specified\n if (options?.readOnly) {\n beginSql += \" READ ONLY\";\n }\n\n await client.query(beginSql);\n\n // Set statement timeout if specified\n if (options?.timeoutMs) {\n await client.query(`SET LOCAL statement_timeout = ${options.timeoutMs}`);\n }\n }\n\n /**\n * Creates a TransactionContext for the given client.\n */\n private createTransactionContext(client: PoolClient): TransactionContext {\n return {\n execute: async <T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> => {\n const result = await client.query(sql, params as unknown[]);\n return result.rows as T[];\n },\n\n insert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options?: InsertOptions\n ): Promise<T> => {\n const columns = Object.keys(data);\n const values = Object.values(data);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES (${placeholders})`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, values);\n return result.rows[0] as T;\n },\n\n insertMany: async <T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> => {\n if (data.length === 0) return [];\n\n const columns = Object.keys(data[0]);\n const params: unknown[] = [];\n const valuesClauses: string[] = [];\n\n for (const record of data) {\n const placeholders: string[] = [];\n for (const col of columns) {\n params.push(record[col]);\n placeholders.push(`$${params.length}`);\n }\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES ${valuesClauses.join(\", \")}`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, params);\n return result.rows as T[];\n },\n\n // TransactionContext CRUD methods delegate to the adapter's CRUD\n // which uses Drizzle query API via the TableResolver.\n // The Drizzle transaction is handled at a higher level.\n select: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T[]> => {\n return this.select<T>(table, options);\n },\n\n selectOne: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T | null> => {\n return this.selectOne<T>(table, options);\n },\n\n update: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n where: WhereClause,\n options?: UpdateOptions\n ): Promise<T[]> => {\n return this.update<T>(table, data, where, options);\n },\n\n delete: async (\n table: string,\n where: WhereClause,\n _options?: DeleteOptions\n ): Promise<number> => {\n return this.delete(table, where);\n },\n\n upsert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options: UpsertOptions\n ): Promise<T> => {\n return this.upsert<T>(table, data, options);\n },\n\n savepoint: async (name: string): Promise<void> => {\n await client.query(`SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n\n rollbackToSavepoint: async (name: string): Promise<void> => {\n await client.query(\n `ROLLBACK TO SAVEPOINT ${this.escapeIdentifier(name)}`\n );\n },\n\n releaseSavepoint: async (name: string): Promise<void> => {\n await client.query(`RELEASE SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n };\n }\n\n /**\n * Classifies a PostgreSQL error into a DatabaseError.\n *\n * @param error - Original error from pg\n * @param sql - SQL statement that caused the error (optional)\n * @returns DatabaseError with proper classification\n */\n private classifyError(error: unknown, sql?: string): DatabaseError {\n // Why short-circuit on existing DatabaseError: F17's\n // UnsupportedDialectVersionError is already a typed DatabaseError with\n // kind: \"unsupported_version\" plus detectedVersion/requiredVersion\n // fields. Re-wrapping it here would erase those fields and re-tag it\n // as kind: \"unknown\".\n if (isDatabaseError(error)) return error;\n\n const pgError = error as {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n column?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n };\n\n // Determine error kind from PostgreSQL error code\n const kind: DatabaseErrorKind =\n (pgError.code && PG_ERROR_CODES[pgError.code]) || \"unknown\";\n\n // Build error message\n let message = pgError.message ?? String(error);\n if (sql && kind === \"query\") {\n message = `Query failed: ${message}`;\n }\n\n return createDatabaseError({\n kind,\n message,\n code: pgError.code,\n constraint: pgError.constraint,\n table: pgError.table,\n column: pgError.column,\n detail: pgError.detail,\n hint: pgError.hint,\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Override handleQueryError to use PostgreSQL-specific classification.\n */\n protected override handleQueryError(\n error: unknown,\n operation: string,\n table: string\n ): DatabaseError {\n const dbError = this.classifyError(error);\n\n // Add operation context if not already present\n if (!dbError.message.includes(operation)) {\n dbError.message = `${operation} operation failed on table '${table}': ${dbError.message}`;\n }\n\n if (!dbError.table) {\n dbError.table = table;\n }\n\n return dbError;\n }\n}\n\n/**\n * Creates a PostgreSQL database adapter instance.\n *\n * @remarks\n * This is the recommended way to create a PostgreSQL adapter.\n * The adapter is not connected after creation - call `connect()` to\n * establish the database connection.\n *\n * @param config - Adapter configuration\n * @returns A new PostgresAdapter instance\n *\n * @example\n * Simple usage:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * With full configuration:\n * ```typescript\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 5,\n * max: 20,\n * idleTimeoutMs: 30000,\n * connectionTimeoutMs: 10000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * ca: process.env.CA_CERT,\n * },\n * applicationName: 'my-app',\n * statementTimeout: 30000,\n * });\n * ```\n *\n * @public\n */\nexport function createPostgresAdapter(\n config: PostgresAdapterConfig\n): PostgresAdapter {\n return new PostgresAdapter(config);\n}\n\n/**\n * Type guard to check if a value is a PostgresAdapter instance.\n *\n * @param value - Value to check\n * @returns True if value is a PostgresAdapter\n *\n * @example\n * ```typescript\n * import { isPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * if (isPostgresAdapter(adapter)) {\n * // TypeScript knows adapter is PostgresAdapter\n * console.log(adapter.dialect); // 'postgresql'\n * }\n * ```\n *\n * @public\n */\nexport function isPostgresAdapter(value: unknown): value is PostgresAdapter {\n return value instanceof PostgresAdapter;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
1
2
|
import { DrizzleAdapter } from '@nextlyhq/adapter-drizzle';
|
|
2
3
|
import { createDatabaseError, isDatabaseError } from '@nextlyhq/adapter-drizzle/types';
|
|
3
4
|
import { checkDialectVersion } from '@nextlyhq/adapter-drizzle/version-check';
|
|
@@ -98,6 +99,21 @@ var PG_ERROR_CODES = {
|
|
|
98
99
|
function delay(ms) {
|
|
99
100
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
100
101
|
}
|
|
102
|
+
var HAPPY_EYEBALLS_MIN_TIMEOUT_MS = 5e3;
|
|
103
|
+
var happyEyeballsTimeoutApplied = false;
|
|
104
|
+
function applyHappyEyeballsTimeoutOnce() {
|
|
105
|
+
if (happyEyeballsTimeoutApplied) return;
|
|
106
|
+
happyEyeballsTimeoutApplied = true;
|
|
107
|
+
try {
|
|
108
|
+
const current = typeof net.getDefaultAutoSelectFamilyAttemptTimeout === "function" ? net.getDefaultAutoSelectFamilyAttemptTimeout() : 0;
|
|
109
|
+
if (current < HAPPY_EYEBALLS_MIN_TIMEOUT_MS) {
|
|
110
|
+
net.setDefaultAutoSelectFamilyAttemptTimeout(
|
|
111
|
+
HAPPY_EYEBALLS_MIN_TIMEOUT_MS
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
}
|
|
101
117
|
var PostgresAdapter = class extends DrizzleAdapter {
|
|
102
118
|
/**
|
|
103
119
|
* The database dialect - always 'postgresql' for this adapter.
|
|
@@ -145,6 +161,7 @@ var PostgresAdapter = class extends DrizzleAdapter {
|
|
|
145
161
|
* @throws {DatabaseError} If connection fails
|
|
146
162
|
*/
|
|
147
163
|
async connect() {
|
|
164
|
+
applyHappyEyeballsTimeoutOnce();
|
|
148
165
|
if (this.connected && this.pool) {
|
|
149
166
|
return;
|
|
150
167
|
}
|
|
@@ -511,8 +528,9 @@ var PostgresAdapter = class extends DrizzleAdapter {
|
|
|
511
528
|
if (this.config.applicationName) {
|
|
512
529
|
config.application_name = this.config.applicationName;
|
|
513
530
|
}
|
|
514
|
-
|
|
515
|
-
|
|
531
|
+
const effectiveStatementTimeout = this.config.statementTimeout ?? this.providerDefaults.statementTimeoutMs;
|
|
532
|
+
if (effectiveStatementTimeout !== void 0) {
|
|
533
|
+
config.statement_timeout = effectiveStatementTimeout;
|
|
516
534
|
}
|
|
517
535
|
if (this.config.queryTimeout) {
|
|
518
536
|
config.query_timeout = this.config.queryTimeout;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// Auto-detects PostgreSQL provider from DATABASE_URL pattern\n// and returns appropriate connection defaults.\n// Standard pg driver works with all providers - only config changes.\n\nexport type PostgresProvider = \"standard\" | \"neon\" | \"supabase\";\n\nexport interface ProviderDefaults {\n ssl: boolean;\n poolMax: number;\n poolMin: number;\n idleTimeoutMs: number;\n connectionTimeoutMs: number;\n statementTimeoutMs: number;\n retryAttempts: number;\n}\n\n// Detect provider from URL pattern or explicit override\nexport function detectPostgresProvider(\n url: string,\n explicitProvider?: string\n): PostgresProvider {\n // Explicit override takes priority (if valid)\n if (explicitProvider) {\n const normalized = explicitProvider.toLowerCase();\n if (\n normalized === \"neon\" ||\n normalized === \"supabase\" ||\n normalized === \"standard\"\n ) {\n return normalized;\n }\n }\n\n // Auto-detect from URL hostname\n if (url.includes(\".neon.tech\") || url.includes(\"neon.\")) {\n return \"neon\";\n }\n if (url.includes(\".supabase.\") || url.includes(\"supabase.\")) {\n return \"supabase\";\n }\n\n return \"standard\";\n}\n\n// Get connection defaults for a provider\nexport function getProviderDefaults(\n provider: PostgresProvider\n): ProviderDefaults {\n switch (provider) {\n case \"neon\":\n // Neon: serverless PG with auto-suspend, cold starts need more retries\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 10000,\n connectionTimeoutMs: 20000,\n statementTimeoutMs: 30000,\n retryAttempts: 5,\n };\n case \"supabase\":\n // Supabase: managed PG with Supavisor pooler, SSL required\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n case \"standard\":\n default:\n // Standard: Docker, self-hosted, direct PG connections\n return {\n ssl: false,\n poolMax: 10,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n }\n}\n","/**\n * @nextlyhq/adapter-postgres\n *\n * PostgreSQL database adapter for Nextly.\n * Extends the base DrizzleAdapter from @nextlyhq/adapter-drizzle to provide\n * PostgreSQL-specific functionality.\n *\n * @remarks\n * This adapter uses the `pg` (node-postgres) driver for database connections\n * and integrates with Drizzle ORM for type-safe queries.\n *\n * Features:\n * - Connection pooling via pg.Pool\n * - Full transaction support with savepoints\n * - RETURNING clause support for all CRUD operations\n * - PostgreSQL-specific error classification\n * - JSONB support\n * - Full-text search capabilities\n * - Automatic retry for serialization failures and deadlocks\n *\n * @example\n * Simple usage with connection string:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * Full configuration:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 2,\n * max: 20,\n * idleTimeoutMs: 30000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * },\n * applicationName: 'my-nextly-app',\n * });\n * ```\n *\n * @example\n * Using the adapter class directly:\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n * import type { PostgresAdapterConfig } from '@nextlyhq/adapter-postgres';\n *\n * const config: PostgresAdapterConfig = {\n * url: process.env.DATABASE_URL!,\n * };\n *\n * const adapter = new PostgresAdapter(config);\n * await adapter.connect();\n * ```\n *\n * @packageDocumentation\n */\n\nimport { DrizzleAdapter } from \"@nextlyhq/adapter-drizzle\";\n// F17: connect-time DB version check shared across all adapters.\nimport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n WhereClause,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport {\n createDatabaseError,\n isDatabaseError,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport { checkDialectVersion } from \"@nextlyhq/adapter-drizzle/version-check\";\nimport { drizzle, type NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient, PoolConfig } from \"pg\";\nimport { Pool } from \"pg\";\n\nimport {\n detectPostgresProvider,\n getProviderDefaults,\n type PostgresProvider,\n type ProviderDefaults,\n} from \"./provider\";\n\n// Re-export types from @nextlyhq/adapter-drizzle for convenience\nexport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n // Additional types users might need\n BaseAdapterConfig,\n AdapterLogger,\n PoolConfig as AdapterPoolConfig,\n SslConfig,\n WhereClause,\n WhereCondition,\n WhereOperator,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n OrderBySpec,\n JoinSpec,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\n\n/**\n * Package version.\n */\nexport const VERSION = \"0.1.0\";\n\n/**\n * Default pool configuration values.\n *\n * min: 0 – Never eagerly create background connections. This is critical\n * for cold-start recovery (e.g. Neon auto-suspend): after the\n * initial smoke-test connection, the pool won't immediately try\n * to create additional connections that might still fail while\n * the DB is waking up.\n *\n * max: 5 – Conservative default to avoid overwhelming cloud databases\n * (Neon free-tier limit is ~25-30 simultaneous connections).\n * With Next.js spawning up to 7 build workers this keeps the\n * total connection count safely under typical limits.\n */\nconst DEFAULT_POOL_CONFIG = {\n min: 0,\n max: 5,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n};\n\n/**\n * PostgreSQL error codes mapping to DatabaseErrorKind.\n *\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\nconst PG_ERROR_CODES: Record<string, DatabaseErrorKind> = {\n // Class 08 - Connection Exception\n \"08000\": \"connection\",\n \"08003\": \"connection\",\n \"08006\": \"connection\",\n \"08001\": \"connection\",\n \"08004\": \"connection\",\n \"08007\": \"connection\",\n \"08P01\": \"connection\",\n\n // Class 23 - Integrity Constraint Violation\n \"23000\": \"constraint\",\n \"23001\": \"constraint\",\n \"23502\": \"not_null_violation\",\n \"23503\": \"foreign_key_violation\",\n \"23505\": \"unique_violation\",\n \"23514\": \"check_violation\",\n \"23P01\": \"constraint\",\n\n // Class 40 - Transaction Rollback\n \"40000\": \"query\",\n \"40001\": \"serialization_failure\",\n \"40002\": \"constraint\",\n \"40003\": \"query\",\n \"40P01\": \"deadlock\",\n\n // Class 57 - Operator Intervention\n \"57014\": \"timeout\",\n \"57P01\": \"connection\",\n \"57P02\": \"connection\",\n \"57P03\": \"connection\",\n};\n\n/**\n * Delay helper for retry logic.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * PostgreSQL database adapter for Nextly.\n *\n * @remarks\n * This class extends the base DrizzleAdapter to provide PostgreSQL-specific\n * functionality including:\n *\n * - Connection pooling with pg.Pool\n * - Transaction support with savepoints\n * - PostgreSQL-specific error codes\n * - JSONB and array type support\n * - Full-text search\n * - Automatic retry for serialization failures and deadlocks\n *\n * For most use cases, use the `createPostgresAdapter` factory function\n * instead of instantiating this class directly.\n *\n * @example\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = new PostgresAdapter({\n * url: 'postgres://user:pass@localhost:5432/mydb',\n * });\n *\n * await adapter.connect();\n *\n * // Use the adapter\n * const users = await adapter.select('users', {\n * where: { and: [{ column: 'status', op: '=', value: 'active' }] },\n * });\n *\n * await adapter.disconnect();\n * ```\n *\n * @public\n */\nexport class PostgresAdapter extends DrizzleAdapter {\n /**\n * The database dialect - always 'postgresql' for this adapter.\n */\n public readonly dialect = \"postgresql\" as const;\n\n /**\n * Adapter configuration.\n */\n protected readonly config: PostgresAdapterConfig;\n\n /**\n * Connection pool instance.\n */\n private pool: Pool | null = null;\n\n /**\n * Connection state flag.\n */\n private connected = false;\n\n /**\n * Auto-detected provider (Neon, Supabase, or standard).\n * Set during connect() from DATABASE_URL pattern or DB_PROVIDER env var.\n */\n private detectedProvider: PostgresProvider = \"standard\";\n\n /**\n * Provider-specific connection defaults. Applied as fallbacks when\n * user config doesn't specify a value.\n */\n private providerDefaults: ProviderDefaults = getProviderDefaults(\"standard\");\n\n /**\n * Creates a new PostgreSQL adapter instance.\n *\n * @param config - Adapter configuration\n */\n constructor(config: PostgresAdapterConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Establishes a connection to the PostgreSQL database.\n *\n * @remarks\n * This method initializes the connection pool and verifies connectivity\n * by executing a simple query. It is idempotent - calling it multiple\n * times will not create multiple pools.\n *\n * @throws {DatabaseError} If connection fails\n */\n async connect(): Promise<void> {\n if (this.connected && this.pool) {\n return;\n }\n\n // Auto-detect provider from URL and apply defaults\n const url = this.config.url || \"\";\n this.detectedProvider = detectPostgresProvider(\n url,\n process.env.DB_PROVIDER\n );\n this.providerDefaults = getProviderDefaults(this.detectedProvider);\n\n // Log detected provider for developer awareness\n if (this.config.logger?.info) {\n const source = process.env.DB_PROVIDER ? \"(explicit)\" : \"(auto-detected)\";\n this.config.logger.info(\n `PostgreSQL provider: ${this.detectedProvider} ${source}`,\n {}\n );\n }\n\n // Node.js network error codes that are safe to retry (transient failures).\n // These cover cloud databases (e.g. Neon) waking from auto-suspend, brief\n // network hiccups, and DNS resolution races during build parallelism.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ]);\n\n // Use provider-specific retry count (Neon needs more for cold starts)\n const maxAttempts = this.providerDefaults.retryAttempts;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const poolConfig = this.buildPoolConfig();\n this.pool = new Pool(poolConfig);\n\n // Handle pool errors (background errors on idle clients)\n this.pool.on(\"error\", (err: Error) => {\n // Log through adapter logger if configured\n if (this.config.logger?.error) {\n this.config.logger.error(err, {\n context: \"pool_error\",\n message: \"Unexpected error on idle client\",\n });\n }\n // Client is automatically removed from pool, no action needed\n });\n\n // Verify connection with smoke test, then check dialect version.\n // Why: F17 hard-fails at connect on unsupported PG versions (<15.0)\n // so users see a clear upgrade pointer instead of cryptic errors\n // mid-apply later. The version query runs inside the existing retry\n // loop's try block, so transient network failures (Neon cold start,\n // EAI_AGAIN) continue to retry; only confirmed version mismatch\n // surfaces as UnsupportedDialectVersionError and exits the loop.\n const client = await this.pool.connect();\n try {\n await client.query(\"SELECT 1\");\n await checkDialectVersion(client, \"postgresql\", {\n // Why: route any future variant warnings through the adapter's\n // logger. PG has no recognized variants today, but this keeps\n // the integration symmetric with MySQL.\n onWarning: msg => this.config.logger?.warn?.(msg),\n });\n this.connected = true;\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection established\", {\n host: this.config.host ?? \"from URL\",\n database: this.config.database ?? \"from URL\",\n });\n }\n\n return; // Success — exit retry loop\n } finally {\n client.release();\n }\n } catch (error) {\n // Clean up the failed pool before deciding whether to retry\n if (this.pool) {\n await this.pool.end().catch(() => {});\n this.pool = null;\n }\n\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxAttempts) {\n // Exponential back-off with jitter: ~1 s, ~2 s, ~3 s, ~4 s\n const waitMs = 1000 * attempt;\n const msg = `PostgreSQL connection attempt ${attempt}/${maxAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`;\n if (this.config.logger?.warn) {\n this.config.logger.warn(msg);\n } else {\n console.warn(`[PostgresAdapter] ${msg}`);\n }\n await delay(waitMs);\n continue;\n }\n\n // Non-retryable error or exhausted retries — surface to caller\n throw this.classifyError(error);\n }\n }\n }\n\n /**\n * Closes the database connection and releases all pool resources.\n *\n * @remarks\n * This method is idempotent - calling it multiple times is safe.\n * It waits for all checked-out clients to be returned before shutting down.\n */\n async disconnect(): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n try {\n await this.pool.end();\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection closed\");\n }\n } finally {\n this.pool = null;\n this.connected = false;\n }\n }\n\n /**\n * Checks if the adapter is currently connected.\n *\n * @returns True if connected and pool is available\n */\n override isConnected(): boolean {\n return this.connected && this.pool !== null;\n }\n\n /**\n * Executes a raw SQL query.\n *\n * @param sql - SQL statement with $1, $2, ... placeholders\n * @param params - Query parameters\n * @returns Array of result rows\n *\n * @throws {DatabaseError} If query execution fails\n */\n async executeQuery<T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> {\n const pool = this.ensurePool();\n const startTime = Date.now();\n\n // Transient network errors that are safe to retry at the query level.\n // These occur when Neon auto-suspends between the pool smoke-test and the\n // actual query, or when multiple build workers compete for cold-start.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n ]);\n const maxQueryAttempts = 3;\n\n for (let attempt = 1; attempt <= maxQueryAttempts; attempt++) {\n try {\n const result = await pool.query(sql, params as unknown[]);\n\n // Log query if logger configured\n if (this.config.logger?.query) {\n const durationMs = Date.now() - startTime;\n this.config.logger.query(sql, params, durationMs);\n }\n\n return result.rows as T[];\n } catch (error) {\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxQueryAttempts) {\n const waitMs = 500 * attempt;\n console.warn(\n `[PostgresAdapter] Query attempt ${attempt}/${maxQueryAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`\n );\n await delay(waitMs);\n continue;\n }\n\n throw this.classifyError(error, sql);\n }\n }\n\n // Unreachable — loop always returns or throws\n throw this.classifyError(new Error(\"executeQuery: exhausted retries\"));\n }\n\n /**\n * Executes a callback within a database transaction.\n *\n * @remarks\n * PostgreSQL supports full ACID transactions with savepoints.\n * If the callback throws, the transaction is rolled back.\n *\n * Supports automatic retry for serialization failures (40001) and\n * deadlocks (40P01) when `retryCount` is specified in options.\n *\n * @param callback - Function to execute within the transaction\n * @param options - Transaction options (isolation level, timeout, retry)\n * @returns The result of the callback\n *\n * @throws {DatabaseError} If transaction fails after all retries\n */\n async transaction<T>(\n callback: (ctx: TransactionContext) => Promise<T>,\n options?: TransactionOptions\n ): Promise<T> {\n const pool = this.ensurePool();\n const maxAttempts = (options?.retryCount ?? 0) + 1;\n const retryDelayMs = options?.retryDelayMs ?? 100;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const client = await pool.connect();\n const startTime = Date.now();\n\n try {\n // Begin transaction with options\n await this.beginTransaction(client, options);\n\n // Create transaction context\n const ctx = this.createTransactionContext(client);\n\n // Execute callback\n const result = await callback(ctx);\n\n // Commit transaction\n await client.query(\"COMMIT\");\n\n // Log success\n if (this.config.logger?.debug) {\n const durationMs = Date.now() - startTime;\n this.config.logger.debug(\"Transaction committed\", {\n attempt,\n durationMs,\n });\n }\n\n return result;\n } catch (error) {\n // Rollback transaction\n await client.query(\"ROLLBACK\").catch(() => {});\n\n lastError = error;\n\n // Check if error is retryable\n const pgError = error as { code?: string };\n const isRetryable =\n pgError.code === \"40001\" || // serialization_failure\n pgError.code === \"40P01\"; // deadlock\n\n if (isRetryable && attempt < maxAttempts) {\n if (this.config.logger?.warn) {\n this.config.logger.warn(\n `Transaction failed with ${pgError.code}, retrying (${attempt}/${maxAttempts})`,\n { code: pgError.code, attempt }\n );\n }\n await delay(retryDelayMs * attempt); // Exponential backoff\n continue;\n }\n\n throw this.classifyError(error);\n } finally {\n client.release();\n }\n }\n\n // Should not reach here, but handle just in case\n throw this.classifyError(lastError);\n }\n\n /**\n * Returns the database capabilities for PostgreSQL.\n *\n * @remarks\n * PostgreSQL has the most comprehensive feature set of all supported\n * databases, including JSONB, arrays, full-text search, and more.\n */\n getCapabilities(): DatabaseCapabilities {\n return {\n dialect: \"postgresql\",\n supportsJsonb: true,\n supportsJson: true,\n supportsArrays: true,\n supportsGeneratedColumns: true,\n supportsFts: true,\n supportsIlike: true,\n supportsReturning: true,\n supportsSavepoints: true,\n supportsOnConflict: true,\n maxParamsPerQuery: 65535, // PostgreSQL limit\n maxIdentifierLength: 63, // PostgreSQL default\n };\n }\n\n /**\n * Returns connection pool statistics.\n *\n * @returns Pool stats or null if not connected\n */\n override getPoolStats(): PoolStats | null {\n if (!this.pool) {\n return null;\n }\n\n return {\n total: this.pool.totalCount,\n idle: this.pool.idleCount,\n waiting: this.pool.waitingCount,\n active: this.pool.totalCount - this.pool.idleCount,\n };\n }\n\n /**\n * Override insertMany for bulk insert optimization.\n *\n * @remarks\n * Uses a single multi-row INSERT statement for better performance\n * when inserting multiple records.\n */\n override async insertMany<T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n // For single record, use parent implementation\n if (data.length === 1) {\n const result = await this.insert<T>(table, data[0], options);\n return [result];\n }\n\n // Build multi-row INSERT\n const columns = Object.keys(data[0]);\n const params: SqlParam[] = [];\n const valuesClauses: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const record = data[i];\n const placeholders: string[] = [];\n\n for (const col of columns) {\n params.push(record[col] as SqlParam);\n placeholders.push(`$${params.length}`);\n }\n\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n const columnList = columns\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columnList}) VALUES ${valuesClauses.join(\", \")}`;\n\n // Add RETURNING clause\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning.map(col => this.escapeIdentifier(col)).join(\", \");\n sql += ` RETURNING ${returning}`;\n }\n\n try {\n return await this.executeQuery<T>(sql, params);\n } catch (error) {\n throw this.handleQueryError(error, \"insertMany\", table);\n }\n }\n\n // ============================================================\n // Protected Helper Methods\n // ============================================================\n\n /**\n * Ensures pool is connected and returns it.\n *\n * @throws {DatabaseError} If not connected\n */\n private ensurePool(): Pool {\n if (!this.pool) {\n throw createDatabaseError({\n kind: \"connection\",\n message: \"PostgresAdapter is not connected. Call connect() first.\",\n });\n }\n return this.pool;\n }\n\n /**\n * Return the typed Drizzle instance for PostgreSQL.\n * Guarded for server-only usage and requires an active connection.\n *\n * @param schema - Optional schema for relational queries (db.query.*)\n * @returns Drizzle ORM instance wrapping the pg pool connection\n * @throws {Error} If called in browser or not connected\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getDrizzle<T = NodePgDatabase<any>>(schema?: Record<string, unknown>): T {\n if (typeof window !== \"undefined\") {\n throw new Error(\"getDrizzle() is server-only\");\n }\n const pool = this.ensurePool();\n return (schema ? drizzle(pool, { schema }) : drizzle(pool)) as T;\n }\n\n /**\n * Builds pg Pool configuration from adapter config.\n */\n private buildPoolConfig(): PoolConfig {\n const config: PoolConfig = {};\n\n // Connection string or explicit options\n if (this.config.url) {\n config.connectionString = this.config.url;\n } else {\n if (this.config.host) config.host = this.config.host;\n if (this.config.port) config.port = this.config.port;\n if (this.config.database) config.database = this.config.database;\n if (this.config.user) config.user = this.config.user;\n if (this.config.password) config.password = this.config.password;\n }\n\n // Pool settings (user config > provider defaults > hardcoded defaults)\n config.min =\n this.config.pool?.min ??\n this.providerDefaults.poolMin ??\n DEFAULT_POOL_CONFIG.min;\n config.max =\n this.config.pool?.max ??\n this.providerDefaults.poolMax ??\n DEFAULT_POOL_CONFIG.max;\n config.idleTimeoutMillis =\n this.config.pool?.idleTimeoutMs ??\n this.providerDefaults.idleTimeoutMs ??\n DEFAULT_POOL_CONFIG.idleTimeoutMs;\n config.connectionTimeoutMillis =\n this.config.pool?.connectionTimeoutMs ??\n this.providerDefaults.connectionTimeoutMs ??\n DEFAULT_POOL_CONFIG.connectionTimeoutMs;\n\n // TCP keepalive - prevents cloud databases (e.g. Neon) from silently\n // dropping idle connections between the pool smoke-test and the first\n // real query, which manifests as ETIMEDOUT on the query itself.\n config.keepAlive = true;\n config.keepAliveInitialDelayMillis = 10000;\n\n // SSL configuration (user config > provider default)\n if (this.config.ssl) {\n if (typeof this.config.ssl === \"boolean\") {\n config.ssl = this.config.ssl;\n } else {\n if (this.config.ssl.rejectUnauthorized === false) {\n console.warn(\n \"[nextly/adapter-postgres] ssl.rejectUnauthorized is set to false — \" +\n \"TLS certificates will not be validated. This is unsafe on untrusted networks. \" +\n \"Provide a trusted `ca` cert instead, or remove the rejectUnauthorized override.\"\n );\n }\n config.ssl = {\n rejectUnauthorized: this.config.ssl.rejectUnauthorized,\n ca: this.config.ssl.ca,\n cert: this.config.ssl.cert,\n key: this.config.ssl.key,\n };\n }\n } else if (this.providerDefaults.ssl) {\n // Provider requires SSL but user didn't explicitly configure it.\n // Default to validating certs; the user can opt out by setting\n // `ssl: { rejectUnauthorized: false }` explicitly (which logs a warning above).\n config.ssl = { rejectUnauthorized: true };\n }\n\n // PostgreSQL-specific options\n if (this.config.applicationName) {\n config.application_name = this.config.applicationName;\n }\n\n if (this.config.statementTimeout) {\n config.statement_timeout = this.config.statementTimeout;\n }\n\n if (this.config.queryTimeout) {\n config.query_timeout = this.config.queryTimeout;\n }\n\n return config;\n }\n\n /**\n * Begins a transaction with the specified options.\n */\n private async beginTransaction(\n client: PoolClient,\n options?: TransactionOptions\n ): Promise<void> {\n let beginSql = \"BEGIN\";\n\n // Add isolation level if specified\n if (options?.isolationLevel) {\n const isolationMap: Record<string, string> = {\n \"read uncommitted\": \"READ UNCOMMITTED\",\n \"read committed\": \"READ COMMITTED\",\n \"repeatable read\": \"REPEATABLE READ\",\n serializable: \"SERIALIZABLE\",\n };\n const level = isolationMap[options.isolationLevel];\n if (level) {\n beginSql += ` ISOLATION LEVEL ${level}`;\n }\n }\n\n // Add read-only mode if specified\n if (options?.readOnly) {\n beginSql += \" READ ONLY\";\n }\n\n await client.query(beginSql);\n\n // Set statement timeout if specified\n if (options?.timeoutMs) {\n await client.query(`SET LOCAL statement_timeout = ${options.timeoutMs}`);\n }\n }\n\n /**\n * Creates a TransactionContext for the given client.\n */\n private createTransactionContext(client: PoolClient): TransactionContext {\n return {\n execute: async <T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> => {\n const result = await client.query(sql, params as unknown[]);\n return result.rows as T[];\n },\n\n insert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options?: InsertOptions\n ): Promise<T> => {\n const columns = Object.keys(data);\n const values = Object.values(data);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES (${placeholders})`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, values);\n return result.rows[0] as T;\n },\n\n insertMany: async <T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> => {\n if (data.length === 0) return [];\n\n const columns = Object.keys(data[0]);\n const params: unknown[] = [];\n const valuesClauses: string[] = [];\n\n for (const record of data) {\n const placeholders: string[] = [];\n for (const col of columns) {\n params.push(record[col]);\n placeholders.push(`$${params.length}`);\n }\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES ${valuesClauses.join(\", \")}`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, params);\n return result.rows as T[];\n },\n\n // TransactionContext CRUD methods delegate to the adapter's CRUD\n // which uses Drizzle query API via the TableResolver.\n // The Drizzle transaction is handled at a higher level.\n select: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T[]> => {\n return this.select<T>(table, options);\n },\n\n selectOne: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T | null> => {\n return this.selectOne<T>(table, options);\n },\n\n update: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n where: WhereClause,\n options?: UpdateOptions\n ): Promise<T[]> => {\n return this.update<T>(table, data, where, options);\n },\n\n delete: async (\n table: string,\n where: WhereClause,\n _options?: DeleteOptions\n ): Promise<number> => {\n return this.delete(table, where);\n },\n\n upsert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options: UpsertOptions\n ): Promise<T> => {\n return this.upsert<T>(table, data, options);\n },\n\n savepoint: async (name: string): Promise<void> => {\n await client.query(`SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n\n rollbackToSavepoint: async (name: string): Promise<void> => {\n await client.query(\n `ROLLBACK TO SAVEPOINT ${this.escapeIdentifier(name)}`\n );\n },\n\n releaseSavepoint: async (name: string): Promise<void> => {\n await client.query(`RELEASE SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n };\n }\n\n /**\n * Classifies a PostgreSQL error into a DatabaseError.\n *\n * @param error - Original error from pg\n * @param sql - SQL statement that caused the error (optional)\n * @returns DatabaseError with proper classification\n */\n private classifyError(error: unknown, sql?: string): DatabaseError {\n // Why short-circuit on existing DatabaseError: F17's\n // UnsupportedDialectVersionError is already a typed DatabaseError with\n // kind: \"unsupported_version\" plus detectedVersion/requiredVersion\n // fields. Re-wrapping it here would erase those fields and re-tag it\n // as kind: \"unknown\".\n if (isDatabaseError(error)) return error;\n\n const pgError = error as {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n column?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n };\n\n // Determine error kind from PostgreSQL error code\n const kind: DatabaseErrorKind =\n (pgError.code && PG_ERROR_CODES[pgError.code]) || \"unknown\";\n\n // Build error message\n let message = pgError.message ?? String(error);\n if (sql && kind === \"query\") {\n message = `Query failed: ${message}`;\n }\n\n return createDatabaseError({\n kind,\n message,\n code: pgError.code,\n constraint: pgError.constraint,\n table: pgError.table,\n column: pgError.column,\n detail: pgError.detail,\n hint: pgError.hint,\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Override handleQueryError to use PostgreSQL-specific classification.\n */\n protected override handleQueryError(\n error: unknown,\n operation: string,\n table: string\n ): DatabaseError {\n const dbError = this.classifyError(error);\n\n // Add operation context if not already present\n if (!dbError.message.includes(operation)) {\n dbError.message = `${operation} operation failed on table '${table}': ${dbError.message}`;\n }\n\n if (!dbError.table) {\n dbError.table = table;\n }\n\n return dbError;\n }\n}\n\n/**\n * Creates a PostgreSQL database adapter instance.\n *\n * @remarks\n * This is the recommended way to create a PostgreSQL adapter.\n * The adapter is not connected after creation - call `connect()` to\n * establish the database connection.\n *\n * @param config - Adapter configuration\n * @returns A new PostgresAdapter instance\n *\n * @example\n * Simple usage:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * With full configuration:\n * ```typescript\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 5,\n * max: 20,\n * idleTimeoutMs: 30000,\n * connectionTimeoutMs: 10000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * ca: process.env.CA_CERT,\n * },\n * applicationName: 'my-app',\n * statementTimeout: 30000,\n * });\n * ```\n *\n * @public\n */\nexport function createPostgresAdapter(\n config: PostgresAdapterConfig\n): PostgresAdapter {\n return new PostgresAdapter(config);\n}\n\n/**\n * Type guard to check if a value is a PostgresAdapter instance.\n *\n * @param value - Value to check\n * @returns True if value is a PostgresAdapter\n *\n * @example\n * ```typescript\n * import { isPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * if (isPostgresAdapter(adapter)) {\n * // TypeScript knows adapter is PostgresAdapter\n * console.log(adapter.dialect); // 'postgresql'\n * }\n * ```\n *\n * @public\n */\nexport function isPostgresAdapter(value: unknown): value is PostgresAdapter {\n return value instanceof PostgresAdapter;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// Auto-detects PostgreSQL provider from DATABASE_URL pattern\n// and returns appropriate connection defaults.\n// Standard pg driver works with all providers - only config changes.\n\nexport type PostgresProvider = \"standard\" | \"neon\" | \"supabase\";\n\nexport interface ProviderDefaults {\n ssl: boolean;\n poolMax: number;\n poolMin: number;\n idleTimeoutMs: number;\n connectionTimeoutMs: number;\n statementTimeoutMs: number;\n retryAttempts: number;\n}\n\n// Detect provider from URL pattern or explicit override\nexport function detectPostgresProvider(\n url: string,\n explicitProvider?: string\n): PostgresProvider {\n // Explicit override takes priority (if valid)\n if (explicitProvider) {\n const normalized = explicitProvider.toLowerCase();\n if (\n normalized === \"neon\" ||\n normalized === \"supabase\" ||\n normalized === \"standard\"\n ) {\n return normalized;\n }\n }\n\n // Auto-detect from URL hostname\n if (url.includes(\".neon.tech\") || url.includes(\"neon.\")) {\n return \"neon\";\n }\n if (url.includes(\".supabase.\") || url.includes(\"supabase.\")) {\n return \"supabase\";\n }\n\n return \"standard\";\n}\n\n// Get connection defaults for a provider\nexport function getProviderDefaults(\n provider: PostgresProvider\n): ProviderDefaults {\n switch (provider) {\n case \"neon\":\n // Neon: serverless PG with auto-suspend, cold starts need more retries\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 10000,\n connectionTimeoutMs: 20000,\n statementTimeoutMs: 30000,\n retryAttempts: 5,\n };\n case \"supabase\":\n // Supabase: managed PG with Supavisor pooler, SSL required\n return {\n ssl: true,\n poolMax: 5,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n case \"standard\":\n default:\n // Standard: Docker, self-hosted, direct PG connections\n return {\n ssl: false,\n poolMax: 10,\n poolMin: 0,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n statementTimeoutMs: 15000,\n retryAttempts: 3,\n };\n }\n}\n","/**\n * @nextlyhq/adapter-postgres\n *\n * PostgreSQL database adapter for Nextly.\n * Extends the base DrizzleAdapter from @nextlyhq/adapter-drizzle to provide\n * PostgreSQL-specific functionality.\n *\n * @remarks\n * This adapter uses the `pg` (node-postgres) driver for database connections\n * and integrates with Drizzle ORM for type-safe queries.\n *\n * Features:\n * - Connection pooling via pg.Pool\n * - Full transaction support with savepoints\n * - RETURNING clause support for all CRUD operations\n * - PostgreSQL-specific error classification\n * - JSONB support\n * - Full-text search capabilities\n * - Automatic retry for serialization failures and deadlocks\n *\n * @example\n * Simple usage with connection string:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * Full configuration:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 2,\n * max: 20,\n * idleTimeoutMs: 30000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * },\n * applicationName: 'my-nextly-app',\n * });\n * ```\n *\n * @example\n * Using the adapter class directly:\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n * import type { PostgresAdapterConfig } from '@nextlyhq/adapter-postgres';\n *\n * const config: PostgresAdapterConfig = {\n * url: process.env.DATABASE_URL!,\n * };\n *\n * const adapter = new PostgresAdapter(config);\n * await adapter.connect();\n * ```\n *\n * @packageDocumentation\n */\n\nimport * as net from \"node:net\";\n\nimport { DrizzleAdapter } from \"@nextlyhq/adapter-drizzle\";\n// F17: connect-time DB version check shared across all adapters.\nimport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n WhereClause,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport {\n createDatabaseError,\n isDatabaseError,\n} from \"@nextlyhq/adapter-drizzle/types\";\nimport { checkDialectVersion } from \"@nextlyhq/adapter-drizzle/version-check\";\nimport { drizzle, type NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient, PoolConfig } from \"pg\";\nimport { Pool } from \"pg\";\n\nimport {\n detectPostgresProvider,\n getProviderDefaults,\n type PostgresProvider,\n type ProviderDefaults,\n} from \"./provider\";\n\n// Re-export types from @nextlyhq/adapter-drizzle for convenience\nexport type {\n PostgresAdapterConfig,\n DatabaseCapabilities,\n PoolStats,\n TransactionContext,\n TransactionOptions,\n SqlParam,\n // Additional types users might need\n BaseAdapterConfig,\n AdapterLogger,\n PoolConfig as AdapterPoolConfig,\n SslConfig,\n WhereClause,\n WhereCondition,\n WhereOperator,\n SelectOptions,\n InsertOptions,\n UpdateOptions,\n DeleteOptions,\n UpsertOptions,\n OrderBySpec,\n JoinSpec,\n DatabaseError,\n DatabaseErrorKind,\n} from \"@nextlyhq/adapter-drizzle/types\";\n\n/**\n * Package version.\n */\nexport const VERSION = \"0.1.0\";\n\n/**\n * Default pool configuration values.\n *\n * min: 0 – Never eagerly create background connections. This is critical\n * for cold-start recovery (e.g. Neon auto-suspend): after the\n * initial smoke-test connection, the pool won't immediately try\n * to create additional connections that might still fail while\n * the DB is waking up.\n *\n * max: 5 – Conservative default to avoid overwhelming cloud databases\n * (Neon free-tier limit is ~25-30 simultaneous connections).\n * With Next.js spawning up to 7 build workers this keeps the\n * total connection count safely under typical limits.\n */\nconst DEFAULT_POOL_CONFIG = {\n min: 0,\n max: 5,\n idleTimeoutMs: 30000,\n connectionTimeoutMs: 15000,\n};\n\n/**\n * PostgreSQL error codes mapping to DatabaseErrorKind.\n *\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\nconst PG_ERROR_CODES: Record<string, DatabaseErrorKind> = {\n // Class 08 - Connection Exception\n \"08000\": \"connection\",\n \"08003\": \"connection\",\n \"08006\": \"connection\",\n \"08001\": \"connection\",\n \"08004\": \"connection\",\n \"08007\": \"connection\",\n \"08P01\": \"connection\",\n\n // Class 23 - Integrity Constraint Violation\n \"23000\": \"constraint\",\n \"23001\": \"constraint\",\n \"23502\": \"not_null_violation\",\n \"23503\": \"foreign_key_violation\",\n \"23505\": \"unique_violation\",\n \"23514\": \"check_violation\",\n \"23P01\": \"constraint\",\n\n // Class 40 - Transaction Rollback\n \"40000\": \"query\",\n \"40001\": \"serialization_failure\",\n \"40002\": \"constraint\",\n \"40003\": \"query\",\n \"40P01\": \"deadlock\",\n\n // Class 57 - Operator Intervention\n \"57014\": \"timeout\",\n \"57P01\": \"connection\",\n \"57P02\": \"connection\",\n \"57P03\": \"connection\",\n};\n\n/**\n * Delay helper for retry logic.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n// Node 20+ defaults the Happy Eyeballs per-address connection-attempt timeout\n// to 250ms. For consumers connecting from a region with RTT > 250ms to their\n// database (typical transcontinental: Pakistan→Singapore is ~310ms),\n// every TCP attempt is killed mid-handshake and the pg driver reports\n// ETIMEDOUT after exhausting all DNS-resolved addresses — even though the\n// network is fine.\n//\n// We bump the timeout to 5000ms on first adapter connect. This is process-\n// global state but the change is purely permissive (only increases the\n// per-address budget; cannot break anything that worked at 250ms). If the\n// process has already set a higher value, we leave it alone.\n//\n// References:\n// https://nodejs.org/api/net.html#netsetdefaultautoselectfamilyattempttimeoutvalue\n// https://www.rfc-editor.org/rfc/rfc8305\nconst HAPPY_EYEBALLS_MIN_TIMEOUT_MS = 5000;\nlet happyEyeballsTimeoutApplied = false;\nfunction applyHappyEyeballsTimeoutOnce(): void {\n if (happyEyeballsTimeoutApplied) return;\n happyEyeballsTimeoutApplied = true;\n try {\n const current =\n typeof net.getDefaultAutoSelectFamilyAttemptTimeout === \"function\"\n ? net.getDefaultAutoSelectFamilyAttemptTimeout()\n : 0;\n if (current < HAPPY_EYEBALLS_MIN_TIMEOUT_MS) {\n net.setDefaultAutoSelectFamilyAttemptTimeout(\n HAPPY_EYEBALLS_MIN_TIMEOUT_MS\n );\n }\n } catch {\n // Older Node versions (< 20) don't have these APIs. Swallow — the\n // 250ms default they have predates Happy Eyeballs anyway, so they\n // don't suffer this bug.\n }\n}\n\n/**\n * PostgreSQL database adapter for Nextly.\n *\n * @remarks\n * This class extends the base DrizzleAdapter to provide PostgreSQL-specific\n * functionality including:\n *\n * - Connection pooling with pg.Pool\n * - Transaction support with savepoints\n * - PostgreSQL-specific error codes\n * - JSONB and array type support\n * - Full-text search\n * - Automatic retry for serialization failures and deadlocks\n *\n * For most use cases, use the `createPostgresAdapter` factory function\n * instead of instantiating this class directly.\n *\n * @example\n * ```typescript\n * import { PostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = new PostgresAdapter({\n * url: 'postgres://user:pass@localhost:5432/mydb',\n * });\n *\n * await adapter.connect();\n *\n * // Use the adapter\n * const users = await adapter.select('users', {\n * where: { and: [{ column: 'status', op: '=', value: 'active' }] },\n * });\n *\n * await adapter.disconnect();\n * ```\n *\n * @public\n */\nexport class PostgresAdapter extends DrizzleAdapter {\n /**\n * The database dialect - always 'postgresql' for this adapter.\n */\n public readonly dialect = \"postgresql\" as const;\n\n /**\n * Adapter configuration.\n */\n protected readonly config: PostgresAdapterConfig;\n\n /**\n * Connection pool instance.\n */\n private pool: Pool | null = null;\n\n /**\n * Connection state flag.\n */\n private connected = false;\n\n /**\n * Auto-detected provider (Neon, Supabase, or standard).\n * Set during connect() from DATABASE_URL pattern or DB_PROVIDER env var.\n */\n private detectedProvider: PostgresProvider = \"standard\";\n\n /**\n * Provider-specific connection defaults. Applied as fallbacks when\n * user config doesn't specify a value.\n */\n private providerDefaults: ProviderDefaults = getProviderDefaults(\"standard\");\n\n /**\n * Creates a new PostgreSQL adapter instance.\n *\n * @param config - Adapter configuration\n */\n constructor(config: PostgresAdapterConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Establishes a connection to the PostgreSQL database.\n *\n * @remarks\n * This method initializes the connection pool and verifies connectivity\n * by executing a simple query. It is idempotent - calling it multiple\n * times will not create multiple pools.\n *\n * @throws {DatabaseError} If connection fails\n */\n async connect(): Promise<void> {\n // Fix Node 20+ Happy Eyeballs default before constructing the pool —\n // see applyHappyEyeballsTimeoutOnce above.\n applyHappyEyeballsTimeoutOnce();\n\n if (this.connected && this.pool) {\n return;\n }\n\n // Auto-detect provider from URL and apply defaults\n const url = this.config.url || \"\";\n this.detectedProvider = detectPostgresProvider(\n url,\n process.env.DB_PROVIDER\n );\n this.providerDefaults = getProviderDefaults(this.detectedProvider);\n\n // Log detected provider for developer awareness\n if (this.config.logger?.info) {\n const source = process.env.DB_PROVIDER ? \"(explicit)\" : \"(auto-detected)\";\n this.config.logger.info(\n `PostgreSQL provider: ${this.detectedProvider} ${source}`,\n {}\n );\n }\n\n // Node.js network error codes that are safe to retry (transient failures).\n // These cover cloud databases (e.g. Neon) waking from auto-suspend, brief\n // network hiccups, and DNS resolution races during build parallelism.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ]);\n\n // Use provider-specific retry count (Neon needs more for cold starts)\n const maxAttempts = this.providerDefaults.retryAttempts;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const poolConfig = this.buildPoolConfig();\n this.pool = new Pool(poolConfig);\n\n // Handle pool errors (background errors on idle clients)\n this.pool.on(\"error\", (err: Error) => {\n // Log through adapter logger if configured\n if (this.config.logger?.error) {\n this.config.logger.error(err, {\n context: \"pool_error\",\n message: \"Unexpected error on idle client\",\n });\n }\n // Client is automatically removed from pool, no action needed\n });\n\n // Verify connection with smoke test, then check dialect version.\n // Why: F17 hard-fails at connect on unsupported PG versions (<15.0)\n // so users see a clear upgrade pointer instead of cryptic errors\n // mid-apply later. The version query runs inside the existing retry\n // loop's try block, so transient network failures (Neon cold start,\n // EAI_AGAIN) continue to retry; only confirmed version mismatch\n // surfaces as UnsupportedDialectVersionError and exits the loop.\n const client = await this.pool.connect();\n try {\n await client.query(\"SELECT 1\");\n await checkDialectVersion(client, \"postgresql\", {\n // Why: route any future variant warnings through the adapter's\n // logger. PG has no recognized variants today, but this keeps\n // the integration symmetric with MySQL.\n onWarning: msg => this.config.logger?.warn?.(msg),\n });\n this.connected = true;\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection established\", {\n host: this.config.host ?? \"from URL\",\n database: this.config.database ?? \"from URL\",\n });\n }\n\n return; // Success — exit retry loop\n } finally {\n client.release();\n }\n } catch (error) {\n // Clean up the failed pool before deciding whether to retry\n if (this.pool) {\n await this.pool.end().catch(() => {});\n this.pool = null;\n }\n\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxAttempts) {\n // Exponential back-off with jitter: ~1 s, ~2 s, ~3 s, ~4 s\n const waitMs = 1000 * attempt;\n const msg = `PostgreSQL connection attempt ${attempt}/${maxAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`;\n if (this.config.logger?.warn) {\n this.config.logger.warn(msg);\n } else {\n console.warn(`[PostgresAdapter] ${msg}`);\n }\n await delay(waitMs);\n continue;\n }\n\n // Non-retryable error or exhausted retries — surface to caller\n throw this.classifyError(error);\n }\n }\n }\n\n /**\n * Closes the database connection and releases all pool resources.\n *\n * @remarks\n * This method is idempotent - calling it multiple times is safe.\n * It waits for all checked-out clients to be returned before shutting down.\n */\n async disconnect(): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n try {\n await this.pool.end();\n\n if (this.config.logger?.info) {\n this.config.logger.info(\"PostgreSQL connection closed\");\n }\n } finally {\n this.pool = null;\n this.connected = false;\n }\n }\n\n /**\n * Checks if the adapter is currently connected.\n *\n * @returns True if connected and pool is available\n */\n override isConnected(): boolean {\n return this.connected && this.pool !== null;\n }\n\n /**\n * Executes a raw SQL query.\n *\n * @param sql - SQL statement with $1, $2, ... placeholders\n * @param params - Query parameters\n * @returns Array of result rows\n *\n * @throws {DatabaseError} If query execution fails\n */\n async executeQuery<T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> {\n const pool = this.ensurePool();\n const startTime = Date.now();\n\n // Transient network errors that are safe to retry at the query level.\n // These occur when Neon auto-suspends between the pool smoke-test and the\n // actual query, or when multiple build workers compete for cold-start.\n const retryableNodeCodes = new Set([\n \"ETIMEDOUT\",\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n ]);\n const maxQueryAttempts = 3;\n\n for (let attempt = 1; attempt <= maxQueryAttempts; attempt++) {\n try {\n const result = await pool.query(sql, params as unknown[]);\n\n // Log query if logger configured\n if (this.config.logger?.query) {\n const durationMs = Date.now() - startTime;\n this.config.logger.query(sql, params, durationMs);\n }\n\n return result.rows as T[];\n } catch (error) {\n const nodeError = error as { code?: string };\n const isRetryable =\n nodeError.code != null && retryableNodeCodes.has(nodeError.code);\n\n if (isRetryable && attempt < maxQueryAttempts) {\n const waitMs = 500 * attempt;\n console.warn(\n `[PostgresAdapter] Query attempt ${attempt}/${maxQueryAttempts} failed with ${nodeError.code}, retrying in ${waitMs}ms...`\n );\n await delay(waitMs);\n continue;\n }\n\n throw this.classifyError(error, sql);\n }\n }\n\n // Unreachable — loop always returns or throws\n throw this.classifyError(new Error(\"executeQuery: exhausted retries\"));\n }\n\n /**\n * Executes a callback within a database transaction.\n *\n * @remarks\n * PostgreSQL supports full ACID transactions with savepoints.\n * If the callback throws, the transaction is rolled back.\n *\n * Supports automatic retry for serialization failures (40001) and\n * deadlocks (40P01) when `retryCount` is specified in options.\n *\n * @param callback - Function to execute within the transaction\n * @param options - Transaction options (isolation level, timeout, retry)\n * @returns The result of the callback\n *\n * @throws {DatabaseError} If transaction fails after all retries\n */\n async transaction<T>(\n callback: (ctx: TransactionContext) => Promise<T>,\n options?: TransactionOptions\n ): Promise<T> {\n const pool = this.ensurePool();\n const maxAttempts = (options?.retryCount ?? 0) + 1;\n const retryDelayMs = options?.retryDelayMs ?? 100;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const client = await pool.connect();\n const startTime = Date.now();\n\n try {\n // Begin transaction with options\n await this.beginTransaction(client, options);\n\n // Create transaction context\n const ctx = this.createTransactionContext(client);\n\n // Execute callback\n const result = await callback(ctx);\n\n // Commit transaction\n await client.query(\"COMMIT\");\n\n // Log success\n if (this.config.logger?.debug) {\n const durationMs = Date.now() - startTime;\n this.config.logger.debug(\"Transaction committed\", {\n attempt,\n durationMs,\n });\n }\n\n return result;\n } catch (error) {\n // Rollback transaction\n await client.query(\"ROLLBACK\").catch(() => {});\n\n lastError = error;\n\n // Check if error is retryable\n const pgError = error as { code?: string };\n const isRetryable =\n pgError.code === \"40001\" || // serialization_failure\n pgError.code === \"40P01\"; // deadlock\n\n if (isRetryable && attempt < maxAttempts) {\n if (this.config.logger?.warn) {\n this.config.logger.warn(\n `Transaction failed with ${pgError.code}, retrying (${attempt}/${maxAttempts})`,\n { code: pgError.code, attempt }\n );\n }\n await delay(retryDelayMs * attempt); // Exponential backoff\n continue;\n }\n\n throw this.classifyError(error);\n } finally {\n client.release();\n }\n }\n\n // Should not reach here, but handle just in case\n throw this.classifyError(lastError);\n }\n\n /**\n * Returns the database capabilities for PostgreSQL.\n *\n * @remarks\n * PostgreSQL has the most comprehensive feature set of all supported\n * databases, including JSONB, arrays, full-text search, and more.\n */\n getCapabilities(): DatabaseCapabilities {\n return {\n dialect: \"postgresql\",\n supportsJsonb: true,\n supportsJson: true,\n supportsArrays: true,\n supportsGeneratedColumns: true,\n supportsFts: true,\n supportsIlike: true,\n supportsReturning: true,\n supportsSavepoints: true,\n supportsOnConflict: true,\n maxParamsPerQuery: 65535, // PostgreSQL limit\n maxIdentifierLength: 63, // PostgreSQL default\n };\n }\n\n /**\n * Returns connection pool statistics.\n *\n * @returns Pool stats or null if not connected\n */\n override getPoolStats(): PoolStats | null {\n if (!this.pool) {\n return null;\n }\n\n return {\n total: this.pool.totalCount,\n idle: this.pool.idleCount,\n waiting: this.pool.waitingCount,\n active: this.pool.totalCount - this.pool.idleCount,\n };\n }\n\n /**\n * Override insertMany for bulk insert optimization.\n *\n * @remarks\n * Uses a single multi-row INSERT statement for better performance\n * when inserting multiple records.\n */\n override async insertMany<T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n // For single record, use parent implementation\n if (data.length === 1) {\n const result = await this.insert<T>(table, data[0], options);\n return [result];\n }\n\n // Build multi-row INSERT\n const columns = Object.keys(data[0]);\n const params: SqlParam[] = [];\n const valuesClauses: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const record = data[i];\n const placeholders: string[] = [];\n\n for (const col of columns) {\n params.push(record[col] as SqlParam);\n placeholders.push(`$${params.length}`);\n }\n\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n const columnList = columns\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columnList}) VALUES ${valuesClauses.join(\", \")}`;\n\n // Add RETURNING clause\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning.map(col => this.escapeIdentifier(col)).join(\", \");\n sql += ` RETURNING ${returning}`;\n }\n\n try {\n return await this.executeQuery<T>(sql, params);\n } catch (error) {\n throw this.handleQueryError(error, \"insertMany\", table);\n }\n }\n\n // ============================================================\n // Protected Helper Methods\n // ============================================================\n\n /**\n * Ensures pool is connected and returns it.\n *\n * @throws {DatabaseError} If not connected\n */\n private ensurePool(): Pool {\n if (!this.pool) {\n throw createDatabaseError({\n kind: \"connection\",\n message: \"PostgresAdapter is not connected. Call connect() first.\",\n });\n }\n return this.pool;\n }\n\n /**\n * Return the typed Drizzle instance for PostgreSQL.\n * Guarded for server-only usage and requires an active connection.\n *\n * @param schema - Optional schema for relational queries (db.query.*)\n * @returns Drizzle ORM instance wrapping the pg pool connection\n * @throws {Error} If called in browser or not connected\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getDrizzle<T = NodePgDatabase<any>>(schema?: Record<string, unknown>): T {\n if (typeof window !== \"undefined\") {\n throw new Error(\"getDrizzle() is server-only\");\n }\n const pool = this.ensurePool();\n return (schema ? drizzle(pool, { schema }) : drizzle(pool)) as T;\n }\n\n /**\n * Builds pg Pool configuration from adapter config.\n */\n private buildPoolConfig(): PoolConfig {\n const config: PoolConfig = {};\n\n // Connection string or explicit options\n if (this.config.url) {\n config.connectionString = this.config.url;\n } else {\n if (this.config.host) config.host = this.config.host;\n if (this.config.port) config.port = this.config.port;\n if (this.config.database) config.database = this.config.database;\n if (this.config.user) config.user = this.config.user;\n if (this.config.password) config.password = this.config.password;\n }\n\n // Pool settings (user config > provider defaults > hardcoded defaults)\n config.min =\n this.config.pool?.min ??\n this.providerDefaults.poolMin ??\n DEFAULT_POOL_CONFIG.min;\n config.max =\n this.config.pool?.max ??\n this.providerDefaults.poolMax ??\n DEFAULT_POOL_CONFIG.max;\n config.idleTimeoutMillis =\n this.config.pool?.idleTimeoutMs ??\n this.providerDefaults.idleTimeoutMs ??\n DEFAULT_POOL_CONFIG.idleTimeoutMs;\n config.connectionTimeoutMillis =\n this.config.pool?.connectionTimeoutMs ??\n this.providerDefaults.connectionTimeoutMs ??\n DEFAULT_POOL_CONFIG.connectionTimeoutMs;\n\n // TCP keepalive - prevents cloud databases (e.g. Neon) from silently\n // dropping idle connections between the pool smoke-test and the first\n // real query, which manifests as ETIMEDOUT on the query itself.\n config.keepAlive = true;\n config.keepAliveInitialDelayMillis = 10000;\n\n // SSL configuration (user config > provider default)\n if (this.config.ssl) {\n if (typeof this.config.ssl === \"boolean\") {\n config.ssl = this.config.ssl;\n } else {\n if (this.config.ssl.rejectUnauthorized === false) {\n console.warn(\n \"[nextly/adapter-postgres] ssl.rejectUnauthorized is set to false — \" +\n \"TLS certificates will not be validated. This is unsafe on untrusted networks. \" +\n \"Provide a trusted `ca` cert instead, or remove the rejectUnauthorized override.\"\n );\n }\n config.ssl = {\n rejectUnauthorized: this.config.ssl.rejectUnauthorized,\n ca: this.config.ssl.ca,\n cert: this.config.ssl.cert,\n key: this.config.ssl.key,\n };\n }\n } else if (this.providerDefaults.ssl) {\n // Provider requires SSL but user didn't explicitly configure it.\n // Default to validating certs; the user can opt out by setting\n // `ssl: { rejectUnauthorized: false }` explicitly (which logs a warning above).\n config.ssl = { rejectUnauthorized: true };\n }\n\n // PostgreSQL-specific options\n if (this.config.applicationName) {\n config.application_name = this.config.applicationName;\n }\n\n // User config beats provider default; both beat \"unset\".\n // Why: provider.ts:58 declared a Neon statementTimeoutMs default but the\n // adapter previously ignored it, leaving stuck queries to pin pool slots\n // indefinitely. Wire the fallback chain here so the declared defaults\n // actually fire.\n const effectiveStatementTimeout =\n this.config.statementTimeout ?? this.providerDefaults.statementTimeoutMs;\n if (effectiveStatementTimeout !== undefined) {\n config.statement_timeout = effectiveStatementTimeout;\n }\n\n if (this.config.queryTimeout) {\n config.query_timeout = this.config.queryTimeout;\n }\n\n return config;\n }\n\n /**\n * Begins a transaction with the specified options.\n */\n private async beginTransaction(\n client: PoolClient,\n options?: TransactionOptions\n ): Promise<void> {\n let beginSql = \"BEGIN\";\n\n // Add isolation level if specified\n if (options?.isolationLevel) {\n const isolationMap: Record<string, string> = {\n \"read uncommitted\": \"READ UNCOMMITTED\",\n \"read committed\": \"READ COMMITTED\",\n \"repeatable read\": \"REPEATABLE READ\",\n serializable: \"SERIALIZABLE\",\n };\n const level = isolationMap[options.isolationLevel];\n if (level) {\n beginSql += ` ISOLATION LEVEL ${level}`;\n }\n }\n\n // Add read-only mode if specified\n if (options?.readOnly) {\n beginSql += \" READ ONLY\";\n }\n\n await client.query(beginSql);\n\n // Set statement timeout if specified\n if (options?.timeoutMs) {\n await client.query(`SET LOCAL statement_timeout = ${options.timeoutMs}`);\n }\n }\n\n /**\n * Creates a TransactionContext for the given client.\n */\n private createTransactionContext(client: PoolClient): TransactionContext {\n return {\n execute: async <T = unknown>(\n sql: string,\n params: SqlParam[] = []\n ): Promise<T[]> => {\n const result = await client.query(sql, params as unknown[]);\n return result.rows as T[];\n },\n\n insert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options?: InsertOptions\n ): Promise<T> => {\n const columns = Object.keys(data);\n const values = Object.values(data);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES (${placeholders})`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, values);\n return result.rows[0] as T;\n },\n\n insertMany: async <T = unknown>(\n table: string,\n data: Record<string, unknown>[],\n options?: InsertOptions\n ): Promise<T[]> => {\n if (data.length === 0) return [];\n\n const columns = Object.keys(data[0]);\n const params: unknown[] = [];\n const valuesClauses: string[] = [];\n\n for (const record of data) {\n const placeholders: string[] = [];\n for (const col of columns) {\n params.push(record[col]);\n placeholders.push(`$${params.length}`);\n }\n valuesClauses.push(`(${placeholders.join(\", \")})`);\n }\n\n let sql = `INSERT INTO ${this.escapeIdentifier(table)} (${columns.map(c => this.escapeIdentifier(c)).join(\", \")}) VALUES ${valuesClauses.join(\", \")}`;\n\n if (options?.returning) {\n const returning =\n options.returning === \"*\"\n ? \"*\"\n : options.returning\n .map(col => this.escapeIdentifier(col))\n .join(\", \");\n sql += ` RETURNING ${returning}`;\n } else {\n sql += \" RETURNING *\";\n }\n\n const result = await client.query(sql, params);\n return result.rows as T[];\n },\n\n // TransactionContext CRUD methods delegate to the adapter's CRUD\n // which uses Drizzle query API via the TableResolver.\n // The Drizzle transaction is handled at a higher level.\n select: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T[]> => {\n return this.select<T>(table, options);\n },\n\n selectOne: async <T = unknown>(\n table: string,\n options?: SelectOptions\n ): Promise<T | null> => {\n return this.selectOne<T>(table, options);\n },\n\n update: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n where: WhereClause,\n options?: UpdateOptions\n ): Promise<T[]> => {\n return this.update<T>(table, data, where, options);\n },\n\n delete: async (\n table: string,\n where: WhereClause,\n _options?: DeleteOptions\n ): Promise<number> => {\n return this.delete(table, where);\n },\n\n upsert: async <T = unknown>(\n table: string,\n data: Record<string, unknown>,\n options: UpsertOptions\n ): Promise<T> => {\n return this.upsert<T>(table, data, options);\n },\n\n savepoint: async (name: string): Promise<void> => {\n await client.query(`SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n\n rollbackToSavepoint: async (name: string): Promise<void> => {\n await client.query(\n `ROLLBACK TO SAVEPOINT ${this.escapeIdentifier(name)}`\n );\n },\n\n releaseSavepoint: async (name: string): Promise<void> => {\n await client.query(`RELEASE SAVEPOINT ${this.escapeIdentifier(name)}`);\n },\n };\n }\n\n /**\n * Classifies a PostgreSQL error into a DatabaseError.\n *\n * @param error - Original error from pg\n * @param sql - SQL statement that caused the error (optional)\n * @returns DatabaseError with proper classification\n */\n private classifyError(error: unknown, sql?: string): DatabaseError {\n // Why short-circuit on existing DatabaseError: F17's\n // UnsupportedDialectVersionError is already a typed DatabaseError with\n // kind: \"unsupported_version\" plus detectedVersion/requiredVersion\n // fields. Re-wrapping it here would erase those fields and re-tag it\n // as kind: \"unknown\".\n if (isDatabaseError(error)) return error;\n\n const pgError = error as {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n column?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n };\n\n // Determine error kind from PostgreSQL error code\n const kind: DatabaseErrorKind =\n (pgError.code && PG_ERROR_CODES[pgError.code]) || \"unknown\";\n\n // Build error message\n let message = pgError.message ?? String(error);\n if (sql && kind === \"query\") {\n message = `Query failed: ${message}`;\n }\n\n return createDatabaseError({\n kind,\n message,\n code: pgError.code,\n constraint: pgError.constraint,\n table: pgError.table,\n column: pgError.column,\n detail: pgError.detail,\n hint: pgError.hint,\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Override handleQueryError to use PostgreSQL-specific classification.\n */\n protected override handleQueryError(\n error: unknown,\n operation: string,\n table: string\n ): DatabaseError {\n const dbError = this.classifyError(error);\n\n // Add operation context if not already present\n if (!dbError.message.includes(operation)) {\n dbError.message = `${operation} operation failed on table '${table}': ${dbError.message}`;\n }\n\n if (!dbError.table) {\n dbError.table = table;\n }\n\n return dbError;\n }\n}\n\n/**\n * Creates a PostgreSQL database adapter instance.\n *\n * @remarks\n * This is the recommended way to create a PostgreSQL adapter.\n * The adapter is not connected after creation - call `connect()` to\n * establish the database connection.\n *\n * @param config - Adapter configuration\n * @returns A new PostgresAdapter instance\n *\n * @example\n * Simple usage:\n * ```typescript\n * import { createPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * });\n *\n * await adapter.connect();\n * ```\n *\n * @example\n * With full configuration:\n * ```typescript\n * const adapter = createPostgresAdapter({\n * url: process.env.DATABASE_URL!,\n * pool: {\n * min: 5,\n * max: 20,\n * idleTimeoutMs: 30000,\n * connectionTimeoutMs: 10000,\n * },\n * ssl: {\n * rejectUnauthorized: true,\n * ca: process.env.CA_CERT,\n * },\n * applicationName: 'my-app',\n * statementTimeout: 30000,\n * });\n * ```\n *\n * @public\n */\nexport function createPostgresAdapter(\n config: PostgresAdapterConfig\n): PostgresAdapter {\n return new PostgresAdapter(config);\n}\n\n/**\n * Type guard to check if a value is a PostgresAdapter instance.\n *\n * @param value - Value to check\n * @returns True if value is a PostgresAdapter\n *\n * @example\n * ```typescript\n * import { isPostgresAdapter } from '@nextlyhq/adapter-postgres';\n *\n * if (isPostgresAdapter(adapter)) {\n * // TypeScript knows adapter is PostgresAdapter\n * console.log(adapter.dialect); // 'postgresql'\n * }\n * ```\n *\n * @public\n */\nexport function isPostgresAdapter(value: unknown): value is PostgresAdapter {\n return value instanceof PostgresAdapter;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextlyhq/adapter-postgres",
|
|
3
|
-
"version": "0.0.2-alpha.
|
|
3
|
+
"version": "0.0.2-alpha.8",
|
|
4
4
|
"description": "PostgreSQL database adapter for Nextly - extends @nextlyhq/adapter-drizzle",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"drizzle-orm": "^0.45.2",
|
|
25
25
|
"pg": "^8.16.3",
|
|
26
|
-
"@nextlyhq/adapter-drizzle": "0.0.2-alpha.
|
|
26
|
+
"@nextlyhq/adapter-drizzle": "0.0.2-alpha.8"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/pg": "^8.11.0",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"typescript": "^5.9.3",
|
|
36
36
|
"vite-tsconfig-paths": "^5.1.4",
|
|
37
37
|
"vitest": "^4.0.8",
|
|
38
|
-
"@nextlyhq/eslint-config": "0.0.2-alpha.
|
|
39
|
-
"@nextlyhq/tsconfig": "0.0.2-alpha.
|
|
38
|
+
"@nextlyhq/eslint-config": "0.0.2-alpha.7",
|
|
39
|
+
"@nextlyhq/tsconfig": "0.0.2-alpha.7"
|
|
40
40
|
},
|
|
41
41
|
"keywords": [
|
|
42
42
|
"nextly",
|