TypeORM: a pnpm monorepo where the install step skips six native drivers
TypeScript & JavaScript ORM for Node.js — supports PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, and more.
At a glance
- What is it?
- TypeORM is a TypeScript and JavaScript ORM that runs on Node.js through browsers and mobile shells, supporting Data Mapper and Active Record styles over Spanner, SQL Server, MySQL/MariaDB, MongoDB, Oracle, Postgres, SAP HANA, and SQLite. Its root package.json shows a pnpm workspace that deliberately ignores native build scripts for oracledb, libpq, ssh2, and three more packages, and it publishes no install command at all.
- Who is it for?
- TypeORM fits teams that want one API across many relational databases plus MongoDB, and that will accept choosing their own pattern per entity rather than having it chosen for them. It does not fit a project that needs the choice made once by a framework, or that expects native driver compilation to happen at install.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The same entity, two call styles, decided by one extends clause
The Data Mapper version is a plain class. Every operation goes through a repository obtained from a data source:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
age: number
}The Active Record version adds `BaseEntity` to the import list and puts it on the extends clause, and that single change rewrites the call sites: `user.save()` replaces a repository save, `User.find()` and `User.findOneBy()` become statics on the class, and `timber.remove()` replaces the repository call. The project supports both patterns in the same application, which is unusual among JavaScript ORMs, and the cost of that flexibility is that the accessor style is a property of the entity, not of a setting you can flip later without touching call sites.
The root README ships no install command, only fifteen sample repositories
Read the entry point looking for a `npm install` line and there is none. What the project offers instead is a directory of runnable examples, each a separate repository: TypeScript, JavaScript, JavaScript with Babel, TypeScript with SystemJS in the browser, TypeScript with React in the browser, Express, Koa, MongoDB, Cordova, Ionic, React Native, Nativescript-Vue, Nativescript-Angular, and Electron in both JavaScript and TypeScript. The consequence is that the fastest path to a working setup is to clone the example that matches your stack, not to read the main repository. This is also where a framework user finds out what is not covered: no NestJS example appears in that list, so integration details for a specific framework are not answered by this repository.
The pnpm config skips native builds for oracledb, libpq, and four others
The root package.json is where the install-time behavior lives, and it is explicit about what does not get built. One package is allowed to compile, and six are told not to. Verbatim from the pnpm block in the root package.json:
"onlyBuiltDependencies": [
"better-sqlite3"
],
"ignoredBuiltDependencies": [
"@sap/hana-client",
"cpu-features",
"libpq",
"oracledb",
"protobufjs",
"ssh2"
]So `better-sqlite3` is the only native module whose install script runs, while the Oracle, Postgres, SAP HANA, and SSH client packages are installed with their build steps suppressed. If your application connects to one of those databases, `npm install` completing successfully tells you nothing about whether the driver can actually load, and the failure arrives later at connection time. The repository does not document in the root README how those binaries are supposed to be produced, so that step is something you have to work out against the driver page for your database.
Node 20.19 is the floor and a wrong pnpm version is a hard error
Two separate version gates apply to anyone working inside the repository. The first is the engines field, a three-way range:
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24.11.0"
},The second is devEngines, which pins the package manager itself:
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": "^10.34.5",
"onFail": "error"
}
},That `onFail` setting turns a package manager mismatch into a hard stop instead of a warning, and pnpm 10.34.5 is the version the lockfile was resolved with. Contributors therefore face a stricter environment than library consumers, and the practical effect on a team is that CI for this repository is not the same setup as CI for an application that depends on the published package. Note also that the root package is private and named typeorm-monorepo, so nothing at the root is what your application installs.
docker-compose maps mysql-5 and mysql-9 to the same host port
The compose file exists to test the library against many engines at once, and its port map is worth reading as documentation of that intent. The mysql-5 service uses image `mysql:5.7.44` and the mysql-9 service uses `mysql:26.7.0`, and both publish `3306:3306`. The mariadb-10 service on `mariadb:10.11.19` and mariadb-12 on `mariadb:12.3.3` both publish `3307:3306`. Postgres is handled differently, with a purpose-built image per major version, for example `ghcr.io/typeorm/docker:postgres-14.22-postgis-3.6.2-pgvector-0.8.2` and the same shape for postgres-17, each with a comment noting that PostGIS is the only extension bundled and that more calls for your own image. Credentials are checked in as plain literals, database `typeorm`, user `username`, password `password`. Two services on one host port cannot run at the same time, so this file is a version matrix to start one entry at a time, never a compose stack to bring up wholesale.
Version 1.1.0 and 0.3.31 shipped seventeen minutes apart
The release history shows two live lines. Version 1.1.0 is dated 2026-07-13T19:07:27Z, 0.3.31 is dated 2026-07-13T19:24:24Z, and 1.1.1 followed on 2026-09-01. The two different major lines shipped on the same afternoon, seventeen minutes apart, which means the 0.x line was still receiving patches after the 1.x line was out. The root package.json tracks the 1.x number in its own version field even though the package is private, so the monorepo version and the published package version are not the same thing to watch. There is no upgrade guide, migration note, or breaking change list in the repository root, so a team moving between lines has to compare changelog entries rather than follow a documented procedure.
Every script routes through pnpm --filter typeorm
Nothing in the root scripts block runs a tool directly against the whole workspace. Each one delegates to the single package named typeorm:
pnpm --filter typeorm run compile
pnpm --filter typeorm run package
pnpm --filter typeorm run test:fastTwo exceptions are worth noting. Linting is recursive instead of filtered, `pnpm -r run lint`, so every workspace package is linted rather than the library alone. Formatting is the one command that targets the whole tree, and it comes in a write form and a check form, `prettier --cache --write .` and `prettier --check .`, where the check form is what continuous integration should run. There is also a packaging guard with no build step at all:
node scripts/check-publishable-manifests.mjsrun through the `check:manifests` script, which is the project's answer to shipping a broken package manifest from a workspace root.
A monorepo where docs, playground, and pull request bots live beside the source
The repository root is a workspace, not the library. pnpm-workspace.yaml and pnpm-lock.yaml sit at the top with a packages/ directory, and a root package that is private and self-described as the workspace root for the TypeORM repository. Alongside the source are the operational directories a contributor actually uses: docs/ for the documentation site with its own `docs:dev` script, playground/ for experiments, docker/ plus docker-compose.yml for the engine matrix, scripts/ for repository automation, and resources/ for the logo assets the README pulls in. Governance and automation files take up the rest, with .husky/ and .lintstagedrc.json for commit hooks, .prettierrc.js and .prettierignore for formatting, a pr_compliance_checklist.yaml and .pr_agent.toml for pull request review, and CONTRIBUTING.md, DEVELOPER.md, CHANGELOG.md, and SECURITY.md. The last push landed on 2026-09-21, so the work here is current, but a reader looking for a single package manifest will not find one at the root.
Editorial conclusion
TypeORM fits teams that want one API across many relational databases plus MongoDB, and that will accept choosing their own pattern per entity rather than having it chosen for them. It does not fit a project that needs the choice made once by a framework, or that expects native driver compilation to happen at install. Before adopting it, check the driver page for your exact database under docs/docs/drivers, confirm your Node version satisfies the engines field, and read how the ignored native builds for your driver are supposed to be compiled, because the repository does not answer that in the root README.
Frequently asked questions
What is TypeORM?
An ORM for Node.js, the browser, Cordova, Ionic, React Native, NativeScript, Expo, and Electron, usable from TypeScript and JavaScript (ES2023). It supports both Data Mapper and Active Record patterns, and covers Google Spanner, SQL Server, MySQL/MariaDB, MongoDB, Oracle, Postgres, SAP HANA, and SQLite.
Is TypeORM available on NPM?
The README links straight to the npm package page for typeorm, and the badges at the top of the file point there. The repository itself is a private pnpm workspace named typeorm-monorepo, with pnpm-workspace.yaml and a packages/ directory, so the root you clone is not what gets installed.
how to use transaction in typeorm
Transactions are one of the supported features, alongside connection pooling, replication, and multiple database instances. The documentation is organized per database, with a page per driver under docs/docs/drivers, so transaction and connection behavior is documented against a specific engine rather than in one place.
Is TypeORM better than Prisma?
The repository makes no comparison with Prisma and publishes no benchmark. Its own claim is that it supports both DataMapper and ActiveRecord patterns unlike other JavaScript ORMs, and that it is highly influenced by Hibernate, Doctrine, and Entity Framework, which are the projects it names as models.
how to install typeorm
The root README contains no install command. What it offers is a set of sample repositories to clone, including TypeScript, JavaScript, Babel, browser, Express, Koa, MongoDB, Cordova, Ionic, React Native, NativeScript, and Electron examples, plus a link to the documentation site.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typeorm-typeorm)