> For the complete documentation index, see [llms.txt](https://asamarsal.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://asamarsal.gitbook.io/notes/personal-documentation/express-js-+-prisma-+-typescript.md).

# Express Js + Prisma + Typescript

<pre><code>npm init -y

npm install express
<strong>npm install -D typescript ts-node-dev @types/node @types/express
</strong>
npx tsc --init

npm install -D prisma
npx prisma init
npm install @prisma/client

npx prisma generate
npx prisma migrate dev --name init

npx prisma studio

npm install bcrypt
npm install -D @types/bcrypt

npm install jsonwebtoken
npm install -D @types/jsonwebtoken

npm install joi
npm install -D @types/joi
</code></pre>

Masukkan di package.json

```mtrace
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "ts-node-dev --respawn src/app.ts"
  },
```

Masukkan di .env

```properties
DATABASE_URL="postgresql://postgres:uuaauaua123@localhost:5432/dblivecode?schema=public"
```

App.ts

```
import express from "express";
import { router as authRoutes } from "./routes/auth";

const app = express();
app.use(express.json());

app.use(authRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

Controller

```
import { Request, Response } from "express";

const testing = async (req: Request, res: Response) => {
    try {
      res.status(200).json({ 
        message: "Server berhasil connect" 
      });
    } catch (error) {
      console.error(error);
      res.status(500).json({ 
        error, 
        message: "Server tidak terhubung" 
      });
    }
  };

export {
    testing,
};
```

Routes

```
import { Router } from "express";
import {
    testing,
} from "../controllers/auth";

const router = Router();

router.get("/test", testing);

export { router };
```

Schema.prisma

```
model Product {
  id        Int       @id @default(autoincrement())
  name      String
  price     Float
  stock     Int       @default(0)
  createdAt DateTime  @default(now())
}

model User {
  id        Int       @id @default(autoincrement())
  name      String
  email     String    @unique
  createdAt DateTime  @default(now())
}
```

\====================================================

Tambahkan konfigurasi seeder di package.json

```
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "ts-node-dev --respawn src/app.ts",
    "seed": "ts-node prisma/seed.ts"
  },
```

Setelah membuat seed.ts, jalankan

```
npm run seed
```

Tambahkan di controllers

```
import { PrismaClient } from "../generated/prisma";

const prisma = new PrismaClient();
```

Tambahkan table order

```
model User {
  orders    Order[]
}

model Product {
  orders    Order[]
}

model Order {
  id        Int      @id @default(autoincrement())
  userId    Int
  productId Int
  quantity  Int
  user      User     @relation(fields: [userId], references: [id])
  product   Product  @relation(fields: [productId], references: [id])
  createdAt DateTime @default(now())
}
```

Update dan Delete

```
const updateProduct = async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const updateData = req.body;

    const product = await prisma.product.update({
      where: { id: Number(id) },
      data: updateData
    });

    res.status(200).json({
      status: "Success",
      data: product,
      message: "Product updated success"
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({
      status: "Error",
      message: "Internal server error"
    });
  }
};
```

```
const deleteProduct = async (req: Request, res: Response) => {
  try {
    const { id } = req.params;

    await prisma.product.delete({
      where: { id: Number(id) }
    });

    res.status(200).json({
      status: "Success",
      message: "Product deleted success"
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({
      status: "Error", 
      message: "Internal server error"
    });
  }
};
```

Validate price tidak boleh < 0

```typescript
const createProduct = async (req: Request, res: Response) => {
    try {
      const { name, price, stock } = req.body;
      
      if (price < 0) {
        return res.status(400).json({
          status: "Error",
          message: "Price cannot be less than 0"
        });
      }
}
```
