npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts-prorm-orm

v2.4.0

Published

A TypeScript ORM for MySQL, PostgreSQL, SQLite, MSSQL, and more

Readme

ts-prorm-orm

npm version npm downloads license TypeScript pipeline status

A TypeScript ORM supporting multiple database dialects with full TypeScript support.

Published on npm as ts-prorm-ormnpm install ts-prorm-orm

Documentation: prod-orm.iogetting started · core concepts · guides · API reference · in the browser

Features

  • Multi-database support: 27 SQL dialects. Core implementations for SQLite, PostgreSQL, MySQL, MariaDB, Oracle, MSSQL, CockroachDB, Amazon Redshift, IBM Db2, Snowflake, ClickHouse, DuckDB, SAP HANA and Google Cloud Spanner; Postgres-derived support for TimescaleDB, Greenplum, YugabyteDB, Vertica, Trino, Exasol, CrateDB, QuestDB and Firebird; MySQL-derived for TiDB, SingleStore and Databricks; and Turso/libSQL on SQLite. See Supported Dialects for what is verified against a real engine.
  • Relations without SQL: hasOne/hasMany/belongsTo/belongsToMany via methods or decorators, eager loading with include, and required / include.where to filter parents by their children — applied before LIMIT, so pagination is correct
  • TypeScript-first: Full TypeScript support with decorators
  • CRUD operations: Full query builder with associations, scopes, transactions
  • Migrations: Database versioning and seeding
  • Hooks: Lifecycle events for models
  • Validation: Built-in and custom validators
  • Stored Procedures: Create and call stored procedures (across supported dialects)
  • Triggers: Database triggers with FOR EACH ROW and WHEN clauses (across supported dialects)
  • Query logging: Sequelize-compatible logging (false / true / a (sql, timing) function), overridable per query, plus benchmark for elapsed time and logQueryParameters for bound values. Every operation logs, not just some
  • Bulk writes: increment/decrement do the arithmetic in the database, so concurrent updates don't lose each other; bulkUpdate writes different values to many rows in one statement instead of one round trip per row
  • Aggregates: count, sum, avg, min, max — all issuing real SQL aggregates and honouring where, scopes, soft-deletes and relation filters; group + having for grouped results
  • Sequences: createSequence() on PostgreSQL, MariaDB, Oracle, MSSQL, Db2 and friends. SQLite and MySQL have no sequences and report that explicitly rather than emitting SQL the driver rejects
  • Table Partitions: RANGE, LIST, HASH partitioning (across supported dialects)
  • Partial Indexes: Conditional indexes for MySQL, MariaDB, PostgreSQL, Oracle, MSSQL
  • Row-Level Security (RLS): PostgreSQL, Oracle VPD, MSSQL Security Policies
  • Materialized Views: With FAST/COMPLETE refresh (PostgreSQL, Oracle)
  • Views: Database views support
  • Full-Text Search: one createFullTextIndex() call resolves per dialect — GIN over to_tsvector on PostgreSQL, FULLTEXT on MySQL/MariaDB, FTS5 on SQLite
  • JSON/JSONB: Native JSON data type support
  • Spatial Data: PostGIS support for PostgreSQL
  • Foreign Data Wrappers: PostgreSQL FDW support
  • User Management: Database users and privileges (PostgreSQL, Oracle, MSSQL)
  • Connection Pooling: Efficient connection pool management
  • Query Optimization: Prepared statements, query hints, caching
  • Audit Logging: Built-in audit trail functionality
  • Polymorphic Associations: Built-in helpers for polymorphic relationships
  • Self-referential Associations: Tree structure support
  • Object, key-value and document stores: S3, MinIO, R2, GCS, Azure Blob, Redis, MongoDB, DynamoDB, Cassandra, Elasticsearch and ~90 more ship as standalone *Store classes with APIs matching each engine. These are not part of the model/relation layer — see NoSQL Stores

Installation

npm install ts-prorm-orm

In the browser

No build step required — one script tag, served from the documentation site:

<script src="https://prod-orm.io/cdn/prorm.min.js"></script>
<script>
  const db = await prorm.openBrowserDatabase({ database: 'notes' });
  const Note = db.define('Note', { title: prorm.DataTypes.STRING });
  await db.sync();
  await Note.create({ title: 'Hello' });
</script>

The same models, finders and operators, against a real SQLite database in the page — SQLite compiled to WebAssembly where Web SQL is gone, which is Chrome and Firefox. localStorage, sessionStorage, cookies and adapters for PouchDB and RxDB come with it. See the browser guide.

Quick Start

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'sqlite',
  storage: ':memory:',
  logging: console.log,
});

const User = prorm.define('User', {
  name: DataTypes.STRING,
  email: {
    type: DataTypes.STRING,
    validate: { isEmail: true },
  },
});

await prorm.sync();
const user = await User.create({ name: 'John', email: '[email protected]' });
console.log(user.toJSON());

Database type coverage

prorm spans 22 database types, each with at least 5 supported engines — 27 SQL dialects and 102 NoSQL/data stores (129 engines). Full taxonomy: docs/database-types.md.

| Type | Engines | |------|---------| | Relational (OLTP) | SQLite, MySQL, PostgreSQL, MariaDB, Oracle, MSSQL, Db2, Firebird, Turso | | Warehouse / OLAP | ClickHouse, DuckDB, Redshift, Snowflake, Vertica, Greenplum, Exasol, HANA, Databricks, Trino | | NewSQL / distributed | CockroachDB, YugabyteDB, TiDB, SingleStore, Spanner | | Document | MongoDB, Couchbase, RethinkDB, SurrealDB, ArangoDB | | Key-value | Redis, Memcached, etcd, DynamoDB, Aerospike | | Wide-column | Cassandra, ScyllaDB, Keyspaces, HBase, Bigtable | | Graph | Neo4j, ArangoDB, TigerGraph, Neptune, Dgraph | | Vector | Pinecone, Milvus, Qdrant, Weaviate, Chroma | | Time-series | InfluxDB, TimescaleDB, QuestDB, Prometheus, VictoriaMetrics | | Search | Elasticsearch, OpenSearch, Meilisearch, Typesense, Solr | | Object storage | S3, GCS, Azure Blob, MinIO, Cloudflare R2 | | Streaming / queue | Kafka, NATS, RabbitMQ, Pulsar, Redpanda | | In-memory data grid | Hazelcast, Ignite, GridGain, Infinispan, Geode, Coherence | | Embedded storage engine | RocksDB, LevelDB, LMDB, UnQLite, NeDB, PouchDB | | Ledger / immutable | QLDB, immudb, BigchainDB, TerminusDB, Fluree, ProvenDB | | Multi-model | Cosmos DB, FaunaDB, OrientDB, MarkLogic, Firestore, RavenDB | | RDF / triplestore | Fuseki, GraphDB, Stardog, Blazegraph, Virtuoso, AllegroGraph | | Real-time OLAP | Druid, Pinot, StarRocks, Doris, Rockset, Materialize | | Cloud pub/sub | Kinesis, Event Hubs, Pub/Sub, SQS, SNS, EventStoreDB | | Edge / serverless KV | Cloudflare KV, Vercel KV, Upstash, Deno KV, Momento, DAX | | Job / task queue | Beanstalkd, Gearman, BullMQ, NSQ, Resque, Bee-Queue | | Log / observability | Loki, Splunk, Graylog, Sumo Logic, SigNoz, Papertrail |

Supported Dialects

How these are verified. SQLite and DuckDB are embedded, so the test suite runs against the real engine on every commit. PostgreSQL, MySQL, MariaDB, MSSQL, Oracle, CockroachDB and ClickHouse have real servers available via docker-compose.test.yml and are exercised by npm run test:integration. The remaining dialects are covered by unit tests against an in-memory SQL simulator, which checks generated SQL but not engine behaviour. "Stable" below means the implementation is complete, not that it has been run against that vendor's server in CI.

Dialects not listed in the table are implemented as subclasses of a core dialect and inherit its behaviour: TimescaleDB, Greenplum, YugabyteDB, Vertica, Trino, Exasol, CrateDB, QuestDB and Firebird extend PostgreSQL; TiDB, SingleStore and Databricks extend MySQL; Turso/libSQL extends SQLite.

| Dialect | Status | Features | |---------|--------|-----------| | SQLite | Stable | FTS5, CTEs, Window Functions, UPSERT | | MySQL | Stable | Stored procedures, triggers, partitions | | PostgreSQL | Stable | RLS, FDW, PostGIS, Sequences, Extensions | | MariaDB | Stable | Stored procedures, triggers, virtual columns | | Oracle | Stable | Sequences, stored procedures | | MSSQL | Stable | Sequences, stored procedures, RLS | | CockroachDB | Stable | Distributed SQL, Postgres wire protocol/driver (pg), horizontal scalability | | Amazon Redshift | Stable | Postgres-derived cloud data warehouse (pg driver), DISTKEY/SORTKEY instead of indexes, no FK/unique enforcement | | IBM Db2 | Stable | ibm_db driver, FETCH FIRST pagination, MERGE upsert | | Snowflake | Stable | snowflake-sdk driver, VARIANT semi-structured type, warehouse-based compute, no traditional indexes | | ClickHouse | Stable | @clickhouse/client driver, columnar OLAP, requires ENGINE clause on CREATE TABLE, no multi-statement transactions, no FK enforcement | | DuckDB | Stable | duckdb driver, embedded/in-process OLAP (file or :memory:, no server), window functions, recursive CTEs, LIST/STRUCT/MAP types, direct Parquet/CSV/JSON table functions | | SAP HANA | Stable | hdb driver, in-memory column-store tables, native UPSERT ... WITH PRIMARY KEY, LIMIT n OFFSET m pagination requiring a sentinel LIMIT | | Google Cloud Spanner | Stable | @google-cloud/spanner driver (GoogleSQL), globally distributed with externally-consistent transactions, Mutation API for bulk/blind writes, INSERT OR UPDATE upsert syntax |

Extended dialects

Twelve additional dialects subclass the nearest wire-compatible base dialect and override the grammar / type-mapping that genuinely differs, reusing the base's driver. Each has a dedicated page under docs/dialects/ and a connection-free SQL-generation test suite (tests/dialects/<name>*.test.ts).

| Dialect | Base (driver) | Key differences | |---------|---------------|-----------------| | TiDB | MySQL (mysql2) | AUTO_RANDOM, SHARD_ROW_ID_BITS/PRE_SPLIT_REGIONS, SPLIT TABLE | | SingleStore | MySQL (mysql2) | SHARD KEY/SORT KEY, ROWSTORE/columnstore, REFERENCE tables, FK omitted | | Databricks | MySQL (mysql2) | USING DELTA, MERGE INTO upsert, Spark types, GENERATED ALWAYS AS IDENTITY | | YugabyteDB | PostgreSQL (pg) | SPLIT INTO TABLETS, colocation, HASH primary keys, tablegroups | | TimescaleDB | PostgreSQL (pg) | create_hypertable, compression/retention policies, continuous aggregates | | Greenplum | PostgreSQL (pg) | DISTRIBUTED BY, append-optimized storage, external tables, staging-table upsert | | Vertica | PostgreSQL (pg) | ORDER BY/SEGMENTED BY, projections, IDENTITY, LONG VARCHAR | | Trino | PostgreSQL (pg) | catalog.schema.table, WITH (format=…), CTAS, no PK/FK/index | | Exasol | PostgreSQL (pg) | DISTRIBUTE BY, IDENTITY, IMPORT/EXPORT, MERGE upsert | | QuestDB | PostgreSQL (pg) | designated TIMESTAMP, PARTITION BY, SYMBOL, DEDUP | | CrateDB | PostgreSQL (pg) | CLUSTERED/PARTITIONED, OBJECT/ARRAY types | | Firebird | PostgreSQL (pg) | FIRST/SKIP paging, GENERATED … IDENTITY, generators |

These dialect layers are verified at the SQL-generation level (connection-free tests); end-to-end execution against a live server of each engine is not part of the automated suite. See each page's "verification status" section.

Diagrams

The src/diagrams module renders standalone SVG diagrams from schema data — 15 generators (model card, ER, migration, UML class, crow's-foot relational, sequence, state, dependency graph, data-dictionary, index map, flowchart, tree, Chen-ER, package, gantt) built on a shared DOM-backed SVG builder with light/dark themes and configurable accent colours.

import { ModelDiagram } from 'ts-prorm-orm';

new ModelDiagram({
  name: 'User',
  fields: { id: { type: 'INTEGER', primaryKey: true }, email: { type: 'VARCHAR(255)', unique: true } },
  theme: 'dark',
  color: 'emerald',
}).save('./diagrams/User.svg');

See the diagram module guide for every generator.

External Fields

A model field whose contents live in an object or key-value store, while the row lives in the database. The table column holds only the object key; the ORM keeps the two in step, so the link between a row and its object isn't something you maintain by hand.

import { Prorm, DataTypes, ExternalField, Table, Column, PrimaryKey, AutoIncrement } from 'ts-prorm-orm';
import { S3Store } from 'ts-prorm-orm';

const s3 = new S3Store({ region: 'us-east-1' });
await s3.connect();

prorm.registerStore('assets', s3, { defaultBucket: 'avatars' });

@Table()
class User {
  @Column(DataTypes.INTEGER())
  @PrimaryKey()
  @AutoIncrement()
  declare id: number;

  @Column(DataTypes.STRING(100))
  declare name: string;

  // `avatarKey` is registered for you; only the key is stored in the table
  @ExternalField({ store: 'assets', contentType: 'image/png' })
  declare avatar: Buffer;
}

prorm.addModel(User);
await prorm.sync();

const user = await User.create({ name: 'Ada' });

user.avatar = pngBytes;
await user.save();          // PUT to S3, then persists avatarKey

const fetched = await User.findByPk(user.id);
await fetched.loadAvatar(); // GET from S3
fetched.avatar;             // Buffer

await fetched.deleteAvatar(); // removes the object and clears the key
await fetched.destroy();      // deleting the row cleans up its objects

Each external field x gets loadX(), saveX(value), deleteX() and hasX().

Any shipped store works without an adapter. S3, MinIO, R2, GCS, Azure Blob and Redis all have different method names (putObject vs uploadObject vs uploadBlob; deleteObject vs removeObject vs deleteBlob) — these are normalized internally, so registerStore() takes the store directly. Key-value stores have no bucket concept, so a configured bucket becomes a key prefix, and binary payloads round-trip through base64.

| Option | Default | Purpose | |--------|---------|---------| | store | — | Name the store was registered under | | bucket | store's defaultBucket | Bucket/container; a key prefix on key-value stores | | keyColumn | <field>Key | Column holding the object key | | keyPrefix | <field>/ | Prefix for generated keys | | contentType | — | Recorded on write where the store supports it | | encoding | buffer | buffer, utf8, or json (parsed on read, stringified on write) |

Pass your own object implementing ExternalStoreAdapter to registerStore() for a store that isn't recognized.

NoSQL Stores

NoSQL engines don't share the SQL-shaped Dialect interface used above (no query(sql), no identifier escaping, no DDL). Instead, each is its own store class under src/nosql/<name>/, exposing the operations that engine actually supports — see each store's README for full details.

| Store | Status | Features | |-------|--------|-----------| | MongoDB | Stable | mongodb driver, document CRUD, filters, aggregation pipeline, indexes, multi-document transactions (requires replica set) | | Redis | Stable | ioredis driver, string/hash/list/set/sorted-set commands, pub/sub, pipelining/MULTI, no query language | | Amazon DynamoDB | Stable | @aws-sdk/client-dynamodb + @aws-sdk/lib-dynamodb, partition/sort-key CRUD, Query/Scan, batch and transactional writes, no arbitrary queries |

import { MongoStore, RedisStore, DynamoDbStore } from 'ts-prorm-orm';

const mongo = new MongoStore({ uri: 'mongodb://localhost:27017', database: 'app' });
await mongo.connect();
await mongo.collection('users').insertOne({ name: 'Ada' });

const redis = new RedisStore({ host: 'localhost', port: 6379 });
await redis.connect();
await redis.set('session:1', 'active', { ex: 3600 });

const dynamo = new DynamoDbStore({ region: 'us-east-1' });
await dynamo.connect();
await dynamo.putItem('Users', { id: '1', name: 'Ada' });

Object storage, streaming & additional stores

Twelve more adapters cover object storage, streaming/queues, wide-column, document, cache, and search engines. Each lazy-loads its driver (none is a hard dependency) and accepts an injected client, so it can be used and unit-tested without the driver installed. Full pages under docs/stores/.

| Store | Driver | Kind | |-------|--------|------| | S3Store | @aws-sdk/client-s3 | Amazon S3 object storage | | GCSStore | @google-cloud/storage | Google Cloud Storage | | AzureBlobStore | @azure/storage-blob | Azure Blob Storage | | KafkaStore | kafkajs | Apache Kafka streaming | | NatsStore | nats | NATS + JetStream KV | | RabbitMQStore | amqplib | RabbitMQ / AMQP | | CassandraStore | cassandra-driver | Apache Cassandra (CQL) | | CouchbaseStore | couchbase | Couchbase (N1QL) | | MemcachedStore | memjs | Memcached cache | | SurrealStore | surrealdb | SurrealDB multi-model | | OpenSearchStore | @opensearch-project/opensearch | OpenSearch | | RethinkDBStore | rethinkdb-ts | RethinkDB |

import { S3Store, KafkaStore } from 'ts-prorm-orm';

const s3 = new S3Store({ region: 'us-east-1' });
await s3.connect();
await s3.putObject('bucket', 'hello.txt', 'hi');

const kafka = new KafkaStore({ clientId: 'app', brokers: ['localhost:9092'] });
await kafka.connect();
await kafka.produce('events', [{ value: JSON.stringify({ hello: 'world' }) }]);

Usage Examples by Dialect

SQLite

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'sqlite',
  storage: './database.db',
});

// Define model with SQLite-specific features
const User = prorm.define('User', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: DataTypes.STRING,
  email: DataTypes.STRING(255),
  // SQLite supports virtual columns
  fullName: {
    type: DataTypes.VIRTUAL,
    get() {
      return `${this.name}`;
    }
  }
});

// Full-text search (FTS5 on SQLite, GIN/to_tsvector on Postgres,
// FULLTEXT on MySQL/MariaDB - the dialect decides)
await prorm.getQueryInterface().createFullTextIndex({
  name: 'users_fts',
  table: 'users',
  columns: ['name', 'email'],
});

// Upsert (INSERT OR REPLACE)
await User.upsert({
  id: 1,
  name: 'John',
  email: '[email protected]'
});

MySQL

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'mysql',
  host: 'localhost',
  port: 3306,
  database: 'mydb',
  username: 'root',
  password: 'password',
});

const User = prorm.define('User', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: DataTypes.STRING(100),
  email: {
    type: DataTypes.STRING(255),
    unique: true,
  },
  // MySQL JSON column
  preferences: DataTypes.JSON,
  // MySQL enum
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'pending'),
    defaultValue: 'active',
  }
});

// Declare a stored procedure with @Procedure, then let sync() create it
import { Procedure, ProcedureRegistry } from 'ts-prorm-orm';

class UserProcedures {
  @Procedure({
    name: 'get_user_by_email',
    params: [{ name: 'user_email', type: 'VARCHAR(255)', mode: 'IN' }],
    body: 'SELECT * FROM users WHERE email = user_email;',
  })
  getUserByEmail(email: string) {}
}

prorm.registerProcedures(UserProcedures);
await prorm.sync(); // issues the CREATE PROCEDURE

// Call it
const rows = await ProcedureRegistry.call(
  prorm, UserProcedures, 'getUserByEmail', ['[email protected]']
);

PostgreSQL

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'postgres',
  host: 'localhost',
  port: 5432,
  database: 'mydb',
  username: 'postgres',
  password: 'password',
});

const User = prorm.define('User', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: DataTypes.STRING(100),
  email: {
    type: DataTypes.STRING(255),
    unique: true,
  },
  // PostgreSQL UUID
  uuid: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
  },
  // PostgreSQL JSONB
  metadata: DataTypes.JSONB,
  // PostgreSQL array
  tags: DataTypes.ARRAY(DataTypes.STRING),
  // PostgreSQL hstore
  properties: DataTypes.HSTORE,
});

const qi = prorm.getQueryInterface();

// Row-Level Security (RLS)
await qi.enableRowLevelSecurity('users');
await qi.createPolicy({
  name: 'users_policy',
  table: 'users',
  using: 'user_id = current_user_id()',
});

// Full-text search
await qi.createFullTextIndex({
  name: 'users_fts_idx',
  table: 'users',
  columns: ['name', 'email'],
  language: 'english',
});

// Sequence
await qi.createSequence('user_id_seq', { start: 1000 });

MariaDB

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'mariadb',
  host: 'localhost',
  port: 3306,
  database: 'mydb',
  username: 'root',
  password: 'password',
});

const Product = prorm.define('Product', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: DataTypes.STRING(200),
  price: DataTypes.DECIMAL(10, 2),
  // MariaDB virtual column
  price_with_tax: {
    type: DataTypes.VIRTUAL,
    get() {
      return parseFloat(this.price) * 1.2;
    }
  },
  // MariaDB JSON
  attributes: DataTypes.JSON,
});

// Stored procedure - declared once, created by sync()
class ProductProcedures {
  @Procedure({
    name: 'get_products_by_price',
    params: [{ name: 'min_price', type: 'DECIMAL(10,2)', mode: 'IN' }],
    body: 'SELECT * FROM products WHERE price >= min_price;',
  })
  getProductsByPrice(minPrice: number) {}
}

prorm.registerProcedures(ProductProcedures);
await prorm.sync();

const rows = await ProcedureRegistry.call(
  prorm, ProductProcedures, 'getProductsByPrice', [10.0]
);

Oracle

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'oracle',
  host: 'localhost',
  port: 1521,
  database: 'ORCL',
  username: 'system',
  password: 'password',
});

const Employee = prorm.define('Employee', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: DataTypes.STRING(100),
  email: DataTypes.STRING(255),
  // Oracle BLOB for binary data
  resume: DataTypes.BLOB,
  // Oracle CLOB for large text
  description: DataTypes.TEXT,
});

// Oracle sequence
await prorm.getQueryInterface().createSequence('employee_seq', {
  start: 1000,
  increment: 1,
});

// Stored procedure with an OUT parameter
class EmployeeProcedures {
  @Procedure({
    name: 'get_employee_count',
    params: [{ name: 'p_count', type: 'NUMBER', mode: 'OUT' }],
    body: 'SELECT COUNT(*) INTO p_count FROM employees;',
  })
  getEmployeeCount() {}
}

prorm.registerProcedures(EmployeeProcedures);
await prorm.sync();

MSSQL

import { Prorm, DataTypes } from 'ts-prorm-orm';

const prorm = new Prorm({
  dialect: 'mssql',
  host: 'localhost',
  port: 1433,
  database: 'mydb',
  username: 'sa',
  password: 'password',
});

const Order = prorm.define('Order', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  customer_id: DataTypes.INTEGER,
  total: DataTypes.DECIMAL(10, 2),
  // MSSQL datetime2
  order_date: DataTypes.DATE,
  // MSSQL-specific geometry
  location: DataTypes.GEOMETRY('POINT'),
  // MSSQL XML
  details: DataTypes.XML,
});

// MSSQL sequence
await prorm.getQueryInterface().createSequence('order_id_seq', {
  start: 1000,
  increment: 1,
});

// Row-Level Security. SQL Server models RLS as a security policy bound to a
// predicate function rather than as a per-table policy, and prorm has no
// builder for it yet - this is one of the few places raw SQL is still needed.
await prorm.query(`
  CREATE SECURITY POLICY SalesFilter
  ADD FILTER PREDICATE dbo.fn_tenantAccessPredicate(TenantId)
  ON dbo.Sales
`);

CLI Commands

# Generate a model
npm run model:create -- --name User --attributes name:string,email:string

# Run migrations
npm run model:create

# Generate ER diagram
npm run diagram:model

Documentation

Full documentation is in the docs/ directory — start there for the complete index.

Core

Schema

Connections & performance

Extending & operating

Databases & tooling

Architecture / Component Guides

In-depth, code-level reference docs for each major subsystem, living alongside the source under src/:

  • Dialects - The Dialect interface and per-database (SQLite/MySQL/PostgreSQL/MariaDB/Oracle/MSSQL/CockroachDB/Redshift/Db2/Snowflake/ClickHouse/DuckDB/HANA/Spanner) implementations of connections, DDL, views, partitioning, RLS, and query building.
  • Models - The model layer: attribute/data types, prorm.define(), associations, scopes, indexes/constraints, and the model registry.
  • Query Builders - Translates where/order/limit/include options into dialect-specific SQL strings and bound parameter values. Includes a typed SQL function-builder library (src/query-builders/functions/** - window functions, date/time, JSON paths, string/math functions, CASE expressions, cross-dialect aggregates, full-text search) usable via import { ... } from 'ts-prorm-orm'; see src/query-builders/README.md for the function list.
  • Extension Catalog - A discoverability reference (not executable code) of ~124 verified real extensions/plugins/licensed features across dialects, queryable via findExtension()/listExtensionsForDialect()/listExtensionsByCategory()/searchExtensions().
  • Query Optimizers - Opt-in performance tooling (query hints, explain plans, slow-query logging, batch optimization, prepared-statement/result caching).
  • Migrations - Migration files, the Migrator, PrormMeta history tracking, seeders, QueryInterface, and schema diffing (src/schema/).
  • Compliance - GDPR/privacy/security tooling layered on the ORM core: DSAR workflows, right to erasure, consent tracking, and the composite @Security decorator.
  • Decorators - TypeScript decorator API for defining models (@Table, @Column, etc.) plus a larger set of feature decorators for constraints, associations, and dialect-specific column types.
  • Connections, Transactions & Hooks - Connection pooling, connection/replica management, transactions, and the lifecycle hooks manager.
  • CLI Tooling - Reference for the multiple (non-unified) CLI entry points for model generation, migrations, seeding, and diagrams.
  • Utilities - Supporting modules: error hierarchy, validators, logging, audit logging, caching, diagram generation, streams, foreign-data helpers, and user management.

Online documentation: prod-orm.io — every guide above, searchable, plus the generated API reference and the browser build.

Contributing

See CONTRIBUTING.md for the development workflow, testing, the release/publish flow, and the CI/CD + deployment runbook.

License

MIT