TypeORM to ER diagram
ErdDocs draws an ER diagram straight from TypeORM entity files — paste the @Entity classes and see the tables TypeORM builds: snake_cased table names, the key columns your relations own, and the junction table @JoinTable creates. No migration to generate, no SQL to export, no DataSource to load; the entities are parsed in your browser and never uploaded.
Six entities above, seven tables below. Paste your own file over the example.
Snake_case tables, camelCase columns
TypeORM’s default naming strategy is asymmetric, and it catches people the first time they open a query console: tableName is snakeCase(className), so class RentalAgreement becomes rental_agreement — but columnName keeps the property exactly as written, so dailyRate stays dailyRate. One half converted, the other not.
That single inconsistency is why a shelf of SnakeNamingStrategy packages exists on npm. The diagram above follows the default, because the default is what runs until a DataSource says otherwise — and if yours does, the names it produces are the ones you already see in your database.
Ownership decides what exists
A relation in TypeORM is written from both ends, and only one end is a column. The diagram follows the same rule the migration does:
- @ManyToOne owns the key. It becomes a column named
<property>Id—vehiclebecomesvehicleId— unless@JoinColumnrenames it, asreturned_to_idis renamed above. - @OneToMany owns nothing. It is the inverse view of a key that lives on the other table, so it produces no column at all. A diagram that draws it produces a table with columns your database has never had.
- @OneToOne needs @JoinColumn. Whichever side carries it gets the key and a unique constraint; the other side gets nothing. Above, the customer holds the license, not the other way around.
- @ManyToMany needs @JoinTable — and creates a whole table:
vehicle_features_feature, fromsnake_case(table_property_table), with camelCase key columns on both sides.
Without loading a DataSource
ErdDocs applies TypeORM’s own default naming and ownership rules to the file in front of it, so the tables appear without the project compiling or connecting. The packages that answer this question — typeorm-erd, typeorm-uml, ERDIA — load your DataSource and ask TypeORM itself for the metadata, which is the most accurate possible route and the right tool inside a project that already runs. The cost is that it has to run: a review copy, a repository you were handed, an entity file in a pull request, or a laptop without the database credentials all fall outside it.
ErdDocs asks for neither a build nor a database connection, and what comes back is not only a picture: the same entities produce a printable data dictionary, Mermaid for a README, and CREATE TABLE statements if what you needed was the SQL.
FAQ
Do I need to build or run the project?
No. ErdDocs reads the entity file as text you paste, so a file with a missing import, a half-finished refactor, or a class copied out of a pull request still draws. The CLI tools for this job — typeorm-erd, typeorm-uml, ERDIA — load your DataSource instead, which means the project must compile and often connect to a database before a diagram exists.
Why is my table snake_case but my columns are not?
Because that is what TypeORM’s default naming strategy does, and it surprises nearly everyone. tableName is snakeCase(className), so class UserProfile becomes user_profile — but columnName keeps the property as written, so firstName stays firstName. That asymmetry is why so many projects install a SnakeNamingStrategy package. The diagram follows the default, which is what runs unless your DataSource says otherwise.
Which side of a relation makes the column?
The owning side, exactly as in TypeORM. @ManyToOne makes the column and names it <property>Id; @OneToMany is the inverse view and makes nothing at all. @OneToOne makes a column only where @JoinColumn is, and @ManyToMany makes the junction table only where @JoinTable is. Drawing both sides would double every relation and invent columns your migration never writes.
What is the junction table called?
snake_case(<owning table>_<property>_<other table>) — so a Vehicle with a features relation to Feature gives vehicle_features_feature, with camelCase key columns. @JoinTable({ name: "..." }) overrides it, and then that name is used instead.
Is my code uploaded anywhere?
No. The parser is JavaScript running in your browser, so the entities are read on your machine and never sent to a server. There is no account, and closing the tab is the whole cleanup.
Is it free?
Drawing and exporting the picture are free, no account, for schemas up to 25 tables. $9 once lifts the limit and unlocks the data dictionary and the SQL export, which turns the same entities into CREATE TABLE statements.
Related
- Sequelize models to ER diagram — the other JavaScript ORM, same paste-a-file approach.
- Django models to ER diagram — the same job in Python, without Graphviz.
- Prisma schema to ER diagram — schema-first, with its own implicit join tables.
- Data dictionary generator — the entities as a printable document, comments included.
- Example schemas — eleven domains, each teaching one modeling pattern.
- SQL to ER diagram — the tool with every format it reads.