Database and PostgreSQL
The complete library surface is PostgreSQL-oriented. TypeORM abstracts basic entity access, but the following public behaviors use PostgreSQL-specific types or SQL:
WithAuditstorescreatorandmodifierasjsonb.- uploaded files and action history store metadata/snapshots as
jsonb. - job scheduler uses enum/jsonb columns,
INSERT ... ON CONFLICT ... RETURNING, the database clock, and PostgreSQL interval casts. BaseRepository.import()usesRETURNING '*'.- contains-search uses
UNACCENT(...), PostgreSQL casts, andNULLS FIRST/LASTordering.
Basic unscoped TypeORM operations may happen to work on another driver, but this project does not claim full cross-database support. Run your own integration suite before using a different driver; the job scheduler in particular should be treated as PostgreSQL-only.
Recommended data source
import { TypeOrmModule } from '@nestjs/typeorm';
TypeOrmModule.forRoot({
type: 'postgres',
url: process.env.DATABASE_URL,
autoLoadEntities: true,
synchronize: false,
ssl: process.env.NODE_ENV === 'production'
? { rejectUnauthorized: true }
: undefined,
});Use your platform's verified CA configuration rather than disabling TLS verification.
unaccent extension
@SearchableFields({ contain: [...] }) generates UNACCENT expressions. Enable the extension in a migration before using contains-search:
CREATE EXTENSION IF NOT EXISTS unaccent;Exact search and UUID lookup do not need unaccent.
Migrations for library entities
When you enable stateful modules, generate and review migrations for their exported entities:
import {
ActionHistory,
JobScheduler,
UploadedFile,
} from '@sdcorejs/nestjs/features';
export const libraryEntities = [UploadedFile, ActionHistory, JobScheduler];The exact schema depends on your TypeORM naming strategy and data-source schema. Generate migrations inside the consuming application; the library cannot safely ship one universal SQL migration.
Transaction rules
Scoped multi-step mutations create their own transaction when no QueryRunner is passed. If you pass a runner to a scoped mutation, it must already have an active transaction or InactiveMutationTransactionError is raised. This avoids splitting scope verification and mutation across different transaction boundaries.
The raw APIs unsafeRepository, unsafeGetRepository(), and unsafeCreateQueryRunner() bypass tenancy and affected-row protection. Keep them behind a reviewed maintenance boundary.
Paging and query limits
- Pages are 0-based (
pageNumber: 0is the first page). BaseRepository.paging()defaults to 10 rows and capspageSizeat 200.all()is deliberately unbounded and is not exposed byBaseController.- Generic search returns at most 20 rows.
- Action-history paging has a configurable limit that can never exceed 200.
