mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-06-30 18:45:34 +02:00
181f24cfcc
Restructure into apps/worker, apps/cli, packages/mcp-server with Turborepo task orchestration, pnpm workspaces, Biome linting/formatting, and tsdown CLI bundling. Key changes: - src/ -> apps/worker/src/, cli/ -> apps/cli/, mcp-server/ -> packages/mcp-server/ - prompts/ and configs/ moved into apps/worker/ - npm replaced with pnpm, package-lock.json replaced with pnpm-lock.yaml - Dockerfile updated for pnpm-based builds - CLI logs command rewritten with chokidar for cross-platform reliability - Router health checking added for auto-detected router mode - Centralized path resolution via apps/worker/src/paths.ts
74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
// Copyright (C) 2025 Keygraph, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License version 3
|
|
// as published by the Free Software Foundation.
|
|
|
|
/**
|
|
* Config Loader Service
|
|
*
|
|
* Wraps parseConfig + distributeConfig with Result type for explicit error handling.
|
|
* Pure service with no Temporal dependencies.
|
|
*/
|
|
|
|
import { distributeConfig, parseConfig } from '../config-parser.js';
|
|
import type { DistributedConfig } from '../types/config.js';
|
|
import { ErrorCode } from '../types/errors.js';
|
|
import { err, ok, type Result } from '../types/result.js';
|
|
import { PentestError } from './error-handling.js';
|
|
|
|
/**
|
|
* Service for loading and distributing configuration files.
|
|
*
|
|
* Provides a Result-based API for explicit error handling,
|
|
* allowing callers to decide how to handle failures.
|
|
*/
|
|
export class ConfigLoaderService {
|
|
/**
|
|
* Load and distribute a configuration file.
|
|
*
|
|
* @param configPath - Path to the YAML configuration file
|
|
* @returns Result containing DistributedConfig on success, PentestError on failure
|
|
*/
|
|
async load(configPath: string): Promise<Result<DistributedConfig, PentestError>> {
|
|
try {
|
|
const config = await parseConfig(configPath);
|
|
const distributed = distributeConfig(config);
|
|
return ok(distributed);
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
|
|
// Determine appropriate error code based on error message
|
|
let errorCode = ErrorCode.CONFIG_PARSE_ERROR;
|
|
if (errorMessage.includes('not found') || errorMessage.includes('ENOENT')) {
|
|
errorCode = ErrorCode.CONFIG_NOT_FOUND;
|
|
} else if (errorMessage.includes('validation failed')) {
|
|
errorCode = ErrorCode.CONFIG_VALIDATION_FAILED;
|
|
}
|
|
|
|
return err(
|
|
new PentestError(
|
|
`Failed to load config ${configPath}: ${errorMessage}`,
|
|
'config',
|
|
false,
|
|
{ configPath, originalError: errorMessage },
|
|
errorCode,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load config if path is provided, otherwise return null config.
|
|
*
|
|
* @param configPath - Optional path to the YAML configuration file
|
|
* @returns Result containing DistributedConfig (or null) on success, PentestError on failure
|
|
*/
|
|
async loadOptional(configPath: string | undefined): Promise<Result<DistributedConfig | null, PentestError>> {
|
|
if (!configPath) {
|
|
return ok(null);
|
|
}
|
|
return this.load(configPath);
|
|
}
|
|
}
|