npm package: @nestgate/entity
Description: Type-safe entity decorators with automatic validation and Swagger integration for NestJS. Write less code, maintain better.
Author: berkerozer
Latest version: 0.0.1

# @nestgate/entity

Type-safe entity decorators with automatic validation and Swagger integration for NestJS. Write less code, maintain better.

## 📦 Installation

```bash
npm install @nestgate/entity
# or
pnpm add @nestgate/entity
# or
yarn add @nestgate/entity
```

### Peer Dependencies

```bash
npm install @nestjs/common @nestjs/swagger class-validator class-transformer
```

## 🎯 Features

- **🎨 All-in-one decorators** - Validation + Swagger in single decorator
- **✅ Automatic validation** - Built-in class-validator integration
- **📚 Auto-documentation** - Swagger schemas generated automatically
- **🔒 Type-safe** - Full TypeScript support
- **🎭 Faker integration** - Auto-generated examples
- **👁️ Visibility control** - Hide sensitive fields from API

## 🚀 Quick Start

### Before @nestgate/entity

```typescript
import { IsString, IsInt, Min, Max, IsNotEmpty } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  @ApiProperty({
    description: 'User name',
    example: 'John Doe',
    type: 'string',
  })
  name: string;

  @IsInt()
  @Min(0)
  @Max(120)
  @ApiProperty({
    description: 'User age',
    example: 25,
    type: 'integer',
    minimum: 0,
    maximum: 120,
  })
  age: number;
}
```

### With @nestgate/entity

```typescript
import { String, Integer } from '@nestgate/entity';

export class CreateUserDto {
  @String({ description: 'User name' })
  name: string;

  @Integer({ min: 0, max: 120, description: 'User age' })
  age: number;
}
```

**60% less code, same functionality!** 🎉

## 📚 API Reference

### @String(options?)

String validation with automatic Swagger documentation.

```typescript
@String({
  required?: boolean;        // Default: true
  description?: string;      // Swagger description
  example?: string;          // Swagger example (auto-generated if not provided)
  minLength?: number;        // Minimum string length
  maxLength?: number;        // Maximum string length
  default?: string;          // Default value
  deprecated?: boolean;      // Mark as deprecated
  exclude?: boolean;         // Hide from API response
})
```

**Example:**

```typescript
class UserDto {
  @String({
    description: 'User full name',
    minLength: 2,
    maxLength: 100,
  })
  name: string;

  @String({
    required: false,
    description: 'User bio',
    maxLength: 500,
  })
  bio?: string;

  @String({
    exclude: true, // Won't appear in API responses
  })
  internalNote: string;
}
```

### @Integer(options?)

Integer validation with min/max constraints.

```typescript
@Integer({
  required?: boolean;        // Default: true
  description?: string;
  example?: number;
  min?: number;             // Minimum value
  max?: number;             // Maximum value
  default?: number;
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
class ProductDto {
  @Integer({
    description: 'Product price in cents',
    min: 0,
  })
  price: number;

  @Integer({
    description: 'Stock quantity',
    min: 0,
    default: 0,
  })
  stock: number;

  @Integer({
    description: 'User age',
    min: 0,
    max: 150,
  })
  age: number;
}
```

### @Float(options?)

Floating point number validation.

```typescript
@Float({
  required?: boolean;
  description?: string;
  example?: number;
  min?: number;
  max?: number;
  default?: number;
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
class MeasurementDto {
  @Float({
    description: 'Temperature in Celsius',
    min: -273.15,
  })
  temperature: number;

  @Float({
    description: 'Product rating',
    min: 0,
    max: 5,
  })
  rating: number;
}
```

### @Boolean(options?)

Boolean validation.

```typescript
@Boolean({
  required?: boolean;
  description?: string;
  example?: boolean;
  default?: boolean;
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
class SettingsDto {
  @Boolean({
    description: 'Email notifications enabled',
    default: true,
  })
  emailNotifications: boolean;

  @Boolean({
    description: 'Account is active',
    default: false,
  })
  isActive: boolean;
}
```

### @UUID(options?)

UUID validation with version support.

```typescript
@UUID({
  required?: boolean;
  description?: string;
  example?: string;
  default?: string;
  version?: '3' | '4' | '5' | 'all';  // Default: '4'
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
class EntityDto {
  @UUID({
    description: 'Unique identifier',
  })
  id: string;

  @UUID({
    description: 'Parent entity ID',
    required: false,
  })
  parentId?: string;

  @UUID({
    version: '5',
    description: 'Namespace UUID',
  })
  namespaceId: string;
}
```

### @DateTime(options?)

Date/DateTime validation with automatic transformation.

```typescript
@DateTime({
  required?: boolean;
  description?: string;
  example?: string | Date;
  default?: string | Date;
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
class EventDto {
  @DateTime({
    description: 'Event start time',
  })
  startAt: Date;

  @DateTime({
    description: 'Event end time',
    required: false,
  })
  endAt?: Date;

  @DateTime({
    description: 'Created timestamp',
    default: new Date(),
  })
  createdAt: Date;
}
```

**Alias:** `@Date` is also available.

### @Enum(enumType, options?)

Enum validation.

```typescript
@Enum(EnumType, {
  required?: boolean;
  description?: string;
  example?: any;
  default?: any;
  deprecated?: boolean;
  exclude?: boolean;
})
```

**Example:**

```typescript
enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  MODERATOR = 'moderator',
}

enum Status {
  ACTIVE = 'ACTIVE',
  INACTIVE = 'INACTIVE',
  PENDING = 'PENDING',
}

class UserDto {
  @Enum(UserRole, {
    description: 'User role',
    default: UserRole.USER,
  })
  role: UserRole;

  @Enum(Status, {
    description: 'Account status',
    default: Status.PENDING,
  })
  status: Status;
}
```

### @ConnectOne(entity, options?)

Connect a single nested entity (from `@nestgate/core`).

```typescript
import { ConnectOne } from '@nestgate/entity';

class AddressDto {
  @String()
  street: string;

  @String()
  city: string;
}

class UserDto {
  @ConnectOne(AddressDto, {
    description: 'User address',
    required: false,
  })
  address?: AddressDto;
}
```

### @ConnectMany(entity, options?)

Connect array of nested entities (from `@nestgate/core`).

```typescript
import { ConnectMany } from '@nestgate/entity';

class PostDto {
  @String()
  title: string;
}

class UserDto {
  @ConnectMany(PostDto, {
    description: 'User posts',
  })
  posts: PostDto[];
}
```

## 💡 Complete Examples

### User Entity

```typescript
import {
  String,
  Integer,
  Boolean,
  UUID,
  DateTime,
  Enum,
} from '@nestgate/entity';

enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
}

export class CreateUserDto {
  @String({
    description: 'User email address',
    example: 'user@example.com',
  })
  email: string;

  @String({
    description: 'User password',
    minLength: 8,
    exclude: true, // Hide from API response
  })
  password: string;

  @String({
    description: 'User full name',
    minLength: 2,
    maxLength: 100,
  })
  name: string;

  @Integer({
    description: 'User age',
    min: 13,
    max: 120,
    required: false,
  })
  age?: number;

  @Enum(UserRole, {
    description: 'User role',
    default: UserRole.USER,
  })
  role: UserRole;

  @Boolean({
    description: 'Is email verified',
    default: false,
  })
  isVerified: boolean;
}

export class UserResponseDto extends CreateUserDto {
  @UUID({
    description: 'User unique identifier',
  })
  id: string;

  @DateTime({
    description: 'Account creation date',
  })
  createdAt: Date;

  @DateTime({
    description: 'Last update date',
  })
  updatedAt: Date;
}
```

### Product Entity with Relations

```typescript
import {
  String,
  Integer,
  Float,
  Boolean,
  UUID,
  ConnectMany,
} from '@nestgate/entity';

class CategoryDto {
  @UUID()
  id: string;

  @String()
  name: string;
}

class TagDto {
  @String()
  name: string;
}

export class CreateProductDto {
  @String({
    description: 'Product name',
    minLength: 3,
    maxLength: 200,
  })
  name: string;

  @String({
    description: 'Product description',
    required: false,
  })
  description?: string;

  @Float({
    description: 'Product price',
    min: 0,
  })
  price: number;

  @Integer({
    description: 'Stock quantity',
    min: 0,
    default: 0,
  })
  stock: number;

  @Boolean({
    description: 'Is product available',
    default: true,
  })
  isAvailable: boolean;

  @ConnectMany(CategoryDto, {
    description: 'Product categories',
  })
  categories: CategoryDto[];

  @ConnectMany(TagDto, {
    description: 'Product tags',
    required: false,
  })
  tags?: TagDto[];
}
```

### Blog Post with Mixins

```typescript
import { Mix } from '@nestgate/core';
import {
  String,
  UUID,
  DateTime,
  ConnectOne,
  ConnectMany,
} from '@nestgate/entity';

// Reusable mixins
class Timestamped {
  @DateTime()
  createdAt: Date;

  @DateTime()
  updatedAt: Date;
}

class Authorable {
  @UUID()
  authorId: string;
}

// Related entities
class AuthorDto {
  @UUID()
  id: string;

  @String()
  name: string;
}

class CommentDto {
  @String()
  text: string;

  @DateTime()
  createdAt: Date;
}

// Main entity
export class BlogPostDto extends Mix(Timestamped, Authorable) {
  @UUID()
  id: string;

  @String({
    minLength: 3,
    maxLength: 200,
  })
  title: string;

  @String()
  content: string;

  @ConnectOne(AuthorDto)
  author: AuthorDto;

  @ConnectMany(CommentDto, { required: false })
  comments?: CommentDto[];
}
```

## 🎭 Auto-generated Examples

All decorators use Faker.js to generate realistic examples automatically:

```typescript
@String()  // example: "John Doe"

@Integer()  // example: 42

@UUID()  // example: "123e4567-e89b-12d3-a456-426614174000"

@DateTime()  // example: "2024-01-01T00:00:00.000Z"
```

## 🔒 Excluding Sensitive Fields

Use `exclude: true` to hide fields from API responses:

```typescript
class UserDto {
  @String()
  email: string;

  @String({ exclude: true })
  password: string; // Won't appear in responses

  @String({ exclude: true })
  refreshToken: string; // Won't appear in responses
}
```

## 🔗 Related Packages

- [@nestgate/core](../core) - Core utilities (Mix, ConnectOne, ConnectMany)
- [@nestgate/rest](../rest) - REST API decorators
- [@nestgate/setup](../setup) - Quick application setup

## 📝 License

MIT © [NestGate](https://nestgate.org)

## 🤝 Contributing

Contributions are welcome! Please see our [Contributing Guide](../../CONTRIBUTING.md).

## 💬 Support

- [Documentation](https://nestgate.org)
- [GitHub Issues](https://github.com/nestgate/nestgate/issues)
- [Discord](https://discord.gg/nestgate)