export interface FleetSettings { deployKeepDays: number; observationKeepDays: number; restartConcurrency: number; createConcurrency: number; destroyConcurrency: number; } export const defaultFleetSettings: FleetSettings = { deployKeepDays: 7, observationKeepDays: 1, restartConcurrency: 1, createConcurrency: 1, destroyConcurrency: 1 }; export const fleetSettingLabels: Record = { deployKeepDays: 'Campaign history retention', observationKeepDays: 'Routine operation history retention', restartConcurrency: 'Concurrent restarts', createConcurrency: 'Concurrent server startups', destroyConcurrency: 'Concurrent server destructions' }; export function validateFleetSettings(input: unknown): FleetSettings { if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Provide fleet settings.'); const values = input as Record; for (const key of Object.keys(values)) { if (!Object.hasOwn(defaultFleetSettings, key)) throw new Error(`Unknown setting: ${key}`); } for (const key of Object.keys(defaultFleetSettings) as (keyof FleetSettings)[]) { const value = values[key]; const minimum = key === 'observationKeepDays' ? 0 : 1; if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum) { throw new Error(`${fleetSettingLabels[key]} must be ${minimum === 0 ? 'zero or a positive whole number' : 'a positive whole number'}.`); } if ((key === 'deployKeepDays' || key === 'observationKeepDays') && value > 36500) { throw new Error(`${fleetSettingLabels[key]} must be at most 36500 days.`); } } return { deployKeepDays: values.deployKeepDays as number, observationKeepDays: values.observationKeepDays as number, restartConcurrency: values.restartConcurrency as number, createConcurrency: values.createConcurrency as number, destroyConcurrency: values.destroyConcurrency as number }; }