Changelog
Release-by-release behavior changes for nestjs-drizzle-crud. Mirrors CHANGELOG.md shipped in the npm tarball.
This page mirrors the CHANGELOG.md shipped in the npm tarball. Feature pages describe current behavior; this page is the historical record. If something here disagrees with a feature page, the feature page wins (and the changelog is the bug).
[3.1.0] - 2026-06-29
Added
findAll/countnow supportoptions.search. Callers can pass a search term and a list of table columns, e.g.{ search: { term: "na", columns: ["name", "code"] } }. The default mode is cross-columnILIKE '%term%';mode: "fullText"compiles a PostgreSQLto_tsvector(...) @@ plainto_tsquery(...)condition. The search predicate is applied to both the data query and the count query, so paginatedtotalstays correct.
[3.0.4] - 2026-06-21
Found while probing the package over real HTTP from the drizzle-pkg-demo consumer. PostgreSQL-first.
Fixed
- Bad client input on
create/updatenow maps to 400, not a raw 500. A value that is too long for its column (Postgres22001), fails aCHECKconstraint (23514), or is numerically out of range (22003) previously surfaced as an unhandledDrizzleQueryError→ 500 Internal Server Error. These are now translated toValidationFailedException(400), mirroring the existing unique-violation → 409 mapping.
[3.0.3] - 2026-06-20
Correctness fix found while validating the package from a fresh NestJS consumer. PostgreSQL-first.
Fixed
- Case-insensitive string filters are now EXACT, not wildcard patterns. A plain string value in a
findAll/countfilter (e.g.{ name: "foo" }) is documented as a case-insensitive exact match, but compiled toilike(column, value). ILIKE interprets%,_and\in the value as wildcards / escapes, so an equality filter silently became aLIKEpattern and returned non-matching rows (e.g.{ title: "a_b" }matched"aXb";{ title: "a%" }matched everything). It now compiles tolower(column) = lower(value), so those characters are treated as literal data. The explicit{ like }/{ ilike }operators are unchanged for intentional pattern matching.
[3.0.2] - 2026-06-19
Residual-edge hardening found by an end-to-end HTTP probe of 3.0.1 (all LOW severity; no behavior change to the happy path).
Changed
fullTextSearchnow returns the same envelope asfindAll—{ data, total, page, limit }instead of{ data, total }.page/limitare the resolved (clamped) values; the query is still only constrained when the caller passespagination. Callers paginating search results can now read back the page / limit they got.
Fixed
- Invalid
sortOrdernow fails fast (400).?sortOrder=<anything but asc/desc>previously fell through to ascending silently; it now throwsBadRequestException, mirroring the unknown-sortBycheck added in 3.0.1. - Non-finite numeric filter operands return 400, not 500. A
{ gt: NaN }/{ lte: Infinity }operand ongt/gte/lt/lte(e.g. from an unguardedNumber('abc')in a controller) reached SQL and surfaced as an opaqueDatabaseException(500). It is now rejected asBadRequestException. Non-number operands (dates, strings) are unaffected.
[3.0.1] - 2026-06-19
Correctness pass: typed exceptions now map to real HTTP status codes, plus several read-path fixes. PostgreSQL-first.
Fixed
- Exceptions extend
HttpExceptionso Nest maps them automatically:EntityNotFoundException→ 404,DuplicateEntityException→ 409,ValidationFailedException/BulkOperationException→ 400,Database*/TransactionException→ 500. Previously every error surfaced as a generic 500. - Duplicate-key translation. A Postgres unique violation (SQLSTATE
23505, on eithererr.codeor the Drizzle-wrappederr.cause.code) is converted toDuplicateEntityException(409), parsing the offending field / value from the driverdetail. fullTextSearchexcludes soft-deleted rows (added theIS NULLguard on the soft-delete column to both the data and count queries, matchingfindAll/count).- Pagination clamping.
page < 1,limit <= 0, andlimit > maxLimitare clamped via a sharedresolvePaginationhelper — no more negativeOFFSETorLIMIT 0. - Unknown sort column fails fast. A caller-supplied
sortBynot on the table throwsBadRequestException; an unknown column in a configureddefaultSortis warned and skipped. restore()returns the restored row on the PostgresRETURNINGpath (no longer re-find()s, which would have excluded the just-restored row via the soft-delete filter).
Added
- Row-level lock options on Postgres reads (
find/findOne/findAll):lock: 'update' | 'share'andforNoKeyUpdateapply.for(...). No-op on MySQL. See Row-level locks.
[3.0.0] - 2026-06-19
- First release under the
nestjs-drizzle-crudname with the 3.x API surface (DrizzleCrudModule.forRoot/forRootAsync/forFeature,SqlBaseCrudService).
Earlier (≤ 2.2.0)
Published as @quybquang/nestjs-drizzle-crud. Notable: 2.2.0 added a configurable module-level default sort; 2.1.2 documented the timestamps feature. See git history for details.