# πŸš€ 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:5432/boilerplate_db ``` ### 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` 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> { 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( '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(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.