v4.1.2
The substance of the 4.1 line: every exported symbol documented, the first published API
reference, and the defects that writing that documentation turned up — one of which made a
whole feature unreachable. v4.1.1 and v4.1.2 are documentation and packaging on top of
v4.1.0; these notes cover everything since v4.0.3.
Nothing here breaks code that was already producing correct SQL. Several calls that used
to succeed now throw, and in every case they are the ones that were silently producing wrong
output.
Upgrade notes (4.0.x → 4.1.x)
-
@ColumnIndexand@NullableIndexnow work at all. They threwTypeErrorat import
time on any ordinary model: TypeScript applies property decorators before class
decorators, so they ran before@Tablecreated the options bag they read from, and@Column
does not create one either. No decorator order worked — the feature was unreachable. If you
gave up on them, they are usable now. -
CREATE INDEXoutput changed, and indices will appear that never existed. Five of the
thirteenColumnIndexOptionsemitted invalid SQL —USINGcame beforeON, andCOLLATE,
the operator class, the sort order and the nulls position landed after the closing
parenthesis.method,collation,opClass,orderandnullsFirstnow work, and
includeis emitted for the first time. Those statements were failing silently, because
syncIndexdiscarded its own rejections; expect the indices to be created on your next
sync(). -
@NullableIndex's factory form declared the wrong indices. It built both halves by
mutating one options object, which@ColumnIndexstores by reference, so you got two
identicalIS NOT NULLindices and neither carried the predicate that makes them partial.
It now builds a fresh object per half, combines your own predicate with the null test, and
suffixes your own name so the halves cannot collide. -
query.sqlnow throws when given a template substitution. It ignored substitution
values, and a tagged template hands the literal parts in as an array — whichString()
joins with commas. Sosql`SELECT * FROM t WHERE id = ${id}`yielded
SELECT * FROM t WHERE id = ,;: valid-looking, silently wrong. Use bind parameters. Calling
sql()as a plain function is as lenient as it was. -
query.Lnow interpolates its substitutions. The same defect fixed the other way round:
a literal fragment has no bind channel, so escaping and interpolation are the only option.
Its own documented example previously produced
(SELECT COUNT(*) FROM "SomeTable" WHERE owner = ,) = 0. -
query.E()now doubles embedded quotes. It wrapped a string in single quotes without
escaping the ones inside it, so any value containing a quote produced a broken string
constant — and a value chosen for the purpose produced SQL. This is also the helper that
escapes a dynamic view's parameters on their way into the view definition, andviewParams
can arrive with afind()call, so a service that let a caller choose them was exposed. -
sync()rejects instead of leaking an unhandled rejection, andsync(options)now
passes its options to the view pass — sowithoutDrop: truetakes effect, where before it
did nothing whatever. The order is tables, then views, then indices, each awaited, so an
index on a materialized view has something to attach to.syncIndices()on a model that
declares no index resolves rather than throwing synchronously. -
@Viewand@DynamicViewreject a blank definition with aTypeErrornaming the
problem, instead of accepting it or failing later with an unhelpful one. -
@AssociatedWithresolves its thunk on first read rather than at decoration time — the
one moment a thunk exists to avoid. Input classes and models import each other, so the
decorator body could run while the other module was still initialising and capture
undefinedas the model.
Fixed
- A caller-supplied
loggingfunction no longer crashes on the first query. Setting
sequelize.loggingto a plain callback — the shape sequelize's own option takes — got it
cast toILoggerand put in the logger slot, so the first logged query threw
TypeError: logger.log is not a function. Both shapes are now accepted, a supplied callback
still receives formatted SQL, andfalsestill disables logging. Logging is on unless
explicitly turned off, so this was the default path, not an edge case.
Added
- API reference — every exported symbol,
searchable, always serving the current major. SqlLoggingFunction— names the callback shape accepted bylogging.
Documentation
Doc-block coverage went from 81% to 100% with no bare pages: all 25 BaseModel symbols, all
36 remaining decorator symbols, and the query namespace. Several things that were true of the
code but written down nowhere are now stated — toWhereOptions treating a % anywhere in a
string as an ILIKE pattern and a leading comparison operator as that operator, pureFields()
always appending primary keys, database() caching process-wide. Graph was documented as
undirected and is directed; its path() returns the reachable set, not the longest path.
@Emittable is now documented as what it is — an empty body behind a doc-block that promised
NOTIFY-based change events.
Every fix above is pinned by a test that fails against the code it replaces.
Full Changelog: v4.0.3...v4.1.2
About
@imqueue/sequelize turns a query described as data — filters, paging, ordering and the requested fields — into one efficient Sequelize statement, with database views as models and the Postgres index options Sequelize cannot express. Part of the @imqueue framework for Node.js & TypeScript microservices.
- Docs: https://imqueue.org/
- API reference: https://imqueue.org/api/sequelize/latest/
- Guide for AI assistants / LLMs: https://imqueue.org/llms.txt
- Commercial license & support: https://imqueue.com/
npm i @imqueue/sequelize