/
fleisar
/
agent-timetracker
Обзор
Документация
Войти
/
fleisar
/
agent-timetracker
Код
Запросы
0
Задачи
Вики
Пакеты
1
Релизы
2
CI/CD
Аналитика
Безопасность
main
src/config/loadConfig.ts
108 строк
3 KB
Matvey Kuznetsov
fix: harden config defaults against mutation
02 июл 2026, 18:27
02 июл 2026, 18:27
42fba2e
Код
Авторство
О чём код?
import { trackerError } from "../domain/errors.js"; import { DEFAULT_HEARTBEAT_INTERVAL_SECONDS, DEFAULT_IDLE_TIMEOUT_SECONDS, defaultAgents } from "./defaultAgents.js"; import type { TrackerConfig, TrackerConfigEnv } from "./types.js"; const DEFAULT_DATABASE_PATH = ".agent-timetracker/tracker.sqlite"; const DEFAULT_AUDIT_LOG_PATH = ".agent-timetracker/audit.jsonl"; function getEnvValue(env: TrackerConfigEnv, key: string): string | undefined { return Object.prototype.hasOwnProperty.call(env, key) ? env[key] : undefined; } function isConfiguredAgentId(agentId: string): boolean { return Object.prototype.hasOwnProperty.call(defaultAgents, agentId); } type DefaultAgentId = keyof typeof defaultAgents; function cloneAgentProfile(agentId: DefaultAgentId): TrackerConfig["agents"][string] { const profile = defaultAgents[agentId]; const cloned: TrackerConfig["agents"][string] = { ...profile }; if (profile.metadata !== undefined) { cloned.metadata = { ...profile.metadata }; } return cloned; } function cloneDefaultAgents(): TrackerConfig["agents"] { const agents: TrackerConfig["agents"] = {}; for (const agentId of Object.keys(defaultAgents) as DefaultAgentId[]) { agents[agentId] = cloneAgentProfile(agentId); } return agents; } function parsePositiveInteger( value: string, envName: string, configField: "defaultIdleTimeoutSeconds" | "defaultHeartbeatIntervalSeconds" ): number { const trimmed = value.trim(); if (!/^\d+$/.test(trimmed)) { throw trackerError( "invalid_idle_timeout", `Environment variable ${envName} must be a positive integer`, { envName, configField } ); } const parsed = Number(trimmed); if (!Number.isSafeInteger(parsed) || parsed <= 0) { throw trackerError( "invalid_idle_timeout", `Environment variable ${envName} must be a positive integer`, { envName, configField } ); } return parsed; } export function loadConfig(env: TrackerConfigEnv = process.env): TrackerConfig { const idleTimeoutValue = getEnvValue(env, "AGENT_TIMETRACKER_IDLE_TIMEOUT_SECONDS"); const heartbeatIntervalValue = getEnvValue( env, "AGENT_TIMETRACKER_HEARTBEAT_INTERVAL_SECONDS" ); const defaultAgentIdValue = getEnvValue(env, "AGENT_TIMETRACKER_DEFAULT_AGENT_ID"); const defaultIdleTimeoutSeconds = idleTimeoutValue !== undefined ? parsePositiveInteger( idleTimeoutValue, "AGENT_TIMETRACKER_IDLE_TIMEOUT_SECONDS", "defaultIdleTimeoutSeconds" ) : DEFAULT_IDLE_TIMEOUT_SECONDS; const defaultHeartbeatIntervalSeconds = heartbeatIntervalValue !== undefined ? parsePositiveInteger( heartbeatIntervalValue, "AGENT_TIMETRACKER_HEARTBEAT_INTERVAL_SECONDS", "defaultHeartbeatIntervalSeconds" ) : DEFAULT_HEARTBEAT_INTERVAL_SECONDS; if (defaultAgentIdValue !== undefined && !isConfiguredAgentId(defaultAgentIdValue)) { throw trackerError("unknown_agent", `Unknown default agent id: ${defaultAgentIdValue}`); } return { databasePath: getEnvValue(env, "AGENT_TIMETRACKER_DB") ?? DEFAULT_DATABASE_PATH, auditLogPath: getEnvValue(env, "AGENT_TIMETRACKER_AUDIT_LOG") ?? DEFAULT_AUDIT_LOG_PATH, defaultAgentId: defaultAgentIdValue, defaultIdleTimeoutSeconds, defaultHeartbeatIntervalSeconds, agents: cloneDefaultAgents() }; }