Sql To Mikroorm

SQL DDL to MikroORM TypeScript Entity Generator

Convert SQL CREATE TABLE definitions into MikroORM entity classes with @Entity, @PrimaryKey, @Property, @Index, and relationship decorators.

Presets:
SQL Dialect:Class Naming:Property Style:
SQL DDL Input (CREATE TABLE Statements)
/**
 * MikroORM TypeScript Entities
 * Generated automatically by ToolsAA SQL to MikroORM Generator
 * Dialect: POSTGRES | Entities: 7
 */

import {
  Cascade,
  Collection,
  Entity,
  Enum,
  ManyToOne,
  OneToMany,
  OneToOne,
  PrimaryKey,
  Property,
  Unique,
} from '@mikro-orm/core';

// ============================================================================
// Database Enums
// ============================================================================

UserStatusEnum {
  ACTIVE = 'active',
  PENDING = 'pending',
  SUSPENDED = 'suspended',
  ARCHIVED = 'archived',
}

OrderStatusEnum {
  DRAFT = 'draft',
  PENDING = 'pending',
  PAID = 'paid',
  SHIPPED = 'shipped',
  CANCELLED = 'cancelled',
}

@Entity({ tableName: 'tenants' })
export class Tenant {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
  id!: string;

  @Property({ unique: true, length: 64 })
  slug!: string;

  @Property({ length: 120, fieldName: 'company_name' })
  companyName!: string;

  @Property({ type: 'boolean', fieldName: 'is_active', default: true })
  isActive!: boolean;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @Property({ onUpdate: () => new Date() })
  updatedAt: Date = new Date();

  @OneToMany(() => User, (user) => user.tenant, { cascade: [Cascade.ALL], orphanRemoval: true })
  users = new Collection<User>(this);

  @OneToMany(() => Category, (category) => category.tenant, { cascade: [Cascade.ALL], orphanRemoval: true })
  categories = new Collection<Category>(this);

  @OneToMany(() => Product, (product) => product.tenant, { cascade: [Cascade.ALL], orphanRemoval: true })
  products = new Collection<Product>(this);

  @OneToMany(() => Order, (order) => order.tenant, { cascade: [Cascade.ALL], orphanRemoval: true })
  orders = new Collection<Order>(this);
}

@Entity({ tableName: 'users' })
@Unique({ properties: ['tenant', 'email'] })
export class User {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
  id!: string;

  @Property({ length: 255 })
  email!: string;

  @Property({ length: 255, fieldName: 'password_hash' })
  passwordHash!: string;

  @Property({ length: 100, fieldName: 'display_name' })
  displayName!: string;

  @Enum(() => UserStatusEnum)
  status!: UserStatusEnum = UserStatusEnum.ACTIVE;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @Property({ onUpdate: () => new Date() })
  updatedAt: Date = new Date();

  @ManyToOne(() => Tenant, { fieldName: 'tenant_id', deleteRule: 'cascade' })
  tenant!: Tenant;

  @OneToOne(() => UserProfile, (userProfile) => userProfile.user)
  userProfile?: UserProfile;

  @OneToMany(() => Order, (order) => order.user, { cascade: [Cascade.ALL], orphanRemoval: true })
  orders = new Collection<Order>(this);
}

@Entity({ tableName: 'user_profiles' })
export class UserProfile {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
  id!: string;

  @Property({ length: 500, nullable: true, fieldName: 'avatar_url' })
  avatarUrl?: string;

  @Property({ type: 'text', nullable: true })
  bio?: string;

  @Property({ length: 32, nullable: true, fieldName: 'phone_number' })
  phoneNumber?: string;

  @Property({ type: 'json', nullable: true })
  preferences?: Record<string, unknown>;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @OneToOne(() => User, { fieldName: 'user_id', deleteRule: 'cascade', owner: true })
  user!: User;
}

@Entity({ tableName: 'categories' })
@Unique({ properties: ['tenant', 'slug'] })
export class Category {
  @PrimaryKey({ autoincrement: true })
  id!: number;

  @Property({ length: 100 })
  name!: string;

  @Property({ length: 120 })
  slug!: string;

  @Property({ fieldName: 'sort_order', default: 0 })
  sortOrder!: number;

  @ManyToOne(() => Tenant, { fieldName: 'tenant_id', deleteRule: 'cascade' })
  tenant!: Tenant;

  @ManyToOne(() => Category, { fieldName: 'parent_id', deleteRule: 'set null', nullable: true })
  parent?: Category;

  @OneToMany(() => Category, (category) => category.parent, { cascade: [Cascade.ALL], orphanRemoval: true })
  children = new Collection<Category>(this);

  @OneToMany(() => Product, (product) => product.category, { cascade: [Cascade.ALL], orphanRemoval: true })
  products = new Collection<Product>(this);
}

@Entity({ tableName: 'products' })
@Unique({ properties: ['tenant', 'sku'] })
export class Product {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
  id!: string;

  @Property({ length: 64 })
  sku!: string;

  @Property({ length: 200 })
  title!: string;

  @Property({ type: 'decimal', precision: 12, scale: 2 })
  price!: string;

  @Property({ fieldName: 'inventory_count', default: 0 })
  inventoryCount!: number;

  @Property({ type: 'json', nullable: true })
  attributes?: Record<string, unknown>;

  @Property({ type: 'array', nullable: true })
  tags?: string[];

  @Property({ type: 'boolean', fieldName: 'is_published', default: false })
  isPublished!: boolean;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @Property({ onUpdate: () => new Date() })
  updatedAt: Date = new Date();

  @ManyToOne(() => Tenant, { fieldName: 'tenant_id', deleteRule: 'cascade' })
  tenant!: Tenant;

  @ManyToOne(() => Category, { fieldName: 'category_id', deleteRule: 'set null', nullable: true })
  category?: Category;

  @OneToMany(() => OrderItem, (orderItem) => orderItem.product, { cascade: [Cascade.ALL], orphanRemoval: true })
  orderItems = new Collection<OrderItem>(this);
}

@Entity({ tableName: 'orders' })
export class Order {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
  id!: string;

  @Property({ unique: true, length: 32, fieldName: 'order_number' })
  orderNumber!: string;

  @Enum(() => OrderStatusEnum)
  status!: OrderStatusEnum = OrderStatusEnum.DRAFT;

  @Property({ type: 'decimal', precision: 12, scale: 2 })
  subtotal!: string;

  @Property({ type: 'decimal', precision: 12, scale: 2, fieldName: 'tax_amount', default: 0.00 })
  taxAmount!: string;

  @Property({ type: 'decimal', precision: 12, scale: 2, fieldName: 'shipping_cost', default: 0.00 })
  shippingCost!: string;

  @Property({ type: 'decimal', precision: 12, scale: 2, fieldName: 'total_amount' })
  totalAmount!: string;

  @Property({ type: 'text', nullable: true })
  notes?: string;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @Property({ onUpdate: () => new Date() })
  updatedAt: Date = new Date();

  @ManyToOne(() => Tenant, { fieldName: 'tenant_id', deleteRule: 'cascade' })
  tenant!: Tenant;

  @ManyToOne(() => User, { fieldName: 'user_id', deleteRule: 'restrict' })
  user!: User;

  @OneToMany(() => OrderItem, (orderItem) => orderItem.order, { cascade: [Cascade.ALL], orphanRemoval: true })
  orderItems = new Collection<OrderItem>(this);
}

@Entity({ tableName: 'order_items' })
export class OrderItem {
  @PrimaryKey({ autoincrement: true })
  id!: string;

  @Property()
  quantity!: number;

  @Property({ type: 'decimal', precision: 12, scale: 2, fieldName: 'unit_price' })
  unitPrice!: string;

  @Property({ type: 'decimal', precision: 12, scale: 2, fieldName: 'line_total' })
  lineTotal!: string;

  @Property({ onCreate: () => new Date() })
  createdAt: Date = new Date();

  @ManyToOne(() => Order, { fieldName: 'order_id', deleteRule: 'cascade' })
  order!: Order;

  @ManyToOne(() => Product, { fieldName: 'product_id', deleteRule: 'restrict' })
  product!: Product;
}

MikroORM Entities7 entities generated
Relations Mapped10 foreign keys resolved
Columns Converted58 columns typed

100% Client-Side In-Memory Engine

Zero database connections, remote API calls, or server uploads. All SQL parsing, AST extraction, and MikroORM TypeScript entity synthesis execute entirely in your local browser sandbox.

Complete MikroORM v5 & v6 Decorator Ecosystem

Accurately maps @PrimaryKey (UUID, autoincrement, composite), @Property (types, length, nullable, defaultRaw), @Index, @Unique, @Enum, and automated onCreate/onUpdate timestamp hooks.

Type-Safe Relational Graph & Multi-Dialect Support

Automatically detects foreign key constraints to build @ManyToOne, @OneToMany Collection<T>, and @OneToOne relations with cascade options across PostgreSQL, MySQL, SQLite, and MSSQL.

Technical Reference & Architecture Guide

SQL DDL to MikroORM TypeScript Entity Generator — Reference Guide

Convert SQL CREATE TABLE definitions into MikroORM entity classes with @Entity, @PrimaryKey, @Property, @Index, and relationship decorators.

Key Parameters & Controls

SQL DialectEnum (PostgreSQL | MySQL | SQLite | MSSQL)

Specifies the database SQL dialect used to parse column data types, sequence defaults (such as SERIAL, AUTO_INCREMENT, or IDENTITY), and index options.

Default: PostgreSQL
Class Naming StrategyEnum (PascalCase Singular | Preserve Table Name)

Controls how SQL table names are converted into TypeScript entity class names, converting pluralized table names (e.g., 'user_accounts') into singular PascalCase identifiers (e.g., 'UserAccount').

Default: PascalCase Singular
Property Naming StrategyEnum (camelCase | Preserve snake_case)

Determines whether table column identifiers are transformed into camelCase properties with explicit field mappings (e.g., @Property({ fieldName: 'first_name' })) or kept in raw snake_case.

Default: camelCase
Relation GenerationEnum (Bidirectional (@ManyToOne & @OneToMany) | Foreign Key Fields Only)

Configures whether SQL foreign key references generate bidirectional MikroORM relations with Collection<T> or output simple scalar foreign key properties.

Default: Bidirectional (@ManyToOne & @OneToMany)

Pro Tips & Best Practices

In MikroORM

In MikroORM, reverse collections in @OneToMany or @ManyToMany relations must be initialized as new Collection<T>(this) in the entity definition. This enables lazy-loading and ensures methods like .init() and .getItems() function seamlessly without undefined errors.

When declaring entity relations across

When declaring entity relations across separate files with @ManyToOne(() => Author) and @OneToMany(() => Book, book => book.author), always pass the target entity class as an ES arrow function to prevent module evaluation deadlocks during Node.js startup.

When converting snake_case SQL columns

When converting snake_case SQL columns to idiomatic TypeScript camelCase properties, specify @Property({ fieldName: 'db_column' }). This maintains complete compatibility with legacy schemas and production databases without triggering unexpected migration diffs.

Common Gotchas & Troubleshooting

TypeScript compile error: 'Property has no initializer and is not definitely assigned in constructor' (TS2564)

When TypeScript strictPropertyInitialization is enabled, add the definite assignment assertion exclamation mark to MikroORM entity fields (e.g., 'name!: string;'). MikroORM's Identity Map and EntityManager will hydrate these properties dynamically from the database.

Cannot find type for @Property() when emitting metadata with TypeScript reflection

If TypeScript emitDecoratorMetadata fails to infer complex or generic types, explicitly provide the type option inside the decorator, such as @Property({ type: 'text', nullable: true }) or @Property({ type: 'json' }).

Frequently Asked Questions

How does the converter map SQL primary keys to MikroORM decorators?▼

Columns defined with PRIMARY KEY and AUTO_INCREMENT or SERIAL syntax map to @PrimaryKey({ autoincrement: true }). UUID columns map to @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' }). Composite primary keys are supported by annotating each composite key property with @PrimaryKey().

How are SQL foreign keys translated into MikroORM relationship decorators?▼

SQL REFERENCES constraints are converted into @ManyToOne(() => TargetEntity, { nullable: true/false }). If bidirectional relations are enabled, the referenced target entity also receives an opposing @OneToMany(() => CurrentEntity, current => current.foreignKeyProperty) with new Collection<CurrentEntity>(this).

Does the generator support MikroORM v5 and v6 features?▼

Yes. Generated code adheres to modern MikroORM standards, including clean decorator imports from '@mikro-orm/core', optional Opt<T> / EntityRef<T> type constructs, Collection<T> initializers, and mikro-orm.config.ts configuration snippets.

Are SQL schemas or proprietary database definitions uploaded to any server?▼

No. The entire conversion process executes 100% client-side in your local browser sandbox via WebAssembly and JavaScript AST parsing. No SQL statements, schema structures, or metadata are ever transmitted across the network.

Related Tools & Utilities

All Tools →