3.1 KiB
AGENTS.md
Guidance specific to the cli package. See the root AGENTS.md
for repo-wide conventions.
TypeORM boundary
TypeORM belongs in the persistence layer, not in business logic.
Allowed to import @n8n/typeorm — entity and repository files, including the
ones co-located inside src/modules/**:
src/databases/**- a module's
database/entities/**anddatabase/repositories/** - files named
*.entity.tsor*.repository.ts(some modules keep these at the module root)
These are exempted in eslint.config.mjs by location, so a genuine @Entity
or repository class is never flagged — including the few entity files that lack
the .entity.ts suffix (they live in a database/entities/ folder).
Not allowed — business logic (services, controllers, public-api handlers,
commands, factories) must not import @n8n/typeorm or @n8n/typeorm/...
subpaths. The misplaced-n8n-typeorm-import lint rule enforces this; a new
import — or an inline eslint-disable of the rule — fails CI. The same rule also
catches the relabel dodge: importing a TypeORM operator/driver type (In,
Not, FindOptionsWhere, EntityManager, …) from @n8n/db, which
re-exports them from @n8n/typeorm — that silences the direct-import check
without decoupling anything. Existing leaks of both kinds are tracked in two
files-scoped allowlists in eslint.config.mjs (direct @n8n/typeorm imports,
and @n8n/db relabels) that only ever shrink: never add to them, and never
suppress the rule inline.
Distinct from that shrink-only ratchet, two files are permanently exempted in
eslint.config.mjs for legitimate TypeORM use outside the persistence tree —
these are sanctioned, not migration targets, so don't try to relocate them or
suppress the rule:
src/commands/db/revert.ts—MigrationExecutor(CLI migration tooling)src/security-audit/security-audit.repository.ts—PackagesRepository
Need an operator query (In, IsNull, FindOptionsWhere, …)? Add a
use-case-named repository method (plain parameters, domain-shaped return) rather
than importing the operator into business logic. Relabeling the import to
@n8n/db is lint-enforced against, not just convention (see above); likewise
don't string-match QueryFailedError or push .manager / createQueryBuilder
into business logic to dodge the rule. See the root "Persistence layer & the
TypeORM boundary" section for the full rationale.
Transactions
Three patterns coexist while the persistence layer is migrated — new code uses only the third:
manager.transaction(...)— raw TypeORM, leaks the ORM into business logic. Anti-pattern; being removed.withTransaction(...)(@n8n/db) — deprecated helper that still hands anEntityManagerto its callback. Removed as call sites migrate.TransactionRunner.run(ctx, fn)(@n8n/db) — the target. Inject theTransactionRunnerport and thread theOperationContext; the driver handle never reaches business logic. Use this for new work.
See the root AGENTS.md "Transactions" bullet for the full API and a worked example.