Skip to content

Commit

Permalink
docs(examples): add postgres.js example (#42962)
Browse files Browse the repository at this point in the history
  • Loading branch information
silvioprog committed Nov 16, 2022
1 parent 5e11f52 commit 10b635e
Show file tree
Hide file tree
Showing 17 changed files with 719 additions and 0 deletions.
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')
}
}

0 comments on commit 10b635e

Please sign in to comment.