Skip to content

Commit 4172cbc

Browse files
committed
initial commit
0 parents  commit 4172cbc

36 files changed

+8162
-0
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ADMIN_PASSWORD=
2+
DATABASE_URL="postgresql://codersteps:@localhost:5432/fullstack_app?schema=public"

.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}

.gitignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
.pnpm-debug.log*
27+
28+
# local env files
29+
.env
30+
.env*.local
31+
32+
# vercel
33+
.vercel
34+
35+
# typescript
36+
*.tsbuildinfo

.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"tabWidth": 2,
3+
"singleQuote": true,
4+
"trailingComma": "all",
5+
"semi": false
6+
}

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## About
2+
3+
A Next.js full-stack boilerplate with TypeScript, Tailwind CSS, and Prisma.js for your future full-stack apps.
4+
5+
## Tasks
6+
7+
- [x] Create a new Next.js app
8+
- [x] Install and configure Tailwind CSS
9+
- [x] Set up Typesafe environment variables
10+
- [x] Set up Prisma.js
11+
- [x] Automatize Next.js api handlers and Structure next.js api handlers
12+
- [x] Setup Next.js api hello world middleware
13+
- [x] Set up hello world MOBX store (under review)
14+
15+
## Notes
16+
17+
Don't forget to run: `cp .env.example .env`
18+
19+
Soon the related article will be published at codersteps.com

app/users/create.handler.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { NextApiHandler } from 'next'
2+
import bcrypt from 'bcrypt'
3+
import { Prisma, User } from '@prisma/client'
4+
import { ReasonPhrases, StatusCodes } from 'http-status-codes'
5+
import db from '@/lib/database'
6+
7+
interface Data {
8+
error: string | null
9+
data: User | null
10+
}
11+
12+
const createHandler: NextApiHandler<Data> = async (req, res) => {
13+
const { firstName, lastName, bio, username, password } =
14+
req.body as Prisma.UserUncheckedCreateInput
15+
16+
if (
17+
typeof username !== 'string' ||
18+
typeof password !== 'string' ||
19+
password.length < 6
20+
) {
21+
res
22+
.status(StatusCodes.BAD_REQUEST)
23+
.json({ data: null, error: ReasonPhrases.BAD_REQUEST })
24+
return
25+
}
26+
27+
const hashedPassword = bcrypt.hashSync(password, 10)
28+
const data: Prisma.UserUncheckedCreateInput = {
29+
username,
30+
password: hashedPassword,
31+
}
32+
33+
if (typeof firstName === 'string') {
34+
data.firstName = firstName
35+
}
36+
if (typeof lastName === 'string') {
37+
data.lastName = lastName
38+
}
39+
if (typeof bio === 'string') {
40+
data.bio = bio
41+
}
42+
43+
const createdUser = await db.user.create({ data })
44+
res.status(StatusCodes.OK).json({ data: createdUser, error: null })
45+
}
46+
47+
export default createHandler

app/users/delete.handler.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { NextApiHandler } from 'next'
2+
import { User } from '@prisma/client'
3+
import { StatusCodes } from 'http-status-codes'
4+
import db from '@/lib/database'
5+
6+
interface Data {
7+
data: User | null
8+
error: string | null
9+
}
10+
11+
const deleteHandler: NextApiHandler<Data> = async (req, res) => {
12+
const id = typeof req.query.id === 'string' ? parseInt(req.query.id, 10) : 0
13+
14+
const user = await db.user.delete({ where: { id } })
15+
res.status(StatusCodes.OK).json({ data: user, error: null })
16+
}
17+
18+
export default deleteHandler

app/users/index.handler.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { NextApiHandler } from 'next'
2+
import { User } from '@prisma/client'
3+
import { StatusCodes } from 'http-status-codes'
4+
import db from '@/lib/database'
5+
6+
interface Data {
7+
data: User[]
8+
}
9+
10+
const indexHandler: NextApiHandler<Data> = async (req, res) => {
11+
const users = await db.user.findMany()
12+
res.status(StatusCodes.OK).json({ data: users })
13+
}
14+
15+
export default indexHandler

app/users/show.handler.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { NextApiHandler } from 'next'
2+
import { User } from '@prisma/client'
3+
import { ReasonPhrases, StatusCodes } from 'http-status-codes'
4+
import db from '@/lib/database'
5+
6+
interface Data {
7+
data: User | null
8+
error: string | null
9+
}
10+
11+
const showHandler: NextApiHandler<Data> = async (req, res) => {
12+
const id = typeof req.query.id === 'string' ? parseInt(req.query.id, 10) : 0
13+
14+
const user = await db.user.findFirst({ where: { id } })
15+
16+
if (!user) {
17+
res
18+
.status(StatusCodes.NOT_FOUND)
19+
.json({ data: null, error: ReasonPhrases.NOT_FOUND })
20+
}
21+
22+
res.status(StatusCodes.OK).json({ data: user, error: null })
23+
}
24+
25+
export default showHandler

app/users/update.handler.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { NextApiHandler } from 'next'
2+
import { Prisma, User } from '@prisma/client'
3+
import { ReasonPhrases, StatusCodes } from 'http-status-codes'
4+
import db from '@/lib/database'
5+
6+
interface Data {
7+
data: User | null
8+
error: string | null
9+
}
10+
11+
const updateHandler: NextApiHandler<Data> = async (req, res) => {
12+
const id = typeof req.query.id === 'string' ? parseInt(req.query.id, 10) : 0
13+
14+
const { firstName, lastName, bio } =
15+
req.body as Prisma.UserUncheckedUpdateInput
16+
17+
const data: Prisma.UserUncheckedUpdateInput = {}
18+
19+
if (typeof firstName === 'string') {
20+
data.firstName = firstName
21+
}
22+
if (typeof lastName === 'string') {
23+
data.lastName = lastName
24+
}
25+
if (typeof bio === 'string') {
26+
data.bio = bio
27+
}
28+
29+
const user = await db.user.update({ data, where: { id } })
30+
res.status(StatusCodes.OK).json({ data: user, error: null })
31+
}
32+
33+
export default updateHandler

0 commit comments

Comments
 (0)