SQL → Sequelize TS
Génération de code de base de données et ORM

Générateur de Modèles Sequelize TypeScript depuis SQL DDL

Guide technique complet pour convertir les instructions SQL CREATE TABLE DDL en modèles typés Sequelize TypeScript, définitions DataTypes, attributs CreationOptional et déclarations Model.init.

Confidentialité 100% côté client
Zéro transmission au serveur
Presets :
Options du compilateur SQL et mappage de schéma
postgres•Model.init
PostgreSQL5 tables
Entrée DDL SQL CREATE TABLEPostgreSQL
import { DataTypes, Model, Optional, Sequelize } from 'sequelize';

// ============================================================================
// Sequelize TypeScript Models Generated by ToolsAA
// Dialect: POSTGRES | Syntax: Model.init
// ============================================================================

UserAttributes {
  id?: string;
  email: string;
  fullName?: string | null;
  role?: 'CUSTOMER' | 'ADMIN' | 'VENDOR';
  isActive?: boolean;
  metadata?: Record<string, any> | null;
  createdAt?: Date;
  updatedAt?: Date;
}

UserCreationAttributes extends Optional<UserAttributes, 'id' | 'fullName' | 'role' | 'isActive' | 'metadata' | 'createdAt' | 'updatedAt'> {}

export class User extends Model<UserAttributes, UserCreationAttributes> implements UserAttributes {
  public id!: string;
  public email!: string;
  public fullName!: string | null;
  public role!: 'CUSTOMER' | 'ADMIN' | 'VENDOR';
  public isActive!: boolean;
  public metadata!: Record<string, any> | null;
  public readonly createdAt!: Date;
  public readonly updatedAt!: Date;
}

initUser(sequelize: Sequelize): typeof User {
  User.init(
    {
      id: {
        type: DataTypes.UUID,
        primaryKey: true,
        allowNull: false,
        defaultValue: DataTypes.UUIDV4,
      },
      email: {
        type: DataTypes.STRING(255),
        allowNull: false,
        unique: true,
      },
      fullName: {
        type: DataTypes.STRING(120),
        allowNull: true,
        field: 'full_name',
      },
      role: {
        type: DataTypes.ENUM('CUSTOMER', 'ADMIN', 'VENDOR'),
        allowNull: false,
        defaultValue: 'CUSTOMER',
      },
      isActive: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: true,
        field: 'is_active',
      },
      metadata: {
        type: DataTypes.JSONB,
        allowNull: true,
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'created_at',
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'updated_at',
      },
    },
    {
      sequelize,
      tableName: 'users',
      modelName: 'User',
      timestamps: true,
      underscored: true,
    }
  );
  return User;
}

UserProfileAttributes {
  id?: string;
  userId: string;
  avatarUrl?: string | null;
  phone?: string | null;
  shippingAddress?: string | null;
  taxIdentifier?: string | null;
}

UserProfileCreationAttributes extends Optional<UserProfileAttributes, 'id' | 'avatarUrl' | 'phone' | 'shippingAddress' | 'taxIdentifier'> {}

export class UserProfile extends Model<UserProfileAttributes, UserProfileCreationAttributes> implements UserProfileAttributes {
  public id!: string;
  public userId!: string;
  public avatarUrl!: string | null;
  public phone!: string | null;
  public shippingAddress!: string | null;
  public taxIdentifier!: string | null;

  // Association Mixin Placeholders
  // public getUser!: BelongsToGetAssociationMixin<User>;
}

initUserProfile(sequelize: Sequelize): typeof UserProfile {
  UserProfile.init(
    {
      id: {
        type: DataTypes.UUID,
        primaryKey: true,
        allowNull: false,
        defaultValue: DataTypes.UUIDV4,
      },
      userId: {
        type: DataTypes.UUID,
        allowNull: false,
        unique: true,
        field: 'user_id',
        references: {
          model: 'users',
          key: 'id',
        },
        onDelete: 'CASCADE',
      },
      avatarUrl: {
        type: DataTypes.STRING(500),
        allowNull: true,
        field: 'avatar_url',
      },
      phone: {
        type: DataTypes.STRING(30),
        allowNull: true,
      },
      shippingAddress: {
        type: DataTypes.TEXT,
        allowNull: true,
        field: 'shipping_address',
      },
      taxIdentifier: {
        type: DataTypes.STRING(50),
        allowNull: true,
        field: 'tax_identifier',
      },
    },
    {
      sequelize,
      tableName: 'user_profiles',
      modelName: 'UserProfile',
      timestamps: true,
      underscored: true,
    }
  );
  return UserProfile;
}

ProductAttributes {
  id?: number;
  sku: string;
  title: string;
  description?: string | null;
  price?: number;
  inventory?: number;
  isPublished?: boolean;
  createdAt?: Date;
}

ProductCreationAttributes extends Optional<ProductAttributes, 'id' | 'description' | 'price' | 'inventory' | 'isPublished' | 'createdAt'> {}

export class Product extends Model<ProductAttributes, ProductCreationAttributes> implements ProductAttributes {
  public id!: number;
  public sku!: string;
  public title!: string;
  public description!: string | null;
  public price!: number;
  public inventory!: number;
  public isPublished!: boolean;
  public readonly createdAt!: Date;
}

initProduct(sequelize: Sequelize): typeof Product {
  Product.init(
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
      },
      sku: {
        type: DataTypes.STRING(64),
        allowNull: false,
        unique: true,
      },
      title: {
        type: DataTypes.STRING(200),
        allowNull: false,
      },
      description: {
        type: DataTypes.TEXT,
        allowNull: true,
      },
      price: {
        type: DataTypes.DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.00,
      },
      inventory: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0,
      },
      isPublished: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: true,
        field: 'is_published',
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'created_at',
      },
    },
    {
      sequelize,
      tableName: 'products',
      modelName: 'Product',
      timestamps: true,
      underscored: true,
      indexes: [
        {
          name: 'idx_products_sku',
          fields: ['sku'],
        },
      ],
    }
  );
  return Product;
}

OrderAttributes {
  id?: string;
  customerId: string;
  orderNumber: string;
  status?: 'PENDING' | 'PAID' | 'PROCESSING' | 'SHIPPED' | 'DELIVERED' | 'CANCELLED';
  totalAmount?: number;
  notes?: string | null;
  createdAt?: Date;
}

OrderCreationAttributes extends Optional<OrderAttributes, 'id' | 'status' | 'totalAmount' | 'notes' | 'createdAt'> {}

export class Order extends Model<OrderAttributes, OrderCreationAttributes> implements OrderAttributes {
  public id!: string;
  public customerId!: string;
  public orderNumber!: string;
  public status!: 'PENDING' | 'PAID' | 'PROCESSING' | 'SHIPPED' | 'DELIVERED' | 'CANCELLED';
  public totalAmount!: number;
  public notes!: string | null;
  public readonly createdAt!: Date;

  // Association Mixin Placeholders
  // public getUser!: BelongsToGetAssociationMixin<User>;
}

initOrder(sequelize: Sequelize): typeof Order {
  Order.init(
    {
      id: {
        type: DataTypes.UUID,
        primaryKey: true,
        allowNull: false,
        defaultValue: DataTypes.UUIDV4,
      },
      customerId: {
        type: DataTypes.UUID,
        allowNull: false,
        field: 'customer_id',
        references: {
          model: 'users',
          key: 'id',
        },
        onDelete: 'RESTRICT',
      },
      orderNumber: {
        type: DataTypes.STRING(64),
        allowNull: false,
        unique: true,
        field: 'order_number',
      },
      status: {
        type: DataTypes.ENUM('PENDING', 'PAID', 'PROCESSING', 'SHIPPED', 'DELIVERED', 'CANCELLED'),
        allowNull: false,
        defaultValue: 'PENDING',
      },
      totalAmount: {
        type: DataTypes.DECIMAL(12, 2),
        allowNull: false,
        defaultValue: 0.00,
        field: 'total_amount',
      },
      notes: {
        type: DataTypes.TEXT,
        allowNull: true,
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'created_at',
      },
    },
    {
      sequelize,
      tableName: 'orders',
      modelName: 'Order',
      timestamps: true,
      underscored: true,
      indexes: [
        {
          name: 'idx_orders_customer',
          fields: ['customer_id'],
        },
      ],
    }
  );
  return Order;
}

OrderItemAttributes {
  id?: number;
  orderId: string;
  productId: number;
  quantity?: number;
  unitPrice: number;
}

OrderItemCreationAttributes extends Optional<OrderItemAttributes, 'id' | 'quantity'> {}

export class OrderItem extends Model<OrderItemAttributes, OrderItemCreationAttributes> implements OrderItemAttributes {
  public id!: number;
  public orderId!: string;
  public productId!: number;
  public quantity!: number;
  public unitPrice!: number;

  // Association Mixin Placeholders
  // public getOrder!: BelongsToGetAssociationMixin<Order>;
  // public getProduct!: BelongsToGetAssociationMixin<Product>;
}

initOrderItem(sequelize: Sequelize): typeof OrderItem {
  OrderItem.init(
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
      },
      orderId: {
        type: DataTypes.UUID,
        allowNull: false,
        field: 'order_id',
        references: {
          model: 'orders',
          key: 'id',
        },
        onDelete: 'CASCADE',
      },
      productId: {
        type: DataTypes.INTEGER,
        allowNull: false,
        field: 'product_id',
        references: {
          model: 'products',
          key: 'id',
        },
        onDelete: 'RESTRICT',
      },
      quantity: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 1,
      },
      unitPrice: {
        type: DataTypes.DECIMAL(10, 2),
        allowNull: false,
        field: 'unit_price',
      },
    },
    {
      sequelize,
      tableName: 'order_items',
      modelName: 'OrderItem',
      timestamps: true,
      underscored: true,
    }
  );
  return OrderItem;
}

// ============================================================================
// Unified Model Registry & Associations Initializer
// ============================================================================

DatabaseModels {
  User: typeof User;
  UserProfile: typeof UserProfile;
  Product: typeof Product;
  Order: typeof Order;
  OrderItem: typeof OrderItem;
}

initModels(sequelize: Sequelize): DatabaseModels {
  initUser(sequelize);
  initUserProfile(sequelize);
  initProduct(sequelize);
  initOrder(sequelize);
  initOrderItem(sequelize);

  // Setup Relationships
  UserProfile.belongsTo(User, { foreignKey: 'userId', as: 'user' });
  User.hasMany(UserProfile, { foreignKey: 'userId', as: 'userProfiles' });
  Order.belongsTo(User, { foreignKey: 'customerId', as: 'user' });
  User.hasMany(Order, { foreignKey: 'customerId', as: 'orders' });
  OrderItem.belongsTo(Order, { foreignKey: 'orderId', as: 'order' });
  Order.hasMany(OrderItem, { foreignKey: 'orderId', as: 'orderItems' });
  OrderItem.belongsTo(Product, { foreignKey: 'productId', as: 'product' });
  Product.hasMany(OrderItem, { foreignKey: 'productId', as: 'orderItems' });

  return {
    User,
    UserProfile,
    Product,
    Order,
    OrderItem,
  };
}

Tables et architecture détectées (5)

usersUser
Colonnes8
Clé primaire :id
Clés étrangères :0
user_profilesUserProfile
Colonnes6
Clé primaire :id
Clés étrangères :1
productsProduct
Colonnes8
Clé primaire :id
Clés étrangères :0
ordersOrder
Colonnes7
Clé primaire :id
Clés étrangères :1
order_itemsOrderItem
Colonnes5
Clé primaire :id
Clés étrangères :2

Confidentialité Locale Zéro Téléversement

L'analyse complète du DDL SQL et la génération du code des modèles Sequelize s'effectuent à 100% dans votre navigateur. Vos structures de données ne quittent jamais votre machine.

Double Architecture TypeScript

Générez des déclarations Model.init standard Sequelize v6/v7 avec interfaces complètes ou utilisez les décorateurs de classe modernes de sequelize-typescript avec typage strict.

Associations & Migrations Complètes

Détection automatique des relations 1:1, 1:N et N:M pour générer les déclarations hasMany, belongsTo ainsi que les scripts de migration prêts pour Sequelize CLI.

Référence technique et guide d'architecture

Guide Développeur : Générateur de Modèles Sequelize TypeScript depuis SQL DDL — Guide de référence

Guide technique complet pour convertir les instructions SQL CREATE TABLE DDL en modèles typés Sequelize TypeScript, définitions DataTypes, attributs CreationOptional et déclarations Model.init.

Paramètres clés et contrôles

ddlInputstring

Instructions SQL CREATE TABLE brutes contenant la définition des colonnes, clés primaires, contraintes de nullité, valeurs par défaut et clés étrangères.

Par défaut : CREATE TABLE users (...)
dialectenum ('postgres' | 'mysql' | 'sqlite' | 'mssql')

Dialecte de base de données SQL cible déterminant les DataTypes Sequelize spécifiques (tels que JSONB, UUID, ENUM ou INET).

Par défaut : postgres
tsSyntaxenum ('v6-infer' | 'decorators' | 'interface')

Style de syntaxe TypeScript du modèle : Sequelize v6 InferAttributes/InferCreationAttributes, décorateurs sequelize-typescript ou interfaces typées classiques.

Par défaut : v6-infer
camelCaseboolean

Convertit automatiquement les noms de colonnes SQL en snake_case vers des attributs TypeScript en camelCase avec mappage field explicite.

Par défaut : true

Conseils de pro et bonnes practices

Avec Sequelize v6+

Avec Sequelize v6+, déclarez les clés primaires auto-incrémentées, colonnes avec DEFAULT et horodatages avec `declare id: CreationOptional<number>;`. Ainsi, la méthode `Model.create()` n'exige pas ces champs à la création tout en assurant leur typage strict sur les instances récupérées.

Activez la conversion camelCase pour

Activez la conversion camelCase pour manipuler des attributs clairs comme createdAt ou userId en TypeScript, pendant que Sequelize assure la correspondance avec le schéma SQL via l'option `field: 'created_at'`.

Les contraintes SQL FOREIGN KEY

Les contraintes SQL FOREIGN KEY génèrent directement les champs de clés étrangères dans Sequelize. Associez-les aux interfaces exportées pour définir des relations hasMany et belongsTo sans conflits de dépendances circulaires.

Pièges courants et dépannage

Erreur TypeScript : La propriété 'id' n'a pas d'initialiseur et n'est pas définitivement assignée dans le constructeur (TS2564)

Ajoutez le mot-clé `declare` devant les attributs de classe (ex. : `declare id: CreationOptional<number>;`) lorsque TypeScript est configuré avec l'option `useDefineForClassFields: true`.

Erreur de DataType non supporté lors du changement de dialecte (ex. : DataTypes.JSONB avec MySQL)

Sélectionnez le dialecte SQL cible approprié avant de lancer la conversion. Le générateur convertira automatiquement les types spécifiques comme JSONB ou ARRAY vers des équivalents universels comme `DataTypes.JSON` ou `DataTypes.TEXT`.

Foire aux questions (FAQ)

Comment les types SQL sont-ils convertis en Sequelize DataTypes ?▼

Les types SQL courants (VARCHAR, INT, BIGINT, TIMESTAMP, BOOLEAN, TEXT, DECIMAL, JSON) sont convertis vers les Sequelize DataTypes équivalents (DataTypes.STRING, DataTypes.INTEGER, DataTypes.BIGINT, DataTypes.DATE, DataTypes.BOOLEAN, etc.). Les types propres à PostgreSQL comme UUID ou JSONB sont conservés lorsque le dialecte correspondant est sélectionné.

Le générateur prend-il en charge Sequelize v6 InferAttributes et sequelize-typescript ?▼

Oui. Vous pouvez choisir entre la syntaxe standard Sequelize v6 (`Model<InferAttributes<T>, InferCreationAttributes<T>>` avec `Model.init`) et l'approche par décorateurs de sequelize-typescript (`@Table`, `@Column`, `@PrimaryKey`, `@DataType`).

Comment les contraintes NOT NULL et valeurs DEFAULT sont-elles traitées ?▼

Les colonnes avec NOT NULL reçoivent `allowNull: false`. Les clauses DEFAULT sont converties en `defaultValue: ...` et annotées avec `CreationOptional<T>` en TypeScript, ce qui permet de les omettre lors des créations d'enregistrements.

Mon schéma SQL ou DDL est-il transmis à un serveur externe ?▼

Non. L'analyse syntaxique du SQL, le découpage en lexèmes et la génération du code TypeScript s'effectuent exclusivement en local dans votre navigateur via des Web Workers. Aucune donnée n'est envoyée ni enregistrée sur un serveur.

Outils et utilitaires connexes

Tous les outils →