Skip to content

Commit 41167bf

Browse files
r1tsuuDanRibbens
andauthored
feat(db-vercel-postgres): allow to use a local database using pg instead of @vercel/postgres (#9771)
### What? This PR allows you to use a local database when using `vercelPostgresAdapter`. This adapter doesn't work with them because it requires an SSL connection and Neon's WS proxy. Instead we fallback to using pool from `pg` if `hostname` is either `127.0.0.1` or `localhost`. If you still want to use `@vercel/postgres` even locally you can pass `disableUsePgForLocalDatabase: true` here and you'd have to spin up the DB with a special Neon's Docker Compose setup - https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker ### Why? Forcing people to use a cloud database locally isn't great. Not only they are slow but also paid. --------- Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
1 parent ed44ec0 commit 41167bf

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

docs/database/postgres.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ export default buildConfig({
5050
})
5151
```
5252

53+
<Banner type="info">
54+
<strong>Note:</strong>
55+
If when using `vercelPostgresAdapter` your `process.env.POSTGRES_URL` or `pool.connectionString` points to a local database (e.g hostname has `localhost` or `127.0.0.1`) we use the `pg` module for pooling instead of `@vercel/postgres`. This is because `@vercel/postgres` doesn't work with local databases, if you want to disable that behavior, you can pass `forceUseVercelPostgres: true` to adapter's 'args and follow [Vercel guide](https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker) for a Docker Neon DB setup.
56+
</Banner>
57+
5358
## Options
5459

5560
| Option | Description |
@@ -178,7 +183,7 @@ postgresAdapter({
178183
})
179184
```
180185

181-
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
186+
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
182187

183188

184189
### afterSchemaInit

packages/db-vercel-postgres/src/connect.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Connect } from 'payload'
44
import { pushDevSchema } from '@payloadcms/drizzle'
55
import { sql, VercelPool } from '@vercel/postgres'
66
import { drizzle } from 'drizzle-orm/node-postgres'
7+
import pg from 'pg'
78

89
import type { VercelPostgresAdapter } from './types.js'
910

@@ -24,10 +25,30 @@ export const connect: Connect = async function connect(
2425

2526
try {
2627
const logger = this.logger || false
28+
29+
let client: pg.Pool | VercelPool
30+
31+
const connectionString = this.poolOptions?.connectionString ?? process.env.POSTGRES_URL
32+
33+
// Use non-vercel postgres for local database
34+
if (
35+
!this.forceUseVercelPostgres &&
36+
connectionString &&
37+
['127.0.0.1', 'localhost'].includes(new URL(connectionString).hostname)
38+
) {
39+
client = new pg.Pool(
40+
this.poolOptions ?? {
41+
connectionString,
42+
},
43+
)
44+
} else {
45+
client = this.poolOptions ? new VercelPool(this.poolOptions) : sql
46+
}
47+
2748
// Passed the poolOptions if provided,
2849
// else have vercel/postgres detect the connection string from the environment
2950
this.drizzle = drizzle({
30-
client: this.poolOptions ? new VercelPool(this.poolOptions) : sql,
51+
client,
3152
logger,
3253
schema: this.schema,
3354
})

packages/db-vercel-postgres/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj<Verce
9999
json: true,
100100
},
101101
fieldConstraints: {},
102+
forceUseVercelPostgres: args.forceUseVercelPostgres ?? false,
102103
idType: postgresIDType,
103104
indexes: new Set<string>(),
104105
initializing,

packages/db-vercel-postgres/src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ export type Args = {
3131
*/
3232
disableCreateDatabase?: boolean
3333
extensions?: string[]
34+
/**
35+
* By default, we connect to a local database using the `pg` module instead of `@vercel/postgres`.
36+
* This is because `@vercel/postgres` doesn't work with local databases.
37+
* If you still want to use `@vercel/postgres` even locally you can pass `true` here
38+
* and you'd to spin up the database with a special Neon's Docker Compose setup - https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker
39+
*/
40+
forceUseVercelPostgres?: boolean
3441
idType?: 'serial' | 'uuid'
3542
localesSuffix?: string
3643
logger?: DrizzleConfig['logger']
@@ -58,6 +65,7 @@ export type Args = {
5865
}
5966

6067
export type VercelPostgresAdapter = {
68+
forceUseVercelPostgres?: boolean
6169
pool?: VercelPool
6270
poolOptions?: Args['pool']
6371
} & BasePostgresAdapter

0 commit comments

Comments
 (0)