Sql To Typeorm

SQL DDL to TypeORM Entity Generator (TypeScript Entities)

Convert SQL CREATE TABLE DDL statements into TypeScript TypeORM entity classes with @Column, @PrimaryGeneratedColumn, and relations.

Presets:
Database Dialect:Class Naming:Property Style:
SQL DDL Input(5 tables)
/**
 * TypeORM Entity Definitions (Generated by ToolsAA)
 * Target Dialect: POSTGRES
 * Date: 2026-10-21
 */

import {
  Column,
  CreateDateColumn,
  Entity,
  Index,
  JoinColumn,
  ManyToOne,
  OneToMany,
  OneToOne,
  PrimaryGeneratedColumn,
  Unique,
  UpdateDateColumn,
} from 'typeorm';

OrderStatusEnum {
  PENDING = 'PENDING',
  PAID = 'PAID',
  PROCESSING = 'PROCESSING',
  SHIPPED = 'SHIPPED',
  DELIVERED = 'DELIVERED',
  CANCELLED = 'CANCELLED',
}

UserRoleEnum {
  ADMIN = 'ADMIN',
  CUSTOMER = 'CUSTOMER',
  VENDOR = 'VENDOR',
}

@Entity('users')
User {
  @PrimaryGeneratedColumn('uuid', { name: 'id' })
  id!: string;

  @Column({ type: 'varchar', length: 255, name: 'email', unique: true })
  email!: string;

  @Column({ type: 'varchar', length: 150, name: 'full_name', nullable: true })
  fullName: string | null;

  @Column({ type: 'enum', enum: UserRoleEnum, default: UserRoleEnum.CUSTOMER, name: 'role' })
  role!: UserRoleEnum;

  @Column({ type: 'boolean', name: 'is_verified', default: false })
  isVerified!: boolean;

  @Column({ type: 'jsonb', name: 'metadata', nullable: true })
  metadata: Record<string, any> | null;

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt!: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
  updatedAt!: Date;

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

  @OneToMany(() => Order, (order) => order.customer)
  orders!: Order[];
}

@Entity('user_profiles')
UserProfile {
  @PrimaryGeneratedColumn('uuid', { name: 'id' })
  id!: string;

  @Column({ type: 'uuid', name: 'user_id', unique: true })
  userId!: string;

  @Column({ type: 'varchar', length: 500, name: 'avatar_url', nullable: true })
  avatarUrl: string | null;

  @Column({ type: 'varchar', length: 32, name: 'phone_number', nullable: true })
  phoneNumber: string | null;

  @Column({ type: 'text', name: 'shipping_address', nullable: true })
  shippingAddress: string | null;

  @Column({ type: 'varchar', length: 64, name: 'tax_identifier', nullable: true })
  taxIdentifier: string | null;

  @OneToOne(() => User, (user) => user.userProfile, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'user_id' })
  user!: User;
}

@Entity('products')
@Index('idx_products_sku', ['sku'])
Product {
  @PrimaryGeneratedColumn({ name: 'id' })
  id!: number;

  @Column({ type: 'varchar', length: 64, name: 'sku', unique: true })
  sku!: string;

  @Column({ type: 'varchar', length: 200, name: 'title' })
  title!: string;

  @Column({ type: 'text', name: 'description', nullable: true })
  description: string | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, name: 'unit_price', default: 0.00 })
  unitPrice!: string;

  @Column({ type: 'int', name: 'inventory_count', default: 0 })
  inventoryCount!: number;

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

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt!: Date;

  @OneToMany(() => OrderItem, (orderItem) => orderItem.product)
  orderItems!: OrderItem[];
}

@Entity('orders')
@Index('idx_orders_status', ['status'])
Order {
  @PrimaryGeneratedColumn('uuid', { name: 'id' })
  id!: string;

  @Column({ type: 'uuid', name: 'customer_id' })
  customerId!: string;

  @Column({ type: 'varchar', length: 64, name: 'order_number', unique: true })
  orderNumber!: string;

  @Column({ type: 'enum', enum: OrderStatusEnum, default: OrderStatusEnum.PENDING, name: 'status' })
  status!: OrderStatusEnum;

  @Column({ type: 'decimal', precision: 12, scale: 2, name: 'total_amount', default: 0.00 })
  totalAmount!: string;

  @Column({ type: 'decimal', precision: 10, scale: 2, name: 'tax_amount', default: 0.00 })
  taxAmount!: string;

  @Column({ type: 'text', name: 'shipping_notes', nullable: true })
  shippingNotes: string | null;

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt!: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
  updatedAt!: Date;

  @ManyToOne(() => User, (user) => user.orders, { onDelete: 'RESTRICT' })
  @JoinColumn({ name: 'customer_id' })
  customer!: User;

  @OneToMany(() => OrderItem, (orderItem) => orderItem.order)
  orderItems!: OrderItem[];
}

@Entity('order_items')
@Unique('uq_order_product', ['orderId', 'productId'])
OrderItem {
  @PrimaryGeneratedColumn({ name: 'id' })
  id!: number;

  @Column({ type: 'uuid', name: 'order_id' })
  orderId!: string;

  @Column({ type: 'int', name: 'product_id' })
  productId!: number;

  @Column({ type: 'int', name: 'quantity', default: 1 })
  quantity!: number;

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

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

  @ManyToOne(() => Order, (order) => order.orderItems, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'order_id' })
  order!: Order;

  @ManyToOne(() => Product, (product) => product.orderItems, { onDelete: 'RESTRICT' })
  @JoinColumn({ name: 'product_id' })
  product!: Product;
}

TypeORM Entities5 entities generated
Relations Resolved4 foreign keys mapped
Columns Mapped37 columns converted

100% Client-Side Privacy

Zero database connections or server uploads. All SQL parsing, AST extraction, and TypeScript TypeORM entity synthesis occur entirely within your local browser.

Intelligent TypeORM Decorators

Automatically maps primary keys (@PrimaryGeneratedColumn, @PrimaryColumn), column types, precision, default values, @CreateDateColumn, @UpdateDateColumn, @Index, and @Unique.

Multi-Dialect & Bidirectional Relations

Seamlessly converts PostgreSQL, MySQL, SQLite, and SQL Server schemas into typed @ManyToOne, @OneToMany, and @OneToOne relations with cascade options.

Technical Reference & Architecture Guide

SQL DDL to TypeORM Entity Generator (TypeScript Entities) — Reference Guide

Convert SQL CREATE TABLE DDL statements into TypeScript TypeORM entity classes with @Column, @PrimaryGeneratedColumn, and relations.

Key Parameters & Controls

SQL DialectEnum (PostgreSQL | MySQL | SQLite | SQL Server | Oracle)

Specifies the SQL database syntax used to parse column data types, character limits, default constraint clauses, and autoincrement primary keys.

Default: PostgreSQL
Property Naming StrategyEnum (camelCase with @Column({ name }) | Preserve SQL snake_case)

Determines whether snake_case database column names are transformed into idiomatic TypeScript camelCase properties with explicit @Column({ name: 'column_name' }) mappings.

Default: camelCase with @Column({ name })
Relation Generation StrategyEnum (Bidirectional (@ManyToOne & @OneToMany) | Scalar Foreign Keys Only)

Configures whether SQL foreign key constraints produce full TypeORM relation decorators with @JoinColumn or retain scalar foreign key fields without navigational object properties.

Default: Bidirectional (@ManyToOne & @OneToMany)
Timestamp DecoratorsEnum (Automatic @CreateDateColumn & @UpdateDateColumn | Standard @Column)

Detects canonical auditing columns (such as created_at and updated_at) and decorates them with TypeORM specialized automatic lifecycle timestamp annotations.

Default: Automatic @CreateDateColumn & @UpdateDateColumn

Pro Tips & Best Practices

Always configure the camelCase naming

Always configure the camelCase naming strategy with explicit @Column({ name: 'db_col_name' }). This keeps your TypeScript application code clean and idiomatic while guaranteeing existing relational database tables remain 100% backward compatible without table migrations.

SQL types like DECIMAL

SQL types like DECIMAL(18,4) and BIGINT exceed the safe integer precision of JavaScript number primitives. TypeORM automatically maps DECIMAL to TypeScript string by default; ensure your business logic uses libraries like decimal.js or BigInt for exact financial calculations.

When establishing @ManyToOne

When establishing @ManyToOne and @OneToMany relationships between separate entity files, always define target entity references as lambda functions (e.g., @ManyToOne(() => Author, (author) => author.posts)) to avoid runtime circular module import errors in Node.js and TypeScript.

Common Gotchas & Troubleshooting

TypeORM error: 'Missing @JoinColumn on entity relation'

In TypeORM, @JoinColumn() is required on the owner side of a @OneToOne relation and on the foreign key side of a @ManyToOne relation. Ensure @JoinColumn({ name: 'author_id' }) is placed directly alongside the relation property that owns the physical foreign key column.

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

TypeScript with strictPropertyInitialization enabled requires class fields to be initialized in a constructor. For TypeORM entity classes, add the definite assignment assertion exclamation mark (e.g., 'title!: string;') so the compiler recognizes that TypeORM manages property population.

Frequently Asked Questions

How does the converter map SQL column types to TypeScript types and TypeORM decorators?▼

SQL data types are mapped dual-layer: the decorator specifies the database physical type (e.g., @Column({ type: 'varchar', length: 255 })) while the property declaration is assigned the corresponding TypeScript primitive (e.g., string, number, boolean, Date, or object for JSONB).

How are primary keys and autoincrement sequences translated?▼

Columns defined with PRIMARY KEY and AUTO_INCREMENT, SERIAL, or IDENTITY clauses are converted to @PrimaryGeneratedColumn('increment'). UUID primary keys default to @PrimaryGeneratedColumn('uuid'), and non-generated compound primary keys use @PrimaryColumn().

Can I use the generated entities directly in NestJS projects?▼

Yes. The generated code produces standard TypeORM TypeScript classes decorated with @Entity(), @Column(), and relation annotations, which are 100% compatible with @nestjs/typeorm TypeOrmModule.forFeature([Entity]) registration.

Is my SQL DDL schema sent to any external server during conversion?▼

No. The entire parsing and TypeScript entity synthesis pipeline runs 100% client-side inside your browser via local JavaScript abstract syntax tree parsing. Your proprietary schema definitions never leave your device.

Related Tools & Utilities

All Tools →