config.ts•1.38 kB
import { readFileSync, existsSync } from 'fs';
import { z } from 'zod';
import { Config } from './types';
/**
* Zod schema for validating configuration files
*/
const ParamConfigSchema = z.object({
name: z.string().min(1),
type: z.enum(['string', 'number', 'boolean']),
description: z.string().min(1),
flag: z.string().optional(),
required: z.boolean(),
});
const ToolConfigSchema = z.object({
name: z.string().min(1),
description: z.string().min(1),
subcommand: z.string(),
parameters: z.array(ParamConfigSchema),
});
const ConfigSchema = z.object({
tools: z.array(ToolConfigSchema).min(1),
});
/**
* Loads and validates a configuration file
* @throws Error if file not found or validation fails
*/
export function loadConfig(configPath: string): Config {
if (!existsSync(configPath)) {
throw new Error(`Config file not found: ${configPath}`);
}
const rawContent = readFileSync(configPath, 'utf-8');
let parsed: unknown;
try {
parsed = JSON.parse(rawContent);
} catch {
throw new Error(`Invalid JSON in config file: ${configPath}`);
}
const result = ConfigSchema.safeParse(parsed);
if (!result.success) {
const errors = result.error.errors
.map((e) => ` - ${e.path.join('.')}: ${e.message}`)
.join('\n');
throw new Error(`Config validation failed:\n${errors}`);
}
return result.data;
}