# 🚀 Enterprise NestJS Boilerplate (Antigravity Edition)

[![NestJS](https://img.shields.io/badge/NestJS-E0234E?style=for-the-badge&logo=nestjs&logoColor=white)](https://nestjs.com/)
[![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Prisma](https://img.shields.io/badge/Prisma-2D3748?style=for-the-badge&logo=prisma&logoColor=white)](https://www.prisma.io/)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1?style=for-the-badge&logo=postgresql&logoColor=white)](https://www.postgresql.org/)
[![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com/)

> **FOR AI AGENTS & DEVELOPERS:** This documentation is structured to provide deep context, architectural decisions, and operational details to ensure seamless handover to any AI coding assistant (like Antigravity) or human developer.

---

## 🧠 Project Context & Architecture (Read Me First)

This is an **opinionated, production-ready** backend boilerplate built with NestJS. It is designed to be scalable, type-safe, and fully localized.

### 🏗️ Core Philosophy

- **Type Safety First:** Strict TypeScript configuration. `any` is forbidden. DTOs are the source of truth.
- **Generic Abstraction:** `BaseService` and `BaseController` handle 80% of CRUD operations, allowing developers to focus on business logic.
- **i18nNative:** Localization is not an afterthought. It is baked into the exception filters, response interceptors, and guards.
- **Security by Default:** JWT Auth, RBAC (Role-Based Access Control), Throttling, and Helmet are pre-configured.

### 📐 Architectural Decision Records (ADR)

_To understand WHY things are the way they are:_

1.  **Handling i18n Assets:**
    - **Problem:** Translation JSON files are not TypeScript code, so `tsc` ignores them during build.
    - **Solution:** We configured `nest-cli.json` with `"assets": ["i18n/**/*"]`. This ensures `src/i18n` is copied to `dist/i18n` automatically.
    - **Note:** When running with `node`, ensure `dist/main.js` can find these files.

2.  **Global Response Wrapping:**
    - **Mechanism:** `ResponseInterceptor` wraps all successful responses.
    - **Feature:** It automatically translates the "Operation successful" message based on the `Accept-Language` header using `I18nService`.
    - **Output Format:**
      ```json
      {
        "success": true,
        "status": 200,
        "message": "İşlem başarıyla tamamlandı", // Translated
        "data": { ... }
      }
      ```

3.  **Centralized Error Handling:**
    - **Mechanism:** `GlobalExceptionFilter` catches all `HttpException` and unknown `Error` types.
    - **Feature:** It accepts error keys (e.g., `AUTH_REQUIRED`) and translates them using `i18n`. If a translation is found in `errors.json`, it is returned; otherwise, the original message is shown.

4.  **UUID Generation:**
    - **Decision:** We use Node.js native `crypto.randomUUID()` instead of the external `uuid` package to avoid CommonJS/ESM compatibility issues.

---

## 🚀 Quick Start for AI & Humans

### 1. Prerequisites

- **Node.js:** v20.19+ (LTS)
- **Docker:** For running PostgreSQL and Redis effortlessly.
- **Package Manager:** `npm` (Lockfile: `package-lock.json`)

### 2. Environment Setup

```bash
cp .env.example .env
# ⚠️ CRITICAL: Ensure DATABASE_URL includes the username!
# Example: postgresql://postgres:password@localhost:15432/boilerplate_db
# Required for v20 prediction flow:
# AI_ENGINE_URL=http://127.0.0.1:8000
```

### 3. Installation & Database

```bash
# Install dependencies
npm ci

# Start Infrastructure (Postgres + Redis)
docker-compose up -d postgres redis

# Generate Prisma Client (REQUIRED after install)
npx prisma generate

# Run Migrations
npx prisma migrate dev

# Seed Database (Optional - Creates Admin & Roles)
npx prisma db seed
```

### 4. Running the App

```bash
# Debug Mode (Watch) - Best for Development
npm run start:dev

# Production Build & Run
npm run build
npm run start:prod
```

---

## 🛡️ Response Standardization & Type Safety Protocol

This boilerplate enforces a strict **"No-Leak"** policy for API responses to ensure both Security and Developer Experience.

### 1. The `unknown` Type is Forbidden

- **Rule:** Controllers must NEVER return `ApiResponse<unknown>` or raw Prisma entities.
- **Why:** Returning raw entities risks exposing sensitive fields like `password` hashes or internal metadata. It also breaks contract visibility for frontend developers.

### 2. DTO Pattern & Serialization

- **Tool:** We use `class-transformer` for all response serialization.
- **Implementation:**
  - All Response DTOs must use `@Exclude()` class-level decorator.
  - Only fields explicitly marked with `@Expose()` are returned to the client.
  - Controllers use `plainToInstance(UserResponseDto, data)` before returning data.

**Example:**

```typescript
// ✅ Good: Secure & Typed
@Get('me')
async getMe(@CurrentUser() user: User): Promise<ApiResponse<UserResponseDto>> {
  return createSuccessResponse(plainToInstance(UserResponseDto, user));
}

// ❌ Bad: Leaks password hash & Weak Types
@Get('me')
async getMe(@CurrentUser() user: User) {
  return createSuccessResponse(user);
}
```

---

## ⚡ High-Performance Caching (Redis Strategy)

To ensure enterprise-grade performance, we utilize **Redis** for caching frequently accessed data (e.g., Roles, Permissions).

- **Library:** `@nestjs/cache-manager` with `cache-manager-redis-yet` (Supports Redis v6+ / v7).
- **Configuration:** Global Cache Module in `AppModule`.
- **Strategy:** Read-heavy endpoints use `@UseInterceptors(CacheInterceptor)`.
- **Invalidation:** Write operations (Create/Update/Delete) manually invalidate relevant cache keys.

**Usage:**

```typescript
// 1. Automatic Caching
@Get('roles')
@UseInterceptors(CacheInterceptor)
@CacheKey('roles_list') // Unique Key
@CacheTTL(60000)        // 60 Seconds
async getAllRoles() { ... }

// 2. Manual Invalidation (Inject CACHE_MANAGER)
async createRole(...) {
  // ... create role logic
  await this.cacheManager.del('roles_list'); // Clear cache
}
```

---

## 🤖 Gemini AI Integration (Optional)

This boilerplate includes an **optional** AI module powered by Google's Gemini API. It's disabled by default and can be enabled during CLI setup or manually.

### Configuration

Add these to your `.env` file:

```env
# Enable Gemini AI features
ENABLE_GEMINI=true

# Your Google API Key (get from https://aistudio.google.com/apikey)
GOOGLE_API_KEY=your-api-key-here

# Model to use (optional, defaults to gemini-2.5-flash)
GEMINI_MODEL=gemini-2.5-flash
```

### Usage

The `GeminiService` is globally available when enabled:

```typescript
import { GeminiService } from './modules/gemini';

@Injectable()
export class MyService {
  constructor(private readonly gemini: GeminiService) {}

  async generateContent() {
    // Check if Gemini is available
    if (!this.gemini.isAvailable()) {
      throw new Error('AI features are not enabled');
    }

    // 1. Simple Text Generation
    const { text, usage } = await this.gemini.generateText(
      'Write a product description for a coffee mug',
    );

    // 2. With System Prompt & Options
    const { text } = await this.gemini.generateText('Translate: Hello World', {
      systemPrompt: 'You are a professional Turkish translator',
      temperature: 0.3,
      maxTokens: 500,
    });

    // 3. Multi-turn Chat
    const { text } = await this.gemini.chat([
      { role: 'user', content: 'What is TypeScript?' },
      {
        role: 'model',
        content: 'TypeScript is a typed superset of JavaScript...',
      },
      { role: 'user', content: 'Give me an example' },
    ]);

    // 4. Structured JSON Output
    interface ProductData {
      name: string;
      price: number;
      features: string[];
    }

    const { data } = await this.gemini.generateJSON<ProductData>(
      'Generate a product entry for a wireless mouse',
      '{ name: string, price: number, features: string[] }',
    );
    console.log(data.name, data.price); // Fully typed!
  }
}
```

### Available Methods

| Method                                      | Description                                      |
| ------------------------------------------- | ------------------------------------------------ |
| `isAvailable()`                             | Check if Gemini is properly configured and ready |
| `generateText(prompt, options?)`            | Generate text from a single prompt               |
| `chat(messages, options?)`                  | Multi-turn conversation                          |
| `generateJSON<T>(prompt, schema, options?)` | Generate and parse structured JSON               |

### Options

```typescript
interface GeminiGenerateOptions {
  model?: string; // Override default model
  systemPrompt?: string; // System instructions
  temperature?: number; // Creativity (0-1)
  maxTokens?: number; // Max response length
}
```

## 🌍 Internationalization (i18n) Guide

Unique to this project is the deep integration of `nestjs-i18n`.

- **Location:** `src/i18n/{lang}/`
- **Files:**
  - `common.json`: Generic messages (success, welcome)
  - `errors.json`: Error codes (AUTH_REQUIRED, USER_NOT_FOUND)
  - `validation.json`: Validation messages (IS_EMAIL)
  - `auth.json`: Auth specific success messages (LOGIN_SUCCESS)

**How to Translate a New Error:**

1.  Throw an exception with a key: `throw new ConflictException('EMAIL_EXISTS');`
2.  Add `"EMAIL_EXISTS": "Email already taken"` to `src/i18n/en/errors.json`.
3.  Add Turkish translation to `src/i18n/tr/errors.json`.
4.  Start server; the `GlobalExceptionFilter` handles the rest.

---

## 🧪 Testing & CI/CD

- **GitHub Actions:** `.github/workflows/ci.yml` handles build and linting checks on push.
- **Local Testing:**
  ```bash
  npm run test        # Unit tests
  npm run test:e2e    # End-to-End tests
  ```

---

## 📂 System Map (Directory Structure)

```
src/
├── app.module.ts           # Root module (Redis, Config, i18n setup)
├── main.ts                 # Entry point
├── common/                 # Shared resources
│   ├── base/               # Abstract BaseService & BaseController (CRUD)
│   ├── types/              # Interfaces (ApiResponse, PaginatedData)
│   ├── filters/            # Global Exception Filter
│   └── interceptors/       # Response Interceptor
├── config/                 # Application configuration
├── database/               # Prisma Service
├── i18n/                   # Localization assets
└── modules/                # Feature modules
    ├── admin/              # Admin capabilities (Roles, Permissions + Caching)
    │   ├── admin.controller.ts
    │   └── dto/            # Admin Response DTOs
    ├── auth/               # Authentication layer
    ├── gemini/             # 🤖 Optional AI module (Google Gemini)
    ├── health/             # Health checks
    └── users/              # User management
```

---

## 🛠️ Troubleshooting (Known Issues)

**1. `EADDRINUSE: address already in use`**

- **Fix:** `lsof -ti:3000 | xargs kill -9`

**2. `PrismaClientInitializationError` / Database Connection Hangs**

- **Fix:** Check `.env` `DATABASE_URL`. Ensure `docker-compose up` is running.

**3. Cache Manager Deprecation Warnings**

- **Context:** `cache-manager-redis-yet` may show deprecation warnings regarding `Keyv`. This is expected as we wait for the ecosystem to stabilize on `cache-manager` v6/v7. The current implementation is fully functional.

---

## 📃 License

This project is proprietary and confidential.
