-
Notifications
You must be signed in to change notification settings - Fork 48
feat: add neon for serverless postgres
#191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3e4ec15
8cc74c5
b61438f
a8ee790
59bf1bc
0efbc9e
1e7358d
0faac68
9747619
f79fcda
b110f35
222cfd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| icon: cbi:neon | ||
| --- | ||
|
|
||
| # NEON INSTANT | ||
|
|
||
| > The [Neon connector](/connectors/neon), plus a database provisioned for you when you don't have one yet. | ||
|
|
||
| :read-more{to="https://neon.com/docs/reference/neon-new"} | ||
|
|
||
| ## Instant Postgres Provisioning | ||
|
|
||
| This connector behaves exactly like the [Neon connector](/connectors/neon), except that it does not require a connection string. On first use, it resolves one in this order: | ||
|
|
||
| 1. The `url` / `connectionString` option, if given. | ||
| 2. The `DATABASE_URL` environment variable (see [`dotEnvKey`](#dotenvfile-dotenvkey)), if set. | ||
| 3. Otherwise, it provisions a claimable Postgres database via [`neon-new`](https://www.npmjs.com/package/neon-new), optionally seeding it from a `.sql` file. | ||
|
|
||
| This is intended as a development-time affordance. When `NODE_ENV` is `production`, nothing is provisioned and a missing connection string throws — use the [Neon connector](/connectors/neon) there. | ||
|
|
||
| `neon-new` is imported lazily, only when a database actually has to be provisioned, so it stays out of your production bundle. | ||
|
|
||
| ## Usage | ||
|
|
||
| Install the Neon Serverless Driver for the postgres connection, and `neon-new` to provision the database. | ||
|
|
||
| :pm-install{name="@neondatabase/serverless neon-new"} | ||
|
|
||
| With those dependencies installed, you can immediately start building: | ||
|
|
||
| ```ts | ||
| import { createDatabase } from "db0"; | ||
| import neonInstant from "db0/connectors/neon-instant"; | ||
|
|
||
| const db = createDatabase( | ||
| neonInstant({ | ||
| seed: { type: "sql-script", path: "init.sql" }, | ||
| }), | ||
| ); | ||
| ``` | ||
|
|
||
| ```sql [init.sql] | ||
| CREATE TABLE IF NOT EXISTS xmen ( | ||
| id SERIAL PRIMARY KEY, | ||
| name TEXT NOT NULL | ||
| ); | ||
|
|
||
| INSERT INTO xmen (name) VALUES | ||
| ('Wolverine'), | ||
| ('Cyclops'), | ||
| ('Storm'), | ||
| ('Jean Grey'), | ||
| ('Beast'), | ||
| ('Professor X'), | ||
| ('Gambit'), | ||
| ('Rogue'), | ||
| ('Nightcrawler') | ||
| ON CONFLICT DO NOTHING; | ||
| ``` | ||
|
|
||
| The generated connection string is appended to your `.env` file. As long as that file is loaded into `process.env` (with `dotenv`, or natively via `node --env-file`), later runs pick it up and reuse the same database instead of provisioning a new one. | ||
|
|
||
| ## Options | ||
|
|
||
| Accepts every [Neon connector option](/connectors/neon#options), plus the [`neon-new` parameters](https://www.npmjs.com/package/neon-new) below. | ||
|
|
||
| ### `url` or `connectionString` | ||
|
|
||
| - **Type:** `string` _(optional)_ | ||
| - Connection string to an existing Neon database. | ||
| - If provided, no database is provisioned. | ||
|
|
||
| ### `seed` | ||
|
|
||
| - **Type:** `{ type: "sql-script", path: string }` _(optional)_ | ||
| - **Default:** `undefined` | ||
| - Path to a `.sql` file for seeding the database schema and initial data. | ||
|
|
||
| ### `dotEnvFile` / `dotEnvKey` | ||
|
|
||
| - **Type:** `string` _(optional)_ | ||
| - **Default:** `".env"` and `"DATABASE_URL"` | ||
| - File the generated connection string is written to, and the variable name it is written under. `dotEnvKey` is also the environment variable read to reuse an existing database. | ||
|
|
||
| ### `envPrefix` | ||
|
|
||
| - **Type:** `string` _(optional)_ | ||
| - **Default:** `"PUBLIC_"` | ||
| - Prefix used for the public environment variables written alongside the connection string. | ||
|
|
||
| ### `settings` | ||
|
|
||
| - **Type:** `{ logicalReplication?: boolean }` _(optional)_ | ||
| - Extra settings for the provisioned database. | ||
|
|
||
| ### `referrer` | ||
|
|
||
| - **Type:** `string` _(optional)_ | ||
| - **Default:** `"db0/neon-connector"` | ||
| - Referrer name Neon uses for tracking. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,45 @@ icon: cbi:neon | |
|
|
||
| # NEON | ||
|
|
||
| > Connect DB0 to Neon Serverless Postgres. | ||
| > Very similar to [Postgres connector](/connectors/postgresql), but optimized for serverless environments. | ||
|
|
||
| :read-more{to="https://neon.tech/"} | ||
| :read-more{to="https://neon.com"} | ||
|
|
||
| ::read-more{to="https://github.com/unjs/db0/issues/32"} | ||
| This connector is planned to be supported. Follow up via [unjs/db0#32](https://github.com/unjs/db0/issues/32). | ||
| ## Why Neon Connector? | ||
|
|
||
| The fundamental difference is that Postgres Connector uses the [node-postgres](https://node-postgres.com/) driver, which needs a raw TCP connection, while Neon uses [neondatabase/serverless](https://neon.com/docs/serverless/serverless-driver), whose `Client` speaks postgres over WebSockets. The drivers have feature parity, but the connection type creates some runtime differences. | ||
|
|
||
| A WebSocket connection is usually preferred over TCP for serverless environments because many of those runtimes cannot open raw TCP sockets at all. | ||
|
|
||
| ## Usage | ||
|
|
||
| Install the Neon Serverless Driver for the postgres connection. | ||
|
|
||
| :pm-install{name="@neondatabase/serverless"} | ||
|
|
||
| This connector always connects to an existing database, so a connection string is required. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Describe the required database identifier, not a required connection string. Line 23 contradicts the documented and tested support for host-based Proposed fix-This connector always connects to an existing database, so a connection string is required.
+This connector always connects to an existing database, so it requires either a connection string or another identifying `ClientConfig` field such as `host`.Also applies to: 44-48 🤖 Prompt for AI Agents |
||
|
|
||
| ```ts | ||
| import { createDatabase } from "db0"; | ||
| import neon from "db0/connectors/neon"; | ||
|
|
||
| const db = createDatabase( | ||
| neon({ | ||
| url: process.env.DATABASE_URL, | ||
| }), | ||
| ); | ||
| ``` | ||
|
|
||
| ::tip | ||
| Want a database provisioned for you in development, without bringing your own connection string? Use the [Neon Instant connector](/connectors/neon-instant). | ||
| :: | ||
|
|
||
| ## Options | ||
|
|
||
| Options are passed through to the underlying [`Client`](https://neon.com/docs/serverless/serverless-driver), so any `ClientConfig` field is accepted in addition to the following. | ||
|
|
||
| ### `url` or `connectionString` | ||
|
|
||
| - **Type:** `string` | ||
| - Connection string to your Neon database. | ||
| - Optional if the database is identified another way, such as a `host` in the `ClientConfig`. If neither is present, the first query throws (the client connects lazily). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,7 @@ | |
| "@cloudflare/workers-types": "^5", | ||
| "@electric-sql/pglite": "^0.5.4", | ||
| "@libsql/client": "^0.17.4", | ||
| "@neondatabase/serverless": "^1.1.0", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n## package.json relevant lines\n'
nl -ba package.json | sed -n '1,220p'
printf '\n## neon connector\n'
if [ -f src/connectors/neon.ts ]; then
nl -ba src/connectors/neon.ts | sed -n '1,220p'
fi
printf '\n## publish/bundle/search\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'(files"|publishConfig|bundl|tsup|rollup|esbuild|webpack|vite|pkg\.exports|exports|main"|module"|type"|prepare|prepack|prepublishOnly|devDependencies|dependencies)' \
package.json . 2>/dev/null | sed -n '1,220p'Repository: unjs/db0 Length of output: 218 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n## package.json\n'
sed -n '1,220p' package.json | cat -n
printf '\n## src/connectors/neon.ts\n'
if [ -f src/connectors/neon.ts ]; then
sed -n '1,220p' src/connectors/neon.ts | cat -n
fi
printf '\n## publish/bundle config search\n'
if command -v rg >/dev/null 2>&1; then
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'(files|publishConfig|bundle|bundl|tsup|rollup|esbuild|webpack|vite|prepack|prepublishOnly|prepare|exports|main|module|type)' \
package.json . 2>/dev/null | sed -n '1,260p'
else
grep -RInE --exclude-dir=.git --exclude-dir=node_modules \
'(files|publishConfig|bundle|bundl|tsup|rollup|esbuild|webpack|vite|prepack|prepublishOnly|prepare|exports|main|module|type)' \
package.json . | sed -n '1,260p'
fiRepository: unjs/db0 Length of output: 23958 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n## obuild-related files\n'
find . -maxdepth 2 \( -name '*obuild*' -o -name '.obuild*' -o -name 'build.*' -o -name 'tsup.*' -o -name 'rollup.*' -o -name 'vite.*' -o -name 'unbuild.*' \) | sed 's#^\./##' | sort
printf '\n## search for bundling/externalization hints\n'
if command -v rg >/dev/null 2>&1; then
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'(external|bundle|bundled|noExternal|inlineDependencies|inlineDeps|emit.*d\.ts|preserveModules|metafile|rollupOptions|esbuildOptions|externals?)' \
. 2>/dev/null | sed -n '1,260p'
else
grep -RInE --exclude-dir=.git --exclude-dir=node_modules \
'(external|bundle|bundled|noExternal|inlineDependencies|inlineDeps|emit.*d\.ts|preserveModules|metafile|rollupOptions|esbuildOptions|externals?)' \
. | sed -n '1,260p'
fi
printf '\n## all package.json entries for scripts/build tooling\n'
sed -n '1,140p' package.json | cat -nRepository: unjs/db0 Length of output: 4795 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n## build.config.ts\n'
sed -n '1,200p' build.config.ts | cat -n
printf '\n## connector build outputs/search\n'
if command -v rg >/dev/null 2>&1; then
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'(src/connectors|connectors/\*|type: "bundle"|type: "copy"|type: "transpile"|type: "unbundle"|obuild)' \
build.config.ts scripts src .github AGENTS.md 2>/dev/null | sed -n '1,240p'
fiRepository: unjs/db0 Length of output: 1255 Move Neon runtime packages out of
🤖 Prompt for AI Agents |
||
| "@planetscale/database": "^1.20.1", | ||
| "@types/better-sqlite3": "^7.6.13", | ||
| "@types/bun": "^1.3.14", | ||
|
|
@@ -62,6 +63,7 @@ | |
| "kysely": "^0.29.3", | ||
| "mlly": "^1.8.2", | ||
| "mysql2": "^3.22.6", | ||
| "neon-new": "^0.15.0", | ||
| "obuild": "^0.4.38", | ||
| "pathe": "^2.0.3", | ||
| "pg": "^8.22.0", | ||
|
|
@@ -74,16 +76,24 @@ | |
| "peerDependencies": { | ||
| "@electric-sql/pglite": "*", | ||
| "@libsql/client": "*", | ||
| "@neondatabase/serverless": "*", | ||
| "better-sqlite3": "*", | ||
| "drizzle-orm": "*", | ||
| "kysely": "*", | ||
| "mysql2": "*", | ||
| "neon-new": "*", | ||
| "sqlite3": "*" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@libsql/client": { | ||
| "optional": true | ||
| }, | ||
| "@neondatabase/serverless": { | ||
| "optional": true | ||
| }, | ||
| "neon-new": { | ||
| "optional": true | ||
| }, | ||
| "better-sqlite3": { | ||
| "optional": true | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the
dotEnvKeysection fragment.The generated anchor for
### dotEnvFile / dotEnvKeycontains two separators.Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 16-16: Link fragments should be valid
(MD051, link-fragments)
🤖 Prompt for AI Agents
Source: Linters/SAST tools