/** * 系统配置 Prisma 行 -> 共享 DTO 映射(A4-BE-02)。 * * 元数据(标签 / 说明 / 影响面 / 类型 / 上下限 / 是否公开)唯一来源是 * `SYSTEM_CONFIG_DEFINITIONS`;`system_configs` 只提供当前值与版本。 * DB 缺行时用定义默认值 + version 1 兜底,不写库。 */ import { type SystemConfig, type SystemConfigChange, type SystemConfigDefinition, type SystemConfigValue, systemConfigValueType, } from '@lingxi/shared'; import type { Prisma } from '@prisma/client'; import type { SystemConfig as PrismaSystemConfig, SystemConfigVersion as PrismaSystemConfigVersion, } from '@prisma/client'; /** 从未落库的配置:用 epoch 表示「未更新过」,避免伪造读取时间 */ const NEVER_UPDATED_AT = new Date(0).toISOString(); /** Prisma JsonB 只应存原始值;异常结构回退配置默认值,避免脏数据打穿前端 schema */ export function normalizeConfigValue( raw: Prisma.JsonValue | undefined, fallback: SystemConfigValue, ): SystemConfigValue { if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') { return raw; } return fallback; } export function toSystemConfig( definition: SystemConfigDefinition, row: PrismaSystemConfig | undefined, updatedByName?: string | null, ): SystemConfig { return { key: definition.key, group: definition.group, label: definition.label, description: definition.description, impact: definition.impact, type: definition.type, value: normalizeConfigValue(row?.configValue, definition.defaultValue), valueType: systemConfigValueType(definition), unit: definition.unit ?? null, version: row?.version ?? 1, updatedAt: row === undefined ? NEVER_UPDATED_AT : row.updatedAt.toISOString(), updatedBy: updatedByName ?? row?.updatedBy ?? null, editable: definition.editable, isPublic: definition.public, min: definition.min ?? null, max: definition.max ?? null, step: definition.step ?? null, maxLength: definition.maxLength ?? null, }; } export function toSystemConfigChange( row: PrismaSystemConfigVersion, label: string, operator: string | null, ): SystemConfigChange { return { key: row.configKey, label, version: row.version, oldValue: row.oldValue, newValue: row.newValue, reason: row.reason, operator, changedAt: row.changedAt.toISOString(), result: '已生效', }; }