Saltar al contenido principal

Databases

xpress-generator supports four databases. Each one generates a dedicated config file, model, service layer, migration files, and a ready-to-use docker-compose.yml automatically.


MongoDB

Uses Mongoose as the ODM.

Generated files

FileDescription
src/config/config-mongo.jsConnects via mongoose.connect()
src/modules/{name}/{name}Model.jsMongoose schema with timestamps
src/modules/auth/RefreshToken.jsTTL-indexed refresh token model

Environment variables

MONGO_URI=mongodb://localhost:27017/myapp

Docker

# docker-compose.yml (excerpt)
mongo:
image: mongo:7
ports: ['27017:27017']
volumes: [mongo_data:/data/db]
healthcheck:
test: ['CMD', 'mongosh', '--eval', 'db.adminCommand("ping")']
docker compose up

Migrations

MongoDB is schema-less — no migrations needed. Mongoose creates collections automatically when you insert the first document.

Auto-delete refresh tokens

The RefreshToken model uses a TTL index (expires: 7d) so tokens are automatically deleted from the database when they expire — no manual cleanup needed.


MySQL

Uses Sequelize ORM with the mysql2 driver.

Generated files

FileDescription
src/config/config-mysql.jsSequelize instance with connection pool
src/config/sequelize.jsSequelize CLI configuration (reads from .env)
src/modules/{name}/{name}Model.jssequelize.define() model
src/modules/auth/RefreshToken.jsSequelize refresh token model
.sequelizercPoints CLI to db/migrations/ and src/config/sequelize.js
db/migrations/{ts}-create-{name}.jsInitial migration: creates the {name}s table

Environment variables

MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=myapp
MYSQL_USER=dev
MYSQL_PASSWORD=devpass

Migrations

# Apply all pending migrations
npm run db:migrate

# Roll back the last migration
npm run db:migrate:undo

Migration files are tracked automatically by Sequelize CLI in the SequelizeMeta table. Running db:migrate multiple times is safe — already-applied files are skipped.

Docker

docker compose up

The generated docker-compose.yml starts MySQL 8 with a healthcheck. The app waits for MySQL to be ready before starting (depends_on with condition: service_healthy).

# docker-compose.yml (excerpt)
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: myapp
MYSQL_USER: dev
MYSQL_PASSWORD: devpass
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
interval: 10s
retries: 10
Auto-sync disabled in production

The generated config does NOT call sequelize.sync(). Use migrations to manage schema changes. Only use sequelize.sync({ alter: true }) in local development if needed, and never { force: true } with real data.


PostgreSQL

Uses Sequelize ORM with the pg and pg-hstore drivers.

Generated files

FileDescription
src/config/config-postgres.jsSequelize instance pointing to PostgreSQL
src/config/sequelize.jsSequelize CLI configuration
src/modules/{name}/{name}Model.jssequelize.define() model
src/modules/auth/RefreshToken.jsSequelize refresh token model
.sequelizercPoints CLI to db/migrations/
db/migrations/{ts}-create-{name}.jsInitial migration

Environment variables

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DATABASE=myapp
POSTGRES_USER=dev
POSTGRES_PASSWORD=devpass

Migrations

Identical to MySQL:

npm run db:migrate # apply pending
npm run db:migrate:undo # roll back last

Docker

docker compose up
# docker-compose.yml (excerpt)
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: dev
POSTGRES_PASSWORD: devpass
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U dev -d myapp']
Identical to MySQL (Sequelize-wise)

The generated configuration is identical to MySQL except for dialect: 'postgres' and the env variable names. All Sequelize knowledge transfers directly.


SQL Server

Uses mssql directly (no ORM).

Generated files

FileDescription
src/config/config-sqlserver.jsmssql connection pool
src/modules/{name}/{name}Model.jsRepository pattern with raw SQL queries
src/modules/auth/RefreshToken.jsmssql-based refresh token model
db/migrations/{ts}-create-{name}.sqlRaw SQL migration with IF NOT EXISTS guard
db/migrate.jsCustom migration runner

Environment variables

DB_SERVER=localhost
DB_NAME=myapp
DB_USER=sa
DB_PASSWORD=Dev@Pass123

Migrations

npm run db:migrate

The custom runner (db/migrate.js):

  1. Creates a _migrations table if it doesn't exist
  2. Reads all .sql files in db/migrations/ sorted by name
  3. Skips already-applied files
  4. Runs new files and records them in _migrations

Running db:migrate multiple times is safe — applied files are tracked and skipped.

Docker

docker compose up
# docker-compose.yml (excerpt)
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: Dev@Pass123
MSSQL_PID: Developer
healthcheck:
test: ['CMD-SHELL', '/opt/mssql-tools/bin/sqlcmd -S localhost -U sa ...']
interval: 15s
retries: 10
SQL Server password requirements

SQL Server enforces strong passwords by default. The password must contain uppercase, lowercase, digit, and special character, and be at least 8 characters. Dev@Pass123 satisfies this.

Repository pattern

Because mssql has no ORM, the generated model uses explicit parameterized SQL queries:

async function create(data) {
const pool = await getPool();
const request = pool.request();
request.input('name', mssql.NVarChar, data.name);
request.input('email', mssql.NVarChar, data.email);
const result = await request.query(
'INSERT INTO items (name, email) OUTPUT INSERTED.* VALUES (@name, @email)'
);
return result.recordset[0];
}

Working with migrations after generate:model

Every time you run generate:model, a new timestamped migration file is created alongside the module:

npx xpress-generator generate:model Invoice
# creates:
# src/modules/invoice/...
# db/migrations/1712345678-create-invoice.js (MySQL/PostgreSQL)
# db/migrations/1712345678-create-invoice.sql (SQL Server)

Then apply it:

npm run db:migrate