import { ConstraintType, ReferentialAction, IsolationLevel } from 'ts-prorm-orm';
await Order.addConstraint('order_user_fk', {
type: ConstraintType.ForeignKey,
fields: ['userId'],
references: { table: 'users', fields: ['id'] },
onDelete: ReferentialAction.Cascade,
});ALTER TABLE … ADD CONSTRAINT. Only a UNIQUE constraint can bereferences onCREATE TABLE.'FORIEGN KEY' — a- import { Prorm } from 'ts-prorm-orm';
+ import { Prorm, SqlDialect, ConstraintType, ReferentialAction } from 'ts-prorm-orm';
- const prorm = new Prorm({ dialect: 'postgres', database: 'shop' });
+ const prorm = new Prorm({ dialect: SqlDialect.Postgres, database: 'shop' });
await Order.addConstraint('order_user_fk', {
- type: 'FOREIGN KEY',
+ type: ConstraintType.ForeignKey,
fields: ['userId'],
references: { table: 'users', fields: ['id'] },
- onDelete: 'CASCADE',
+ onDelete: ReferentialAction.Cascade,
});[!NOTE]
This page is about the TypeScript vocabulary — the values you pass
to the ORM. For the SQL statements that change session behaviour —PRAGMA,sql_mode,search_path, isolation level as a statement — see
SQL constants.
[!TIP]
Every field still accepts the plain string. The enums are
string-valued and the option types were widened rather than replaced, so{ type: 'UNIQUE' }and{ type: ConstraintType.Unique }are the same value.
Existing code needs no change, and the two spellings mix freely.
SqlDialectProrm targets. This one is worth naming more than most: it is'postgressql' is a perfectly good string.import { Prorm, SqlDialect } from 'ts-prorm-orm';
const prorm = new Prorm({ dialect: SqlDialect.Postgres, database: 'shop' });SqlDialect declaration in src/dialect-names.ts; DIALECT_LOADERS insrc/dialects/loaders.ts is typed Record<SqlDialect, …>, so the two cannot| Group | Members |
|---|---|
| Core engines | Postgres, MySQL, MariaDB, SQLite, MSSQL, Oracle, Db2, HANA, Firebird, MonetDB, Teradata |
| PostgreSQL-compatible | CockroachDB, YugabyteDB, TimescaleDB, Greenplum, Redshift, OpenGauss, Citus, AlloyDB, AuroraDSQL, Yellowbrick, ParadeDB, Materialize, RisingWave, Neon, Supabase |
| MySQL-compatible | TiDB, SingleStore, OceanBase, PolarDB, Vitess, Dolt, Doris, StarRocks, HeatWave |
| SQLite-compatible | Turso, D1, Rqlite |
| Analytic / warehouse | ClickHouse, DuckDB, MotherDuck, Snowflake, Vertica, Exasol, Databricks, Trino, Presto, Athena, BigQuery, Synapse, Fabric, CrateDB, QuestDB, Druid, Kusto |
| Managed variants of an engine | RdsPostgres, AuroraPostgres, RdsMySQL, AuroraMySQL, RdsMariaDB, RdsData, RedshiftData, RdsMSSQL, RdsOracle, RdsDb2, AzureSQL, AzureSQLMI, AzurePostgres, AzureMySQL, CosmosPostgres, CloudSQLPostgres, CloudSQLMySQL, CloudSQLMSSQL, AlloyDBOmni, OracleAutonomous |
| Spanner | Spanner, SpannerPostgres |
engineOf('cloudsqlpostgres') is 'postgres'); Neon, Supabase andHeatWave are managed too but are listed with their families. SeeSQL_DIALECTS is the same list as an array — what a CLI's choices or aisSqlDialect(value) narrows an unknown string:import { Prorm, SQL_DIALECTS, isSqlDialect } from 'ts-prorm-orm';
const dialect = process.env.DB_DIALECT ?? 'sqlite';
if (!isSqlDialect(dialect)) {
// Fails at boot with the list of valid names, not at the first query.
throw new Error(`DB_DIALECT must be one of: ${SQL_DIALECTS.join(', ')}`);
}
// `dialect` is narrowed to SqlDialect here, so no cast is needed.
export const prorm = new Prorm({
dialect,
storage: dialect === 'sqlite' ? './dev.sqlite' : undefined,
database: process.env.DB_NAME,
});Dialect union are two declarations of the same list, so avocabulary.ts fails the build if they ever disagree —switch statements inside theConstraintType| Member | SQL | Means |
|---|---|---|
PrimaryKey | PRIMARY KEY | The row's identity. One per table, never null. |
Unique | UNIQUE | No two rows share these values. Nulls are exempt on most engines. |
ForeignKey | FOREIGN KEY | The value must exist in another table. |
Check | CHECK | A predicate every row must satisfy. |
Exclude | EXCLUDE | No two rows overlap on the given operators — the general form of UNIQUE. |
Exclude is PostgreSQL-only. Fields on engines that cannot emit it takeTableConstraintTypeLike, the same enum without that member, so asking MySQLNote: this enum reconciles two definitions that disagreed — models/constraints.tsincludedEXCLUDEandmodels/indexes.tsdid not, so
which members were legal depended on which module you imported the type from.
ReferentialAction| Member | Means |
|---|---|
Cascade | Apply the same change — delete the referencing rows, or follow the new key. The convenient one, and the one that silently removes data. |
Restrict | Refuse immediately, before other constraints are considered. |
SetNull | Null the referencing column. It must allow null. |
NoAction | Refuse, but only at end of statement — so a deferred constraint can still be satisfied by a later row. The SQL default. |
SetDefault | Set the referencing column to its column default. |
users row does to the orders rows that point at it:Restrict and NoAction differ only in when the check runs. That mattersNoAction lets a transaction fixRestrict does not.Deferrable| Member | Means |
|---|---|
InitiallyDeferred | At the end of the transaction. Lets you insert rows that reference each other. |
InitiallyImmediate | Per statement, but can be deferred within a transaction. |
NotDeferrable | Per statement, always. |
IndexMethod| Member | Good for | Where |
|---|---|---|
BTree | Equality, ranges, sorting, prefixes | Everywhere; the default |
Hash | Equality only, smaller than a B-tree for it | PostgreSQL, MySQL (MEMORY) |
Gin | Arrays, JSONB, full-text | PostgreSQL |
Gist | Geometric and range types | PostgreSQL |
SpGist | Data dividing into non-overlapping regions — points, text prefixes | PostgreSQL |
Brin | Very large, naturally ordered tables; tiny indexes | PostgreSQL |
PartitionKind| Member | Divides by |
|---|---|
Range | A contiguous span of values. The usual choice for dates. |
List | An explicit set of values per partition. |
Hash | A hash of the key — even distribution rather than meaning. |
SortDirectionASC and DESC. Worth knowing: null placement differs by engine — nulls sortASC, and the placement invertsNullsOrder when it matters.JoinType| Member | Keeps |
|---|---|
Inner | Only rows matching on both sides. The default. |
Left | Every row from the left, nulls where the right has no match. |
Right | Every row from the right. A Left join with the sides swapped. |
Full | Every row from both. Not supported by MySQL. |
Cross | Every combination — left × right rows. Rarely intended. |
AssociationType| Member | Foreign key lives on |
|---|---|
HasOne | the other table |
HasMany | the other table |
BelongsTo | this table |
BelongsToMany | a join table |
BelongsTo.IsolationLevel| Member | Guarantees |
|---|---|
ReadUncommitted | Nothing; reads can see uncommitted changes. PostgreSQL accepts it and silently gives you ReadCommitted. |
ReadCommitted | Each statement sees committed data — but two statements in one transaction can see different data. PostgreSQL's default. |
RepeatableRead | Every read sees one snapshot. MySQL's default. Does not rule out phantoms on every engine. |
Serializable | As if transactions ran one at a time. The only level that rules out write skew. |
[!WARNING] Serializablemakes serialisation failures a normal outcome, not
an error condition. Code using it must retry the transaction rather than
surface the failure —prorm.transaction(fn, { retry: { max: 3 } })does
that; see Transactions.
SqliteTransactionTypeDeferred (SQLite's default: no lock until the first read or write),Immediate (take the write lock at BEGIN) and Exclusive. This is thetype transaction option, and it is refused on every other engine except asDeferred.LockLevel| Member | Blocks |
|---|---|
KeyShare | Only changes to the key itself — rows referencing this one can still be inserted. |
Share | Writers. Other readers are fine. |
NoKeyUpdate | Other writers, but not KeyShare readers. |
Update | Everything else. |
KeyShare implicitly,SELECT … FOR UPDATE on a parent row can block inserts into aTriggerTiming, TriggerEvent, TriggerForEachTriggerEvent.Truncate isParamMode, Volatility, RoutineLanguageVolatility names two families that are notImmutable / Stable / Volatile, MySQLDeterministic / NotDeterministic. Naming them in one enum makesSqlCommandALL, SELECT, INSERT, UPDATE, DELETE — for grants and row-levelInsert is checked with withCheck ratherusing, because there is no existing row to test.ModelHook and PrormHookModelHook names every model lifecycle hook — the values Model.addHook(),hook(), hasHook(), removeHook() and define(..., { hooks }) take:BeforeValidate, AfterValidate, BeforeCreate, AfterCreate,BeforeUpdate, AfterUpdate, BeforeDestroy, AfterDestroy, BeforeSave,AfterSave, BeforeUpsert, AfterUpsert, BeforeFind, AfterFind,BeforeCount, the six Before/After BulkCreate / BulkUpdate /BulkDestroy hooks, BeforeReload and AfterReload. PrormHook names theprorm.addHook() registers: BeforeDefine, AfterDefine,BeforeSync, AfterSync, BeforeConnect, AfterConnect, BeforeDisconnect,AfterDisconnect, and the destroy, upsert and reload hooks at instance level.HookName and PrormHookName are the matching string unions. Seeimport { ModelHook, PrormHook } from 'ts-prorm-orm';
User.hook(ModelHook.BeforeCreate, (user) => {
user.email = String(user.email).trim().toLowerCase();
});
prorm.addHook(PrormHook.AfterSync, () => {
console.log('schema is in sync');
});OrderDirectionSortDirection is ASC / DESC. OrderDirection adds the null placement:ASC_NULLS_FIRST, ASC_NULLS_LAST, DESC_NULLS_FIRST, DESC_NULLS_LAST,ORDER BY. isOrderDirection(value) narrowsorderDirectionSuffix() renders the clause.import { OrderDirection } from 'ts-prorm-orm';
const recentlyShipped = await Order.findAll({
order: [['shippedAt', OrderDirection.DESC_NULLS_LAST]],
limit: 20,
});NULLS LAST, which it rejects.WindowFrameType, SetOperation, GroupingType| Enum | Members | Used by |
|---|---|---|
WindowFrameType | Rows, Range, Groups (PostgreSQL 11+, SQLite 3.28+) | window function frames |
SetOperation | Union, UnionAll, Except, Intersect | combining result sets |
GroupingType | Rollup, Cube, Grouping (grouping sets), None | GROUP BY extensions |
TimeUnitYear, Quarter, Month, Week, Day, Hour, Minute, Second, fordateTrunc, dateAdd, dateDiff, extract and scheduled events. The valuesdateAdd and extract have no quarter or week, so their parameter type isBasicTimeUnitLike.QueryTypes and ExplainFormatQueryTypes (SELECT, INSERT, UPDATE, DELETE, UPSERT, BULKINSERT,BULKUPDATE, BULKDELETE, VERSION, SHOWTABLES, DESCRIBE, CALL, RAW)type option of prorm.query(); ExplainFormat (TEXT, JSON,XML, YAML, TREE) is the format option of an EXPLAIN. See| Enum | Members | Means |
|---|---|---|
MigrationState | Pending, Up, Down | the status field of a migrator.status() record |
SeedState | Pending, Executed | the same for getSeedStatus() |
MigrationStorage | Prorm, Table, None | where the migrator records what has run |
MigrationState rather than MigrationStatus because MigrationStatus isTableCheckLevel (Quick, Fast, Medium, Extended, Changed) is theCHECK TABLE level. Severity — Low, Medium, High,Critical — is how serious a finding is in the compliance modules; it isSeverityLevel, because the root'sSeverity is the transfer guard's 'block' | 'warn' | 'info'.DiagramType names all fifteen generators (counted insrc/diagrams/diagram-type.ts), so a diagram can be chosen from a CLI flag orimport {
ConstraintType, ReferentialAction, Deferrable, IndexMethod, PartitionKind,
SortDirection, OrderDirection, JoinType, AssociationType, LockLevel,
SqlCommand, TriggerTiming, TriggerEvent, TriggerForEach,
ParamMode, Volatility, RoutineLanguage, DiagramType,
ModelHook, PrormHook, TimeUnit, WindowFrameType, SetOperation, GroupingType,
IsolationLevel, SqliteTransactionType, MigrationState, SeedState, MigrationStorage,
TableCheckLevel, SeverityLevel, QueryTypes,
} from 'ts-prorm-orm';…Like type — ConstraintTypeLike, ReferentialActionLike andwhere vocabulary