Runbooks

Backend Local Setup

Настройка локального окружения для backend разработки.

Настройка локального окружения для backend разработки.

Применимо для: feature, change, bug, improvement — любая задача, требующая разработки backend функционала.

Prerequisites

  • Node.js >= 20
  • pnpm >= 9
  • Git
  • PostgreSQL >= 15 (локально или Docker)
  • Локальный проект настроен (runbook-local-setup)

1. Настройка базы данных

Вариант A: Docker (рекомендуется)

# Запустить PostgreSQL в Docker
docker run --name postgres-dev \
  -e POSTGRES_USER=dev \
  -e POSTGRES_PASSWORD=dev \
  -e POSTGRES_DB=app_dev \
  -p 5432:5432 \
  -d postgres:15

Вариант B: Локальный PostgreSQL

# macOS (Homebrew)
brew install postgresql@15
brew services start postgresql@15

# Создать базу
createdb app_dev

Проверка подключения

psql postgresql://dev:dev@localhost:5432/app_dev -c "SELECT 1;"

Ожидаемый результат: 1 в выводе.


2. Настройка Prisma 7

Установка

pnpm add prisma@latest
pnpm add -D @types/node

Инициализация

pnpm prisma init

Конфигурация schema.prisma

// prisma/schema.prisma
generator client {
  provider = "prisma-client"
  output   = "../server/generated/prisma"
}

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

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Важно (Prisma 7):

  • Генератор: prisma-client (НЕ prisma-client-js)
  • Обязательный output с путём к генерации
  • Импорт из сгенерированного пути, НЕ из @prisma/client

Переменные окружения

# .env
DATABASE_URL="postgresql://dev:dev@localhost:5432/app_dev"

Создание Prisma Client Singleton

// server/utils/prisma.ts
import { PrismaClient } from '../generated/prisma'

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined
}

export const prisma = globalForPrisma.prisma ?? new PrismaClient()

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}

Генерация клиента и миграции

# Сгенерировать Prisma Client
pnpm prisma generate

# Создать миграцию
pnpm prisma migrate dev --name init

# Проверить соединение
pnpm prisma db pull

Проверка

# Открыть Prisma Studio
pnpm prisma studio

Ожидаемый результат: Prisma Studio открывается на http://localhost:5555


3. Настройка Nuxt Server для WebSocket

Включение WebSocket в Nuxt

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    experimental: {
      websocket: true
    }
  }
})

Установка Socket.io

pnpm add socket.io socket.io-client

Создание серверного плагина

// server/plugins/socket.io.ts
import { Server } from 'socket.io'
import { Server as Engine } from 'engine.io'

export default defineNitroPlugin((nitroApp) => {
  const engine = new Engine()
  const io = new Server()
  io.bind(engine)

  io.on('connection', (socket) => {
    console.log('Client connected:', socket.id)

    socket.on('disconnect', () => {
      console.log('Client disconnected:', socket.id)
    })
  })

  nitroApp.router.use('/socket.io/', defineEventHandler({
    handler(event) {
      engine.handleRequest(event.node.req, event.node.res)
      event._handled = true
    },
    websocket: {
      open(peer) {
        engine.handleUpgrade(peer.request, peer.websocket.socket)
      }
    }
  }))
})

Проверка Socket.io

# Запустить dev сервер
pnpm dev

# В другом терминале - тест подключения
node -e "
const { io } = require('socket.io-client');
const socket = io('http://localhost:3000');
socket.on('connect', () => {
  console.log('Connected:', socket.id);
  socket.disconnect();
  process.exit(0);
});
socket.on('connect_error', (err) => {
  console.error('Error:', err.message);
  process.exit(1);
});
"

Ожидаемый результат: Connected: <socket-id>


4. Тестирование API

Установка инструментов

# REST Client для VS Code
code --install-extension humao.rest-client

# Или httpie для терминала
brew install httpie

Создание тестового эндпоинта

// server/api/health.get.ts
export default defineEventHandler(async (event) => {
  return {
    status: 'ok',
    timestamp: new Date().toISOString()
  }
})

Тестирование с REST Client

# api.http
### Health Check
GET http://localhost:3000/api/health

### Create User (пример)
POST http://localhost:3000/api/users
Content-Type: application/json

{
  "email": "test@example.com",
  "name": "Test User"
}

Тестирование с httpie

# GET запрос
http GET localhost:3000/api/health

# POST запрос
http POST localhost:3000/api/users email=test@example.com name="Test User"

Тестирование с curl

# Health check
curl -s http://localhost:3000/api/health | jq

# POST запрос
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","name":"Test User"}' | jq

5. Seed данные

Создание seed скрипта

// prisma/seed.ts
import { PrismaClient } from '../server/generated/prisma'

const prisma = new PrismaClient()

async function main() {
  // Очистка
  await prisma.user.deleteMany()

  // Создание тестовых данных
  await prisma.user.createMany({
    data: [
      { email: 'admin@example.com', name: 'Admin' },
      { email: 'user@example.com', name: 'User' },
    ],
  })

  console.log('Seed completed')
}

main()
  .catch(console.error)
  .finally(() => prisma.$disconnect())

Настройка package.json

{
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  }
}

Запуск seed

# Установить tsx если нет
pnpm add -D tsx

# Запустить seed
pnpm prisma db seed

Troubleshooting

Cannot find module '@prisma/client'

Симптомы: Cannot find module '@prisma/client'

Причина: Prisma 7 требует импорт из сгенерированного пути.

Решение:

// Неправильно (старый способ)
import { PrismaClient } from '@prisma/client'

// Правильно (Prisma 7)
import { PrismaClient } from '../generated/prisma'

ECONNREFUSED к PostgreSQL

Симптомы: Error: connect ECONNREFUSED 127.0.0.1:5432

Решение:

# Проверить статус PostgreSQL
docker ps | grep postgres

# Если не запущен
docker start postgres-dev

# Или проверить локальный сервис
brew services list | grep postgresql

Socket.io connection refused

Симптомы: connect_error: xhr poll error

Решение:

  1. Проверить что dev сервер запущен
  2. Проверить nitro.experimental.websocket: true в nuxt.config.ts
  3. Проверить что плагин создан в server/plugins/

Migration failed

Симптомы: Error: P3014: Prisma Migrate could not create the shadow database

Решение:

# Пересоздать базу
dropdb app_dev
createdb app_dev

# Применить миграции заново
pnpm prisma migrate dev

Hot reload создаёт множество подключений

Симптомы: too many connections или утечка памяти

Решение: Использовать singleton паттерн для Prisma Client (см. шаг 2).


Финальный чек-лист

  • PostgreSQL запущен и доступен
  • DATABASE_URL настроен в .env
  • Prisma Client сгенерирован
  • Миграции применены
  • Prisma Studio открывается
  • WebSocket включен в nuxt.config.ts
  • Socket.io плагин создан
  • Тестовое подключение Socket.io работает
  • API эндпоинты отвечают
  • Seed данные загружены

Связанные документы