Skip to content
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

docs(examples): add postgres.js example #42962

Merged
merged 3 commits into from Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/with-postgres/.env.local.example
@@ -0,0 +1 @@
DATABASE_URL=postgresql://user:pass@host/user/database?ssl=false
36 changes: 36 additions & 0 deletions examples/with-postgres/.gitignore
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
65 changes: 65 additions & 0 deletions examples/with-postgres/README.md
@@ -0,0 +1,65 @@
# Postgres.js Example

An example using [Postgres.js](https://github.com/porsager/postgres) in a Next.js project.

## Deploy your own

Once you have access to [the environment variables you'll need](#configure-environment-variables), deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-postgres&project-name=with-postgres&repository-name=with-postgres&env=DATABASE_URL&envDescription=Required%20to%20connect%20the%20app%20with%20Postgres)

## How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:

```bash
npx create-next-app --example with-postgres with-postgres-app
```

```bash
yarn create next-app --example with-postgres with-postgres-app
```

```bash
pnpm create next-app --example with-postgres with-postgres-app
```

## Configuration

### Set up a Postgres database

Set up a Postgres database locally or use your favorite provider.

### Configure environment variables

Copy the `.env.local.example` file in this directory to `.env.local` (this will be ignored by Git):

```bash
cp .env.local.example .env.local
```

Set the `DATABASE_URL` variable in `.env.local` to the connection uri of your postgres database.

### Apply migrations

To setup up the migrations, use:

```bash
npm run migrate:up
# or
yarn migrate:up
```

### Start Next.js in development mode

```bash
npm run dev
# or
yarn dev
```

Your app should now be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions).

## Deploy on Vercel

Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
8 changes: 8 additions & 0 deletions examples/with-postgres/ley.config.js
@@ -0,0 +1,8 @@
const dotenv = require('dotenv')
const { parse } = require('pg-connection-string')

dotenv.config({ path: '.env.local' })

const options = parse(process.env.DATABASE_URL || '')

module.exports = options
5 changes: 5 additions & 0 deletions examples/with-postgres/lib/db.ts
@@ -0,0 +1,5 @@
import postgres from 'postgres'

const sql = postgres(process.env.DATABASE_URL as string)

export default sql
35 changes: 35 additions & 0 deletions examples/with-postgres/lib/todos.ts
@@ -0,0 +1,35 @@
import sql from './db'

export interface ToDo {
id: number
text: string
done: boolean
}

export async function list() {
return await sql<ToDo[]>`
SELECT id, text, done FROM todos
ORDER BY id
`
}

export async function create(todo: ToDo) {
return await sql<ToDo[]>`
INSERT INTO todos (text, done) VALUES (${todo.text}, false)
RETURNING id, text, done
`
}

export async function update(todo: ToDo) {
return await sql<ToDo[]>`
UPDATE todos SET done=${todo.done} WHERE id=${todo.id}
RETURNING id, text, done
`
}

export async function remove(todo: ToDo) {
return await sql<ToDo[]>`
DELETE FROM todos WHERE id=${todo.id}
RETURNING id, text, done
`
}
15 changes: 15 additions & 0 deletions examples/with-postgres/migrations/000-todos.js
@@ -0,0 +1,15 @@
exports.up = async function (sql) {
await sql`
CREATE TABLE IF NOT EXISTS todos (
id SERIAL PRIMARY KEY NOT NULL,
text CHARACTER VARYING(255) NOT NULL,
done BOOLEAN NOT NULL DEFAULT FALSE
)
`
}

exports.down = async function (sql) {
await sql`
DROP TABLE IF EXISTS todos
`
}
7 changes: 7 additions & 0 deletions examples/with-postgres/next.config.js
@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}

module.exports = nextConfig
25 changes: 25 additions & 0 deletions examples/with-postgres/package.json
@@ -0,0 +1,25 @@
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"migrate:up": "ley up",
"migrate:down": "ley down"
},
"dependencies": {
"@types/node": "^18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"next": "latest",
"postgres": "^3.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^4.8.4"
},
"devDependencies": {
"dotenv": "^16.0.3",
"ley": "^0.8.1",
"pg-connection-string": "^2.5.0"
}
}
7 changes: 7 additions & 0 deletions examples/with-postgres/pages/_app.tsx
@@ -0,0 +1,7 @@
import type { AppProps } from 'next/app'

import '../styles/globals.css'

export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
23 changes: 23 additions & 0 deletions examples/with-postgres/pages/api/todos.ts
@@ -0,0 +1,23 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import { type ToDo } from '../../lib/todos'
import * as todos from '../../lib/todos'

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<ToDo[] | string>
) {
switch (req.method) {
case 'GET':
return res.status(200).json(await todos.list())
case 'POST':
return res.status(201).json(await todos.create(req.body))
case 'PUT':
const updated = await todos.update(req.body)
return res.status(updated.length > 0 ? 200 : 404).json(updated)
case 'DELETE':
const removed = await todos.remove(req.body)
return res.status(removed.length > 0 ? 204 : 404).end()
default:
return res.status(405).send('Method Not Allowed')
}
}