mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-23 11:37:02 -04:00
refactor(backend): config validation joi to zod
Co-authored-by: Philip Molares <philip.molares@udo.edu> Signed-off-by: Philip Molares <philip.molares@udo.edu> Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
91ebd519a8
commit
748702daf5
37 changed files with 1299 additions and 994 deletions
|
@ -1,73 +1,92 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { registerAs } from '@nestjs/config';
|
||||
import * as Joi from 'joi';
|
||||
import z from 'zod';
|
||||
|
||||
import { DatabaseType } from './database-type.enum';
|
||||
import { buildErrorMessage, parseOptionalNumber } from './utils';
|
||||
import { parseOptionalNumber } from './utils';
|
||||
import {
|
||||
buildErrorMessage,
|
||||
extractDescriptionFromZodIssue,
|
||||
} from './zod-error-message';
|
||||
|
||||
export interface DatabaseConfig {
|
||||
username: string;
|
||||
password: string;
|
||||
database: string;
|
||||
host: string;
|
||||
port: number;
|
||||
type: DatabaseType;
|
||||
}
|
||||
|
||||
const databaseSchema = Joi.object({
|
||||
type: Joi.string()
|
||||
.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(),
|
||||
otherwise: Joi.optional(),
|
||||
}).label('HD_DATABASE_USER'),
|
||||
password: Joi.when('type', {
|
||||
is: Joi.invalid(DatabaseType.SQLITE),
|
||||
then: Joi.string(),
|
||||
otherwise: Joi.optional(),
|
||||
}).label('HD_DATABASE_PASS'),
|
||||
host: Joi.when('type', {
|
||||
is: Joi.invalid(DatabaseType.SQLITE),
|
||||
then: Joi.string(),
|
||||
otherwise: Joi.optional(),
|
||||
}).label('HD_DATABASE_HOST'),
|
||||
port: Joi.when('type', {
|
||||
is: Joi.invalid(DatabaseType.SQLITE),
|
||||
then: Joi.number(),
|
||||
otherwise: Joi.optional(),
|
||||
}).label('HD_DATABASE_PORT'),
|
||||
const sqliteDbSchema = z.object({
|
||||
type: z.literal(DatabaseType.SQLITE).describe('HD_DATABASE_TYPE'),
|
||||
name: z.string().describe('HD_DATABASE_NAME'),
|
||||
});
|
||||
|
||||
const postgresDbSchema = z.object({
|
||||
type: z.literal(DatabaseType.POSTGRES).describe('HD_DATABASE_TYPE'),
|
||||
name: z.string().describe('HD_DATABASE_NAME'),
|
||||
username: z.string().describe('HD_DATABASE_USERNAME'),
|
||||
password: z.string().describe('HD_DATABASE_PASSWORD'),
|
||||
host: z.string().describe('HD_DATABASE_HOST'),
|
||||
port: z
|
||||
.number()
|
||||
.positive()
|
||||
.max(65535)
|
||||
.default(5432)
|
||||
.describe('HD_DATABASE_PORT'),
|
||||
});
|
||||
|
||||
const mariaDbSchema = z.object({
|
||||
type: z.literal(DatabaseType.MARIADB).describe('HD_DATABASE_TYPE'),
|
||||
name: z.string().describe('HD_DATABASE_NAME'),
|
||||
username: z.string().describe('HD_DATABASE_USERNAME'),
|
||||
password: z.string().describe('HD_DATABASE_PASSWORD'),
|
||||
host: z.string().describe('HD_DATABASE_HOST'),
|
||||
port: z
|
||||
.number()
|
||||
.positive()
|
||||
.max(65535)
|
||||
.default(3306)
|
||||
.describe('HD_DATABASE_PORT'),
|
||||
});
|
||||
|
||||
const mysqlDbSchema = z.object({
|
||||
type: z.literal(DatabaseType.MYSQL).describe('HD_DATABASE_TYPE'),
|
||||
name: z.string().describe('HD_DATABASE_NAME'),
|
||||
username: z.string().describe('HD_DATABASE_USERNAME'),
|
||||
password: z.string().describe('HD_DATABASE_PASSWORD'),
|
||||
host: z.string().describe('HD_DATABASE_HOST'),
|
||||
port: z
|
||||
.number()
|
||||
.positive()
|
||||
.max(65535)
|
||||
.default(3306)
|
||||
.describe('HD_DATABASE_PORT'),
|
||||
});
|
||||
|
||||
const dbSchema = z.discriminatedUnion('type', [
|
||||
sqliteDbSchema,
|
||||
mariaDbSchema,
|
||||
mysqlDbSchema,
|
||||
postgresDbSchema,
|
||||
]);
|
||||
|
||||
export type SqliteDatabaseConfig = z.infer<typeof sqliteDbSchema>;
|
||||
export type PostgresDatabaseConfig = z.infer<typeof postgresDbSchema>;
|
||||
export type MariadbDatabaseConfig = z.infer<typeof mariaDbSchema>;
|
||||
export type MySQLDatabaseConfig = z.infer<typeof mysqlDbSchema>;
|
||||
export type DatabaseConfig = z.infer<typeof dbSchema>;
|
||||
|
||||
export default registerAs('databaseConfig', () => {
|
||||
const databaseConfig = databaseSchema.validate(
|
||||
{
|
||||
type: process.env.HD_DATABASE_TYPE,
|
||||
username: process.env.HD_DATABASE_USER,
|
||||
password: process.env.HD_DATABASE_PASS,
|
||||
database: process.env.HD_DATABASE_NAME,
|
||||
host: process.env.HD_DATABASE_HOST,
|
||||
port: parseOptionalNumber(process.env.HD_DATABASE_PORT),
|
||||
},
|
||||
{
|
||||
abortEarly: false,
|
||||
presence: 'required',
|
||||
},
|
||||
);
|
||||
const databaseConfig = dbSchema.safeParse({
|
||||
type: process.env.HD_DATABASE_TYPE,
|
||||
username: process.env.HD_DATABASE_USERNAME,
|
||||
password: process.env.HD_DATABASE_PASSWORD,
|
||||
name: process.env.HD_DATABASE_NAME,
|
||||
host: process.env.HD_DATABASE_HOST,
|
||||
port: parseOptionalNumber(process.env.HD_DATABASE_PORT),
|
||||
});
|
||||
if (databaseConfig.error) {
|
||||
const errorMessages = databaseConfig.error.details.map(
|
||||
(detail) => detail.message,
|
||||
const errorMessages = databaseConfig.error.errors.map((issue) =>
|
||||
extractDescriptionFromZodIssue(issue, 'HD_DATABASE'),
|
||||
);
|
||||
throw new Error(buildErrorMessage(errorMessages));
|
||||
}
|
||||
return databaseConfig.value as DatabaseConfig;
|
||||
return databaseConfig.data;
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue