SQL a MikroORM

Generador de Entidades MikroORM TypeScript desde SQL DDL

Convierte definiciones SQL CREATE TABLE en clases de entidad MikroORM con decoradores @Entity, @PrimaryKey, @Property, @Index y relaciones.

Preajustes:
Dialecto SQL:Nombres de Clases:Estilo de Propiedades:
Entrada SQL DDL (CREATE TABLE)
/**
 * 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;
}

Entidades MikroORM7 entidades generadas
Relaciones Mapeadas10 claves foráneas resueltas
Columnas Convertidas58 columnas tipadas

100% Privacidad del Lado del Cliente

Sin envíos al servidor ni conexiones remotas a bases de datos. Todo el procesamiento se realiza en el navegador local.

Decoradores Completos MikroORM v5 y v6

Mapeo preciso de @PrimaryKey (UUID, autoincrementable), @Property, @Index, @Unique, @Enum y marcas de tiempo onCreate/onUpdate.

Relaciones con Seguridad de Tipos y Multi-Dialecto

Detecta claves foráneas para generar @ManyToOne, @OneToMany con Collection<T> y @OneToOne en PostgreSQL, MySQL, SQLite y SQL Server.

Referencia técnica y guía de arquitectura

Guía del Desarrollador del Generador de Entidades MikroORM TypeScript desde SQL DDL — Guía de referencia

Convierte definiciones SQL CREATE TABLE en clases de entidad MikroORM con decoradores @Entity, @PrimaryKey, @Property, @Index y relaciones.

Parámetros clave y controles

Dialecto SQL (SQL Dialect)Enum (PostgreSQL | MySQL | SQLite | MSSQL)

Especifica la sintaxis del motor SQL para interpretar con precisión tipos de datos, secuencias automáticas (SERIAL, AUTO_INCREMENT, IDENTITY) y cláusulas de índices.

Por defecto: PostgreSQL
Estrategia de Nombres de Clases (Class Naming Strategy)Enum (PascalCase Singular | Conservar Nombre de Tabla)

Controla cómo se transforman los nombres de tablas SQL en nombres de clases TypeScript, convirtiendo tablas en plural (ej. 'user_accounts') a identificadores en singular PascalCase ('UserAccount').

Por defecto: PascalCase Singular
Estilo de Propiedades (Property Naming Strategy)Enum (camelCase | Conservar snake_case)

Determina si las columnas de base de datos se adaptan a camelCase idiomático con @Property({ fieldName: 'nombre_columna' }) o si se mantiene el formato original snake_case.

Por defecto: camelCase
Generación de Relaciones (Relation Generation)Enum (Bidireccional (@ManyToOne y @OneToMany) | Solo Claves Foráneas Escalares)

Configura si las restricciones de clave foránea producen relaciones MikroORM completas con Collection<T> o propiedades escalares simples.

Por defecto: Bidireccional (@ManyToOne y @OneToMany)

Consejos profesionales y mejores prácticas

En MikroORM

En MikroORM, las colecciones inversas de @OneToMany y @ManyToMany deben instanciarse siempre como 'new Collection<T>(this)'. Esto evita valores undefined y asegura el correcto funcionamiento de métodos como .init() y .getItems().

Al declarar relaciones entre archivos

Al declarar relaciones entre archivos independientes mediante @ManyToOne(() => Author) y @OneToMany(() => Book, b => b.author), emplea siempre funciones flecha para diferir la resolución de clases y prevenir bloqueos de importación en Node.js.

Al convertir columnas snake_case a

Al convertir columnas snake_case a propiedades camelCase en TypeScript, añade @Property({ fieldName: 'columna_sql' }). Así garantizas compatibilidad absoluta con bases de datos en producción sin causar discrepancias en migraciones.

Errores comunes y solución de problemas

Error de compilación TypeScript: 'Property has no initializer and is not definitely assigned in constructor' (TS2564)

Con strictPropertyInitialization habilitado, añade el operador de aserción '!' a los campos de la entidad (ej. 'name!: string;'). MikroORM hidratará estas propiedades dinámicamente mediante el EntityManager.

El tipo de @Property no se infiere correctamente con emitDecoratorMetadata

Si TypeScript tiene dificultades para emitir metadatos de tipos complejos o genéricos, especifica el tipo explícitamente dentro del decorador, por ejemplo @Property({ type: 'text', nullable: true }) o @Property({ type: 'json' }).

Preguntas frecuentes (FAQ)

¿Cómo traduce el generador las claves primarias SQL a decoradores MikroORM?▼

Las columnas PRIMARY KEY con AUTO_INCREMENT o SERIAL se transforman en @PrimaryKey({ autoincrement: true }). Los identificadores UUID se mapean a @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' }), y las claves primarias compuestas se configuran marcando cada campo clave con @PrimaryKey().

¿Cómo se transforman las claves foráneas en relaciones de entidad?▼

Las cláusulas SQL REFERENCES se convierten en @ManyToOne(() => TargetEntity, { nullable: ... }). Con relaciones bidireccionales activadas, la entidad destino recibe además su correspondiente @OneToMany(() => CurrentEntity, c => c.target) con Collection<CurrentEntity>(this).

¿Es compatible el código generado con MikroORM v5 y v6?▼

Sí. El generador sigue las recomendaciones oficiales actuales de MikroORM, incluyendo importaciones modulares desde '@mikro-orm/core', instanciación de Collection<T> y plantillas de configuración para mikro-orm.config.ts.

¿Mis sentencias SQL o esquemas se transfieren a servidores externos?▼

No. Todo el análisis DDL y la síntesis de clases TypeScript se ejecutan de forma 100% local en tu navegador. Tus esquemas y definiciones de tablas jamás salen de tu equipo.

Herramientas y utilidades relacionadas

Todas las herramientas →
Guía de Desarrollo: Generador de Esquemas Mongoose y Modelos TypeScript desde JSONDesarrollo

Infiere y genera esquemas MongoDB Mongoose, interfaces Document de TypeScript, subdocumentos anidados, marcas de tiempo y exportación de modelos desde JSON.

Abrir herramienta→
Guía para Desarrolladores del Generador de Esquemas de Validación Yup desde JSONDesarrollo

Transforme muestras JSON en esquemas de validación de objetos Yup con seguridad de tipos, yup.string(), yup.number(), yup.array() y reglas requeridas.

Abrir herramienta→
Guía de Desarrollo: Generador de Esquemas de Validación Joi desde JSONDesarrollo

Transforme estructuras de datos JSON en esquemas de validación de Joi con reglas Joi.object(), Joi.string(), Joi.number() y Joi.array().

Abrir herramienta→
Guía para Desarrolladores del Conversor de JSON a Esquema Apache Avro (.avsc)Desarrollo

Convierta cargas útiles JSON en definiciones de esquema Apache Avro (.avsc) para producción con espacios de nombres, tipos primitivos y lógicos, uniones que admiten nulos y reglas de evolución.

Abrir herramienta→
Guía para Desarrolladores: Generador de Esquemas de Validación Zod desde GraphQL SDLDesarrollo

Convierta tipos, consultas y entradas de GraphQL SDL en esquemas de validación Zod en tiempo de ejecución (z.object, z.string, z.array) con soporte exhaustivo de nulabilidad.

Abrir herramienta→
Guía de desarrollo del convertidor de GraphQL SDL a tipos e interfaces TypeScriptDesarrollo

Transforme definiciones de esquemas GraphQL (SDL), tipos, inputs y enums directamente en interfaces TypeScript limpias y sin dependencias.

Abrir herramienta→