(databaseUrl = process.env.DATABASE_URL)
| 85 | }; |
| 86 | |
| 87 | export const createPrismaPgAdapter = (databaseUrl = process.env.DATABASE_URL): TParsedPrismaPgConfig => { |
| 88 | if (!databaseUrl) { |
| 89 | throw new Error("DATABASE_URL is required to create a Prisma PostgreSQL adapter."); |
| 90 | } |
| 91 | |
| 92 | if (databaseUrl.startsWith("prisma://") || databaseUrl.startsWith("prisma+postgres://")) { |
| 93 | throw new Error( |
| 94 | "Prisma Accelerate URLs are not supported by Formbricks' PostgreSQL adapter. Use a direct PostgreSQL DATABASE_URL." |
| 95 | ); |
| 96 | } |
| 97 | |
| 98 | const parsedUrl = new URL(databaseUrl); |
| 99 | const schema = parsedUrl.searchParams.get("schema") ?? undefined; |
| 100 | // connection_limit must be strictly positive; max:0 in pg disables the pool. |
| 101 | // Fall back to Prisma 6's formula so multi-core hosts keep their previous |
| 102 | // capacity instead of silently dropping to pg's default of 10. |
| 103 | const connectionLimit = |
| 104 | toPositiveInt(parsedUrl.searchParams.get("connection_limit")) ?? DEFAULT_CONNECTION_LIMIT; |
| 105 | // connect_timeout → pg's TCP-connect timeout. 0 means "wait indefinitely" |
| 106 | // (Prisma 6 semantics; pg also honors this). pool_timeout (Prisma's |
| 107 | // "max wait for a pooled connection") has no pg equivalent — warn instead |
| 108 | // of silently misapplying it to a different knob. |
| 109 | const connectTimeoutSeconds = toNonNegativeInt(parsedUrl.searchParams.get("connect_timeout")); |
| 110 | const connectionTimeoutMillis = toMillis(connectTimeoutSeconds) ?? 5_000; |
| 111 | const poolTimeoutRaw = parsedUrl.searchParams.get("pool_timeout"); |
| 112 | if (poolTimeoutRaw !== null && poolTimeoutRaw.trim() !== "") { |
| 113 | logger.warn( |
| 114 | { pool_timeout: poolTimeoutRaw }, |
| 115 | "pool_timeout in DATABASE_URL is a Prisma-only param with no pg equivalent; ignoring." |
| 116 | ); |
| 117 | } |
| 118 | // 0 = "never expire idle connections" (Prisma 6 semantics). |
| 119 | const maxIdleConnectionLifetime = toMillis( |
| 120 | toNonNegativeInt(parsedUrl.searchParams.get("max_idle_connection_lifetime")) |
| 121 | ); |
| 122 | // 0 = "no max lifetime" (Prisma 6 semantics). |
| 123 | const maxConnectionLifetime = toNonNegativeInt(parsedUrl.searchParams.get("max_connection_lifetime")); |
| 124 | const ssl = sslConfigFromSslAccept(parsedUrl.searchParams.get("sslaccept")); |
| 125 | const connectionString = getConnectionString(parsedUrl); |
| 126 | |
| 127 | const poolConfig: PoolConfig = { |
| 128 | connectionString, |
| 129 | connectionTimeoutMillis, |
| 130 | idleTimeoutMillis: maxIdleConnectionLifetime ?? 300_000, |
| 131 | max: connectionLimit, |
| 132 | ...(maxConnectionLifetime !== undefined && { maxLifetimeSeconds: maxConnectionLifetime }), |
| 133 | ...(ssl !== undefined && { ssl }), |
| 134 | }; |
| 135 | |
| 136 | return { |
| 137 | adapter: new PrismaPg(poolConfig, schema ? { schema } : undefined), |
| 138 | connectionString, |
| 139 | }; |
| 140 | }; |
no test coverage detected