Upgrade guide
Only releases that may require something on your side. Everything else is in the changelog.
0.44.0 — 2026-09-07
Section titled “0.44.0 — 2026-09-07”One pair applies the schema, sync and planSync, over one options shape:
| Before | Now |
|---|---|
migrator.autoSync(options) |
migrator.sync(options) |
migrator.syncForce() |
migrator.sync({ force: true }) |
migrator.syncEntity(entity, options) |
migrator.sync({ entity, ...options }) |
uql-migrate sync --dry-run now prints the statements beside --force instead of ignoring the flag and
recreating your tables.
A naming strategy no longer rewrites a table you named yourself: @Entity({ name: 'UserProfile' }) on
class UserProfile used to be snake-cased like a default. Entities that name no table are unaffected.
0.43.0 — 2026-09-07
Section titled “0.43.0 — 2026-09-07”An option a column cannot use is now an error where it used to be silently ignored, at compile time and again when the entity registers. Delete whichever your entities state:
lengthoutside a string column,precision,scaleandautoIncrementoutside a numeric one,dimensionsanddistanceoutside a vector.- Any DDL or generator option on a
virtualfield, which is never in the schema. onUpdatebesideupdatable: false, andnullable: trueon a key.nullable: falseon a key still compiles: it states what the key already is.defaultValuethat is not the value the column holds. A JSON column keeps the SQL literal it stores,defaultValue: '{}'.
Writing a dialect or reading metadata? getSqlType(field) and fieldOptionsToCanonical(options) no
longer take a second argument, and columnFamily(type) replaces isNumericType, isBooleanType and
isJsonType.
0.42.1 — 2026-09-05
Section titled “0.42.1 — 2026-09-05”Nothing in your database is renamed or rewritten: keys and indexes are recognised by the columns they cover.
- Derived names now read
<table>__<columns>_<kind>, on new tables only. - A migration can change a primary key. SQLite refuses — rebuilding the table is its only route.
- Adding a key column to a table with rows fails until you fill it in.
- Writing a dialect?
serialPrimaryKeyisserialType(the type alone), plusserialDeclaresPrimaryKey.
0.42.0 — 2026-09-04
Section titled “0.42.0 — 2026-09-04”- A second
@Idcomposes the key instead of replacing the first, so an entity relying on that gains a column and a two-columnPRIMARY KEY. Narrowing an inherited key is unaffected. EntityMeta.idis nowids, a list.- Insert and save return
IdValue<E> | undefined, as they already did on MySQL.
0.24.0 — 2026-08-02
Section titled “0.24.0 — 2026-08-02”The pool runs every operation, so a function that writes can take “a querier, or the pool”:
const save = (querier: UniversalQuerier, user: User) => querier.saveOne(User, user);
await save(pool, user);await pool.transaction((querier) => save(querier, user));Only a hand-written QuerierPool has anything to do: insertMany, updateMany, upsertOne,
upsertMany and saveMany are no longer optional.
0.23.0 — 2026-08-01
Section titled “0.23.0 — 2026-08-01”Decorators are the standard TC39 ones now. No experimentalDecorators, no emitDecoratorMetadata, no
reflect-metadata. A codemod does most of it:
npx uql-codemod --dry-runIt adds type to every @Field/@Id and entity to every relation, unwraps Relation<T>, drops
declare from decorated fields, and removes the decorator flags. Where the choice is yours it reports
instead: @Transactional(), @InjectQuerier(), @Log(), @Serialized(), and a branded id type it
writes as String (the column your database already has — 'uuid' needs a migration).
Then, by hand:
targetmust not beesnext(you can set any modern target other than that), the one target TypeScript leaves decorators untransformed.- Your build must transform them. esbuild, SWC, Babel
version: '2023-11', Bun andtscdo. Oxc does not, so Vite 8 needs one of the others. uql.config.tsneedsbunornode --import tsxif it imports entities — decorators are not erasable syntax.- NestJS: use
defineEntity. Nest’s DI needs parameter decorators, and onetsconfig.jsoncannot mix specs. See NestJS. - Node 24 is the minimum.