# Backend Documentation

> Hono + tRPC API service

## 📋 Overview

The Izri backend is a modern, type-safe API server built with Hono (fast web framework) and tRPC (type-safe RPC), using Drizzle ORM for database access. This provides end-to-end type safety from database to frontend with excellent performance.

## 🎯 Technology Stack

- **Framework**: Hono (Fast, lightweight web server)
- **API Layer**: tRPC (Type-safe Remote Procedure Calls)
- **Database ORM**: Drizzle ORM (TypeScript-first ORM)
- **Database**: PostgreSQL 15
- **Cache**: Redis 7
- **Validation**: Zod schemas
- **Logging**: Pino (structured logging)
- **Observability**: OpenTelemetry (optional)
- **Runtime**: Node.js 18+ with tsx for development

## 📚 Documentation Pages

### [API Server Setup](./api-server-setup.md)

**Complete API server configuration guide**

- Server architecture overview
- Quick start and installation
- Environment configuration
- Hono + tRPC integration
- OpenTelemetry setup
- Docker deployment
- Testing and debugging

### [tRPC Server](./trpc-server.md)

**tRPC implementation details**

- Router structure
- Procedure types (query vs mutation)
- Context creation
- Middleware implementation
- Input validation
- Type inference
- Client integration

### [Authentication](./authentication.md)

**Backend authentication strategies**

- Authentication architecture
- Session management
- API tokens
- OAuth integration
- Authorization patterns
- Security best practices

### [Database Schema](./database-schema.md)

**Complete database reference**

- Full schema documentation
- Table relationships
- Indexes and constraints
- Enums and types
- Query patterns
- Performance optimization

### [Migrations](./migrations.md)

**Database migration workflow**

- Creating migrations
- Applying migrations
- Rolling back changes
- Migration best practices
- Schema versioning
- Production migration strategy

### [Error Handling](./error-handling.md)

**Error management patterns**

- Error types and codes
- Error transformation
- Client error handling
- Logging errors
- User-facing errors
- Debugging strategies

### [Logging](./logging.md)

**Structured logging and observability**

- Pino configuration
- Log levels and structure
- Request logging
- Error logging
- Performance logging
- OpenTelemetry integration
- Log aggregation

## 🏗️ API Structure

```
apps/api/
└── src/
    └── index.ts              # Hono server entry point

packages/trpc/
├── src/
│   ├── context.ts            # tRPC context (auth, db)
│   ├── routers/
│   │   └── index.ts          # All tRPC procedures
│   └── index.ts              # Exports
└── package.json

packages/database/
├── src/
│   ├── schema.ts             # Drizzle schema definitions
│   ├── client.ts             # Database client
│   ├── seed.ts               # Seed script
│   └── index.ts              # Exports
├── migrations/               # SQL migration files
└── drizzle.config.ts         # Drizzle configuration
```

## 🚀 Quick Start

### Development

```bash
# Start API server
pnpm dev:api

# Or from root
pnpm dev

# Access at http://localhost:4000
```

### Testing Endpoints

```bash
# Health check (REST)
curl http://localhost:4000/health

# Health check (tRPC)
curl -X POST http://localhost:4000/trpc/health

# Get projects (tRPC)
curl -X POST http://localhost:4000/trpc/projects.getProjects \
  -H "Content-Type: application/json" \
  -d '{"userEmail":"test@izri.com"}'
```

## 📡 API Endpoints

### REST Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health check |
| POST | `/trpc/*` | tRPC endpoint |

### tRPC Procedures

#### Queries (Read Operations)

| Procedure | Input | Output | Description |
|-----------|-------|--------|-------------|
| `health` | - | `{ ok: boolean }` | API health check |
| `projects.getProjects` | `{ userEmail }` | `Project[]` | Get user's projects |
| `projects.getProject` | `{ projectId, userEmail }` | `Project` | Get single project |
| `organizations.list` | `{ userEmail }` | `Organization[]` | List user's organizations |
| `auth.getSession` | - | `SessionInfo` | Get current session |

#### Mutations (Write Operations)

| Procedure | Input | Output | Description |
|-----------|-------|--------|-------------|
| `projects.createProject` | `CreateProjectInput` | `Project` | Create new project |
| `projects.updateProject` | `UpdateProjectInput` | `Project` | Update project |
| `projects.deleteProject` | `{ projectId, userEmail }` | `{ message }` | Delete project |
| `organizations.create` | `CreateOrganizationInput` | `Organization` | Create organization |
| `analysis.analyzeRepository` | `AnalyzeRepositoryInput` | `AnalysisResult` | Analyze repository |

## 🗄️ Database Schema

### Core Tables

- **users**: User accounts and profiles
- **organizations**: Teams and workspaces
- **projects**: Repository projects
- **test_runs**: Test execution records
- **project_settings**: Project configuration
- **organization_members**: Team memberships
- **api_keys**: API authentication tokens

### Relationships

```
users ──< projects ──< test_runs
  │        │
  │        └─ project_settings
  │
  └─< organization_members >─ organizations
```

## 🔐 Authentication Flow

```mermaid
graph LR
    A[Client] --> B{Auth Type}
    B -->|Session| C[Cookie]
    B -->|API Token| D[Bearer Token]
    C --> E[Validate Session]
    D --> F[Validate Token]
    E --> G[User Context]
    F --> G
    G --> H[tRPC Procedures]
```

## 📝 Example Implementation

### tRPC Procedure

```typescript
// packages/trpc/src/routers/index.ts
import { z } from 'zod'
import { publicProcedure, router } from '../trpc'
import { projects } from '@izri/database'
import { eq } from 'drizzle-orm'

export const appRouter = router({
  projects: router({
    // Query example
    getProject: protectedProcedure
      .input(z.object({
        projectId: z.string(),
        userEmail: z.string().email()
      }))
      .query(async ({ ctx, input }) => {
        const project = await ctx.db.query.projects.findFirst({
          where: eq(projects.id, input.projectId),
          with: {
            testRuns: {
              orderBy: (testRuns, { desc }) => [desc(testRuns.createdAt)],
              limit: 10
            }
          }
        })

        if (!project) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: 'Project not found'
          })
        }

        return project
      }),

    // Mutation example
    createProject: protectedProcedure
      .input(z.object({
        name: z.string(),
        description: z.string().optional(),
        repository: z.string().url(),
        branch: z.string().default('main'),
        language: z.string(),
        framework: z.string().optional(),
        userEmail: z.string().email()
      }))
      .mutation(async ({ ctx, input }) => {
        const [project] = await ctx.db
          .insert(projects)
          .values({
            ...input,
            userId: ctx.user.id
          })
          .returning()

        return project
      })
  })
})
```

### Using from Frontend

```typescript
// In React component
import { trpc } from '~/lib/trpc'

function ProjectDetail({ projectId }: { projectId: string }) {
  // Query - auto-typed!
  const { data: project, isLoading } = trpc.projects.getProject.useQuery({
    projectId,
    userEmail: user.email
  })

  // Mutation - auto-typed!
  const updateProject = trpc.projects.updateProject.useMutation({
    onSuccess: () => {
      // Handle success
    }
  })

  if (isLoading) return <div>Loading...</div>

  return (
    <div>
      <h1>{project.name}</h1>
      <p>{project.description}</p>
      {/* ... */}
    </div>
  )
}
```

## 🔧 Configuration

### Environment Variables

```bash
# Database
DATABASE_URL="postgresql://postgres:password@localhost:5433/izri"

# API Server
API_PORT=4000
LOG_LEVEL="info"  # debug, info, warn, error

# OpenTelemetry (optional)
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318/v1/traces"

# Authentication (future)
JWT_SECRET="your-secret-key"
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"
```

### Hono Server Configuration

```typescript
// apps/api/src/index.ts
import { Hono } from 'hono'
import { trpcServer } from '@hono/trpc-server'
import { appRouter } from '@izri/trpc'
import { createContext } from '@izri/trpc/context'

const app = new Hono()

// Health endpoint
app.get('/health', (c) => c.json({ ok: true }))

// tRPC endpoint
app.use(
  '/trpc/*',
  trpcServer({
    router: appRouter,
    createContext
  })
)

const port = process.env.API_PORT || 4000
console.log(`🚀 Server running on http://localhost:${port}`)

export default app
```

## 📊 Performance

### Query Optimization

```typescript
// Use indexes
await ctx.db.query.projects.findMany({
  where: eq(projects.userId, userId),
  // Fast due to index on userId
})

// Use select for large tables
await ctx.db
  .select({
    id: projects.id,
    name: projects.name
  })
  .from(projects)
  .where(eq(projects.userId, userId))

// Use with for relations
await ctx.db.query.projects.findFirst({
  with: {
    testRuns: true  // Efficient join
  }
})
```

### Caching Strategy

```typescript
// Redis caching (future)
const cacheKey = `project:${projectId}`
const cached = await redis.get(cacheKey)

if (cached) return JSON.parse(cached)

const project = await db.query.projects.findFirst({...})

await redis.set(cacheKey, JSON.stringify(project), 'EX', 3600)
```

## 🧪 Testing

```typescript
// Test tRPC procedures
import { appRouter } from './routers'
import { createContext } from './context'

describe('projects.getProject', () => {
  it('should return project', async () => {
    const ctx = await createContext({})
    const caller = appRouter.createCaller(ctx)

    const project = await caller.projects.getProject({
      projectId: 'test-project-id',
      userEmail: 'test@example.com'
    })

    expect(project).toBeDefined()
    expect(project.id).toBe('test-project-id')
  })
})
```

## 🔗 Related Documentation

- **Architecture**: [System Overview](../architecture/overview.md)
- **Frontend**: [tRPC Integration](../frontend/trpc-integration.md)
- **Database**: [Database Package](../packages/database.md)
- **API Reference**: [tRPC Procedures](../api-reference/trpc-procedures.md)

## 🆘 Troubleshooting

### Server Won't Start

```bash
# Check if port is in use
lsof -ti:4000 | xargs kill -9

# Check database connection
psql $DATABASE_URL

# Check environment variables
cat .env | grep DATABASE_URL
```

### Type Errors

```bash
# Rebuild packages
pnpm build:packages

# Generate database types
pnpm db:generate
```

### Database Errors

```bash
# Check migrations
pnpm db:migrate

# Restart database
pnpm docker:down
pnpm dev:docker
```

---

*Ready to dive deep? Start with [API Overview](./api-overview.md) →*
