Инициализация проекта на express и установка требуемых библиотек::

npm init -y
npm i express body-parser jsonwebtoken nodemon dotenv pg argon2 cookie-parser

Меняем в package.json: нужно добавить type и скрипт dev

  "main": "index.js",
  "type": "module",
  "scripts": {
    "dev": "nodemon app.js"
  },

Создаем app.js в корневой папке

Базовая структура проекта
Базовая структура проекта

Скачиваем Prisma и инициализируем её через консоль:

npm i prisma @prisma/client
npx prisma init 

Далее нужно заполнить schema.prisma моделями сущностей. Для этого вы можете изучить статью Обзор Prisma ORM: как забыть об SQL и сосредоточиться на данных. Вот мой пример:

generator client {
  provider = "prisma-client-js"
  // Тут будет output, его нужно удалить
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Users {
  id Int @id @default(autoincrement())
  phone String @unique //УНИКАЛЬНОЕ ХНАЧЕНИЕ(КОГДА НЕ МОЖЕТ ПОВТОРЯТЬСЯ)
  name String
  
  applications Applications[]
}

model Doctors{
  id Int @id @default(autoincrement())
  name String
  surname String
  patronymic String? //опционально, если не обязательное значение 
  specialization String

  applications  Applications[] // привязка к другой модели (даём "разрешение")
}

model Applications { // для записей с интервалом 30 мин с 10 до 20
  id Int @id @default(autoincrement())
  doctorid Int 
  date DateTime
  date DateTime
  userid Int?

  doctor Doctors @relation(fields: [doctorid], references: [id]) //делаем связь
  user Users? @relation(fields: [userid], references: [id])//делаем опциональную связь
}

После этого нужно добавить изменения в файл .env:

DATABASE_URL="postgresql://postgres:1234@localhost:5432/cat?schema=public"

Теперь у нас готова базовая настройка Prisma, поэтому нам нужно создать миграции. Миграции - это контролируемый набор изменений, которые изменяют структуру базы данных. Они помогают переводить схему базы данных из одного состояния в другое, например, создавать или удалять таблицы и столбцы, разделять поля в таблице или добавлять типы и ограничения.

npx prisma migrate dev --name init
npx prisma db push

Если в schema.prisma были добавлены изменения, то нужно сделать ряд функций:

npx prisma migrate reset // Удаление данных в бд
npx prisma migrate dev // Создание миграции
npx prisma db push // Добавление таблиц в бд

(Если нужно отслеживать изменения в бд, можно использовать prisma studio)

Итоговая структура проекта
Итоговая структура проекта

Создаём client.js и пишем там подключение к бд:

// Связь с бд, для получения, добавления, изменения и удаления данных в бд
import { PrismaClient } from "../generated/prisma/index.js";

const prisma = new PrismaClient();


export default prisma;

Теперь заполняем app.js:

//создаем приложение
import express from "express";
import router from './route/index.js'

const app = express() //сохранения экспресс переменную
app.use(express.json()) //подключение джисон вывода

BigInt.prototype.toJSON = function() { return this.toString() } // Конвертирует bigint в строку

app.use('/api', router); // Нужно добавить позже

app.listen(3000, () => { //ОТВЕЧАЕТ ЗА ЗАПУСК СЕРВЕРА
    console.log('http://localhost:3000') //вывод пути сервера 
})

process.on('SIGINT', async () => {
  await prisma.$disconnect()
  process.exit(0)
}) //останавливает работу бд, когда отключаешься от сервера

Для запуска сервера пишем npm run dev. Заполняем файлы для каждой модели по очередности: сервис, контролер, роутер.

Пишем сервис для доктора (doctor.service.js). Подробнее можно прочитать в статье Prisma ORM: полное руководство для начинающих (и не только). Часть 1:

import prisma from '../../prisma/clinet.js' // импортируем призму

class DoctorService { //создание класса, где хранятся методы, которые изменяют бд
    async getAll() {
        return await prisma.doctors.findMany(); //возвращает всех докторов
    }
    async getOneById(id) {
        return await prisma.doctors.findUnique({
            where: {
                id
            }
        }); //возвращает одного доктора по ID
    }
    async create(name, surname, patronymic, specialization) {
        return await prisma.doctors.create({
            data:{
                name, 
                surname, 
                patronymic, 
                specialization
            }
        }); //cоздание докторов
    }
    async update(id, name, surname, patronymic, specialization) {
        const doctor = this.getOneById(id);
        if (!doctor)
            return "такого доктора нет"

        return await prisma.doctors.update({
            data: {
                name: name ? name : doctor.name,
                surname,
                patronymic, 
                specialization
            },
            where:{ 
                id
            }
        }); //обновление докторов
    }
    async delete(id) {
        return await prisma.doctors.delete({
            where:{
                id
            }
        }); //удаляет доктора по айди
    }
    
}

export default new DoctorService();

Далее заполняет контролер доктора (doctor.controller.js):

import DoctorService from "./doctor.service.js";

class DoctorController {
    async getAllDoctors(req, res) {
        try {
            const doctors = await DoctorService.getAll(); 
            return res.json(doctors);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
    }
     async getOneDoctors(req, res) {
        try {
            const id = req.params.id;
            const doctors = await DoctorService.getOneById(id); 
            return res.json(doctors);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
    }
     async createDoctor(req, res) {
        try {
            const {name, surname, patronymic, specialization} = req.body;
            const doctors = await DoctorService.create(name, surname, patronymic, specialization); 
            return res.json(doctors);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
    }
     async updateDoctor(req, res) {
        try {
            const id = req.params.id;
            const {name, surname, patronymic, specialization} = req.body;
            const doctors = await DoctorService.update(id, name, surname, patronymic, specialization); 
            return res.json(doctors);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
    }
      async deleteDoctor(req, res) {
        try {
            const id = req.params.id;
            const doctors = await DoctorService.update(id); 
            return res.json(doctors);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
    }
    
    
}

export default new DoctorController();

Дальше заполняем маршрут доктора (doctor.router.js):

import express from 'express'
import DoctorController from './doctor.conroller.js';

const doctorRouter = express.Router() //сохранение метода роутер в переменную

doctorRouter.get('/getall', DoctorController.getAllDoctors)
doctorRouter.get('/get/:id', DoctorController.getOneDoctors)
doctorRouter.post('/post', DoctorController.createDoctor)
doctorRouter.put('/put/:id', DoctorController.updateDoctor)
doctorRouter.delete('/delete/:id', DoctorController.deleteDoctor)

// doctorRouter.post('/create')

export default doctorRouter;

Также заполняем остальные модели.

И после того, как мы все заполнили, мы идем в route, а там в index.js:

import express from 'express'
import doctorRouter from '../models/doctor/doctor.router.js'; // импортитуем маршруты доктора
import userRouter from '../models/user/user.router.js'; // испортируем маршруты пользователей
import apllicationsRouter from '../models/applications/applications.router.js';

const router = express.Router() // объявление переменной маршрута

router.use('/doctor', doctorRouter); // маршруты доктора
router.use('/user', userRouter); // маршруты пользователя
router.use('/apllication', apllicationsRouter); // маршруты заявок

export default router;

После этого мы добавляем app.use(‘/api’, router)  (это было выше)

После всех манипуляция наша структура может выглядеть вот так:

Вот ещё примеры сервиса, контроллера и роутера:

В application.service.js мы пишем:

import prisma from '../../prisma/clinet.js' // импортируем призму
import doctorService from '../doctor/doctor.service.js';

class ApplicationsService { //создание класса, где хранятся методы, которые изменяют бд
    async createApplication(userId, doctorId, day, month, year, time) {
        const doctor = doctorService.getOneById(userId);
        if (!doctor)
            return "Такого доктора нет";

        return prisma.applications.create({
            data: {
                userid: userId,
                doctorid: doctorId,
                date: new Date(year, month, day)
            }
        })
    }
}

export default new ApplicationsService();

В application.controller.js контролер:

import applicationsService from "./applications.service.js";

class ApllicationsController {
    
     async createApplications(req, res) {
        try {
            const {userid, doctorid, day, month, year, time} = req.body;
            const application = await applicationsService.create(userid, doctorid, day, month, year, time); 
            return res.json(application);
        } catch (err) {
            console.error(err);
            return res.status(500).json({ error: err.message });
        }
 
     }

    }
export default new ApllicationsController();

В application.router.js:

import express from 'express'
import applicationsController from './applications.controller.js';

const apllicationsRouter = express.Router() //сохранение метода роутер в переменную

apllicationsRouter.post('/post', applicationsController.createApplications)

export default apllicationsRouter;

Наше API готово! Если остались вопросы по оформлению, то можете почитать следующие статьи:

Understanding Express Routes, Controllers, and Services - DEV Community

Building REST APIs with Prisma ORM | Prisma Documentation

Комментарии (3)


  1. KonstantinTokar
    21.06.2025 20:34

    В русском языке API - мужского рода...


  1. Elkost
    21.06.2025 20:34

    То есть вместо объяснений что и почему, как работает технология и тд, мы получили generic пример с анти-паттернами, а в чем идея собственно?


  1. CloudlyNosound
    21.06.2025 20:34

    "Быстро" ещё не значит "хорошо".

    Как, с точки зрения качества работы, у такого проекта обстоят дела?