Skip to content

Dev -> Master - #37

Merged
cookieMonsterDev merged 3 commits into
masterfrom
develop
Sep 16, 2026
Merged

cookieMonsterDev merged 3 commits into
masterfrom
develop

Conversation

@cookieMonsterDev

Copy link
Copy Markdown
Owner

Summary

Test plan

  • Unit tests (pnpm test) cover the change
  • Integration tests run for the databases the change affects (DB=… pnpm test:integration)
  • README or CONTRIBUTING updated when the public API or workflow changes

Checklist

  • Branch name follows type/short-kebab-description (see CONTRIBUTING.md)
  • Commits follow Conventional Commits (feat, fix, docs, …)
  • pnpm lint, pnpm format:check, and pnpm typecheck are clean
  • No unrelated refactors or formatting-only noise

cookieMonsterDev and others added 2 commits September 16, 2026 10:36
* build!: move to ESM, Vite and Vitest

Replace the CommonJS tsc build and Jest with an ESM-only Vite library
build plus tsc-emitted declarations, and Vitest with separate unit and
integration projects. Lint, format, commitlint and lint-staged move to
ESM flat configs; the sources are reformatted for the new Prettier width
and adjusted for erasableSyntaxOnly.

BREAKING CHANGE: the package is now ESM-only and requires Node
^20.19.0 || ^22.13.0 || >=24.11.0 (the TypeORM 1.x range), where
CommonJS consumers can still require() it.

* feat!: compile rules through a boolean condition tree

Rules are flattened once into an and/or/not tree of FindOptionsWhere
fragments that every backend translates. The find-options backend now
applies De Morgan to multi-field `cannot` rules, joins constraints on the
same property with And() instead of overwriting them, and throws
UnsupportedConditionError for a `cannot` rule on a relation, which
FindOptionsWhere cannot negate.

BREAKING CHANGE: `accessibleBy(...).ofType()` throws
UnsupportedConditionError for negated relation conditions instead of
returning an invalid where object, and multi-field `cannot` rules now
produce one OR branch per field. TypeOrmAbility is a PureAbility-style
`Ability<A, TypeOrmQuery>`.

* fix(matcher): align instance checks with database semantics

To-many relations match when any related record matches (EXISTS), arrays
of nested conditions and top-level arrays are OR, scalar arrays are IN,
Date/Buffer/ObjectId values compare by value, ordered comparisons against
null never match, and Equal, Any and JsonContains are supported.

* test: integration harness with sqlite fixtures and database gates

Decorator-based entities covering every relation kind, a deterministic
seed, DB selection helpers with compose-file resolution, a Vitest global
setup and the describeIfSql/describeIfMongo/testIfDb gates. Runs on
sqlite in-process by default.

* feat: relation-aware accessibleBy(...).applyTo(queryBuilder)

Compile the condition tree onto a SelectQueryBuilder with Brackets and
NotBrackets. Relation conditions become correlated EXISTS subqueries for
many-to-one, one-to-one, one-to-many and many-to-many relations, so
`cannot` rules on related records negate exactly and to-many conditions
never duplicate rows or break pagination. Columns, embedded objects and
relation ids are delegated to TypeORM's object-literal where. The subject
type defaults to the entity class when the ability has rules for it and
to the entity name otherwise.

The table-driven suite cross-checks the query builder, find() and
ability.can() on loaded entities against each other.

* test: use the portable Date column type in fixtures

PostgreSQL rejects type 'datetime'; the Date constructor lets every
driver pick its native timestamp type.

* feat(matcher): unloadedRelation option for undefined nested values

createTypeOrmAbility(rules, { unloadedRelation: 'deny' }) makes
ability.can() treat an undefined nested property as null instead of
throwing, which suits optional embedded documents. The default still
throws. createTypeormQueryMatcher(options) exposes the same choice for
custom abilities.

* feat: toMongoQuery for the TypeORM mongodb driver

TypeORM's mongodb driver passes `where` straight to the driver, so rules
are compiled into a native filter: nested objects become dotted paths,
FindOperators map to $in/$gt/$regex/$all and friends, `cannot` rules
become $nor and the @ObjectIdColumn() property is renamed to _id.

* feat: accessibleRecords repository extension

`repository.extend(accessibleRecords)` adds `accessibleBy(ability,
action, alias)` returning a filtered SelectQueryBuilder and
`findAccessible(ability, action, options)` which merges the caller's
find options with the ability, on SQL databases through
setFindOptions() and on MongoDB through a $and filter.

* test: docker compose matrix for postgres, mysql, mssql and mongodb

One compose file per database version under test/assets with health
checks, selected by DB and DB_VERSION from Vitest's global setup and from
the compose-*.sh scripts. MongoDB uses the 8.2 image because 8.0 refuses
to start on Linux kernels 6.19 and newer (SERVER-121912).

* ci: lint and unit job plus a database integration matrix

Replace build-and-test.yml with ci.yml: a Docker-free job for format,
commitlint, lint, typecheck, unit tests, build and the sqlite
integration run, followed by an integration matrix over postgres, mysql,
mssql and mongodb with a per-database Docker image cache. Share the
Node/pnpm setup as a composite action with the release workflow.

* test: use the portable Boolean column type in fixtures

SQL Server rejects type 'boolean'; the Boolean constructor lets every
driver pick its native type (bit, tinyint, boolean).

* test: postgres array and jsonb operator suite

Cross-check ArrayContains, ArrayContainedBy, ArrayOverlap and
JsonContains across the query builder, find() and ability.can() on a
postgres-only fixture entity, gated with describeIfDb('postgres').

* test: published tarball smoke test

Build and pack the package, install the tarball into a scratch project
and import it from ESM and CommonJS; assert dist only imports typeorm,
@casl/ability, node: modules or relative files.

* docs: rewrite readme, contributing and agents guide for v2

Document the query builder, repository extension, find-options and
MongoDB backends, how rules compile, operator support per backend, the
SQL NULL caveat under negation and the migration from v1. CONTRIBUTING
and the new AGENTS.md follow the shared repository conventions; the test
assets README describes the database matrix and its environment
variables.

* refactor(repository): type findAccessible options consistently

* fix: compile null to IsNull() and plain arrays to In()

TypeORM compiles both to `=`, which never matches, while the matcher
reads them as IS NULL and IN. Every SQL backend now normalises them
first, so `cannot(..., { deletedAt: null })` becomes Not(IsNull()) and
the matcher treats a null condition as IS NULL for missing values too.
Shares isRelationLike() across backends along the way.

* fix: throw package errors for unloaded relations and raw-table builders

ability.can() now throws RelationNotLoadedError, a CaslTypeOrmError, and
points at the unloadedRelation option. applyTo() checks the alias with
hasMetadata before reading metadata, so a query builder that selects a
raw table gets the intended CaslTypeOrmError instead of TypeORM's.

* chore: drop unused test config and redundant test comments

Remove gate names and include globs that nothing defines, stop declaring
declarationMap only to override it, and delete comments in the
accessible-by tests that restate their titles.

* docs: document the describeIfDb gate
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v5...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@gitguardian

gitguardian Bot commented Sep 16, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
37321388 Triggered Generic Password 25468be test/assets/docker-compose.mssql-2022.yml View secret
37321389 Triggered Generic Password 25468be test/assets/docker-compose.postgres-17.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@cookieMonsterDev
cookieMonsterDev merged commit 0f18385 into master Sep 16, 2026
11 checks passed
@cookieMonsterDev

Copy link
Copy Markdown
Owner Author

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant