From 48e71d4345b698d6c78707b4ee2559a1d64c91b7 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 12 Mar 2026 09:53:31 -0700 Subject: [PATCH] use null for unsetting instead of empty string --- .../repositories/settings/ISettingsRepository.ts | 4 ++-- .../settings/MongoSettingsRepository.ts | 6 +++--- server/src/service/system/settingsService.ts | 6 +++--- server/src/types/settings.ts | 4 ++++ server/src/validation/settingsValidation.ts | 16 ++++++++-------- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/server/src/repositories/settings/ISettingsRepository.ts b/server/src/repositories/settings/ISettingsRepository.ts index 578d7f40d..0485a5aea 100644 --- a/server/src/repositories/settings/ISettingsRepository.ts +++ b/server/src/repositories/settings/ISettingsRepository.ts @@ -1,11 +1,11 @@ -import type { Settings } from "@/types/index.js"; +import type { Settings, SettingsUpdate } from "@/types/index.js"; export interface ISettingsRepository { // create create(settings: Partial): Promise; // fetch findSingleton(): Promise; // update - update(settings: Partial): Promise; + update(settings: SettingsUpdate): Promise; // delete deleteLegacy: () => Promise; } diff --git a/server/src/repositories/settings/MongoSettingsRepository.ts b/server/src/repositories/settings/MongoSettingsRepository.ts index f803ae6a9..e41abcd96 100644 --- a/server/src/repositories/settings/MongoSettingsRepository.ts +++ b/server/src/repositories/settings/MongoSettingsRepository.ts @@ -1,6 +1,6 @@ import mongoose from "mongoose"; import { ISettingsRepository } from "@/repositories/settings/ISettingsRepository.js"; -import type { Settings } from "@/types/index.js"; +import type { Settings, SettingsUpdate } from "@/types/index.js"; import { AppSettingsModel, type AppSettingsDocument } from "@/db/models/index.js"; class MongoSettingsRepository implements ISettingsRepository { @@ -59,12 +59,12 @@ class MongoSettingsRepository implements ISettingsRepository { return this.toEntity(settings); }; - update = async (settings: Partial) => { + update = async (settings: SettingsUpdate) => { const update: Record = { $set: {}, $unset: {} }; // Iterate through settings and separate into $set and $unset Object.entries(settings).forEach(([key, value]) => { - if (value === undefined || value === "") { + if (value === undefined || value === null) { // Unset undefined or empty string values update.$unset[key] = ""; } else { diff --git a/server/src/service/system/settingsService.ts b/server/src/service/system/settingsService.ts index 10ac61725..519d2f390 100755 --- a/server/src/service/system/settingsService.ts +++ b/server/src/service/system/settingsService.ts @@ -1,5 +1,5 @@ import { ISettingsRepository } from "@/repositories/index.js"; -import { Settings } from "@/types/index.js"; +import { Settings, SettingsUpdate } from "@/types/index.js"; import { AppError } from "@/utils/AppError.js"; import { ValidatedEnv } from "@/validation/envValidation.js"; import type { StringValue } from "ms"; @@ -19,7 +19,7 @@ export interface ISettingsService { loadSettings(): EnvConfig; getSettings(): EnvConfig; getDBSettings(): Promise; - updateDbSettings(newSettings: Partial): Promise; + updateDbSettings(newSettings: SettingsUpdate): Promise; } export class SettingsService implements ISettingsService { @@ -54,7 +54,7 @@ export class SettingsService implements ISettingsService { return this.settings; } - updateDbSettings = async (newSettings: Partial) => { + updateDbSettings = async (newSettings: SettingsUpdate) => { return await this.settingsRepository.update(newSettings); }; diff --git a/server/src/types/settings.ts b/server/src/types/settings.ts index 108cdcb72..405dc3efe 100644 --- a/server/src/types/settings.ts +++ b/server/src/types/settings.ts @@ -5,6 +5,10 @@ export interface SettingsThresholds { temperature?: number; } +export type SettingsUpdate = { + [K in keyof Settings]?: Settings[K] | null; +}; + export interface Settings { id: string; checkTTL: number; diff --git a/server/src/validation/settingsValidation.ts b/server/src/validation/settingsValidation.ts index b9551dd4e..f2c4e4c94 100644 --- a/server/src/validation/settingsValidation.ts +++ b/server/src/validation/settingsValidation.ts @@ -8,16 +8,16 @@ import { z } from "zod"; export const updateAppSettingsBodyValidation = z .object({ checkTTL: z.number().int().min(1).max(CHECK_TTL_SENTINEL).optional(), - systemEmailPort: z.number().optional(), - pagespeedApiKey: z.string().optional(), + systemEmailPort: z.number().nullable().optional(), + pagespeedApiKey: z.string().nullable().optional(), language: z.string().optional(), timezone: z.string().optional(), - systemEmailHost: z.string().optional(), - systemEmailAddress: z.string().optional(), - systemEmailPassword: z.string().optional(), - systemEmailUser: z.string().optional(), - systemEmailConnectionHost: z.string().optional(), - systemEmailTLSServername: z.string().optional(), + systemEmailHost: z.string().nullable().optional(), + systemEmailAddress: z.string().nullable().optional(), + systemEmailPassword: z.string().nullable().optional(), + systemEmailUser: z.string().nullable().optional(), + systemEmailConnectionHost: z.string().nullable().optional(), + systemEmailTLSServername: z.string().nullable().optional(), showURL: z.boolean().optional(), systemEmailSecure: z.boolean().optional(),