refactor(db-config): Use typeorm-style options

TypeORM does not use a separate config option for the path
to the SQLite file.
Additionally, the "dialect" is called "type."

This commit adjusts our config to follow the upstream convention
to reduce confusion.

Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
David Mehren 2022-04-18 15:21:49 +02:00
parent 40c23acd49
commit cd5256da7f
6 changed files with 34 additions and 43 deletions

View file

@ -55,15 +55,14 @@ We officially support and test these databases:
- PostgreSQL - PostgreSQL
- MariaDB - MariaDB
| environment variable | default | example | description | | environment variable | default | example | description |
|------------------------|---------|---------------------|-----------------------------------------------------------------------------------------------| |-----------------------|---------|---------------------|--------------------------------------------------------------------------------------------|
| `HD_DATABASE_DIALECT` | - | `postgres` | The database dialect you want to use. This can be `postgres`, `mysql`, `mariadb` or `sqlite`. | | `HD_DATABASE_TYPE` | - | `postgres` | The database type you want to use. This can be `postgres`, `mysql`, `mariadb` or `sqlite`. |
| `HD_DATABASE_HOST` | - | `db.example.com` | The host, where the database runs. *Only if you're **not** using `sqlite`.* | | `HD_DATABASE_NAME` | - | `hedgedoc` | The name of the database to use. When using SQLite, this is the path to the database file. |
| `HD_DATABASE_PORT` | - | `5432` | The port, where the database runs. *Only if you're **not** using `sqlite`.* | | `HD_DATABASE_HOST` | - | `db.example.com` | The host, where the database runs. *Only if you're **not** using `sqlite`.* |
| `HD_DATABASE_NAME` | - | `hedgedoc` | The name of the database to use. *Only if you're **not** using `sqlite`.* | | `HD_DATABASE_PORT` | - | `5432` | The port, where the database runs. *Only if you're **not** using `sqlite`.* |
| `HD_DATABASE_USER` | - | `hedgedoc` | The user that logs in the database. *Only if you're **not** using `sqlite`.* | | `HD_DATABASE_USER` | - | `hedgedoc` | The user that logs in the database. *Only if you're **not** using `sqlite`.* |
| `HD_DATABASE_PASS` | - | `password` | The password to log into the database. *Only if you're **not** using `sqlite`.* | | `HD_DATABASE_PASS` | - | `password` | The password to log into the database. *Only if you're **not** using `sqlite`.* |
| `HD_DATABASE_STORAGE` | - | `./hedgedoc.sqlite` | The location of the database file. *Only if you're using `sqlite`.* |
## External services ## External services

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
export enum DatabaseDialect { export enum DatabaseType {
POSTGRES = 'postgres', POSTGRES = 'postgres',
MYSQL = 'mysql', MYSQL = 'mysql',
MARIADB = 'mariadb', MARIADB = 'mariadb',

View file

@ -6,7 +6,7 @@
import { registerAs } from '@nestjs/config'; import { registerAs } from '@nestjs/config';
import * as Joi from 'joi'; import * as Joi from 'joi';
import { DatabaseDialect } from './database-dialect.enum'; import { DatabaseType } from './database-type.enum';
import { buildErrorMessage, parseOptionalNumber } from './utils'; import { buildErrorMessage, parseOptionalNumber } from './utils';
export interface DatabaseConfig { export interface DatabaseConfig {
@ -15,56 +15,48 @@ export interface DatabaseConfig {
database: string; database: string;
host: string; host: string;
port: number; port: number;
storage: string; type: DatabaseType;
dialect: DatabaseDialect;
} }
const databaseSchema = Joi.object({ const databaseSchema = Joi.object({
username: Joi.when('dialect', { type: Joi.string()
is: Joi.invalid(DatabaseDialect.SQLITE), .valid(...Object.values(DatabaseType))
.label('HD_DATABASE_TYPE'),
// This is the database name, except for SQLite,
// where it is the path to the database file.
database: Joi.string().label('HD_DATABASE_NAME'),
username: Joi.when('type', {
is: Joi.invalid(DatabaseType.SQLITE),
then: Joi.string(), then: Joi.string(),
otherwise: Joi.optional(), otherwise: Joi.optional(),
}).label('HD_DATABASE_USER'), }).label('HD_DATABASE_USER'),
password: Joi.when('dialect', { password: Joi.when('type', {
is: Joi.invalid(DatabaseDialect.SQLITE), is: Joi.invalid(DatabaseType.SQLITE),
then: Joi.string(), then: Joi.string(),
otherwise: Joi.optional(), otherwise: Joi.optional(),
}).label('HD_DATABASE_PASS'), }).label('HD_DATABASE_PASS'),
database: Joi.when('dialect', { host: Joi.when('type', {
is: Joi.invalid(DatabaseDialect.SQLITE), is: Joi.invalid(DatabaseType.SQLITE),
then: Joi.string(),
otherwise: Joi.optional(),
}).label('HD_DATABASE_NAME'),
host: Joi.when('dialect', {
is: Joi.invalid(DatabaseDialect.SQLITE),
then: Joi.string(), then: Joi.string(),
otherwise: Joi.optional(), otherwise: Joi.optional(),
}).label('HD_DATABASE_HOST'), }).label('HD_DATABASE_HOST'),
port: Joi.when('dialect', { port: Joi.when('type', {
is: Joi.invalid(DatabaseDialect.SQLITE), is: Joi.invalid(DatabaseType.SQLITE),
then: Joi.number(), then: Joi.number(),
otherwise: Joi.optional(), otherwise: Joi.optional(),
}).label('HD_DATABASE_PORT'), }).label('HD_DATABASE_PORT'),
storage: Joi.when('dialect', {
is: Joi.valid(DatabaseDialect.SQLITE),
then: Joi.string(),
otherwise: Joi.optional(),
}).label('HD_DATABASE_STORAGE'),
dialect: Joi.string()
.valid(...Object.values(DatabaseDialect))
.label('HD_DATABASE_DIALECT'),
}); });
export default registerAs('databaseConfig', () => { export default registerAs('databaseConfig', () => {
const databaseConfig = databaseSchema.validate( const databaseConfig = databaseSchema.validate(
{ {
type: process.env.HD_DATABASE_TYPE,
username: process.env.HD_DATABASE_USER, username: process.env.HD_DATABASE_USER,
password: process.env.HD_DATABASE_PASS, password: process.env.HD_DATABASE_PASS,
database: process.env.HD_DATABASE_NAME, database: process.env.HD_DATABASE_NAME,
host: process.env.HD_DATABASE_HOST, host: process.env.HD_DATABASE_HOST,
port: parseOptionalNumber(process.env.HD_DATABASE_PORT), port: parseOptionalNumber(process.env.HD_DATABASE_PORT),
storage: process.env.HD_DATABASE_STORAGE,
dialect: process.env.HD_DATABASE_DIALECT,
}, },
{ {
abortEarly: false, abortEarly: false,

View file

@ -5,18 +5,18 @@
*/ */
import { registerAs } from '@nestjs/config'; import { registerAs } from '@nestjs/config';
import { DatabaseDialect } from '../database-dialect.enum'; import { DatabaseType } from '../database-type.enum';
import { DatabaseConfig } from '../database.config'; import { DatabaseConfig } from '../database.config';
export default registerAs( export default registerAs(
'databaseConfig', 'databaseConfig',
(): DatabaseConfig => ({ (): DatabaseConfig => ({
dialect: (process.env.HEDGEDOC_TEST_DB_TYPE || 'sqlite') as DatabaseDialect, type: (process.env.HEDGEDOC_TEST_DB_TYPE ||
DatabaseType.SQLITE) as DatabaseType,
database: 'hedgedoc', database: 'hedgedoc',
password: 'hedgedoc', password: 'hedgedoc',
host: 'localhost', host: 'localhost',
port: 0, port: 0,
storage: '',
username: 'hedgedoc', username: 'hedgedoc',
}), }),
); );

View file

@ -10,7 +10,7 @@ import session from 'express-session';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { AuthConfig } from '../config/auth.config'; import { AuthConfig } from '../config/auth.config';
import { DatabaseDialect } from '../config/database-dialect.enum'; import { DatabaseType } from '../config/database-type.enum';
import { DatabaseConfig } from '../config/database.config'; import { DatabaseConfig } from '../config/database.config';
import { Session } from '../users/session.entity'; import { Session } from '../users/session.entity';
@ -36,7 +36,7 @@ export function setupSessionMiddleware(
saveUninitialized: false, saveUninitialized: false,
store: new TypeormStore({ store: new TypeormStore({
cleanupLimit: 2, cleanupLimit: 2,
limitSubquery: dbConfig.dialect !== DatabaseDialect.MARIADB, limitSubquery: dbConfig.type !== DatabaseType.MARIADB,
}).connect(app.get<Repository<Session>>(getRepositoryToken(Session))), }).connect(app.get<Repository<Session>>(getRepositoryToken(Session))),
}), }),
); );

View file

@ -33,8 +33,8 @@ describe('App', () => {
}) })
.overrideProvider(getConfigToken('databaseConfig')) .overrideProvider(getConfigToken('databaseConfig'))
.useValue({ .useValue({
storage: ':memory:', database: ':memory:',
dialect: 'sqlite', type: 'sqlite',
}) })
.overrideProvider(getConfigToken('authConfig')) .overrideProvider(getConfigToken('authConfig'))
.useValue({ .useValue({