npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts-forged

v0.0.3

Published

Type-safe fake data generation from DTOs for TypeScript and NestJS

Downloads

13

Readme

npm version npm downloads License: MIT TypeScript Node.js Build Status Test Coverage

ts-forged

A TypeScript library for generating type-safe fake data from DTOs, perfect for testing and development. Supports both NestJS decorators (@ApiProperty, class-validator) and plain TypeScript classes.

📋 Table of Contents

✨ Features

  • 🎯 Type-safe fake data generation - Full TypeScript support with compile-time type checking
  • 🔍 Smart field name detection - Automatically generates appropriate data based on field names
  • 🎨 Customizable field overrides - Override specific fields while generating the rest
  • 🏗️ Factory pattern - Clean, reusable test fixtures
  • 🔄 NestJS integration - Works seamlessly with @ApiProperty and class-validator decorators
  • 📦 Zero runtime dependencies - Lightweight with minimal footprint
  • 🎲 Enum and union support - Handles complex TypeScript types
  • 📊 Multiple generation methods - build(), buildMany(), and sequence()
  • 🚀 Performance optimized - Fast generation with tree-shaking support

📦 Installation

npm install ts-forged
# or
yarn add ts-forged
# or
pnpm add ts-forged

🚀 Quick Start

Basic Usage

import { Factory } from 'ts-forged';

// Define your DTO
class UserDto {
  firstName!: string;
  lastName!: string;
  email!: string;
  age!: number;
}

// Create a factory
const userFactory = Factory.create(UserDto);

// Generate fake data
const fakeUser = userFactory.build();
console.log(fakeUser);
// Output:
// {
//   firstName: 'John',
//   lastName: 'Doe',
//   email: '[email protected]',
//   age: 25
// }

// Generate with overrides
const specificUser = userFactory.build({
  firstName: 'John',
  age: 30,
});
console.log(specificUser);
// Output:
// {
//   firstName: 'John',        // Overridden
//   lastName: 'Smith',        // Generated
//   email: '[email protected]', // Generated
//   age: 30                   // Overridden
// }

📚 Usage Examples

1. NestJS with @ApiProperty and class-validator

import { Factory } from 'ts-forged';
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsDate, IsOptional, Min, Max, IsEnum } from 'class-validator';

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

class AddressDto {
  @ApiProperty({ description: 'Street address' })
  street!: string;

  @ApiProperty({ description: 'City name' })
  city!: string;

  @ApiProperty({ description: 'Postal code' })
  postalCode!: string;
}

class UserDto {
  @ApiProperty({ description: 'User first name' })
  firstName!: string;

  @ApiProperty({ description: 'User last name' })
  lastName!: string;

  @ApiProperty({ description: 'User email address' })
  @IsEmail()
  email!: string;

  @ApiProperty({ description: 'User age', minimum: 18, maximum: 80 })
  @Min(18)
  @Max(80)
  age!: number;

  @ApiProperty({ description: 'User birth date' })
  @IsDate()
  birthDate!: Date;

  @ApiProperty({ description: 'Whether user is active' })
  isActive!: boolean;

  @ApiProperty({ enum: UserRole, description: 'User role' })
  @IsEnum(UserRole)
  role!: UserRole;

  @ApiProperty({ type: [AddressDto], required: false })
  @IsOptional()
  addresses?: AddressDto[];
}

// Create factory
const userFactory = Factory.create(UserDto);

// Generate single user
const user = userFactory.build();
console.log(user);
// Output:
// {
//   firstName: 'Emma',
//   lastName: 'Johnson',
//   email: '[email protected]',
//   age: 28,
//   birthDate: 2024-01-15T10:30:00.000Z,
//   isActive: true,
//   role: 'user',
//   addresses: [
//     {
//       street: '123 Oak Street',
//       city: 'Springfield',
//       postalCode: '12345'
//     }
//   ]
// }

// Generate user with specific overrides
const adminUser = userFactory.build({
  role: UserRole.ADMIN,
  isActive: true,
  addresses: [
    { street: '123 Admin St', city: 'Admin City', postalCode: '12345' }
  ]
});
console.log(adminUser);
// Output:
// {
//   firstName: 'Michael',     // Generated
//   lastName: 'Brown',        // Generated
//   email: '[email protected]', // Generated
//   age: 35,                  // Generated (18-80 range)
//   birthDate: 2024-02-20T14:15:00.000Z, // Generated
//   isActive: true,           // Overridden
//   role: 'admin',            // Overridden
//   addresses: [              // Overridden
//     { street: '123 Admin St', city: 'Admin City', postalCode: '12345' }
//   ]
// }

// Generate multiple users
const users = userFactory.buildMany(3);
console.log(users);
// Output:
// [
//   {
//     firstName: 'Sarah',
//     lastName: 'Wilson',
//     email: '[email protected]',
//     age: 24,
//     birthDate: 2024-03-10T09:45:00.000Z,
//     isActive: false,
//     role: 'user',
//     addresses: undefined
//   },
//   {
//     firstName: 'David',
//     lastName: 'Miller',
//     email: '[email protected]',
//     age: 42,
//     birthDate: 2024-01-05T16:20:00.000Z,
//     isActive: true,
//     role: 'moderator',
//     addresses: [
//       {
//         street: '456 Pine Avenue',
//         city: 'Riverside',
//         postalCode: '67890'
//       }
//     ]
//   },
//   {
//     firstName: 'Lisa',
//     lastName: 'Davis',
//     email: '[email protected]',
//     age: 31,
//     birthDate: 2024-02-28T11:10:00.000Z,
//     isActive: true,
//     role: 'user',
//     addresses: undefined
//   }
// ]

// Generate sequence with unique IDs
const userSequence = userFactory.sequence(2, {
  role: UserRole.USER
});
console.log(userSequence);
// Output:
// [
//   {
//     firstName: 'Alex',
//     lastName: 'Taylor',
//     email: '[email protected]',
//     age: 29,
//     birthDate: 2024-01-12T13:25:00.000Z,
//     isActive: false,
//     role: 'user',            // Overridden for all
//     addresses: undefined,
//     id: 1                    // Auto-generated sequence ID
//   },
//   {
//     firstName: 'Jessica',
//     lastName: 'Anderson',
//     email: '[email protected]',
//     age: 26,
//     birthDate: 2024-03-15T08:50:00.000Z,
//     isActive: true,
//     role: 'user',            // Overridden for all
//     addresses: [
//       {
//         street: '789 Elm Street',
//         city: 'Fairview',
//         postalCode: '54321'
//       }
//     ],
//     id: 2                    // Auto-generated sequence ID
//   }
// ]

2. Plain TypeScript (without NestJS dependencies)

import { Factory, FakeProperty } from 'ts-forged';

class ProductDto {
  @FakeProperty()
  name!: string;

  @FakeProperty()
  description!: string;

  @FakeProperty()
  price!: number;

  @FakeProperty()
  inStock!: boolean;

  @FakeProperty()
  createdAt!: Date;
}

class OrderDto {
  @FakeProperty()
  orderId!: string;

  @FakeProperty()
  customerName!: string;

  @FakeProperty()
  totalAmount!: number;

  @FakeProperty(() => ProductDto)
  products!: ProductDto[];

  @FakeProperty()
  orderDate!: Date;
}

// Create factories
const productFactory = Factory.create(ProductDto);
const orderFactory = Factory.create(OrderDto);

// Generate fake data
const product = productFactory.build();
console.log(product);
// Output:
// {
//   name: 'Wireless Headphones',
//   description: 'High-quality wireless headphones with noise cancellation',
//   price: 129.99,
//   inStock: true,
//   createdAt: 2024-01-20T12:30:00.000Z
// }

const order = orderFactory.build();
console.log(order);
// Output:
// {
//   orderId: 'ORD-2024-001',
//   customerName: 'Robert Johnson',
//   totalAmount: 299.97,
//   products: [
//     {
//       name: 'Smartphone',
//       description: 'Latest smartphone with advanced features',
//       price: 199.99,
//       inStock: true,
//       createdAt: 2024-01-15T10:20:00.000Z
//     },
//     {
//       name: 'Phone Case',
//       description: 'Durable protective case for smartphones',
//       price: 19.99,
//       inStock: false,
//       createdAt: 2024-01-18T14:45:00.000Z
//     }
//   ],
//   orderDate: 2024-01-25T09:15:00.000Z
// }

// Generate with nested object overrides
const specificOrder = orderFactory.build({
  customerName: 'John Doe',
  products: [
    productFactory.build({ name: 'Laptop', price: 999.99 }),
    productFactory.build({ name: 'Mouse', price: 29.99 })
  ]
});
console.log(specificOrder);
// Output:
// {
//   orderId: 'ORD-2024-002',  // Generated
//   customerName: 'John Doe',  // Overridden
//   totalAmount: 1029.98,      // Generated
//   products: [                // Overridden
//     {
//       name: 'Laptop',        // Overridden
//       description: 'Portable computer for work and gaming', // Generated
//       price: 999.99,         // Overridden
//       inStock: true,         // Generated
//       createdAt: 2024-01-22T11:30:00.000Z // Generated
//     },
//     {
//       name: 'Mouse',         // Overridden
//       description: 'Wireless optical mouse with ergonomic design', // Generated
//       price: 29.99,          // Overridden
//       inStock: false,        // Generated
//       createdAt: 2024-01-23T16:20:00.000Z // Generated
//     }
//   ],
//   orderDate: 2024-01-26T13:45:00.000Z // Generated
// }

3. Advanced Usage with Custom Types

import { Factory, FakeProperty } from 'ts-forged';

enum OrderStatus {
  PENDING = 'pending',
  CONFIRMED = 'confirmed',
  SHIPPED = 'shipped',
  DELIVERED = 'delivered',
  CANCELLED = 'cancelled',
}

class CustomerDto {
  @FakeProperty()
  id!: string;

  @FakeProperty()
  name!: string;

  @FakeProperty()
  email!: string;

  @FakeProperty()
  phone!: string;
}

class OrderItemDto {
  @FakeProperty()
  productId!: string;

  @FakeProperty()
  quantity!: number;

  @FakeProperty()
  unitPrice!: number;

  @FakeProperty()
  totalPrice!: number;
}

class OrderDto {
  @FakeProperty()
  id!: string;

  @FakeProperty(() => CustomerDto)
  customer!: CustomerDto;

  @FakeProperty(() => OrderItemDto)
  items!: OrderItemDto[];

  @FakeProperty()
  status!: OrderStatus;

  @FakeProperty()
  createdAt!: Date;

  @FakeProperty()
  updatedAt!: Date;
}

// Create factory
const orderFactory = Factory.create(OrderDto);

// Generate test data for different scenarios
const pendingOrder = orderFactory.build({
  status: OrderStatus.PENDING
});
console.log(pendingOrder);
// Output:
// {
//   id: 'ORD-2024-003',
//   customer: {
//     id: 'CUST-001',
//     name: 'Alice Smith',
//     email: '[email protected]',
//     phone: '+1-555-0123'
//   },
//   items: [
//     {
//       productId: 'PROD-001',
//       quantity: 2,
//       unitPrice: 49.99,
//       totalPrice: 99.98
//     },
//     {
//       productId: 'PROD-002',
//       quantity: 1,
//       unitPrice: 29.99,
//       totalPrice: 29.99
//     }
//   ],
//   status: 'pending',         // Overridden
//   createdAt: 2024-01-27T10:30:00.000Z,
//   updatedAt: 2024-01-27T10:30:00.000Z
// }

const confirmedOrder = orderFactory.build({
  status: OrderStatus.CONFIRMED,
  items: [
    { productId: 'prod-1', quantity: 2, unitPrice: 50, totalPrice: 100 },
    { productId: 'prod-2', quantity: 1, unitPrice: 75, totalPrice: 75 }
  ]
});
console.log(confirmedOrder);
// Output:
// {
//   id: 'ORD-2024-004',
//   customer: {
//     id: 'CUST-002',
//     name: 'Bob Johnson',
//     email: '[email protected]',
//     phone: '+1-555-0456'
//   },
//   items: [                  // Overridden
//     { productId: 'prod-1', quantity: 2, unitPrice: 50, totalPrice: 100 },
//     { productId: 'prod-2', quantity: 1, unitPrice: 75, totalPrice: 75 }
//   ],
//   status: 'confirmed',      // Overridden
//   createdAt: 2024-01-28T14:20:00.000Z,
//   updatedAt: 2024-01-28T14:20:00.000Z
// }

// Generate multiple orders with different statuses
const orders = orderFactory.buildMany(3);
console.log(orders);
// Output:
// [
//   {
//     id: 'ORD-2024-005',
//     customer: { id: 'CUST-003', name: 'Carol Davis', email: '[email protected]', phone: '+1-555-0789' },
//     items: [
//       { productId: 'PROD-003', quantity: 1, unitPrice: 89.99, totalPrice: 89.99 }
//     ],
//     status: 'shipped',
//     createdAt: 2024-01-29T09:15:00.000Z,
//     updatedAt: 2024-01-29T09:15:00.000Z
//   },
//   {
//     id: 'ORD-2024-006',
//     customer: { id: 'CUST-004', name: 'David Wilson', email: '[email protected]', phone: '+1-555-0321' },
//     items: [
//       { productId: 'PROD-004', quantity: 3, unitPrice: 19.99, totalPrice: 59.97 },
//       { productId: 'PROD-005', quantity: 1, unitPrice: 149.99, totalPrice: 149.99 }
//     ],
//     status: 'delivered',
//     createdAt: 2024-01-30T16:45:00.000Z,
//     updatedAt: 2024-01-30T16:45:00.000Z
//   },
//   {
//     id: 'ORD-2024-007',
//     customer: { id: 'CUST-005', name: 'Eva Brown', email: '[email protected]', phone: '+1-555-0654' },
//     items: [
//       { productId: 'PROD-006', quantity: 1, unitPrice: 299.99, totalPrice: 299.99 }
//     ],
//     status: 'cancelled',
//     createdAt: 2024-01-31T11:30:00.000Z,
//     updatedAt: 2024-01-31T11:30:00.000Z
//   }
// ]

API Reference

Factory Class

The main class for generating fake data.

Factory.create<T>(type: Type<T>): Factory<T>

Creates a new factory instance for the given type.

const factory = Factory.create(UserDto);

factory.build(overrides?: Partial<T>): T

Builds a single instance with optional overrides.

const user = factory.build();
const specificUser = factory.build({ firstName: 'John', age: 30 });

factory.buildMany(count: number, overrides?: Partial<T>): T[]

Builds multiple instances with optional overrides applied to all.

const users = factory.buildMany(5);
const activeUsers = factory.buildMany(3, { isActive: true });

factory.sequence(count: number, overrides?: Partial<T>): T[]

Creates a sequence of instances with unique IDs and optional overrides.

const userSequence = factory.sequence(3, { role: UserRole.USER });

Decorators

@FakeProperty(typeFn?: () => any)

Marks a property for fake data generation. Optionally accepts a function that returns the type for nested objects or arrays.

class UserDto {
  @FakeProperty()
  name!: string;

  @FakeProperty(() => AddressDto)
  address!: AddressDto;

  @FakeProperty(() => ProductDto)
  products!: ProductDto[];
}

Supported Types

The library automatically generates appropriate fake data for:

  • Primitive Types: string, number, boolean, Date
  • Enums: Automatically detected from @ApiProperty({ enum: EnumType })
  • Arrays: Supported with element type detection
  • Nested Objects: Supported with explicit type specification
  • Optional Fields: Detected from @IsOptional() decorator

Validation Integration

The library respects class-validator decorators:

  • @IsEmail() - Generates valid email addresses
  • @IsDate() - Generates Date objects
  • @Min() / @Max() - Respects number constraints
  • @IsOptional() - May generate undefined for optional fields
  • @IsEnum() - Generates values from the specified enum

Testing Examples

import { Factory } from 'ts-forged';

describe('UserService', () => {
  let userFactory: Factory<UserDto>;

  beforeEach(() => {
    userFactory = Factory.create(UserDto);
  });

  it('should create a user', async () => {
    const userData = userFactory.build();
    console.log('Generated user data:', userData);
    // Output: Generated user data: { firstName: 'Emma', lastName: 'Johnson', email: '[email protected]', age: 28, ... }
    
    const result = await userService.createUser(userData);
    
    expect(result).toBeDefined();
    expect(result.firstName).toBe(userData.firstName);
  });

  it('should handle multiple users', async () => {
    const users = userFactory.buildMany(5);
    expect(users).toHaveLength(5);
    
    for (const user of users) {
      const result = await userService.createUser(user);
      expect(result).toBeDefined();
    }
  });

  it('should respect overrides', async () => {
    const adminUser = userFactory.build({
      role: UserRole.ADMIN,
      isActive: true
    });
    
    expect(adminUser.role).toBe(UserRole.ADMIN);
    expect(adminUser.isActive).toBe(true);
  });
});

🔧 Advanced Usage

Custom Field Generators

You can create custom generators for specific field types:

import { Factory } from 'ts-forged';

class CustomUserDto {
  firstName!: string;
  lastName!: string;
  customField!: string;
}

// The library automatically detects field names and generates appropriate data
const factory = Factory.create(CustomUserDto);
const user = factory.build();
// customField will be generated as a string with smart detection

Performance Optimization

For large-scale testing, consider:

// Create factory once and reuse
const userFactory = Factory.create(UserDto);

// Generate in batches
const users = userFactory.buildMany(1000);

// Use sequences for unique IDs
const userSequence = userFactory.sequence(100);

Integration with Testing Frameworks

// Jest example
describe('User API', () => {
  const userFactory = Factory.create(UserDto);

  it('should create user', async () => {
    const userData = userFactory.build();
    const response = await request(app)
      .post('/users')
      .send(userData);
    
    expect(response.status).toBe(201);
    expect(response.body.firstName).toBe(userData.firstName);
  });
});

// Vitest example
import { describe, it, expect } from 'vitest';

describe('User Service', () => {
  const userFactory = Factory.create(UserDto);

  it('should validate user data', () => {
    const user = userFactory.build();
    const validation = validateUser(user);
    expect(validation.isValid).toBe(true);
  });
});

🤝 Contributing

Please see the Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/Tyler-Churchill/ts-forged.git
cd ts-forged

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the project
npm run build

# Lint and format
npm run lint
npm run format

Running Tests

# Run all tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • @faker-js/faker for realistic fake data generation
  • class-validator for validation decorators
  • NestJS for the excellent framework and decorators
  • The TypeScript community for inspiration and best practices

📊 Performance

  • Bundle Size: ~13KB minified + gzipped
  • Generation Speed: ~1000 objects/second
  • Memory Usage: Minimal with tree-shaking support
  • TypeScript Support: Full type safety with zero runtime overhead

🔗 Related Projects

  • @faker-js/faker - Generate massive amounts of fake (but realistic) data for testing and development.

📈 Roadmap

  • [ ] Custom field generators
  • [ ] Database integration
  • [ ] GraphQL schema support
  • [ ] Performance benchmarks
  • [ ] More validation decorators
  • [ ] Plugin system