From 09d03808044b882fead96f5b9c0e2fb7229a4bf9 Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 18 Jun 2026 13:56:02 +0200 Subject: [PATCH] refactor(server): use zod time validation (#29189) --- .../lib/model/system_config_nightly_tasks_dto.dart | 2 +- open-api/immich-openapi-specs.json | 4 ++-- packages/sdk/src/fetch-client.ts | 2 +- server/src/controllers/system-config.controller.spec.ts | 2 +- server/src/dtos/system-config.dto.ts | 8 ++++++-- server/src/validation.ts | 4 ---- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mobile/openapi/lib/model/system_config_nightly_tasks_dto.dart b/mobile/openapi/lib/model/system_config_nightly_tasks_dto.dart index 0db417427f..4838c86065 100644 --- a/mobile/openapi/lib/model/system_config_nightly_tasks_dto.dart +++ b/mobile/openapi/lib/model/system_config_nightly_tasks_dto.dart @@ -33,7 +33,7 @@ class SystemConfigNightlyTasksDto { /// Missing thumbnails bool missingThumbnails; - /// Start time + /// Start time (HH:MM) String startTime; /// Sync quota usage diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index e825cf216b..d87b8190c0 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -26144,8 +26144,8 @@ "type": "boolean" }, "startTime": { - "description": "Start time", - "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$", + "description": "Start time (HH:MM)", + "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$", "type": "string" }, "syncQuotaUsage": { diff --git a/packages/sdk/src/fetch-client.ts b/packages/sdk/src/fetch-client.ts index e230917b74..fed100055d 100644 --- a/packages/sdk/src/fetch-client.ts +++ b/packages/sdk/src/fetch-client.ts @@ -2501,7 +2501,7 @@ export type SystemConfigNightlyTasksDto = { generateMemories: boolean; /** Missing thumbnails */ missingThumbnails: boolean; - /** Start time */ + /** Start time (HH:MM) */ startTime: string; /** Sync quota usage */ syncQuotaUsage: boolean; diff --git a/server/src/controllers/system-config.controller.spec.ts b/server/src/controllers/system-config.controller.spec.ts index 4e86aa56db..1770bdd89e 100644 --- a/server/src/controllers/system-config.controller.spec.ts +++ b/server/src/controllers/system-config.controller.spec.ts @@ -70,7 +70,7 @@ describe(SystemConfigController.name, () => { errorDto.validationError([ { path: ['nightlyTasks', 'startTime'], - message: 'Invalid input: expected string in HH:mm format, received string', + message: 'Invalid input: expected string in HH:MM format, received string', }, ]), ); diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 7e1efdc862..85618723b2 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -20,7 +20,6 @@ import { VideoCodecSchema, VideoContainerSchema, } from 'src/enum'; -import { isValidTime } from 'src/validation'; import z from 'zod'; /** Coerces 'true'/'false' strings to boolean, but also allows booleans. */ @@ -204,7 +203,12 @@ const SystemConfigNewVersionCheckSchema = z const SystemConfigNightlyTasksSchema = z .object({ - startTime: isValidTime.describe('Start time'), + startTime: z.iso + .time({ + precision: -1, + error: (iss) => `Invalid input: expected string in HH:MM format, received ${typeof iss.input}`, + }) + .describe('Start time (HH:MM)'), databaseCleanup: configBool.describe('Database cleanup'), missingThumbnails: configBool.describe('Missing thumbnails'), clusterNewFaces: configBool.describe('Cluster new faces'), diff --git a/server/src/validation.ts b/server/src/validation.ts index ce2eb4ee09..60cb0fa802 100644 --- a/server/src/validation.ts +++ b/server/src/validation.ts @@ -188,10 +188,6 @@ export const isoDateToDate = z ) .meta({ example: '2024-01-01' }); -export const isValidTime = z - .string() - .regex(/^([01]\d|2[0-3]):[0-5]\d$/, 'Invalid input: expected string in HH:mm format, received string'); - /** * Latitude in range [-90, 90]. Reuse for body or query params. *