Skip to content

v4.1.2

Choose a tag to compare

@github-actions github-actions released this 01 Aug 13:58
· 22 commits to master since this release

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)

  • @ColumnIndex and @NullableIndex now work at all. They threw TypeError at import
    time on any ordinary model: TypeScript applies property decorators before class
    decorators, so they ran before @Table created 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 INDEX output changed, and indices will appear that never existed. Five of the
    thirteen ColumnIndexOptions emitted invalid SQL — USING came before ON, and COLLATE,
    the operator class, the sort order and the nulls position landed after the closing
    parenthesis. method, collation, opClass, order and nullsFirst now work, and
    include is emitted for the first time. Those statements were failing silently, because
    syncIndex discarded 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 @ColumnIndex stores by reference, so you got two
    identical IS NOT NULL indices 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.sql now throws when given a template substitution. It ignored substitution
    values, and a tagged template hands the literal parts in as an array — which String()
    joins with commas. So sql`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.L now 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, and viewParams
    can arrive with a find() call, so a service that let a caller choose them was exposed.

  • sync() rejects instead of leaking an unhandled rejection, and sync(options) now
    passes its options to the view pass — so withoutDrop: true takes 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.

  • @View and @DynamicView reject a blank definition with a TypeError naming the
    problem, instead of accepting it or failing later with an unhelpful one.

  • @AssociatedWith resolves 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
    undefined as the model.

Fixed

  • A caller-supplied logging function no longer crashes on the first query. Setting
    sequelize.logging to a plain callback — the shape sequelize's own option takes — got it
    cast to ILogger and 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, and false still 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 by logging.

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.