← Blog

Migrate TypeORM entities to Prisma schema automatically

Moving between TypeORM and Prisma means translating model definitions into a different schema language and workflow.

The migration itself is the problem. A medium-size service with 20–40 TypeORM entity classes means hundreds of fields, custom column types, composite indexes, and enum definitions to translate by hand. One missed @Column({ unique: true }) and you drop a constraint in production.

SchemaForge converts TypeORM entity files to a Prisma schema as a reviewable starting point. Its shared representation preserves tables, columns, types, defaults, indexes, unique constraints, and enums; relationship details still need review before you apply generated output.

Install SchemaForge

# Install from source (PyPI publishing pending)
pip install git+https://github.com/Coding-Dev-Tools/schemaforge.git
Not on public PyPI. A bare pip install schemaforge will fail or install an unrelated package. Use the source-install command above. Requires Python 3.10+.

A typical TypeORM entity

Start with a representative entity. Most teams have something like this:

// src/entities/user.entity.ts
import {
  Entity, PrimaryGeneratedColumn, Column,
  CreateDateColumn, UpdateDateColumn, Index, Unique
} from 'typeorm';

export enum UserRole { ADMIN = 'admin', MEMBER = 'member', VIEWER = 'viewer' }

@Entity('users')
@Index(['email'])
@Unique(['email'])
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ length: 100 })
  name: string;

  @Column({ unique: true, length: 255 })
  email: string;

  @Column({ type: 'enum', enum: UserRole, default: UserRole.MEMBER })
  role: UserRole;

  @Column({ nullable: true })
  avatarUrl: string | null;

  @Column({ default: true })
  isActive: boolean;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;
}

Convert with one command

Single file

schemaforge convert --from typeorm --to prisma \
  --input src/entities/user.entity.ts \
  --output prisma/schema.prisma

Entire entities directory

schemaforge convert --from typeorm --to prisma \
  --input src/entities/ \
  --output prisma/schema.prisma

SchemaForge reads all .ts files in the directory, merges them into a single Prisma schema, and resolves shared enums across entity files.

Output

// prisma/schema.prisma (generated)
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

enum UserRole {
  admin
  member
  viewer
}

model User {
  id        String   @id @default(uuid())
  name      String   @db.VarChar(100)
  email     String   @unique @db.VarChar(255)
  role      UserRole @default(member)
  avatarUrl String?
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@map("users")
  @@index([email])
}

The @map directive preserves the original table name from @Entity('users'), @db.VarChar preserves column-length constraints, and the unique index from both @Unique(['email']) and @Column({ unique: true }) collapses correctly to a single @unique.

Batch convert the whole codebase

If your entities are spread across subdirectories, run a conversion for each service:

# Convert each service's entities separately
for service in users orders billing; do
  schemaforge convert --from typeorm --to prisma \
    --input "services/$service/entities/" \
    --output "services/$service/prisma/schema.prisma"
done

What's preserved and what isn't

TypeORM featureIn SchemaForge output
Columns (@Column) + types + lengths✓ Preserved
Nullability (nullable: true/false)✓ Preserved
Defaults (literals, now(), uuid())✓ Preserved
Primary keys (@PrimaryGeneratedColumn)✓ Preserved
Unique constraints (@Unique, unique: true)✓ Preserved
Indexes (@Index)✓ Preserved
Enums (type: 'enum')✓ Preserved
Table name from @Entity('name')✓ as @@map
Create/Update timestamps✓ as @default(now()) / @updatedAt
Relations (@ManyToOne, @OneToMany, etc.)⚠ Dropped — see note below
Foreign keys / @JoinColumn⚠ Dropped — see note below
Embedded entities⚠ Review after conversion
Relations need review. Foreign-key constraints and ORM relation fields (@ManyToOne, @OneToMany, @ManyToMany) are dropped during conversion. SchemaForge's shared representation preserves tables, columns, types, defaults, indexes, unique constraints, and enums; review and add the relationship details before applying generated output.

The mechanical structural work is automated; relational semantics receive a deliberate review before the generated schema is applied.

Verify with diff

Once you've added relations manually, use SchemaForge's diff command to compare the original TypeORM-derived schema against an updated version:

# Compare two Prisma schema files
schemaforge diff prisma/schema-v1.prisma prisma/schema-v2.prisma

The output shows added, removed, and modified tables, columns, indexes, and constraints — useful for catching regressions during the migration review.

Custom type mappings

TypeORM lets you use raw database types like jsonb, tsvector, or custom Postgres enums. If SchemaForge's defaults don't match what you want in Prisma, supply a mapping file:

# type-map.yaml
jsonb: Json
tsvector: String
citext: String
schemaforge convert --from typeorm --to prisma \
  --input src/entities/ \
  --output prisma/schema.prisma \
  --type-map type-map.yaml

VS Code extension

SchemaForge ships a VS Code extension with live preview: open a TypeORM entity file and see the Prisma output update as you type. Install it from the VS Code Marketplace.

MCP server for AI-assisted migrations

If you use Claude Code, Cursor, or another MCP-compatible editor, SchemaForge can run as an MCP server so an assistant can call its conversion, diff, and check tools directly:

pip install "git+https://github.com/Coding-Dev-Tools/schemaforge.git[mcp]"
schemaforge mcp

The MCP server exposes convert, diff, and check as tools. Generated output remains a starting point: review the missing relationship details before applying it.

Summary

SchemaForge reduces the mechanical column-copying work of a TypeORM → Prisma migration. It supports 11 schema formats and 100 conversion directions; Alembic is generator-only. Use generated output as a starting point, then spend review time on relationship fields, query rewrites, and transaction patterns.

Get SchemaForge on GitHub →

SchemaForge is an open-source CLI by Coding Dev Tools. See also: SchemaForge overview · GitHub