Skip to content

Pre-Release Final Review (v0.3.0)

Review Date: 2026-03-01


1. Test Status

Passing Tests

CategoryCountStatus
ORM unit tests63 suitesAll passed
ORM integration tests (MySQL)14 suites, 182 testsAll passed
ORM total77 suites, 1469 tests0 failures
nestjs-cats e2e23 testsAll passed
nestjs-blog e2e59 testsAll passed
nestjs-multitenant e2e33 testsAll passed
Example type check (tsc --noEmit)3 projectsAll passed

Bugs Found and Fixed in This Session

BugCauseCommit
Column 'parentFk' specified twiceDuplicate addition in INSERT/UPDATE SQL when @Column and @ManyToOne joinColumn have the same namebc7c7cc
nestjs-cats e2e 3 failuresTests expected count/hasNext/cursor, but actual API returns total/hasNextPage/nextCursorThis session

Tests Added in This Session

FileTest CountContent
__tests__/integration/p0-fk-object-assignment.test.ts15P0 FK object assignment patterns (J-2, J-3, M-1, M-2, S-7)

2. Test Scenarios Not Yet Automated

These are items from the P1-P3 scenarios in docs/manual-testing-guide.md that lack integration tests.

IDScenarioCurrent StatusNotes
J-1Query immediately after entity creationPartially covered in crud-basic.test.tsNeeds explicit save -> findOne round-trip verification
J-4save() return typeUnit tests onlyVerify actual EntityResult<T> type in integration tests
J-5Query non-existent IDPartially covered in crud-basic.test.tsExplicit null return verification
J-6find() on empty tableNot coveredVerify empty array vs undefined return value
M-3OneToMany cascade insertCovered in relations-one-to-many.test.tsComplete
M-4Delete with FK constraint violationPartially covered in relations-one-to-many.test.tsNeeds error message format verification
M-5Soft delete + relationsCovered in soft-delete.test.tsComplete
M-6FK preservation during partial updateNot coveredImportant — Verify whether existing FK is reset to null on save({ id, name })

P2 — When Driver Changes

IDScenarioCurrent StatusNotes
M-7UpsertCovered in upsert.test.tsComplete
S-9QueryBuilder SQL InjectionUnit only in sql-injection.test.tsVerify actual DB parameter binding in integration tests

P3 — Infrastructure

IDScenarioCurrent StatusNotes
S-1Transaction rollbackNot coveredVerify DB state restoration on mid-transaction error
S-2Concurrent save()Not coveredDeadlock, data integrity
S-3Connection pool exhaustionNot coveredQueuing/timeout when pool size exceeded
S-4Multi-tenancy concurrent accessPartially covered in multi-tenancy-postgres.test.tsPostgreSQL only, concurrency not verified
S-5Lifecycle hooks with plain objectsPartially covered in lifecycle-hooks.test.tsVerify difference between plain object and class instance
S-6EntitySubscriber event orderCovered in entity-subscriber.test.tsComplete
S-8Large-scale paginationNot coveredVerify cursor pagination with 1000+ records for missing/duplicate entries

3. Areas Requiring Additional Testing

3-1. PostgreSQL Driver Integration Tests

Current integration tests are MySQL-based. The following items may behave differently on PostgreSQL.

ItemMySQLPostgreSQLRisk Level
INSERT returninsertIdRETURNINGHigh
ENUM typeStringCREATE TYPEMedium
Schema-qualified identifiersNot supportedschema.tableHigh
Upsert syntaxON DUPLICATE KEYON CONFLICTMedium
SERIAL vs AUTO_INCREMENTAUTO_INCREMENTSERIALHigh

Recommendation: Add driver matrix tests that run the same scenarios as MySQL integration tests on PostgreSQL.

3-2. save() Return Type Consistency

EntityManager.save() returns Promise<InstanceType<ClazzType<T>>>, but BaseRepository.save() returns Promise<EntityResult<T>> (T | T[] | undefined). This inconsistency causes user confusion.

Verification needed:

  • Are there cases where BaseRepository.save() actually returns an array?
  • Can the return type be simplified to Promise<T>?

3-3. FK Preservation During Partial Update (M-6)

typescript
const cat = await catRepo.save({ name: "Nabi", parent: owner });
// Then update only name
await catRepo.save({ id: cat.id, name: "NewName" });
// -> Is the owner FK preserved, or reset to null?

Currently, in the save() UPDATE path, metadata.columns.map() includes all columns in SET, so columns missing from item may be SET to undefined. Verification needed whether this behavior is intended.

3-4. Transaction Isolation (S-1)

typescript
@Transactional()
async failingOperation() {
  await repo.save({ name: "A" });
  throw new Error("rollback!");
}

After the error, "A" should not exist in the DB. The rollback path of the @Transactional decorator is currently not verified in integration tests.

3-5. Concurrency Safety (S-2)

typescript
await Promise.all([
  repo.save({ id: 1, name: "A" }),
  repo.save({ id: 1, name: "B" }),
]);
  • Whether deadlock occurs
  • Final data integrity (one of A or B)
  • @Version optimistic locking behavior

3-6. Example e2e Test Status

Examplee2e TestsHow to RunStatus
nestjs-cats23 testsINTEGRATION_TEST=true pnpm test:e2eAll passed
nestjs-blog59 testsINTEGRATION_TEST=true pnpm testAll passed
nestjs-multitenant33 testsINTEGRATION_TEST=true pnpm test:e2eAll passed

All 3 example project e2e tests confirmed passing (2026-03-01).


4. Security Review

ItemStatusNotes
SQL Injection (4 drivers)Audit complete (2026-02-27)Unit coverage in sql-injection.test.ts
Parameter bindingApplied to all driversUses sql-template-tag
Identifier escapingApplied to all driversescapeIdentifier() / wrapIdentifier()
Tenant metadata isolationVerifiedgetAllInContext() merges public+context only
AsyncLocalStorage concurrencyVerifiedresolveContext() introduced, setContext() deprecated

5. Required Pre-Release Checklist

  • [x] All unit tests passed (1469)
  • [x] All integration tests passed (1507)
  • [x] nestjs-cats e2e all passed (23)
  • [x] nestjs-blog e2e all passed (59)
  • [x] nestjs-multitenant e2e all passed (33)
  • [x] 3 example type checks passed
  • [x] SQL Injection audit complete
  • [x] P0 FK object assignment bug fixed and tests added
  • [x] M-6 partial update FK preservation verified — bug fix + 10 integration tests (4a242e2)
  • [x] S-1 transaction rollback integration tests — 8 integration tests (4a242e2)
  • [x] PostgreSQL integration tests — 35 tests (CRUD/FK/M-6/Upsert/Transaction/Schema)
  • [x] BaseRepository.save() return type cleanup — EntityResult<T> -> InstanceType<ClazzType<T>> (4a242e2)

6. Prioritized Roadmap

Release Blockers (Required Before v0.1.0)

  1. M-6 Partial Update FK Preservation — Fix complete. UPDATE path skips undefined columns, 10 integration tests added.

Quick Follow-Up After Release (v0.1.1)

  1. S-1 Transaction Rollback Integration Tests — Complete. 8 integration tests (manual rollback, savepoint, isolation levels)
  2. PostgreSQL Integration Tests — Complete. 35 integration tests (SERIAL/RETURNING, FK, M-6, ON CONFLICT, transaction, schema-qualified)
  3. BaseRepository.save() Return Type — Complete. EntityResult<T> -> InstanceType<ClazzType<T>> change

Stabilization (v0.2.0)

  1. S-2 Concurrency — Deadlock, optimistic locking
  2. S-3 Connection Pool Exhaustion — Behavior when pool size exceeded
  3. S-8 Large-Scale Pagination — Cursor missing/duplicate with 1000+ records

Released under the MIT License.