Cursor generates TypeORM entities with camelCase column names that do not match your database's snake_case conventions because it ignores your NamingStrategy configuration. By referencing your ormconfig with @file, adding TypeORM rules to .cursorrules, and including your naming strategy in the entity generation prompt, you get entities that match your actual database schema.
Why Cursor ignores ORM naming conventions
TypeORM naming strategies (like SnakeNamingStrategy) transform entity property names to database column names automatically. Cursor does not read your ormconfig or data source configuration, so it generates entities with default camelCase naming that fails at runtime. This tutorial fixes the disconnect.
Prerequisites
- Cursor installed with a NestJS + TypeORM project
- A naming strategy configured (e.g., typeorm-naming-strategies)
- Existing database with established naming conventions
- Familiarity with Cursor Chat (Cmd+L) and Cmd+K
Step-by-step guide
Add TypeORM rules to .cursor/rules
Add TypeORM rules to .cursor/rules
Create rules that specify your naming convention and TypeORM patterns. This ensures Cursor generates entities that match your database schema.
1---2description: TypeORM entity conventions3globs: "src/**/*.entity.ts"4alwaysApply: true5---67## TypeORM Naming Rules8- Database uses snake_case column names9- Entity properties use camelCase10- SnakeNamingStrategy is configured in data source11- Do NOT add explicit @Column({ name: 'snake_case' }) — the strategy handles it12- Use @CreateDateColumn() for created_at (auto-mapped to snake_case)13- Use @UpdateDateColumn() for updated_at (auto-mapped to snake_case)14- Use @PrimaryGeneratedColumn('uuid') for IDs15- Join columns: @JoinColumn() without explicit name (strategy handles it)16- Table names: @Entity('table_name') with explicit snake_case name1718## NestJS Patterns19- Entities in src/modules/{module}/entities/20- DTOs in src/modules/{module}/dto/21- Repositories use @InjectRepository(Entity)Expected result: Cursor generates TypeORM entities that work with your SnakeNamingStrategy.
Reference your data source config in prompts
Reference your data source config in prompts
When generating entities, reference your TypeORM data source configuration so Cursor sees the naming strategy and connection settings.
1// Cursor Chat prompt (Cmd+L):2// @src/config/data-source.ts @.cursor/rules/typeorm.mdc3// Generate a Product entity for the 'products' table with:4// - id (UUID primary key)5// - name (string, not null)6// - description (text, nullable)7// - price (decimal 10,2)8// - stockQuantity (integer, default 0)9// - isActive (boolean, default true)10// - categoryId (UUID foreign key to categories)11// - createdAt, updatedAt timestamps12//13// Our SnakeNamingStrategy maps camelCase properties to14// snake_case columns automatically.Expected result: An entity with camelCase properties that the naming strategy maps correctly to snake_case columns.
Generate the entity with correct decorators
Generate the entity with correct decorators
The generated entity should use camelCase properties without explicit column name overrides. The naming strategy handles the mapping.
1import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';2import { Category } from './category.entity';34@Entity('products')5export class Product {6 @PrimaryGeneratedColumn('uuid')7 id: string;89 @Column({ type: 'varchar', length: 255 })10 name: string;1112 @Column({ type: 'text', nullable: true })13 description: string | null;1415 @Column({ type: 'decimal', precision: 10, scale: 2 })16 price: number;1718 @Column({ type: 'int', default: 0 })19 stockQuantity: number;2021 @Column({ type: 'boolean', default: true })22 isActive: boolean;2324 @ManyToOne(() => Category)25 @JoinColumn()26 category: Category;2728 @Column({ type: 'uuid' })29 categoryId: string;3031 @CreateDateColumn()32 createdAt: Date;3334 @UpdateDateColumn()35 updatedAt: Date;36}Pro tip: Do NOT add explicit column names like @Column({ name: 'stock_quantity' }). The SnakeNamingStrategy handles this automatically. Adding explicit names would double-transform the name.
Expected result: An entity with camelCase properties and no explicit column name overrides.
Audit existing entities for naming mismatches
Audit existing entities for naming mismatches
Check your existing entities for naming issues that may have been introduced by Cursor without the rules in place.
1// Cursor Chat prompt (Cmd+L, Ask mode):2// @src/ Find all TypeORM entities and check for:3// 1. Explicit @Column({ name: '...' }) that conflict with4// the SnakeNamingStrategy (double transformation)5// 2. Properties that don't follow camelCase convention6// 3. @Entity() without explicit table name7// 4. Missing @CreateDateColumn or @UpdateDateColumn8// 5. @JoinColumn with explicit name that conflicts with strategyExpected result: A report of naming mismatches and conflicts in existing entities.
Generate matching DTOs and migrations
Generate matching DTOs and migrations
Ask Cursor to generate DTOs and a migration for the entity, ensuring consistent naming throughout the module.
1// Cursor Chat prompt (Cmd+L):2// @src/modules/product/entities/product.entity.ts3// Generate:4// 1. CreateProductDto with class-validator decorators5// 2. UpdateProductDto (Partial of Create)6// 3. A TypeORM migration that creates the products table7// with snake_case column names matching our entity8// (stock_quantity, is_active, category_id, created_at, updated_at)Expected result: DTOs and migration that are consistent with the entity and naming strategy.
Complete working example
1import {2 Entity,3 Column,4 PrimaryGeneratedColumn,5 CreateDateColumn,6 UpdateDateColumn,7 ManyToOne,8 JoinColumn,9 Index,10} from 'typeorm';11import { Category } from '../../category/entities/category.entity';1213@Entity('products')14export class Product {15 @PrimaryGeneratedColumn('uuid')16 id: string;1718 @Column({ type: 'varchar', length: 255 })19 @Index()20 name: string;2122 @Column({ type: 'text', nullable: true })23 description: string | null;2425 @Column({ type: 'decimal', precision: 10, scale: 2 })26 price: number;2728 @Column({ type: 'int', default: 0 })29 stockQuantity: number;3031 @Column({ type: 'boolean', default: true })32 isActive: boolean;3334 @ManyToOne(() => Category, { onDelete: 'SET NULL', nullable: true })35 @JoinColumn()36 category: Category | null;3738 @Column({ type: 'uuid', nullable: true })39 @Index()40 categoryId: string | null;4142 @CreateDateColumn()43 createdAt: Date;4445 @UpdateDateColumn()46 updatedAt: Date;47}4849// With SnakeNamingStrategy, columns in database:50// id, name, description, price, stock_quantity,51// is_active, category_id, created_at, updated_atCommon mistakes
Why it's a problem: Adding explicit @Column({ name: 'snake_case' }) with a naming strategy
How to avoid: Add 'Do NOT add explicit column names, the naming strategy handles it' to .cursorrules.
Why it's a problem: Cursor generating entities without @Entity('table_name')
How to avoid: Always specify the table name: @Entity('products'). Add this requirement to your TypeORM rules.
Why it's a problem: Using @Column() without type specification
How to avoid: Require explicit types: @Column({ type: 'varchar', length: 255 }). Add this to your .cursorrules.
Best practices
- Reference your data source config with @file when generating entities
- Add TypeORM rules specifying naming conventions to .cursor/rules
- Use camelCase properties without explicit column names when using a naming strategy
- Always specify @Entity('table_name') with explicit snake_case table name
- Include explicit column types in @Column decorators
- Generate DTOs and migrations alongside entities for consistency
- Audit existing entities periodically for naming strategy conflicts
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
Create a TypeORM entity for a 'products' table in a NestJS project that uses SnakeNamingStrategy. Properties should be camelCase (stockQuantity, isActive, categoryId) without explicit column name overrides. Include: UUID primary key, varchar name, text description, decimal price, int stockQuantity, boolean isActive, UUID categoryId FK, timestamps. Add @Index where appropriate.
In Cursor Chat (Cmd+L): @src/config/data-source.ts @.cursor/rules/typeorm.mdc Generate a Product entity for the products table. Use camelCase properties — our SnakeNamingStrategy maps to snake_case automatically. Do NOT add explicit column names. Include UUID id, name, description, price, stockQuantity, isActive, categoryId FK, timestamps.
Frequently asked questions
What is the SnakeNamingStrategy?
It is a TypeORM naming strategy from the typeorm-naming-strategies package that automatically converts camelCase entity properties to snake_case database columns. For example, stockQuantity becomes stock_quantity.
Can Cursor generate TypeORM migrations?
Yes. Reference the entity and ask Cursor to generate a migration. However, for production, always use TypeORM's CLI: npx typeorm migration:generate to ensure accuracy.
How do I handle custom column names that differ from the naming convention?
For exceptions, use @Column({ name: 'custom_name' }). Add a comment explaining why the override exists. This should be rare with a proper naming strategy.
Does this apply to Prisma or Drizzle?
Each ORM has its own naming conventions. Create separate .cursor/rules for your ORM. Prisma uses @map for column names, Drizzle uses explicit column definitions.
Will Cursor respect the naming strategy in query builder code?
Not automatically. When generating QueryBuilder code, Cursor should use camelCase property names, not snake_case column names. The naming strategy translates at the ORM level.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation